From 8fe65029b07fbd3f03c6a4721aac5a081ac46dd8 Mon Sep 17 00:00:00 2001 From: Andinus Date: Mon, 14 Dec 2020 13:14:51 +0530 Subject: Add day-11 solution --- 2020/day-11/day-11.partial.raku | 102 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100755 2020/day-11/day-11.partial.raku (limited to '2020/day-11/day-11.partial.raku') diff --git a/2020/day-11/day-11.partial.raku b/2020/day-11/day-11.partial.raku new file mode 100755 index 0000000..2f5e48e --- /dev/null +++ b/2020/day-11/day-11.partial.raku @@ -0,0 +1,102 @@ +#!/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; + } +} -- cgit 1.4.1-2-gfad0