From: Jan "Yenya" Kasprzak Date: Thu, 24 Nov 2022 15:58:37 +0000 (+0100) Subject: First half of Year 2019 X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=aoc.git;a=commitdiff_plain;h=4fc399ecb8a8626d476087a9ec1809e260a8268c First half of Year 2019 --- diff --git a/2019/01.pl b/2019/01.pl new file mode 100755 index 0000000..946d264 --- /dev/null +++ b/2019/01.pl @@ -0,0 +1,7 @@ +#!/usr/bin/perl -w + +use v5.16; + +my $sum; +$sum += int($_/3)-2 for <>; +say $sum; diff --git a/2019/02.pl b/2019/02.pl new file mode 100755 index 0000000..90a125c --- /dev/null +++ b/2019/02.pl @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use v5.16; + +my $sum; +while (<>) { + while (1) { + $_ = int($_/3)-2; + last if $_ <= 0; + $sum += $_; + } +} +say $sum; diff --git a/2019/03.pl b/2019/03.pl new file mode 100755 index 0000000..a73fcf4 --- /dev/null +++ b/2019/03.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl -w + +use v5.16; + +chomp (my @mem = split /,/, <>); +$mem[1] = 12; +$mem[2] = 2; +my $pc = 0; +while (1) { + if ($mem[$pc] == 1) { + $mem[ $mem[$pc+3] ] = $mem[ $mem[$pc+1] ] + $mem[ $mem[$pc+2] ]; + } elsif ($mem[$pc] == 2) { + $mem[ $mem[$pc+3] ] = $mem[ $mem[$pc+1] ] * $mem[ $mem[$pc+2] ]; + } elsif ($mem[$pc] == 99) { + last; + } + $pc += 4; +} + +say $mem[0]; diff --git a/2019/04.pl b/2019/04.pl new file mode 100755 index 0000000..4e43c5d --- /dev/null +++ b/2019/04.pl @@ -0,0 +1,31 @@ +#!/usr/bin/perl -w + +use v5.16; + +chomp (my @mem = split /,/, <>); + +sub run { + my ($m1, $m2, @mem) = @_; + $mem[1] = $m1; + $mem[2] = $m2; + my $pc = 0; + while (1) { + if ($mem[$pc] == 1) { + $mem[ $mem[$pc+3] ] = $mem[ $mem[$pc+1] ] + $mem[ $mem[$pc+2] ]; + } elsif ($mem[$pc] == 2) { + $mem[ $mem[$pc+3] ] = $mem[ $mem[$pc+1] ] * $mem[ $mem[$pc+2] ]; + } elsif ($mem[$pc] == 99) { + last; + } + $pc += 4; + } + return $mem[0]; +} + +for my $n (0..99) { + for my $v (0..99) { + say 100*$n + $v if run($n, $v, @mem) == 19690720; + } +} + +say $mem[0]; diff --git a/2019/05.pl b/2019/05.pl new file mode 100755 index 0000000..72fb699 --- /dev/null +++ b/2019/05.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl -w + +use v5.16; + +$; = ','; +sub walk { + my ($desc) = @_; + my %rv; + my ($x, $y) = (0, 0); + for my $step (split /,/, $desc) { + my ($dir, $dist) = $step =~ /([A-Z])(\d+)/; + my ($dx, $dy); + ($dx, $dy) = (1, 0) if $dir eq 'R'; + ($dx, $dy) = (0, 1) if $dir eq 'D'; + ($dx, $dy) = (0, -1) if $dir eq 'U'; + ($dx, $dy) = (-1, 0) if $dir eq 'L'; + $rv{$x += $dx, $y += $dy} = 1 while $dist--; + say "$step -> $x, $y"; + } + return \%rv; +} + +my $p1 = walk(scalar <>); +my $p2 = walk(scalar <>); + +my $dist; +for my $pos (keys %$p1) { + next if !$p2->{$pos}; + my ($x, $y) = split /,/, $pos; + my $d = abs($x)+abs($y); + $dist = $d if !$dist || $dist > $d; +} + +say $dist; + diff --git a/2019/06.pl b/2019/06.pl new file mode 100755 index 0000000..b67d12a --- /dev/null +++ b/2019/06.pl @@ -0,0 +1,40 @@ +#!/usr/bin/perl -w + +use v5.16; + +$; = ','; +sub walk { + my ($desc) = @_; + my %rv; + my ($x, $y) = (0, 0); + my $l = 0; + for my $step (split /,/, $desc) { + my ($dir, $dist) = $step =~ /([A-Z])(\d+)/; + my ($dx, $dy); + ($dx, $dy) = (1, 0) if $dir eq 'R'; + ($dx, $dy) = (0, 1) if $dir eq 'D'; + ($dx, $dy) = (0, -1) if $dir eq 'U'; + ($dx, $dy) = (-1, 0) if $dir eq 'L'; + while ($dist--) { + $x += $dx; $y += $dy; ++$l; + $rv{$x, $y} //= $l; + } + say "$step -> $x, $y ($rv{$x,$y})"; + } + return \%rv; +} + +my $p1 = walk(scalar <>); +my $p2 = walk(scalar <>); + +my $dist; +for my $pos (keys %$p1) { + next if !$p2->{$pos}; + next if $pos eq '0,0'; + my $d = $p1->{$pos}+$p2->{$pos}; + say "Intersection at $pos dist $d"; + $dist = $d if !$dist || $dist > $d; +} + +say $dist; + diff --git a/2019/07.pl b/2019/07.pl new file mode 100755 index 0000000..7dce860 --- /dev/null +++ b/2019/07.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl -w + +use v5.16; + +my $count; +NUM: +for (347312..805915) { + next if !/(.)\1/; + my $prev = 0; + for my $d (split //) { + next NUM if $d < $prev; + $prev = $d; + } + $count++; +} + +say $count; + diff --git a/2019/08.pl b/2019/08.pl new file mode 100755 index 0000000..948322f --- /dev/null +++ b/2019/08.pl @@ -0,0 +1,22 @@ +#!/usr/bin/perl -w + +use v5.16; + +my $count; +NUM: +for (347312..805915) { + for my $d (0 .. 9) { + goto FOUND if /$d{2}/ && !/$d{3}/; + } + next; + FOUND: + my $prev = 0; + for my $d (split //) { + next NUM if $d < $prev; + $prev = $d; + } + $count++; +} + +say $count; + diff --git a/2019/09.pl b/2019/09.pl new file mode 100755 index 0000000..84f958c --- /dev/null +++ b/2019/09.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w + +use v5.16; + +chomp (my @mem = split /,/, <>); + +sub m2val { + my ($mref, $addr, $mode) = @_; + if ($mode == 0) { + return $mref->[ $mref->[$addr] ]; + } elsif ($mode == 1) { + return $mref->[$addr]; + } +} + + + +sub run { + my ($mref, $iref) = @_; + my @mem = @$mref; + my @inputs = @$iref; + my $pc = 0; + while (1) { + my $opcode = $mem[$pc]; + my $op = int($opcode % 100); + my $m1 = int($opcode / 100) % 10; + my $m2 = int($opcode / 1000) % 10; + if ($op == 1) { + $mem[ $mem[$pc+3] ] = m2val(\@mem, $pc+1, $m1) + + m2val(\@mem, $pc+2, $m2); + $pc += 4; + } elsif ($op == 2) { + $mem[ $mem[$pc+3] ] = m2val(\@mem, $pc+1, $m1) + * m2val(\@mem, $pc+2, $m2); + $pc += 4; + } elsif ($op == 3) { + $mem[ $mem[$pc+1] ] = shift @inputs; + $pc += 2; + } elsif ($op == 4) { + say m2val(\@mem, $pc+1, $m1); + $pc += 2; + } elsif ($op == 99) { + last; + } + } +} + +run(\@mem, [ 1 ]); diff --git a/2019/10.pl b/2019/10.pl new file mode 100755 index 0000000..61b4cf8 --- /dev/null +++ b/2019/10.pl @@ -0,0 +1,70 @@ +#!/usr/bin/perl -w + +use v5.16; + +chomp (my @mem = split /,/, <>); + +sub m2val { + my ($mref, $addr, $mode) = @_; + if ($mode == 0) { + return $mref->[ $mref->[$addr] ]; + } elsif ($mode == 1) { + return $mref->[$addr]; + } +} + + + +sub run { + my ($mref, $iref) = @_; + my @mem = @$mref; + my @inputs = @$iref; + my $pc = 0; + while (1) { + my $opcode = $mem[$pc]; + my $op = int($opcode % 100); + my $m1 = int($opcode / 100) % 10; + my $m2 = int($opcode / 1000) % 10; + if ($op == 1) { + $mem[ $mem[$pc+3] ] = m2val(\@mem, $pc+1, $m1) + + m2val(\@mem, $pc+2, $m2); + $pc += 4; + } elsif ($op == 2) { + $mem[ $mem[$pc+3] ] = m2val(\@mem, $pc+1, $m1) + * m2val(\@mem, $pc+2, $m2); + $pc += 4; + } elsif ($op == 3) { + $mem[ $mem[$pc+1] ] = shift @inputs; + $pc += 2; + } elsif ($op == 4) { + say m2val(\@mem, $pc+1, $m1); + $pc += 2; + } elsif ($op == 5) { + if (m2val(\@mem, $pc+1, $m1)) { + $pc = m2val(\@mem, $pc+2, $m2); + } else { + $pc += 3; + } + } elsif ($op == 6) { + if (!m2val(\@mem, $pc+1, $m1)) { + $pc = m2val(\@mem, $pc+2, $m2); + } else { + $pc += 3; + } + } elsif ($op == 7) { + $mem[ $mem[$pc+3] ] = + m2val(\@mem, $pc+1, $m1) + < m2val(\@mem, $pc+2, $m2) ? 1 : 0; + $pc += 4; + } elsif ($op == 8) { + $mem[ $mem[$pc+3] ] = + m2val(\@mem, $pc+1, $m1) + == m2val(\@mem, $pc+2, $m2) ? 1 : 0; + $pc += 4; + } elsif ($op == 99) { + last; + } + } +} + +run(\@mem, [ 5 ]); diff --git a/2019/11.pl b/2019/11.pl new file mode 100755 index 0000000..fb05dc9 --- /dev/null +++ b/2019/11.pl @@ -0,0 +1,29 @@ +#!/usr/bin/perl -w + +use v5.16; +use List::Util qw(sum); + +my %orb; +while (<>) { + chomp; + my @b = split /\)/; + $orb{$b[0]}{$b[1]} = 1; +} + +my %orbs; +sub walk { + my ($b, $depth) = @_; + say "walking $b at $depth"; + $orbs{$b} = $depth; + for my $x (keys %{ $orb{$b} }) { + walk($x, $depth+1); + } +} + +walk('COM', 0); +say sum values %orbs; + + + + + diff --git a/2019/12.pl b/2019/12.pl new file mode 100755 index 0000000..0a83ffd --- /dev/null +++ b/2019/12.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl -w + +use v5.16; +use List::Util qw(sum); + +my %orb; +while (<>) { + chomp; + my @b = split /\)/; + $orb{$b[0]}{$b[1]} = 1; +} + +sub walk { + my ($b, $depth) = @_; + my @rv; + $rv[0] = 0 if $b eq 'YOU'; + $rv[1] = 0 if $b eq 'SAN'; + say "walking $b at $depth, rv=", ($rv[0] // '_'), ',', ($rv[1] // '_'); + for my $x (keys %{ $orb{$b} }) { + say "$b->$x"; + my ($v1, $v2) = walk($x, $depth+1); + say "$b<-$x, rv=", ($rv[0] // '_'), ',', ($rv[1] // '_'); + $rv[0] //= $v1; + $rv[1] //= $v2; + if (defined $rv[0] && defined $rv[1]) { + say "Back at $b: $rv[0],$rv[1]"; + say $rv[0]+$rv[1] - 2; + exit 0; + } + } + $rv[0]++ if defined $rv[0]; + $rv[1]++ if defined $rv[1]; + say "returning from $b at $depth, rv=", ($rv[0] // '_'), ',', ($rv[1] // '_'); + return @rv; +} + +walk('COM', 0); + + + + + diff --git a/2019/13.pl b/2019/13.pl new file mode 100755 index 0000000..9bdf64e --- /dev/null +++ b/2019/13.pl @@ -0,0 +1,91 @@ +#!/usr/bin/perl -w + +use v5.16; + +chomp (my @mem = split /,/, <>); + +sub m2val { + my ($mref, $addr, $mode) = @_; + if ($mode == 0) { + return $mref->[ $mref->[$addr] ]; + } elsif ($mode == 1) { + return $mref->[$addr]; + } +} + +sub run { + my ($mref, $iref) = @_; + my @mem = @$mref; + my @inputs = @$iref; + my $pc = 0; + my @out; + while (1) { + my $opcode = $mem[$pc]; + my $op = int($opcode % 100); + my $m1 = int($opcode / 100) % 10; + my $m2 = int($opcode / 1000) % 10; + if ($op == 1) { + $mem[ $mem[$pc+3] ] = m2val(\@mem, $pc+1, $m1) + + m2val(\@mem, $pc+2, $m2); + $pc += 4; + } elsif ($op == 2) { + $mem[ $mem[$pc+3] ] = m2val(\@mem, $pc+1, $m1) + * m2val(\@mem, $pc+2, $m2); + $pc += 4; + } elsif ($op == 3) { + $mem[ $mem[$pc+1] ] = shift @inputs; + $pc += 2; + } elsif ($op == 4) { + push @out, m2val(\@mem, $pc+1, $m1); + $pc += 2; + } elsif ($op == 5) { + if (m2val(\@mem, $pc+1, $m1)) { + $pc = m2val(\@mem, $pc+2, $m2); + } else { + $pc += 3; + } + } elsif ($op == 6) { + if (!m2val(\@mem, $pc+1, $m1)) { + $pc = m2val(\@mem, $pc+2, $m2); + } else { + $pc += 3; + } + } elsif ($op == 7) { + $mem[ $mem[$pc+3] ] = + m2val(\@mem, $pc+1, $m1) + < m2val(\@mem, $pc+2, $m2) ? 1 : 0; + $pc += 4; + } elsif ($op == 8) { + $mem[ $mem[$pc+3] ] = + m2val(\@mem, $pc+1, $m1) + == m2val(\@mem, $pc+2, $m2) ? 1 : 0; + $pc += 4; + } elsif ($op == 99) { + last; + } + } + return @out; +} + +my $max = 0; +sub permute { + my ($remaining, $input) = @_; + for my $i (0 .. $#$remaining) { + my @nr = @$remaining; + my @in = ($nr[$i], @$input); + say "running with ", join(',', @in); + splice(@nr, $i, 1); + my @rv = run(\@mem, \@in); + if (@nr) { + permute(\@nr, \@rv); + } else { + say @rv; + $max = $rv[0] if $max < $rv[0]; + } + } +} + +permute([ 0 .. 4 ], [0]); + +say $max; + diff --git a/2019/14.pl b/2019/14.pl new file mode 100755 index 0000000..8e8388d --- /dev/null +++ b/2019/14.pl @@ -0,0 +1,160 @@ +#!/usr/bin/perl -w + +use v5.16; + +package IntComp; + +sub new { + my ($class, $mem, $inputs) = @_; + my $self = { + mem => [ @$mem ], + pc => 0, + want_input => undef, + }; + $self->{inputs} = [ @$inputs ] + if defined $inputs; + bless $self, $class; +} + +sub m2val { + my ($self, $off, $mode) = @_; + if ($mode == 0) { + return $self->{mem}->[ $self->{mem}->[$self->{pc} + $off] ]; + } elsif ($mode == 1) { + return $self->{mem}->[$self->{pc} + $off]; + } +} + +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(',', @{ $self->{mem} }); + my $op = int($opcode % 100); + my $m1 = int($opcode / 100) % 10; + my $m2 = int($opcode / 1000) % 10; + if ($op == 1) { + $mem->[ $mem->[$self->{pc}+3] ] + = m2val($self, 1, $m1) + + m2val($self, 2, $m2); + $self->{pc} += 4; + } elsif ($op == 2) { + $mem->[ $mem->[$self->{pc}+3] ] + = m2val($self, 1, $m1) + * m2val($self, 2, $m2); + $self->{pc} += 4; + } elsif ($op == 3) { + if (@{ $self->{inputs} }) { + $mem->[ $mem->[$self->{pc} + 1] ] + = shift @{ $self->{inputs} }; + $self->{pc} += 2; + } else { + $self->{want_input} = $self->{pc} + 1; + $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->[ $mem->[$self->{pc}+3] ] = + m2val($self, 1, $m1) + < m2val($self, 2, $m2) ? 1 : 0; + $self->{pc} += 4; + } elsif ($op == 8) { + $mem->[ $mem->[$self->{pc}+3] ] = + m2val($self, 1, $m1) + == m2val($self, 2, $m2) ? 1 : 0; + $self->{pc} += 4; + } elsif ($op == 99) { + return undef; + } + } +} + +package main; + +chomp (my @mem = split /,/, <>); + +my $max; +sub run_all { + my @perm = @_; + my @interps; + + for my $p (@perm) { + push @interps, IntComp->new(\@mem, [ $p ]); + } + + my $last_rv; + my $rv = 0; + ROUND: + while (1) { + say "Starting from 0"; + for my $int (@interps) { + if (defined $rv) { + $int->input($rv); + } + $rv = $int->run; + say "Interp returned ", $rv // '_'; + next ROUND if !defined $rv && $int->{want_input}; + } + if (defined $rv) { + say "Loop returned $rv"; + $last_rv = $rv; + next ROUND; + } + last if !defined $rv; + } + return $last_rv; +} + +my $max = 0; +sub permute { + my ($rem, $used) = @_; + for my $i (0 .. $#$rem) { + my @nr = @$rem; + my @in = ($nr[$i], @$used); + splice(@nr, $i, 1); + + if (@nr) { + permute(\@nr, \@in); + } else { + say "Running with perm ", join(',', @in); + my $rv = run_all(@in); + say $rv; + $max = $rv if $max < $rv; + } + } +} + +permute([ 5 .. 9 ], []); + +say $max; + diff --git a/2019/15.pl b/2019/15.pl new file mode 100755 index 0000000..38a4607 --- /dev/null +++ b/2019/15.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w + +use v5.16; + +chomp (my $data = <>); + +my @min; +my $count = 25*6; +for my $l ($data =~ /.{$count}/g) { + say $l; + my @x; + $x[0] = () = $l =~ /0/g; + $x[1] = () = $l =~ /1/g; + $x[2] = () = $l =~ /2/g; + @min = @x + if !defined $min[0] || $min[0] > $x[0]; +} + +say $min[1] * $min[2]; diff --git a/2019/16.pl b/2019/16.pl new file mode 100755 index 0000000..79a272d --- /dev/null +++ b/2019/16.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl -w + +use v5.16; + +chomp (my $data = <>); + +my @min; +my $count = 25*6; +my @p; +for my $l ($data =~ /.{$count}/g) { + my @px = split //, $l; + my @p1; + for (@px) { + my $p0 = shift @p; + push @p1, !defined $p0 || $p0 == 2 ? $_ : $p0; + } + @p = @p1; + say "---"; +} + +my $i = 0; +for (@p) { + print $_ ? '#' : ' '; + print "\n" if ++$i % 25 == 0; +} diff --git a/2019/17.pl b/2019/17.pl new file mode 100755 index 0000000..2fb88f6 --- /dev/null +++ b/2019/17.pl @@ -0,0 +1,128 @@ +#!/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 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 $comp = IntComp->new(\@mem, [1]); +print $_,'_' while defined ($_ = $comp->run); +print "\n"; + + + diff --git a/2019/18.pl b/2019/18.pl new file mode 100755 index 0000000..7e1c0ca --- /dev/null +++ b/2019/18.pl @@ -0,0 +1,128 @@ +#!/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 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 $comp = IntComp->new(\@mem, [2]); +print $_,'_' while defined ($_ = $comp->run); +print "\n"; + + + diff --git a/2019/19.pl b/2019/19.pl new file mode 100755 index 0000000..8755717 --- /dev/null +++ b/2019/19.pl @@ -0,0 +1,73 @@ +#!/usr/bin/perl -w + +use v5.16; + +my %m; +$; = ','; +my $y = 0; +my ($maxx, $maxy); +while (<>) { + chomp; + my $x = 0; + $maxx = length; + for my $c (split //) { + $m{$x,$y}++ if $c eq '#'; + $x++; + } + $y++; +} +$maxy = $y; + +my %gcd; +sub gcd { + my ($n1, $n2) = @_; + return $gcd{$n1,$n2} //= + $n1 == $n2 ? $n1 + : $n1 > $n2 ? gcd($n2, $n1-$n2) + : gcd($n1, $n2-$n1); +} + +my %dir; +sub dir1 { + my ($x, $y) = @_; + return (0, 1) if $x == 0 && $y > 0; + return (0,-1) if $x == 0 && $y < 0; + return (1, 0) if $y == 0 && $x > 0; + return (-1,0) if $y == 0 && $x < 0; + my $g = gcd(abs($x), abs($y)); + return ($x/$g, $y/$g); +} + +sub dir { + my ($x, $y) = @_; + $dir{$x,$y} //= [ dir1($x,$y) ]; + return @{ $dir{$x,$y} }; +} + +my %sum; +for (keys %m) { + my ($x,$y) = split /,/; + ASTEROID: + for (keys %m) { + my ($ax, $ay) = split /,/; + next if $ax == $x && $ay == $y; + say "testing $ax,$ay from $x,$y"; + my ($dx, $dy) = dir($ax-$x, $ay-$y); + # next if $tried_dir{$dx,$dy}++; + say "dx,dy=$dx,$dy"; + my ($x0, $y0) = ($x+$dx, $y+$dy); + while ($x0 != $ax || $y0 != $ay) { + say "x0,y0=$x0,$y0"; + if ($m{$x0,$y0}) { + say "$ax,$ay cannot be seen from $x,$y because of $x0,$y0"; + next ASTEROID; + } + $x0 += $dx; $y0 += $dy; + } + say "$ax,$ay CAN be seen from $x,$y"; + $sum{$x,$y}++; + } +} + +my @s = sort { $sum{$b} <=> $sum{$a} } keys %sum; +say $s[0], '=', $sum{$s[0]}; diff --git a/2019/20.pl b/2019/20.pl new file mode 100755 index 0000000..d34db6f --- /dev/null +++ b/2019/20.pl @@ -0,0 +1,124 @@ +#!/usr/bin/perl -w + +use v5.16; + +my %m; +$; = ','; +my $y = 0; +my ($maxx, $maxy); +while (<>) { + chomp; + my $x = 0; + $maxx = length; + for my $c (split //) { + $m{$x,$y}++ if $c eq '#'; + $x++; + } + $y++; +} +$maxy = $y; + +my %gcd; +sub gcd { + my ($n1, $n2) = @_; + return $gcd{$n1,$n2} //= + $n1 == $n2 ? $n1 + : $n1 > $n2 ? gcd($n2, $n1-$n2) + : gcd($n1, $n2-$n1); +} + +my %dir; +sub dir1 { + my ($x, $y) = @_; + return (0, 1) if $x == 0 && $y > 0; + return (0,-1) if $x == 0 && $y < 0; + return (1, 0) if $y == 0 && $x > 0; + return (-1,0) if $y == 0 && $x < 0; + my $g = gcd(abs($x), abs($y)); + return ($x/$g, $y/$g); +} + +sub dir { + my ($x, $y) = @_; + $dir{$x,$y} //= [ dir1($x,$y) ]; + return @{ $dir{$x,$y} }; +} + +my $max_sum; +my $max_pos; +my @max_dirs; +for (keys %m) { + my ($x,$y) = split /,/; + my $sum; + my @dirs; + ASTEROID: + for (keys %m) { + my ($ax, $ay) = split /,/; + next if $ax == $x && $ay == $y; + # say "testing $ax,$ay from $x,$y"; + my ($dx, $dy) = dir($ax-$x, $ay-$y); + # next if $tried_dir{$dx,$dy}++; + # say "dx,dy=$dx,$dy"; + my ($x0, $y0) = ($x+$dx, $y+$dy); + while ($x0 != $ax || $y0 != $ay) { + # say "x0,y0=$x0,$y0"; + if ($m{$x0,$y0}) { + # say "$ax,$ay cannot be seen from $x,$y because of $x0,$y0"; + next ASTEROID; + } + $x0 += $dx; $y0 += $dy; + } + # say "$ax,$ay CAN be seen from $x,$y"; + push @dirs, [$dx, $dy]; + $sum++; + } + if (!defined $max_sum || $max_sum < $sum) { + $max_sum = $sum; + $max_pos = "$x,$y"; + @max_dirs = @dirs; + } +} + +say $max_pos, '=', $max_sum; + +my $x; +($x, $y) = split /,/, $max_pos; +my @dirs = ( + (grep { $_->[0] == 0 && $_->[1] < 0 } @max_dirs), + (sort { $b->[0]/$b->[1] <=> $a->[0]/$a->[1] } + grep { $_->[0] > 0 && $_->[1] < 0 } @max_dirs), + (grep { $_->[0] > 0 && $_->[1] == 0 } @max_dirs), + (sort { $b->[0]/$b->[1] <=> $a->[0]/$a->[1] } + grep { $_->[0] > 0 && $_->[1] > 0 } @max_dirs), + (grep { $_->[0] == 0 && $_->[1] > 0 } @max_dirs), + (sort { $b->[0]/$b->[1] <=> $a->[0]/$a->[1] } + grep { $_->[0] < 0 && $_->[1] > 0 } @max_dirs), + (grep { $_->[0] < 0 && $_->[1] == 0 } @max_dirs), + (sort { $b->[0]/$b->[1] <=> $a->[0]/$a->[1] } + grep { $_->[0] < 0 && $_->[1] < 0 } @max_dirs), +); + + +my %seen; +my $count; +my %skip_dir; +while (1) { + for my $dir (@dirs) { + my ($dx,$dy) = @$dir; + next if $skip_dir{$dx,$dy}; + #say "dir $dx,$dy"; + my ($x0, $y0) = ($x + $dx, $y + $dy); + while ($x0 >= 0 && $y0 >= 0 && $x0 < $maxx && $y0 < $maxy) { + if (!$seen{$x0,$y0} && $m{$x0,$y0}) { + $seen{$x0,$y0} = 1; + say ++$count, " at $x0,$y0 dir $dx,$dy (", 100*$x0+$y0, ")"; + exit 0 if $count == 200; + goto OUT; + } + $x0 += $dx; $y0 += $dy; + } + $skip_dir{$dx,$dy}=1; + OUT: + } +} + diff --git a/2019/21.pl b/2019/21.pl new file mode 100755 index 0000000..f4842d3 --- /dev/null +++ b/2019/21.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 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 @dirs = ([0, -1], [1, 0], [0, 1], [-1, 0]); +my ($x, $y, $dir) = (0, 0, 0); +my %board; +my $comp = IntComp->new(\@mem, [ 0 ]); + +while (1) { + my $rv; + while (1) { + $rv = $comp->run; + last if !$comp->{want_input}; + $comp->input($board{$x,$y} ? 1 : 0); + } + last if !defined $rv; + $board{$x,$y} = $rv; + say "Painted $x,$y = $rv"; + while (1) { + $rv = $comp->run; + last if !$comp->{want_input}; + $comp->input($board{$x,$y} ? 1 : 0); + } + last if !defined $rv; + if ($rv) { + $dir++; + $dir = 0 if $dir > 3; + } else { + $dir--; + $dir = 3 if $dir < 0; + } + $x += $dirs[$dir]->[0]; + $y += $dirs[$dir]->[1]; + say "rotated ", $rv ? 'right' : 'left', " and moved to $x, $y"; +} + +say "painted ", scalar keys %board, " fields"; + + diff --git a/2019/22.pl b/2019/22.pl new file mode 100755 index 0000000..581ac56 --- /dev/null +++ b/2019/22.pl @@ -0,0 +1,169 @@ +#!/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 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 @dirs = ([0, -1], [1, 0], [0, 1], [-1, 0]); +my ($x, $y, $dir) = (0, 0, 0); +my %board = ("0,0" => 1); +my $comp = IntComp->new(\@mem, [ 1 ]); + +my ($minx, $maxx, $miny, $maxy); +while (1) { + my $rv; + while (1) { + $rv = $comp->run; + last if !$comp->{want_input}; + $comp->input($board{$x,$y} ? 1 : 0); + } + last if !defined $rv; + $board{$x,$y} = $rv; + say "Painted $x,$y = $rv"; + while (1) { + $rv = $comp->run; + last if !$comp->{want_input}; + $comp->input($board{$x,$y} ? 1 : 0); + } + last if !defined $rv; + if ($rv) { + $dir++; + $dir = 0 if $dir > 3; + } else { + $dir--; + $dir = 3 if $dir < 0; + } + $x += $dirs[$dir]->[0]; + $y += $dirs[$dir]->[1]; + $minx = $x if !defined $minx || $minx > $x; + $miny = $y if !defined $miny || $miny > $y; + $maxx = $x if !defined $maxx || $maxx < $x; + $maxy = $y if !defined $maxy || $maxy < $y; + say "rotated ", $rv ? 'right' : 'left', " and moved to $x, $y"; +} + +say "x=$minx..$maxx, y=$miny..$maxy"; +for $y ($miny .. $maxy) { + for $x ($minx .. $maxx) { + print $board{$x,$y} ? '#' : ' '; + } + print "\n"; +} + diff --git a/2019/23.pl b/2019/23.pl new file mode 100755 index 0000000..64d1d68 --- /dev/null +++ b/2019/23.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl -w + +use v5.16; +use Data::Dumper; + +my (@m, @v); +while (<>) { + my @row = /-?\d+/g; + push @m, [ @row ]; + push @v, [ 0, 0, 0]; +} + +for (1 .. 1000) { + for my $m1 (0 .. $#m) { + for my $m2 (0 .. $#m) { + next if $m1 == $m2; + for my $c (0 .. 2) { + $v[$m1][$c]++ if $m[$m1][$c] < $m[$m2][$c]; + $v[$m1][$c]-- if $m[$m1][$c] > $m[$m2][$c]; + } + } } + for my $m1 (0 .. $#m) { + for my $c (0 .. 2) { + $m[$m1][$c] += $v[$m1][$c]; + } + } + print Dumper \@m, \@v; +} + +my $sum; +for my $m1 (0 .. $#m) { + my ($pot, $kin); + for my $c (0 .. 2) { + $pot += abs($m[$m1][$c]); + $kin += abs($v[$m1][$c]); + } + $sum += $pot*$kin; +} + +say $sum; + + + diff --git a/2019/24.pl b/2019/24.pl new file mode 100755 index 0000000..326e8c3 --- /dev/null +++ b/2019/24.pl @@ -0,0 +1,69 @@ +#!/usr/bin/perl -w + +use v5.16; +use Data::Dumper; + +my (@m, @v); +while (<>) { + my @row = /-?\d+/g; + push @m, [ @row ]; + push @v, [ 0, 0, 0]; +} + +my @states; +my $rep = 0; +my @reps; +my $i = 0; +while (1) { + for my $m1 (0 .. $#m) { + for my $m2 (0 .. $#m) { + next if $m1 == $m2; + for my $c (0 .. 2) { + $v[$m1][$c]++ if $m[$m1][$c] < $m[$m2][$c]; + $v[$m1][$c]-- if $m[$m1][$c] > $m[$m2][$c]; + } + } } + for my $m1 (0 .. $#m) { + for my $c (0 .. 2) { + $m[$m1][$c] += $v[$m1][$c]; + } + } + for my $c (0 .. 2) { + next if $reps[$c]; + my $state = join(',', (map { $_->[$c] } @m), (map { $_->[$c] } @v)); + next unless $states[$c]->{$state}++; + $reps[$c] = $i; + $rep++; + } + last if $rep > 2; + $i++; +} + +sub gcd { + my ($n1, $n2) = @_; + while ($n1 != $n2) { + ($n1, $n2) = ($n2, $n1) if $n1 < $n2; + $n1 -= $n2; + } + return $n1; +} + +say "reps: ", join(',', @reps); +my $m = $reps[0]*$reps[1]/gcd($reps[0], $reps[1]); +$m = $m*$reps[2]/gcd($m, $reps[2]); +say $m; + +my $sum; +for my $m1 (0 .. $#m) { + my ($pot, $kin); + for my $c (0 .. 2) { + $pot += abs($m[$m1][$c]); + $kin += abs($v[$m1][$c]); + } + $sum += $pot*$kin; +} + +say $sum; + + + diff --git a/2019/25.pl b/2019/25.pl new file mode 100755 index 0000000..05d69cf --- /dev/null +++ b/2019/25.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl -w +#!/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 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 %m; +my @out; + +my $comp = IntComp->new(\@mem); +while (defined(my $rv = $comp->run)) { + push @out, $rv; + if (@out == 3) { + $m{$out[0],$out[1]} = $out[2]; + @out = (); + } +} + +say scalar grep { $_ == 2 } values %m; + diff --git a/2019/26.pl b/2019/26.pl new file mode 100755 index 0000000..836eb9f --- /dev/null +++ b/2019/26.pl @@ -0,0 +1,172 @@ +#!/usr/bin/perl -w +#!/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 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 %m; +my @out; +my ($maxx, $maxy); + +$mem[0] = 2; +my $comp = IntComp->new(\@mem); + +my @chars = (' ', '#', 'x', '=', 'o'); +my ($p_x, $b_x, $b_dir); +my $score; +while (1) { + $b_dir = 1; + while (defined(my $rv = $comp->run)) { + push @out, $rv; + if (@out == 3) { + if ($out[0] == -1 && $out[1] == 0) { + $score = $out[2]; + say "Score: $score"; + } else { + $maxx = $out[0] if !defined $maxx || $maxx < $out[0]; + $maxy = $out[1] if !defined $maxy || $maxy < $out[1]; + $m{$out[0],$out[1]} = $out[2]; + $b_x = $out[0] if $out[2] == 4; + $p_x = $out[0] if $out[2] == 3; + } + @out = (); + } + } + last if !$comp->{want_input}; + for my $y (0 .. $maxy) { + for my $x (0 .. $maxx) { + print $chars[ $m{$x,$y} // 0 ]; + } + print "\n"; + } + print "\n"; + if ($p_x > $b_x) { + $comp->input(-1); + } elsif ($p_x < $b_x) { + $comp->input(1); + } else { + $comp->input(0); + } +} + +say "Final score: $score"; + diff --git a/2019/27.pl b/2019/27.pl new file mode 100755 index 0000000..6c4764c --- /dev/null +++ b/2019/27.pl @@ -0,0 +1,51 @@ +#!/usr/bin/perl -w + +use v5.16; +use Data::Dumper; +use List::Util qw(any); + +my %rules; +while (<>) { + chomp; + my ($srcs, $dstcount, $dst) = /(.*) => (\d+) (\w+)/; + my %srcs = reverse $srcs =~ /(\d+) (\w+)/g; + $rules{$dst} = { + count => $dstcount, + srcs => \%srcs, + }; +} + +my (%want, %have); +$want{FUEL} = 1; + +use List::Util qw(first); + +my $expanded; +while (my $w = first { $_ ne 'ORE' && $want{$_} } keys %want) { + $expanded = 1; + my $r = $rules{$w}; + my $rcount = int (($want{$w}+$r->{count}-1)/$r->{count}); + say "want $want{$w} of $w, rule has $r->{count}, need $rcount rules"; + if ($rcount * $r->{count} > $want{$w}) { + $have{$w} = $rcount * $r->{count} - $want{$w}; + } + delete $want{$w}; + for my $src (keys %{ $r->{srcs} }) { + my $need = $r->{srcs}->{$src} * $rcount; + if ($have{$src}) { + if ($need >= $have{$src}) { + $need -= $have{$src}; + delete $have{$src}; + } else { + $have{$src} -= $need; + next; + } + } + $want{$src} += $need; + } + say "want: ", join(', ', map { "$want{$_} of $_" } keys %want); + say "have: ", join(', ', map { "$have{$_} of $_" } keys %have); + say ""; +} + +say $want{ORE}; diff --git a/2019/28.pl b/2019/28.pl new file mode 100755 index 0000000..c13b528 --- /dev/null +++ b/2019/28.pl @@ -0,0 +1,70 @@ +#!/usr/bin/perl -w + +use v5.16; +use Data::Dumper; +use List::Util qw(any); + +my %rules; +while (<>) { + chomp; + my ($srcs, $dstcount, $dst) = /(.*) => (\d+) (\w+)/; + my %srcs = reverse $srcs =~ /(\d+) (\w+)/g; + $rules{$dst} = { + count => $dstcount, + srcs => \%srcs, + }; +} + +use List::Util qw(first); + +sub fuel_from_ore { + my $fuel = shift; + + my (%want, %have); + $want{FUEL} = $fuel; + while (my $w = first { $_ ne 'ORE' && $want{$_} } keys %want) { + my $r = $rules{$w}; + my $rcount = int (($want{$w}+$r->{count}-1)/$r->{count}); + # say "want $want{$w} of $w, rule has $r->{count}, need $rcount rules"; + if ($rcount * $r->{count} > $want{$w}) { + $have{$w} = $rcount * $r->{count} - $want{$w}; + } + delete $want{$w}; + for my $src (keys %{ $r->{srcs} }) { + my $need = $r->{srcs}->{$src} * $rcount; + if ($have{$src}) { + if ($need >= $have{$src}) { + $need -= $have{$src}; + delete $have{$src}; + } else { + $have{$src} -= $need; + next; + } + } + $want{$src} += $need; + } + # say "want: ", join(', ', map { "$want{$_} of $_" } keys %want); + # say "have: ", join(', ', map { "$have{$_} of $_" } keys %have); + # say ""; + } + return $want{ORE}; +} + +my $low = fuel_from_ore(1); +say $low; +my $high = $low; + +my $max_ore = 1_000_000_000_000; +$high *= 2 while fuel_from_ore($high) <= $max_ore; + +my $now; +do { + $now = int(($high + $low) / 2); + if (fuel_from_ore($now) <= $max_ore) { + $low = $now; + } else { + $high = $now; + } +} while ($low + 1 < $high); + +say $low; diff --git a/2019/get.sh b/2019/get.sh new file mode 100755 index 0000000..68b3188 --- /dev/null +++ b/2019/get.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +DAY=`date +%e|sed 's/ //g'` +test -n "$1" && DAY="$1" +FILE="$((2*DAY - 1))in.txt" +COOKIE=`cat cookie` + +START="6:00:02" +MAXWAIT=300 +STARTSEC=`date -d "$START" "+%s"` +NOW=`date "+%s"` +WAITSEC=`expr $STARTSEC - $NOW` + +if [ $WAITSEC -gt 0 -a $WAITSEC -lt $MAXWAIT ] +then + echo "Waiting for $WAITSEC seconds till $START for getting $FILE ..." + sleep $WAITSEC +fi + +URL="https://adventofcode.com/2019/day/$DAY/input" +echo +echo "Downloading $URL to $FILE" +curl -s -b "$COOKIE" "$URL" --output "$FILE" +echo ======================================================================== +cat "$FILE" +echo ======================================================================== +echo "lines words chars" +wc "$FILE" +echo