blob: 2f5e48e188980e6f74eadfdd3052ca46313b31b1 (
plain) (
tree)
|
|
#!/usr/bin/env raku
sub MAIN (
Int $part where * == 1|2 = 1 #= part to run (1 or 2)
) {
my @input = "input".IO.lines;
my Int $x-max = @input[0].chars - 1;
my Int $row-length = $x-max + 1;
my @seats = @input.join.comb;
my $max-seats = @seats.end;
my @directions = (+$row-length, -$row-length); # down, up
# @non-left-corner contains directions that left corner can't
# follow. It should only be followed by non-left corner seats.
my @non-left-corner = (
-$row-length - 1, # up-left
-1, # left
+$row-length - 1, # down-left
);
# @non-right-corner contains directions that right corner can't
# follow. It should only be followed by non-right corner seats.
my @non-right-corner = (
-$row-length + 1, # up-right
+1, # right
+$row-length + 1, # down-right
);
my Int $round = 0;
loop {
my @changed;
my Bool $change = False;
INNER: for @seats.kv -> $idx, $seat {
@changed[$idx] = $seat;
given $seat {
when '.' { next INNER; }
when 'L' {
if adjacent-occupied($idx, 1) == 0 {
@changed[$idx] = '#';
$change = True;
}
}
when '#' {
if adjacent-occupied($idx, 1) >= 4 {
@changed[$idx] = 'L';
$change = True;
}
}
}
}
$round++;
print "Round $round.\r";
last unless $change;
for @changed.kv -> $idx, $changed_seat {
@seats[$idx] = $changed_seat;
}
}
my Int $occupied = @seats.comb('#').elems;
say "Part $part: ", $occupied;
# adjacent-occupied returns the number of adjacent cells that have
# been occupied by others. $visibility_range should be 1 if only
# directly adjacent seats are to be counted. Make it -1 for
# infinite visibility. It ignores floors ('.').
sub adjacent-occupied (
Int $idx, Int $visibility_range --> Int
) {
my Int $occupied = 0;
for @directions -> $direction {
with @seats[$idx + $direction] {
$occupied++ if $_ eq '#';
}
}
# Elements in right corner can't follow @non-right-corner.
unless ($idx + 1) % 10 == 0 {
for @non-right-corner -> $direction {
with @seats[$idx + $direction] {
$occupied++ if $_ eq '#';
}
}
}
# Elements in left corner can't follow @non-left-corner.
unless $idx % 10 == 0 {
for @non-left-corner -> $direction {
with @seats[$idx + $direction] {
$occupied++ if $_ eq '#';
}
}
}
return $occupied;
}
}
|