From 6ecae2b5bf63b118252bb8992bbef59941191147 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Sun, 13 Dec 2020 21:53:37 -0800 Subject: [PATCH] Add day 4 solution. --- day14.cr | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 day14.cr diff --git a/day14.cr b/day14.cr new file mode 100644 index 0000000..d6fc3fe --- /dev/null +++ b/day14.cr @@ -0,0 +1,60 @@ +require "advent" +raw = input(2020, 14).lines +input = [] of {UInt64, UInt64, Array(Int32), UInt64, UInt64} + +and_mask = (2_u64**63) + (2_u64**63-1) +or_mask = 0_u64 +floats = [] of Int32 + +raw.each do |line| + if data = line.match(/^mask = (.+)$/) + new_mask = data[1] + and_mask = (2_u64**63) + (2_u64**63-1) + or_mask = 0_u64 + floats = [] of Int32 + new_mask.reverse.chars.each_with_index do |c, i| + floats << i if c == 'X' + or_mask = or_mask | (1_u64 << i) if c == '1' + and_mask = and_mask & ~(1_u64 << i) if c == '0' + end + elsif data = line.match(/^mem\[(\d+)\] = (\d+)$/) + input << {and_mask, or_mask, floats, data[1].to_u64, data[2].to_u64} + else + raise "Invalid line" + end +end + +def part1(input) + memory = {} of UInt64 => UInt64 + input.each do |i| + and_mask, or_mask, floats, addr, v = i + memory[addr] = (v & and_mask) | or_mask + end + memory.values.sum +end + +def generate_possible(indices, index, n, &block : UInt64 -> _) + if index == indices.size + yield n + return + end + float_addr = indices[index] + no = n | (1_u64 << float_addr) + generate_possible(indices, index+1, no, &block) + nz = n & ~(1_u64 << float_addr) + generate_possible(indices, index+1, nz, &block) +end + +def part2(input) + memory = {} of UInt64 => UInt64 + input.each do |i| + _, or_mask, floats, addr, v = i + generate_possible(floats, 0, addr | or_mask) do |addr| + memory[addr] = v + end + end + memory.values.sum +end + +puts part1(input) +puts part2(input)