diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AdventOfCode.pm6 | 111 | ||||
-rw-r--r-- | lib/AdventOfCode/Day3.rakumod | 24 | ||||
-rw-r--r-- | lib/AdventOfCode/Day3.rakumod~ | 3 | ||||
-rw-r--r-- | lib/AdventOfCode/Utils.rakumod | 78 | ||||
-rw-r--r-- | lib/AdventOfCode/Utils.rakumod~ | 64 |
5 files changed, 280 insertions, 0 deletions
diff --git a/lib/AdventOfCode.pm6 b/lib/AdventOfCode.pm6 new file mode 100644 index 0000000..cac317a --- /dev/null +++ b/lib/AdventOfCode.pm6 @@ -0,0 +1,111 @@ +use v6.d; +enum opcode ( + halt => 99, + add => 1, + multiply => 2 +); +class X::Halt is Exception {} + +class IntcodeVM is export { + has @.program; + has @.memory; + # Program counter + has $!pc = 0; + + submethod new(Str $program) { + my @program = $program.split(',').map(*.Int); + self.bless(:@program, :memory(@program)); + } + + method run { + loop { + CATCH { + when X::Halt { last } + } + self!run-next-command; + } + } + + method reset-memory { + @!memory = @.program; + $!pc = 0; + } + + method !run-next-command { + given self!peek-opcode { + when halt { + die X::Halt.new; + } + when add { + self!add(); + $!pc += 4; + } + when multiply { + self!multiply(); + $!pc += 4; + } + default { die "Unknwon opcode {self!peek-opcode()}"; } + } + } + + method !peek-opcode(--> Int) { + die "$!pc exceeds memory {@!memory.elems}" if $!pc >= @!memory.elems; + @!memory[$!pc] + } + + method !program-chunk(Range $r) { + @!memory[$r + $!pc] + } + + method !add { + my ($opcode, $mem1, $mem2, $memresult) = self!program-chunk(^4); + @!memory[$memresult] = @!memory[$mem1] + @!memory[$mem2]; + } + + method !multiply { + my ($opcode, $mem1, $mem2, $memresult) = self!program-chunk(^4); + @!memory[$memresult] = @!memory[$mem1] * @!memory[$mem2]; + } + + method output { + @!memory[0] + } +} + +sub try-inputs(IntcodeVM $vm, $noun, $verb) { + $vm.reset-memory(); + $vm.memory[1] = $noun; + $vm.memory[2] = $verb; + $vm.run; + say $vm.memory[^3]; + return $vm.memory[0]; +} + +#| First problem of day 2 +sub day2a($input-filename) is export { + my $program = slurp($input-filename); + my $vm = IntcodeVM.new($program); + # Replace bits + $vm.memory[1] = 12; + $vm.memory[2] = 2; + $vm.run; + + say "Value at position 0: {$vm.output}" +} + +sub day2b($input-filename) is export { + my $program = slurp($input-filename); + my $vm = IntcodeVM.new($program); + + for ((^100) X (^100)) -> $p { + $vm.memory[1] = $p[0]; + $vm.memory[2] = $p[1]; + $vm.run; + my $output = $vm.output; + if $output == 19690720 { + say "100 * noun + verb: {100 * $p[0] + $p[1]}"; + last; + } + $vm.reset-memory; + } +} diff --git a/lib/AdventOfCode/Day3.rakumod b/lib/AdventOfCode/Day3.rakumod new file mode 100644 index 0000000..46aac01 --- /dev/null +++ b/lib/AdventOfCode/Day3.rakumod @@ -0,0 +1,24 @@ +use AdventOfCode::Utils; + +sub minimum-distance($input1, $input2) { + my $wire1 = Wire.new($input1); + dd $wire1; + my $wire2 = Wire.new($input2); + + for $wire1.lines -> $line1 { + for $wire2.lines -> $line2 { + if my $intersection = intersection($line1, $line2) { + say "Manhattan distance of intersection $intersection: " ~ manhattan-distance( + Point.new, $intersection + ); + } + } + } +} + +sub MAIN('day3') is export(:main) { + minimum-distance( + "R8,U5,L5,D3", + "U7,R6,D4,L4" + ); +} diff --git a/lib/AdventOfCode/Day3.rakumod~ b/lib/AdventOfCode/Day3.rakumod~ new file mode 100644 index 0000000..0952835 --- /dev/null +++ b/lib/AdventOfCode/Day3.rakumod~ @@ -0,0 +1,3 @@ +sub MAIN() { + say "a" +} diff --git a/lib/AdventOfCode/Utils.rakumod b/lib/AdventOfCode/Utils.rakumod new file mode 100644 index 0000000..9abedb8 --- /dev/null +++ b/lib/AdventOfCode/Utils.rakumod @@ -0,0 +1,78 @@ +class Point { + has Real $.x = 0; + has Real $.y = 0; + + method Str(--> Str) { + try { "<$.x, $.y>" } or "undefined" + } +} + +class Line { + has Point $.p; + has Point $.q; + + multi method new(Point $p, Point $q) { + self.bless(:$p, :$q) + } + + multi method new(Point :$p, Point :$q) { + self.bless(:$p, :$q) + } +} + +sub intersection(Line $l1, Line $l2) is export { + my $a1 = $l1.q.y - $l1.p.y; + my $b1 = $l1.p.x - $l1.q.x; + my $c1 = $a1 * $l1.p.x + $b1 * $l1.p.y; + + my $a2 = $l2.q.y - $l2.p.y; + my $b2 = $l2.p.x - $l2.q.x; + my $c2 = $a2 * $l2.p.x + $b2 * $l2.p.y; + + my $delta = $a1 * $b2 - $a2 * $b1; + + return Point.new( + :x(($b2 * $c1 - $b1 * $c2) / $delta), + :y(($a1 * $c2 - $a2 * $c1) / $delta) + ) +} + +sub manhattan-distance(Point $p, Point $q) is export { + abs($p.x - $q.x) + abs($p.y - $q.y) +} + + +class Wire is export { + has Point @.points; + + submethod new(Str $input) { + my @movements = $input.split(','); + my @points; + my $x = 0; + my $y = 0; + + for @movements -> $move { + if $move ~~ /$<direction> = [ <[ UDLR ]> ] $<size> = [ \d+]/ { + given $<direction> { + when "U" { $y += $<size>.Int } + when "D" { $y += -$<size>.Int } + when "L" { $x += -$<size>.Int } + when "R" { $x += $<size>.Int } + } + @points.append: Point.new(:$x, :$y); + } + } + + self.bless(:@points); + } + + method segments { + @.points[0..^*-1] Z @.points[1..*] + } + + method lines { + gather for self.segments -> $s { + take Line.new($s[0], $s[1]); + } + } +} diff --git a/lib/AdventOfCode/Utils.rakumod~ b/lib/AdventOfCode/Utils.rakumod~ new file mode 100644 index 0000000..d55a045 --- /dev/null +++ b/lib/AdventOfCode/Utils.rakumod~ @@ -0,0 +1,64 @@ +class Point { + has $.x = 0; + has $.y = 0; + + method Str(--> Str) { + "Point ($.x, $.y)" + } +} + +class Line { + has Point $.p; + has Point $.q; +} + +sub intersection(Line $l1, Line $l2) is export { + my $a1 = $l1.q.y - $l1.p.y; + my $b1 = $l1.p.x - $l1.q.x; + my $c1 = $a1 * $l1.p.x + $b1 * $l1.p.y; + + my $a2 = $l2.q.y - $l2.p.y; + my $b2 = $l2.p.x - $l2.q.x; + my $c2 = $a2 * $l2.p.x + $b2 * $l2.p.y; + + my $delta = $a1 * $b2 - $a2 * $b1; + + return Point.new( + :x(($b2 * $c1 - $b1 * $c2) / $delta), + :y(($a1 * $c2 - $a2 * $c1) / $delta) + ) +} + +sub manhattan-distance(Point $p, Point $q) { + abs($p.x - $q.x) + abs($p.y - $q.y) +} + + +class Wire { + has Point @.points; + + submethod new(Str $input) { + my @movements = $input.split(','); + my @points; + + for @movements -> $move { + if $move ~~ /$<direction> = [ <[ UDLR ]> ] $<size> = [ \d+]/ { + my $x = 0; + my $y = 0; + given $<direction> { + when "U" { $y += $<size>.Int } + when "D" { $y += -$<size>.Int } + when "L" { $x += -$<size>.Int } + when "R" { $x += $<size>.Int } + } + @points.append: Point.new(:$x, :$y); + } + } + + self.bless(:@points); + } + + method segments { + @.points[0..^*-1] Z @.points[1..*] + } +} |