-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path08.pl
88 lines (79 loc) · 1.37 KB
/
08.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my @PROG;
while (<>) {
print;
chomp;
push @PROG, $_;
}
sub run {
my @PROG = @_;
my %SEEN;
my $pc = 0;
my $acc = 0;
while (!$SEEN{$pc}) {
$SEEN{$pc}++;
if ($pc > $#PROG) {
return $acc;
}
my $inst = $PROG[$pc];
$inst =~ m{^(\w+)\s+([-+]\d+)$};
my ($opc, $arg) = ($1, $2);
if ($opc eq "acc") {
$acc += $arg;
} elsif ($opc eq "jmp") {
$pc += $arg - 1;
}
$pc++;
}
return "fail";
}
my @REV;
for my $i (0..$#PROG) {
my $l = $PROG[$i];
$l =~ m{^(\w+)\s+([-+]\d+)$};
my ($opc, $arg) = ($1, $2);
my $target = $i + 1;
if ($opc eq "jmp") {
$target = $i + $arg;
}
push @{$REV[$target]}, $i;
}
my %endzone;
my @q = ($#PROG + 1);
while (@q) {
my $i = shift @q;
$endzone{$i}++;
for my $r (@{$REV[$i]}) {
if (!$endzone{$r}) {
push @q, $r;
}
}
}
my %SEEN;
my $pc = 0;
my $acc = 0;
while (!$SEEN{$pc}) {
$SEEN{$pc}++;
if ($pc > $#PROG) {
print "$acc\n";
exit;
}
my $inst = $PROG[$pc];
$inst =~ m{^(\w+)\s+([-+]\d+)$};
my $alt = $pc + 1;
my ($opc, $arg) = ($1, $2);
if ($opc eq "acc") {
$acc += $arg;
} elsif ($opc eq "jmp") {
$pc += $arg - 1;
} elsif ($opc eq "nop") {
$alt = $pc + $arg;
}
$pc++;
if (!$endzone{$pc} && $endzone{$alt}) {
print "Set PC from $pc to $alt\n";
$pc = $alt;
}
}