diff --git a/spring24/week4/Challenge$Stack$Node.class b/spring24/week4/Challenge$Stack$Node.class new file mode 100644 index 0000000..908f7ba Binary files /dev/null and b/spring24/week4/Challenge$Stack$Node.class differ diff --git a/spring24/week4/Challenge$Stack.class b/spring24/week4/Challenge$Stack.class new file mode 100644 index 0000000..52af3bb Binary files /dev/null and b/spring24/week4/Challenge$Stack.class differ diff --git a/spring24/week7/Challenge$Stack$Node.class b/spring24/week7/Challenge$Stack$Node.class new file mode 100644 index 0000000..8a0fe3f Binary files /dev/null and b/spring24/week7/Challenge$Stack$Node.class differ diff --git a/spring24/week7/Challenge$Stack.class b/spring24/week7/Challenge$Stack.class new file mode 100644 index 0000000..4827a2f Binary files /dev/null and b/spring24/week7/Challenge$Stack.class differ diff --git a/spring24/week7/Challenge.class b/spring24/week7/Challenge.class new file mode 100644 index 0000000..0d3095f Binary files /dev/null and b/spring24/week7/Challenge.class differ diff --git a/spring24/week9/Cell$List$Value.class b/spring24/week9/Cell$List$Value.class new file mode 100644 index 0000000..0456d1b Binary files /dev/null and b/spring24/week9/Cell$List$Value.class differ diff --git a/spring24/week9/Cell$List.class b/spring24/week9/Cell$List.class new file mode 100644 index 0000000..5b3d5f3 Binary files /dev/null and b/spring24/week9/Cell$List.class differ diff --git a/spring24/week9/Cell.class b/spring24/week9/Cell.class new file mode 100644 index 0000000..9fc9f24 Binary files /dev/null and b/spring24/week9/Cell.class differ diff --git a/spring24/week9/Cell.java b/spring24/week9/Cell.java new file mode 100644 index 0000000..38a6087 --- /dev/null +++ b/spring24/week9/Cell.java @@ -0,0 +1,285 @@ +package spring24.week9; + +/** + * A Cell represents a single cell in the Sudoku grid. + * This helper class is used to store the row, column, value, and possible values for a cell. + * The possible values are stored in an ArrayList of Integers, and are sorted in ascending order. + * + * The Cell class also contains a method to add a possible value to the cell, and a method to get the possible values. + */ +public class Cell { + private int row; + private int col; + private int box; + private int value; + private List possibleValues; + + /** + * Create a new Cell with the given row and column. + * + * The value of the cell is initially -2, and the possible values are initially empty. + * + * @param row + * @param col + */ + public Cell(int row, int col) { + this.row = row; + this.col = col; + setBox(); + possibleValues = new List(); + } + + /** + * Create a new Cell with the given row, column, and value. + * + * The possible values are initially empty. + * + * @param row + * @param col + * @param value + */ + public Cell(int row, int col, int value) { + this.row = row; + this.col = col; + this.value = value; + setBox(); + possibleValues = new List(); + } + + /** + * Create a new Cell with the given row, column, and possible values. + * + * The value of the cell is initially -2. + * + * @param row + * @param col + * @param possibleValues + */ + public Cell(int row, int col, int[] possibleValues) { + this.row = row; + this.col = col; + setBox(); + this.possibleValues = new List(possibleValues); + } + + /** + * Set the value of a cell. + * + * The value must be between 1 and 9, inclusive. + * + * @param value + */ + public void setValue(int value) { + if(value < 1 || value > 9) { + System.out.println("Value " + value + " is not a valid value for this cell."); + return; + } + + possibleValues.clear(); + this.value = value; + } + + /** + * Get the value of a cell. + * + * @return + */ + public int getValue() { + return value; + } + + /** + * Get the box a cell is in. + * + * @return box number + */ + public int getBox() { + return box; + } + + /** + * Add a value to the list of possible values. + * + * If the value is already possible for the cell, or if the value is not a valid value for the cell, then the value is not added. + * + * @param value + */ + public void addPossibleValue(int value) { + if(possibleValues.contains(value)) { + System.out.println("Value " + value + " is already possible for this cell."); + return; + } else if(value < -1 || value > 9) { + System.out.println("Value " + value + " is not a valid value for this cell."); + return; + } + + possibleValues.add(value); + } + + /** + * Get a list of possible values for the cell. + * + * This list is a copy of the cell's possible values, and is sorted in ascending order. + * + * @return list of possible values for the cell + */ + public int[] getPossibleValues() { + return possibleValues.toArray(); + } + + /** + * Given the cell's row and column, set the box number for the cell. + */ + private void setBox() { + int boxRow = row % 3; + int boxCol = col % 3; + box = boxRow * 3 + boxCol; + } + + /** + * This class is used to store the possible values for a cell in a sorted list. + * The list is sorted in ascending order, and the values are stored in a linked list. + * + * The List class also contains a method to add a value to the list, and a method to get the list of values as an array. + */ + private class List { + + private Value head; + private Value tail; + private int size; + private int max; + private int min; + + /** + * Create a new empty List. + * + * By default, the head and tail are null, the size is 0, and the max and min are 0. + */ + public List() { + head = null; + tail = null; + size = 0; + max = 0; + min = 0; + } + + /** + * Create a new List with the given initial value. + * + * By default, the head and tail are the same, the size is 1, and the max and min are the initial value. + * @param initValue + */ + public List(int initValue) { + head = new Value(initValue); + tail = head; + size = 1; + max = initValue; + min = initValue; + } + + /** + * Create a new List with the given initial values. + * + * @param initValues + */ + public List(int[] initValues) { + for(int i = 0; i < initValues.length; i++) add(initValues[i]); + } + + /** + * Add a new value to the list. + * + * By default, the value will be inserted at it's sorted place in the list. + * + * @param newValue + */ + public void add(int newValue) { + if(size == 0) { + head = new Value(newValue); + tail = head; + size = 1; + max = newValue; + min = newValue; + } else { + if(newValue > max) { + max = newValue; + tail.next = new Value(newValue); + tail = tail.next; + } else if(newValue < min) { + min = newValue; + Value tmp = new Value(newValue); + tmp.setNext(head); + head = tmp; + } else { + Value current = head; + while(current.next != null && current.next.value < newValue) { + current = current.next; + } + Value tmp = new Value(newValue); + tmp.setNext(current.next); + current.setNext(tmp); + } + size++; + } + } + + /** + * Get the list of values as an array. + * + * @return array of values in the list + */ + public int[] toArray() { + int[] array = new int[size]; + Value current = head; + for(int i = 0; i < size; i++) { + array[i] = current.value; + current = current.next; + } + return array; + } + + /** + * Check if the list contains the given value. + * + * @param value + * @return + */ + public boolean contains(int value) { + Value current = head; + while(current != null) { + if(current.value == value) return true; + current = current.next; + } + return false; + } + + /** + * Clear the list of all values. + */ + public void clear() { + head = null; + tail = null; + size = 0; + max = 0; + min = 0; + } + + /** + * Value class is a Node for the List class. + */ + private class Value { + + private int value; + private Value next; + + public Value(int value) { + this.value = value; + next = null; + } + + public void setNext(Value next) { + this.next = next; + } + } + } +} \ No newline at end of file diff --git a/spring24/week9/Sudoku.class b/spring24/week9/Sudoku.class new file mode 100644 index 0000000..7800c89 Binary files /dev/null and b/spring24/week9/Sudoku.class differ diff --git a/spring24/week9/Sudoku.java b/spring24/week9/Sudoku.java new file mode 100644 index 0000000..2b4ea47 --- /dev/null +++ b/spring24/week9/Sudoku.java @@ -0,0 +1,225 @@ +package spring24.week9; + +import java.util.ArrayList; +import java.util.Scanner; + +/** + * A Sudoku puzzle is a 9x9 grid of numbers, where each row, column, and 3x3 subgrid contains the numbers 1-9 exactly once. + * + * The goal of this challenge is to write a program that can solve Sudoku puzzles. + * + * Given an input .sdku file (a plain-text file containing the initial state of a Sudoku puzzle), find the solution to the puzzle and write the solution to a new .sdku file. + * + * The input file will contain 9 lines, each containing 9 characters. Each character will be a digit (1-9) or a period (.), representing an empty cell. + * + * The output file should contain the same 9x9 grid, with the empty cells filled in with the correct numbers. + * + * For example, given the following input file: + * + * 53..7.... + * 6..195... + * .98....6. + * 8...6...3 + * 4..8.3..1 + * 7...2...6 + * .6....28. + * ...419..5 + * ....8..79 + * + * The output file should be: + * + * 534678912 + * 672195348 + * 198342567 + * 859761423 + * 426853791 + * 713924856 + * 961537284 + * 287419635 + * 345286179 + * + * This challenge is broken up into parts. In Programming Club, we will split into teams of 3-4 people to work on each method. + */ +public class Sudoku { + + public static void main(String[] args) { + System.out.println("Welcome to the Sudoku Solver!"); + System.out.println("Let's solve a Sudoku puzzle."); + + Scanner in = new Scanner(System.in); + System.out.print("Enter the name of the input file (do not include the file extension): "); + String inputFilename = in.nextLine(); + System.out.print("Enter the name of the output file (do not include the file extension): "); + String outputFilename = in.nextLine(); + + Sudoku app = new Sudoku(); + Cell[][] grid = app.readPuzzle(inputFilename); + app.solve(grid); + app.saveSolution(outputFilename, grid); + } + + /** + * Given an input filename, read the Sudoku puzzle from the file and return it as a 9x9 grid numbers, with no value for spaces in the file. + * + * @param filename + * @return + */ + public Cell[][] readPuzzle(String filename) { + System.out.println("TODO: Read sudoku puzzle solution from " + filename); + // TODO: Account for possible invalid input file and handle an error. + // TODO: Spaces in the file should be represented as '.' in the grid. + // TOOD: Read the file's puzzle. + return null; + } + + /** + * Given an output filename and a 9x9 grid of numbers, write the Sudoku puzzle to the file. + * + * @param grid + * @return + */ + public void saveSolution(String filename, Cell[][] grid) { + System.out.println("TODO: Write sudoku puzzle solution to " + filename); + // TODO: Account for possible invalid solution from isSolved and handle an error. + // TODO: Write the solution to the file. + } + + /** + * Determine what numbers are available to be placed in the given cell of the grid. + * + * @param grid + * @param row + * @param col + * @return an array of numbers that are available to be placed in the given cell + */ + private void getAvailableNumbers(Cell[][] grid, int row, int col) { + // TODO: Account for possible invalid inputs and handle an error. + // TODO: Given the rules of Sudoku, determine what numbers are available to be placed in the given cell of the grid. + // HINT: Use the getRowRemainingNumbers, getColRemainingNumbers, and getBoxRemainingNumbers methods and save to the Cell. + System.out.println("TODO: Get available numbers for cell at row " + row + " and column " + col); + } + + /** + * Solve the Sudoku puzzle. + * + * @param grid + */ + public void solve(Cell[][] grid) { + // TODO: Account for possible invalid inputs and handle an error. + // TODO: Given the rules of Sudoku, solve the puzzle. + + // HINT: Use the getAvailableNumbers method to find the available numbers for each cell. + // HINT: Use the isSolved method to check if the puzzle is solved. + // HINT: Assume the puzzle is solvable and has only one solution. + System.out.println("TODO: Solve the Sudoku puzzle"); + } + + /** + * Get any number between 1 and 9 that is not in the row. + * + * @param grid + * @param row + * @return + */ + private ArrayList getRowRemainingNumbers(Cell[][] grid, int row) { + ArrayList remainingNumbers = new ArrayList(); + for(int i = 1; i <= 9; i++) { + boolean found = false; + for(int j = 0; j < 9; j++) { + if(grid[row][j].getValue() == i) { + found = true; + break; + } + } + if(!found) { + remainingNumbers.add(i); + } + } + + return remainingNumbers; + } + + /** + * Get any number between 1 and 9 that is not in the column. + * + * @param grid + * @param col + * @return + */ + private ArrayList getColRemainingNumbers(Cell[][] grid, int col) { + ArrayList remainingNumbers = new ArrayList(); + for(int i = 1; i <= 9; i++) { + boolean found = false; + for(int j = 0; j < 9; j++) { + if(grid[j][col].getValue() == i) { + found = true; + break; + } + } + if(!found) { + remainingNumbers.add(i); + } + } + + return remainingNumbers; + } + + /** + * Get any number between 1 and 9 that is not in the box. + * + * A box is a 3x3 subgrid of the 9x9 grid. + * + * @param grid + * @param box + * @return + */ + private ArrayList getBoxRemainingNumbers(Cell[][] grid, int row, int col) { + ArrayList remainingNumbers = new ArrayList(); + int boxRow = row % 3; + int boxCol = col % 3; + for(int i = 1; i <= 9; i++) { + boolean found = false; + for(int j = 0; j < 3; j++) { + for(int k = 0; k < 3; k++) { + if(grid[boxRow * 3 + j][boxCol * 3 + k].getValue() == i) { + found = true; + break; + } + } + } + if(!found) { + remainingNumbers.add(i); + } + } + + return remainingNumbers; + } + + /** + * Given a list of numbers, return an array of the numbers. + * + * A helper method to keep the code using arrays instead of lists whenever possible. + * + * @param list + * @return + */ + private int[] arrayListToArray(ArrayList list) { + int[] array = new int[list.size()]; + for(int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + return array; + } + + /** + * Given a 9x9 grid of numbers, return true if the grid is a valid Sudoku puzzle solution, and false otherwise. + * + * A valid Sudoku puzzle is one where each row, column, and 3x3 subgrid contains the numbers 1-9 exactly once. + * + * @param grid a 9x9 grid of numbers + * @return true if the grid is a valid Sudoku puzzle, and false otherwise + */ + private boolean isSolved(Cell[][] grid) { + return false; // TODO: I need to do this before club. + } +} \ No newline at end of file