#!/usr/bin/env raku
use v6;
sub MAIN ($filename = $?FILE.subst(/\.raku$/, '.tmp')) {
my $inputs = get-inputs($filename);
my ($part1, $part2) = solve($inputs);
my $highlight = "\e[1;97;45m";
my $reset = "\e[0m";
($highlight, $reset) = '', '';
put "part1 $highlight$part1$reset";
put "part2\n$highlight$part2$reset";
}
sub get-inputs ($filename) {
my @board;
my @folds;
my $do-board = 1;
for $*IN.lines -> $line {
if $line ~~ /^ \s* $/ {
$do-board = 0;
}
elsif $do-board {
@board.push: [$line.comb: /\d+/];
}
else {
my @fold = 0, 0;
$line ~~ / (.) \= (\d+) /;
if $0 eq 'x' { @fold[0] = +$1 }
else { @fold[1] = +$1 }
@folds.push: @fold;
}
}
return {board => @board, folds => @folds};
}
sub solve ($inputs) {
return (part1($inputs), part2($inputs));
}
sub part1 ($inputs) {
my @folded = fold($inputs<board>, $inputs<folds>[0]);
return @folded.elems;
}
sub part2 ($inputs) {
my $board = $inputs<board>;
$board = fold($board, $_) for $inputs<folds>.List;
my ($mx, $my) X= 0;
for @$board -> $p {
$mx = max($mx, +$p[0]);
$my = max($my, +$p[1]);
}
my @rendered = (0 .. ($my / 2).Int).map({[' ' xx (1 + $mx)]});
for @$board -> $p {
my $y = ($p[1] / 2).Int;
if @rendered[$y][$p[0]] ne ' ' {
@rendered[$y][$p[0]] = "\c[FULL BLOCK]";
}
elsif $p[1] %% 2 {
@rendered[$y][$p[0]] = "\c[UPPER HALF BLOCK]";
}
else {
@rendered[$y][$p[0]] = "\c[LOWER HALF BLOCK]";
}
}
return @rendered».join('').join("\n");
}
sub fold ($board, $fold) {
$board.map(-> $p {
(0 .. $fold.end).map({
$p[$_] <= $fold[$_] ?? $p[$_] !! 2 * $fold[$_] - $p[$_];
}).join(',')
}).Set.keys».comb(/\d+/)».Array;
}