├── .gitignore ├── Leo.toml ├── inputs ├── test_input │ └── test_input.in ├── silly-sudoku.in └── silly-sudoku.state ├── README.md └── src ├── main.leo └── lib.leo /.gitignore: -------------------------------------------------------------------------------- 1 | outputs/ 2 | -------------------------------------------------------------------------------- /Leo.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "silly-sudoku" 3 | version = "0.1.2" 4 | description = "A simple Sudoku puzzle grid" 5 | license = "MIT" 6 | 7 | [remote] 8 | author = "howard" 9 | -------------------------------------------------------------------------------- /inputs/test_input/test_input.in: -------------------------------------------------------------------------------- 1 | [main] 2 | puzzle: [u8; (3, 3)] = [[0, 4, 6], 3 | [3, 0, 9], 4 | [7, 5, 0]]; 5 | answer: [u8; (3, 3)] = [[8, 4, 6], 6 | [3, 1, 9], 7 | [7, 5, 2]]; 8 | expected: bool = true; 9 | 10 | -------------------------------------------------------------------------------- /inputs/silly-sudoku.in: -------------------------------------------------------------------------------- 1 | // The program input for stable_token/src/main.leo 2 | [main] 3 | puzzle: [u8; (3, 3)] = [[0, 4, 6], 4 | [3, 0, 9], 5 | [7, 5, 0]]; 6 | answer: [u8; (3, 3)] = [[8, 4, 6], 7 | [3, 1, 9], 8 | [7, 5, 2]]; 9 | 10 | [registers] 11 | r0: bool = false; 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # silly-sudoku 2 | 3 | A simple Sudoku puzzle grid in Leo. 4 | 5 | ## Usage 6 | 7 | Add `silly-sudoku` to your Leo project: 8 | ``` 9 | leo add howard/silly-sudoku 10 | ``` 11 | 12 | This package is hosted on [Aleo.pm](https://aleo.pm/@howard/silly-sudoku). 13 | 14 | ## Walkthrough 15 | 16 | Start by defining a puzzle grid: 17 | ``` 18 | [[0, 4, 6], 19 | [3, 0, 9], 20 | [7, 5, 0]] 21 | ``` 22 | We treat all 0's as empty cells in the grid. 23 | 24 | Next, generate an answer and construct it as a puzzle grid solution: 25 | ``` 26 | [[8, 4, 6], 27 | [3, 1, 9], 28 | [7, 5, 2]] 29 | ``` 30 | 31 | The SillySudoku circuit will proceed to verify that the solution grid matches the starting puzzle grid, 32 | and check that each number between 1 - 9 is used exactly once. 33 | -------------------------------------------------------------------------------- /inputs/silly-sudoku.state: -------------------------------------------------------------------------------- 1 | // The program state for world/src/main.leo 2 | [[public]] 3 | 4 | [state] 5 | leaf_index: u32 = 0; 6 | root: [u8; 32] = [0u8; 32]; 7 | 8 | [[private]] 9 | 10 | [record] 11 | serial_number: [u8; 64] = [0u8; 64]; 12 | commitment: [u8; 32] = [0u8; 32]; 13 | owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9; 14 | is_dummy: bool = false; 15 | value: u64 = 5; 16 | payload: [u8; 32] = [0u8; 32]; 17 | birth_program_id: [u8; 48] = [0u8; 48]; 18 | death_program_id: [u8; 48] = [0u8; 48]; 19 | serial_number_nonce: [u8; 32] = [0u8; 32]; 20 | commitment_randomness: [u8; 32] = [0u8; 32]; 21 | 22 | [state_leaf] 23 | path: [u8; 128] = [0u8; 128]; 24 | memo: [u8; 32] = [0u8; 32]; 25 | network_id: u8 = 0; 26 | leaf_randomness: [u8; 32] = [0u8; 32]; 27 | -------------------------------------------------------------------------------- /src/main.leo: -------------------------------------------------------------------------------- 1 | import lib.SillySudoku; 2 | 3 | // The `silly-sudoku` main function 4 | function main(puzzle: [u8; (3, 3)], answer: [u8; (3, 3)]) -> bool { 5 | console.log("Starting Sudoku solver..."); 6 | console.log("{}", puzzle); 7 | 8 | // Instantiate the Sudoku puzzle. 9 | let sudoku = SillySudoku { puzzle_grid: puzzle }; 10 | 11 | console.log("Checking Sudoku answer..."); 12 | console.log("{}", answer); 13 | 14 | // Evaluate the Sudoku puzzle with the given answer. 15 | let result = sudoku.solve(answer); 16 | 17 | console.log("The answer is {}.", result); 18 | 19 | return result 20 | } 21 | 22 | // Tests that the `silly-sudoku` circuit outputs true on a correct answer. 23 | test function test_solve_pass() { 24 | let puzzle: [u8; (3, 3)] = [[0, 2, 0], 25 | [0, 0, 6], 26 | [0, 8, 9]]; 27 | 28 | let answer: [u8; (3, 3)] = [[1, 2, 3], 29 | [4, 5, 6], 30 | [7, 8, 9]]; 31 | 32 | // Runs the Sudoku checker. 33 | let result = main(puzzle, answer); 34 | 35 | // Expects the result to be true. 36 | console.assert(true == result); 37 | } 38 | 39 | // Tests that the `silly-sudoku` circuit outputs false on an incorrect answer. 40 | test function test_solve_fail() { 41 | let puzzle: [u8; (3, 3)] = [[0, 2, 0], 42 | [0, 0, 6], 43 | [0, 8, 0]]; 44 | 45 | let answer: [u8; (3, 3)] = [[1, 2, 3], 46 | [4, 5, 6], 47 | [7, 8, 8]]; // We have an extra `8` in this column! 48 | 49 | // Runs the Sudoku checker. 50 | let result = main(puzzle, answer); 51 | 52 | // Expects the result to be false. 53 | console.assert(false == result); 54 | } 55 | 56 | // Test that the `silly-sudoku` circuit outputs the expected value on a custom test input. 57 | @context(test_input) 58 | test function test_solve_with_input( 59 | puzzle: [u8; (3, 3)], 60 | answer: [u8; (3, 3)], 61 | expected: bool 62 | ) { 63 | // Runs the Sudoku checker. 64 | let result = main(puzzle, answer); 65 | 66 | console.log("expected {}, got {}", expected, result); 67 | 68 | console.assert(expected == result); 69 | } 70 | -------------------------------------------------------------------------------- /src/lib.leo: -------------------------------------------------------------------------------- 1 | /** 2 | * The SillySudoku circuit 3 | * 4 | * This circuit generates a silly Sudoku puzzle, 5 | * by constructing a 3x3 puzzle grid with some preset numbers 1-9, 6 | * and requiring an answer where each number is used exactly once. 7 | * 8 | * ----------- 9 | * | 5 | 8 | 3 | 10 | * |-----------| 11 | * | 2 | 7 | 4 | 12 | * |-----------| 13 | * | 1 | 9 | 6 | 14 | * ----------- 15 | */ 16 | circuit SillySudoku { 17 | // The starting grid values for the Sudoku puzzle. 18 | // Unset cells on the puzzle grid are set to 0. 19 | puzzle_grid: [u8; (3, 3)], 20 | 21 | /** 22 | * Returns true if a given Sudoku answer is correct. 23 | * 24 | * Verifies a given answer by iterating through the Sudoku puzzle, 25 | * and checking that each number is set exactly once. 26 | */ 27 | function solve(self, answer: [u8; (3, 3)]) -> bool { 28 | // The result boolean is set to true, if the answer is correct. 29 | let mut result = true; 30 | // An array that tracks the numbers used on the Sudoku grid. 31 | let mut seen = [false; 9]; 32 | 33 | // Iterate through the Sudoku grid and check each cell. 34 | for i in 0..3 { 35 | for j in 0..3 { 36 | 37 | // Fetch the current cell value for the Sudoku grid. 38 | let grid_value = self.puzzle_grid[i][j]; 39 | 40 | // Fetch the current cell value for the given answer. 41 | let answer_value = answer[i][j]; 42 | 43 | // Set the index by subtracting 1 from the answer value. 44 | let index = answer_value - 1; 45 | 46 | // Check if this number has already been used on the grid. 47 | let already_seen: bool = seen[index]; 48 | 49 | // If this number is already used, the answer is incorrect. 50 | // Sets the result to false. 51 | if already_seen { 52 | result = false; 53 | } 54 | 55 | // If the cell is not empty, and the grid value doesn't match 56 | // the answer value, the answer is incorrect. 57 | // Sets the result to false. 58 | if (grid_value != 0 && grid_value != answer_value) { 59 | result = false; 60 | } 61 | 62 | // Sets the answer value as seen. 63 | seen[index] = true; 64 | } 65 | } 66 | 67 | // Returns true if all numbers 1-9 have been seen exactly once. 68 | return result 69 | } 70 | } 71 | --------------------------------------------------------------------------------