diff options
Diffstat (limited to 'projects/project3_kenken/stab2/Solver.java')
| -rw-r--r-- | projects/project3_kenken/stab2/Solver.java | 865 |
1 files changed, 865 insertions, 0 deletions
diff --git a/projects/project3_kenken/stab2/Solver.java b/projects/project3_kenken/stab2/Solver.java new file mode 100644 index 0000000..18a864b --- /dev/null +++ b/projects/project3_kenken/stab2/Solver.java @@ -0,0 +1,865 @@ +import java.util.Scanner; +import java.io.*; + +public class Solver +{ + public int[][] puzzle; + public Constraint[] constraints; + public int size; + public Solver(String filename) + { + parsePuzzle(filename); + /*puzzle = new int[3][3]; + constraints = new Constraint[5]; + + Position[] p1 = new Position[1]; + p1[0] = new Position(0,0); + constraints[0] = new Constraint(3," ",p1); + + Position[] p2 = new Position[2]; + p2[0] = new Position(1,0); + p2[1] = new Position(1,1); + constraints[1] = new Constraint(6,"*",p2); + + Position[] p3 = new Position[2]; + p3[0] = new Position(2,0); + p3[1] = new Position(2,1); + constraints[2] = new Constraint(2,"/",p3); + + Position[] p4 = new Position[2]; + p4[0] = new Position(0,1); + p4[1] = new Position(0,2); + constraints[3] = new Constraint(2,"/",p4); + + Position[] p5 = new Position[2]; + p5[0] = new Position(1,2); + p5[1] = new Position(2,2); + constraints[4] = new Constraint(2,"-",p5); + + size = puzzle.length; + */ + System.out.println("Everything parsed, data is:"); + System.out.println("Puzzle:"); + printArray(puzzle); + System.out.println("Constraints:"); + printArray(constraints); + System.out.println("size: " + size); + } + private void parsePuzzle(String filename) + { + Scanner s = null; + try + { + s = new Scanner(new FileInputStream(filename)); + } + catch (Exception e) + { + System.out.println("Something went terribly wrong!\n" + e); + } + size = Integer.parseInt(s.nextLine().replaceAll("\n","")); + + puzzle = new int[size][size]; + + constraints = new Constraint[Integer.parseInt(s.nextLine().replaceAll("\n",""))]; + + //System.out.println("Puzzle size: " + size + " Cages: " + p.length); + for(int i = 0; s.hasNextLine();i++) + { + String t1 = s.nextLine(); + System.out.println("Praseing: " + t1); + String[] t2 = t1.split(","); + System.out.println("Parts length: " + t2.length); + if(t2.length > 1) + { + Position[] allcells = new Position[Integer.parseInt(t2[2])]; + for(int j = 0; j < Integer.parseInt(t2[2]);j++) + { + String[] coords = s.nextLine().split(","); + allcells[j] = new Position(Integer.parseInt(coords[1]),Integer.parseInt(coords[0])); + } + constraints[i] = new Constraint(Integer.parseInt(t2[0]),t2[1],allcells); + System.out.println("Created new constraint(" + Integer.parseInt(t2[0]) + "," + t2[1] + ","); + printArray(allcells); + /* + for(Position c : allcells) + { + constraints[i] = new Constraint(Integer.parseInt(t2[0]),t2[1],allcells); + } + */ + //p[i] = new KCage(Integer.parseInt(t2[0]),getOp(t2[1]),allcells); + //System.out.println("Created " + p[i]); + } + } + } + public void put(int x, int y, int num) + { + puzzle[x][y] = num; + } + public int remove(int x, int y) + { + int num = puzzle[x][y]; + puzzle[x][y] = 0; + return num; + } + public boolean[] getPossibilities(int x, int y) + { + boolean[] row = getPossibilitiesByRow(y); + boolean[] col = getPossibilitiesByCol(x); + boolean[] cage = getPossibilitiesByCage(x,y); + boolean[] output = new boolean[size]; + System.out.println("By row:"); + printArray(row); + System.out.println("By col:"); + printArray(col); + System.out.println("By cage:"); + printArray(cage); + for(int i = 0; i < size; i++) + { + if(row[i] && col[i] && cage[i]) + { + output[i] = true; + } + } + System.out.println("Possibilities for (" + x + "," + y + ") are "); + printArray(output); + return output; + } + public boolean[] getPossibilitiesByRow(int row) + { + boolean[] possibs = new boolean[size]; + for(int j = 0; j < size; j++) + {//Set all places is possibs to true + possibs[j] = true; + } + //Find all the possibilities + for(int j = 0; j < size; j++) + { //For every other place + if(puzzle[j][row] != 0) + { + //System.out.println("Setting (" + j + "," + row + "): " + puzzle[j][row] + " to false"); + possibs[puzzle[j][row]-1] = false; + } + } + return possibs; + } + public boolean[] getPossibilitiesByCol(int col) + { + boolean[] possibs = new boolean[size]; + for(int j = 0; j < size; j++) + {//Set all places is possibs to true + possibs[j] = true; + } + //Find all the possibilities + for(int j = 0; j < size; j++) + { //For every other place + if(puzzle[col][j] != 0) + { + //System.out.println("Setting (" + col + "," + j + "): " + puzzle[col][j] + " to false"); + possibs[puzzle[col][j]-1] = false; + } + } + return possibs; + } + public boolean[] getPossibilitiesByCage(int x, int y) + { + //System.out.println("Finding cage possibilities on (" + x + "," + y + ")"); + for(Constraint c : constraints) + { + //System.out.println("Testing a constraint: " + c.op); + for(Position p : c.positions) + { + //System.out.println("Found a position in this constraint: (" + p.x + "," + p.y + ")"); + if(p.x == x && p.y == y) + { + System.out.println("Found cell being talked about."); + //We found the cage that's being talked about + if(c.op.equals("+")) + { + System.out.println("Found op: +"); + return getPossibilitiesByCageAdd(c); + } + else if(c.op.equals("-")) + { + System.out.println("Found op: -"); + return getPossibilitiesByCageSub(c); + } + else if(c.op.equals("*")) + { + System.out.println("Found op: *"); + return getPossibilitiesByCageMul(c); + } + else if(c.op.equals("/")) + { + System.out.println("Found op: /"); + return getPossibilitiesByCageDiv(c); + } + else if(c.op.equals(" ")) + { + System.out.println("Found op: (NONE)"); + boolean[] output = new boolean[size]; + output[c.targNumber-1] = true; + //System.out.println("Returning:"); + //printArray(output); + return output; + } + else + { + System.out.println("Bad operator: (" + c.op + ")"); + return null; + } + } + } + } + System.out.println("Something has gone wrong in getPossibilitiesByCage"); + return null; + } + private boolean[] getPossibilitiesByCageAdd(Constraint c) + { + System.out.println("Getting possibilities for add cage"); + //Try the numbers 1 to size for every square + boolean[] output = new boolean[size]; + int targ = c.targNumber; + //If any of the numbers are already in, subtract them from targ + for(Position p : c.positions) + { + targ -= puzzle[p.x][p.y]; + } + //possibilities are targnumber - 1*# of positions to fill + int numcells = c.positions.length; + int max = targ - numcells; + int min = 1; + for(int i = min; i < max; i++) + { + output[i-1] = true; + } + return output; + } + private boolean[] getPossibilitiesByCageMul(Constraint c) + { + //Numbers can be from 1 to size for this one + //If the target number is odd, only an odd* an odd will work + int targ = c.targNumber; + System.out.println("Getting mul cage possibs:"); + System.out.println("Cage: (" + c.targNumber + "," + c.op); + printArray(c.positions); + //If any of the numbers are already in, divide the target by that. + for(Position p : c.positions) + { + if(puzzle[p.x][p.y] != 0) + { + System.out.println("Found a number, useing division shortcut"); + targ /= puzzle[p.x][p.y]; + } + } + boolean[] output = new boolean[size]; + if(c.targNumber % 2 == 1) + { + System.out.println("Found an odd number, useing odd numbers shortcut"); + for(int i = 1; i < size+1; i+= 2) + { + System.out.println("Setting " + i + " to true"); + output[i-1] = true; + } + System.out.println("Returning "); + printArray(output); + return output; + } + for(int i = 1; i < size+1; i++) + { + output[i-1] = true; + } + return output; + } + private boolean[] getPossibilitiesByCageSub(Constraint c) + { + //If one of the items is already in it, find what the other value must be + boolean[] output = new boolean[size]; + int x1 = c.positions[0].x; + int y1 = c.positions[0].y; + int x2 = c.positions[1].x; + int y2 = c.positions[1].y; + if(puzzle[x1][y1] != 0) + { + int onlypossib = 0; + if(c.targNumber > puzzle[x1][y1]) + { + onlypossib = c.targNumber-puzzle[x1][y1]; + } + else if(c.targNumber < puzzle[x1][y1]) + { + onlypossib = puzzle[x1][y1] - c.targNumber; + } + output[onlypossib-1] = true; + return output; + } + if(puzzle[x2][y2] != 0) + { + int onlypossib = 0; + if(c.targNumber>puzzle[x2][y2]) + { + onlypossib = c.targNumber-puzzle[x2][y2]; + } + else if(c.targNumber < puzzle[x2][y2]) + { + onlypossib = puzzle[x2][y2] - c.targNumber; + } + output[onlypossib-1] = true; + return output; + } + //Otherwise, values can be from 1 to targnumber - 2 + for(int i = 1; i < c.targNumber-2; i++) + { + output[i-1] = true; + } + return output; + } + private boolean[] getPossibilitiesByCageDiv(Constraint c) + { + //If one of the items is already in it, find what the other value must be + boolean[] output = new boolean[size]; + int x1 = c.positions[0].x; + int y1 = c.positions[0].y; + int x2 = c.positions[1].x; + int y2 = c.positions[1].y; + if(puzzle[x1][y1] != 0) + { + int onlypossib = c.targNumber/puzzle[x1][y1]; + output[onlypossib-1] = true; + return output; + } + if(puzzle[x2][y2] != 0) + { + int onlypossib = c.targNumber/puzzle[x2][y2]; + output[onlypossib-1] = true; + return output; + } + //Otherwise, values can be from 1 to targnumber + for(int i = 1; i < c.targNumber+1; i++) + { + output[i-1] = true; + } + return output; + } + public boolean isSolved() + { + boolean tr = testRows(); + boolean tc = testCols(); + boolean ta = testCages(); + System.out.println("Checking for solution(Rows: " + tr + ")(Cols: " + tc + ")(Cages: " + ta+"):"); + printArray(puzzle); + if(!testRows() || !testCols() || !testCages()) + { + return false; + } + return true; + } + private boolean testCages() + { + for(Constraint c : constraints) + { + if(!testConstraint(c)) + { + return false; + } + } + return true; + } + private boolean testConstraint(Constraint c) + { + if(c.op.equals("+")) + { + int sum = 0; + for(Position p : c.positions) + { + if(puzzle[p.x][p.y] != 0) + { + sum += puzzle[p.x][p.y]; + } + else + { + return false; + } + } + if(sum == c.targNumber) + { + return true; + } + else + { + System.out.println("Failed on constraint:("+c.targNumber+","+c.op+","); + printArray(c.positions); + return false; + } + } + else if(c.op.equals("-")) + { + Position p1 = c.positions[0]; + Position p2 = c.positions[1]; + if(puzzle[p1.x][p1.y] != 0 && puzzle[p2.x][p2.y] != 0) + { + int num1 = puzzle[p1.x][p1.y]; + int num2 = puzzle[p2.x][p2.y]; + if(num1 - num2 == c.targNumber) + { + return true; + } + if(num2 - num1 == c.targNumber) + { + return true; + } + } + else + { + System.out.println("Failed on constraint:("+c.targNumber+","+c.op+","); + printArray(c.positions); + return false; + } + return false; + } + else if(c.op.equals("*")) + { + int product = 1; + for(Position p : c.positions) + { + if(puzzle[p.x][p.y] != 0) + { + product *= puzzle[p.x][p.y]; + } + else + { + return false; + } + } + if(product == c.targNumber) + { + return true; + } + else + { + System.out.println("Failed on constraint:("+c.targNumber+","+c.op+","); + printArray(c.positions); + System.out.println("Product is " + product); + return false; + } + } + else if(c.op.equals("/")) + { + Position p1 = c.positions[0]; + Position p2 = c.positions[1]; + if(puzzle[p1.x][p1.y] != 0 && puzzle[p2.x][p2.y] != 0) + { + double num1 = puzzle[p1.x][p1.y]; + double num2 = puzzle[p2.x][p2.y]; + if(num1 / num2 == c.targNumber) + { + return true; + } + if(num2 / num1 == c.targNumber) + { + return true; + } + } + else + { + System.out.println("Failed on constraint:("+c.targNumber+","+c.op+","); + printArray(c.positions); + return false; + } + return false; + } + else if(c.op.equals(" ")) + { + int x = c.positions[0].x; + int y = c.positions[0].y; + if(puzzle[x][y] == c.targNumber) + { + return true; + } + else + { + return false; + } + } + System.out.println("Something went wrong in testConstraint"); + return false; + } + private boolean testCols() + { + for(int i = 0; i < size; i++) + { + boolean[] uniqueCols = new boolean[size]; + for(int j = 0; j < size; j++) + { + if(puzzle[i][j] == 0) + { + return false; + } + uniqueCols[puzzle[i][j]-1] = true; + } + for(int j = 0; j < uniqueCols.length; j++) + { + if(!uniqueCols[j]) + { + return false; + } + } + } + //System.out.println("Something went wrong in testCols!"); + return true; + } + private boolean testRows() + { + for(int i = 0; i < size; i++) + { + boolean[] uniqueRows = new boolean[size]; + for(int j = 0; j < size; j++) + { + if(puzzle[j][i] == 0) + { + return false; + } + uniqueRows[puzzle[j][i]-1] = true; + } + for(int j = 0; j < uniqueRows.length; j++) + { + if(!uniqueRows[j]) + { + return false; + } + } + } + //System.out.println("Something went wrong in testRows"); + return true; + } + public int[][] implyByRows() + { + //System.out.println("Implying by rows..."); + int[][][] output = new int[size][4][size]; + int numImplyed = 0; + for(int i = 0; i < size; i++) + { + //System.out.println("Calling imply row helper on row " + i); + output[i] = implyByRowsHelper(i); + if(output[i].length > 0) + { + numImplyed++; + } + } + int[][] realoutput = new int[numImplyed][4]; + int j = 0; + for(int i = 0; i < numImplyed;i++) + { + if(output[i].length > 0) + { + realoutput[j] = output[i][0]; + j++; + } + } + return realoutput; + } + public int[][] implyByCols() + { + //System.out.println("Implying by cols..."); + int[][][] output = new int[size][4][size]; + int numImplyed = 0; + for(int i = 0; i < size; i++) + { + //System.out.println("Calling imply col helper on col " + i); + output[i] = implyByColsHelper(i); + if(output[i].length > 0) + { + numImplyed++; + } + } + int[][] realoutput = new int[numImplyed][4]; + int j = 0; + for(int i = 0; i < numImplyed;i++) + { + if(output[i].length > 0) + { + realoutput[j] = output[i][0]; + j++; + } + } + return realoutput; + } + public int[][] implyByCages() + { + //System.out.println("Implying by cages"); + int[][][][] output = new int[size][size][4][size]; + int numImplyed = 0; + //We should only be implying ONE number max! + for(int x = 0; x < size; x++) + { + for(int y = 0; y < size; y++) + { + //Scan for a num that has only 1 possibility + output[x][y] = implyByCagesHelper(x,y); + //System.out.println("Attempted to imply by cages on (" + x + "," + y + "):"); + //printArray(output[x][y]); + if(output[x][y].length == 1) + { + //numImplyed++; + //System.out.println("Implything by cage. returning:"); + //printArray(output[x][y]); + return output[x][y]; + } + else + { + //System.out.println("Unable to imply"); + } + } + } + //System.out.println("Unable to imply ANYTHING"); + int[][] realoutput = new int[0][0]; + return realoutput; + /* + int[][] realoutput = new int[1][4]; + int track = 0; + if(output.length == 1) + { + realoutput[0] = output[x][y][0]; + return realoutput; + } + */ + } + public int[][] implyByCagesHelper(int x, int y) + { + int[][] realoutput = new int[size][4]; + //System.out.println("Implying on cage(" + x + "," + y + ")"); + int[][] output = new int[size][4]; + if(puzzle[x][y] != 0) + { + //This square already has a number in it. + } + else + { + boolean[] possibs = getPossibilitiesByCage(x,y); + //System.out.println("Got possibilities:"); + //printArray(possibs); + int j = 0; + int numtrue = 0; + for(boolean b : possibs) + { + if(b) + { + numtrue++; + } + } + if(numtrue == 1) + { + for(int i = 0; i < possibs.length;i++) + { + if(possibs[i]) + { + realoutput = new int[1][4]; + puzzle[x][y] = i+1; + realoutput[j][0] = 0; + realoutput[j][1] = x; + realoutput[j][2] = y; + realoutput[j][3] = i; + return realoutput; + } + } + } + } + return realoutput; + } + private int[][] implyByRowsHelper(int row) + { + //System.out.println("Implying on row " + row); + //boolean[] places = new boolean[size]; + //Outputs all numbers that should go on the stack, each number is in the form (0,x,y,num) + //this method may output more than 1 implyed number. + int[][] output = new int[size][4]; + int numImplyed = 0; + for(int i = 0; i < size; i++) + { //For each square + //This place already has something + if(puzzle[i][row] != 0) + { + //System.out.println("(" + i + "," + row + ") already has " + puzzle[i][row]); + } + else + { + boolean[] possibs = getPossibilitiesByRow(row); + //System.out.println("Possibilities for (" + i + "," + row + ") are:"); + printArray(possibs); + //Find out how many possibilites for this place is true + int numtrue = 0; + int lasttrue = 0; + for(int j = 0; j < size;j++) + { + if(possibs[j]) + { + numtrue++; + lasttrue = j+1; + } + } + if(numtrue == 1) + { + puzzle[i][row] = lasttrue; + output[numImplyed][0] = 0; + output[numImplyed][1] = i; + output[numImplyed][2] = row; + output[numImplyed][3] = lasttrue; + numImplyed++; + } + } + } + //System.out.println("First output is : "); + //printArray(output); + int[][] realoutput = new int[numImplyed][4]; + for(int i = 0; i < numImplyed; i++) + { + realoutput[i] = output[i]; + } + //System.out.println("Real output is : "); + //printArray(realoutput); + return realoutput; + } + private int[][] implyByColsHelper(int col) + { + // System.out.println("Implying on row " + row); + //boolean[] places = new boolean[size]; + //Outputs all numbers that should go on the stack, each number is in the form (0,x,y,num) + //this method may output more than 1 implyed number. + int[][] output = new int[size][4]; + int numImplyed = 0; + for(int i = 0; i < size; i++) + { //For each square + //This place already has something + if(puzzle[col][i] != 0) + { + //System.out.println("(" + i + "," + row + ") already has " + puzzle[i][row]); + } + else + { + boolean[] possibs = getPossibilitiesByCol(col); + //System.out.println("Possibilities for (" + col + "," + i + ") are:"); + //printArray(possibs); + //Find out how many possibilites for this place is true + int numtrue = 0; + int lasttrue = 0; + for(int j = 0; j < size;j++) + { + if(possibs[j]) + { + numtrue++; + lasttrue = j+1; + } + } + if(numtrue == 1) + { + puzzle[col][i] = lasttrue; + output[numImplyed][0] = 0; + output[numImplyed][1] = col; + output[numImplyed][2] = i; + output[numImplyed][3] = lasttrue; + numImplyed++; + } + } + } + //System.out.println("First output is : "); + //printArray(output); + int[][] realoutput = new int[numImplyed][4]; + for(int i = 0; i < numImplyed; i++) + { + realoutput[i] = output[i]; + } + //System.out.println("Real output is : "); + //printArray(realoutput); + return realoutput; + } + public void printPuzzle() + { + for(int y = 0; y < puzzle.length; y++) + { + for(int x = 0; x < puzzle[y].length; x++) + { + System.out.print(puzzle[x][y] + " "); + } + System.out.print("\n"); + } + } + public void printArray(int[] arr) + { + if(arr.length == 0) + { + System.out.println("[]"); + return; + } + System.out.print("[" + arr[0]); + for(int i = 1; i < arr.length; i++) + { + System.out.print("," + arr[i]); + } + System.out.print("]\n"); + } + public void printArray(int[][] arr) + { + if(arr.length == 0) + { + System.out.println("[[]]"); + return; + } + System.out.print("[\t"); + printArray(arr[0]); + for(int i = 1; i < arr.length; i++) + { + System.out.print("\t"); + printArray(arr[i]); + } + System.out.print("]\n"); + + } + public void printArray(boolean[] arr) + { + if(arr.length == 0) + { + System.out.println("[]"); + return; + } + System.out.print("[" + arr[0]); + for(int i = 1; i < arr.length; i++) + { + System.out.print("," + arr[i]); + } + System.out.print("]\n"); + } + public void printArray(Position[] arr) + { + if(arr.length == 0) + { + System.out.println("[]"); + return; + } + System.out.print("[(" + arr[0].x + "," + arr[0].y + ")"); + for(int i = 1; i < arr.length; i++) + { + System.out.print(",(" + arr[i].x + "," + arr[i].y + ")"); + } + System.out.print("]\n"); + } + public void printArray(Constraint[] arr) + { + if(arr.length == 0) + { + System.out.println("[[]]"); + return; + } + System.out.print("[\t"); + printArray(arr[0]); + for(int i = 1; i < arr.length; i++) + { + System.out.print("\t"); + printArray(arr[i]); + } + System.out.print("]\n"); + } + public void printArray(Constraint c) + { + System.out.print("(" + c.op + "," + c.targNumber + ","); + printArray(c.positions); + } +}
\ No newline at end of file |
