summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AdventOfCode.pm6111
-rw-r--r--lib/AdventOfCode/Day3.rakumod24
-rw-r--r--lib/AdventOfCode/Day3.rakumod~3
-rw-r--r--lib/AdventOfCode/Utils.rakumod78
-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..*]
+ }
+}