// 3 column Array class for arrays of x, y integer variables and group number import java.applet.Applet; import java.math.BigInteger; import java.awt.TextArea; public class xyArray { private int array[][]; //array [][3] with n, p, group private int length = 0; private int row; //Total amount of rows in array //(allocated and unallocated) private int isRow; //variable in case an element has already be selected public boolean reMove = false; private BigInteger primes[]; private int p[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}; private static BigInteger ZERO = new BigInteger("0"); private static BigInteger ONE = new BigInteger("1"); private static BigInteger NEGONE = new BigInteger("-1"); //private int minW, minH, maxW; //minW is the distance to the left edge of the //triangle from the point in the array closest //to that edge //maxW is the distance to the right edge of the //triangle from the point in the array closest //to that edge //similarly minH public xyArray(int r) { row = r; primes = new BigInteger[p.length]; for(int i = 0; i < p.length; i++) { BigInteger temp = new BigInteger(Integer.toString(p[i])); primes[i] = temp; } if(row > 0) array = new int[row][3]; else if(row <= 0) System.out.println("Invalid array initialization value: " + row); } public void addElement(int n, int p, int group) { if(isElement(n, p) == 0) { //if((minW > (n - p)) || (length == 0)) if(length < row) { array[length][0] = n; array[length][1] = p; array[length][2] = group; } length++; if(length >= row - 2) addLength(); } else if(group == array[isRow][2]) { removeElement(); reMove = true; } else array[isRow][2] = group; } private void addLength() { int temp[][]; row += 20; temp = new int[row][3]; for(int i = 0; i == length; i++) { temp[i][0] = array[i][0]; temp[i][1] = array[i][1]; temp[i][2] = array[i][2]; } array = new int[row][3]; for(int i = 0; i == length; i++) { array[i][0] = temp[i][0]; array[i][1] = temp[i][1]; array[i][2] = temp[i][2]; } } private int isElement(int n, int p) { for(int i = 0; i < length; i++) { if(array[i][0] == n) { if(array[i][1] == p) { isRow = i; return array[i][2]; } } } return 0; } private void removeElement() { for(int i = isRow; i < length; i++) { array[i][0] = array[i+1][0]; array[i][1] = array[i+1][1]; array[i][2] = array[i+1][2]; } length--; } void calcLcmGcd(int group, BigInteger gcdlcm[]) { int primeFact[], lcm[], gcd[]; boolean first = true; lcm = new int[primes.length]; gcd = new int[primes.length]; primeFact = new int[primes.length]; for(int i = 0; i < length; i++) { if(array[i][2] == group) { if(factor(primeFact, array[i][0], array[i][1]) == 1) { if(first) { for(int j = 0; j < primes.length; j++) { lcm[j] = primeFact[j]; gcd[j] = primeFact[j]; } first = false; } compare(primeFact, lcm, 1); compare(primeFact, gcd, -1); } else { gcdlcm[0] = NEGONE; break; } } } BigInteger div = ONE; BigInteger mult = ONE; for(int i = 0; i < primes.length; i++) { mult = mult.multiply(primes[i].pow(lcm[i])); div = div.multiply(primes[i].pow(gcd[i])); } gcdlcm[0] = div; gcdlcm[1] = mult; } private int factor(int fact[], int n, int p) { int count = 0; BigInteger numb = ONE, temp; for(int i = 0; i < p; i++) { BigInteger t = new BigInteger(Integer.toString(n - i)); numb = numb.multiply(t); } for(int i = 0; i < p; i++) { BigInteger t = new BigInteger(Integer.toString(p - i)); numb = numb.divide(t); } temp = numb; for(int i = 0; i < primes.length; i++) { while(temp.remainder(primes[i]).compareTo(ZERO) == 0 && (temp.compareTo(ZERO) == 1)) { temp = temp.divide(primes[i]); count++; } fact[i] = count; count = 0; } //check to make sure all factors are correctly accounted for temp = ONE; for(int i = 0; i < primes.length; i++) temp = temp.multiply(primes[i].pow(fact[i])); if(temp.compareTo(numb) == 0) return 1; else return -1; } public void compare(int factor[], int comp[], int dir) //dir indicates whether to calculate gcd(dir < 0) or lcm(dir > 0) { if(dir > 0) { for(int i = 0; i < primes.length; i++) comp[i] = Math.max(comp[i], factor[i]); } if(dir < 0) { for(int i = 0; i < primes.length; i++) comp[i] = Math.min(comp[i], factor[i]); } } public int getN(int el) { return array[el][0]; } public int getP(int el) { return array[el][1]; } public int getG(int el) { return array[el][2]; } public void clear() { length = 0; } public int getSize() //Returns size of array { return length; } public int move(int direction) { int proceed = 1; if(length > 0) { //check for move left if(direction == 1) { for(int i = 0; i < length; i++) { if(array[i][1] <= 0) { proceed = 0; break; } } if(proceed == 1) { for(int k = 0; k < length; k++) array[k][1]--; return 1; } else return 0; } //check for move right if(direction == 2) { for(int i = 0; i < length; i++) { if(array[i][0] - array[i][1] <= 0) { proceed = 0; break; } } if(proceed == 1) { for(int k = 0; k < length; k++) array[k][1]++; return 1; } else return 0; } //check for move up if(direction == 3) { for(int i = 0; i < length; i++) { if(array[i][1] == array[i][0]) { proceed = 0; break; } } if(proceed == 1) { for(int k = 0; k < length; k++) array[k][0]--; return 1; } else return 0; } //for move down (no check necessary if(direction == 4) { for(int k = 0; k < length; k++) array[k][0]++; return 1; } else return 0; } else return 0; } private void bulkMove(int curRow[], int minW[], int maxW[], int minH[]) { int numbRows = curRow[0] - minH[0]; for(int i = 0; i < length; i++) { array[i][0] += numbRows; array[i][1] -= minW[0]; } minH[0] += numbRows; maxW[0] += minW[0] + numbRows; minW[0] = 0; } private void moveNextRow(int maxW[], int minW[]) { for(int i = 0; i < length; i++) { array[i][0]++; array[i][1] -= minW[0]; } maxW[0] = minW[0] + 1; minW[0] = 0; } public void report(int begRow, int endRow, TextArea txtReport, String colDel, boolean delim) { int minW[] = new int[1], minH[] = new int[1]; int maxW[] = new int[1]; int curRow[] = {begRow}; boolean group[] = {false, false, false, false, false}; if(length <= 0 ) { txtReport.setText("No elements selected on triangle"); return; } group[array[0][2] - 1] = true; minW[0] = array[0][1]; //minW, maxW, and minH are the maxW[0] = array[0][0] - array[0][1];//smallest distances from the minH[0] = array[0][0]; //pattern to the left, right, and //top edges of the triangle respectively int tempN, tempP; for(int i = 1; i < length; i++) { tempN = array[i][0]; tempP = array[i][1]; group[array[i][2] - 1] = true; if(tempP < minW[0]) minW[0] = tempP; if(tempN - tempP < maxW[0]) maxW[0] = tempN - tempP; if(tempN < minH[0]) minH[0] = tempN; } txtReport.setText(""); while((minW[0] + maxW[0] < (minH[0] - curRow[0])) && (curRow[0] <= endRow)) { txtReport.append("Pattern doesn't fit as high as row " + curRow[0] + "\n"); curRow[0]++; } if(curRow[0] > endRow) return; bulkMove(curRow, minW, maxW, minH); BigInteger tmpGcdLcm[] = new BigInteger[2]; txtReport.append("\n"); if(delim) { txtReport.append("row" + colDel + "column"); for(int k = 0; k < 5; k++) { if(group[k]) { txtReport.append(colDel + "Group " + (k+1) + " LCM" + colDel + "Group " + k + " GCD"); } } txtReport.append("\n"); } while(curRow[0] <= endRow) { while(maxW[0] >= 0) { if(delim) txtReport.append(minH[0] + colDel + minW[0]); else txtReport.append("row: " + minH[0]); for(int k = 0; k < 5; k++) { if(group[k]) { calcLcmGcd(k + 1, tmpGcdLcm); if(delim) txtReport.append(colDel + tmpGcdLcm[1] + colDel + tmpGcdLcm[0]); else txtReport.append(" Group " + (k+1) +" LCM: " + tmpGcdLcm[1] + " GCD: " + tmpGcdLcm[0]); } } move(2); txtReport.append("\n"); if(maxW[0] == 0) break; maxW[0]--; minW[0]++; } if(curRow[0] == endRow) break; if(!delim) txtReport.append("\n"); moveNextRow(maxW, minW); curRow[0]++; minH[0] = curRow[0]; } } }