summaryrefslogtreecommitdiffstats
path: root/2019/day7/intcode.pl
diff options
context:
space:
mode:
Diffstat (limited to '2019/day7/intcode.pl')
-rw-r--r--2019/day7/intcode.pl109
1 files changed, 109 insertions, 0 deletions
diff --git a/2019/day7/intcode.pl b/2019/day7/intcode.pl
new file mode 100644
index 0000000..d83d2db
--- /dev/null
+++ b/2019/day7/intcode.pl
@@ -0,0 +1,109 @@
1use strict;
2use warnings;
3use Data::Dumper;
4# use Smart::Comments;
5use v5.10;
6
7$| = 1;
8
9sub pos {
10 my ($tape_ref, $index) = @_;
11 my @tape = @{ $tape_ref };
12 ### returning: $tape[$tape[$index]]
13 ### for: $index
14 return $tape[$tape[$index]];
15}
16
17sub imm {
18 my ($tape_ref, $index) = @_;
19 my @tape = @{ $tape_ref };
20 return $tape[$index];
21}
22
23my $file_name = $ARGV[0];
24
25if (not defined $file_name) {
26 die "missing filename\n";
27}
28
29open my $fh, "<", $file_name or die "Can't open $file_name, $!\n";
30
31my $inputline = <$fh>;
32chomp $inputline;
33my @tape = split /,/, $inputline;
34close $fh;
35
36my $pc = 0; # program counter is no longer consistent
37
38my @actions = (
39 sub { print "noop" }, # no opcode 0
40 sub { return $_[0] + $_[1] }, # 1
41 sub { return $_[0] * $_[1] }, # 2
42 sub {
43 print STDERR ("Getting input!\n");
44 my $in = <STDIN>;
45 print STDERR ("Read >$in<\n");
46 chomp $in;
47 return $in;
48 }, # 3
49 sub { say $_[0]; }, # 4
50 sub { return $_[0] ? $_[1] : -1 }, # 5, ugh, you might want to jump to 0
51 sub { return $_[0] ? -1 : $_[1] }, # 6
52 sub { return $_[0] < $_[1] ? 1 : 0}, # 7
53 sub { return $_[0] == $_[1] ? 1 : 0}, # 8
54);
55
56my @modes = (\&pos, \&imm);
57my %offsets = qw/1 4 2 4 3 2 4 2 5 3 6 3 7 4 8 4 99 1/;
58my $inst_ptr = 0;
59
60while ( 1 ) {
61
62 my $raw_op_code = $tape[$inst_ptr];
63 last if ($raw_op_code == 99);
64
65 # print("====================================\n");
66
67 my @modes_and_opcode;
68 push @modes_and_opcode, $_ // 0 for $raw_op_code =~ m/^(\d)??(\d)??(\d)??0?(\d)$/g;
69 ### @modes_and_opcode
70
71 my $op_code = pop @modes_and_opcode;
72 ### $op_code
73
74 # foreach my $x (0..5) {
75 # print("TAPE[" . ($inst_ptr + $x) . "] = $tape[($inst_ptr + $x)]\n")
76 # }
77
78 my $toread = $offsets{$op_code} - 1; # excluding opcode
79 my @params;
80 foreach my $offset (1..$toread) {
81 push @params, $modes[ (!($op_code == 4 || $op_code == 5 || $op_code == 6) && $offset == $toread) ? 1 : pop @modes_and_opcode ]->(\@tape, $inst_ptr + $offset);
82 }
83 ### @params
84
85 $inst_ptr += $offsets{$op_code};
86
87 if ($op_code == 1 || $op_code == 2 || $op_code == 7 || $op_code == 8) { # arithmetic
88 my $res = $actions[$op_code]->($params[0], $params[1]);
89 $tape[$params[2]] = $res;
90 ### writing: $res
91 ### on address: $params[2]
92 }
93 elsif ($op_code == 3) { # input
94 my $res = $actions[$op_code]->();
95 $tape[$params[0]] = $res;
96 ### saved: $res
97 ### on: $params[0]
98 } elsif ($op_code == 4) { # output
99 $actions[$op_code]->($params[0]);
100 } elsif ($op_code == 5 || $op_code == 6) { # jumps
101 my $res = $actions[$op_code]->($params[0], $params[1]);
102 $inst_ptr = $res == -1 ? $inst_ptr : $res;
103 ### jumped to: $inst_ptr
104 next;
105 } else {
106 ### OH NO...
107 die;
108 }
109}