We have a list of elements and have a very simplistic collision detection where we check every object against every other object.
The check is commutative, so to avoid repeating it twice, we would do this in C++:
for (list<Object>::iterator it0 = list.begin(); it0 != list.end(); ++it0)
{
for (list<Object>::iterator it1 = it0; it1 != list.end(); ++it1)
{
Test(*it0, *it1);
}
}
The key bit here is the copy
it1 = it0
How would you write this in Java?
You can do this with ListIterator:
for(ListIterator<O> outer = list.listIterator(); outer.hasNext() ; ) {
O oVal = outer.next();
for(ListIterator<O> inner = list.listIterator(outer.nextIndex()); inner.hasNext(); ) {
Test(oVal, inner.next());
}
}
For a linked list (which has slow index access) the list.listIterator(index) still needs to iterate to the right place, though.
But this way it is only O(n²) (and you can't get better than this) instead of O(n³) like the index-access in the other answers then. (You might be even faster if you copy your list first to an array, but it is only a constant factor here.)
Of course, if you usually need index-based access (or this iterator-cloning), you would better use an array-based list (or a custom list whose iterator supports cloning).
You cannot copy Java iterators, so you'll have to do it without them:
for(int i=0; i<list.size(); i++){
for(int j=i; j<list.size(); j++){
Test(list.get(i), list.get(j));
}
}
For a linked list (which has slow index access), I think there is a way to do it without incurring in the O(n²) slowdown that Paŭlo mentioned. As long as you don't care about the order the list is visited, you can start the outer loop from the last element and iterate back, and start the inner loop from the first element and iterate forward until the two iterators meet. See iterRevIterator in the code below. The call to list.listIterator(list.size()) is fast because list is a LinkedList, i.e. a doubly-linked list, and accessing the last element does not require iterating through the list.
The difference is not enormous...
iterIndex: 384.59ms sum=29656666
iterIterator: 1.91ms sum=29656666
iterRevIterator: 1.55ms sum=29656666
but still significant.
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;
public class TestIter {
public static int iterIndex(List<Integer> list) {
int sum = 0;
for(int i = 0; i < list.size(); ++i) {
for(int j = i+1; j < list.size(); ++j) {
sum += list.get(i) * list.get(j);
}
}
return sum;
}
public static int iterIterator(List<Integer> list) {
int sum = 0;
for(ListIterator<Integer> outer = list.listIterator(); outer.hasNext() ; ) {
Integer oVal = outer.next();
for(ListIterator<Integer> inner = list.listIterator(outer.nextIndex()); inner.hasNext(); ) {
sum += oVal * inner.next();
}
}
return sum;
}
public static int iterRevIterator(List<Integer> list) {
int sum = 0;
for(ListIterator<Integer> outer = list.listIterator(list.size()); outer.hasPrevious() ; ) {
Integer oVal = outer.previous();
for(ListIterator<Integer> inner = list.listIterator(); inner.nextIndex() <= outer.previousIndex(); ) {
sum += oVal * inner.next();
}
}
return sum;
}
public static void main(String[] args) {
int size = 1000;
int rep = 100;
int sum = 0;
// List<Integer> list = new ArrayList<Integer>();
List<Integer> list = new LinkedList<Integer>();
for (int i = 0; i < size; ++i) {
list.add(i);
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < rep; ++i) {
sum = iterIndex(list);
}
System.out.println("iterIndex: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);
startTime = System.currentTimeMillis();
for (int i = 0; i < rep; ++i) {
sum = iterIterator(list);
}
System.out.println("iterIterator: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);
startTime = System.currentTimeMillis();
for (int i = 0; i < rep; ++i) {
sum = iterRevIterator(list);
}
System.out.println("iterRevIterator: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);
}
}
Related
I have two 2d boolean arrays, the smaller array (shape) is going over the larger array (world).
I am having trouble to find a method to find out when the smaller array can "fit" into the larger one.
When I run the code it either just goes through the larger array, never stopping, or stops after one step (incorrectly).
public void solve() {
ArrayList<Boolean> worldList=new ArrayList<>();
ArrayList<Boolean> shapeList=new ArrayList<>();
for (int i = 0; i < world.length; i++) {
for (int k = 0; k < world[i].length; k++) {
worldList.add(world[i][k]);
display(i, k, Orientation.ROTATE_NONE);
for (int j = 0; j < shape.length; j++) {
for (int l = 0; l < shape[j].length; l++) {
shapeList.add(shape[j][l]);
if(shapeList.equals(worldList)) {
return;
}
}
}
}
}
}
A good place to start with a problem like this is brute force for the simplest case. So, for each index in the world list, just check to see if every following index of world and shapes match.
Notice we only iterate to world.size()-shapes.size(), because naturally if shapes is longer than the portion of world we haven't checked, it won't fit.
import java.util.ArrayList;
public class Test {
ArrayList<Boolean> world = new ArrayList<>();
ArrayList<Boolean> shapes = new ArrayList<>();
public static void main(String[] args) {
new Work();
}
public Test() {
world.add(true);
world.add(false);
world.add(false);
world.add(true);
shapes.add(false);
shapes.add(true);
// Arraylists initialized to these values:
// world: T F F T
// shapes: F T
System.out.println(getFitIndex());
}
/**
* Get the index of the fit, -1 if it won't fit.
* #return
*/
public int getFitIndex() {
for (int w = 0; w <= world.size()-shapes.size(); w++) {
boolean fits = true;
for (int s = 0; s < shapes.size(); s++) {
System.out.println("Compare shapes[" + s + "] and world["+ (w+s) + "]: " +
shapes.get(s).equals(world.get(w+s)));
if (!shapes.get(s).equals(world.get(w+s))) fits = false;
}
System.out.println();
if (fits) return w;
}
return -1;
}
}
When we run this code, we get a value of 2 printed to the console, since shapes does indeed fit inside world, starting at world[2].
You can find the row and column of fitting like this
public void fit() {
int h = world.length - shape.length;
int w = world[0].length - shape[0].length;
for (int i = 0; i <= h; i++) {
for (int k = 0; k <= w; k++) {
boolean found = true;
for (int j = 0; j < shape.length && found; j++) {
for (int l = 0; l < shape[j].length && found; l++) {
if (shape[j][l] != world[i + j][k + l])
found = false;
}
}
if (found) {
//Your shape list fit the world list at starting index (i, k)
//You can for example save the i, k variable in instance variable
//Or return then as an object for further use
return;
}
}
}
I need to find all the permutations for a given n(user input) without backtracking.
What i tried is:
import java.util.Scanner;
import java.util.Vector;
class Main {
private static int n;
private static Vector<Vector<Integer>> permutations = new Vector<>();
private static void get_n() {
Scanner user = new Scanner(System.in);
System.out.print("n = ");
n = user.nextInt();
}
private static void display(Vector<Vector<Integer>> permutations) {
for (int i = 0; i < factorial(n) - 1; ++i) {
for (int j = 0; j < n; ++j) {
System.out.print(permutations.elementAt(i).elementAt(j) + " ");
}
System.out.println();
}
}
private static int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}
private static int max(Vector<Integer> permutation) {
int max = permutation.elementAt(0);
for (int i = 1; i < permutation.size(); ++i)
if (permutation.elementAt(i) > max)
max = permutation.elementAt(i);
return max;
}
// CHECKS FOR ELEMENT COUNT AND 0 - (n-1) APPARITION
public static int validate_permutation(Vector<Integer> permutation) {
// GOOD NUMBER OF ELEMENTS
if (max(permutation) != permutation.size() - 1)
return 0;
// PROPER ELEMENTS APPEAR
for (int i = 0; i < permutation.size(); ++i)
if (!permutation.contains(i))
return 0;
return 1;
}
private static Vector<Integer> next_permutation(Vector<Integer> permutation) {
int i;
do {
i = 1;
// INCREMENT LAST ELEMENT
permutation.set(permutation.size() - i, permutation.elementAt(permutation.size() - i) + 1);
// IN A P(n-1) PERMUTATION FOUND n. "OVERFLOW"
while (permutation.elementAt(permutation.size() - i) == permutation.size()) {
// RESET CURRENT POSITION
permutation.set(permutation.size() - i, 0);
// INCREMENT THE NEXT ONE
++i;
permutation.set(permutation.size() - i, permutation.elementAt(permutation.size() - i) + 1);
}
} while (validate_permutation(permutation) == 0);
// OUTPUT
System.out.print("output of next_permutation:\t\t");
for (int j = 0; j < permutation.size(); ++j)
System.out.print(permutation.elementAt(j) + " ");
System.out.println();
return permutation;
}
private static Vector<Vector<Integer>> permutations_of(int n) {
Vector<Vector<Integer>> permutations = new Vector<>();
// INITIALIZE PERMUTATION SET WITH 0
for (int i = 0; i < factorial(n); ++i) {
permutations.addElement(new Vector<>());
for(int j = 0; j < n; ++j)
permutations.elementAt(i).addElement(0);
}
for (int i = 0; i < n; ++i)
permutations.elementAt(0).set(i, i);
for (int i = 1; i < factorial(n); ++i) {
// ADD THE NEXT PERMUTATION TO THE SET
permutations.setElementAt(next_permutation(permutations.elementAt(i - 1)), i);
System.out.print("values set by permutations_of:\t");
for (int j = 0; j < permutations.elementAt(i).size(); ++j)
System.out.print(permutations.elementAt(i).elementAt(j) + " ");
System.out.println("\n");
}
System.out.print("\nFinal output of permutations_of:\n\n");
display(permutations);
return permutations;
}
public static void main(String[] args) {
get_n();
permutations.addAll(permutations_of(n));
}
}
Now, the problem is obvious when running the code. next_permutation outputs the correct permutations when called, the values are set correctly to the corresponding the vector of permutations, but the end result is a mass copy of the last permutation, which leads me to believe that every time a new permutation is outputted by next_permutation and set into the permutations vector, somehow that permutation is also copied over all of the other permutations. And I can't figure out why for the life of me.
I tried both set, setElementAt, and an implementation where I don't initialize the permutations vector fist, but add the permutations as they are outputted by next_permutation with add() and I hit the exact same problem. Is there some weird way in which Java handles memory? Or what would be the cause of this?
Thank you in advance!
permutations.setElementAt(next_permutation(permutations.elementAt(i - 1)), i);
This is literally setting the vector at permutations(i) to be the same object as permutations[i-1]. Not the same value - the exact same object. I think this the source of your problems. You instead need to copy the values in the vector.
I'm currently working my way up in the algorithmical problems. But I guess I still don't fully understand how to count algorithm complexity. I would say that my code have complexity O(n^3) because of three main loops inside them working on the data set, could someone confirm this or if I'm wrong show me on this bit of code how it should be counted?
public class BigOhN3 {
private Integer[] result;
private long time;
BigOhN3(Integer[] list) {
long start = System.currentTimeMillis();
int coefficientSum = calculateCoefficient(list);
result = new Integer[list.length];
//Main loop
for(int i = 0; i < list.length; i++) {
int coefficientSumIndexI = coefficientSum;
for(int j = 0; j < list.length; j++) {
Integer[] listIndexJ = list.clone();
if(j == i && j < list.length - 1) {
j++;
}
int a = listIndexJ[i];
int b = listIndexJ[j];
listIndexJ[i] = b;
listIndexJ[j] = a;
int coefficientSumIndexJ = calculateCoefficient(listIndexJ);
if(coefficientSumIndexJ < coefficientSumIndexI) {
coefficientSumIndexI = coefficientSumIndexJ;
result[i] = coefficientSumIndexJ;
}
}
if(result[i] == null) {
result[i] = coefficientSum;
}
}
time = System.currentTimeMillis() - start;
}
public long getTime() {
return time;
}
private int calculateCoefficient(Integer[] list) {
int sum = 0;
for(int i = 0; i < list.length - 1; i++) {
int item = list[i] - list[i + 1];
if(item < 0) {
item = item * (-1);
}
sum = sum + item;
}
return sum;
}
Integer[] getResult() {
return result;
}
}
It's O(n^3) indeed. But even if there was no most inner loop, it would be O(n^3) due to cloning a list (an array actually) takes at least O(n) as you need at least to read all elements. This means, that the complexity of the algorithm is:
O(n)*O(n)*(O(n)+O(n)) = O(n^3)
n times execute a loop a.
for each execution of a, execute loop b n times.
for each execution of b copy an array which takes O(n) and run the third loop which executes n times.
I want to get pairs of objects from an ArrayList so I can perform calculations between the elements of each object. Ideally it should iterate over pairs of objects. For example in a List with {obj1, obj2, obj3, obj4} it should go over {obj1,obj2}, {obj2,obj3} and {obj3,obj4}.
What I have tried so far is as follows.
public class Sum {
public ArrayList<Double> calculateSum(ArrayList<Iter> iter) {
ListIterator<Iter> it = iter.listIterator();
ArrayList<Double> sums = new ArrayList<>();
while (it.hasNext()) {
Iter it1 = it.next();
Iter it2;
if(it.hasNext()){
it2 = it.next();
} else { break; }
double sum = it1.getValue() + it2.getValue();
sums.add(sum);
}
return sums;
}
}
Here, it just iterates as {obj1,obj2} and {obj3,obj4}. How can I fix this?
All help is greatly appreciated. Thanks!
A very normal loop, except that you need to loop up to list.size() - 1, the before last element of the array.
public ArrayList<Double> calculateSum(ArrayList<Iter> list) {
ArrayList<Double> sums = new ArrayList<>();
for (int i = 0; i < list.size() - 1; i++) {
double sum = list.get(i).getValue() + list.get(i + 1).getValue();
sums.add(sum);
}
return sums;
}
EDIT
Using an iterator in this case will not be faster than doing a normal loop and just makes the logic unnecessarily complicated and can easily introduce bugs.
A little modification to Davide's answer
for (int i = 0; i < list.size() - 1; i ++) {
sums.add(list.get(i) + list.get(i+1));
}
Because the OP wanted {obj1, obj2} {obj2, obj3} ...etc
Using a iterator
itr = list.iterator();
while(itr.hasNext()) {
Double x = itr.next();
if(itr.hasNext()){
x+= itr.next();
sum.add(x);}
itr.previous();
}
This is not recommended.
Simply use a for loop and stop at element before last one.
for (int i = 0; i < iter.size() - 1; i++) {
Iter first = iter.get(i);
Iter second = iter.get(i + 1);
// Your code here
}
public static ArrayList<Double> calculateSum(ArrayList<Iter> iter) {
ListIterator<Iter> it = iter.listIterator();
ArrayList<Double> sums = new ArrayList<>();
if (it.hasNext()) {
double prev = it.next().getValue();
while (it.hasNext()) {
double current = it.next().getValue();
double sum = prev + current;
sums.add(sum);
prev = current;
}
}
return sums;
}
Try this :-
public ArrayList<Double> calculateSum(ArrayList<Iter> inputList) {
ArrayList<Double> sums = new ArrayList<Double>();
int inputSize = inputList.size(); // size should be saved as an int , instead of calling size() over the list again and again in for loop
int incVar = 1; // 1 incremented value
double sum = 0.0d;
for(int i = 0; incVar < inputSize; i++,incVar++){
sum = inputList.get(i).getValue() + inputList.get(incVar).getValue();
sums.add(sum);
}
return sums;
}
I've tried many different variations, and I keep getting the same problem. After selectio nsort runs, the number of items outputted, does not match the size of my array. I've been running through with any array of size 10, yet the output does not contain 10 numbers. However, the output of selection sort is sorted.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Sorts {
public static Integer[] createArray(int size) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < size; i++)
list.add(i);
Collections.shuffle(list);
Integer[] array = list.toArray(new Integer[list.size()]);
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
}
return array;
}
public static void selectionSort(Integer[] array) {
Integer min;
for (Integer i = 0; i < array.length - 1; i++) {
min = i;
for (Integer j = i + 1; j < array.length; j++) {
if (array[j].compareTo(array[min]) > 0) {
min = j;
}
}
if (min != i) {
Integer temp = array[i];
array[i] = array[min];
array[min] = temp;
System.out.print(array[i]);
}
}
}
public static void main(String args[]) {
int number = 10;
Integer[] list = createArray(number);
System.out.println("");
selectionSort(list);
}
}
Whenever you make a swap, you print out a number. But in an array of 10 elements, you'll only make 9 swaps -- the final element will already be in its correct place! To fix this, add System.out.print(array[array.length - 1]); to the end of your function.
Also, if the minimum element happens to be i, then no swap will be performed and no element printed. This still sorts the array, but if you want it to be printed out, you could remove the if (min != i) statement and simply do a swap on every pass through the list.
You should also take a look at using ints rather than Integers. An Integer is generally slower than an int and you usually only use them when Java wants an object.