enum Space (Gap => '.', Star => '*', Strudel => '@', Cross => 'X', Naught => 'O');
sub postfix:($_) {
Space($_)
}
sub swap($_) { # swap sides
when Strudel { Star }
when Star { Strudel }
when Cross { Naught }
when Naught { Cross }
default { Gap }
}
sub back($_) {
when 'd' { 'u' }
when 'u' { 'd' }
when 'r' { 'l' }
when 'l' { 'r' }
'n'
}
sub infix:(@a, @b) { # taxicab distance
[+] (@a Z- @b)>>.abs
}
sub honcho($_) {
when Naught { Strudel }
when Cross { Star }
$_
}
class GameBoard {
has @.grid is rw;
has $.ally is rw;
method to-string {
"{ $!ally.value }\n" ~ @!grid.deepmap({.value}).map(*.join).join("\n")
}
method score {
my $otal = 0;
for @!grid {
for @$_ {
when Star | Cross {
$otal++;
}
when Strudel | Naught {
$otal--;
}
}
}
given $!ally {
when Naught { $otal }
default { -$otal }
}
}
method ally-pos {
self.nearest(0, 0){honcho($!ally)}
}
method enemy-pos {
self.nearest(0, 0){honcho(swap($!ally))}
}
method get($x, $y) {
@!grid[$x][$y]
}
method nearest($x, $y) {
my %ashmap;
for ^@!grid -> $i {
for ^@!grid[$i] -> $j {
given %ashmap{ self.get($i, $j) } //= ($i, $j) { # insert into hasmap if unset
when (* taxi ($x, $y)) < (($i, $j) taxi ($x, $y)) { # compare distance
%ashmap{ self.get($i, $j) } = ($i, $j);
}
}
}
}
%ashmap
}
method pathfind($a, $b) {
my ($c, $d) = self.ally-pos;
when $b > $d {
# does horizontal first so more likely to complete boxes as an accident
'r'
}
when $b < $d {
'l'
}
when $a > $c {
'd'
}
when $a < $c {
'u'
}
'n'
}
method pathfind2($a, $b) {
my ($c, $d) = self.ally-pos;
when $a > $c {
'd'
}
when $a < $c {
'u'
}
when $b > $d {
'r'
}
when $b < $d {
'l'
}
'n'
}
method flow($a, $b) {
<
rrrrrrrrrrrrrrrrdddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
rrrrrrrrrrrrrrrurrrrrrrrrrrrrrrd
ullllllllllllllldlllllllllllllll
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuudddddddddddddddd
uuuuuuuuuuuuuuuullllllllllllllll
>>>.comb[$a][$b]
}
method go {
if self.score > 1 { # winning
when (self.enemy-pos taxi self.ally-pos) %% 2 {
'n' # wait
}
# go to enemy
self.pathfind(|self.enemy-pos)
} else {
given self.ally-pos {
# avoid enemy
when (self.enemy-pos taxi *) == 2 {
if (self.pathfind(|self.enemy-pos) | self.pathfind2(|self.enemy-pos)) ~~ self.flow(|self.ally-pos) {
back(self.flow(|self.ally-pos))
} else {
self.flow(|self.ally-pos)
}
}
# get more score
# go to good spot
self.flow(|$_)
}
}
}
}
=my plan was
look for bits where enemy is making 1-wide path with nothing on either side
to ruin all its borders and not get stuck
but that was too hard so its only this instead
sub MAIN {
my $type = (get)space;
my @big = lines>>.comb()>>space;
my $oard = GameBoard.new(grid => @big, ally => $type);
say $oard.go;
}
# prime time
our proto entry(|) {*}
subset Tiny of Int where * < 10;
multi entry(Tiny $nput) { # known primes <10
$nput ~~ one(2, 3, 5, 7)
}
subset Small of Int where * < 100;
multi entry(Small $nput) {
given $nput.comb.tail {
when any(0,2...^10) { False } # even numbers
when 5 { False } # ends in 5
when $nput.comb.sum ~~ one(1..5) * 3 { False } # multiple of 3 <99
when 1 ^ $nput.comb.head ^ 1 { False } # multiple of 11 >11
when seven($nput) { False }
default { True } # no prime factor 0;) {
$otal %= $odulus;
$otal *= $nput--;
if !$otal { last; }
}
$otal % $odulus
}
our sub hard-prime(int $_) { # trial division
$_ <= 1 !|| $_ %% any(2..$_.sqrt)
}