mscha icon

AoC 2016.10

mscha | PRO | 12/10/16 12:58:18 PM UTC | 0 ⭐ | 584 👁️ | Never ⏰ | []
Perl 6 |

0 B

|

None

|

0 👍

/

0 👎

#!/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 <value=num> goes to bot <bot=num> $ }
my rule instr { ^ bot <bot=num> gives low to <dest-low=dest> <value-low=num>
                            and high to <dest-high=dest> <value-high=num> $ }
 
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(+$<bot>).add-value(+$<value>);
            }
            elsif $line ~~ &instr {
                next LINE if $pass == 1;
                Bot.bot(+$<bot>).set-dest(~$<dest-low> => +$<value-low>,
                                          ~$<dest-high> => +$<value-high>);
            }
            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] }.";
}

Comments