]> www.fi.muni.cz Git - aoc2020.git/blob - 40.pl
Task 9 Perl Golf-style
[aoc2020.git] / 40.pl
1 #!/usr/bin/perl -w
2
3 use strict;
4
5 sub rows2str {
6         my (@rows) = @_;
7         return join("\n", @rows) . "\n";
8 }
9
10 sub rotate {
11         my ($str) = (@_);
12         my $dim =()= $str =~ /(\n)/g;
13         my $newstr = '';
14         for my $y (0 .. $dim-1) {
15                 for my $x (0 .. $dim-1) {
16                         $newstr .= substr($str, $y + ($dim+1)*($dim - $x - 1), 1);
17                 }
18                 $newstr .= "\n";
19         }
20         return $newstr;
21 }
22
23 sub flip {
24         my ($str) = @_;
25         return rows2str(map { join('', reverse split //) } split /\n/, $str);
26 }
27
28 sub rotate_or_flip {
29         my ($str, $count) = @_;
30         return $count == 4 ? flip($str) : rotate($str);
31 }
32
33 sub trim {
34         my ($str) = @_;
35         my @rows = split /\n/, $str;
36         shift @rows;
37         pop @rows;
38         return map { s/\A.//; s/.\z//; $_ } @rows;
39 }
40
41 sub top_side {
42         $_[0] =~ /\A(.*?)\n/xms;
43         return $1;
44 }
45
46 sub bottom_side {
47         $_[0] =~ /\A.*\n(.*?)\n\z/xms;
48         return $1;
49 }
50
51 sub left_side {
52         return join('', map { substr($_, 0, 1) } split /\n/, $_[0]);
53 }
54
55 sub right_side {
56         return join('', map { substr($_, -1, 1) } split /\n/, $_[0]);
57 }
58
59 my (%top2tile, %left2tile);
60
61 local $/ = "\n\n";
62
63 while (<>) {
64         my ($id, $data) = /\ATile\s+(\d+):\n(.*?\n)\n?\z/xms;
65         for (1 .. 8) {
66                 push @{ $top2tile{top_side($data)} }, [ $id, $data ];
67                 push @{ $left2tile{left_side($data)} }, [ $id, $data ];
68                 $data = rotate_or_flip($data, $_);
69         }
70 }
71
72 # computed in 39.pl
73 my $dim = 12;
74 my $top_row = '###.#.#...';
75
76 # my $dim = 3;
77 # my $top_row = '#...##.#..';
78
79 my $top_id = -1;
80 my @map_rows;
81 my $data;
82
83 for my $y (0 .. $dim-1) {
84         my ($id)  = grep { $_->[0] != $top_id } @{ $top2tile{$top_row} };
85         ($top_id, $data) = @$id;
86         $top_row = bottom_side($data);
87
88         push @map_rows, trim($data);
89
90         my $right_id = $top_id;
91         my $right_row = right_side($data);
92
93         for my $x (1 .. $dim-1) {
94                 my ($id) = grep { $_->[0] != $right_id } @{ $left2tile{$right_row} };
95                 ($right_id, $data) = @$id;
96                 $right_row = right_side($data);
97
98                 my $i = @map_rows - 8;
99                 for (trim($data)) {
100                         $map_rows[$i++] .= $_;
101                 }
102         }
103 }
104
105 my $map = rows2str(@map_rows);
106 my $hashes =()= $map =~ /#/g;
107
108 my $monster = '.(?='
109         . join('[\.#\n]' x ($dim * 8 - 20 + 1),
110                 map { my $a=$_; $a=~ s/\./[\.#]/g; $a }
111                  '..................#.',
112                 '#....##....##....###',
113                 '.#..#..#..#..#..#...'
114         ) . ')';
115
116 for (1 .. 8) {
117         if (my $count =()= $map =~ /($monster)/g) {
118                 print "$count matches\n";
119                 print "$hashes-$count*15=", $hashes-$count*15, "\n";
120                 exit 0;
121         }
122         $map = rotate_or_flip($map, $_);
123 }
124