add silly-sudoku example

This commit is contained in:
Collin Chin 2021-03-29 22:12:06 -07:00
parent 426cfbc88c
commit c352f41d41
7 changed files with 212 additions and 0 deletions

2
examples/silly-sudoku/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
outputs/
/.leo

View File

@ -0,0 +1,8 @@
[project]
name = "silly-sudoku"
version = "0.1.3"
description = "A simple Sudoku puzzle grid"
license = "MIT"
[remote]
author = "howard"

View File

@ -0,0 +1,23 @@
# silly-sudoku
A simple Sudoku puzzle grid in Leo.
## Walkthrough
Start by defining a puzzle grid:
```
[[0, 4, 6],
[3, 0, 9],
[7, 5, 0]]
```
We treat all 0's as empty cells in the grid.
Next, generate an answer and construct it as a puzzle grid solution:
```
[[8, 4, 6],
[3, 1, 9],
[7, 5, 2]]
```
The SillySudoku circuit will proceed to verify that the solution grid matches the starting puzzle grid,
and check that each number between 1 - 9 is used exactly once.

View File

@ -0,0 +1,12 @@
// The program input for tmp-test/src/main.leo
[main]
puzzle: [u8; (3, 3)] = [[0, 2, 0],
[0, 0, 6],
[0, 8, 9]];
answer: [u8; (3, 3)] = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]];
[registers]
r: bool = false;

View File

@ -0,0 +1,26 @@
// The program state for tmp-test/src/main.leo
[[public]]
[state]
leaf_index: u32 = 0;
root: [u8; 32] = [0; 32];
[[private]]
[record]
serial_number: [u8; 64] = [0; 64];
commitment: [u8; 32] = [0; 32];
owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9;
is_dummy: bool = false;
value: u64 = 0;
payload: [u8; 32] = [0; 32];
birth_program_id: [u8; 48] = [0; 48];
death_program_id: [u8; 48] = [0; 48];
serial_number_nonce: [u8; 32] = [0; 32];
commitment_randomness: [u8; 32] = [0; 32];
[state_leaf]
path: [u8; 128] = [0; 128];
memo: [u8; 32] = [0; 32];
network_id: u8 = 0;
leaf_randomness: [u8; 32] = [0; 32];

View File

@ -0,0 +1,70 @@
/**
* The SillySudoku circuit
*
* This circuit generates a silly Sudoku puzzle,
* by constructing a 3x3 puzzle grid with some preset numbers 1-9,
* and requiring an answer where each number is used exactly once.
*
* -----------
* | 5 | 8 | 3 |
* |-----------|
* | 2 | 7 | 4 |
* |-----------|
* | 1 | 9 | 6 |
* -----------
*/
circuit SillySudoku {
// The starting grid values for the Sudoku puzzle.
// Unset cells on the puzzle grid are set to 0.
puzzle_grid: [u8; (3, 3)],
/**
* Returns true if a given Sudoku answer is correct.
*
* Verifies a given answer by iterating through the Sudoku puzzle,
* and checking that each number is set exactly once.
*/
function solve(self, answer: [u8; (3, 3)]) -> bool {
// The result boolean is set to true, if the answer is correct.
let result = true;
// An array that tracks the numbers used on the Sudoku grid.
let seen = [false; 9];
// Iterate through the Sudoku grid and check each cell.
for i in 0..3 {
for j in 0..3 {
// Fetch the current cell value for the Sudoku grid.
let grid_value = self.puzzle_grid[i][j];
// Fetch the current cell value for the given answer.
let answer_value = answer[i][j];
// Set the index by subtracting 1 from the answer value.
let index = answer_value - 1;
// Check if this number has already been used on the grid.
let already_seen: bool = seen[index];
// If this number is already used, the answer is incorrect.
// Sets the result to false.
if already_seen {
result = false;
}
// If the cell is not empty, and the grid value doesn't match
// the answer value, the answer is incorrect.
// Sets the result to false.
if (grid_value != 0 && grid_value != answer_value) {
result = false;
}
// Sets the answer value as seen.
seen[index] = true;
}
}
// Returns true if all numbers 1-9 have been seen exactly once.
return result
}
}

View File

@ -0,0 +1,71 @@
import lib.SillySudoku;
// The `silly-sudoku` main function
function main(puzzle: [u8; (3, 3)], answer: [u8; (3, 3)]) -> bool {
console.log("Starting Sudoku solver...");
console.log("{}", puzzle);
// Instantiate the Sudoku puzzle.
let sudoku = SillySudoku { puzzle_grid: puzzle };
console.log("Checking Sudoku answer...");
console.log("{}", answer);
// Evaluate the Sudoku puzzle with the given answer.
let result = sudoku.solve(answer);
console.log("The answer is {}.", result);
return result
}
// Tests that the `silly-sudoku` circuit outputs true on a correct answer.
@test
function test_solve_pass() {
let puzzle: [u8; (3, 3)] = [[0, 2, 0],
[0, 0, 6],
[0, 8, 9]];
let answer: [u8; (3, 3)] = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]];
// Runs the Sudoku checker.
let result = main(puzzle, answer);
// Expects the result to be true.
console.assert(true == result);
}
// Tests that the `silly-sudoku` circuit outputs false on an incorrect answer.
@test
function test_solve_fail() {
let puzzle: [u8; (3, 3)] = [[0, 2, 0],
[0, 0, 6],
[0, 8, 0]];
let answer: [u8; (3, 3)] = [[1, 2, 3],
[4, 5, 6],
[7, 8, 8]]; // We have an extra `8` in this column!
// Runs the Sudoku checker.
let result = main(puzzle, answer);
// Expects the result to be false.
console.assert(false == result);
}
// Test that the `silly-sudoku` circuit outputs the expected value on a custom test input.
@test(test_input)
function test_solve_with_input(
puzzle: [u8; (3, 3)],
answer: [u8; (3, 3)],
expected: bool
) {
// Runs the Sudoku checker.
let result = main(puzzle, answer);
console.log("expected {}, got {}", expected, result);
console.assert(expected == result);
}