]> www.fi.muni.cz Git - aoc.git/commitdiff
Year 2015
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 24 Nov 2022 15:54:59 +0000 (16:54 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 24 Nov 2022 15:54:59 +0000 (16:54 +0100)
56 files changed:
.gitignore
2015/01.pl [new file with mode: 0755]
2015/02.pl [new file with mode: 0755]
2015/03.pl [new file with mode: 0755]
2015/04.pl [new file with mode: 0755]
2015/05.pl [new file with mode: 0755]
2015/06.pl [new file with mode: 0755]
2015/07.pl [new file with mode: 0755]
2015/08.pl [new file with mode: 0755]
2015/09.pl [new file with mode: 0755]
2015/10.pl [new file with mode: 0755]
2015/11.pl [new file with mode: 0755]
2015/12.pl [new file with mode: 0755]
2015/13.pl [new file with mode: 0755]
2015/14.pl [new file with mode: 0755]
2015/15.pl [new file with mode: 0755]
2015/16.pl [new file with mode: 0755]
2015/17.pl [new file with mode: 0755]
2015/18.pl [new file with mode: 0755]
2015/19.pl [new file with mode: 0755]
2015/20.pl [new file with mode: 0755]
2015/21.pl [new file with mode: 0755]
2015/22.pl [new file with mode: 0755]
2015/23.pl [new file with mode: 0755]
2015/24.pl [new file with mode: 0755]
2015/25.pl [new file with mode: 0755]
2015/26.pl [new file with mode: 0755]
2015/27.pl [new file with mode: 0755]
2015/28.pl [new file with mode: 0755]
2015/29.pl [new file with mode: 0755]
2015/30.pl [new file with mode: 0755]
2015/31.pl [new file with mode: 0755]
2015/32.pl [new file with mode: 0755]
2015/33.pl [new file with mode: 0755]
2015/34.pl [new file with mode: 0755]
2015/35.pl [new file with mode: 0755]
2015/36.pl [new file with mode: 0755]
2015/37.pl [new file with mode: 0755]
2015/38.pl [new file with mode: 0755]
2015/39.pl [new file with mode: 0755]
2015/40.pl [new file with mode: 0755]
2015/41.pl [new file with mode: 0755]
2015/42.pl [new file with mode: 0755]
2015/43.pl [new file with mode: 0755]
2015/44.pl [new file with mode: 0755]
2015/45.pl [new file with mode: 0755]
2015/46.pl [new file with mode: 0755]
2015/47.pl [new file with mode: 0755]
2015/48.pl [new file with mode: 0755]
2015/49.pl [new file with mode: 0755]
2015/get.sh [new file with mode: 0755]
2015/y/38-ypgen.pl [new file with mode: 0755]
2015/y/Parser.pm [new file with mode: 0644]
2015/y/parse.pl [new file with mode: 0755]
2015/y/task38.yp [new file with mode: 0644]
2015/y/test.yp [new file with mode: 0644]

index 978c3a04636c572a08dac7212043358009df4681..68be32c53d72c406e028d454b897f3021b32b23c 100644 (file)
@@ -4,3 +4,4 @@ cache-*.json
 cookie
 id.txt
 a.out
+leaderboard
diff --git a/2015/01.pl b/2015/01.pl
new file mode 100755 (executable)
index 0000000..13738f1
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+chomp(my $in = <>);
+my $sum;
+$sum++ for $in =~ /\(/g;
+$sum-- for $in =~ /\)/g;
+say $sum;
diff --git a/2015/02.pl b/2015/02.pl
new file mode 100755 (executable)
index 0000000..65e4dee
--- /dev/null
@@ -0,0 +1,5 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
diff --git a/2015/03.pl b/2015/03.pl
new file mode 100755 (executable)
index 0000000..0cba607
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $sum;
+while (<>) {
+       chomp;
+       my @dims = sort { $a <=> $b } split /x/;
+       $sum += 3*$dims[0]*$dims[1] + 2* $dims[0]*$dims[2] + 2* $dims[1]*$dims[2];
+}
+
+say $sum;
+       
+       
diff --git a/2015/04.pl b/2015/04.pl
new file mode 100755 (executable)
index 0000000..5ec30df
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $sum;
+while (<>) {
+       chomp;
+       my @dims = sort { $a <=> $b } split /x/;
+       $sum += 2*$dims[0] + 2*$dims[1] + $dims[0]*$dims[1]*$dims[2];
+}
+
+say $sum;
+       
+       
diff --git a/2015/05.pl b/2015/05.pl
new file mode 100755 (executable)
index 0000000..270a002
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+$_ = <>;
+
+my ($x, $y) = (0, 0);
+$; = ',';
+my %seen = ("0,0" => 1);
+
+for my $v (split //) {
+       $x++ if $v eq '>';
+       $y++ if $v eq 'v';
+       $x-- if $v eq '<';
+       $y-- if $v eq '^';
+       $seen{$x,$y}++;
+}
+
+say scalar keys %seen;
+       
+
diff --git a/2015/06.pl b/2015/06.pl
new file mode 100755 (executable)
index 0000000..9980eb1
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+$_ = <>;
+
+my @x = (0, 0);
+my @y = (0, 0);
+$; = ',';
+my %seen = ("0,0" => 1);
+
+my $s = 0;
+for my $v (split //) {
+       $x[$s]++ if $v eq '>';
+       $y[$s]++ if $v eq 'v';
+       $x[$s]-- if $v eq '<';
+       $y[$s]-- if $v eq '^';
+       $seen{$x[$s],$y[$s]}++;
+       $s = 1-$s;
+}
+
+say scalar keys %seen;
+       
+
diff --git a/2015/07.pl b/2015/07.pl
new file mode 100755 (executable)
index 0000000..5c702e6
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+use Digest::MD5 qw(md5_hex);
+
+my $in = 'ckczppom';
+my $num = 0;
+$num++ while md5_hex("$in$num") !~ /^00000/;
+
+say $num;
+
diff --git a/2015/08.pl b/2015/08.pl
new file mode 100755 (executable)
index 0000000..9067d2c
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+use Digest::MD5 qw(md5_hex);
+
+my $in = 'ckczppom';
+my $num = 0;
+$num++ while md5_hex("$in$num") !~ /^000000/;
+
+say $num;
+
diff --git a/2015/09.pl b/2015/09.pl
new file mode 100755 (executable)
index 0000000..049cf10
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $sum;
+while (<>) {
+       chomp;
+       my $wov =()= /[aeiou]/g;
+       next if $wov < 3;
+       next if ! /(.)\1/;
+       next if /ab|cd|pq|xy/;
+       $sum++;
+}
+say $sum;
diff --git a/2015/10.pl b/2015/10.pl
new file mode 100755 (executable)
index 0000000..5e7be16
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $sum;
+while (<>) {
+       chomp;
+       next if ! /(..).*\1/;
+       next if ! /(.).\1/;
+       $sum++;
+}
+say $sum;
diff --git a/2015/11.pl b/2015/11.pl
new file mode 100755 (executable)
index 0000000..cbad926
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %lights;
+
+$; = ',';
+
+while (<>) {
+       my ($what, $xmin, $ymin, $xmax, $ymax) = /^(.*) (\d+),(\d+) through (\d+),(\d+)/;
+       ($xmax, $xmin) = ($xmin, $xmax) if $xmin > $xmax;
+       ($ymax, $ymin) = ($ymin, $ymax) if $ymin > $ymax;
+       for my $x ($xmin .. $xmax) {
+       for my $y ($ymin .. $ymax) {
+               if ($what eq 'toggle') {
+                       $lights{$x,$y} = !$lights{$x,$y};
+               } elsif ($what eq 'turn on') {
+                       $lights{$x,$y} = 1;
+               } elsif ($what eq 'turn off') {
+                       $lights{$x,$y} = 0;
+               }
+       } }
+}
+
+say scalar grep { $lights{$_} } keys %lights;
+
diff --git a/2015/12.pl b/2015/12.pl
new file mode 100755 (executable)
index 0000000..4cc2191
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %lights;
+
+$; = ',';
+
+while (<>) {
+       my ($what, $xmin, $ymin, $xmax, $ymax) = /^(.*) (\d+),(\d+) through (\d+),(\d+)/;
+       ($xmax, $xmin) = ($xmin, $xmax) if $xmin > $xmax;
+       ($ymax, $ymin) = ($ymin, $ymax) if $ymin > $ymax;
+       for my $x ($xmin .. $xmax) {
+       for my $y ($ymin .. $ymax) {
+               if ($what eq 'toggle') {
+                       $lights{$x,$y} += 2;
+               } elsif ($what eq 'turn on') {
+                       $lights{$x,$y}++;
+               } elsif ($what eq 'turn off') {
+                       $lights{$x,$y}-- if $lights{$x,$y};
+               }
+       } }
+}
+
+use List::Util qw(sum);
+say sum values %lights;
+
diff --git a/2015/13.pl b/2015/13.pl
new file mode 100755 (executable)
index 0000000..4f78ed0
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+use feature 'bitwise';
+
+$/ = undef;
+$_ = <> . "\n";
+
+while (1) {
+       my ($wire, $val);
+       if (s/^(\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($2, $1);
+       } elsif (s/^NOT (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($2, $1 ^ 0xFFFF);
+       } elsif (s/^(\d+) AND (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($3, $1 & $2);
+       } elsif (s/^(\d+) OR (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($3, $1 | $2);
+       } elsif (s/^(\d+) RSHIFT (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($3, $1 >> $2);
+       } elsif (s/^(\d+) LSHIFT (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($3, ($1 << $2) & 0xFFFF);
+       }
+       last if !$wire;
+       if ($wire eq 'a') {
+               say "a=$val";
+               last;
+       }
+       # say "$wire => $val";
+       last if $val !~ /\A\d+\z/;
+       $val &= 0xFFFF;
+       s/\b$wire\b/$val/g;
+       # say "$_\n\n";
+}
diff --git a/2015/14.pl b/2015/14.pl
new file mode 100755 (executable)
index 0000000..a98af3d
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+use feature 'bitwise';
+
+$/ = undef;
+$_ = <> . "\n";
+s/^.*? -> b\n/3176 -> b\n/m;
+
+while (1) {
+       my ($wire, $val);
+       if (s/^(\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($2, $1);
+       } elsif (s/^NOT (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($2, $1 ^ 0xFFFF);
+       } elsif (s/^(\d+) AND (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($3, $1 & $2);
+       } elsif (s/^(\d+) OR (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($3, $1 | $2);
+       } elsif (s/^(\d+) RSHIFT (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($3, $1 >> $2);
+       } elsif (s/^(\d+) LSHIFT (\d+) -> (\w+)\n//m) {
+               ($wire, $val) = ($3, ($1 << $2) & 0xFFFF);
+       }
+       last if !$wire;
+       if ($wire eq 'a') {
+               say "a=$val";
+               last;
+       }
+       # say "$wire => $val";
+       last if $val !~ /\A\d+\z/;
+       $val &= 0xFFFF;
+       s/\b$wire\b/$val/g;
+       # say "$_\n\n";
+}
diff --git a/2015/15.pl b/2015/15.pl
new file mode 100755 (executable)
index 0000000..f770e8f
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my ($clen, $slen) = (0, 0);
+while (<>) {
+       chomp;
+       $clen += length;
+       $slen += length eval $_;
+}
+
+say $clen - $slen;
diff --git a/2015/16.pl b/2015/16.pl
new file mode 100755 (executable)
index 0000000..3430042
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my ($clen, $slen) = (0, 0);
+while (<>) {
+       chomp;
+       $slen += length;
+       $clen += 2+length "\Q$_\E";
+       # say "$_ =>\n\Q$_\E\n\n";
+}
+
+say $clen - $slen;
diff --git a/2015/17.pl b/2015/17.pl
new file mode 100755 (executable)
index 0000000..bbe1c26
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+$; = ',';
+
+my %route;
+my %cities;
+while (<>) {
+       my ($src, $dst, $len) = /^(\w+) to (\w+) = (\d+)/;
+       $cities{$src} = $cities{$dst} = 1;
+       $route{$src,$dst} = $len;
+       $route{$dst,$src} = $len;
+}
+
+
+my $min_dist;
+sub do_perm {
+       my ($path, $dist, $rest) = @_;
+       
+       if (!@$rest) {
+               $min_dist = $dist if !$min_dist || $dist < $min_dist;
+               say "new min $min_dist";
+               return;
+       }
+       for my $i (0 .. $#$rest) {
+               my @nrest = @$rest;
+               my ($next) = splice (@nrest, $i, 1);
+               my @npath = (@$path, $next);
+               my $ndist = $dist;
+               if (@$path) {
+                       my $prev = $path->[-1];
+                       $ndist += $route{$prev,$next};
+               }
+               # say join(',', @npath), " $ndist";
+               do_perm(\@npath, $ndist, \@nrest);
+       }
+}
+
+do_perm([], 0, [ keys %cities ]);
+say $min_dist;
+
diff --git a/2015/18.pl b/2015/18.pl
new file mode 100755 (executable)
index 0000000..53f2b48
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+$; = ',';
+
+my %route;
+my %cities;
+while (<>) {
+       my ($src, $dst, $len) = /^(\w+) to (\w+) = (\d+)/;
+       $cities{$src} = $cities{$dst} = 1;
+       $route{$src,$dst} = $len;
+       $route{$dst,$src} = $len;
+}
+
+
+my $max_dist;
+sub do_perm {
+       my ($path, $dist, $rest) = @_;
+       
+       if (!@$rest) {
+               $max_dist = $dist if !$max_dist || $dist > $max_dist;
+               say "new min $max_dist";
+               return;
+       }
+       for my $i (0 .. $#$rest) {
+               my @nrest = @$rest;
+               my ($next) = splice (@nrest, $i, 1);
+               my @npath = (@$path, $next);
+               my $ndist = $dist;
+               if (@$path) {
+                       my $prev = $path->[-1];
+                       $ndist += $route{$prev,$next};
+               }
+               # say join(',', @npath), " $ndist";
+               do_perm(\@npath, $ndist, \@nrest);
+       }
+}
+
+do_perm([], 0, [ keys %cities ]);
+say $max_dist;
+
diff --git a/2015/19.pl b/2015/19.pl
new file mode 100755 (executable)
index 0000000..e12aeb5
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $in = 1321131112;
+
+for (1 .. 40) {
+       my $out = '';
+       1 while $in =~ s/^(.)(\1*)/$out .= (1+length($2)).$1;''/e;
+       say $out;
+       $in = $out;
+}
+say length $in;
+
diff --git a/2015/20.pl b/2015/20.pl
new file mode 100755 (executable)
index 0000000..36005a6
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $in = 1321131112;
+
+for (1 .. 50) {
+       my $out = '';
+       1 while $in =~ s/^(.)(\1*)/$out .= (1+length($2)).$1;''/e;
+       say $out, " iter $_";
+       $in = $out;
+}
+say length $in;
+
diff --git a/2015/21.pl b/2015/21.pl
new file mode 100755 (executable)
index 0000000..90875ab
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $in = 'cqjxjnds';
+
+NUMBER:
+while (1) {
+       my @l = split //, $in;
+       my $n = $#l;
+       while ($l[$n] eq 'z') {
+               $l[$n] = 'a';
+               $n--;
+       }
+       if ($l[$n] =~ /[hkn]/) {
+               $l[$n] = chr(2+ord($l[$n]));
+               while (++$n <= $#l) {
+                       $l[$n] = 'a';
+               }
+       } else {
+               $l[$n] = chr(1+ord($l[$n]));
+       };
+       $in = join('', @l);
+       say "got $in";
+
+       next NUMBER if $in !~ /(.)\1.*(.)\2/;
+
+       my $prev = $l[0];
+       my $count = 1;
+       for (1 .. $#l) {
+               say "prev=$prev now=$l[$_] count $count";
+               if ($prev eq chr(ord($l[$_])-1)) {
+                       last if ++$count >= 3;
+               } else {
+                       $count = 1;
+               }
+               $prev = $l[$_];
+       }
+       next NUMBER if $count < 3;
+       last;
+}
+
diff --git a/2015/22.pl b/2015/22.pl
new file mode 100755 (executable)
index 0000000..0fa0f9f
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $in = 'cqjxxyzz';
+
+NUMBER:
+while (1) {
+       my @l = split //, $in;
+       my $n = $#l;
+       while ($l[$n] eq 'z') {
+               $l[$n] = 'a';
+               $n--;
+       }
+       if ($l[$n] =~ /[hkn]/) {
+               $l[$n] = chr(2+ord($l[$n]));
+               while (++$n <= $#l) {
+                       $l[$n] = 'a';
+               }
+       } else {
+               $l[$n] = chr(1+ord($l[$n]));
+       };
+       $in = join('', @l);
+       say "got $in";
+
+       next NUMBER if $in !~ /(.)\1.*(.)\2/;
+
+       my $prev = $l[0];
+       my $count = 1;
+       for (1 .. $#l) {
+               say "prev=$prev now=$l[$_] count $count";
+               if ($prev eq chr(ord($l[$_])-1)) {
+                       last if ++$count >= 3;
+               } else {
+                       $count = 1;
+               }
+               $prev = $l[$_];
+       }
+       next NUMBER if $count < 3;
+       last;
+}
+
diff --git a/2015/23.pl b/2015/23.pl
new file mode 100755 (executable)
index 0000000..8e5c819
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+$/ = undef;
+$_ = <>;
+
+my $sum;
+while (/-?\d+/g) {
+       $sum += $&;
+}
+say $sum;
diff --git a/2015/24.pl b/2015/24.pl
new file mode 100755 (executable)
index 0000000..f803084
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+use JSON qw(from_json);
+
+my $j = from_json(<>);
+
+my $sum;
+
+sub walk {
+       my $r = shift;
+       if (ref $r && ref $r eq 'ARRAY') {
+               for my $member (@$r) {
+                       walk($member);
+               }
+       } elsif (ref $r && ref $r eq 'HASH') {
+               for my $k (keys %$r) {
+                       return if $r->{$k} eq 'red';
+               }
+               for my $k (keys %$r) {
+                       walk($r->{$k});
+               }
+       } elsif ($r =~ /\A-?\d+\z/) {
+               $sum += $r;
+       }
+}
+
+walk($j);
+say $sum;
diff --git a/2015/25.pl b/2015/25.pl
new file mode 100755 (executable)
index 0000000..b5a6e70
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %rules;
+my %persons;
+
+while (<>) {
+       my ($p1, $sign, $score, $p2) = /(\w+) would (\w+) (\d+) happiness units? by sitting next to (\w+)\./;
+       $sign = ($sign eq 'gain') ? 1 : -1;
+       $rules{$p1}{$p2} = $sign * $score;
+       $persons{$p1}++;
+       $persons{$p2}++;
+}
+
+my $max;
+sub perm {
+       my ($done, $rest) = @_;
+
+       if (@$rest) {
+               for my $i (0 .. $#$rest) {
+                       my @nd = @$done;
+                       my @nr = @$rest;
+                       push @nd, splice @nr, $i, 1;
+                       perm(\@nd, \@nr);
+               }
+       } else {
+               my $score;
+               for my $i (0 .. $#$done) {
+                       my $self = $done->[$i];
+                       my @neigh = ($done->[$i-1], $done->[$i == $#$done ? 0 : $i+1]);
+                       for my $n (@neigh) {
+                               $score += $rules{$self}{$n};
+                       }
+               }
+               $max = $score if !defined $max || $max < $score;        
+       }
+}
+
+perm([], [ keys %persons ]);
+say $max;
+
diff --git a/2015/26.pl b/2015/26.pl
new file mode 100755 (executable)
index 0000000..39a4200
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %rules;
+my %persons;
+
+while (<>) {
+       my ($p1, $sign, $score, $p2) = /(\w+) would (\w+) (\d+) happiness units? by sitting next to (\w+)\./;
+       $sign = ($sign eq 'gain') ? 1 : -1;
+       $rules{$p1}{$p2} = $sign * $score;
+       $persons{$p1}++;
+       $persons{$p2}++;
+}
+
+$persons{myself}++;
+for my $p (keys %persons) {
+       $rules{myself}{$p} = 0;
+       $rules{$p}{myself} = 0;
+}
+
+my $max;
+sub perm {
+       my ($done, $rest) = @_;
+
+       if (@$rest) {
+               for my $i (0 .. $#$rest) {
+                       my @nd = @$done;
+                       my @nr = @$rest;
+                       push @nd, splice @nr, $i, 1;
+                       perm(\@nd, \@nr);
+               }
+       } else {
+               my $score;
+               for my $i (0 .. $#$done) {
+                       my $self = $done->[$i];
+                       my @neigh = ($done->[$i-1], $done->[$i == $#$done ? 0 : $i+1]);
+                       for my $n (@neigh) {
+                               $score += $rules{$self}{$n};
+                       }
+               }
+               $max = $score if !defined $max || $max < $score;        
+       }
+}
+
+perm([], [ keys %persons ]);
+say $max;
+
diff --git a/2015/27.pl b/2015/27.pl
new file mode 100755 (executable)
index 0000000..bf31739
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my (%speed, %time, %resttime);
+my %state;
+my %dist;
+while (<>) {
+       my ($name, $sp, $t, $r) = /(\w+) can fly (\d+) .* for (\d+) .*rest for (\d+) /;
+       $speed{$name} = $sp;
+       $time{$name} = $t;
+       $resttime{$name} = $r;
+       $state{$name} = $t;
+};
+
+
+my $time = 2503;
+
+my $max;
+
+for my $n (keys %speed) {
+       my $loops = int($time/($time{$n}+$resttime{$n}));
+       my $dist = $loops * $time{$n} * $speed{$n};
+       my $rest = $time - $loops*($time{$n}+$resttime{$n});
+       $rest = $time{$n} if $rest > $time{$n};
+       $dist += $speed{$n} * $rest;
+       say "$n $dist";
+       $max = $dist if !$max || $max < $dist;
+}
+
+say $max;
+               
diff --git a/2015/28.pl b/2015/28.pl
new file mode 100755 (executable)
index 0000000..dcda961
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my (%speed, %time, %resttime);
+my %state;
+my %dist;
+my %score;
+
+while (<>) {
+       my ($name, $sp, $t, $r) = /(\w+) can fly (\d+) .* for (\d+) .*rest for (\d+) /;
+       $speed{$name} = $sp;
+       $time{$name} = $t;
+       $resttime{$name} = $r;
+
+       $state{$name} = $t;
+       $score{$name} = 0;
+};
+
+
+my $time = 2503;
+
+for (1 .. $time) {
+       my $max;
+       for my $n (keys %speed) {
+               $dist{$n} += $speed{$n} if $state{$n} > 0;
+               $state{$n} = $time{$n} if --$state{$n} <= -$resttime{$n};
+               $max = $dist{$n} if !$max || $max < $dist{$n};
+       }
+
+       for my $n (keys %speed) {
+               $score{$n}++ if $dist{$n} == $max;
+       }
+}
+
+my $maxscore;
+for my $n (keys %speed) {
+       $maxscore = $score{$n} if !$maxscore || $score{$n} > $maxscore;
+}
+
+say $maxscore;
+
+
diff --git a/2015/29.pl b/2015/29.pl
new file mode 100755 (executable)
index 0000000..c42f6b1
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %prop;
+while (<>) {
+       my ($name) = /\A(\w+):/;
+       my @vals = /(-?\d+)/g;
+       $prop{$name} = \@vals;
+}
+
+my $max;
+
+sub addprop {
+       my ($amounts, $rem, $rest) = @_;
+
+       if (!@$rest) {
+               for my $p (keys %prop) {
+                       print "$p=$amounts->{$p}, ";
+               }
+               print "\n";
+               my $mul = 1;
+               for my $t (0 ..3) {
+                       my $sum = 0;
+                       for my $p (keys %prop) {
+                               $sum += $prop{$p}->[$t] * $amounts->{$p};
+                       }
+                       $sum = 0 if $sum < 0;
+                       $mul *= $sum;
+               }
+               $max = $mul if !$max || $mul > $max;    
+       } else {
+               for my $i (0 .. $#$rest) {
+                       my @nr = @$rest;
+                       my ($ing) = splice @nr, $i, 1;
+                       my $min = @nr ? 0 : $rem;
+                       for my $a ($min .. $rem) {
+                               my %na = %$amounts;
+                               $na{$ing} = $a;
+                               addprop(\%na, $rem-$a, \@nr);
+                       }
+               }
+       }
+}
+
+addprop({}, 100, [ keys %prop ]);
+
+say $max;
diff --git a/2015/30.pl b/2015/30.pl
new file mode 100755 (executable)
index 0000000..b2d849b
--- /dev/null
@@ -0,0 +1,50 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %prop;
+while (<>) {
+       my ($name) = /\A(\w+):/;
+       my @vals = /(-?\d+)/g;
+       $prop{$name} = \@vals;
+}
+
+my $max;
+
+sub addprop {
+       my ($amounts, $rem, $rest) = @_;
+
+       if (!@$rest) {
+               my $cal = 0;
+               for my $p (keys %prop) {
+                       $cal += $prop{$p}->[-1] * $amounts->{$p};
+               }
+               return if $cal != 500;
+               my $mul = 1;
+               for my $t (0 ..3) {
+                       my $sum = 0;
+                       for my $p (keys %prop) {
+                               $sum += $prop{$p}->[$t] * $amounts->{$p};
+                       }
+                       $sum = 0 if $sum < 0;
+                       $mul *= $sum;
+               }
+               $max = $mul if !$max || $mul > $max;    
+       } else {
+               for my $i (0 .. $#$rest) {
+                       my @nr = @$rest;
+                       my ($ing) = splice @nr, $i, 1;
+                       my $min = @nr ? 0 : $rem;
+                       for my $a ($min .. $rem) {
+                               my %na = %$amounts;
+                               $na{$ing} = $a;
+                               addprop(\%na, $rem-$a, \@nr);
+                       }
+               }
+       }
+}
+
+addprop({}, 100, [ keys %prop ]);
+
+say $max;
diff --git a/2015/31.pl b/2015/31.pl
new file mode 100755 (executable)
index 0000000..1ba982e
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %g = (
+children => 3,
+cats => 7,
+samoyeds => 2,
+pomeranians => 3,
+akitas => 0,
+vizslas => 0,
+goldfish => 5,
+trees => 3,
+cars => 2,
+perfumes => 1,
+);
+
+
+AUNT:
+while (<>) {
+       my ($id, $rest) = /Sue (\d+): (.*)/;
+       my %vals = $rest =~ /(\w+): (\d+)/g;
+       for my $v (keys %vals) {
+               next AUNT if defined $g{$v} && $g{$v} != $vals{$v};
+       }
+       say "aunt $id";
+}
diff --git a/2015/32.pl b/2015/32.pl
new file mode 100755 (executable)
index 0000000..1f6b20f
--- /dev/null
@@ -0,0 +1,34 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %g = (
+children => 3,
+cats => 7,
+samoyeds => 2,
+pomeranians => 3,
+akitas => 0,
+vizslas => 0,
+goldfish => 5,
+trees => 3,
+cars => 2,
+perfumes => 1,
+);
+
+
+AUNT:
+while (<>) {
+       my ($id, $rest) = /Sue (\d+): (.*)/;
+       my %vals = $rest =~ /(\w+): (\d+)/g;
+       for my $v (keys %vals) {
+               if ($v eq 'pomeranians' || $v eq 'goldfish') {
+                       next AUNT if defined $g{$v} && $g{$v} <= $vals{$v};
+               } elsif ($v eq 'cats' || $v eq 'trees') {
+                       next AUNT if defined $g{$v} && $g{$v} >= $vals{$v};
+               } else {
+                       next AUNT if defined $g{$v} && $g{$v} != $vals{$v};
+               }
+       }
+       say "aunt $id";
+}
diff --git a/2015/33.pl b/2015/33.pl
new file mode 100755 (executable)
index 0000000..dbd504c
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+chomp (my @cont = sort { $a <=> $b } <>);
+
+my $count;
+sub walk {
+       my ($rem, $rest, $used) = @_;
+       if (!$rem) {
+               $count++;
+               say join(',', @$used);
+               return;
+       }
+       return if !@$rest || $rem < $rest->[0];
+       for my $i (0 .. $#$rest) {
+               my @nr = @$rest;
+               my @nu = @$used;
+               my (@a) = splice @nr, 0, $i+1;
+               my $n = $a[-1];
+               push @nu, $n;
+               walk($rem - $n, \@nr, \@nu) if $rem >= $n;
+       }
+}
+
+walk(150, \@cont, []);
+say $count;
+
diff --git a/2015/34.pl b/2015/34.pl
new file mode 100755 (executable)
index 0000000..f7c394f
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+chomp (my @cont = sort { $a <=> $b } <>);
+
+my @fits;
+sub walk {
+       my ($rem, $rest, $used) = @_;
+       if (!$rem) {
+               $fits[$#$used]++;
+               say join(',', @$used);
+               return;
+       }
+       return if !@$rest || $rem < $rest->[0];
+       for my $i (0 .. $#$rest) {
+               my @nr = @$rest;
+               my @nu = @$used;
+               my (@a) = splice @nr, 0, $i+1;
+               my $n = $a[-1];
+               push @nu, $n;
+               walk($rem - $n, \@nr, \@nu) if $rem >= $n;
+       }
+}
+
+walk(150, \@cont, []);
+no strict;
+say join(',', @fits);
+
diff --git a/2015/35.pl b/2015/35.pl
new file mode 100755 (executable)
index 0000000..73ee92f
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my @m = map { chomp; [ split // ] } <>;
+
+for (1 .. 100) {
+       my @nm;
+       for my $y (0 .. 99) {
+       for my $x (0 .. 99) {
+               my $sum = 0;
+               for my $dy (-1 .. 1) {
+                       next if $y + $dy < 0 || $y + $dy > 99;
+                       for my $dx (-1 .. 1) {
+                               next if $x + $dx < 0 || $x + $dx > 99;
+                               next if $dx == 0 && $dy == 0;
+                               $sum++ if $m[$y+$dy][$x+$dx] eq '#';
+                       }
+               }
+               if ($m[$y][$x] eq '#') {
+                       $nm[$y][$x] = $sum == 2 || $sum == 3 ? '#' : '.';
+               } else {
+                       $nm[$y][$x] = $sum == 3 ? '#' : '.';
+               }
+       } }
+       @m = @nm;
+}
+
+my $sum;
+for my $y (0 .. 99) {
+for my $x (0 .. 99) {
+       $sum++ if $m[$y][$x] eq '#';
+} }
+
+say $sum;
diff --git a/2015/36.pl b/2015/36.pl
new file mode 100755 (executable)
index 0000000..50cdc44
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my @m = map { chomp; [ split // ] } <>;
+
+my $dim = @m - 1;
+
+for my $x (0, $dim) {
+       for my $y (0, $dim) {
+               $m[$y][$x] = '#';
+       }
+}
+
+for (1 .. 100) {
+       my @nm;
+       for my $y (0 .. $dim) {
+       for my $x (0 .. $dim) {
+               my $sum = 0;
+               for my $dy (-1 .. 1) {
+                       next if $y + $dy < 0 || $y + $dy > $dim;
+                       for my $dx (-1 .. 1) {
+                               next if $x + $dx < 0 || $x + $dx > $dim;
+                               next if $dx == 0 && $dy == 0;
+                               $sum++ if $m[$y+$dy][$x+$dx] eq '#';
+                       }
+               }
+               if (($y == 0 || $y == $dim) && ($x == 0 || $x == $dim)) {
+                       $nm[$y][$x] = '#';
+               } elsif ($m[$y][$x] eq '#') {
+                       $nm[$y][$x] = $sum == 2 || $sum == 3 ? '#' : '.';
+               } else {
+                       $nm[$y][$x] = $sum == 3 ? '#' : '.';
+               }
+       } }
+       @m = @nm;
+}
+
+my $sum;
+for my $y (0 .. $dim) {
+for my $x (0 .. $dim) {
+       $sum++ if $m[$y][$x] eq '#';
+} }
+
+say $sum;
diff --git a/2015/37.pl b/2015/37.pl
new file mode 100755 (executable)
index 0000000..74a2746
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my @rules;
+while (<>) {
+       chomp;
+       last if /^$/;
+       my ($src, $dst) = /(\w+) => (\w+)/;
+       push @rules, [$src, $dst];
+}
+
+chomp (my $mol = <>);
+
+my %seen;
+
+for my $r (@rules) {
+       my ($src, $dst) = @$r;
+       my $m1 = $mol;
+       say "$src => $dst";
+       while ($m1 =~ /$src/g) {
+               my $m2 = $m1;
+               substr($m2, pos($m1)-length($src), length($src)) = $dst;
+               $seen{$m2}++;
+               say $m2;
+       }
+}
+
+say scalar keys %seen;
diff --git a/2015/38.pl b/2015/38.pl
new file mode 100755 (executable)
index 0000000..1a30e5f
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %rules;
+while (<>) {
+       chomp;
+       last if /^$/;
+       my ($src, $dst) = /(\w+) => (\w+)/;
+       # push @rules, [$src, $dst];
+       push @{ $rules{$src} }, [ split(/(?=[A-Z])/, $dst) ];
+}
+
+chomp (my $mol = <>);
+my @mol = split(/(?=[A-Z])/, $mol);
+
+$; = ',';
+my $added = 1;
+while ($added) {
+       $added = 0;
+       for my $elem (keys %rules) {
+               for my $rule (@{ $rules{$elem} }) {
+                       my $first = $
+my @q = ([ ['e'], \@mol, 0 ]);
+
+my %seen;
+
+while (@q) {
+       my $entry = shift @q;
+       my ($stack, $mol, $steps) = @$entry;
+
+       if (!@$stack && !@$mol) {
+               say $steps;
+               last;
+       }
+       if (!@$stack || !@$mol) {
+               next;
+       }
+       say "apply $steps: @$stack => @$mol";
+
+       if ($stack->[0] eq $mol->[0]) {
+               say "reduce $stack->[0]";
+               my @nstack = @$stack;
+               shift @nstack;
+               my @nmol = @$mol;
+               shift @nmol;
+               unshift @q, [ \@nstack, \@nmol, $steps ];
+       }
+       for my $rule (@{ $rules{$stack->[0]} }) {
+               my @nstack = @$stack;
+               shift @nstack;
+               unshift @nstack, @$rule;
+               my $key = join(' ', @nstack, '=', @$mol);
+               next if $seen{$key}++;
+               say "push $stack->[0] => @$rule";
+               push @q, [ \@nstack, [ @$mol ], $steps+1 ];
+       }
+}
diff --git a/2015/39.pl b/2015/39.pl
new file mode 100755 (executable)
index 0000000..5a78b2d
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $in = 33100000;
+
+my $maxh = $in/10;
+
+my @houses = (10) x $maxh;
+for my $elf (2 .. $maxh) {
+       my $h = $elf;
+       do {
+               $houses[$h] += 10*$elf;
+               $h += $elf;
+       } while ($h <= $maxh);
+}
+
+for my $h (1 .. $maxh) {
+       next if $houses[$h] < $in;
+       say $h;
+       last;
+}
+
diff --git a/2015/40.pl b/2015/40.pl
new file mode 100755 (executable)
index 0000000..8252fa5
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my $in = 33100000;
+
+my $maxh = $in;
+
+my @houses;
+for my $elf (1 .. $maxh) {
+       my $h = $elf;
+       my $count = 50;
+       do {
+               $houses[$h] += 11*$elf;
+               $maxh = $h if $houses[$h] >= $in;
+               $h += $elf;
+       } while ($h <= $maxh && --$count);
+}
+
+for my $h (1 .. $maxh) {
+       next if $houses[$h] < $in;
+       say $h;
+       last;
+}
+
diff --git a/2015/41.pl b/2015/41.pl
new file mode 100755 (executable)
index 0000000..969500a
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %weapons = (
+'Dagger' => [ qw(       8     4       0 ) ],
+'Shortsword' => [ qw(  10     5       0 ) ],
+'Warhammer' => [ qw(   25     6       0 ) ],
+'Longsword' => [ qw(   40     7       0 ) ],
+'Greataxe' => [ qw(    74     8       0 ) ],
+);
+
+my %armors = (
+'NONE'    => [ qw(      0     0       0 ) ],
+'Leather' => [ qw(     13     0       1 ) ],
+'Chainmail' => [ qw(   31     0       2 ) ],
+'Splintmail' => [ qw(  53     0       3 ) ],
+'Bandedmail' => [ qw(  75     0       4 ) ],
+'Platemail' => [ qw(  102     0       5 ) ],
+);
+
+my %rings = (
+'NONE_1'    => [ qw(    0     0       0 ) ],
+'NONE_2'    => [ qw(    0     0       0 ) ],
+'Damage_+1' => [ qw(   25     1       0 ) ],
+'Damage_+2' => [ qw(   50     2       0 ) ],
+'Damage_+3' => [ qw(  100     3       0 ) ],
+'Defense_+1' => [ qw(  20     0       1 ) ],
+'Defense_+2' => [ qw(  40     0       2 ) ],
+'Defense_+3' => [ qw(  80     0       3 ) ],
+);
+
+my $boss = [ qw(104 8 1) ];
+
+my $minprice;
+for my $w (keys %weapons) {
+       for my $a (keys %armors) {
+               for my $r1 (keys %rings) {
+                       for my $r2 (keys %rings) {
+                               next if $r1 eq $r2;
+                               my $price = $weapons{$w}->[0]
+                                       + $armors{$a}->[0]
+                                       + $rings{$r1}->[0]
+                                       + $rings{$r2}->[0];
+                               my $damage = $weapons{$w}->[1]
+                                       + $armors{$a}->[1]
+                                       + $rings{$r1}->[1]
+                                       + $rings{$r2}->[1];
+                               my $armor = $weapons{$w}->[2]
+                                       + $armors{$a}->[2]
+                                       + $rings{$r1}->[2]
+                                       + $rings{$r2}->[2];
+                               my $pl = $damage - $boss->[2];
+                               my $bo = $boss->[1] - $armor;
+                               my ($bosshp, $playerhp) = ($boss->[0], 100);
+                               while (1) {
+                                       $bosshp -= $pl;
+                                       if ($bosshp <= 0) {
+                                               $minprice = $price if !$minprice || $price < $minprice;
+                                               say "$price $w $a $r1 $r2";
+                                               last;
+                                       }
+                                       $playerhp -= $bo;
+                                       last if ($playerhp <= 0);
+                               }
+                       }
+               }
+       }
+}
+
+say $minprice;
+                       
+               
+               
+       
+
diff --git a/2015/42.pl b/2015/42.pl
new file mode 100755 (executable)
index 0000000..53227de
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %weapons = (
+'Dagger' => [ qw(       8     4       0 ) ],
+'Shortsword' => [ qw(  10     5       0 ) ],
+'Warhammer' => [ qw(   25     6       0 ) ],
+'Longsword' => [ qw(   40     7       0 ) ],
+'Greataxe' => [ qw(    74     8       0 ) ],
+);
+
+my %armors = (
+'NONE'    => [ qw(      0     0       0 ) ],
+'Leather' => [ qw(     13     0       1 ) ],
+'Chainmail' => [ qw(   31     0       2 ) ],
+'Splintmail' => [ qw(  53     0       3 ) ],
+'Bandedmail' => [ qw(  75     0       4 ) ],
+'Platemail' => [ qw(  102     0       5 ) ],
+);
+
+my %rings = (
+'NONE_1'    => [ qw(    0     0       0 ) ],
+'NONE_2'    => [ qw(    0     0       0 ) ],
+'Damage_+1' => [ qw(   25     1       0 ) ],
+'Damage_+2' => [ qw(   50     2       0 ) ],
+'Damage_+3' => [ qw(  100     3       0 ) ],
+'Defense_+1' => [ qw(  20     0       1 ) ],
+'Defense_+2' => [ qw(  40     0       2 ) ],
+'Defense_+3' => [ qw(  80     0       3 ) ],
+);
+
+my $boss = [ qw(104 8 1) ];
+
+my $maxprice;
+for my $w (keys %weapons) {
+       for my $a (keys %armors) {
+               for my $r1 (keys %rings) {
+                       for my $r2 (keys %rings) {
+                               next if $r1 eq $r2;
+                               my $price = $weapons{$w}->[0]
+                                       + $armors{$a}->[0]
+                                       + $rings{$r1}->[0]
+                                       + $rings{$r2}->[0];
+                               my $damage = $weapons{$w}->[1]
+                                       + $armors{$a}->[1]
+                                       + $rings{$r1}->[1]
+                                       + $rings{$r2}->[1];
+                               my $armor = $weapons{$w}->[2]
+                                       + $armors{$a}->[2]
+                                       + $rings{$r1}->[2]
+                                       + $rings{$r2}->[2];
+                               my $pl = $damage - $boss->[2];
+                               my $bo = $boss->[1] - $armor;
+                               my ($bosshp, $playerhp) = ($boss->[0], 100);
+                               while (1) {
+                                       $bosshp -= $pl;
+                                       last if ($bosshp <= 0);
+                                       $playerhp -= $bo;
+                                       if ($playerhp <= 0) {
+                                               $maxprice = $price if !$maxprice || $price > $maxprice;
+                                               say "$price $w $a $r1 $r2";
+                                               last;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+say $maxprice;
+                       
+               
+               
+       
+
diff --git a/2015/43.pl b/2015/43.pl
new file mode 100755 (executable)
index 0000000..b6c9866
--- /dev/null
@@ -0,0 +1,119 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+
+=comment
+
+    Magic Missile costs 53 mana. It instantly does 4 damage.
+    Drain costs 73 mana. It instantly does 2 damage and heals you for 2 hit points.
+    Shield costs 113 mana. It starts an effect that lasts for 6 turns. While it is active, your armor is increased by 7.
+    Poison costs 173 mana. It starts an effect that lasts for 6 turns. At the start of each turn while it is active, it deals the boss 3 damage.
+    Recharge costs 229 mana. It starts an effect that lasts for 5 turns. At the start of each turn while it is active, it gives you 101 new mana.
+
+You start with 50 hit points and 500 mana points. The boss's actual stats are in your puzzle input. What is the least amount of mana you can spend and still win the fight? (Do not include mana recharge effects as "spending" negative mana.)
+
+Boss: Hit Points: 71
+Damage: 10
+
+=cut
+
+use Array::Heap;
+my @q;
+if (1) {
+       push @q, [ 0, {
+               turn       => 0,
+               player_hp  => 50,
+               mana       => 500,
+               boss_hp    => 71,
+               damage     => 10,
+               spells     => [],
+       } ];
+} else {
+       push @q, [ 0, {
+               turn       => 0,
+               player_hp  => 10,
+               mana       => 250,
+               boss_hp    => 14,
+               damage     => 8,
+               spells     => [],
+       } ];
+}
+
+my %effects = map { $_ => 1 } qw(shield poison recharge);
+
+sub spell {
+       my ($name, $reqd, $entry, $action) = @_;
+       my ($spent, $state, @spells) = @$entry;
+       my %ns = %$state;
+       $ns{turn}++;
+       return if $ns{mana} < $reqd;
+       $ns{mana} -= $reqd;
+       $spent += $reqd;
+       $ns{spells} = [ @{ $state->{spells} }, $name ];
+       if ($effects{$name}) {
+               return if $ns{$name};
+               $ns{$name} = $name eq 'recharge' ? 5 : 6;
+       } else {
+               $action->(\%ns) if $action;
+               if ($ns{boss_hp} <= 0) {
+                       say "won after spending $spent:_", join(',', @{ $ns{spells} });
+                       exit 0;
+               }
+       }
+       push_heap @q, [ $spent, \%ns, ];
+}
+
+sub do_timer {
+       my ($name, $entry, $action) = @_;
+       my ($spent, $state) = @$entry;
+       if ($state->{$name}) {
+               # say "timer $name: $state->{$name}";
+               $action->($entry);
+               $state->{$name}--;
+               if ($state->{boss_hp} <= 0) {
+                       say "won after spedning $spent: ", join(',', @{ $state->{spells} });
+                       exit 0;
+               }
+       }
+}
+
+sub do_timers {
+       my ($entry) = @_;
+       do_timer('shield', $entry, sub { });
+       do_timer('poison', $entry, sub { $_[0]->[1]->{boss_hp} -= 3; });
+       do_timer('recharge', $entry, sub { $_[0]->[1]->{mana} += 101; });
+}
+
+while (@q) {
+       my $entry = pop_heap @q;
+       my ($spent, $state) = @$entry;
+
+       do_timers($entry);
+       if ($state->{turn} & 1) { # boss
+               $state->{turn}++;
+               my $damage = $state->{damage};
+               $damage -= 7 if $state->{shield};
+               $damage = 1 if $damage < 1;
+               $state->{player_hp} -= $damage;
+               say "boss turn $state->{turn} player_hp $state->{player_hp} mana $state->{mana} boss_hp $state->{boss_hp} spent $spent ", join(',', @{ $state->{spells} }), " shield $state->{shield}";
+               if ($state->{player_hp} <= 0) { # boss wins
+                       next;
+               }
+               push_heap @q, [$spent, $state ];
+               next;
+       }
+       # Player
+       spell('magic_missile', 53, $entry, sub {
+               $_[0]->{boss_hp} -= 4;
+       });
+       spell('drain', 73, $entry, sub {
+               $_[0]->{boss_hp} -= 2;
+               $_[0]->{player_hp} += 2;
+       });
+       spell('shield', 113, $entry);
+       spell('poison', 173, $entry);
+       spell('recharge', 229, $entry);
+}
+
diff --git a/2015/44.pl b/2015/44.pl
new file mode 100755 (executable)
index 0000000..aca1684
--- /dev/null
@@ -0,0 +1,120 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+
+=comment
+
+    Magic Missile costs 53 mana. It instantly does 4 damage.
+    Drain costs 73 mana. It instantly does 2 damage and heals you for 2 hit points.
+    Shield costs 113 mana. It starts an effect that lasts for 6 turns. While it is active, your armor is increased by 7.
+    Poison costs 173 mana. It starts an effect that lasts for 6 turns. At the start of each turn while it is active, it deals the boss 3 damage.
+    Recharge costs 229 mana. It starts an effect that lasts for 5 turns. At the start of each turn while it is active, it gives you 101 new mana.
+
+You start with 50 hit points and 500 mana points. The boss's actual stats are in your puzzle input. What is the least amount of mana you can spend and still win the fight? (Do not include mana recharge effects as "spending" negative mana.)
+
+Boss: Hit Points: 71
+Damage: 10
+
+=cut
+
+use Array::Heap;
+my @q;
+if (1) {
+       push @q, [ 0, {
+               turn       => 0,
+               player_hp  => 50,
+               mana       => 500,
+               boss_hp    => 71,
+               damage     => 10,
+               spells     => [],
+       } ];
+} else {
+       push @q, [ 0, {
+               turn       => 0,
+               player_hp  => 10,
+               mana       => 250,
+               boss_hp    => 14,
+               damage     => 8,
+               spells     => [],
+       } ];
+}
+
+my %effects = map { $_ => 1 } qw(shield poison recharge);
+
+sub spell {
+       my ($name, $reqd, $entry, $action) = @_;
+       my ($spent, $state, @spells) = @$entry;
+       my %ns = %$state;
+       $ns{turn}++;
+       return if $ns{mana} < $reqd;
+       $ns{mana} -= $reqd;
+       $spent += $reqd;
+       $ns{spells} = [ @{ $state->{spells} }, $name ];
+       if ($effects{$name}) {
+               return if $ns{$name};
+               $ns{$name} = $name eq 'recharge' ? 5 : 6;
+       } else {
+               $action->(\%ns) if $action;
+               if ($ns{boss_hp} <= 0) {
+                       say "won after spending $spent:_", join(',', @{ $ns{spells} });
+                       exit 0;
+               }
+       }
+       push_heap @q, [ $spent, \%ns, ];
+}
+
+sub do_timer {
+       my ($name, $entry, $action) = @_;
+       my ($spent, $state) = @$entry;
+       if ($state->{$name}) {
+               # say "timer $name: $state->{$name}";
+               $action->($entry);
+               $state->{$name}--;
+               if ($state->{boss_hp} <= 0) {
+                       say "won after spedning $spent: ", join(',', @{ $state->{spells} });
+                       exit 0;
+               }
+       }
+}
+
+sub do_timers {
+       my ($entry) = @_;
+       do_timer('shield', $entry, sub { });
+       do_timer('poison', $entry, sub { $_[0]->[1]->{boss_hp} -= 3; });
+       do_timer('recharge', $entry, sub { $_[0]->[1]->{mana} += 101; });
+}
+
+while (@q) {
+       my $entry = pop_heap @q;
+       my ($spent, $state) = @$entry;
+
+       do_timers($entry);
+       if ($state->{turn} & 1) { # boss
+               $state->{turn}++;
+               my $damage = $state->{damage};
+               $damage -= 7 if $state->{shield};
+               $damage = 1 if $damage < 1;
+               $state->{player_hp} -= $damage;
+               say "boss turn $state->{turn} player_hp $state->{player_hp} mana $state->{mana} boss_hp $state->{boss_hp} spent $spent ", join(',', @{ $state->{spells} }), " shield $state->{shield}";
+               if ($state->{player_hp} <= 0) { # boss wins
+                       next;
+               }
+               push_heap @q, [$spent, $state ];
+               next;
+       }
+       # Player
+       next if --$state->{player_hp} <= 0;
+       spell('magic_missile', 53, $entry, sub {
+               $_[0]->{boss_hp} -= 4;
+       });
+       spell('drain', 73, $entry, sub {
+               $_[0]->{boss_hp} -= 2;
+               $_[0]->{player_hp} += 2;
+       });
+       spell('shield', 113, $entry);
+       spell('poison', 173, $entry);
+       spell('recharge', 229, $entry);
+}
+
diff --git a/2015/45.pl b/2015/45.pl
new file mode 100755 (executable)
index 0000000..dd6e8d6
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %regs = ( a => 0, b => 0 );
+my @code = map { chomp; [ split /[ ,+]+/ ] } <>;
+my $ip = 0;
+while ($ip < @code) {
+       my ($ins, $v1, $v2) = @{ $code[$ip] };
+       say "$ip: ", join(' ', @{ $code[$ip] }), " a=$regs{a} b=$regs{b}";
+       if ($ins eq 'hlf') {
+               $regs{$v1} = int($regs{$v1}/2);
+       } elsif ($ins eq 'tpl') {
+               $regs{$v1} *= 3;
+       } elsif ($ins eq 'inc') {
+               $regs{$v1}++;
+       } elsif ($ins eq 'jmp') {
+               $ip += $v1 - 1;
+       } elsif ($ins eq 'jie') {
+               $ip += $v2 - 1 if $regs{$v1} % 2 == 0;
+       } elsif ($ins eq 'jio') {
+               $ip += $v2 - 1 if $regs{$v1} == 1;
+       } else {
+               say "Invalid insn $ins";
+       }
+       $ip++;
+}
+
+say "ip=$ip";
+say $regs{b};
diff --git a/2015/46.pl b/2015/46.pl
new file mode 100755 (executable)
index 0000000..efb97e3
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my %regs = ( a => 1, b => 0 );
+my @code = map { chomp; [ split /[ ,+]+/ ] } <>;
+my $ip = 0;
+while ($ip < @code) {
+       my ($ins, $v1, $v2) = @{ $code[$ip] };
+       say "$ip: ", join(' ', @{ $code[$ip] }), " a=$regs{a} b=$regs{b}";
+       if ($ins eq 'hlf') {
+               $regs{$v1} = int($regs{$v1}/2);
+       } elsif ($ins eq 'tpl') {
+               $regs{$v1} *= 3;
+       } elsif ($ins eq 'inc') {
+               $regs{$v1}++;
+       } elsif ($ins eq 'jmp') {
+               $ip += $v1 - 1;
+       } elsif ($ins eq 'jie') {
+               $ip += $v2 - 1 if $regs{$v1} % 2 == 0;
+       } elsif ($ins eq 'jio') {
+               $ip += $v2 - 1 if $regs{$v1} == 1;
+       } else {
+               say "Invalid insn $ins";
+       }
+       $ip++;
+}
+
+say "ip=$ip";
+say $regs{b};
diff --git a/2015/47.pl b/2015/47.pl
new file mode 100755 (executable)
index 0000000..c00d3d7
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+use List::Util qw(sum);
+chomp (my @packs = reverse <>);
+# my @packs = reverse(1 .. 5, 7 .. 11);
+my $size = sum @packs;
+$size /= 3;
+say "expect $size";
+
+my $min = @packs;
+my $minqe;
+
+sub divide {
+       my ($s1, $s2, $l1, $qe, @rest) = @_;
+       if ($s2 == $size) {
+               say "$s1 $s2 $l1 $qe";
+               if ($l1 < $min) {
+                       $min = $l1;
+                       $minqe = $qe;
+                       say "min=$min, minqe=$qe";
+               } elsif ($l1 == $min && (!$minqe || $qe < $minqe)) {
+                       $minqe = $qe;
+                       say "minqe=$qe";
+               }
+               return;
+       }
+       for my $i (0 .. $#rest) {
+               my @nr = @rest;
+               my $n = splice (@nr, $i, 1);
+               if ($s1 < $size && $s1 + $n <= $size && $l1+1 <= $min) {
+                       divide($s1+$n, 0, $l1+1, $qe*$n, @nr);
+               } elsif ($s1 == $size && $s2 < $size && $s2 + $n <= $size
+                       && ($l1 < $min || ($l1 == $min && $qe < $minqe))) {
+                       # say "l2 $s1, $s2+$n, $l1, $qe";
+                       divide($s1, $s2+$n, $l1, $qe, @nr);
+               } 
+       }
+}
+
+divide(0, 0, 0, 1, @packs);
+say $minqe;
diff --git a/2015/48.pl b/2015/48.pl
new file mode 100755 (executable)
index 0000000..c6ec297
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+use List::Util qw(sum);
+chomp (my @packs = reverse <>);
+# my @packs = reverse(1 .. 5, 7 .. 11);
+my $size = sum @packs;
+$size /= 4;
+say "expect $size";
+
+my $min = @packs;
+my $minqe;
+
+sub divide {
+       my ($s1, $s2, $s3, $l1, $qe, @rest) = @_;
+       if ($s3 == $size) {
+               say "$s1 $s2 $s2 $l1 $qe";
+               if ($l1 < $min) {
+                       $min = $l1;
+                       $minqe = $qe;
+                       say "min=$min, minqe=$qe";
+               } elsif ($l1 == $min && (!$minqe || $qe < $minqe)) {
+                       $minqe = $qe;
+                       say "minqe=$qe";
+               }
+               return;
+       }
+       for my $i (0 .. $#rest) {
+               my @nr = @rest;
+               my $n = splice (@nr, $i, 1);
+               if ($s1 < $size && $s1 + $n <= $size && $l1+1 <= $min) {
+                       divide($s1+$n, 0, 0, $l1+1, $qe*$n, @nr);
+               } elsif ($s1 == $size && $s2 < $size && $s2 + $n <= $size
+                       && ($l1 < $min || ($l1 == $min && $qe < $minqe))) {
+                       # say "l2 $s1, $s2+$n, $l1, $qe";
+                       divide($s1, $s2+$n, 0, $l1, $qe, @nr);
+               } elsif ($s1 == $size && $s2 == $size && $s3 < $size && $s3 + $n <= $size && ($l1 < $min || ($l1 == $min && $qe < $minqe))) {
+                       divide($s1, $s2, $s3+$n, $l1, $qe, @nr);
+               }
+       }
+}
+
+divide(0, 0, 0, 0, 1, @packs);
+say $minqe;
diff --git a/2015/49.pl b/2015/49.pl
new file mode 100755 (executable)
index 0000000..df78893
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+my ($row, $col) = (2981, 3075);
+
+my $num = 20151125;
+my ($c, $r) = (1, 1);
+while ($col != $c || $row != $r) {
+       $num = $num * 252533 % 33554393;
+       $r--; $c++;
+       if (!$r) {
+               $r = $c;
+               $c = 1;
+       }
+}
+say "$r, $c = $num";
diff --git a/2015/get.sh b/2015/get.sh
new file mode 100755 (executable)
index 0000000..6c8336a
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+DAY=`date +%d|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/2015/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
diff --git a/2015/y/38-ypgen.pl b/2015/y/38-ypgen.pl
new file mode 100755 (executable)
index 0000000..9975d15
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use strict;
+
+say <<'HEAD';
+%{
+       my $count = 0;
+%}
+
+%start e
+
+%%
+HEAD
+
+my $prev;
+while (<>) {
+       chomp;
+       last if /^$/;
+       my ($src, $dst) = /(\w+) => (\w+)/;
+       $dst =~ s/(?=[A-Z])/ /g;
+       if (!$prev || $src ne $prev) {
+               if ($prev) {
+                       say "\t;";
+               }
+               if ($src eq 'e') {
+                       say "$src:";
+               } else {
+                       say "$src :\t'$src'";
+               }
+       }
+       if ($src eq 'e' && $prev ne $src) {
+               say "\t  $dst { shift->YYData->{count}++ }";
+       } else {
+               say "\t| $dst { shift->YYData->{count}++ }";
+       }
+       $prev = $src;
+}
+say "\t;";
+say '%%';
diff --git a/2015/y/Parser.pm b/2015/y/Parser.pm
new file mode 100644 (file)
index 0000000..e988389
--- /dev/null
@@ -0,0 +1,1116 @@
+####################################################################
+#
+#    This file was generated using Parse::Yapp version 1.21.
+#
+#        Don't edit this file, use source file instead.
+#
+#             ANY CHANGE MADE HERE WILL BE LOST !
+#
+####################################################################
+package Parser;
+use vars qw ( @ISA );
+use strict;
+
+@ISA= qw ( Parse::Yapp::Driver );
+use Parse::Yapp::Driver;
+
+#line 1 "task38.yp"
+
+       my $count = 0;
+
+
+sub new {
+        my($class)=shift;
+        ref($class)
+    and $class=ref($class);
+
+    my($self)=$class->SUPER::new( yyversion => '1.21',
+                                  yystates =>
+[
+       {#State 0
+               ACTIONS => {
+                       'C' => 7,
+                       "H" => 3,
+                       "O" => 8,
+                       "N" => 4
+               },
+               GOTOS => {
+                       'O' => 1,
+                       'H' => 2,
+                       'N' => 5,
+                       'e' => 6
+               }
+       },
+       {#State 1
+               ACTIONS => {
+                       "Mg" => 10,
+                       "B" => 12,
+                       "Ti" => 15,
+                       'Rn' => 11
+               },
+               GOTOS => {
+                       'Mg' => 9,
+                       'B' => 14,
+                       'Ti' => 13
+               }
+       },
+       {#State 2
+               ACTIONS => {
+                       "F" => 17,
+                       "Ca" => 23,
+                       "P" => 20,
+                       "Si" => 19
+               },
+               GOTOS => {
+                       'P' => 18,
+                       'Si' => 22,
+                       'Ca' => 16,
+                       'F' => 21
+               }
+       },
+       {#State 3
+               DEFAULT => -19
+       },
+       {#State 4
+               DEFAULT => -33
+       },
+       {#State 5
+               ACTIONS => {
+                       "Th" => 28,
+                       "Al" => 24,
+                       'Rn' => 27
+               },
+               GOTOS => {
+                       'Th' => 25,
+                       'Al' => 26
+               }
+       },
+       {#State 6
+               ACTIONS => {
+                       '' => 29
+               }
+       },
+       {#State 7
+               ACTIONS => {
+                       'Rn' => 30
+               }
+       },
+       {#State 8
+               DEFAULT => -36
+       },
+       {#State 9
+               DEFAULT => -55
+       },
+       {#State 10
+               DEFAULT => -30
+       },
+       {#State 11
+               ACTIONS => {
+                       "Ca" => 23,
+                       "F" => 17,
+                       "P" => 20,
+                       "Si" => 19
+               },
+               GOTOS => {
+                       'F' => 33,
+                       'Ca' => 31,
+                       'Si' => 34,
+                       'P' => 32
+               }
+       },
+       {#State 12
+               DEFAULT => -4
+       },
+       {#State 13
+               ACTIONS => {
+                       "Mg" => 10,
+                       "B" => 12,
+                       'Rn' => 38,
+                       "Ti" => 15
+               },
+               GOTOS => {
+                       'B' => 35,
+                       'Mg' => 37,
+                       'Ti' => 36
+               }
+       },
+       {#State 14
+               ACTIONS => {
+                       "Si" => 19,
+                       "P" => 20,
+                       "F" => 17,
+                       "Ca" => 23
+               },
+               GOTOS => {
+                       'F' => 41,
+                       'Ca' => 40,
+                       'Si' => 34,
+                       'P' => 39
+               }
+       },
+       {#State 15
+               DEFAULT => -50
+       },
+       {#State 16
+               ACTIONS => {
+                       "P" => 20,
+                       "Si" => 19,
+                       "F" => 17,
+                       "Ca" => 23
+               },
+               GOTOS => {
+                       'Si' => 45,
+                       'P' => 43,
+                       'Ca' => 42,
+                       'F' => 44
+               }
+       },
+       {#State 17
+               DEFAULT => -15
+       },
+       {#State 18
+               ACTIONS => {
+                       "B" => 12,
+                       "Mg" => 10,
+                       "Ti" => 15,
+                       'Rn' => 47
+               },
+               GOTOS => {
+                       'B' => 49,
+                       'Mg' => 46,
+                       'Ti' => 48
+               }
+       },
+       {#State 19
+               DEFAULT => -46
+       },
+       {#State 20
+               DEFAULT => -42
+       },
+       {#State 21
+               DEFAULT => -53
+       },
+       {#State 22
+               ACTIONS => {
+                       "Th" => 28,
+                       'Rn' => 51,
+                       "Al" => 24
+               },
+               GOTOS => {
+                       'Th' => 50,
+                       'Al' => 52
+               }
+       },
+       {#State 23
+               DEFAULT => -8
+       },
+       {#State 24
+               DEFAULT => -1
+       },
+       {#State 25
+               ACTIONS => {
+                       "F" => 17,
+                       'Rn' => 53,
+                       "Ca" => 23,
+                       "Si" => 19,
+                       "P" => 20
+               },
+               GOTOS => {
+                       'Si' => 34,
+                       'P' => 32,
+                       'Ca' => 55,
+                       'F' => 54
+               }
+       },
+       {#State 26
+               DEFAULT => -54
+       },
+       {#State 27
+               ACTIONS => {
+                       "Ca" => 23,
+                       "Si" => 19,
+                       "P" => 20,
+                       "Mg" => 10,
+                       "F" => 17,
+                       "Ti" => 15,
+                       "B" => 12
+               },
+               GOTOS => {
+                       'Mg' => 58,
+                       'F' => 56,
+                       'Si' => 34,
+                       'Ti' => 59,
+                       'B' => 57,
+                       'Ca' => 31,
+                       'P' => 32
+               }
+       },
+       {#State 28
+               DEFAULT => -48
+       },
+       {#State 29
+               DEFAULT => 0
+       },
+       {#State 30
+               ACTIONS => {
+                       "Al" => 24,
+                       "Ti" => 15,
+                       "F" => 17,
+                       "B" => 12,
+                       "Ca" => 23,
+                       "Th" => 28,
+                       "Mg" => 10,
+                       "P" => 20,
+                       "Si" => 19
+               },
+               GOTOS => {
+                       'F' => 62,
+                       'Mg' => 60,
+                       'Si' => 34,
+                       'Al' => 63,
+                       'Th' => 61,
+                       'Ca' => 31,
+                       'B' => 57,
+                       'Ti' => 59,
+                       'P' => 32
+               }
+       },
+       {#State 31
+               ACTIONS => {
+                       "Ca" => 23,
+                       "F" => 17,
+                       "Si" => 19,
+                       "P" => 20
+               },
+               GOTOS => {
+                       'Si' => 45,
+                       'P' => 43,
+                       'Ca' => 42,
+                       'F' => 44
+               }
+       },
+       {#State 32
+               ACTIONS => {
+                       "B" => 12,
+                       "Mg" => 10,
+                       "Ti" => 15,
+                       'Rn' => 47
+               },
+               GOTOS => {
+                       'Mg' => 46,
+                       'B' => 49,
+                       'Ti' => 48
+               }
+       },
+       {#State 33
+               ACTIONS => {
+                       'Ar' => 64
+               }
+       },
+       {#State 34
+               ACTIONS => {
+                       "Th" => 28,
+                       "Al" => 24,
+                       'Rn' => 51
+               },
+               GOTOS => {
+                       'Al' => 52,
+                       'Th' => 50
+               }
+       },
+       {#State 35
+               ACTIONS => {
+                       "Ca" => 23,
+                       "Si" => 19,
+                       "P" => 20,
+                       "F" => 17
+               },
+               DEFAULT => -6,
+               GOTOS => {
+                       'Ca' => 40,
+                       'F' => 41,
+                       'P' => 39,
+                       'Si' => 34
+               }
+       },
+       {#State 36
+               ACTIONS => {
+                       "Mg" => 10,
+                       "B" => 12,
+                       "Ti" => 15,
+                       'Rn' => 38
+               },
+               GOTOS => {
+                       'Mg' => 37,
+                       'B' => 35,
+                       'Ti' => 36
+               }
+       },
+       {#State 37
+               DEFAULT => -32
+       },
+       {#State 38
+               ACTIONS => {
+                       "Si" => 19,
+                       "P" => 20,
+                       "F" => 17,
+                       "Ca" => 23
+               },
+               GOTOS => {
+                       'Si' => 34,
+                       'P' => 32,
+                       'Ca' => 31,
+                       'F' => 65
+               }
+       },
+       {#State 39
+               ACTIONS => {
+                       "Ti" => 15,
+                       'Rn' => 47,
+                       "Mg" => 10,
+                       "B" => 12
+               },
+               GOTOS => {
+                       'Ti' => 48,
+                       'Mg' => 46,
+                       'B' => 49
+               }
+       },
+       {#State 40
+               ACTIONS => {
+                       "F" => 17,
+                       "Ca" => 23,
+                       "Si" => 19,
+                       "P" => 20
+               },
+               DEFAULT => -5,
+               GOTOS => {
+                       'Si' => 45,
+                       'P' => 43,
+                       'Ca' => 42,
+                       'F' => 44
+               }
+       },
+       {#State 41
+               DEFAULT => -31
+       },
+       {#State 42
+               ACTIONS => {
+                       "F" => 17,
+                       "Si" => 19,
+                       "P" => 20,
+                       "Ca" => 23
+               },
+               DEFAULT => -9,
+               GOTOS => {
+                       'P' => 43,
+                       'Si' => 45,
+                       'F' => 44,
+                       'Ca' => 42
+               }
+       },
+       {#State 43
+               ACTIONS => {
+                       "Mg" => 10,
+                       "B" => 12,
+                       "Ti" => 15,
+                       'Rn' => 47
+               },
+               GOTOS => {
+                       'Mg' => 46,
+                       'Ti' => 48,
+                       'B' => 49
+               }
+       },
+       {#State 44
+               DEFAULT => -16
+       },
+       {#State 45
+               ACTIONS => {
+                       "Al" => 24,
+                       'Rn' => 51,
+                       "Th" => 28
+               },
+               GOTOS => {
+                       'Al' => 52,
+                       'Th' => 50
+               }
+       },
+       {#State 46
+               DEFAULT => -17
+       },
+       {#State 47
+               ACTIONS => {
+                       "F" => 17,
+                       "Ca" => 23,
+                       "Si" => 19,
+                       "P" => 20
+               },
+               GOTOS => {
+                       'F' => 66,
+                       'Ca' => 31,
+                       'P' => 32,
+                       'Si' => 34
+               }
+       },
+       {#State 48
+               ACTIONS => {
+                       "Ti" => 15,
+                       'Rn' => 38,
+                       "B" => 12,
+                       "Mg" => 10
+               },
+               GOTOS => {
+                       'Mg' => 37,
+                       'Ti' => 36,
+                       'B' => 35
+               }
+       },
+       {#State 49
+               ACTIONS => {
+                       "F" => 17,
+                       "P" => 20,
+                       "Si" => 19,
+                       "Ca" => 23
+               },
+               DEFAULT => -10,
+               GOTOS => {
+                       'Si' => 34,
+                       'P' => 39,
+                       'F' => 41,
+                       'Ca' => 40
+               }
+       },
+       {#State 50
+               ACTIONS => {
+                       "Si" => 19,
+                       "P" => 20,
+                       "Ca" => 23,
+                       'Rn' => 53,
+                       "F" => 17
+               },
+               GOTOS => {
+                       'Ca' => 55,
+                       'F' => 54,
+                       'Si' => 34,
+                       'P' => 32
+               }
+       },
+       {#State 51
+               ACTIONS => {
+                       "F" => 17,
+                       "Ti" => 15,
+                       "B" => 12,
+                       "Ca" => 23,
+                       "Mg" => 10,
+                       "Si" => 19,
+                       "P" => 20
+               },
+               GOTOS => {
+                       'Mg' => 68,
+                       'F' => 67,
+                       'Si' => 34,
+                       'B' => 57,
+                       'Ti' => 59,
+                       'Ca' => 31,
+                       'P' => 32
+               }
+       },
+       {#State 52
+               DEFAULT => -18
+       },
+       {#State 53
+               ACTIONS => {
+                       "Ca" => 23,
+                       "F" => 17,
+                       "Si" => 19,
+                       "P" => 20
+               },
+               GOTOS => {
+                       'P' => 32,
+                       'Si' => 34,
+                       'F' => 69,
+                       'Ca' => 31
+               }
+       },
+       {#State 54
+               DEFAULT => -2
+       },
+       {#State 55
+               ACTIONS => {
+                       "P" => 20,
+                       "Si" => 19,
+                       "Ca" => 23,
+                       "F" => 17
+               },
+               DEFAULT => -49,
+               GOTOS => {
+                       'Si' => 45,
+                       'P' => 43,
+                       'Ca' => 42,
+                       'F' => 44
+               }
+       },
+       {#State 56
+               ACTIONS => {
+                       'Y' => 70,
+                       'Ar' => 71
+               }
+       },
+       {#State 57
+               ACTIONS => {
+                       "F" => 17,
+                       "Ca" => 23,
+                       "P" => 20,
+                       "Si" => 19
+               },
+               GOTOS => {
+                       'Si' => 34,
+                       'P' => 39,
+                       'F' => 41,
+                       'Ca' => 40
+               }
+       },
+       {#State 58
+               ACTIONS => {
+                       'Ar' => 72
+               }
+       },
+       {#State 59
+               ACTIONS => {
+                       "Mg" => 10,
+                       "B" => 12,
+                       "Ti" => 15,
+                       'Rn' => 38
+               },
+               GOTOS => {
+                       'B' => 35,
+                       'Ti' => 36,
+                       'Mg' => 37
+               }
+       },
+       {#State 60
+               ACTIONS => {
+                       'Ar' => 73,
+                       'Y' => 74
+               }
+       },
+       {#State 61
+               ACTIONS => {
+                       "P" => 20,
+                       "Si" => 19,
+                       "Ca" => 23,
+                       'Rn' => 53,
+                       "F" => 17
+               },
+               GOTOS => {
+                       'Si' => 34,
+                       'P' => 32,
+                       'F' => 54,
+                       'Ca' => 55
+               }
+       },
+       {#State 62
+               ACTIONS => {
+                       'Ar' => 75,
+                       'Y' => 76
+               }
+       },
+       {#State 63
+               ACTIONS => {
+                       'Ar' => 77
+               }
+       },
+       {#State 64
+               DEFAULT => -29
+       },
+       {#State 65
+               ACTIONS => {
+                       'Ar' => 78
+               }
+       },
+       {#State 66
+               ACTIONS => {
+                       'Ar' => 79
+               }
+       },
+       {#State 67
+               ACTIONS => {
+                       'Y' => 81,
+                       'Ar' => 80
+               }
+       },
+       {#State 68
+               ACTIONS => {
+                       'Ar' => 82
+               }
+       },
+       {#State 69
+               ACTIONS => {
+                       'Ar' => 83
+               }
+       },
+       {#State 70
+               ACTIONS => {
+                       "Si" => 19,
+                       "P" => 20,
+                       "Ca" => 23,
+                       "F" => 17
+               },
+               GOTOS => {
+                       'Si' => 34,
+                       'P' => 32,
+                       'Ca' => 31,
+                       'F' => 84
+               }
+       },
+       {#State 71
+               DEFAULT => -40
+       },
+       {#State 72
+               DEFAULT => -26
+       },
+       {#State 73
+               DEFAULT => -38
+       },
+       {#State 74
+               ACTIONS => {
+                       "Si" => 19,
+                       "P" => 20,
+                       "Ca" => 23,
+                       "F" => 17
+               },
+               GOTOS => {
+                       'P' => 32,
+                       'Si' => 34,
+                       'Ca' => 31,
+                       'F' => 85
+               }
+       },
+       {#State 75
+               DEFAULT => -34
+       },
+       {#State 76
+               ACTIONS => {
+                       "B" => 12,
+                       "F" => 17,
+                       "Ti" => 15,
+                       "Mg" => 10,
+                       "Si" => 19,
+                       "P" => 20,
+                       "Ca" => 23
+               },
+               GOTOS => {
+                       'P' => 32,
+                       'Ti' => 59,
+                       'B' => 57,
+                       'Ca' => 31,
+                       'Si' => 34,
+                       'Mg' => 87,
+                       'F' => 86
+               }
+       },
+       {#State 77
+               DEFAULT => -20
+       },
+       {#State 78
+               DEFAULT => -7
+       },
+       {#State 79
+               DEFAULT => -11
+       },
+       {#State 80
+               DEFAULT => -45
+       },
+       {#State 81
+               ACTIONS => {
+                       "Ca" => 23,
+                       "F" => 17,
+                       "Si" => 19,
+                       "P" => 20
+               },
+               GOTOS => {
+                       'Si' => 34,
+                       'P' => 32,
+                       'Ca' => 31,
+                       'F' => 88
+               }
+       },
+       {#State 82
+               DEFAULT => -13
+       },
+       {#State 83
+               DEFAULT => -3
+       },
+       {#State 84
+               ACTIONS => {
+                       'Ar' => 89
+               }
+       },
+       {#State 85
+               ACTIONS => {
+                       'Ar' => 90
+               }
+       },
+       {#State 86
+               ACTIONS => {
+                       'Y' => 91,
+                       'Ar' => 92
+               }
+       },
+       {#State 87
+               ACTIONS => {
+                       'Ar' => 93
+               }
+       },
+       {#State 88
+               ACTIONS => {
+                       'Ar' => 94
+               }
+       },
+       {#State 89
+               DEFAULT => -25
+       },
+       {#State 90
+               DEFAULT => -23
+       },
+       {#State 91
+               ACTIONS => {
+                       "F" => 17,
+                       "Ca" => 23,
+                       "P" => 20,
+                       "Si" => 19
+               },
+               GOTOS => {
+                       'Si' => 34,
+                       'P' => 32,
+                       'F' => 95,
+                       'Ca' => 31
+               }
+       },
+       {#State 92
+               DEFAULT => -37
+       },
+       {#State 93
+               DEFAULT => -22
+       },
+       {#State 94
+               DEFAULT => -12
+       },
+       {#State 95
+               ACTIONS => {
+                       'Ar' => 96
+               }
+       },
+       {#State 96
+               DEFAULT => -21
+       }
+],
+                                  yyrules  =>
+[
+       [#Rule 0
+                '$start', 2, undef
+       ],
+       [#Rule 1
+                'Al', 1, undef
+       ],
+       [#Rule 2
+                'Al', 2,
+sub
+#line 10 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 3
+                'Al', 4,
+sub
+#line 11 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 4
+                'B', 1, undef
+       ],
+       [#Rule 5
+                'B', 2,
+sub
+#line 14 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 6
+                'B', 2,
+sub
+#line 15 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 7
+                'B', 4,
+sub
+#line 16 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 8
+                'Ca', 1, undef
+       ],
+       [#Rule 9
+                'Ca', 2,
+sub
+#line 19 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 10
+                'Ca', 2,
+sub
+#line 20 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 11
+                'Ca', 4,
+sub
+#line 21 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 12
+                'Ca', 6,
+sub
+#line 22 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 13
+                'Ca', 4,
+sub
+#line 23 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 14
+                'Ca', 2,
+sub
+#line 24 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 15
+                'F', 1, undef
+       ],
+       [#Rule 16
+                'F', 2,
+sub
+#line 27 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 17
+                'F', 2,
+sub
+#line 28 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 18
+                'F', 2,
+sub
+#line 29 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 19
+                'H', 1, undef
+       ],
+       [#Rule 20
+                'H', 4,
+sub
+#line 32 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 21
+                'H', 8,
+sub
+#line 33 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 22
+                'H', 6,
+sub
+#line 34 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 23
+                'H', 6,
+sub
+#line 35 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 24
+                'H', 2,
+sub
+#line 36 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 25
+                'H', 6,
+sub
+#line 37 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 26
+                'H', 4,
+sub
+#line 38 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 27
+                'H', 2,
+sub
+#line 39 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 28
+                'H', 2,
+sub
+#line 40 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 29
+                'H', 4,
+sub
+#line 41 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 30
+                'Mg', 1, undef
+       ],
+       [#Rule 31
+                'Mg', 2,
+sub
+#line 44 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 32
+                'Mg', 2,
+sub
+#line 45 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 33
+                'N', 1, undef
+       ],
+       [#Rule 34
+                'N', 4,
+sub
+#line 48 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 35
+                'N', 2,
+sub
+#line 49 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 36
+                'O', 1, undef
+       ],
+       [#Rule 37
+                'O', 6,
+sub
+#line 52 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 38
+                'O', 4,
+sub
+#line 53 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 39
+                'O', 2,
+sub
+#line 54 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 40
+                'O', 4,
+sub
+#line 55 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 41
+                'O', 2,
+sub
+#line 56 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 42
+                'P', 1, undef
+       ],
+       [#Rule 43
+                'P', 2,
+sub
+#line 59 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 44
+                'P', 2,
+sub
+#line 60 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 45
+                'P', 4,
+sub
+#line 61 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 46
+                'Si', 1, undef
+       ],
+       [#Rule 47
+                'Si', 2,
+sub
+#line 64 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 48
+                'Th', 1, undef
+       ],
+       [#Rule 49
+                'Th', 2,
+sub
+#line 67 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 50
+                'Ti', 1, undef
+       ],
+       [#Rule 51
+                'Ti', 2,
+sub
+#line 70 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 52
+                'Ti', 2,
+sub
+#line 71 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 53
+                'e', 2,
+sub
+#line 74 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 54
+                'e', 2,
+sub
+#line 75 "task38.yp"
+{ shift->YYData->{count}++ }
+       ],
+       [#Rule 55
+                'e', 2,
+sub
+#line 76 "task38.yp"
+{ shift->YYData->{count}++ }
+       ]
+],
+                                  @_);
+    bless($self,$class);
+}
+
+#line 78 "task38.yp"
+
+
+1;
diff --git a/2015/y/parse.pl b/2015/y/parse.pl
new file mode 100755 (executable)
index 0000000..bda1c0b
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl -w
+
+use v5.16;
+use lib '.';
+use Parser;
+
+my @data = split /(?=[A-Z])/, 'ORnPBPMgArCaCaCaSiThCaCaSiThCaCaPBSiRnFArRnFArCaCaSiThCaCaSiThCaCaCaCaCaCaSiRnFYFArSiRnMgArCaSiRnPTiTiBFYPBFArSiRnCaSiRnTiRnFArSiAlArPTiBPTiRnCaSiAlArCaPTiTiBPMgYFArPTiRnFArSiRnCaCaFArRnCaFArCaSiRnSiRnMgArFYCaSiRnMgArCaCaSiThPRnFArPBCaSiRnMgArCaCaSiThCaSiRnTiMgArFArSiThSiThCaCaSiRnMgArCaCaSiRnFArTiBPTiRnCaSiAlArCaPTiRnFArPBPBCaCaSiThCaPBSiThPRnFArSiThCaSiThCaSiThCaPTiBSiRnFYFArCaCaPRnFArPBCaCaPBSiRnTiRnFArCaPRnFArSiRnCaCaCaSiThCaRnCaFArYCaSiRnFArBCaCaCaSiThFArPBFArCaSiRnFArRnCaCaCaFArSiRnFArTiRnPMgArF';
+
+my $p = new Parser;
+$p->YYParse(yylex => sub { my $elem = shift @data; return ($elem, $elem); });
+
+say $p->YYData->{count};
+
diff --git a/2015/y/task38.yp b/2015/y/task38.yp
new file mode 100644 (file)
index 0000000..84145e4
--- /dev/null
@@ -0,0 +1,78 @@
+%{
+       my $count = 0;
+%}
+
+%start e
+
+%%
+
+Al :   'Al'
+       |  Th F { shift->YYData->{count}++ }
+       |  Th Rn F Ar { shift->YYData->{count}++ }
+       ;
+B :    'B'
+       |  B Ca { shift->YYData->{count}++ }
+       |  Ti B { shift->YYData->{count}++ }
+       |  Ti Rn F Ar { shift->YYData->{count}++ }
+       ;
+Ca :   'Ca'
+       |  Ca Ca { shift->YYData->{count}++ }
+       |  P B { shift->YYData->{count}++ }
+       |  P Rn F Ar { shift->YYData->{count}++ }
+       |  Si Rn F Y F Ar { shift->YYData->{count}++ }
+       |  Si Rn Mg Ar { shift->YYData->{count}++ }
+       |  Si Th { shift->YYData->{count}++ }
+       ;
+F :    'F'
+       |  Ca F { shift->YYData->{count}++ }
+       |  P Mg { shift->YYData->{count}++ }
+       |  Si Al { shift->YYData->{count}++ }
+       ;
+H :    'H'
+       |  C Rn Al Ar { shift->YYData->{count}++ }
+       |  C Rn F Y F Y F Ar { shift->YYData->{count}++ }
+       |  C Rn F Y Mg Ar { shift->YYData->{count}++ }
+       |  C Rn Mg Y F Ar { shift->YYData->{count}++ }
+       |  H Ca { shift->YYData->{count}++ }
+       |  N Rn F Y F Ar { shift->YYData->{count}++ }
+       |  N Rn Mg Ar { shift->YYData->{count}++ }
+       |  N Th { shift->YYData->{count}++ }
+       |  O B { shift->YYData->{count}++ }
+       |  O Rn F Ar { shift->YYData->{count}++ }
+       ;
+Mg :   'Mg'
+       |  B F { shift->YYData->{count}++ }
+       |  Ti Mg { shift->YYData->{count}++ }
+       ;
+N :    'N'
+       |  C Rn F Ar { shift->YYData->{count}++ }
+       |  H Si { shift->YYData->{count}++ }
+       ;
+O :    'O'
+       |  C Rn F Y F Ar { shift->YYData->{count}++ }
+       |  C Rn Mg Ar { shift->YYData->{count}++ }
+       |  H P { shift->YYData->{count}++ }
+       |  N Rn F Ar { shift->YYData->{count}++ }
+       |  O Ti { shift->YYData->{count}++ }
+       ;
+P :    'P'
+       |  Ca P { shift->YYData->{count}++ }
+       |  P Ti { shift->YYData->{count}++ }
+       |  Si Rn F Ar { shift->YYData->{count}++ }
+       ;
+Si :   'Si'
+       |  Ca Si { shift->YYData->{count}++ }
+       ;
+Th :   'Th'
+       |  Th Ca { shift->YYData->{count}++ }
+       ;
+Ti :   'Ti'
+       |  B P { shift->YYData->{count}++ }
+       |  Ti Ti { shift->YYData->{count}++ }
+       ;
+e:
+          H F { shift->YYData->{count}++ }
+       |  N Al { shift->YYData->{count}++ }
+       |  O Mg { shift->YYData->{count}++ }
+       ;
+%%
diff --git a/2015/y/test.yp b/2015/y/test.yp
new file mode 100644 (file)
index 0000000..7b2c4a0
--- /dev/null
@@ -0,0 +1,32 @@
+%start e
+
+%%
+
+O :
+         C Rn F Y F Ar { $count++ }
+       | C Rn Mg Ar { $count++ }
+       | H P { $count++ }
+       | N Rn F Ar { $count++ }
+       | O Ti { $count++ }
+       ;
+P :
+         Ca P { $count++ }
+       | P Ti { $count++ }
+       | Si Rn F Ar { $count++ }
+       ;
+Si :
+         Ca Si { $count++ }
+       ;
+Th :
+         Th Ca { $count++ }
+       ;
+Ti :
+         B P { $count++ }
+       | Ti Ti { $count++ }
+       ;
+e :
+         H F { $count++ }
+       | N Al { $count++ }
+       | O Mg { $count++ }
+       ;
+%%