]> www.fi.muni.cz Git - aoc.git/blob - 2022/34.pl
Day 25: examining the input
[aoc.git] / 2022 / 34.pl
1 #!/usr/bin/perl -w
2
3 use v5.36;
4 use strict;
5
6 $_ = <>;
7 my @moves = /(\S)/g;
8
9 my @units = (
10         [ [0, 0], [1, 0], [2, 0], [3, 0] ], # horiz i
11         [ [0, 1], [1, 1], [2, 1], [1, 0], [1, 2] ], # x
12         [ [0, 0], [1, 0], [2, 0], [2, 1], [2, 2] ], # v
13         [ [0, 0], [0, 1], [0, 2], [0, 3] ], # vert i
14         [ [0, 0], [0, 1], [1, 0], [1, 1] ], # o
15 );
16
17 my $w = 7;
18 my $h = 0;
19 my @map;
20 my $map_top = 0;
21 my $max_map = 100;
22
23 my $units = 0;
24 my $move = 0;
25
26 sub can_move($unit, $vect) {
27         # say "can_move $vect->[0] $vect->[1]";
28         for my $pt (@$unit) {
29                 my @dst = ($pt->[0] + $vect->[0], $pt->[1] + $vect->[1]);
30                 return 0 if $dst[0] < 0 || $dst[0] >= $w;
31                 return 0 if $dst[1] < 0;
32                 return 0 if $map[$dst[1]-$map_top][$dst[0]];
33         }
34         return 1;
35 }
36
37 sub move_unit {
38         my $u = $units[$units % @units];
39         # say "unit $units h=$h";
40         # say "$state";
41         my ($x, $y) = (2, $h+3);
42         while (1) {     
43                 my $m = $moves[$move++];
44                 # say "$x $y $m";
45                 $move = 0 if $move > $#moves;
46                 if ($m eq '>') {
47                         $x++ if can_move($u, [$x+1, $y]);
48                 } else {
49                         $x-- if can_move($u, [$x-1, $y]);
50                 }
51                 if (can_move($u, [$x, $y-1])) {
52                         $y--;
53                         next;
54                 }
55                 last;
56         }
57         for my $pt (@$u) {
58                 $map[$y + $pt->[1] - $map_top][$x + $pt->[0]] = 1;
59                 $h = 1 + $y + $pt->[1] if $h < 1 + $y + $pt->[1];
60                 while (@map > $max_map) {
61                         shift @map;
62                         $map_top++;
63                 }
64         }
65         $units++;
66 }
67
68 my %seen;
69
70 while (1) {
71         my $state = join(' ', $units % @units, $move);
72         for my $y (0 .. $#map) {
73                 my $n = 0;
74                 for my $x (0 .. $w-1) {
75                         $n <<= 1;
76                         $n |= 1 if $map[$y][$x];
77                 }
78                 $state .= sprintf(" %02x", $n);
79         }
80         if ($seen{$state}) {
81                 my ($first_u, $first_h) = $seen{$state} =~ /(\d+) (\d+)$/;
82                 my $u_diff = $units - $first_u;
83                 my $h_diff = $h - $first_h;
84                 # say "$state $units $h\n$seen{$state}\n\n";
85                 my $n = int((1000000000000-$units)/$u_diff);
86                 $h += $n * $h_diff;
87                 $map_top += $n * $h_diff;
88                 $units += $n * $u_diff;
89                 while ($units < 1000000000000) {
90                         move_unit;
91                 }
92                 last;
93         }
94         $seen{$state} = $state . " $units $h";
95         move_unit;
96 }
97
98 say $h;