]> www.fi.muni.cz Git - aoc.git/blob - 2018/40.pl
Year 2018
[aoc.git] / 2018 / 40.pl
1 #!/usr/bin/perl -w
2
3 use v5.36;
4 use strict;
5 use List::Util qw(max);
6 use feature 'multidimensional';
7
8 my (%hdoor, %vdoor);
9 my ($minx, $miny, $maxx, $maxy) = (0, 0, 0, 0);
10 my $was_change;
11 my $maxdist;
12 chomp (my $re = <>);
13
14 $re =~ s/\A\^//;
15 $re =~ s/\$\z//;
16
17 sub walk($positions, $re) {
18         my @npos;
19         my %seen;
20         for my $p (@$positions) {
21                 next if $seen{$p->[0],$p->[1]}++;
22                 push @npos, [ @$p ];
23         }
24
25         say "len=", length($re), " npos=", scalar @npos;
26
27         my @rv;
28
29         while (length $re) {
30                 my ($first, $rest) = $re =~ /\A(.)(.*)\z/;
31
32                 if ($first =~ /[NSWE]/) {
33                         for my $p (@npos) {
34                                 my ($x, $y) = @$p;
35                                 if    ($first eq 'N') { $hdoor{$x,$y} = 1; $y--; }
36                                 elsif ($first eq 'S') { $y++; $hdoor{$x,$y} = 1; }
37                                 elsif ($first eq 'W') { $vdoor{$x,$y} = 1; $x--; }
38                                 elsif ($first eq 'E') { $x++; $vdoor{$x,$y} = 1; }
39                                 $p->[0] = $x;
40                                 $p->[1] = $y;
41                                 $minx = $x if $minx > $x;
42                                 $maxx = $x if $maxx < $x;
43                                 $miny = $y if $miny > $y;
44                                 $maxy = $y if $maxy < $y;
45                         }
46                 } elsif ($first eq '|') {
47                         push @rv, @npos;
48                         @npos = map { [ @$_ ] } @$positions;
49                 } elsif ($first eq ')') {
50                         push @rv, @npos;
51                         return (\@rv, $rest);
52                 } elsif ($first eq '(') {
53                         my ($n, $re1) = walk(\@npos, $rest);
54                         @npos = @$n;
55                         $rest = $re1;
56                 }
57                 $re = $rest;
58         }
59         return (\@npos, '');
60 }
61
62 sub print_map {
63         for my $y ($miny .. $maxy+1) {
64                 for my $x ($minx .. $maxx) {
65                         print $hdoor{$x,$y} ? '#-' : '##';
66                 }
67                 print "#\n";
68                 if ($y <= $maxy) {
69                         for my $x ($minx .. $maxx) {
70                                 print $vdoor{$x,$y} ? '|.' : '#.';
71                         }
72                         print "#\n";
73                 }
74         }
75 }
76
77 walk([ [0, 0] ], $re);
78 print_map();
79
80 my @q = ([ 0, 0, 0 ]);
81 my %seen;
82 $seen{0,0} = 1;
83 my $max_dist = 0;
84 my $rooms = 0;
85
86 while (@q) {
87         my $h = shift @q;
88         my ($x, $y, $dist) = @$h;
89         $rooms++ if $dist >= 1000;
90         
91         if (!$max_dist || $dist > $max_dist) {
92                 $max_dist = $dist;
93         }
94         if ($hdoor{$x,$y} && !$seen{$x,$y-1}++) {
95                 push @q, [$x, $y-1, $dist+1];
96         }
97         if ($hdoor{$x,$y+1} && !$seen{$x,$y+1}++) {
98                 push @q, [$x, $y+1, $dist+1];
99         }
100         if ($vdoor{$x,$y} && !$seen{$x-1,$y}++) {
101                 push @q, [$x-1, $y, $dist+1];
102         }
103         if ($vdoor{$x+1,$y} && !$seen{$x+1,$y}++) {
104                 push @q, [$x+1, $y, $dist+1];
105         }
106 }
107
108 say $max_dist;
109
110 say $rooms;