Posts

Raku: Advent of Code 2020 - Day Seven

Raku solution for Day 7 of Advent of Code. Commentary follows the code... If you enjoy it or can offer improvements, please leave a comment. #!/usr/bin/env raku use v6.d ; grammar Baggage { rule TOP { < rule > + } rule rule { < color > 'bags contain' < contents > '.' } rule contents { 'no other bags' | [ < quantity > < color > < . bag > ] + % ',' } token color { \w + \W + \w + } token quantity { \d + } token bag { 'bag' | 'bags' } } class BaggageActions { has $.inside = {}; has $.outside = {}; method rule ( $/ ) { return if 'no other bags' eq ~ $< contents > ; my $outer = ~ $< color > ; my $inner = %( $< contents > . < color > . map ({ ~ $_ }) . List Z=> $< contents > . < quantity > . map ({ + $_ }) . List ) ; $!inside { $outer } = $inner ; for $inner . pa...

Raku: Advent of Code 2020 - Day Six

Here is my final short form Raku answer to the puzzle for Day 6 of Advent of Code: sub rv ( &code ) { 'input' . IO . slurp . split ( " \n\n " , :skip-empty ) . map ( &code ) . sum } say "One: " ~ rv { . comb ( / \S / ) . Set . elems }; say "Two: " ~ rv { . lines . map ({ . comb ( / \S / ) . Set }) . reduce ( &infix :< ∩ > ) . elems }; Below is the initial Raku code that earned me my gold stars. How did I get from the code below to what's above? Commentary and refactoring notes follow... #!/usr/bin/env raku use v6.d ; sub MAIN ( IO () : $input where * . f = $?FILE . IO . sibling ( 'input' ), Int : $part where * == 1 | 2 = 1 , # Solve Part One or Part Two? --> Nil ) { given $part { when 1 { say $input . slurp . split ( " \n\n " , :skip-empty ) . map ({ my $x = $_ ; $x ~~ s:g:s/ \s + // ; $x . comb . Set . elems }) ...

Raku: Advent of Code 2020 - Day Five

Below is my current solution to the puzzle for Day 5 in the 2020 Advent of Code. Code commentary follows the code... #!/usr/bin/env raku use v6.d ; sub MAIN ( IO () : $input where * . f = $?FILE . IO . sibling ( 'input' ), Int : $part where * == 1 | 2 = 1 , # Solve Part One or Part Two? --> Nil ) { given $part { when 1 { say $input . lines . map ({ seat_id ( $_ ) }) . max ; } when 2 { my @vacant = ( ( 0 .. 1023 ) (-) $input . lines . map ({ seat_id ( $_ ) }) ) . keys ; say @vacant . grep ({ ! ( $_ + 1 ~~ any @vacant ) and ! ( $_ - 1 ~~ any @vacant ) })[ 0 ]; } } } sub seat_id ( Str $code --> Int ) { return + ( '0b' ~ $code . trans ( <F B R L> => <0 1 1 0> )); } I enjoyed being able to use the set difference operator (-) to quickly find all the possible seat ids which were missing from the input. Instead of using the 3 character (-) operator, I could als...

Raku: Advent of Code 2020 - Day Four

The code below which solves the puzzle for Day Four of Advent of Code is very different from my first working version. Given today's Raku Advent Calendar post on Grammars , I decided to throw out my initial code and write a solution using grammars. And after reading the 1st post for this year's Raku Advent Calendar by codesections, I decided to include the little bit of boilerplate which enables Raku's default command line interface . Today's script should show the influence of other Raku AoC solutions in the advent-of-raku-2020 github repository . Special mention goes out to mienaikage, who has most heavily influenced the code which follows. [04.raku] #!/usr/bin/env raku use v6.d ; sub MAIN ( IO () : $input where * . f = $?FILE . IO . sibling ( 'input' ), Int : $part where * == 1 | 2 = 1 , # Solve Part One or Part Two? --> Nil ) { ... } Executed without any command line parameters it defaults to the equivalent of: $ 04.raku --input=inp...

Raku: Advent of Code 2020 - Day Three

Below is a Raku solution to the puzzle for Day Three in the 2020 Advent of Code. Commentary follows the code. use v6.d; my @input = 'input' . IO . lines ; my @map ; for @input -> $line { my $geology = ( $line . comb xx * ) . flat ; @map . push ( $geology ); } sub detect_collisions ( Int $sx , Int $sy ) { my $rval = 0 ; loop ( my ( $x , $y ) = ( $sx , $sy ); $y < @map . elems ; $x += $sx , $y += $sy ) { $rval ++ if @map [ $y ][ $x ] eq '#' ; } return $rval } # Part One say "Part One: { detect_collisions ( 3 , 1 )} " ; # Part Two my @collision ; for 1 , 1 , 3 , 1 , 5 , 1 , 7 , 1 , 1 , 2 -> $x , $y { @collision . push ( detect_collisions ( $x , $y )); } say "Part Two: " ~ [*] @collision ; Lazy lists and infinite sequences , the list repetition operator , and the * whatever placeholder are a few of the things Raku provides which made the repeating geology input in today's challenge fairly easy to deal wi...

Raku: Advent of Code 2020 - Day Two

Below is a solution in Raku to the puzzle for Day Two . I'm impressed by how clear, succinct, and expressive it is to code in Raku. As you'll see below, regular expressions in Raku are not a write-only sub-language reminiscent of line-noise. A lot of thought went into improving the clarity and readability of regexes. By default whitespace is not syntacticially significant in a regex unless you declare it. This allows you to layout and format your regular expressions for readability. token and rule are shorthand for named regexes with specific adverb modifiers applied. Tokens are regexes which do not ratchet (backtrack). And rules both don't ratchet _and_ treat whitespace as syntactically significant.  The use of tokens and rules provide for named access to values within the returned match object.  Which as you'll see below is quite handy. I haven't explored Grammars yet. But one can begin to see how grammars are only a hop, a skip, and a jump further on the lea...