]> www.fi.muni.cz Git - aoc.git/blob - 2023/28.pl
Day 14: ugly but fast written solution
[aoc.git] / 2023 / 28.pl
1 #!/usr/bin/perl -w
2
3 use v5.38;
4
5 my @map = map { chomp; [ split // ] } <>;
6 my $xmax = $#{ $map[0] };
7 my $ymax = $#map;
8
9 my %seen;
10 my @rounds;
11 my $round;
12 while (1) {
13         $round++;
14         my $retry;
15         $retry = 1;
16         while ($retry) {
17                 $retry = 0;
18                 for my $y (1 .. $ymax) {
19                         for my $x (0 .. $xmax) {
20                                 if ($map[$y][$x] eq 'O' && $map[$y-1][$x] eq '.') {
21                                         $map[$y-1][$x] = 'O';
22                                         $map[$y][$x] = '.';
23                                         $retry = 1;
24                                 }
25                         }
26                 }
27         }
28         $retry = 1;
29         while ($retry) {
30                 $retry = 0;
31                 for my $x (1 .. $xmax) {
32                         for my $y (0 .. $ymax) {
33                                 if ($map[$y][$x] eq 'O' && $map[$y][$x-1] eq '.') {
34                                         $map[$y][$x-1] = 'O';
35                                         $map[$y][$x] = '.';
36                                         $retry = 1;
37                                 }
38                         }
39                 }
40         }
41         $retry = 1;
42         while ($retry) {
43                 $retry = 0;
44                 for my $y (reverse 0 .. $ymax-1) {
45                         for my $x (0 .. $xmax) {
46                                 if ($map[$y][$x] eq 'O' && $map[$y+1][$x] eq '.') {
47                                         $map[$y+1][$x] = 'O';
48                                         $map[$y][$x] = '.';
49                                         $retry = 1;
50                                 }
51                         }
52                 }
53         }
54         $retry = 1;
55         while ($retry) {
56                 $retry = 0;
57                 for my $x (reverse 0 .. $xmax-1) {
58                         for my $y (0 .. $ymax) {
59                                 if ($map[$y][$x] eq 'O' && $map[$y][$x+1] eq '.') {
60                                         $map[$y][$x+1] = 'O';
61                                         $map[$y][$x] = '.';
62                                         $retry = 1;
63                                 }
64                         }
65                 }
66         }
67                 
68         # say join('', @$_) for @map;
69
70         my $sum;
71         for my $y (0 .. $ymax) {
72                 for my $x (0 .. $xmax) {
73                         $sum += $ymax + 1 - $y if $map[$y][$x] eq 'O';
74                 }
75         }
76         say $sum;
77         $rounds[$round] = $sum;
78         say "round $round sum $sum";
79         my $map = join("\n", map { join('', @$_) } @map);
80         if ($seen{$map}) {
81                 say "round $round seen also at $seen{$map}";
82                 my $period = $round - $seen{$map};
83                 my $total = 1000000000;
84                 $total -= $round;
85                 $total %= $period;
86                 say "looking at ", $round - $period + $total;
87                 say $rounds[$round-$period+$total];
88                 last;
89         }
90         $seen{$map} = $round;
91 }
92