How to use compareToIgnoreCase - java
I was given an example on how to alphabetically sort my Actor objects in an array.
public class AlphaSortingExchange
{
public static void main(String[ ] args)
{
String[ ] names = {"joe", "slim", "ed", "george"};
sortStringExchange (names);
for ( int k = 0; k < 4; k++ )
System.out.println( names [ k ] );
}
public static void sortStringExchange( String x [ ] )
{
int i, j;
String temp;
for ( i = 0; i < x.length - 1; i++ )
{
for ( j = i + 1; j < x.length; j++ )
{
if ( x [ i ].compareToIgnoreCase( x [ j ] ) > 0 )
{ // ascending sort
temp = x [ i ];
x [ i ] = x [ j ]; // swapping
x [ j ] = temp;
}
}
}
}
}
I am only allowed to follow this sort of format in sorting my array. NetBeans is not liking the "compareToIgnoreCase" statement in my code, giving the error
"cannot find symbol: method compareToIgnoreCase(Actors) location class
Actors"
. Below is my sorting function.
public static void sortActors(Actors actors[]) {
int i, j;
Actors temp;
for (i = 0; i < actors.length - 1; i++)
{
for (j = i + 1; j < actors.length; j++)
{
if (actors[i].compareToIgnoreCase(actors[j]) > 0)
{
temp = actors[i];
actors[i] = actors[j];
actors[j] = temp;
}
}
}
}
This is my object array and an example of an object in the array. Like I said before, I can only use compareToIgnoreCase. I am at a loss at how to use this function
private static void createActorsList() {
Actors[] actors = new Actors[Constants.NUMBER_OF_ACTORS];
Actors ladyViolet = new Actors();
ladyViolet.setName("Lady Violet");
ladyViolet.setDialogue("dialogue");
ladyViolet.setHappiness(0);
ladyViolet.setHealth(100);
actors[Constants.VIOLET] = ladyViolet;
}
Any help or solution would be much appreciated!
Thanks in advance!
Your Actor class doesn't have a compareToIgnoreCase method. You probably mean to call the method on one of the class's fields, e.g.,
if (actors[i].getName().compareToIgnoreCase(actors[j].getName()) > 0)
If the method needs to be on the Actor class, you'd have to write your own implementation:
public int compareToIgnoreCase(Actor actor) {
return this.name.compareToIgnoreCase(actor.name);
}
Related
Get all unique sequences from an array [duplicate]
For example I have this array: int a[] = new int[]{3,4,6,2,1}; I need list of all permutations such that if one is like this, {3,2,1,4,6}, others must not be the same. I know that if the length of the array is n then there are n! possible combinations. How can this algorithm be written? Update: thanks, but I need a pseudo code algorithm like: for(int i=0;i<a.length;i++){ // code here } Just algorithm. Yes, API functions are good, but it does not help me too much.
Here is how you can print all permutations in 10 lines of code: public class Permute{ static void permute(java.util.List<Integer> arr, int k){ for(int i = k; i < arr.size(); i++){ java.util.Collections.swap(arr, i, k); permute(arr, k+1); java.util.Collections.swap(arr, k, i); } if (k == arr.size() -1){ System.out.println(java.util.Arrays.toString(arr.toArray())); } } public static void main(String[] args){ Permute.permute(java.util.Arrays.asList(3,4,6,2,1), 0); } } You take first element of an array (k=0) and exchange it with any element (i) of the array. Then you recursively apply permutation on array starting with second element. This way you get all permutations starting with i-th element. The tricky part is that after recursive call you must swap i-th element with first element back, otherwise you could get repeated values at the first spot. By swapping it back we restore order of elements (basically you do backtracking). Iterators and Extension to the case of repeated values The drawback of previous algorithm is that it is recursive, and does not play nicely with iterators. Another issue is that if you allow repeated elements in your input, then it won't work as is. For example, given input [3,3,4,4] all possible permutations (without repetitions) are [3, 3, 4, 4] [3, 4, 3, 4] [3, 4, 4, 3] [4, 3, 3, 4] [4, 3, 4, 3] [4, 4, 3, 3] (if you simply apply permute function from above you will get [3,3,4,4] four times, and this is not what you naturally want to see in this case; and the number of such permutations is 4!/(2!*2!)=6) It is possible to modify the above algorithm to handle this case, but it won't look nice. Luckily, there is a better algorithm (I found it here) which handles repeated values and is not recursive. First note, that permutation of array of any objects can be reduced to permutations of integers by enumerating them in any order. To get permutations of an integer array, you start with an array sorted in ascending order. You 'goal' is to make it descending. To generate next permutation you are trying to find the first index from the bottom where sequence fails to be descending, and improves value in that index while switching order of the rest of the tail from descending to ascending in this case. Here is the core of the algorithm: //ind is an array of integers for(int tail = ind.length - 1;tail > 0;tail--){ if (ind[tail - 1] < ind[tail]){//still increasing //find last element which does not exceed ind[tail-1] int s = ind.length - 1; while(ind[tail-1] >= ind[s]) s--; swap(ind, tail-1, s); //reverse order of elements in the tail for(int i = tail, j = ind.length - 1; i < j; i++, j--){ swap(ind, i, j); } break; } } Here is the full code of iterator. Constructor accepts an array of objects, and maps them into an array of integers using HashMap. import java.lang.reflect.Array; import java.util.*; class Permutations<E> implements Iterator<E[]>{ private E[] arr; private int[] ind; private boolean has_next; public E[] output;//next() returns this array, make it public Permutations(E[] arr){ this.arr = arr.clone(); ind = new int[arr.length]; //convert an array of any elements into array of integers - first occurrence is used to enumerate Map<E, Integer> hm = new HashMap<E, Integer>(); for(int i = 0; i < arr.length; i++){ Integer n = hm.get(arr[i]); if (n == null){ hm.put(arr[i], i); n = i; } ind[i] = n.intValue(); } Arrays.sort(ind);//start with ascending sequence of integers //output = new E[arr.length]; <-- cannot do in Java with generics, so use reflection output = (E[]) Array.newInstance(arr.getClass().getComponentType(), arr.length); has_next = true; } public boolean hasNext() { return has_next; } /** * Computes next permutations. Same array instance is returned every time! * #return */ public E[] next() { if (!has_next) throw new NoSuchElementException(); for(int i = 0; i < ind.length; i++){ output[i] = arr[ind[i]]; } //get next permutation has_next = false; for(int tail = ind.length - 1;tail > 0;tail--){ if (ind[tail - 1] < ind[tail]){//still increasing //find last element which does not exceed ind[tail-1] int s = ind.length - 1; while(ind[tail-1] >= ind[s]) s--; swap(ind, tail-1, s); //reverse order of elements in the tail for(int i = tail, j = ind.length - 1; i < j; i++, j--){ swap(ind, i, j); } has_next = true; break; } } return output; } private void swap(int[] arr, int i, int j){ int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } public void remove() { } } Usage/test: TCMath.Permutations<Integer> perm = new TCMath.Permutations<Integer>(new Integer[]{3,3,4,4,4,5,5}); int count = 0; while(perm.hasNext()){ System.out.println(Arrays.toString(perm.next())); count++; } System.out.println("total: " + count); Prints out all 7!/(2!*3!*2!)=210 permutations.
If you're using C++, you can use std::next_permutation from the <algorithm> header file: int a[] = {3,4,6,2,1}; int size = sizeof(a)/sizeof(a[0]); std::sort(a, a+size); do { // print a's elements } while(std::next_permutation(a, a+size));
Here is an implementation of the Permutation in Java: Permutation - Java You should have a check on it! Edit: code pasted below to protect against link-death: // Permute.java -- A class generating all permutations import java.util.Iterator; import java.util.NoSuchElementException; import java.lang.reflect.Array; public class Permute implements Iterator { private final int size; private final Object [] elements; // copy of original 0 .. size-1 private final Object ar; // array for output, 0 .. size-1 private final int [] permutation; // perm of nums 1..size, perm[0]=0 private boolean next = true; // int[], double[] array won't work :-( public Permute (Object [] e) { size = e.length; elements = new Object [size]; // not suitable for primitives System.arraycopy (e, 0, elements, 0, size); ar = Array.newInstance (e.getClass().getComponentType(), size); System.arraycopy (e, 0, ar, 0, size); permutation = new int [size+1]; for (int i=0; i<size+1; i++) { permutation [i]=i; } } private void formNextPermutation () { for (int i=0; i<size; i++) { // i+1 because perm[0] always = 0 // perm[]-1 because the numbers 1..size are being permuted Array.set (ar, i, elements[permutation[i+1]-1]); } } public boolean hasNext() { return next; } public void remove() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } private void swap (final int i, final int j) { final int x = permutation[i]; permutation[i] = permutation [j]; permutation[j] = x; } // does not throw NoSuchElement; it wraps around! public Object next() throws NoSuchElementException { formNextPermutation (); // copy original elements int i = size-1; while (permutation[i]>permutation[i+1]) i--; if (i==0) { next = false; for (int j=0; j<size+1; j++) { permutation [j]=j; } return ar; } int j = size; while (permutation[i]>permutation[j]) j--; swap (i,j); int r = size; int s = i+1; while (r>s) { swap(r,s); r--; s++; } return ar; } public String toString () { final int n = Array.getLength(ar); final StringBuffer sb = new StringBuffer ("["); for (int j=0; j<n; j++) { sb.append (Array.get(ar,j).toString()); if (j<n-1) sb.append (","); } sb.append("]"); return new String (sb); } public static void main (String [] args) { for (Iterator i = new Permute(args); i.hasNext(); ) { final String [] a = (String []) i.next(); System.out.println (i); } } }
According to wiki https://en.wikipedia.org/wiki/Heap%27s_algorithm Heap's algorithm generates all possible permutations of n objects. It was first proposed by B. R. Heap in 1963. The algorithm minimizes movement: it generates each permutation from the previous one by interchanging a single pair of elements; the other n−2 elements are not disturbed. In a 1977 review of permutation-generating algorithms, Robert Sedgewick concluded that it was at that time the most effective algorithm for generating permutations by computer. So if we want to do it in recursive manner, Sudo code is bellow. procedure generate(n : integer, A : array of any): if n = 1 then output(A) else for i := 0; i < n - 1; i += 1 do generate(n - 1, A) if n is even then swap(A[i], A[n-1]) else swap(A[0], A[n-1]) end if end for generate(n - 1, A) end if java code: public static void printAllPermutations( int n, int[] elements, char delimiter) { if (n == 1) { printArray(elements, delimiter); } else { for (int i = 0; i < n - 1; i++) { printAllPermutations(n - 1, elements, delimiter); if (n % 2 == 0) { swap(elements, i, n - 1); } else { swap(elements, 0, n - 1); } } printAllPermutations(n - 1, elements, delimiter); } } private static void printArray(int[] input, char delimiter) { int i = 0; for (; i < input.length; i++) { System.out.print(input[i]); } System.out.print(delimiter); } private static void swap(int[] input, int a, int b) { int tmp = input[a]; input[a] = input[b]; input[b] = tmp; } public static void main(String[] args) { int[] input = new int[]{0,1,2,3}; printAllPermutations(input.length, input, ','); }
This a 2-permutation for a list wrapped in an iterator import java.util.Iterator; import java.util.LinkedList; import java.util.List; /* all permutations of two objects * * for ABC: AB AC BA BC CA CB * * */ public class ListPermutation<T> implements Iterator { int index = 0; int current = 0; List<T> list; public ListPermutation(List<T> e) { list = e; } public boolean hasNext() { return !(index == list.size() - 1 && current == list.size() - 1); } public List<T> next() { if(current == index) { current++; } if (current == list.size()) { current = 0; index++; } List<T> output = new LinkedList<T>(); output.add(list.get(index)); output.add(list.get(current)); current++; return output; } public void remove() { } }
There are n! total permutations for the given array size n. Here is code written in Java using DFS. public List<List<Integer>> permute(int[] nums) { List<List<Integer>> results = new ArrayList<List<Integer>>(); if (nums == null || nums.length == 0) { return results; } List<Integer> result = new ArrayList<>(); dfs(nums, results, result); return results; } public void dfs(int[] nums, List<List<Integer>> results, List<Integer> result) { if (nums.length == result.size()) { List<Integer> temp = new ArrayList<>(result); results.add(temp); } for (int i=0; i<nums.length; i++) { if (!result.contains(nums[i])) { result.add(nums[i]); dfs(nums, results, result); result.remove(result.size() - 1); } } } For input array [3,2,1,4,6], there are totally 5! = 120 possible permutations which are: [[3,4,6,2,1],[3,4,6,1,2],[3,4,2,6,1],[3,4,2,1,6],[3,4,1,6,2],[3,4,1,2,6],[3,6,4,2,1],[3,6,4,1,2],[3,6,2,4,1],[3,6,2,1,4],[3,6,1,4,2],[3,6,1,2,4],[3,2,4,6,1],[3,2,4,1,6],[3,2,6,4,1],[3,2,6,1,4],[3,2,1,4,6],[3,2,1,6,4],[3,1,4,6,2],[3,1,4,2,6],[3,1,6,4,2],[3,1,6,2,4],[3,1,2,4,6],[3,1,2,6,4],[4,3,6,2,1],[4,3,6,1,2],[4,3,2,6,1],[4,3,2,1,6],[4,3,1,6,2],[4,3,1,2,6],[4,6,3,2,1],[4,6,3,1,2],[4,6,2,3,1],[4,6,2,1,3],[4,6,1,3,2],[4,6,1,2,3],[4,2,3,6,1],[4,2,3,1,6],[4,2,6,3,1],[4,2,6,1,3],[4,2,1,3,6],[4,2,1,6,3],[4,1,3,6,2],[4,1,3,2,6],[4,1,6,3,2],[4,1,6,2,3],[4,1,2,3,6],[4,1,2,6,3],[6,3,4,2,1],[6,3,4,1,2],[6,3,2,4,1],[6,3,2,1,4],[6,3,1,4,2],[6,3,1,2,4],[6,4,3,2,1],[6,4,3,1,2],[6,4,2,3,1],[6,4,2,1,3],[6,4,1,3,2],[6,4,1,2,3],[6,2,3,4,1],[6,2,3,1,4],[6,2,4,3,1],[6,2,4,1,3],[6,2,1,3,4],[6,2,1,4,3],[6,1,3,4,2],[6,1,3,2,4],[6,1,4,3,2],[6,1,4,2,3],[6,1,2,3,4],[6,1,2,4,3],[2,3,4,6,1],[2,3,4,1,6],[2,3,6,4,1],[2,3,6,1,4],[2,3,1,4,6],[2,3,1,6,4],[2,4,3,6,1],[2,4,3,1,6],[2,4,6,3,1],[2,4,6,1,3],[2,4,1,3,6],[2,4,1,6,3],[2,6,3,4,1],[2,6,3,1,4],[2,6,4,3,1],[2,6,4,1,3],[2,6,1,3,4],[2,6,1,4,3],[2,1,3,4,6],[2,1,3,6,4],[2,1,4,3,6],[2,1,4,6,3],[2,1,6,3,4],[2,1,6,4,3],[1,3,4,6,2],[1,3,4,2,6],[1,3,6,4,2],[1,3,6,2,4],[1,3,2,4,6],[1,3,2,6,4],[1,4,3,6,2],[1,4,3,2,6],[1,4,6,3,2],[1,4,6,2,3],[1,4,2,3,6],[1,4,2,6,3],[1,6,3,4,2],[1,6,3,2,4],[1,6,4,3,2],[1,6,4,2,3],[1,6,2,3,4],[1,6,2,4,3],[1,2,3,4,6],[1,2,3,6,4],[1,2,4,3,6],[1,2,4,6,3],[1,2,6,3,4],[1,2,6,4,3]] Hope this helps.
Example with primitive array: public static void permute(int[] intArray, int start) { for(int i = start; i < intArray.length; i++){ int temp = intArray[start]; intArray[start] = intArray[i]; intArray[i] = temp; permute(intArray, start + 1); intArray[i] = intArray[start]; intArray[start] = temp; } if (start == intArray.length - 1) { System.out.println(java.util.Arrays.toString(intArray)); } } public static void main(String[] args){ int intArr[] = {1, 2, 3}; permute(intArr, 0); }
Visual representation of the 3-item recursive solution: http://www.docdroid.net/ea0s/generatepermutations.pdf.html Breakdown: For a two-item array, there are two permutations: The original array, and The two elements swapped For a three-item array, there are six permutations: The permutations of the bottom two elements, then Swap 1st and 2nd items, and the permutations of the bottom two element Swap 1st and 3rd items, and the permutations of the bottom two elements. Essentially, each of the items gets its chance at the first slot
A simple java implementation, refer to c++ std::next_permutation: public static void main(String[] args){ int[] list = {1,2,3,4,5}; List<List<Integer>> output = new Main().permute(list); for(List result: output){ System.out.println(result); } } public List<List<Integer>> permute(int[] nums) { List<List<Integer>> list = new ArrayList<List<Integer>>(); int size = factorial(nums.length); // add the original one to the list List<Integer> seq = new ArrayList<Integer>(); for(int a:nums){ seq.add(a); } list.add(seq); // generate the next and next permutation and add them to list for(int i = 0;i < size - 1;i++){ seq = new ArrayList<Integer>(); nextPermutation(nums); for(int a:nums){ seq.add(a); } list.add(seq); } return list; } int factorial(int n){ return (n==1)?1:n*factorial(n-1); } void nextPermutation(int[] nums){ int i = nums.length -1; // start from the end while(i > 0 && nums[i-1] >= nums[i]){ i--; } if(i==0){ reverse(nums,0,nums.length -1 ); }else{ // found the first one not in order int j = i; // found just bigger one while(j < nums.length && nums[j] > nums[i-1]){ j++; } //swap(nums[i-1],nums[j-1]); int tmp = nums[i-1]; nums[i-1] = nums[j-1]; nums[j-1] = tmp; reverse(nums,i,nums.length-1); } } // reverse the sequence void reverse(int[] arr,int start, int end){ int tmp; for(int i = 0; i <= (end - start)/2; i++ ){ tmp = arr[start + i]; arr[start + i] = arr[end - i]; arr[end - i ] = tmp; } }
Do like this... import java.util.ArrayList; import java.util.Arrays; public class rohit { public static void main(String[] args) { ArrayList<Integer> a=new ArrayList<Integer>(); ArrayList<Integer> b=new ArrayList<Integer>(); b.add(1); b.add(2); b.add(3); permu(a,b); } public static void permu(ArrayList<Integer> prefix,ArrayList<Integer> value) { if(value.size()==0) { System.out.println(prefix); } else { for(int i=0;i<value.size();i++) { ArrayList<Integer> a=new ArrayList<Integer>(); a.addAll(prefix); a.add(value.get(i)); ArrayList<Integer> b=new ArrayList<Integer>(); b.addAll(value.subList(0, i)); b.addAll(value.subList(i+1, value.size())); permu(a,b); } } } }
Implementation via recursion (dynamic programming), in Java, with test case (TestNG). Code PrintPermutation.java import java.util.Arrays; /** * Print permutation of n elements. * * #author eric * #date Oct 13, 2018 12:28:10 PM */ public class PrintPermutation { /** * Print permutation of array elements. * * #param arr * #return count of permutation, */ public static int permutation(int arr[]) { return permutation(arr, 0); } /** * Print permutation of part of array elements. * * #param arr * #param n * start index in array, * #return count of permutation, */ private static int permutation(int arr[], int n) { int counter = 0; for (int i = n; i < arr.length; i++) { swapArrEle(arr, i, n); counter += permutation(arr, n + 1); swapArrEle(arr, n, i); } if (n == arr.length - 1) { counter++; System.out.println(Arrays.toString(arr)); } return counter; } /** * swap 2 elements in array, * * #param arr * #param i * #param k */ private static void swapArrEle(int arr[], int i, int k) { int tmp = arr[i]; arr[i] = arr[k]; arr[k] = tmp; } } PrintPermutationTest.java (test case via TestNG) import org.testng.Assert; import org.testng.annotations.Test; /** * PrintPermutation test. * * #author eric * #date Oct 14, 2018 3:02:23 AM */ public class PrintPermutationTest { #Test public void test() { int arr[] = new int[] { 0, 1, 2, 3 }; Assert.assertEquals(PrintPermutation.permutation(arr), 24); int arrSingle[] = new int[] { 0 }; Assert.assertEquals(PrintPermutation.permutation(arrSingle), 1); int arrEmpty[] = new int[] {}; Assert.assertEquals(PrintPermutation.permutation(arrEmpty), 0); } }
Here is one using arrays and Java 8+ import java.util.Arrays; import java.util.stream.IntStream; public class HelloWorld { public static void main(String[] args) { int[] arr = {1, 2, 3, 5}; permutation(arr, new int[]{}); } static void permutation(int[] arr, int[] prefix) { if (arr.length == 0) { System.out.println(Arrays.toString(prefix)); } for (int i = 0; i < arr.length; i++) { int i2 = i; int[] pre = IntStream.concat(Arrays.stream(prefix), IntStream.of(arr[i])).toArray(); int[] post = IntStream.range(0, arr.length).filter(i1 -> i1 != i2).map(v -> arr[v]).toArray(); permutation(post, pre); } } }
Instead of permutations, we can preferably call them combinations. Irrespective of the coding language, we can use a simple approach, To append the array elements to the already existing list of combinations thus, using the dynamic programming approach. This code focuses on those combinations without adjacency as well. #include <iostream> #include <vector> using namespace std; template <class myIterator, class T> myIterator findDigit(myIterator first, myIterator last, T val) { while(first != last) { if(*first == val) { break; } first++; } return first; } void printCombinations(vector<vector<int>> combinations) { cout << "printing all " << combinations.size() << " combinations" << endl; for(int i=0; i<combinations.size(); i++) { cout << "["; for(int j=0; j<combinations[i].size(); j++) { cout << " " << combinations[i][j] << " "; } cout << "] , "; } return; } int main() { vector<int> a = {1,2,3,4,5}; vector<vector<int>> comb; vector<int> t; int len=a.size(); for(int i=0; i<len; i++) { t.push_back(a.at(i)); comb.push_back(t); t.clear(); } for(int l=1; l<len; l++) { for(int j=0; j<comb.size(); j++) { if(comb[j].size()==l) { int t = comb[j].back(); if(t != a.back()) { vector<int>::iterator it = findDigit(a.begin(), a.end(), t); for(std::vector<int>::iterator k=it+1; k!=a.end();k++) { vector<int> t (comb[j].begin(), comb[j].end()); t.push_back(*k); comb.push_back(t); t.clear(); } } } } } printCombinations(comb); return 0; } Although the complexity is a bit high, it's definitely lower than the recursion approach, especially when the array size is very large. Output for the above array (or vecter, if you will) is : printing all 31 combinations [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ], [ 1 2 ], [ 1 3 ], [ 1 4 ], [ 1 5 ], [ 2 3 ], [ 2 4 ], [ 2 5 ], [ 3 4 ], [ 3 5 ], [ 4 5 ], [ 1 2 3 ], [ 1 2 4 ], [ 1 2 5 ], [ 1 3 4 ], [ 1 3 5 ], [ 1 4 5 ], [ 2 3 4 ], [ 2 3 5 ], [ 2 4 5 ], [ 3 4 5 ], [ 1 2 3 4 ], [ 1 2 3 5 ], [ 1 2 4 5 ], [ 1 3 4 5 ], [ 2 3 4 5 ], [ 1 2 3 4 5 ], The code can be used for characters and strings as well, by just replacing the datatype wherever required. eg. vector<char> a = {'d','g','y','u','t'}; To give printing all 31 combinations [ d ] , [ g ] , [ y ] , [ u ] , [ t ] , [ d g ] , [ d y ] , [ d u ] , [ d t ] , [ g y ] , [ g u ] , [ g t ] , [ y u ] , [ y t ] , [ u t ] , [ d g y ] , [ d g u ] , [ d g t ] , [ d y u ] , [ d y t ] , [ d u t ] , [ g y u ] , [ g y t ] , [ g u t ] , [ y u t ] , [ d g y u ] , [ d g y t ] , [ d g u t ] , [ d y u t ] , [ g y u t ] , [ d g y u t ] , and vector<string> a = {"asdf","myfl", "itshot", "holy"}; to give printing all 15 combinations [ asdf ] , [ myfl ] , [ itshot ] , [ holy ] , [ asdf myfl ] , [ asdf itshot ] , [ asdf holy ] , [ myfl itshot ] , [ myfl holy ] , [ itshot holy ] , [ asdf myfl itshot ] , [ asdf myfl holy ] , [ asdf itshot holy ] , [ myfl itshot holy ] , [ asdf myfl itshot holy ] ,
Trying to combine a class file into one single java file
I'm trying to avoid using two files and instead, just make it into one file all together. So i made a single class in a .java file, this is how it looks: import javax.swing.JOptionPane; public class Raindrop { double [] rainfallStats; public double getTotalRainfall() { double totalRainfall; for ( int index = 0; index < rainfallStats.length; index++) { totalRainfall = totalRainfall + rainfallStats[ index ]; } return totalRainfall; } public double getAverageRainfall() { return getTotalRainfall() / rainfallStats.length; } public double getMostRainMonth () { double mostRain = rainfallStats [ 0 ]; int mostRainMonth; for( int index = 0; index < rainfallStats.length; index++ ) { if ( rainfallStats[ index ] > mostRain ) { mostRain = rainfallStats [ index ]; mostRainMonth = index + 1; } } return mostRainMonth; } public double getLeastRainMonth () { double leastRain = rainfallStats [ 0 ]; int leastRainMonth; for( int index = 0; index < rainfallStats.length; index++ ) { if ( rainfallStats[ index ] > leastRain ) { leastRain = rainfallStats [ index ]; leastRainMonth = index + 1; } } return leastRainMonth; } public Rainfall ( double [] rainfallStatsGiven) { rainfallStats = new double [ rainfallStatsGiven.length ]; for (int index = 0; index < rainfallStatsGiven; index++) { rainfallStats[ index ] = rainfallStatsGiven [ index ]; } } public static void fillArrayWithUserInput ( double [] arrayGiven ) { String userInputString; double userMonthlyRainfallFigure; for ( int index = 0; index < arrayGiven.length; index++ ){ userInputString = JOptionPane.showInputDialog( "Please enter rainfall figures for month " + (index + 1) ); userMonthlyRainfallFigure = Double.parseDouble( userInputString ); arrayGiven [ index ] = userMonthlyRainfallFigure; } } public static void main(String[] args) { final int MONTH_IN_A_YEAR = 12; double [] rainfallStats = new double [12]; String userOutputString; fillArrayWithUserInput( rainfallStats ); Rainfall rainfallData = new Rainfall( rainfallStats ); userOutputString = String.format ( "Total rainfall: %f\nAverage monthly rainfall" + ":" + "%f\nMonth with most rain: %f\nMonth with least rain: %f", rainfallData.getTotalRainfall(), rainfallData.getAverageRainfall(), rainfallData.getMostRainMonth(), rainfallData.getLeastRainMonth() ); JOptionPane.showMessageDialog(null, userOutputString ); System.exit( 0 ); } } I get the error: Raindrop.java:45: error: invalid method declaration; return type required public Rainfall ( double [] rainfallStatsGiven) { ^ 1 error I try changing public Rainfall into a methoed but it couldnt figure out how to do it, would like any suggestion on how to make this work. I couldnt figure out how to nest the class ethier , and i couldnt figure out how to make the public class into anything else that would work.
I was able to look through my code again and found many errors and fixed them which,in the process, fixed my problem because there were many more problem, so i was able to get what I wanted. Heres the revised one if anyone also want to look at: import javax.swing.JOptionPane; public class Rainfall { double [] rainfallStats; public double getTotalRainfall() { double totalRainfall =0; for ( int index = 0; index < rainfallStats.length; index++) { totalRainfall = totalRainfall + rainfallStats[ index ]; } return totalRainfall; } public double getAverageRainfall() { return getTotalRainfall() / rainfallStats.length; } public double getMostRainMonth () { double mostRain = rainfallStats [ 0 ]; int mostRainMonth = 1; for( int index = 0; index < rainfallStats.length; index++ ) { if ( rainfallStats[ index ] > mostRain ) { mostRain = rainfallStats [ index ]; mostRainMonth = index + 1; } } return mostRainMonth; } public double getLeastRainMonth () { double leastRain = rainfallStats [ 0 ]; int leastRainMonth =1; for( int index = 0; index < rainfallStats.length; index++ ) { if ( rainfallStats[ index ] < leastRain ) { leastRain = rainfallStats [ index ]; leastRainMonth = index + 1; } } return leastRainMonth; } public Rainfall ( double [] rainfallStatsGiven) { rainfallStats = new double [ rainfallStatsGiven.length ]; for (int index = 0; index < rainfallStatsGiven.length; index++) { rainfallStats[ index ] = rainfallStatsGiven [ index ]; } } public static void fillArrayWithUserInput ( double [] arrayGiven ) { String userInputString; double userMonthlyRainfallFigure; for ( int index = 0; index < arrayGiven.length; index++ ){ userInputString = JOptionPane.showInputDialog("Please enter rainfall figures for month " + (index + 1) ); userMonthlyRainfallFigure = Double.parseDouble( userInputString ); arrayGiven [ index ] = userMonthlyRainfallFigure; } } public static void main(String[] args) { final int MONTH_IN_A_YEAR = 12; double [] rainfallStats = new double [12]; String userOutputString; fillArrayWithUserInput( rainfallStats ); Rainfall rainfallData = new Rainfall( rainfallStats ); userOutputString = String.format ( "Total rainfall: %f\nAverage monthly rainfall"+ ":+ %f\nMonth with most rain: %f\nMonth with least rain: %f", rainfallData.getTotalRainfall(), rainfallData.getAverageRainfall(), rainfallData.getMostRainMonth(), rainfallData.getLeastRainMonth() ); JOptionPane.showMessageDialog(null, userOutputString ); System.exit( 0 ); } }
Variable number of nested loops with head and tail
I have these nested for loops: void fun() { int n = 5; int c = 0; for (int i = 0; i < n; i++) { head_function(i, c); for (int j = 0; j < n; j++) { head_function(j, c); for (int w = 0; w < n; w++) { head_function(w, c); for (int x = 0; x < n; x++) { head_function(x, c); c++; body(c); tail_function(x, c); } tail_function(w, c); } tail_function(j, c); } tail_function(i, c); } } It doesn't really matter what the head and tail functions do, as long as they can keep track of their indices i, j, w, x. What I want is to have an arbitrary number of nested for loops instead of just four. The other solutions I found here didn't really work for me, because they did not include the head and tail functions, I guess.
Here's a skeleton to get you started. Feel free to add params and change signatures according to your needs. public void doStuffRecursively(int nTimes){ doIt(nTimes); } void doIt(int depth){ if(depth==0) body(); else{ head(depth); doIt(depth-1); tail(depth); } } void body(){} void head(int depth){} void tail(int depth){}
Here's a non-recursive version that iterates over a single array of loop indices. You're code as a bit of a niggle in it: the innermost loop is different from the other loops in that only it calls body() and increments the general counter. I accounted for this by checking inside my loop for the "inner loop" which is indicated by the loop variable being 0. I also changed your n from 5 to 3 (max), just to reduce the size of the output. The rest of the code I think is pretty straight forward. public class Test { public static void main(String[] args) { System.out.println("\n Loop 1\n"); loop( 1 ); System.out.println("\n Loop 2\n"); loop( 2 ); System.out.println("\n Loop 3\n"); loop( 3 ); } public static void loop( int depth ) { int[] indices = new int[depth]; final int max = 3; int count = 0; for( int x = 0; x < depth - 1; x++ ) head( x, count ); outer: for(;;) { for( int loop = 0; loop < indices.length; loop++ ) { if( indices[loop] < max ) { head( indices[loop], count ); if( loop == 0 ) { count++; body( indices[loop], count ); } tail( indices[loop], count ); indices[loop]++; break; } else { if( loop == indices.length - 1 ) break outer; indices[loop] = 0; } } } } private static void head( int index, int counter ) { System.out.printf( "head index=%d count=%d%n", index, counter ); } private static void body( int index, int counter ) { System.out.printf( "body index=%d count=%d%n", index, counter ); } private static void tail( int index, int counter ) { System.out.printf( "tail index=%d count=%d%n", index, counter ); } } Partial output (it gets rather long): Loop 1 head index=0 count=0 body index=0 count=1 tail index=0 count=1 head index=1 count=1 body index=1 count=2 tail index=1 count=2 head index=2 count=2 body index=2 count=3 tail index=2 count=3
Since n seems to be always the same, you can try (c is now a private field, n is the number of the nested for loops): private int c; void loopAtDepth(int depth){ if( depth == 0){ c++; body(c); } else { for(int i = 0; i < n; i++){ head_function(i, c); loopAtDepth(depth - 1) tail_function(i, c); } } }
Java - Why is this implementation of a binary heap faster than the other?
After reading a bit about heaps/priority queues, I recently made my own implementation of one. Afterwards I decided to compare the performance of my implementation to that of one which I found in a book, and the results are a bit confusing to me. It appears that there is a vast performance difference between the insert methods of the two implementations. I used this code to test both heaps: Random rnd = new Random(); long startTime = System.currentTimeMillis(); for(int i = 0; i < 1_000_000_0; i++) heap.insert(rnd.nextInt(1000)); System.out.println(System.currentTimeMillis() - startTime); When I run this with my heap implementation, I get a result of around 600ms. When I run it with the book's implementation I get around 1900ms. How can the difference possibly be this big? Surely there must be something wrong with my implementation. My implementation: public class Heap<T extends Comparable<? super T>> { private T[] array = (T[])new Comparable[10]; private int size = 0; public void insert(T data) { if(size+1 > array.length) expandArray(); array[size++] = data; int pos = size-1; T temp; while(pos != 0 && array[pos].compareTo(array[pos/2]) < 0) { temp = array[pos/2]; array[pos/2] = array[pos]; array[pos] = temp; pos /= 2; } } private void expandArray() { T[] newArray = (T[])new Comparable[array.length*2]; for(int i = 0; i < array.length; i++) newArray[i] = array[i]; array = newArray; } } The book's implementation: public class BooksHeap<AnyType extends Comparable<? super AnyType>> { private static final int DEFAULT_CAPACITY = 10; private int currentSize; private AnyType [ ] array; public BinaryHeap( ) { this( DEFAULT_CAPACITY ); } public BinaryHeap( int capacity ) { currentSize = 0; array = (AnyType[]) new Comparable[ capacity + 1 ]; } public void insert( AnyType x ) { if( currentSize == array.length - 1 ) enlargeArray( array.length * 2 + 1 ); int hole = ++currentSize; for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 ) array[ hole ] = array[ hole / 2 ]; array[ hole ] = x; } private void enlargeArray( int newSize ) { AnyType [] old = array; array = (AnyType []) new Comparable[ newSize ]; for( int i = 0; i < old.length; i++ ) array[ i ] = old[ i ]; } } Edit: The book is "Data Structures and Algorithm Analysis in Java" by Mark Allen Weiss. Third edition. ISBN: 0-273-75211-1.
Here, your code measured with JMH: #BenchmarkMode(Mode.AverageTime) #OutputTimeUnit(TimeUnit.NANOSECONDS) #OperationsPerInvocation(Measure.SIZE) #Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) #Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) #State(Scope.Thread) #Fork(1) public class Measure { static final int SIZE = 4_000_000; private Random rnd; #Setup public void setup() { rnd = new Random(); } #Benchmark public Object heap() { Heap<Integer> heap = new Heap<>(); for (int i = 0; i < SIZE; i++) heap.insert(rnd.nextInt()); return heap; } #Benchmark public Object booksHeap() { BooksHeap<Integer> heap = new BooksHeap<>(); for (int i = 0; i < SIZE; i++) heap.insert(rnd.nextInt()); return heap; } public static class Heap<T extends Comparable<? super T>> { private T[] array = (T[])new Comparable[10]; private int size = 0; public void insert(T data) { if(size+1 > array.length) expandArray(); array[size++] = data; int pos = size-1; T temp; while(pos != 0 && array[pos].compareTo(array[pos/2]) < 0) { temp = array[pos/2]; array[pos/2] = array[pos]; array[pos] = temp; pos /= 2; } } private void expandArray() { T[] newArray = (T[])new Comparable[array.length*2]; for (int i = 0; i < array.length; i++) newArray[i] = array[i]; array = newArray; } } public static class BooksHeap<AnyType extends Comparable<? super AnyType>> { private static final int DEFAULT_CAPACITY = 10; private int currentSize; private AnyType [ ] array; public BooksHeap() { this( DEFAULT_CAPACITY ); } public BooksHeap( int capacity ) { currentSize = 0; array = (AnyType[]) new Comparable[ capacity + 1 ]; } public void insert( AnyType x ) { if( currentSize == array.length - 1 ) enlargeArray( array.length * 2 + 1 ); int hole = ++currentSize; for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 ) array[ hole ] = array[ hole / 2 ]; array[ hole ] = x; } private void enlargeArray( int newSize ) { AnyType [] old = array; array = (AnyType []) new Comparable[ newSize ]; for( int i = 0; i < old.length; i++ ) array[ i ] = old[ i ]; } } } And the results: Benchmark Mode Cnt Score Error Units Measure.booksHeap avgt 5 62,712 ± 23,633 ns/op Measure.heap avgt 5 62,784 ± 44,228 ns/op They are exactly the same. Moral of the exercise: don't think you can just write a loop and call it a benchmark. Measuring anything meaningful within a complex, self-optimizing runtime like HotSpot is an incredibly difficult challenge, best left to an expert benchmark tool like JMH. As a side note, you could shave some 20% off your times (in both implementations) if you use System.arraycopy instead of the manual loop. Embarassingly, this wasn't my idea—IntelliJ IDEA's automatic inspection suggested that, and converted the code on its own :)
Taking the testing of implementations part of this question, how you are testing these implementations can explain a lot of any difference, consider this example. When I place your Heap in a class called OPHeap and the book's heap in a class called BookHeap and then test in this order: import java.util.Random; public class Test { public static void main(String ...args) { { Random rnd = new Random(); BookHeap<Integer> heap = new BookHeap<Integer>(); long startTime = System.currentTimeMillis(); for(int i = 0; i < 1_000_000_0; i++) heap.insert(rnd.nextInt(1000)); System.out.println("Book's Heap:" + (System.currentTimeMillis() - startTime)); } { Random rnd = new Random(); OPHeap<Integer> heap = new OPHeap<Integer>(); long startTime = System.currentTimeMillis(); for(int i = 0; i < 1_000_000_0; i++) heap.insert(rnd.nextInt(1000)); System.out.println(" OP's Heap:" + (System.currentTimeMillis() - startTime)); } } } I get this output: Book's Heap:1924 OP's Heap:1171 However when I swap the order of the tests I get this output: OP's Heap:1867 Book's Heap:1515 This is called "Warm-up" and you can learn a lot of ways to deal with it from this article. Also anytime you are using Random in a test you should define a seed value, so your "pseudo random" results are predictable.
Searching LinkedList, comparing two "Strings"?
I have a LinkedList where each node contains a word. I also have a variable that contains 6 randomly generated letters. I have a code the determines all possible letter combinations of those letters. I need to traverse through the linked list and determine the best "match" among the nodes. Example: -Letters generated: jghoot -Linked list contains: cat, dog, cow, loot, hooter, ghlooter (I know ghlooter isn't a word) The method would return hooter because it shares the most characters and is most similar to it. Any ideas? I guess you could say I am looking for the word that the generated letters are a substring of.
use a nested for loop, compare each letter of your original string with the one you are comparing it to, and for each match, increase a local int variable. at the end of the loop, compare local int variable to global int variable that holds the "best" match till that one, and if bigger, store local int into global one, and put your found node into global node. at the end you should have a node which matches closest. something like this int currBest = 0; int currBestNode = firstNodeOfLinkedList; while(blabla) { int localBest = 0; for(i= 0; i < currentNodeWord.length; i++) { for(j=0; j < originalWord.length;j++) { if(currentNodeWord[i] == originalWord[j]) { localBest++ } } } if(localBest > currBest) { currBest = localBest; currBestNode = currentNodeStringBeingSearched; } } // here u are out of ur loop, ur currBestNode should be set to the best match found. hope that helps
If you're considering only character counts, first you need a method to count chars in a word public int [] getCharCounts(String word) { int [] result = new int['z' - 'a' + 1]; for(int i = 0; i<word.length(); i++) result[word.charAt(i) - 'a']++; return result; } and then you need to compare character counts of two words public static int compareCounts(int [] count1, int [] count2) [ int result = 0; for(int i = 0; i<count1.length; i++) { result += Math.min(count1[i], count2[i]); } return result; } public static void main(String[] args) { String randomWord = "jghoot"; int [] randomWordCharCount = getCharCounts(randomWord); ArrayList<String> wordList = new ArrayList(); String bestElement = null; int bestMatch = -1; for(String word : wordList) { int [] wordCount = getCharCounts(word); int cmp = compareCounts(randomWordCharCount, wordCount); if(cmp > bestMatch) { bestMatch = cmp; bestElement = word; } } System.out.println(word); }
I think this works. import java.util.*; import java.io.*; class LCSLength { public static void main(String args[]) { ArrayList<String> strlist=new ArrayList<String>(); strlist.add(new String("cat")); strlist.add(new String("cow")); strlist.add(new String("hooter")); strlist.add(new String("dog")); strlist.add(new String("loot")); String random=new String("jghoot"); //Your String int maxLength=-1; String maxString=new String(); for(String s:strlist) { int localMax=longestSubstr(s,random); if(localMax>maxLength) { maxLength=localMax; maxString=s; } } System.out.println(maxString); } public static int longestSubstr(String first, String second) { if (first == null || second == null || first.length() == 0 || second.length() == 0) { return 0; } int maxLen = 0; int fl = first.length(); int sl = second.length(); int[][] table = new int[fl+1][sl+1]; for(int s=0; s <= sl; s++) table[0][s] = 0; for(int f=0; f <= fl; f++) table[f][0] = 0; for (int i = 1; i <= fl; i++) { for (int j = 1; j <= sl; j++) { if (first.charAt(i-1) == second.charAt(j-1)) { if (i == 1 || j == 1) { table[i][j] = 1; } else { table[i][j] = table[i - 1][j - 1] + 1; } if (table[i][j] > maxLen) { maxLen = table[i][j]; } } } } return maxLen; } } Credits: Wikipedia for longest common substring algorithm. http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Longest_common_substring