This is a solution to Advent of Code 2020 day 14, written in Raku.

https://adventofcode.com/2020/day/14

### Part One

Execute the initialization program. What is the sum of all values left in memory after it completes?

#### Raku

Raku's `given / when`

construct is ideal for alternating input lines that require different
parsing. I quickly realised that the mask could be applied to the values as a pair of `and`

and
`or`

operations.

```
my @lines = '14-input.txt'.IO.lines;
my $and;
my $or;
my %mem;
for @lines {
when /'mask = ' (\w+)/ {
my $mask = ~$0;
$and = $mask.trans('X' => '1').parse-base(2);
$or = $mask.trans('X' => '0').parse-base(2);
}
when /'mem[' (\d+) '] = ' (\d+)/ {
%mem{~$0} = (+$1) +& $and +| $or;
}
}
say [+] %mem.values;
```

15403588588538

Execute the initialization program using an emulator for a version 2 decoder chip. What is the sum of all values left in memory after it completes?

#### Raku

Part two is very similar, with the added step of generating all binary combinations for the
sequence of `X`

mask element then generating all the addresses to write into.

```
my @lines = '14-input.txt'.IO.lines;
my $or;
my @bits;
my %mem;
sub base2-word($n, $width) {
my $base2 = $n.base(2);
'0' x ($width - $base2.chars) ~ $base2
}
for @lines {
when /'mask = ' (\w+)/ {
my $mask = ~$0;
$or = $mask.trans('X' => '0').parse-base(2);
my @mask = $mask.comb;
@bits = (^@mask.elems).grep( -> $i { @mask[$i] eq 'X' });
}
when /'mem[' (\d+) '] = ' (\d+)/ {
my $addr = base2-word((+$0) +| $or, 36);
my $value = +$1;
for ^(2 ** @bits.elems) -> $n {
my $bit-values = base2-word($n, @bits.elems);
my @addr = $addr.comb;
@addr[@bits] = $bit-values.comb;
%mem{@addr.join} = $value;
}
}
}
say "{+%mem} memory locations";
say [+] %mem.values;
```

78824 memory locations 3260587250457