X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=aoc2020.git;a=blobdiff_plain;f=40.pl;h=074e56152106287dd84e4420d59c428cfeac882d;hp=df479d91baa74f58b8d4e6935eee2b2eb1de1fe5;hb=HEAD;hpb=3dcbc8cbbed0a020192974ba29b73f0164b49ce2 diff --git a/40.pl b/40.pl index df479d9..074e561 100755 --- a/40.pl +++ b/40.pl @@ -2,157 +2,123 @@ use strict; -local $/ = "\n\n"; +sub rows2str { + my (@rows) = @_; + return join("\n", @rows) . "\n"; +} -sub rev { - my ($in) = @_; - return join('', reverse split //, $in); +sub rotate { + my ($str) = (@_); + my $dim =()= $str =~ /(\n)/g; + my $newstr = ''; + for my $y (0 .. $dim-1) { + for my $x (0 .. $dim-1) { + $newstr .= substr($str, $y + ($dim+1)*($dim - $x - 1), 1); + } + $newstr .= "\n"; + } + return $newstr; } +sub flip { + my ($str) = @_; + return rows2str(map { join('', reverse split //) } split /\n/, $str); +} + +sub rotate_or_flip { + my ($str, $count) = @_; + return $count == 4 ? flip($str) : rotate($str); +} + +sub trim { + my ($str) = @_; + my @rows = split /\n/, $str; + shift @rows; + pop @rows; + return map { s/\A.//; s/.\z//; $_ } @rows; +} + +sub top_side { + $_[0] =~ /\A(.*?)\n/xms; + return $1; +} + +sub bottom_side { + $_[0] =~ /\A.*\n(.*?)\n\z/xms; + return $1; +} + +sub left_side { + return join('', map { substr($_, 0, 1) } split /\n/, $_[0]); +} + +sub right_side { + return join('', map { substr($_, -1, 1) } split /\n/, $_[0]); +} + +my (%top2tile, %left2tile); + +local $/ = "\n\n"; -my %tiles; -my %sides; -my %side2tiles; while (<>) { - my ($id, @rows) = split /\n/; - $id =~ s/Tile //; - $id =~ s/://; - $tiles{$id} = \@rows; - $sides{$id} = [ - $rows[0], - join('', map { substr($_, -1, 1) } @rows), - rev($rows[-1]), - rev(join('', map { substr($_, 0, 1) } @rows)), - ]; - print "Tile <$id> sides ", join(' ', @{ $sides{$id} }), "\n"; - my $i = 0; - for my $side (@{ $sides{$id} }) { - $side2tiles{$side}->{$id} = $i; - $side2tiles{rev($side)}->{$id} = $i+4; - $i++; + my ($id, $data) = /\ATile\s+(\d+):\n(.*?\n)\n?\z/xms; + for (1 .. 8) { + push @{ $top2tile{top_side($data)} }, [ $id, $data ]; + push @{ $left2tile{left_side($data)} }, [ $id, $data ]; + $data = rotate_or_flip($data, $_); } } +# computed in 39.pl my $dim = 12; -my $next = '###.#.#...'; +my $top_row = '###.#.#...'; # my $dim = 3; -# my $next = '#...##.#..'; -my $next_id = -1; -my $map; -my %seen; +# my $top_row = '#...##.#..'; + +my $top_id = -1; +my @map_rows; +my $data; for my $y (0 .. $dim-1) { - my ($id) = grep { $_ != $next_id } keys %{ $side2tiles{$next} }; - my $side = $side2tiles{$next}->{$id}; - $map->[$y][0] = [ $id, $side ]; - die "$id seen again\n" - if $seen{$id}; - $seen{$id} = 1; - my $next_side = $side > 3 - ? (($side - 1) & 3) - : ($side + 1) & 3; - $next = $sides{$id}->[$next_side]; - $next = rev($next) if $side > 3; - my $top_side = $side; - print "id=$id, side=$side, next_side=$next_side, top_side=$top_side, next=|$next|\n"; - $next_id = $id; - - for my $x (1 .. $dim-1) { - ($id) = grep { $_ != $next_id } keys %{ $side2tiles{$next} }; - $side = $side2tiles{$next}->{$id}; - die "$id seen again\n" - if $seen{$id}; - $seen{$id} = 1; - my $top_side = ((($side & 3) + (($side >> 2) ? 1 : -1)) & 3) | (($side & 4) ^ 4); - $map->[$y][$x] = [ $id, $top_side ]; - $next_side = (($side + 2) & 3); - $next = $sides{$id}->[$next_side]; - $next = rev($next) if $side < 4; - $next_id = $id; - print "id=$id, side=$side, next_side=$next_side, top_side=$top_side, next=|$next|\n"; - } + my ($id) = grep { $_->[0] != $top_id } @{ $top2tile{$top_row} }; + ($top_id, $data) = @$id; + $top_row = bottom_side($data); - print "\n"; + push @map_rows, trim($data); - ($next_id, $next_side) = @{ $map->[$y][0] }; - $next = $sides{$next_id}->[($next_side + 2) & 3]; - $next = rev($next) if $next_side < 4; - print "bottom side of $next_id = |$next|\n"; -} + my $right_id = $top_id; + my $right_row = right_side($data); + + for my $x (1 .. $dim-1) { + my ($id) = grep { $_->[0] != $right_id } @{ $left2tile{$right_row} }; + ($right_id, $data) = @$id; + $right_row = right_side($data); -my $shortmap = ''; -for my $y (0 .. 8*$dim-1) { - my $y1 = 1 + ($y % 8); - for my $x (0 .. 8*$dim-1) { - my $x1 = 1 + ($x % 8); - my ($id, $or) = @{ $map->[int($y/8)][int($x/8)] }; - my ($x2, $y2) = ($x1, $y1); - if ($or == 1) { - ($x2, $y2) = (9-$y1, $x1); - } elsif ($or == 2) { - ($x2, $y2) = (9-$x1, 9-$y1); - } elsif ($or == 3) { - ($x2, $y2) = ($y1, 9-$x1); - } elsif ($or == 4) { - ($x2, $y2) = (9-$x1, $y1); - } elsif ($or == 5) { - ($x2, $y2) = (9-$y1, 9-$x1); - } elsif ($or == 6) { - ($x2, $y2) = ($x1, 9-$y1); - } elsif ($or == 7) { - ($x2, $y2) = ($y1, $x1); + my $i = @map_rows - 8; + for (trim($data)) { + $map_rows[$i++] .= $_; } - $shortmap .= substr($tiles{$id}->[$y2], $x2, 1); } - $shortmap .= "\n"; } -print join("\n", $shortmap), "\n"; - -my $monster = join('[\.#\n]' x ($dim * 8 - 20 + 1), map { $a=$_; $a=~ s/\./[\.#]/g; $a } - '..................#.', - '#....##....##....###', - '.#..#..#..#..#..#...' -); - -$monster = ".(?=$monster)"; -print "monster=$monster\n"; - -for (1 .. 2) { - for (1 .. 4) { - my $count; - if (my $count =()= $shortmap =~ /($monster)/g) { - print "$count matches\n"; - my $hashes =()= $shortmap =~ /#/g; - print "$hashes-$count*15=", $hashes-$count*15, "\n"; - exit 0; - } - my $newmap = ''; - for my $y (0 .. 8*$dim-1) { - for my $x (0 .. 8*$dim-1) { - print "$x,$y\n"; - $newmap .= substr($shortmap, - $y + (8*$dim+1)*(8*$dim-$x-1), 1); - } - $newmap .= "\n"; - } - print "\nRotate:\n$newmap\n"; - $shortmap = $newmap; - } - my $newmap; - for my $y (0 .. 8*$dim-1) { - for my $x (0 .. 8*$dim-1) { - $newmap .= substr($shortmap, - $x + (8*$dim+1)*(8*$dim-$y-1), 1); - } - $newmap .= "\n"; +my $map = rows2str(@map_rows); +my $hashes =()= $map =~ /#/g; + +my $monster = '.(?=' + . join('[\.#\n]' x ($dim * 8 - 20 + 1), + map { my $a=$_; $a=~ s/\./[\.#]/g; $a } + '..................#.', + '#....##....##....###', + '.#..#..#..#..#..#...' + ) . ')'; + +for (1 .. 8) { + if (my $count =()= $map =~ /($monster)/g) { + print "$count matches\n"; + print "$hashes-$count*15=", $hashes-$count*15, "\n"; + exit 0; } - $shortmap = $newmap; - print "\nFlip:\n$newmap\n"; - + $map = rotate_or_flip($map, $_); } - - -