Trying to wrap my head around 3 nested if statments - java

Say I have an array of 5 strings and that related to that array is 3 arrays of integers all of the same size. e.g.`
String a[] = new String[5]
int x[] = new int[5]
int y[] = new int[5]
int z[] = new int[5]
so that a[0],x[0],y[0],z[0] are all related to the same thing.
I want to find out which index(es) in x[] hold the highest number. If more than one those has the same highest number then which of those has the highest number in y[] and if there is more than one with the same highest number which one would have the highest in z[](Its safe to assume that none would have the same max value in z[]
I've tried to explain as best I can..
This is the best if got it only checks the first 2 conditions
for(int i=0;i<a.length;i++)
{
if(x[i]>=maximum){
if(x[i]==maximum)
{
if(y[i]>=maximum)
{
maximum=x[i];
winner=a[i];
maximum=y[i];
}
}
else
{
maximum=x[i];
winner=teams[i];
maximum=y[i];
}
}
So this is my new code
static int compareValues(){
for (int i=0; i<a.length; i++){
int max =0;
int diff = x[i] - x[max];
if (diff == 0){
diff = y[i] - y[max];
}
if (diff == 0){
diff = z[i] - z[max];
}
if (diff > 0){
max = i
}
}
return max;
}

If the String[n] is related to the int[n]s for each n then really you should compose them properly, make them Comparable and sort them.
class Thing implements Comparable<Thing> {
final String a;
final int x;
final int y;
final int z;
public Thing(String a, int x, int y, int z) {
this.a = a;
this.x = x;
this.y = y;
this.z = z;
}
#Override
public int compareTo(Thing o) {
int diff = o.x - x;
if (diff == 0) {
diff = o.y - y;
}
if (diff == 0) {
diff = o.z - z;
}
return diff;
}
#Override
public String toString() {
return "{" + a + "," + x + "," + y + "," + z + "}";
}
}
public static int max(Thing[] things) {
// NB - This should really call compareTo.
int max = 0;
for (int i = 1; i < things.length; i++) {
int diff = things[i].x - things[max].x;
if (diff == 0) {
diff = things[i].y - things[max].y;
}
if (diff == 0) {
diff = things[i].z - things[max].z;
}
if (diff > 0) {
// Higher
max = i;
}
}
return max;
}
public void test() {
Thing[] things = new Thing[6];
things[0] = new Thing("Hello", 1, 2, 3);
things[1] = new Thing("There", 1, 2, 4);
things[2] = new Thing("Everyone", 0, 2, 3);
things[3] = new Thing("How", 9, 0, 3);
things[4] = new Thing("Are", 8, 9, 3);
things[5] = new Thing("You", 7, 2, 3);
System.out.println("Before: " + Arrays.toString(things));
System.out.println("Max: " + things[max(things)]);
Arrays.sort(things);
System.out.println("Sorted: " + Arrays.toString(things));
}

This solution might be easier to understand:
static String compareValues() {
// find the maximum in x
int xMax = Integer.MIN_VALUE;
for (int i = 0; i < 5; i++) {
if (x[i] > xMax) {
xMax = x[i];
}
}
// find the maximum in y, but limited to the positions where x is maximal according to the calculation above
int yMax = Integer.MIN_VALUE;
for (int i = 0; i < 5; i++) {
if (x[i] == xMax && y[i] > yMax) {
yMax = y[i];
}
}
// find the maximum in z, but limited to the positions where y is maximal according to the calculation above
int zMax = Integer.MIN_VALUE;
int iMax = 0;
for (int i = 0; i < 5; i++) {
if (y[i] == yMax && z[i] > zMax) {
zMax = z[i];
iMax = i; // record the maximum position
}
}
return a[iMax];
}
I did not test the code, but I think that it should work.

Related

How to write a number as sum of some other numbers' power

Okay firstly I'm sorry I know that I'm not intelligent enough. I'm bad at Math.
I couldn't write an algorithm to this question.
System gives us int x, int y, int boundary and wants us to find which numbers up to boundary satisfy the rule as
some_number = x^i + y^j
Boundary <= 10^6
i and j > = 0
x and y < 100
for example x = 2, y = 3 and boundary= 5,
2 = 2^0 + 3^0
3 = 2^1 + 3^0
4 = 2^0 + 3^1
5 = 2^1 + 3^1
output : 2,3,4,5
import java.util.ArrayList;
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int num = 0;
int remain_x = 0, remain_y = 0;
int count_x = 0, count_y = 0;
if (boundary >= 2) {
res.add(2);
}
for (int i = 3; i <= boundary; ++i) {
if(i == x+y)
res.add(i);
count_x = 0;
count_y = 0;
num = i;
while (num > 0) {
remain_x = num % x;
if (remain_x == 0) {
count_x++;
} else {
while (num > 0) {
remain_y = num % y;
if (remain_y == 0) {
count_y++;
}
num = num / y;
}
}
num = num / x;
}
System.out.println("i =>" +i);
System.out.println("x=>" + count_x);
System.out.println("y =>" + count_y);
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y, boundary );
System.out.println(res);
}
}
Edit:
I wrote something after reading Shark's comment thank you so much. it's working.
import java.util.ArrayList;
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x_k = 0;
int y_k= 0;
while(Math.pow(x,x_k)< boundary){
x_k++;
}
while(Math.pow(y,y_k)< boundary){
y_k++;
}
for(int k = 2 ; k<= boundary;++k) {
for (int i = 0; i < x_k; ++i) {
for (int j = 0; j < y_k; ++j) {
if(k == (int)Math.pow(x,i)+(int)Math.pow(y,j) && !res.contains(k)){
System.out.println("----------------------------------------");
System.out.println(k +" =>" +x + "^" +i +"+"+y+ "^" +j);
res.add(k);
}
}
}
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y,boundary);
System.out.println("x:" + x);
System.out.println("y:" + y);
System.out.println("boundary:" + boundary);
System.out.println("Result:" + res);
}
}
I am not sure if this is the most efficient method. Basically, I increment j until x^i + y^j > boundary then increment i.
public static ArrayList<Integer> findNumbers(int x, int y, int boundary) {
Set<Integer> result = new HashSet<>(); // make sure result is unique
int powerX = 0, powerY = 0, total = 0, tempX = 0;
while (true) {
// calculate x^i
tempX = (int) Math.pow(x, powerX);
while (true) {
// calculate x^i + y^j and compare against boundary
if ((total = tempX + (int) Math.pow(y, powerY)) <= boundary) {
// add result to set and increment y
result.add(total);
powerY++;
// break if y <= 1
if (y <= 1)
break;
} else
break;
}
// break if x <= 1 || x^i > boundary
if (tempX > boundary || x <= 1)
break;
// reset j and increment i
powerY = 0;
powerX++;
}
// return sorted result
ArrayList<Integer> arr = new ArrayList<>();
arr.addAll(result);
arr.sort(null);
return arr;
}
You might be able refactor the code for better efficiency.
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x_k = 0;
int y_k= 0;
while(Math.pow(x,x_k)< boundary){
x_k++;
}
while(Math.pow(y,y_k)< boundary){
y_k++;
}
for(int k = 2 ; k<= boundary;++k) {
for (int i = 0; i < x_k; ++i) {
for (int j = 0; j < y_k; ++j) {
if(k == (int)Math.pow(x,i)+(int)Math.pow(y,j) && !res.contains(k)){
System.out.println("----------------------------------------");
System.out.println(k +" =>" +x + "^" +i +"+"+y+ "^" +j);
res.add(k);
}
}
}
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y,boundary);
System.out.println("x:" + x);
System.out.println("y:" + y);
System.out.println("boundary:" + boundary);
System.out.println("Result:" + res);
}
}

Find smallest possible array for given condition

I have an array say int[] x = {1,0,0,2,0,2}. Sum of pow(2,x[i]) of each element is 13.
I want to find Smallest Possible Array which fulfills same condition (sum of square of each element should be 13).
Please help me out.
public void solution() {
double equation = 0;
int[] a = new int[] { 2, 1, 0, 5, 2, 3 };
try {
for (int i = 0; i < a.length; i++) {
equation = equation + Math.pow(2, a[i]);
}
System.out.println(equation);
int equation1 = (int) equation;
int binaryArray[] = new int[30];
int i = 0;
while (equation1 > 0) {
binaryArray[i++] = equation1 % 2;
equation1 = equation1 / 2;
}
int sum = 0;
List<Integer> list = new ArrayList<Integer>();
do {
for (int j = i - 1; j >= 0; j--) {
if (binaryArray[j] == 0) {
i--;
continue;
}
sum = sum + (binaryArray[j] * (int) Math.pow(2, i));
i--;
list.add(i);
}
} while (i > 0);
// shortest list
System.out.println(list);
// length of shortest list
System.out.println(list.size());
} finally {
}
}

Bruteforce and Conquer and Divide not giving same distance answer for Closest Pair of Points

I created a program that generates a user inputted number of pairs of points. It then goes through a bruteforce and divide and conquer methods to find the closest pair of points. The bruteforce method works perfectly. The divide and conquer method on the other hand gives me an output but it is different than the brute force distance almost 90% of the time. I can't seem to figure out why it is like this in my code. NOTE: Some of the comments in the functions are from my teacher. Also, the closest_pair function along with rec_cl_pair have been given to me by my teacher where I must use them but had to adjust to my code (they were pseudo code for most part).
My code is:
import java.util.*;
import static java.lang.Math.min;
public class ClosestPair{
private Double x;
private Double y;
private static Double minDist = Double.POSITIVE_INFINITY;
private static ClosestPair closestPair1 = new ClosestPair(0.0,0.0);
private static ClosestPair closestPair2 = new ClosestPair(0.0,0.0);
public ClosestPair(Double x, Double y){
this.x = x;
this.y = y;
}
public static void main(String[] args) {
Double rangeMin = 0.0;
Double rangeMax = 1000.0;
Random r = new Random();
Scanner scan = new Scanner(System.in);
System.out.print("\nEnter the number of two dimensional arrays: ");
int dim = scan.nextInt();
ClosestPair[] pair = new ClosestPair[dim];
ClosestPair[] pairCopy = new ClosestPair[dim];
for(int i = 0; i < dim; i++){
Double xVal = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
Double yVal = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
pair[i] = new ClosestPair(xVal,yVal);
//System.out.print(pair[i].x + ", " + pair[i].y + "\n");
}
/*
for(int j = 0; j < pair.length; j++){
System.out.print(pair[j].x + ", " + pair[j].y + "\n");
}
*/
pairCopy = pair;
pair = mergeSort(pair);
/*
System.out.print("\n\n\n");
for(int j = 0; j < pair.length; j++){
System.out.print(pair[j].x + ", " + pair[j].y + "\n");
}
*/
//BRUTE FORCE PRINT STATEMENTS
long startTime = System.nanoTime();
bruteForce(pair);
long endTime = System.nanoTime();
long timeSpent = endTime - startTime;
System.out.print("\nMin Distance = " + minDist);
System.out.print("\n(x1,y1) = " + closestPair1.x + ", " + closestPair1.y);
System.out.print("\n(x2,y2) = " + closestPair2.x + ", " + closestPair2.y);
System.out.print("\nTime: " + timeSpent + "\n\n");
minDist = 0.0;
//CONQUER DIVIDE PRINT STATEMENTS
startTime = System.nanoTime();
minDist = closest_pair(pairCopy);
endTime = System.nanoTime();
timeSpent = endTime - startTime;
System.out.print("Min Distance = " + minDist);
System.out.print("\nTime: " + timeSpent);
scan.close();
}
private static void bruteForce(ClosestPair[] pair) {
for(int i = 1; i < pair.length - 1; i++){
for(int j = i + 1; j < pair.length; j++){
ClosestPair p = new ClosestPair(pair[i].x,pair[i].y);
//System.out.print("\np:" + pair[i].x + ", " + pair[i].y);
ClosestPair q = new ClosestPair(pair[j].x,pair[j].y);
//System.out.print("\nq: " + pair[j].x + ", " + pair[j].y);
if(getDistance(p, q) < minDist){
minDist = getDistance(p, q);
closestPair1.x = p.x;
closestPair1.y = p.y;
closestPair2.x = q.x;
closestPair2.y = q.y;
}
}
}
}
private static Double getDistance(ClosestPair p1, ClosestPair p2) {
double xdist = p2.x - p1.x;
double ydist = p2.y - p1.y;
return Math.hypot(xdist, ydist);
}
static ClosestPair[] mergeSort(ClosestPair[] a) {
if (a.length > 1) {
int q = a.length/2;
ClosestPair[] leftArray = Arrays.copyOfRange(a, 0, q);
ClosestPair[] rightArray = Arrays.copyOfRange(a,q,a.length);
mergeSort(leftArray);
mergeSort(rightArray);
a = merge(a,leftArray,rightArray);
}
return a;
}
static ClosestPair[] merge(ClosestPair[] a, ClosestPair[] l, ClosestPair[] r) {
int totElem = l.length + r.length;
//int[] a = new int[totElem];
int i,li,ri;
i = li = ri = 0;
while ( i < totElem) {
if ((li < l.length) && (ri<r.length)) {
if (l[li].x < r[ri].x) {
a[i] = l[li];
i++;
li++;
}
else {
a[i] = r[ri];
i++;
ri++;
}
}
else {
if (li >= l.length) {
while (ri < r.length) {
a[i] = r[ri];
i++;
ri++;
}
}
if (ri >= r.length) {
while (li < l.length) {
a[i] = l[li];
li++;
i++;
}
}
}
}
return a;
}
//START OF CONQUER DIVIDE SECTOIN
static double closest_pair(ClosestPair[] p){
int n = p.length - 1;
p = mergeSortDC(p, 0, n); // sort all n points by x-coordinate
return rec_cl_pair(p, 0, n);
}
static double rec_cl_pair(ClosestPair[] p, int i, int j){ // finds closest pair between points in p[i..j]
// assumes input is sorted by x-coordinate
// at termination, input is sorted by y-coordinate
// i is the left index of the subarray, j is the right index
if (j - i < 3){ // at most 3 points in p[i..j]
p = mergeSortDC (p, i, j); // sort p[i..j] by y-coordinate
double delta = getDistance(p[i], p[i+1]);
if (j - i == 1) { // two points
minDist = delta;
return delta;
}
else{
double min1 = min(getDistance(p[i+1], p[i+2]), getDistance(p[i], p[i+2]));
minDist = min(delta,min1);
return minDist;
}
}
int m = (i + j)/2;
double line = p[m].x;
double deltaL = rec_cl_pair(p, i, m); // p[i..m] is sorted by y-coordinate
double deltaR = rec_cl_pair(p, m+1, j); // p[m+1..j] is sorted by y-coordinate
double delta = min(deltaL, deltaR);
p = mergeDC(p, i, m, j); // p[i..j] is now sorted by y-coordinate
// Of points in p[i..j], find points in vertical strip of width 2*delta,
// centered at line (middle of x-values), and store in array v
int t = 0;
ClosestPair[] v = new ClosestPair[j+1];
for(int k = i; k < j; k++){
if ((p[k].x > line - delta) && (p[k].x < line + delta)){
t = t + 1;
v[t] = p[k];
}
}
// Find closest pairs among points in array v. NOTE: Cool math shows
// there are at most 8 points in the strip at distance < delta. Thus,
// in the loops below, each point is compared to at most 7 other points.
for(int k = 1;k < t-1; k++){
for(int s = k+1; k < min(t,k+7); s++){ // inner loop iterates <= 7 times
delta = min(delta, getDistance(v[k],v[s]));
minDist = delta;
return delta;
}
}
return minDist;
}
private static ClosestPair[] mergeSortDC(ClosestPair[] p, int low, int high) {
// check if low is smaller then high, if not then the array is sorted
if (low < high) {
// Get the index of the element which is in the middle
int middle = low + (high - low) / 2;
// Sort the left side of the array
mergeSortDC(p, low, middle);
// Sort the right side of the array
mergeSortDC(p, middle + 1, high);
// Combine them both
p = mergeDC(p, low, middle, high);
}
return p;
}
private static ClosestPair[] mergeDC(ClosestPair[] p, int low, int middle, int high) {
ClosestPair[] helper = new ClosestPair[p.length];
// Copy both parts into the helper array
for (int i = low; i <= high; i++) {
helper[i] = p[i];
}
int i = low;
int j = middle + 1;
int k = low;
// Copy the smallest values from either the left or the right side back
// to the original array
while (i <= middle && j <= high) {
if (helper[i].x <= helper[j].x) {
p[k] = helper[i];
i++;
} else {
p[k] = helper[j];
j++;
}
k++;
}
// Copy the rest of the left side of the array into the target array
while (i <= middle) {
p[k] = helper[i];
k++;
i++;
}
return p;
}
}
An example of output is:
Enter the number of two dimensional arrays: 50
Min Distance = 19.014027210555614
(x1,y1) = 76.99595098629398, 600.1657767818473
(x2,y2) = 87.04091889578226, 616.3098732403395
Time: 3852815
Min Distance = 29.457199999686082
Time: 414081
The first min distance is the bruteforce result. The second is the divide and conquer result

Adding binary numbers in Java

I have a function which takes two binary numbers as an array of integers, adds the numbers, then returns the sum as a new array of integers.
public static int[] addBin(int a[], int b[]){
int[] sum = {0, 0, 0, 0, 0, 0, 0, 0};
int carryover = 0;
int randombanana = 0;
int x = 7;
for(x = 7; x > 0; x--){
randombanana = a[x] + a[x] + carryover;
if(randombanana == 1){
sum[x] = 1;
carryover = 0;
}
else if(randombanana == 2){
sum[x] = 0;
carryover = 1;
}
else if(randombanana == 3){
sum[x] = 1;
carryover = 1;
}
else if(randombanana == 0){
sum[x] = 0;
carryover = 0;
}
else{
System.out.println("Either I [censored] up, or you [censored] up. I'm a genius so I'm going to assume you [censored] up");
}
}
if(carryover == 1){
sum[x] = 1;
}
return sum;
}
The code works fine on single digit numbers, including numbers that require carrying a digit, but on double or triple digit numbers it works when a number is added to itself, but not when different multiple digit numbers are added.
Should be
randombanana = a[x] + b[x] + carryover;
Your for loop isn't handling the 0th bit
for(x = 7; x >= 0; x--){
Assuming the two numbers are of the same length the numbers could be added as follows:
public static int[] addNumbers(int[] firstNum, int[] secondNum) {
int[] result = new int[firstNum.length + 1];
int digitSum, carry = 0, i;
for (i = firstNum.length - 1; i >= 0; i--) {
digitSum = firstNum[i] + secondNum[i] + carry;
result[i + 1] = digitSum % 2;
carry = digitSum / 2;
}
result[0] = carry;
return result;
}
Here is a short and crisp solution.
public static int [] addBinaryNumbers(int a[],int b[])
{
int n =Integer.max(a.length, b.length);
int c[]=new int[n+1];
int carry =0;
for(int i=0;i<n;i++)
{
c[n-i]=(a[i]+b[i]+carry)%2;
carry= (a[i]+b[i]+carry) /2;
}
c[n]=carry;
return c;
}

Pseudo Infinite Loop (Optimally Deleting 'missing data' from a matrix)

When I use a random matrix (class Determine), my program runs successfully in 1700 miliseconds. However, when I create a matrix by reading a file through a buffered reader (class Construct) my program experiences a logic error and enters and infinite loop.
Again, it works for a random matrix, but does not work for a 'real' matrix of the same size. I've checked my work and cannot find an error in my reading of the file. Does anyone know what may be causing this logic error? I will append my code with comments if it helps!
Update: OK the problem was from my own silly oversight (see my answer below). This did not occur with random data due to my 'haveIt' method and the probability of getting missing data. As such, my code has been updated to reflect this logic error and I will be happy to explain in detail how this code works if anyone asks:
import java.util.Random;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.*;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.BufferedReader;
class ValMax {
public static int valMax;
}
class Construct {
private static int colEnd;
private static int colStart;
private static int[] colSkip;
public static List<List<Integer>> rFile(String[] args){
if (args.length != 4) {
System.out.println("Format: FileName colStart colEnd colSkipped");
System.exit(0);
}
BufferedReader reader = null;
try {
List<List<Integer>> matrix = new ArrayList<List<Integer>>();
Construct.colEnd = Integer.parseInt(args[2]);
Construct.colStart = Integer.parseInt(args[1]);
String[] colSkipped = args[3].split(",");
Construct.colSkip = new int[colSkipped.length];
for (int x = 0; x < colSkipped.length; x++) {
Construct.colSkip[x] = Integer.parseInt(colSkipped[x]);
}
String line;
reader = new BufferedReader(new FileReader(new File(args[0])));
while ((line = reader.readLine()) != null) {
String[] tokens = line.split(",");
List<Integer> rows = new ArrayList<Integer>(colEnd - colStart + 1 - colSkip.length);
for (int x = 1; x <= tokens.length; x++) {
if (x >= colStart && x <= colEnd && contains(x, colSkip) == false) {
try {
Double.parseDouble(tokens[x - 1]);
} catch (NumberFormatException e3) {
break;
}
if (tokens[x - 1].equals("-999")) { //
rows.add(2);
} else {
rows.add(1);
}
}
}
if (rows.size() == colEnd - colStart + 1 - colSkip.length) {
matrix.add(rows);
}
}
System.out.println(matrix.size() + "\t" + matrix.get(0).size());
return matrix;
} catch (IOException e1) {
System.out.println("IOEXCEPTION!!");
System.exit(0);
} catch (NumberFormatException e2) {
System.out.println("NumberFormatException!!");
System.exit(0);
} finally {
try {
reader.close();
} catch (IOException e5) {
e5.printStackTrace();
}
}
return null;
}
private static boolean contains(int a, int[] colSkip) {
boolean bluejay = false;
for (int skip : colSkip) {
if (a == skip) {
bluejay = true;
}
}
return bluejay;
}
}
class Determine {
private static Integer gen(int a, int b, Random r) {
Integer rand = r.nextInt(a) + b;
return rand;
}
public static List<List<Integer>> rando() {
Random r = new Random();
int k = gen(1, 24, r), l = gen(1, 33, r); //userinput
List<List<Integer>> matrix = new ArrayList<List<Integer>>(k);
for (int x = 1; x <= k; x++) {
List<Integer> row = new ArrayList<Integer>(l);
for (int y = 1; y <= l; y++) {
double bias = Math.random();
if (bias > 0.7) {
row.add(2);
} else {
row.add(1);
}
}
matrix.add(row);
}
return matrix;
}
}
class Search {
public static void finalize(List<List<Integer>> matTan, boolean gumDrop, int minimum) {
final int A = matTan.size();
final int B = matTan.get(0).size();
boolean judge = true;
if (minimum > A && gumDrop == false || minimum > B && gumDrop == true) {
System.out.print("\nMinimum too high\n\n");
System.exit(0);
}
ValMax.valMax = 1; //userinput
int[] rows = new int[2 + A + B];
List<int[]> combination = new ArrayList<int[]>(100);
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(threads);
List<List<int[]>> ranTime = new ArrayList<List<int[]>>(2 * threads);
for (int x = 0; x < 2 * threads; x++) {
List<int[]> jobs = new ArrayList<int[]>(90);
ranTime.add(jobs);
}
if (gumDrop == false) {
for (int x = 1; x <= minimum; x++) {
rows[x] = 1;
}
} else {
rows[1] = 1;
}
rows[A + 1] = 999;
int y = 0, z = 0;
System.out.println(threads);
while (rows[A + 1] == 999) {
y++;
int[] copy = Arrays.copyOf(rows, rows.length);
if (y == 91) {
z++;
y = 1;
if (z < 2* threads) {
ranTime.get(z).clear();
}
}
if (z == 2 * threads) {
processInputs(ranTime, combination, matTan, minimum, gumDrop, service);
z = 0;
ranTime.get(0).clear();
ranTime.get(0).add(copy);
} else {
ranTime.get(z).add(copy);
}
nextComb(A, rows);
}
if (ranTime.get(0).size() > 0) {
for (int x = 0; x < 2 * threads; x++) {
if (judge == false) {
ranTime.remove(x);
threads--;
x--;
}
if (ranTime.get(x).size() != 90 && judge == true) {
judge = false;
}
}
processInputs(ranTime, combination, matTan, minimum, gumDrop, service);
}
service.shutdown();
try {
service.awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException e6) {
System.out.print("Termination Error!");
}
developed(matTan, combination, gumDrop);
}
private static void processInputs(List<List<int[]>> ranTime, List<int[]> combination, List<List<Integer>> matTan, int minimum, boolean gumDrop, ExecutorService service) {
Collection<StringTask> collection = new ArrayList<StringTask>(ranTime.size());
for (List<int[]> jobs : ranTime) {
StringTask analysis = new StringTask(jobs, combination, matTan, minimum, gumDrop);
collection.add(analysis);
}
try {
List<Future<Integer>> futures = service.invokeAll(collection);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void developed(List<List<Integer>> matTan, List<int[]> combination, boolean gumDrop) {
System.out.print("\n\n\n");
for (int[] e : combination) {
if (e[0] == ValMax.valMax) { // == ValMax.valMax
Optimize10.prin(e);
List<List<Integer>> complete = Multi.reduct1(e, matTan);
if (gumDrop == true) {
System.out.println("Solution Matrix, transposed [above data works on column]");
Optimize10.prin(Multi.transpose(complete)); //The solution matrix, reorientated
} else {
System.out.println("Solution Matrix");
Optimize10.prin(complete); //The solution matrix, reorientated
}
}
}
}
private static void nextComb(int bounds, int[] rows) {
int kappas = findMax(rows);
if (rows[bounds] == 0) {
rows[kappas + 1] = 1;
rows[kappas] = 0;
} else {
int y = 1;
int x = bounds;
while (rows[x] == 1) {
rows[x] = 0;
y++;
x--;
}
kappas = findMax(rows);
if (kappas != -1) {
rows[kappas] = 0;
}
int z = kappas + 1;
while (y > 0) {
rows[z] = 1;
z++;
y--;
}
}
}
private static int findMax(int[] rows) {
int y = 0;
for (int x = rows.length - 1; x >= 0; x--) {
if (rows[x] == 1) {
return x;
}
}
return y;
}
}
class StringTask implements Callable<Integer> {
private List<List<Integer>> matTan;
private List<int[]> combination;
private List<int[]> jobs;
private boolean gumDrop;
private int minimum;
StringTask(List<int[]> a, List<int[]> b, List<List<Integer>> c, int d, boolean e) {
this.combination = b;
this.minimum = d;
this.gumDrop = e;
this.matTan = c;
this.jobs = a;
}
public Integer call() {
for (int[] e : jobs) {
int temp = Multi.reduct2(e, matTan, minimum, gumDrop);
if (temp > ValMax.valMax) { //ValMax.valMax //userinput
ValMax.valMax = e[0]; //userinput
combination.add(e);
System.out.print(ValMax.valMax + " ");
}
}
return null;
}
}
class Multi {
public static int[] inverse;
public static void halveIt(int[] col, List<List<Integer>> matCop) {
int size = matCop.size(), a = 0;
inverse = new int[size];
for (int x = 0; x < size; x++) {
for (int y = 0; y < matCop.get(0).size(); y++) {
if (col[y] == 1 && matCop.get(x).get(y) == 2) {
inverse[x + a] = 1;
matCop.remove(x);
size--;
x--;
a++;
break;
}
}
}
}
public static List<List<Integer>> reduct1(int[] row, List<List<Integer>> matCan) {
List<List<Integer>> matTan = new ArrayList<List<Integer>>(matCan);
int with = matTan.size(), high = inverse.length, a = 0;
final int B = matCan.get(0).size() - 1;
final int A = matCan.size();
for (int x = 0; x < A; x++) {
List<Integer> value = new ArrayList<Integer>(matCan.get(x));
matTan.set(x, value);
}
int y = 0, size = 0;
for (int x = 0; x < high; x++) {
if (x < with) {
if (row[x + a + 1] > 0) {
size = matTan.get(0).size();
for (y = 0; y < size; y++) {
if (matTan.get(x).get(y) == 2) {
for (int z = 0; z < with ; z++) {
matTan.get(z).remove(y);
}
size--;
y--;
}
}
} else {
matTan.remove(x);
with--;
high--;
x--;
a++;
}
}
}
return matTan;
}
public static int reduct2(int[] row, List<List<Integer>> matCan, int minimum, boolean gumDrop) {
int b = 0, c = 0, d = 0, e = 0, g = 0, high = inverse.length;
final int B = matCan.get(0).size() - 1;
final int A = matCan.size();
for (int x = 0; x < high; x++) {
if (x < A) {
if (row[x + 1] > 0) {
b++;
for (int y = 0; y < B + 1; y++) {
if (matCan.get(x).get(y) == 2 && row[2 + A + y] == 0) {
row[2 + A + y] = 1; // 1s mean that a column was deleted, 0 is kept.
d -= e;
} else if (row[2 + A + y] == 0) {
d++;
}
}
e++;
}
}
if (inverse[x] == 0 && x < high || gumDrop == true && x < high) {
if (row[x - c + 1] == 1) {
row[x - c + 1] = 1 + c + g;
g++;
} else {
g++;
}
} else {
c++;
}
}
if (d / b < minimum && gumDrop == true) {
row[0] = 0;
d = 0;
} else {
row[0] = d;
}
return d;
}
public static List<List<Integer>> transpose(List<List<Integer>> matTan) {
int d = matTan.get(0).size();
List<List<Integer>> matFlip = new ArrayList<List<Integer>>(d);
for (int y = 0; y < d; y++) {
List<Integer> row = new ArrayList<Integer>();
for (int x = 0; x < matTan.size(); x++) {
row.add(matTan.get(x).get(y));
}
matFlip.add(row);
}
return matFlip;
}
}
// ########## Main Method Start ##########
public class Optimize10 {
public static void main(String[] args) {
double startTime = System.nanoTime() / 1000000;
List<List<Integer>> matrix = Determine.rando();
// List<List<Integer>> matrix = Construct.rFile(args);
List<List<Integer>> matTan = contract(new int[matrix.get(0).size()], matrix);
int a = matTan.size(), b = matTan.get(0).size();
System.out.println(a + "\t" + b);
boolean gumDrop = false;
int minimum = 40; //userinput
BigInteger aNew = new BigInteger("2");
BigInteger bNew = new BigInteger("2");
aNew = aNew.pow(a);
bNew = bNew.pow(b);
for (int x = 1; x < minimum; x++) {
aNew = aNew.subtract(binomial(a, x));
}
if (aNew.compareTo(bNew) > 0) {
gumDrop = true;
matTan = Multi.transpose(matTan);
}
System.out.println(gumDrop);
prin(matrix);
prin(matTan);
Search.finalize(matTan, gumDrop, minimum);
double endTime = System.nanoTime() / 1000000;
double duration = (endTime - startTime);
System.out.println(duration);
}
// ########## MAIN METHOD END ############
private static BigInteger binomial(final int N, final int K) {
BigInteger ret = BigInteger.ONE;
for (int k = 0; k < K; k++) {
ret = ret.multiply(BigInteger.valueOf(N-k)).divide(BigInteger.valueOf(k+1));
}
return ret;
}
private static List<List<Integer>> contract(int[] col, List<List<Integer>> matrix) {
List<List<Integer>> matCop = new ArrayList<List<Integer>>(matrix);
col[0] = 1; //userinput 1 means don't delete!
col[1] = 1; //userinput
col[2] = 1;
col[12] = 1;
col[14] = 1;
col[22] = 1;
col[28] = 1;
col[29] = 1;
Multi.halveIt(col, matCop);
return matCop;
}
public static void prin(List<List<Integer>> matrix) {
for (int x = 0; x < matrix.size(); x ++) {
System.out.print("[" + matrix.get(x).get(0));
for (int y = 1; y < matrix.get(0).size(); y++) {
System.out.print(" " + matrix.get(x).get(y));
}
System.out.print("]\n");
}
System.out.print("\n\n");
}
public static void prin(int[] a) {
System.out.print("[" + a[0]);
for (int x = 1; x < a.length; x ++) {
System.out.print(" " + a[x]);
}
System.out.print("]\n\n");
}
public static void prin(String[] a) {
System.out.print("[" + a[0]);
for (int x = 1; x < a.length; x ++) {
System.out.print(" " + a[x]);
}
System.out.print("]\n\n");
}
public static void prin2(List<Integer> a) {
System.out.print("[" + a.get(0));
for (int x = 1; x < a.size(); x ++) {
System.out.print(" " + a.get(x));
}
System.out.print("]\n\n");
}
}
OK, so there actually was no infinite loop in this code whatsoever. The problem was with line 466 of my code; specifically, I was basing whether I analyzed the original matrix or its transpose on the number of rows after truncation on the original matrix and subtracting the minimum. This is wrong because, for example,
sum_{i = 40)^{54}(54 choose i) >> 2^32.
My program was taking forever because it was told to traverse through over a trillion combinations instead of 'just' a few billion. Granted it can do 10 billion in about 2 hours, and I can save more time by inverting a few nested for loops (another time).
I Guess it's time to learn profiling to see where my code slows down.

Categories

Resources