June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -0,0 +1,90 @@
// version 1.2.0
val example1 = listOf(
"00,00,00,00,00,00,00,00,00",
"00,00,46,45,00,55,74,00,00",
"00,38,00,00,43,00,00,78,00",
"00,35,00,00,00,00,00,71,00",
"00,00,33,00,00,00,59,00,00",
"00,17,00,00,00,00,00,67,00",
"00,18,00,00,11,00,00,64,00",
"00,00,24,21,00,01,02,00,00",
"00,00,00,00,00,00,00,00,00"
)
val example2 = listOf(
"00,00,00,00,00,00,00,00,00",
"00,11,12,15,18,21,62,61,00",
"00,06,00,00,00,00,00,60,00",
"00,33,00,00,00,00,00,57,00",
"00,32,00,00,00,00,00,56,00",
"00,37,00,01,00,00,00,73,00",
"00,38,00,00,00,00,00,72,00",
"00,43,44,47,48,51,76,77,00",
"00,00,00,00,00,00,00,00,00"
)
val moves = listOf(1 to 0, 0 to 1, -1 to 0, 0 to -1)
lateinit var board: List<String>
lateinit var grid: List<IntArray>
lateinit var clues: IntArray
var totalToFill = 0
fun solve(r: Int, c: Int, count: Int, nextClue: Int): Boolean {
if (count > totalToFill) return true
val back = grid[r][c]
if (back != 0 && back != count) return false
if (back == 0 && nextClue < clues.size && clues[nextClue] == count) {
return false
}
var nextClue2 = nextClue
if (back == count) nextClue2++
grid[r][c] = count
for (m in moves) {
if (solve(r + m.second, c + m.first, count + 1, nextClue2)) return true
}
grid[r][c] = back
return false
}
fun printResult(n: Int) {
println("Solution for example $n:")
for (row in grid) {
for (i in row) {
if (i == -1) continue
print("%2d ".format(i))
}
println()
}
}
fun main(args: Array<String>) {
for ((n, ex) in listOf(example1, example2).withIndex()) {
board = ex
val nRows = board.size + 2
val nCols = board[0].split(",").size + 2
var startRow = 0
var startCol = 0
grid = List(nRows) { IntArray(nCols) { -1 } }
totalToFill = (nRows - 2) * (nCols - 2)
val lst = mutableListOf<Int>()
for (r in 0 until nRows) {
if (r in 1 until nRows - 1) {
val row = board[r - 1].split(",")
for (c in 1 until nCols - 1) {
val value = row[c - 1].toInt()
if (value > 0) lst.add(value)
if (value == 1) {
startRow = r
startCol = c
}
grid[r][c] = value
}
}
}
lst.sort()
clues = lst.toIntArray()
if (solve(startRow, startCol, 1, 0)) printResult(n + 1)
}
}

View file

@ -0,0 +1,116 @@
my @adjacent = [-1, 0],
[ 0, -1], [ 0, 1],
[ 1, 0];
put "\n" xx 60;
solveboard q:to/END/;
__ __ __ __ __ __ __ __ __
__ __ 46 45 __ 55 74 __ __
__ 38 __ __ 43 __ __ 78 __
__ 35 __ __ __ __ __ 71 __
__ __ 33 __ __ __ 59 __ __
__ 17 __ __ __ __ __ 67 __
__ 18 __ __ 11 __ __ 64 __
__ __ 24 21 __ 1 2 __ __
__ __ __ __ __ __ __ __ __
END
# And
put "\n" xx 60;
solveboard q:to/END/;
0 0 0 0 0 0 0 0 0
0 11 12 15 18 21 62 61 0
0 6 0 0 0 0 0 60 0
0 33 0 0 0 0 0 57 0
0 32 0 0 0 0 0 56 0
0 37 0 1 0 0 0 73 0
0 38 0 0 0 0 0 72 0
0 43 44 47 48 51 76 77 0
0 0 0 0 0 0 0 0 0
END
sub solveboard($board) {
my $max = +$board.comb(/\w+/);
my $width = $max.chars;
my @grid;
my @known;
my @neigh;
my @degree;
@grid = $board.lines.map: -> $line {
[ $line.words.map: { /^_/ ?? 0 !! /^\./ ?? Rat !! $_ } ]
}
sub neighbors($y,$x --> List) {
eager gather for @adjacent {
my $y1 = $y + .[0];
my $x1 = $x + .[1];
take [$y1,$x1] if defined @grid[$y1][$x1];
}
}
for ^@grid -> $y {
for ^@grid[$y] -> $x {
if @grid[$y][$x] -> $v {
@known[$v] = [$y,$x];
}
if @grid[$y][$x].defined {
@neigh[$y][$x] = neighbors($y,$x);
@degree[$y][$x] = +@neigh[$y][$x];
}
}
}
print "\e[0H\e[0J";
my $tries = 0;
try_fill 1, @known[1];
sub try_fill($v, $coord [$y,$x] --> Bool) {
return True if $v > $max;
$tries++;
my $old = @grid[$y][$x];
return False if +$old and $old != $v;
return False if @known[$v] and @known[$v] !eqv $coord;
@grid[$y][$x] = $v; # conjecture grid value
print "\e[0H"; # show conjectured board
for @grid -> $r {
say do for @$r {
when Rat { ' ' x $width }
when 0 { '_' x $width }
default { .fmt("%{$width}d") }
}
}
my @neighbors = @neigh[$y][$x][];
my @degrees;
for @neighbors -> \n [$yy,$xx] {
my $d = --@degree[$yy][$xx]; # conjecture new degrees
push @degrees[$d], n; # and categorize by degree
}
for @degrees.grep(*.defined) -> @ties {
for @ties.reverse { # reverse works better for this hidato anyway
return True if try_fill $v + 1, $_;
}
}
for @neighbors -> [$yy,$xx] {
++@degree[$yy][$xx]; # undo degree conjectures
}
@grid[$y][$x] = $old; # undo grid value conjecture
return False;
}
say "$tries tries";
}