61 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Crystal
		
	
	
	
	
	
			
		
		
	
	
			61 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Crystal
		
	
	
	
	
	
| 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)
 |