Why the baby step giant step algorithm does not work - java

I've been sitting for 3 days, I checked through debugging, I still don't see an error.
An equation like this: y = a^x mod p
To get started, we choose m=k=sqrt(p) + 1
. Then we start laying out 2 rows:
First: (a,ay,a^2 * y....a^(m-1) * y) mod p.
Second: (a^m, a^2m...a^km) mod p.
Then we look for the first available value from row 1 in the second and write down the indices of both, the answer should be
x = im - j, the equality a^(im) = a^j * y must also hold
BigInteger p = new BigInteger("61");
BigInteger m = p.sqrt().add(BigInteger.ONE);
BigInteger k = p.sqrt().add(BigInteger.ONE);
BigInteger a = new BigInteger("2");
BigInteger y = new BigInteger("45");
ArrayList<BigInteger> array1 = new ArrayList<>();
ArrayList<BigInteger> array2 = new ArrayList<>();
for(BigInteger i = BigInteger.ZERO; i.compareTo(m) < 0; i = i.add(BigInteger.ONE)) {
BigInteger temp = y.multiply(a.pow(i.intValue())).mod(p);
System.out.println(temp);
array1.add(temp);
}
System.out.println("---------------------------------------------------------");
System.out.println("---------------------------------------------------------");
System.out.println("---------------------------------------------------------");
for(BigInteger j = BigInteger.ONE; j.compareTo(k) < 0; j = j.add(BigInteger.ONE)) {
BigInteger temp = a.pow(j.multiply(m).intValue()).mod(p);
array2.add(temp);
System.out.println("temp = " + temp);
for(int h = 0; h < array1.size(); h++) {
if(Objects.equals(array1.get(h), temp)) {
System.out.println(a.pow(m.multiply(BigInteger.valueOf(h)).intValue()));
System.out.println(a.pow(j.intValue()).multiply(y));
System.out.println("h = " + h + " m = " + m + " j = " + j);
return BigInteger.valueOf(h).multiply(m).subtract(j);
}
/*if(a.pow(m.multiply(BigInteger.valueOf(h)).intValue()).equals(a.pow(j.intValue()).multiply(y))) {
System.out.println("h = " + h + " m = " + m + " j = " + j);
return new BigInteger("-1");
}*/
}
}
return new BigInteger("-1");
}

Related

Trying to get my algorithm to O(n) runtime

So in my advanced algorithms class, we are to write an algorithm for a program to find two numbers in two sorted arrays of integers. The format is A[i] + B[j] == x. The runtime of the algorithm needs to be O(n).
I thought i had it and wanted to check so I emailed my professor and she told me my runtime was O(n^2). Here is my code:
int[] A = {1,2,3,4,5};
int[] B = {1,2,3,4,5,6};
int x = 4;
int i = 0;
int j = 0;
for(int n = 0; n < (A.length*B.length); n++) {
if(i >= A.length)
i = 0;
if(n % B.length == 0)
j++;
if(A[i] + B[j] == x) {
System.out.println(A[i] + " + " + B[j] + " = " + x);
break;
}
i++;
}
EDIT
I do apologize if this is still incorrect. I never really grasped the concept of Big-Oh. Would this change the runtime to O(n)? I got rid of the A.length*B.length and tried something a little different.
int[] A = {1,2,3,4,5};
int[] B = {1,2,3,4,5};
int x = 5;
int i = 0;
int j = 0;
while(i < A.length) {
if(B[j] == x - A[i]) {
/* exit */ }
if(j >= B.length) {
j = 0;
i++; }
j++;
}
Solution 1:
Add all values in B to a Map with B value as the map key, and B-index as the map value.
Iterate A, and calculate desired B value as B = x - A. Look for it in the map, and if found, you then have the index.
You will only iterate A and B once each. Adding a single value to map is O(1), and looking up a value is O(1), assuming a HashMap, so overall is O(n).
Solution 2:
Iterate A ascending, and B descending.
For each value in A, look at current B value. Walk down B until A + B <= x (or you reach beginning of B).
You will only iterate A and B once each, so O(n).
Solution 2 requires less memory (no map), and is likely faster (no time spent building map).
UPDATE Here is code:
The above descriptions were based on need for index of values, and the code for each solution is:
Solution 1
private static void findSum(int[] a, int[] b, int x) {
Map<Integer, Integer> bIdx = new HashMap<>();
for (int j = 0; j < b.length; j++)
bIdx.put(b[j], j);
for (int i = 0; i < a.length; i++) {
Integer j = bIdx.get(x - a[i]);
if (j != null)
System.out.println("a[" + i + "] + b[" + j + "] = " + a[i] + " + " + b[j] + " = " + x);
}
}
Solution 2
private static void findSum(int[] a, int[] b, int x) {
for (int i = 0, j = b.length - 1, sum; i < a.length && j >= 0; i++) {
while (j >= 0 && (sum = a[i] + b[j]) >= x) {
if (sum == x)
System.out.println("a[" + i + "] + b[" + j + "] = " + a[i] + " + " + b[j] + " = " + x);
j--;
}
}
}
Test
int[] a = {1,2,3,4,5};
int[] b = {1,2,3,4,5,6};
findSum(a, b, 4);
Output (same from both)
a[0] + b[2] = 1 + 3 = 4
a[1] + b[1] = 2 + 2 = 4
a[2] + b[0] = 3 + 1 = 4
Solution 1 using Set
If you don't need index position, then a Set is better for solution 1:
private static void findSum(int[] aArr, int[] bArr, int x) {
Set<Integer> bSet = new HashSet<>();
for (int b : bArr)
bSet.add(b);
for (int a : aArr)
if (bSet.contains(x - a))
System.out.println(a + " + " + (x - a) + " = " + x);
}
Output
1 + 3 = 4
2 + 2 = 4
3 + 1 = 4
Here is an example of how you can measure your time, i've included another method to find the numbers you mentioned. See the difference in runtime:
int[] A = {1,2,3,4,5};
int[] B = {1,2,3,4,5,6};
int x = 4;
int i = 0;
int j = 0;
long t1 = System.nanoTime();
for(int n = 0; n < (A.length*B.length); n++) {
if(i >= A.length)
i = 0;
if(n % B.length == 0)
j++;
if(A[i] + B[j] == x) {
System.out.println(A[i] + " + " + B[j] + " = " + x);
break;
}
i++;
}
long t2 = System.nanoTime();
System.out.println("Time 1: "+(t2-t1));
//Here's the other method
long t3 = System.nanoTime();
for (int n = 0;n<B.length;n++){
for (int m =0;m<A.length;m++){
if(A[m]+B[n]==x){
System.out.println(A[m] +" + "+B[n] +" = "+ x);
}
}
}
long t4 = System.nanoTime();
System.out.println("Time 2: "+(t4-t3));
Here is the code, for Andreas's Solution 1, that I came up with:
int[] A = {2,3,4};
int[] B = {7,9};
Map<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
int x = 10;
int b;
for(int i = 0; i < B.length; i++) {
hashMap.put(B[i], i);
}
for (int n = 0; n < A.length; n++){
b = x - A[n];
if(hashMap.get(b) != null)
System.out.println(A[n] + " + " + b + " = " + x);
}

Calculate the number of pyramid

I'm trying to calculate the sum of the numbers in my pyramid in java. For this, mathematical rule is 2+5+8+9. I mean first row+first number of second row+ second number of third row like that.
int[] numbers = { 2,5,7,1,8,3,6,0,9,4 };
System.out.println(" " + numbers[0]);
System.out.println(" " + numbers[1] + " " + numbers[2]);
System.out.println(" " + numbers[3] + " " + numbers[4] + " " + numbers[5]);
System.out.println("" + numbers[6] + " " + numbers[7] + " " + numbers[8] + " " + numbers[9]);
For example:
2
5 7
1 8 3
6 0 9 4
How can I calculate 2+5+8+9 in Java?
The simplest way of calculating 2+5+8+9 is using Java build-in feature:
int result = 2+5+8+9;
You should construct your pyramid as a 2D array.
int[] numbers = { 2,5,7,1,8,3,6,0,9,4 };
int addedElements = 0;
int nextSize = 1;
ArrayList<int[]> pyramid = new ArrayList<>();
while(addedElements< numbers.size()) {
int[] level = new int[nextSize++];
for (int i = 0; i < nextSize - 1; i++) {
level[i] = numbers[addedElements++];
}
}
int result = 0;
//add maximum of each `int[]` in pyramid.
for (int[] array : pyramid) {
int currentMax = array[0];
for (int i = 0; i < array.size(); i++) {
if (array[i] > currentMax) {
currentMax = array[i];
}
result+=currentMax;
}
System.out.println(result);
Try the follwoing code :
int[] numbers = { 2,5,7,1,8,3,6,0,9,4 };
int index = 1;
int number = 2;
int result = numbers[0];
while (index < numbers.length) {
result += numbers[index + number -2];
index += number;
number += 1;
}
System.out.println(result);
But the whole whing would be much easier and clearer if you just put your pyramide into a 2 dimensional array.
int[][] numbers = { {2},
{5,7},
{1,8,3},
{6,0,9,4} };
int result = numbers[0][0];
for (int i = 1; i < numbers.length; i++) {
result += numbers[i][i-1];
}
System.out.println(result);

Python code works 20 times slower than Java. Is there a way to speed up Python?

I wrote a program in Python and in Java to search for the smallest integer solution of the equation:
a^5+b^5+c^5+d^5=e^5 (expected output is 133^5+110^5+84^5+27^5=144^5)
Powers and roots are either computed directly ("direct calculation" method) or computed and stored in an array ("power lookup" method). Fifth powers are looked up like n5 = fifth_power[n]. Fifth power root is computed using a binary search in array 'fifth_power`.
I am running it on NetBeans if it matters. It takes:
30. s (Python, direct)
20. s (Python, lookup)
5.6 s (Java, direct)
0.8 s (Java, lookup)
Is there a way to boost Python performance? I am not looking for better math (sieving of some kind). I am looking for better implementation of "for each combination of a,b,c,d compute some of their powers, check if the sum is a perfect power. If it is - print the result".
Is it expected that Python runs some 20 times slower than Java?
Python 3.5
http://pastebin.com/qVthWGKm
from array import *
import math
import time
#PYTHON, BRUTEFORCE : ~30 s
millis1 = int(round(time.time() * 1000))
keep_searching = True
a=1
result=""
while(keep_searching):
a+=1
for b in range(1,a+1):
for c in range(1,b+1):
for d in range(1,c+1):
sum=math.pow(a,5)+math.pow(b,5)+math.pow(c,5)+math.pow(d,5)
root = math.pow(sum,0.2)
e = round(root)
e5 = math.pow(e,5)
if(e5==sum):
result="{}^5 + {}^5 + {}^5 + {}^5 = {}^5".format(int(a),int(b), int(c),int(d), int(e))
keep_searching = False
millis2 = int(round(time.time() * 1000))
print(result)
print("Found solution in {} ms".format(millis2-millis1))
#PYTHON, PRECOMPUTE POWERS: ~20 s
millis3 = int(round(time.time() * 1000))
#fifth_power #175 is enough
size=176
fifth_power = [None] * size
for i in range(size):
fifth_power[i]=long(math.pow(i,5))
millis4 = int(round(time.time() * 1000))
#returns value if it is a perfect power (32 returns 2)
#returns -1 if between perfect powers, -2 if greater than max value in array, -3 if smaller than min value in array
def check_perfect_power(number, min, max, fifth_power):
current=int((min+max)/2)
while(max>=min):
if(number==fifth_power[current]):
return current
elif(number>fifth_power[current]):
min=current+1
current=int((max+min)/2)
else:
max=current-1
current=int((max+min)/2)
if(min>=len(fifth_power)):
return -2
if(max<0):
return -3
return -1
keep_searching = True
a=0
result=""
while(keep_searching):
a+=1
for b in range(1,a+1):
for c in range(1,b+1):
for d in range(1,c+1):
mymax=min(int(a*1.32)+1, size-1)
e=check_perfect_power(fifth_power[a]+fifth_power[b]+fifth_power[c]+fifth_power[d], a, mymax, fifth_power)
if(e>0):
result="{}^5 + {}^5 + {}^5 + {}^5 = {}^5".format(int(a),int(b), int(c),int(d), int(e))
keep_searching = False
millis5 = int(round(time.time() * 1000))
print(result)
print("Populated in {} ms, find solution in {} ms".format(millis4-millis3,millis5-millis4))
Java 8:
http://pastebin.com/G4V3fHnD
import java.util.ArrayList;
public class Eu514 {
public static void main(String[] args) {
bruteforce(); //Solution found by bruteforce in 5600 ms.
prepopulate(); //Solution found by prepopulation in 761 ms.
}
public static void bruteforce(){ //JAVA BRUTEFORCE
Long t2 = 0L;
Long t1 = System.currentTimeMillis();
boolean keepSearching = true;
int a = 0;
long e = 0;
String solution = "";
while (keepSearching) {
a++;
for (int b = 1; b <= a; b++) {
for (int c = 1; c <= b; c++) {
for (int d = 1; d <= c; d++) {
long sum = (long) (Math.pow(a, 5) + Math.pow(b, 5) + Math.pow(c, 5) + Math.pow(d, 5)); //sum=a^5+b^5+c^5+d^5
e = Math.round(Math.pow(sum, 0.2)); //e= sum^(1/5), rounded
long e5 = (long) Math.pow(e,5); //e^5
if(e5==sum){
t2 = System.currentTimeMillis();
solution = a + "^5 + " + b + "^5 + " + c + "^5 + " + d + "^5 = " + e + "^5";
keepSearching = false;
}
}
}
}
}
long delta = ((t2-t1));
System.out.println(solution+"\nSolution found by bruteforce in "+delta+" ms.");
}
public static void prepopulate(){ //JAVA PREPOPULATE
Long t2 = 0L;
Long t1 = System.currentTimeMillis();
int size = 176;
long[] powers = populatePowers(size);
boolean keepSearching = true;
int a = 0;
int e = 0;
String solution = "";
while (keepSearching) {
a++;
for (int b = 1; b <= a; b++) {
for (int c = 1; c <= b; c++) {
for (int d = 1; d <= c; d++) {
long sum = powers[a] + powers[b] + powers[c] + powers[d];
int max = (int) Math.min(size - 1, (a * 1.32 + 1));
e = checkIfPerfectPower(sum, a, max, powers);
if (e > 0) {
t2 = System.currentTimeMillis();
solution = a + "^5 + " + b + "^5 + " + c + "^5 + " + d + "^5 = " + e + "^5";
keepSearching = false;
}
}
}
}
}
long delta = ((t2-t1));
System.out.println(solution+"\nSolution found by prepopulation in "+delta+" ms.");
}
public static long[] populatePowers(int max){
long[] powers = new long[max];
for (int i = 0; i < powers.length; i++) {
powers[i]=(long) Math.pow(i,5);
}
return powers;
}
public static int checkIfPerfectPower(long number, int min, int max, long[] arr){
int current =((min+max)/2);
while(max>=min){
if(number==arr[current]){
return current;
}else if(number>arr[current]){
min = current + 1;
current = (max + min) / 2;
}else{
max=current-1;
current=(max+min)/2;
}
}
if(min>=arr.length) return -2;
if(max<0) return -3;
return -1;
}
}
from array import *
import time
import numpy as np
#PYTHON, BRUTEFORCE : ~30 s
millis1 = int(round(time.time() * 1000))
keep_searching = True
a = 1
result = ""
while(keep_searching):
a += 1
a_pow = a ** 5
for b in xrange(1, a+1):
b_pow = b ** 5
for c in xrange(1, b+1):
c_pow = c ** 5
for d in xrange(1, c+1):
d_pow = d ** 5
sum_pow = a_pow + b_pow + c_pow + d_pow
root = sum_pow ** 0.2
e = round(root)
e5 = e ** 5
if(e5 == sum_pow):
result="{}^5 + {}^5 + {}^5 + {}^5 = {}^5".format(a, b, c, d, e)
keep_searching = False
millis2 = int(round(time.time() * 1000))
print(result)
print("Found solution in {} ms".format(millis2-millis1))
Python 2.7, with some code optimizations
133^5 + 110^5 + 84^5 + 27^5 = 144.0^5
Found solution in 8333 ms
It could be a little different from CPU to CPU.
What about improving the java code?
int size = 200;
long[] pow5 = new long[size];
for (int i = 1; i < size; ++i)
{
long sqr = i * i;
pow5[i] = sqr * sqr * i;
}
for (int a = 1; a < size; ++a)
{
for (int b = 1; b <= a; ++b)
{
for (int c = 1; c <= b; ++c)
{
int e = a + 1;
for (int d = 1; d <= c; ++d)
{
long sum = pow5[a] + pow5[b] + pow5[c] + pow5[d];
while(pow5[e] < sum){ e++; }
if (pow5[e] == sum)
{
System.out.println(a + "^5 + " + b + "^5 + " + c + "^5 + " + d + "^5 = " + e + "^5");
return;
}
}
}
}
}

Implementing Strassen's Algorithm

I would like to multiply matrices very fast on a single core. I have looked around of the web and came across a few algorithms and found out Strassen's algorithm is the only one, that is actually implemented by people. I have looked on a few examples and came to the solution below. I made a simple benchmark which generates two randomly filled 500x500 matrices. Strassen's algorithm took 18 seconds, where the high school algorithm was done in 0.4 seconds. Other people where very promising after implementing the algorithm, so what is wrong with mine, how can I make it quicker?
// return C = A * B
private Matrix strassenTimes(Matrix B, int LEAFSIZE) {
Matrix A = this;
if (B.M != A.M || B.N != A.N) throw new RuntimeException("Illegal matrix dimensions.");
if (N <= LEAFSIZE || M <= LEAFSIZE) {
return A.times(B);
}
// make new sub-matrices
int newAcols = (A.N + 1) / 2;
int newArows = (A.M + 1) / 2;
Matrix a11 = new Matrix(newArows, newAcols);
Matrix a12 = new Matrix(newArows, newAcols);
Matrix a21 = new Matrix(newArows, newAcols);
Matrix a22 = new Matrix(newArows, newAcols);
int newBcols = (B.N + 1) / 2;
int newBrows = (B.M + 1) / 2;
Matrix b11 = new Matrix(newBrows, newBcols);
Matrix b12 = new Matrix(newBrows, newBcols);
Matrix b21 = new Matrix(newBrows, newBcols);
Matrix b22 = new Matrix(newBrows, newBcols);
for (int i = 1; i <= newArows; i++) {
for (int j = 1; j <= newAcols; j++) {
a11.setElement(i, j, A.saveGet(i, j)); // top left
a12.setElement(i, j, A.saveGet(i, j + newAcols)); // top right
a21.setElement(i, j, A.saveGet(i + newArows, j)); // bottom left
a22.setElement(i, j, A.saveGet(i + newArows, j + newAcols)); // bottom right
}
}
for (int i = 1; i <= newBrows; i++) {
for (int j = 1; j <= newBcols; j++) {
b11.setElement(i, j, B.saveGet(i, j)); // top left
b12.setElement(i, j, B.saveGet(i, j + newBcols)); // top right
b21.setElement(i, j, B.saveGet(i + newBrows, j)); // bottom left
b22.setElement(i, j, B.saveGet(i + newBrows, j + newBcols)); // bottom right
}
}
Matrix aResult;
Matrix bResult;
aResult = a11.add(a22);
bResult = b11.add(b22);
Matrix p1 = aResult.strassenTimes(bResult, LEAFSIZE);
aResult = a21.add(a22);
Matrix p2 = aResult.strassenTimes(b11, LEAFSIZE);
bResult = b12.minus(b22); // b12 - b22
Matrix p3 = a11.strassenTimes(bResult, LEAFSIZE);
bResult = b21.minus(b11); // b21 - b11
Matrix p4 = a22.strassenTimes(bResult, LEAFSIZE);
aResult = a11.add(a12); // a11 + a12
Matrix p5 = aResult.strassenTimes(b22, LEAFSIZE);
aResult = a21.minus(a11); // a21 - a11
bResult = b11.add(b12); // b11 + b12
Matrix p6 = aResult.strassenTimes(bResult, LEAFSIZE);
aResult = a12.minus(a22); // a12 - a22
bResult = b21.add(b22); // b21 + b22
Matrix p7 = aResult.strassenTimes(bResult, LEAFSIZE);
Matrix c12 = p3.add(p5); // c12 = p3 + p5
Matrix c21 = p2.add(p4); // c21 = p2 + p4
aResult = p1.add(p4); // p1 + p4
bResult = aResult.add(p7); // p1 + p4 + p7
Matrix c11 = bResult.minus(p5);
aResult = p1.add(p3); // p1 + p3
bResult = aResult.add(p6); // p1 + p3 + p6
Matrix c22 = bResult.minus(p2);
// Grouping the results obtained in a single matrix:
int rows = c11.nrRows();
int cols = c11.nrColumns();
Matrix C = new Matrix(A.M, B.N);
for (int i = 1; i <= A.M; i++) {
for (int j = 1; j <= B.N; j++) {
int el;
if (i <= rows) {
if (j <= cols) {
el = c11.get(i, j);
} else {
el = c12.get(i, j - cols);
}
} else {
if (j <= cols) {
el = c21.get(i - rows, j);
} else {
el = c22.get(i - rows, j - rows);
}
}
C.setElement(i, j, el);
}
}
return C;
}
The little benchmark has the following code:
int AM, AN, BM, BN;
AM = 500;
AN = BM = 500;
BN = 500;
Matrix a = new Matrix(AM, AN);
Matrix b = new Matrix(BM, BN);
Random random = new Random();
for (int i = 1; i <= AM; i++) {
for (int j = 1; j <= AN; j++) {
a.setElement(i, j, random.nextInt(20));
}
}
for (int i = 1; i <= BM; i++) {
for (int j = 1; j <= BN; j++) {
b.setElement(i, j, random.nextInt(20));
}
}
System.out.println("strassen: A x B");
long tijd = System.currentTimeMillis();
Matrix c = a.strassenTimes(b);
System.out.println("time = " + (System.currentTimeMillis() - tijd));
System.out.println("normal: A x B");
tijd = System.currentTimeMillis();
Matrix d = a.times(b);
System.out.println("time = " + (System.currentTimeMillis() - tijd));
System.out.println("nr of different elements = " + c.compare(d));
With the following results:
strassen: A x B
time = 18372
normal: A x B
time = 308
nr of different elements = 0
I know it's a low of code, but I would be very happy if you guys help me out ;)
EDIT 1:
For the sake of completeness I add some methods that is used by the above code.
public int get(int r, int c) {
if (c > nrColumns() || r > nrRows() || c <= 0 || r <= 0) {
throw new ArrayIndexOutOfBoundsException("matrix is of size (" +
nrRows() + ", " + nrColumns() + "), but tries to set element(" + r + ", " + c + ")");
}
return content[r - 1][c - 1];
}
private int saveGet(int r, int c) {
if (c > nrColumns() || r > nrRows() || c <= 0 || r <= 0) {
return 0;
}
return content[r - 1][c - 1];
}
public void setElement(int r, int c, int n) {
if (c > nrColumns() || r > nrRows() || c <= 0 || r <= 0) {
throw new ArrayIndexOutOfBoundsException("matrix is of size (" +
nrRows() + ", " + nrColumns() + "), but tries to set element(" + r + ", " + c + ")");
}
content[r - 1][c - 1] = n;
}
// return C = A + B
public Matrix add(Matrix B) {
Matrix A = this;
if (B.M != A.M || B.N != A.N) throw new RuntimeException("Illegal matrix dimensions.");
Matrix C = new Matrix(M, N);
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
C.content[i][j] = A.content[i][j] + B.content[i][j];
}
}
return C;
}
I should have choosen another leaf size for Strassen´s algorithm. Therefore I did a little experiment. It seems that leaf size 256 works best with the code included in the question. Below a plot with different leaf sizes with each time a random matrix of size 1025 x 1025.
I have compared Strassen´s algorithm with leaf size 256 with the trivial algorithm for matrix multiplication, to see if it´s actually an improvement. It turned out to be an improvement, see below the results on random matrices of different sizes (in steps of 10 and repeated 50 times for each size).
Below the code for the trivial algorithm for matrix multiplication:
// return C = A * B
public Matrix times(Matrix B) {
Matrix A = this;
if (A.N != B.M) throw new RuntimeException("Illegal matrix dimensions.");
Matrix C = new Matrix(A.M, B.N);
for (int i = 0; i < C.M; i++) {
for (int j = 0; j < C.N; j++) {
for (int k = 0; k < A.N; k++) {
C.content[i][j] += (A.content[i][k] * B.content[k][j]);
}
}
}
return C;
}
It still think there can be done other improvements on the implementation, but it turned out that the leaf size is a very important factor. All experiments are done with a machine running on Ubuntu 14.04 with the following specifications:
CPU: Intel(R) Core(TM) i7-2600K CPU # 3.40GHz
Memory: 2 x 4GB DDR3 1333 MHz

Nested For Loop and specific array element searching

I have a question on the method and process of how to look at these generated arrays.
Basically I want to create an array of [a,b,c,(a+b+c)] and as well as a second array of [d,e,f,(d+e+f)] and if the third element in array1 and array2 are the same, display the arrays to strings.
int num = 10;
for(int a = 0; a < num; a++){
for(int b = 0; b < num; b++){
for(int c = 0; c < num; c++){
if(a<=b && b<=c){
arrayOne[0] = a;
arrayOne[1] = b;
arrayOne[2] = c;
arrayOne[3] = (a+b+c);
}
}
}
}
for(int d = 0; d < num; e++){
for(int e = 0; e < num; e++){
for(int f = 0; f < num; f++){
if(d<=e && e<=f){
arrayTwo[0] = d;
arrayTwo[1] = e;
arrayTwo[2] = f;
arrayTwo[3] = (f -(d+e));
}
}
}
}
as you can see I am beyond stump.I am not quite sure where i can get each iteration of the arrays and compare the values by matching the sums in each array and as well as displaying the respective array they are in. Thank you all in advanced.
If I understand your question correctly if a=1, b=3, c=4 and d=2, e=3, f=3 you'd like to print something along the lines of 1 + 3 + 4 = 8 = 2 + 3 + 3. First, what you're doing right now is creating two arrays like Floris described in the comment. What you want to do is store all the values in one array of arrays, as follows:
int max; \\ To determine the value of max see the edit below.
int array[][] = new int[max][num];
int index = 0;
for (int a=0; a < num; a++) {
for (int b=a; b < num; b++) {
for (int c=b; c < num; c++) {
array[index][0] = a;
array[index][1] = b;
array[index][2] = c;
array[index][3] = a + b + c;
index++;
}
}
}
for (int i = 0; i < max; i++) {
for (int j = i; j < max; j++) {
if (array[i][3] == array[j][3]) {
string outString = array[i][0] + " + " + array[i][1] + " + " + array[i][2] + " = " + array[i][3] + " = " + array[j][0] + " + " + array[j][1] + " + " + array[i][2];
System.out.println(outString);
}
}
}
You can see that I improved performance by starting b from a and c from b since you are throw out all the values where b < a or c < b. This also should eliminate the need for your if statement (I say should only because I haven't tested this). I needed to use an independent index due to the complexities of the triple nested loop.
Edit 2: Ignore me. I did the combinatorics wrong. Let An,k be the number of unordered sets of length k having elements in [n] (this will achieve what you desire). Then An,k = An-1,k + An,k-1. We know that An,1 = n (since the values are 0, 1, 2, 3, 4, ..., n), and A1,n = 1 (since the only value can be 11111...1 n times). In this case we are interested in n= num and k = 3 , so plugging in the values we get
A_num,3 = A_num-1,3 + A_num,2
Apply the equation recursively until you come to an answer. For example, if num is 5:
A_5,3 = A_4,3 + A_5,2
= A_3,3 + A_4,2 + A_4,2 + A_5,1
= A_3,3 + 2(A_4,2) + 5
= A_2,3 + A_3,2 + 2(A_3,2) + 2(A_4,1) + 5
= A_2,3 + 3(A_3,2) + 2(4) + 5
= A_1,3 + A_2,2 + 3(A_2,2) + 3(A_3,1) + 2(4) + 5
= 1 + 4(A_2,2) + 3(3) + 2(4) + 5
= 1 + 4(A_1,2) + 4(A_2,1) + 3(3) + 2(4) + 5
= 1 + 4(1) + 4(2) + 3(3) + 2(4) + 5
= 5(1) + 4(2) + 3(3) + 2(4) + 5
It looks like this may simplify to (num + (num - 1)(2) + (num - 2)(3) + ... + (2)(num - 1) + num) which is binomial(num, num) but I haven't done the work to say for sure.
int givenNumber = 10;
int []arrayOne = new int [4];
int []arrayTwo = new int [4];
int count = 0;
for ( int i = 0; i < givenNumber; i ++)
{
for ( int x = 0; x < givenNumber; x ++ )
{
for ( int a = 0; a < givenNumber; a++ ){
arrayOne[0] = (int)(a * java.lang.Math.random() + x);
arrayOne[1] = (int)(a * java.lang.Math.random() + x);
arrayOne[2] = (int)(a * java.lang.Math.random() + x);
arrayOne[3] = (int)(arrayOne[0]+arrayOne[1]+arrayOne[2]);
}
for ( int b = 0; b < givenNumber; b++ ){
arrayTwo[0] = (int)(b * java.lang.Math.random() + x);
arrayTwo[1] = (int)(b * java.lang.Math.random() + x);
arrayTwo[2] = (int)(b * java.lang.Math.random() + x);
arrayTwo[3] = (int)(arrayTwo[0]+arrayTwo[1]+arrayTwo[2]);
}
if (arrayOne[3] == arrayTwo[3])
{
for ( int a = 0; a < 2; a++ )
{
System.out.print(arrayOne[a] + " + ");
} System.out.print(arrayOne[2] + " = " + arrayOne[3] + " = ");
for ( int a = 0; a < 2; a++ )
{
System.out.print(arrayTwo[a] + " + ");
} System.out.print(arrayTwo[2]);
System.out.println("\n");
count += 1;
}
}
}
if (count == 0)
System.out.println(
"\nOops! you dont have a match...\n" +
"Please try running the program again.\n");

Categories