diff options
-rw-r--r-- | .gitignore | 8 | ||||
-rw-r--r-- | .travis.yml | 12 | ||||
-rw-r--r-- | Changes | 4 | ||||
-rw-r--r-- | LICENSE | 201 | ||||
-rw-r--r-- | META6.json | 19 | ||||
-rw-r--r-- | README.md | 29 | ||||
-rw-r--r-- | data/day2-a.txt | 1 | ||||
-rw-r--r-- | dist.ini | 8 | ||||
-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 | ||||
-rw-r--r-- | t/01-basic.t | 62 | ||||
-rw-r--r-- | t/03-day3.t | 49 |
15 files changed, 673 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e9b128a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/blib/ +/src/*.o +/src/Makefile +/.panda-work +/resources/*.so +/resources/*.dylib +.precomp/ +/AdventOfCode-* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e74fe5e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +os: + - linux + - osx +language: perl6 +perl6: + - latest +install: + - rakudobrew build zef + - zef install --deps-only --/test . +script: + - PERL6LIB=$PWD/lib prove -e perl6 -vr t/ +sudo: false @@ -0,0 +1,4 @@ +Revision history for AdventOfCode + +{{$NEXT}} + - Initial version @@ -0,0 +1,201 @@ + The Artistic License 2.0 + + Copyright (c) 2000-2006, The Perl Foundation. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble + +This license establishes the terms under which a given free software +Package may be copied, modified, distributed, and/or redistributed. +The intent is that the Copyright Holder maintains some artistic +control over the development of that Package while still keeping the +Package available as open source and free software. + +You are always permitted to make arrangements wholly outside of this +license directly with the Copyright Holder of a given Package. If the +terms of this license do not permit the full use that you propose to +make of the Package, you should contact the Copyright Holder and seek +a different licensing arrangement. + +Definitions + + "Copyright Holder" means the individual(s) or organization(s) + named in the copyright notice for the entire Package. + + "Contributor" means any party that has contributed code or other + material to the Package, in accordance with the Copyright Holder's + procedures. + + "You" and "your" means any person who would like to copy, + distribute, or modify the Package. + + "Package" means the collection of files distributed by the + Copyright Holder, and derivatives of that collection and/or of + those files. A given Package may consist of either the Standard + Version, or a Modified Version. + + "Distribute" means providing a copy of the Package or making it + accessible to anyone else, or in the case of a company or + organization, to others outside of your company or organization. + + "Distributor Fee" means any fee that you charge for Distributing + this Package or providing support for this Package to another + party. It does not mean licensing fees. + + "Standard Version" refers to the Package if it has not been + modified, or has been modified only in ways explicitly requested + by the Copyright Holder. + + "Modified Version" means the Package, if it has been changed, and + such changes were not explicitly requested by the Copyright + Holder. + + "Original License" means this Artistic License as Distributed with + the Standard Version of the Package, in its current version or as + it may be modified by The Perl Foundation in the future. + + "Source" form means the source code, documentation source, and + configuration files for the Package. + + "Compiled" form means the compiled bytecode, object code, binary, + or any other form resulting from mechanical transformation or + translation of the Source form. + + +Permission for Use and Modification Without Distribution + +(1) You are permitted to use the Standard Version and create and use +Modified Versions for any purpose without restriction, provided that +you do not Distribute the Modified Version. + + +Permissions for Redistribution of the Standard Version + +(2) You may Distribute verbatim copies of the Source form of the +Standard Version of this Package in any medium without restriction, +either gratis or for a Distributor Fee, provided that you duplicate +all of the original copyright notices and associated disclaimers. At +your discretion, such verbatim copies may or may not include a +Compiled form of the Package. + +(3) You may apply any bug fixes, portability changes, and other +modifications made available from the Copyright Holder. The resulting +Package will still be considered the Standard Version, and as such +will be subject to the Original License. + + +Distribution of Modified Versions of the Package as Source + +(4) You may Distribute your Modified Version as Source (either gratis +or for a Distributor Fee, and with or without a Compiled form of the +Modified Version) provided that you clearly document how it differs +from the Standard Version, including, but not limited to, documenting +any non-standard features, executables, or modules, and provided that +you do at least ONE of the following: + + (a) make the Modified Version available to the Copyright Holder + of the Standard Version, under the Original License, so that the + Copyright Holder may include your modifications in the Standard + Version. + + (b) ensure that installation of your Modified Version does not + prevent the user installing or running the Standard Version. In + addition, the Modified Version must bear a name that is different + from the name of the Standard Version. + + (c) allow anyone who receives a copy of the Modified Version to + make the Source form of the Modified Version available to others + under + + (i) the Original License or + + (ii) a license that permits the licensee to freely copy, + modify and redistribute the Modified Version using the same + licensing terms that apply to the copy that the licensee + received, and requires that the Source form of the Modified + Version, and of any works derived from it, be made freely + available in that license fees are prohibited but Distributor + Fees are allowed. + + +Distribution of Compiled Forms of the Standard Version +or Modified Versions without the Source + +(5) You may Distribute Compiled forms of the Standard Version without +the Source, provided that you include complete instructions on how to +get the Source of the Standard Version. Such instructions must be +valid at the time of your distribution. If these instructions, at any +time while you are carrying out such distribution, become invalid, you +must provide new instructions on demand or cease further distribution. +If you provide valid instructions or cease distribution within thirty +days after you become aware that the instructions are invalid, then +you do not forfeit any of your rights under this license. + +(6) You may Distribute a Modified Version in Compiled form without +the Source, provided that you comply with Section 4 with respect to +the Source of the Modified Version. + + +Aggregating or Linking the Package + +(7) You may aggregate the Package (either the Standard Version or +Modified Version) with other packages and Distribute the resulting +aggregation provided that you do not charge a licensing fee for the +Package. Distributor Fees are permitted, and licensing fees for other +components in the aggregation are permitted. The terms of this license +apply to the use and Distribution of the Standard or Modified Versions +as included in the aggregation. + +(8) You are permitted to link Modified and Standard Versions with +other works, to embed the Package in a larger work of your own, or to +build stand-alone binary or bytecode versions of applications that +include the Package, and Distribute the result without restriction, +provided the result does not expose a direct interface to the Package. + + +Items That are Not Considered Part of a Modified Version + +(9) Works (including, but not limited to, modules and scripts) that +merely extend or make use of the Package, do not, by themselves, cause +the Package to be a Modified Version. In addition, such works are not +considered parts of the Package itself, and are not subject to the +terms of this license. + + +General Provisions + +(10) Any use, modification, and distribution of the Standard or +Modified Versions is governed by this Artistic License. By using, +modifying or distributing the Package, you accept this license. Do not +use, modify, or distribute the Package, if you do not accept this +license. + +(11) If your Modified Version has been derived from a Modified +Version made by someone other than you, you are nevertheless required +to ensure that your Modified Version complies with the requirements of +this license. + +(12) This license does not grant you the right to use any trademark, +service mark, tradename, or logo of the Copyright Holder. + +(13) This license includes the non-exclusive, worldwide, +free-of-charge patent license to make, have made, use, offer to sell, +sell, import and otherwise transfer the Package with respect to any +patent claims licensable by the Copyright Holder that are necessarily +infringed by the Package. If you institute patent litigation +(including a cross-claim or counterclaim) against any party alleging +that the Package constitutes direct or contributory patent +infringement, then this Artistic License to you shall terminate on the +date that such litigation is filed. + +(14) Disclaimer of Warranty: +THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS +IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL +LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/META6.json b/META6.json new file mode 100644 index 0000000..09f01e3 --- /dev/null +++ b/META6.json @@ -0,0 +1,19 @@ +{ + "authors" : [ + "Matias Linares" + ], + "build-depends" : [ ], + "depends" : [ ], + "description" : "blah blah blah", + "license" : "Artistic-2.0", + "name" : "AdventOfCode", + "perl" : "6.c", + "provides" : { + "AdventOfCode" : "lib/AdventOfCode.pm6" + }, + "resources" : [ ], + "source-url" : "", + "tags" : [ ], + "test-depends" : [ ], + "version" : "0.0.1" +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..7692e15 --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +NAME +==== + +AdventOfCode - blah blah blah + +SYNOPSIS +======== + +```perl6 +use AdventOfCode; +``` + +DESCRIPTION +=========== + +AdventOfCode is ... + +AUTHOR +====== + +Matias Linares <matias.linares@comprandoengrupo.net> + +COPYRIGHT AND LICENSE +===================== + +Copyright 2019 Matias Linares + +This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0. + diff --git a/data/day2-a.txt b/data/day2-a.txt new file mode 100644 index 0000000..49caf3a --- /dev/null +++ b/data/day2-a.txt @@ -0,0 +1 @@ +1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,9,19,1,10,19,23,2,9,23,27,1,6,27,31,2,31,9,35,1,5,35,39,1,10,39,43,1,10,43,47,2,13,47,51,1,10,51,55,2,55,10,59,1,9,59,63,2,6,63,67,1,5,67,71,1,71,5,75,1,5,75,79,2,79,13,83,1,83,5,87,2,6,87,91,1,5,91,95,1,95,9,99,1,99,6,103,1,103,13,107,1,107,5,111,2,111,13,115,1,115,6,119,1,6,119,123,2,123,13,127,1,10,127,131,1,131,2,135,1,135,5,0,99,2,14,0,0 diff --git a/dist.ini b/dist.ini new file mode 100644 index 0000000..e9f12f8 --- /dev/null +++ b/dist.ini @@ -0,0 +1,8 @@ +name = AdventOfCode + +[ReadmeFromPod] +; enable = false +filename = lib/AdventOfCode.pm6 + +[PruneFiles] +; match = ^ 'xt/' 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..*] + } +} diff --git a/t/01-basic.t b/t/01-basic.t new file mode 100644 index 0000000..cebebd8 --- /dev/null +++ b/t/01-basic.t @@ -0,0 +1,62 @@ +use v6.c; +use Test; +use AdventOfCode; + +plan 8; + +my $test-vm = IntcodeVM.new(slurp("./data/day2-a.txt")); + +sub check-vm($input, $output, $name) { + my $vm = IntcodeVM.new($input); + $vm.run; + is $vm.memory.join(','), $output, $name; +} + +check-vm "1,0,0,0,99", "2,0,0,0,99", 'first example'; +check-vm "2,3,0,3,99", "2,3,0,6,99", 'second example'; +check-vm '2,4,4,5,99,0', '2,4,4,5,99,9801', 'third example'; +check-vm '1,1,1,4,99,5,6,0,99', '30,1,1,4,2,5,6,0,99', 'last example'; + +{ + my $input = slurp("./data/day2-a.txt"); + my $vm = IntcodeVM.new($input); + $vm.memory[1] = 12; + $vm.memory[2] = 2; + + $vm.run(); + + is $vm.output, 3760627, "day 2 first problem output"; +} + +subtest "VM don't change program after run", { + my $input = '1,1,1,4,99,5,6,0,99'; + my $vm = IntcodeVM.new($input); + $vm.run; + is $vm.program, $input.split(','), 'simple input'; +} + +subtest "VM resets memory", { + my $input = '1,1,1,4,99,5,6,0,99'; + my $vm = IntcodeVM.new($input); + $vm.run; + isnt $vm.memory, $vm.program, 'Run changes memory'; + my $memory = $vm.memory; + $vm.reset-memory(); + is $vm.memory, $vm.program, '.reset-memory() resets memory to program'; + + $test-vm.memory[1] = 12; + $test-vm.memory[2] = 2; + $test-vm.run; + is $test-vm.output, 3760627, "day 2 first problem output"; + $test-vm.reset-memory; + isnt $test-vm.output, 3760627, "day2 first problem resets memory"; +} + +subtest "day2 example", { + my $input = slurp("./data/day2-a.txt"); + my $vm = IntcodeVM.new($input); + $vm.run(); +} + + +done-testing; diff --git a/t/03-day3.t b/t/03-day3.t new file mode 100644 index 0000000..0d7c516 --- /dev/null +++ b/t/03-day3.t @@ -0,0 +1,49 @@ +use v6.d; +use Test; +use AdventOfCode::Utils; + +#plan 2; + +subtest "Point", { + ok Point.new, 'Default Point creation'; + is Point.new.x, 0, 'Default x'; + is Point.new.y, 0, 'Default y'; + ok Point.new(:1x, :2y), 'Point creation'; +} + +subtest "Line", { + my $point1 = Point.new; + my $point2 = Point.new; + + ok Line.new($point1, $point2), 'without named parameters'; + ok Line.new(:$point1, :$point2), 'with named parameters'; +} + +subtest "Wire", { + ok Wire.new("R1"); + my $wire = Wire.new("R1"); + + is $wire.points.elems, 1, 'wire has one point'; + isa-ok $wire.points.head, Point, 'Elements are points'; + my $point = $wire.points.head; + + is $point.x, 1, "First wire point x {$point}"; + is $point.y, 0, 'First wire point y {$point}'; + + subtest "intersection", { + my $line1 = Line.new( + :p(Point.new(:4x, :0y)), + :q(Point.new(:6x, :10y)) + ); + my $line2 = Line.new( + :p(Point.new(:0x, :3y)), + :q(Point.new(:10x, :7y)) + ); + + my $intersection = intersection($line1, $line2); + + is $intersection.x, 5, 'intersection x'; + is $intersection.y, 5, 'intersection y'; + } +} +done-testing; |