#!/usr/bin/env perl6 use v6.c; class Bot { has Int $.number; has Pair $.low-dest; has Pair $.high-dest; has Int @.values = (); my Bot @known-bots; my Int @.output; method bot(Bot:U: Int $number) returns Bot { @known-bots[$number] //= Bot.new(:$number); return @known-bots[$number]; } method set-dest(Pair $low-dest, Pair $high-dest) { $!low-dest = $low-dest; $!high-dest = $high-dest; } method add-value(Int $value) { @!values.push($value); if (@!values.elems == 2) { # Part 1 answer # Not very elegant, oh well... if min(@!values) == 17 and max(@!values) == 61 { say "Bot $!number is comparing value-61 microchips with value-17 microchips."; } if !$!low-dest || !$!high-dest { die "Bot $!number has two values but no instructions!"; } else { if $!low-dest.key eq 'bot' { Bot.bot($!low-dest.value).add-value(min(@!values)); } else { @.output[$!low-dest.value] += min(@!values); } if $!high-dest.key eq 'bot' { Bot.bot($!high-dest.value).add-value(max(@!values)); } else { @.output[$!high-dest.value] += max(@!values); } @!values = (); } } } } my token num { \d+ } my token dest { bot || output } my rule init { ^ value goes to bot $ } my rule instr { ^ bot gives low to and high to $ } sub MAIN(IO() $inputfile where *.f) { # Read the input in two passes, first the instructions, then the initializations. PASS: for ^2 -> $pass { LINE: for $inputfile.lines -> $line { if $line ~~ &init { next LINE if $pass == 0; Bot.bot(+$).add-value(+$); } elsif $line ~~ &instr { next LINE if $pass == 1; Bot.bot(+$).set-dest(~$ => +$, ~$ => +$); } else { die "Invalid input: $line"; } } } # Part 2 answer my @output = Bot.output; say "The product of outputs 0, 1 and 2 is @output[^3].join('*') = { [*] @output[^3] }."; }