From 0211c48cce21e17c1fe1026c36f4c8d2108fb96c Mon Sep 17 00:00:00 2001 From: Andinus Date: Tue, 8 Dec 2020 16:49:48 +0530 Subject: Add day-08 solution --- 2020/day-08/day-08.raku | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100755 2020/day-08/day-08.raku (limited to '2020/day-08/day-08.raku') diff --git a/2020/day-08/day-08.raku b/2020/day-08/day-08.raku new file mode 100755 index 0000000..ee9556f --- /dev/null +++ b/2020/day-08/day-08.raku @@ -0,0 +1,88 @@ +#!/usr/bin/env raku + +# Instruction grammar seperates the operation & argument. +grammar Instruction { + rule TOP { } + token operation { acc|jmp|nop } + token argument { .* } +} + +my Int $repeated = 0; + +sub MAIN ( + Int $part where * == 1|2 = 1 #= part to run (1 or 2) +) { + # To match the numbers in instructions with array we just push an + # element at 0th index. + my @instructions = %(instruction => "", executed => 0),; + + for "input".IO.lines { + push @instructions, %( + instruction => $_.Str, + executed => 0, + ); + } + + my Int $acc; + if $part == 1 { + $acc = execute-from(@instructions, 1) if $part == 1; + } elsif $part == 2 { + for @instructions.kv -> $idx, $entry { + next if $idx == 0; + $repeated = 0; + if Instruction.parse($entry) -> $match { + @instructions[$idx] = "nop $match" + if $match eq "jmp"; + + @instructions[$idx] = "jmp $match" + if $match eq "nop"; + + $acc = execute-from(@instructions, 1); + + @instructions[$idx] = "$match $match"; + @instructions = reset-executed(@instructions); + + last if $repeated == 0; + } + } + } + say "Part $part: ", $acc; +} + +sub reset-executed ( + @instructions is copy --> List +) { + $_ = 0 for @instructions; + return @instructions; +} + +# execute-from takes an index & executes instructions from that point. +# It returns the accumulator value. +sub execute-from ( + @instructions, Int $idx --> Int +) { + my Int $acc = 0; + + return $acc unless @instructions[$idx]; + my $entry = @instructions[$idx]; + + $repeated++ if $entry; + return $acc if $entry; + + if Instruction.parse($entry) -> $match { + $entry = 1; + given $match { + when 'acc' { + $acc += $match; + $acc += execute-from(@instructions, $idx + 1); + } + when 'jmp' { + $acc += execute-from(@instructions, $idx + $match); + } + when 'nop' { + $acc += execute-from(@instructions, $idx + 1); + } + } + } + return $acc; +} -- cgit 1.4.1-2-gfad0