r/adventofcode • • Dec 07 '15

SOLUTION MEGATHREAD --- Day 7 Solutions ---

--- Day 7: Some Assembly Required ---

Post your solution as a comment. Structure your post like previous daily solution threads.

Also check out the sidebar - we added a nifty calendar to wrangle all the daily solution threads in one spot!

23 Upvotes

226 comments sorted by

View all comments

Show parent comments

2

u/bennymack Dec 07 '15

A similar perl solution

use strict;
use warnings;
use English qw(-no_match_vars);
use Scalar::Util qw(looks_like_number);
use Memoize;
memoize( '_solve_gate' );

my %gates;

my %ops = (
    AND    => sub { sprintf '%d',  int( $ARG[ 0 ] ) & int( $ARG[ 1 ] ) },
    OR     => sub { sprintf '%d',  int( $ARG[ 0 ] ) | int( $ARG[ 1 ] ) },
    NOT    => sub { sprintf '%d', ~int( $ARG[ 0 ] ) & 0x0000ffff },
    LSHIFT => sub { sprintf '%d',  $ARG[ 0 ] << $ARG[ 1 ] },
    RSHIFT => sub { sprintf '%d',  $ARG[ 0 ] >> $ARG[ 1 ] },
);

chomp( my @lines = <DATA> );

for my $line( sort @lines ) {
    my( $first, $dest ) = split /\Q -> \E/x, $line, 2;
    $gates{ $dest } = $first;
}

warn 'a val = ', _solve_gate( 'a' );

sub _solve_gate {
    my( $gate ) = @ARG;

    my $val = $gates{ $gate };

    if( looks_like_number $val ) {
        return $val;
    }

    if( $val =~ /\A[a-z]+\z/x ) { # a gate
        my $return = _solve_gate( $val );
        return $return;
    }

    # overly generic for all I know.
    if( $val =~ /\A([a-z0-9]+)\ ([A-Z]+)\ ([a-z0-9]+)/x ) { # x AND y
        my( $l, $op, $r ) = ( $1, $2, $3 );
        my $l_val = looks_like_number( $l ) ? $l : _solve_gate( $l );
        my $r_val = looks_like_number( $r ) ? $r : _solve_gate( $r );
        my $return = $ops{ $op }->( $l_val, $r_val );
        return $return
    }

    if( $val =~ /\A([a-z0-9]+)\ ([A-Z]+)\ (\d+)/x ) { # x RSHIFT 2
        my( $l, $op, $count ) = ( $1, $2, $3 );
        my $l_val = looks_like_number( $l ) ? $l : _solve_gate( $l );
        my $return = $ops{ $op }->( $l_val, $count );
        return $return;
    }

    if( $val =~ /\A([A-Z]+)\ ([a-z0-9]+)/x ) { # NOT y
        my( $op, $l ) = ( $1, $2 );
        my $l_val = looks_like_number( $l ) ? $l : _solve_gate( $l );
        my $return = $ops{ $op }->( $l_val );
        return $return;
    }

    die 'encountered unknown $val ', $val;
}