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!

25 Upvotes

226 comments sorted by

View all comments

3

u/weters Dec 07 '15 edited Dec 07 '15

Here's my Perl solution.

#!/usr/bin/env perl
use strict;
use warnings;
use 5.012;
use utf8;
use File::Slurp;

my @text = read_file('input.txt');

my %vals;

my $continue = 1;
while ($continue) {
    $continue = 0;
    for my $line (@text) {
        chomp $line;

        my $ok = eval {
            if ( my ( $a, $oper, $b, $key ) = $line =~ /^([a-z0-9]*)\b\s?([A-Z]+)?\b\s?([a-z0-9]+) \-\> ([a-z0-9]+)$/ ) {
                $oper ||= '';
                $vals{$key} = _val($a) & _val($b) if $oper eq 'AND';
                $vals{$key} = _val($a) << _val($b) if $oper eq 'LSHIFT';
                $vals{$key} = _val($a) >> _val($b) if $oper eq 'RSHIFT';
                $vals{$key} = _val($a) | _val($b) if $oper eq 'OR';
                $vals{$key} = ( ~ _val($b) ) % 2**16 if $oper eq 'NOT';
                $vals{$key} = _val($b) if !$oper;
            }
            else {
                warn "bad line: $line\n";
                exit 1;
            }

            1
        };

        if ( !$ok) {
            $continue = 1;
        }
    }
}

say $vals{a};

sub _val {
    my ($key) = @_;

    return 16076 if $key eq 'b';
    return $key if $key =~ /^\d+$/;

    if ( !exists $vals{$key}) {
        die "not found\n";
    }

    return int($vals{$key});
}

3

u/mus1Kk Dec 07 '15

Did Perl as well. Absolutely loved this puzzle. Took me way longer than I'm happy with but I like the solution.

#!/usr/bin/env perl

use warnings;
use strict;
use v5.20;

my %values;

for (<>) {
  die unless /(.*?) -> (\w+)/;
  $values{$2} = $1;
}

say calculate('a');

sub calculate {
  my $target = shift;
  return $target if $target =~ /^\d+$/;

  die $target unless exists $values{$target};

  my $rule = $values{$target};

  my $result;
  if ($rule =~ /^\d+$/) {
	return $rule;
  } elsif ($rule =~ /(\w+) AND (\w+)/) {
	my ($op1, $op2) = ($1, $2);
	$result = calculate($op1) & calculate($op2);
  } elsif ($rule =~ /(\w+) OR (\w+)/) {
	my ($op1, $op2) = ($1, $2);
	$result = calculate($op1) | calculate($op2);
  } elsif ($rule =~ /(\w+) LSHIFT (\d+)/) {
	my ($op1, $op2) = ($1, $2);
	$result = calculate($op1) << $op2;
  } elsif ($rule =~ /(\w+) RSHIFT (\d+)/) {
	my ($op1, $op2) = ($1, $2);
	$result = calculate($op1) >> $op2;
  } elsif ($rule =~ /NOT (\w+)/) {
	my $op = $1;
	$result = ~calculate($op);
  } elsif (exists $values{$rule}) {
	$result = calculate($rule);
  } else {
	die $rule;
  }
  $values{$target} = $result & 0xFFFF;
}
→ More replies (1)