days 5-11

This commit is contained in:
Ben Charlton 2018-12-11 21:39:38 +00:00
parent d3ae65f625
commit 1d2d5def97
18 changed files with 804 additions and 0 deletions

72
10/1.pl Normal file
View file

@ -0,0 +1,72 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
my (@cx, @cy, @vx, @vy);
foreach my $line (@data) {
# position=< 9, 1> velocity=< 0, 2>
my ($x, $y, $vx, $vy) =
($line =~ m/position=<\s*(-?\d+),\s*(-?\d+)> velocity=<\s*(-?\d+),\s*(-?\d+)>/);
say "$x,$y - $vx,$vy";
push @cx, $x;
push @cy, $y;
push @vx, $vx;
push @vy, $vy;
}
my $count = 0;
my $triggered = 0;
while () {
$count++;
my %sumY;
for (my $i = 0; $i <= $#cx; $i++) {
$cx[$i] += $vx[$i];
$cy[$i] += $vy[$i];
$sumY{$cy[$i]}++;
#say "$i $cx[$i],$cy[$i]";
}
my @most = sort { $sumY{$b} <=> $sumY{$a} } keys %sumY;
if ($sumY{$most[0]} > 14 || $triggered) {
say "count: $count";
$triggered = 1;
sleep 1;
my $minx = 999999999;
my $miny = 999999999;
my $maxx = 0;
my $maxy = 0;
for (my $i = 0; $i <= $#cx; $i++) {
($minx = $cx[$i]) if ($cx[$i] < $minx);
($miny = $cy[$i]) if ($cy[$i] < $miny);
($maxx = $cx[$i]) if ($cx[$i] > $maxx);
($maxy = $cy[$i]) if ($cy[$i] > $maxy);
}
my %render;
for (my $i = 0; $i <= $#cx; $i++) {
$cx[$i] -= $minx;
$cy[$i] -= $miny;
#say "$cx[$i], $cy[$i]";
$render{"$cx[$i],$cy[$i]"}=1;
}
for (my $y = 0; $y <= ($maxy-$miny); $y++) {
for (my $x = 0; $x <= ($maxx-$minx); $x++) {
if ($render{"$x,$y"}) {
print "#";
} else {
print " ";
}
}
print "\n";
}
}
}

31
10/sample.txt Normal file
View file

@ -0,0 +1,31 @@
position=< 9, 1> velocity=< 0, 2>
position=< 7, 0> velocity=<-1, 0>
position=< 3, -2> velocity=<-1, 1>
position=< 6, 10> velocity=<-2, -1>
position=< 2, -4> velocity=< 2, 2>
position=<-6, 10> velocity=< 2, -2>
position=< 1, 8> velocity=< 1, -1>
position=< 1, 7> velocity=< 1, 0>
position=<-3, 11> velocity=< 1, -2>
position=< 7, 6> velocity=<-1, -1>
position=<-2, 3> velocity=< 1, 0>
position=<-4, 3> velocity=< 2, 0>
position=<10, -3> velocity=<-1, 1>
position=< 5, 11> velocity=< 1, -2>
position=< 4, 7> velocity=< 0, -1>
position=< 8, -2> velocity=< 0, 1>
position=<15, 0> velocity=<-2, 0>
position=< 1, 6> velocity=< 1, 0>
position=< 8, 9> velocity=< 0, -1>
position=< 3, 3> velocity=<-1, 1>
position=< 0, 5> velocity=< 0, -1>
position=<-2, 2> velocity=< 2, 0>
position=< 5, -2> velocity=< 1, 2>
position=< 1, 4> velocity=< 2, 1>
position=<-2, 7> velocity=< 2, -2>
position=< 3, 6> velocity=<-1, -1>
position=< 5, 0> velocity=< 1, 0>
position=<-6, 0> velocity=< 2, 0>
position=< 5, 9> velocity=< 1, -2>
position=<14, 7> velocity=<-2, 0>
position=<-3, 6> velocity=< 2, -1>

53
11/1.pl Normal file
View file

@ -0,0 +1,53 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
sub get_grid ($) {
my $serial = shift;
my @grid;
foreach my $y (1..300) {
my @x;
foreach my $x (1..300) {
my $pl = ((($x+10)*$y)+$serial)*($x+10);
$pl = (($pl / 100) % 10)-5;
push @x, $pl;
}
push @grid, \@x
}
return @grid;
}
#122,79, grid serial number 57: power level -5.
#my @grid=get_grid(57);
#say $grid[78][121];
#217,196, grid serial number 39: power level 0.
#@grid=get_grid(39);
#say $grid[195][216];
#101,153, grid serial number 71: power level 4.
#@grid=get_grid(71);
#say $grid[152][100];
my $serial = $ARGV[0];
my @grid = get_grid($serial);
my $biglytotal = -9999;
my $coords;
for (my $y=2; $y < 299; $y++) {
for (my $x=2; $x < 299; $x++) {
my $total = $grid[$y-1][$x-1] + $grid[$y-1][$x] + $grid[$y-1][$x+1] +
$grid[$y][$x-1] + $grid[$y][$x] + $grid[$y][$x+1] +
$grid[$y+1][$x-1] + $grid[$y+1][$x] + $grid[$y+1][$x+1];
if ($total > $biglytotal) {
$biglytotal = $total;
$coords = "$x,$y";
}
}
}
say $coords;

74
11/2.pl Normal file
View file

@ -0,0 +1,74 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
my $serial = $ARGV[0];
my $maxsize = 300;
my @sat = get_grid($serial);
# calculate summed area table
for (my $y=0; $y < $maxsize; $y++) {
for (my $x=0; $x < $maxsize; $x++) {
my $tmp = $sat[$y][$x];
if (($y > 0) && ($x > 0)) {
$tmp -= $sat[$y-1][$x-1];
}
if ($y > 0) {
$tmp += $sat[$y-1][$x];
}
if ($x > 0) {
$tmp += $sat[$y][$x-1];
}
$sat[$y][$x] = $tmp;
}
}
my $biglytotal = -9999;
my $coords;
my $maxgs;
for (my $gridsize=1; $gridsize < 300; $gridsize++) {
for (my $y=0; $y < ($maxsize-$gridsize); $y++) {
for (my $x=0; $x < ($maxsize-$gridsize); $x++) {
my $total = get_total(\@sat, $x, $y, $gridsize);
if ($total > $biglytotal) {
$biglytotal = $total;
$coords = "result:" . ($x+2) . "," . ($y+2);
$maxgs = $gridsize;
}
}
}
}
say $coords, ",", $maxgs;
sub get_total {
my ($table, $x, $y, $gridsize) = @_;
return $$table[$y+$gridsize][$x+$gridsize] + $$table[$y][$x]
- $$table[$y][$x+$gridsize] - $$table[$y+$gridsize][$x];
}
sub get_grid ($) {
my $serial = shift;
my @grid;
foreach my $y (1..300) {
my @x;
foreach my $x (1..300) {
my $pl = ((($x+10)*$y)+$serial)*($x+10);
$pl = (($pl / 100) % 10)-5;
push @x, $pl;
}
push @grid, \@x
}
return @grid;
}

23
5/1-2.pl Normal file
View file

@ -0,0 +1,23 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
@data = sort @data;
my @remove;
foreach my $c ('a'..'z') {
push @remove, ($c . uc($c)), (uc($c) . $c);
}
my $remove = join("|", @remove);
foreach my $line (@data) {
say $line;
while ( $line =~ s/($remove)//ge ) {
}
say $line . " " . length($line);
}

37
5/1.pl Normal file
View file

@ -0,0 +1,37 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
@data = sort @data;
foreach my $line (@data) {
say $line;
my @line = split //, $line;
my $pos = 0;
say $pos, "/", $#line;
while ( $pos < $#line ) {
if (($line[$pos] =~ m/[A-Z]/) && ( lc($line[$pos]) eq $line[$pos+1] )
|| ($line[$pos] =~ m/[a-z]/) && ( uc($line[$pos]) eq $line[$pos+1] )) {
#say "Cancelling ", $line[$pos], $line[$pos+1];
# Urgh, this is slow.
if ($pos > 0) {
@line = (@line[ 0..$pos-1 ], @line[ $pos+2 .. $#line ]);
} else {
@line = @line[ $pos+2 .. $#line ];
}
$pos--;
} else {
$pos++;
}
}
say join("", @line);
print ($#line + 1);
}

34
5/2.pl Normal file
View file

@ -0,0 +1,34 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
@data = sort @data;
my @remove;
foreach my $c ('a'..'z') {
push @remove, ($c . uc($c)), (uc($c) . $c);
}
my $remove = join("|", @remove);
foreach my $line (@data) {
say $line;
my $min = length($line);
foreach my $c ('a'..'z') {
my $test = $line;
say $test . " " . length($test);
my $pre = $c . "|" . uc($c);
$test =~ s/($pre)//ge;
while ( $test =~ s/($remove)//ge ) {
}
if (length($test) < $min) {
$min = length($test);
}
say $pre . " " . $test . " " . length($test);
}
say $min;
}

1
5/sample.txt Normal file
View file

@ -0,0 +1 @@
dabAcCaCBAcCcaDA

83
6/1.pl Normal file
View file

@ -0,0 +1,83 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
@data = sort @data;
my (@x, @y);
foreach my $coord (@data) {
my ($x, $y) = split /, /, $coord;
push @x, $x;
push @y, $y;
}
@x = sort { $a <=> $b } @x;
@y = sort { $a <=> $b } @y;
my $minX = $x[0];
my $minY = $y[0];
my $maxX = $x[$#x];
my $maxY = $y[$#y];
my %infinite;
my %count;
for ( my $y = $minY; $y <= $maxY; $y++ ) {
for ( my $x = $minX; $x <= $maxX; $x++ ) {
# work out distances
my $closest = closest($x, $y, \@data);
$count{$closest}++;
#say "$x, $y, ", $closest;
# establish 'infinite' areas
if ( $closest && (($x == $minX) || ($x == $maxX)
|| ($y == $minY) || ($y == $maxY)) ) {
$infinite{$closest}++
}
}
}
my @best = sort { $count{$b} <=> $count{$a} } keys %count;
foreach my $b (@best) {
if ($infinite{$b}) {
next;
} else {
say "$b $count{$b}";
exit;
}
}
sub closest($$$) {
my ($x, $y, $coords) = @_;
my %result;
foreach my $c (@$coords) {
my ($cx, $cy) = split /, /, $c;
my ($xdiff, $ydiff);
if ($x < $cx) {
$xdiff = $cx - $x;
} else {
$xdiff = $x - $cx;
}
if ($y < $cy) {
$ydiff = $cy - $y;
} else {
$ydiff = $y - $cy;
}
$result{$c} = ($xdiff + $ydiff);
}
my @best = sort { $result{$a} <=> $result{$b} } keys %result;
if ($result{$best[0]} == $result{$best[1]}) {
return undef;
} else {
return $best[0];
}
}

64
6/2.pl Normal file
View file

@ -0,0 +1,64 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
@data = sort @data;
my (@x, @y);
foreach my $coord (@data) {
my ($x, $y) = split /, /, $coord;
push @x, $x;
push @y, $y;
}
@x = sort { $a <=> $b } @x;
@y = sort { $a <=> $b } @y;
my $minX = $x[0];
my $minY = $y[0];
my $maxX = $x[$#x];
my $maxY = $y[$#y];
my $count;
for ( my $y = $minY; $y <= $maxY; $y++ ) {
for ( my $x = $minX; $x <= $maxX; $x++ ) {
# work out distances
my $closest = closest($x, $y, \@data);
# this assumes there's only a single region, but that seems to be the case here.
if ($closest < 10000) {
$count++;
}
}
}
say $count;
sub closest($$$) {
my ($x, $y, $coords) = @_;
my $result;
foreach my $c (@$coords) {
my ($cx, $cy) = split /, /, $c;
my ($xdiff, $ydiff);
if ($x < $cx) {
$xdiff = $cx - $x;
} else {
$xdiff = $x - $cx;
}
if ($y < $cy) {
$ydiff = $cy - $y;
} else {
$ydiff = $y - $cy;
}
$result += ($xdiff + $ydiff);
}
return $result;
}

6
6/sample.txt Normal file
View file

@ -0,0 +1,6 @@
1, 1
1, 6
8, 3
3, 4
5, 5
8, 9

66
7/1.pl Normal file
View file

@ -0,0 +1,66 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
my %deps;
my %steps;
foreach my $line (sort @data) {
my ($dep, $step) = ($line =~ /Step (\S+) must be finished before step (\S+) can begin\./);
say "$dep, $step";
if (exists $deps{$step}) {
my $t = $deps{$step};
push @$t, $dep;
$deps{$step} = $t;
} else {
my @add = ($dep);
$deps{$step} = \@add;
}
$steps{$dep}=0;
$steps{$step}=0;
}
my @final;
while (my @doable = find_nextsteps(\%deps) ) {
my $first = $doable[0];
mark_complete($first, \%deps);
push @final, $first;
}
say join "", @final;
sub mark_complete {
my ($step, $deps) = @_;
# complete task.
$steps{$step} = 1;
# remove from dep list.
foreach my $s (sort keys %$deps) {
my @tasks = @{$$deps{$s}};
@tasks = grep {!/$step/} @tasks;
if ($#tasks > -1) {
$$deps{$s} = \@tasks;
} else {
delete $$deps{$s};
}
}
}
sub find_nextsteps {
my ($deps) = @_;
# find next.
my @doable;
foreach my $s (sort keys %steps) {
next if ($steps{$s} == 1);
if (!$$deps{$s}) {
push @doable, $s;
}
}
return sort @doable;
}

110
7/2.pl Normal file
View file

@ -0,0 +1,110 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
my $timeoffset = 60;
my $workers = 5;
# set up time delay...
my %time;
foreach my $n ('A'..'Z') {
$time{$n} = $timeoffset + ord($n)-64;
}
chomp (my @data = <STDIN>);
my %deps;
my %steps;
foreach my $line (sort @data) {
my ($dep, $step) = ($line =~ /Step (\S+) must be finished before step (\S+) can begin\./);
say "$dep, $step";
if (exists $deps{$step}) {
my $t = $deps{$step};
push @$t, $dep;
$deps{$step} = $t;
} else {
my @add = ($dep);
$deps{$step} = \@add;
}
$steps{$dep}=0;
$steps{$step}=0;
}
my @final;
my %workercurrent;
my %workertime;
my $totaltime = 0;
while ( !check_complete() ) {
my @doable = find_nextsteps(\%deps);
foreach my $w (1...$workers) {
say "worker $w, $workercurrent{$w} $workertime{$w}";
if ($workertime{$w} <= 1 && $workercurrent{$w}) {
mark_complete($workercurrent{$w}, \%deps);
push @final, $workercurrent{$w};
$workercurrent{$w} = undef;
}
if (!$workercurrent{$w}) {
if (my $next = pop @doable) {
say "adding... w:$w t:$next";
$steps{$next} = 2;
$workercurrent{$w} = $next;
$workertime{$w} = $time{$next};
}
}
$workertime{$w}--;
}
$totaltime++;
}
say join "", @final;
say $totaltime;
sub check_complete {
foreach my $k (keys %steps) {
say "check: $k $steps{$k}";
if ($steps{$k} != 1) {
return 0;
}
}
return 1;
}
sub mark_complete {
my ($step, $deps) = @_;
# complete task.
$steps{$step} = 1;
# remove from dep list.
foreach my $s (sort keys %$deps) {
my @tasks = @{$$deps{$s}};
@tasks = grep {!/$step/} @tasks;
if ($#tasks > -1) {
$$deps{$s} = \@tasks;
} else {
delete $$deps{$s};
}
}
}
sub find_nextsteps {
my ($deps) = @_;
# find next.
my @doable;
foreach my $s (sort keys %steps) {
next if ($steps{$s} > 0);
if (!$$deps{$s}) {
push @doable, $s;
}
}
return sort @doable;
}

7
7/sample.txt Normal file
View file

@ -0,0 +1,7 @@
Step C must be finished before step A can begin.
Step C must be finished before step F can begin.
Step A must be finished before step B can begin.
Step A must be finished before step D can begin.
Step B must be finished before step E can begin.
Step D must be finished before step E can begin.
Step F must be finished before step E can begin.

46
8/1.pl Normal file
View file

@ -0,0 +1,46 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
foreach my $line (@data) {
my @list = split / /, $line;
say join ",", @list;
my $pos = 0;
my ($p, $m) = do_process(\@list, $pos);
say "$p, $m";
}
# 2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2
# A----------------------------------
# B----------- C-----------
# D-----
sub do_process {
my ($list, $pos) = @_;
my $children = $$list[$pos++];
my $metadata = $$list[$pos++];
my $mdsum;
for (my $c=0; $c<$children; $c++) {
say "child $c";
my ($p, $m) = do_process($list, $pos);
$pos = $p;
$mdsum += $m;
}
for (my $m=$pos; $m<$pos+$metadata; $m++) {
$mdsum += $$list[$m];
say "metadata: ", $$list[$m];
}
$pos += $metadata;
return ($pos, $mdsum)
}

50
8/2.pl Normal file
View file

@ -0,0 +1,50 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
chomp (my @data = <STDIN>);
foreach my $line (@data) {
my @list = split / /, $line;
my $pos = 0;
my ($p, $m) = do_process(\@list, $pos);
say "$p, $m";
}
# 2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2
# A----------------------------------
# B----------- C-----------
# D-----
sub do_process {
my ($list, $pos) = @_;
my $children = $$list[$pos++];
my $metadata = $$list[$pos++];
my $mdsum = 0;
my @children;
for (my $c=0; $c<$children; $c++) {
my ($p, $value) = do_process($list, $pos);
$pos = $p;
push @children, $value;
}
for (my $m=$pos; $m<$pos+$metadata; $m++) {
my $mval = $$list[$m];
if ($children == 0) {
$mdsum += $mval;
} else {
$mdsum += int($children[$mval-1]);
}
}
$pos += $metadata;
return ($pos, $mdsum)
}

1
8/sample.txt Normal file
View file

@ -0,0 +1 @@
2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2

46
9/1.pl Normal file
View file

@ -0,0 +1,46 @@
#!/usr/bin/perl
use strict;
use v5.10;
use Data::Dumper;
my $players = $ARGV[0];
my $score = $ARGV[1];
say "players: $players, score: $score";
my $marble = 0;
my $currentplayer = 0;
my $currentpos = 0;
my @board;
my %score;
# the splice approach isn't efficient, but it's fine for part 1.
# it takes a couple of hours to solve part 2, but I was short of time to rewrite...
while ($marble <= $score) {
if ($marble > 0 && ($marble % 23 == 0)) {
$score{$currentplayer} += $marble;
$currentpos = $currentpos - 8;
if ($currentpos < 0) {
$currentpos += (scalar @board);
}
#say "KEEP $currentplayer $marble ", $board[$currentpos];
$score{$currentplayer} += $board[$currentpos];
splice(@board,$currentpos,1);
$currentpos = ($currentpos+1) % (scalar @board);
} else {
splice(@board, $currentpos+1, 0, $marble);
$currentpos = ($currentpos+2) % (scalar @board);
}
$marble++;
#say "player: $currentplayer, pos: $currentpos, board: ", join ",", @board;
$currentplayer = ($currentplayer + 1) % $players;
}
say Dumper \%score;
my @keys = sort { $score{$b} <=> $score{$a} } keys %score;
say $score{$keys[0]};