From 77f0e44230512f926d8733efdc0c08322aa21a8b Mon Sep 17 00:00:00 2001 From: "Jan \"Yenya\" Kasprzak" Date: Mon, 13 Nov 2023 10:44:48 +0100 Subject: [PATCH] 2019 day 19 --- 2019/37.pl | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ 2019/38.pl | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 308 insertions(+) create mode 100755 2019/37.pl create mode 100755 2019/38.pl diff --git a/2019/37.pl b/2019/37.pl new file mode 100755 index 0000000..fed338f --- /dev/null +++ b/2019/37.pl @@ -0,0 +1,149 @@ +#!/usr/bin/perl -w + +use v5.16; + +package IntComp; +use bigint; + +sub new { + my ($class, $mem, $inputs) = @_; + my $self = { + mem => [ @$mem ], + pc => 0, + want_input => undef, + base => 0, + }; + $self->{inputs} = [ @$inputs ] + if defined $inputs; + bless $self, $class; +} + +sub clone { + my ($class, $other) = @_; + my $self = { + mem => [ @{ $other->{mem} } ], + pc => $other->{pc}, + want_input => undef, + base => $other->{base}, + inputs => [ ], + }; + bless $self, $class; +} + +sub m2val { + my ($self, $off, $mode) = @_; + if ($mode == 0) { + return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off] ] // 0; + } elsif ($mode == 1) { + return $self->{mem}->[$self->{pc} + $off] // 0; + } elsif ($mode == 2) { + return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off ] + $self->{base} ] // 0; + } +} + +sub m2pos { + my ($self, $off, $mode) = @_; + if ($mode == 0) { + return $self->{mem}->[$self->{pc} + $off]; + } elsif ($mode == 2) { + return $self->{mem}->[$self->{pc} + $off] + $self->{base}; + } +} + +sub input { + my ($self, @input) = @_; + push @{ $self->{inputs} }, @input; +} + +sub run { + my ($self, @input) = @_; + my $mem = $self->{mem}; + + push @{ $self->{inputs} }, @input; + if (defined $self->{want_input}) { + $mem->[$self->{want_input}] = shift @{ $self->{inputs} }; + $self->{want_input} = undef; + } + + while (1) { + my $opcode = $mem->[$self->{pc}]; + # say "pc=", $self->{pc}, " opcode=$opcode"; + # say "mem=", join(',', map { $_ // '_' } @{ $self->{mem} }); + my $op = int($opcode % 100); + my $m1 = int($opcode / 100) % 10; + my $m2 = int($opcode / 1000) % 10; + my $m3 = int($opcode / 10000) % 10; + if ($op == 1) { + $mem->[ m2pos($self, 3, $m3) ] + = m2val($self, 1, $m1) + + m2val($self, 2, $m2); + $self->{pc} += 4; + } elsif ($op == 2) { + $mem->[ m2pos($self, 3, $m3) ] + = m2val($self, 1, $m1) + * m2val($self, 2, $m2); + $self->{pc} += 4; + } elsif ($op == 3) { + if (@{ $self->{inputs} }) { + $mem->[ m2pos($self, 1, $m1) ] + = shift @{ $self->{inputs} }; + $self->{pc} += 2; + } else { + $self->{want_input} = m2pos($self, 1, $m1); + $self->{pc} += 2; + return undef; + } + } elsif ($op == 4) { + my $val = m2val($self, 1, $m1); + $self->{pc} += 2; + return $val; + } elsif ($op == 5) { + if (m2val($self, 1, $m1)) { + $self->{pc} = m2val($self, 2, $m2); + } else { + $self->{pc} += 3; + } + } elsif ($op == 6) { + if (!m2val($self, 1, $m1)) { + $self->{pc} = m2val($self, 2, $m2); + } else { + $self->{pc} += 3; + } + } elsif ($op == 7) { + $mem->[ m2pos($self, 3, $m3) ] = + m2val($self, 1, $m1) + < m2val($self, 2, $m2) ? 1 : 0; + $self->{pc} += 4; + } elsif ($op == 8) { + $mem->[ m2pos($self, 3, $m3) ] = + m2val($self, 1, $m1) + == m2val($self, 2, $m2) ? 1 : 0; + $self->{pc} += 4; + } elsif ($op == 9) { + $self->{base} += m2val($self, 1, $m1); + $self->{pc} += 2; + } elsif ($op == 99) { + return undef; + } + } +} + +package main; + +chomp (my @mem = split /,/, <>); + +$; = ','; + +my $sum; + +for my $x (0 .. 49) { +for my $y (0 .. 49) { + my $comp = IntComp->new(\@mem, [ $x, $y ]); + my $rv = $comp->run; + $sum++ if $rv; + print $rv ? '#' : '.'; +} +print "\n"; +} + +say $sum; diff --git a/2019/38.pl b/2019/38.pl new file mode 100755 index 0000000..2287564 --- /dev/null +++ b/2019/38.pl @@ -0,0 +1,159 @@ +#!/usr/bin/perl -w + +use v5.16; + +package IntComp; +use bigint; + +sub new { + my ($class, $mem, $inputs) = @_; + my $self = { + mem => [ @$mem ], + pc => 0, + want_input => undef, + base => 0, + }; + $self->{inputs} = [ @$inputs ] + if defined $inputs; + bless $self, $class; +} + +sub clone { + my ($class, $other) = @_; + my $self = { + mem => [ @{ $other->{mem} } ], + pc => $other->{pc}, + want_input => undef, + base => $other->{base}, + inputs => [ ], + }; + bless $self, $class; +} + +sub m2val { + my ($self, $off, $mode) = @_; + if ($mode == 0) { + return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off] ] // 0; + } elsif ($mode == 1) { + return $self->{mem}->[$self->{pc} + $off] // 0; + } elsif ($mode == 2) { + return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off ] + $self->{base} ] // 0; + } +} + +sub m2pos { + my ($self, $off, $mode) = @_; + if ($mode == 0) { + return $self->{mem}->[$self->{pc} + $off]; + } elsif ($mode == 2) { + return $self->{mem}->[$self->{pc} + $off] + $self->{base}; + } +} + +sub input { + my ($self, @input) = @_; + push @{ $self->{inputs} }, @input; +} + +sub run { + my ($self, @input) = @_; + my $mem = $self->{mem}; + + push @{ $self->{inputs} }, @input; + if (defined $self->{want_input}) { + $mem->[$self->{want_input}] = shift @{ $self->{inputs} }; + $self->{want_input} = undef; + } + + while (1) { + my $opcode = $mem->[$self->{pc}]; + # say "pc=", $self->{pc}, " opcode=$opcode"; + # say "mem=", join(',', map { $_ // '_' } @{ $self->{mem} }); + my $op = int($opcode % 100); + my $m1 = int($opcode / 100) % 10; + my $m2 = int($opcode / 1000) % 10; + my $m3 = int($opcode / 10000) % 10; + if ($op == 1) { + $mem->[ m2pos($self, 3, $m3) ] + = m2val($self, 1, $m1) + + m2val($self, 2, $m2); + $self->{pc} += 4; + } elsif ($op == 2) { + $mem->[ m2pos($self, 3, $m3) ] + = m2val($self, 1, $m1) + * m2val($self, 2, $m2); + $self->{pc} += 4; + } elsif ($op == 3) { + if (@{ $self->{inputs} }) { + $mem->[ m2pos($self, 1, $m1) ] + = shift @{ $self->{inputs} }; + $self->{pc} += 2; + } else { + $self->{want_input} = m2pos($self, 1, $m1); + $self->{pc} += 2; + return undef; + } + } elsif ($op == 4) { + my $val = m2val($self, 1, $m1); + $self->{pc} += 2; + return $val; + } elsif ($op == 5) { + if (m2val($self, 1, $m1)) { + $self->{pc} = m2val($self, 2, $m2); + } else { + $self->{pc} += 3; + } + } elsif ($op == 6) { + if (!m2val($self, 1, $m1)) { + $self->{pc} = m2val($self, 2, $m2); + } else { + $self->{pc} += 3; + } + } elsif ($op == 7) { + $mem->[ m2pos($self, 3, $m3) ] = + m2val($self, 1, $m1) + < m2val($self, 2, $m2) ? 1 : 0; + $self->{pc} += 4; + } elsif ($op == 8) { + $mem->[ m2pos($self, 3, $m3) ] = + m2val($self, 1, $m1) + == m2val($self, 2, $m2) ? 1 : 0; + $self->{pc} += 4; + } elsif ($op == 9) { + $self->{base} += m2val($self, 1, $m1); + $self->{pc} += 2; + } elsif ($op == 99) { + return undef; + } + } +} + +package main; + +chomp (my @mem = split /,/, <>); + +$; = ','; + +my $sum; + +sub getpos { return IntComp->new(\@mem, [ @_ ])->run; } + +my ($first, $last) = (0, 0); +my $y = 10; + +my @ends; +while (1) { + $y++; + $first++ while !getpos($first, $y); + $last = $first if $last < $first; + $last++ while getpos($last, $y); + say "$y $first..$last-1 (", $last - $first, ")"; + push @ends, $last; + if (@ends >= 100) { + my $end = shift @ends; + if ($end - $first >= 100) { + say "found at $first $y-99, ", 10000*$first+($y-99); + last; + } + } +} -- 2.43.0