1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
unit module Tucana::CLI;
use Octans::Neighbors;
# If no arguments are passed then run USAGE & exit.
proto MAIN (|) is export {unless so @*ARGS {say $*USAGE; exit;}; {*}}
multi sub MAIN (Bool :$version) {
say "Tucana v" ~ $?DISTRIBUTION.meta<version>;
}
multi sub MAIN (
Str $word, #= word for the puzzle
Bool :v($verbose), #= increase verbosity
) {
my @puzzle := generate-puzzle($word);
" $_".say for @puzzle;
}
# generate-puzzle generates a 3x3 puzzle with $word in there.
sub generate-puzzle (
Str $word,
) {
my @puzzle := [
[<_ _ _ _>],
[<_ _ _ _>],
[<_ _ _ _>],
[<_ _ _ _>],
];
my Int ($y, $x) = edges(@puzzle).pick;
@puzzle[$y][$x] = $word.comb[0];
my @visited;
@visited[$y][$x] = True;
my Int $count = 1;
while $count < $word.chars {
neighbor: for neighbors(@puzzle, $y, $x).pick(*) -> ($pos-y, $pos-x) {
next neighbor if @visited[$pos-y][$pos-x];
@visited[$pos-y][$pos-x] = True;
@puzzle[$pos-y][$pos-x] = $word.comb[$count];
($y, $x) = ($pos-y, $pos-x);
last neighbor;
}
$count++;
}
return @puzzle;
}
# edges takes a 2d grid & returns the list of edges, i.e. squares with
# < 4 neighbors.
sub edges (
@puzzle --> List
) {
my List @edges;
for 0 .. @puzzle.end -> $y {
for 0 .. @puzzle[$y].end -> $x {
push @edges, ($y, $x) if neighbors(@puzzle, $y, $x).elems < 4;
}
}
return @edges;
}
|