Compare commits
2 Commits
7e411a5e42
...
503ecd1c04
Author | SHA1 | Date |
---|---|---|
Lucidiot | 503ecd1c04 | |
Lucidiot | e064c79542 |
|
@ -0,0 +1,29 @@
|
||||||
|
local start_timestamp = tonumber(io.read('l'))
|
||||||
|
local buses = {}
|
||||||
|
|
||||||
|
-- 'x' is translated to -1
|
||||||
|
io.read('l'):gsub('[^,]*', function (bus) table.insert(buses, tonumber(bus) or -1) end)
|
||||||
|
|
||||||
|
-- Copy and sort the buses, ignoring 'x' for part 1
|
||||||
|
local sorted_buses = {}
|
||||||
|
for _, bus in ipairs(buses) do
|
||||||
|
if bus > 0 then
|
||||||
|
table.insert(sorted_buses, bus)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(sorted_buses)
|
||||||
|
|
||||||
|
local function find_bus(timestamp)
|
||||||
|
for _, bus in ipairs(sorted_buses) do
|
||||||
|
if bus > 0 and timestamp % bus == 0 then
|
||||||
|
return bus
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local timestamp, bus_id = start_timestamp - 1, nil
|
||||||
|
repeat
|
||||||
|
timestamp = timestamp + 1
|
||||||
|
bus_id = find_bus(timestamp)
|
||||||
|
until bus_id
|
||||||
|
print(bus_id * (timestamp - start_timestamp))
|
|
@ -0,0 +1,82 @@
|
||||||
|
local instructions = {}
|
||||||
|
|
||||||
|
for line in io.lines() do
|
||||||
|
local name, value = line:match('^(.+) = ([X%d]+)$')
|
||||||
|
table.insert(instructions, {name, value})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function run(func)
|
||||||
|
local context = {mem={}}
|
||||||
|
for _, instruction in ipairs(instructions) do
|
||||||
|
context = func(context, table.unpack(instruction))
|
||||||
|
end
|
||||||
|
|
||||||
|
local sum = 0
|
||||||
|
for _, value in pairs(context.mem) do
|
||||||
|
sum = sum + value
|
||||||
|
end
|
||||||
|
return sum
|
||||||
|
end
|
||||||
|
|
||||||
|
local function part1(context, name, value)
|
||||||
|
if name == 'mask' then
|
||||||
|
context.and_mask = tonumber(value:gsub('X', '1'), 2)
|
||||||
|
context.or_mask = tonumber(value:gsub('X', '0'), 2)
|
||||||
|
else
|
||||||
|
local address = tonumber(name:match('%[(%d+)%]'))
|
||||||
|
context.mem[address] = tonumber(value) & context.and_mask | context.or_mask
|
||||||
|
end
|
||||||
|
return context
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Recursive method that sets both 0 and 1 versions of each X character in an address
|
||||||
|
local function part2_set(context, base_address, value)
|
||||||
|
local found = nil
|
||||||
|
for i = 1, #base_address do
|
||||||
|
if base_address[i] == "X" then
|
||||||
|
found = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not found then
|
||||||
|
context.mem[tonumber(table.concat(base_address), 2)] = value
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
base_address[found] = '0'
|
||||||
|
part2_set(context, base_address, value)
|
||||||
|
base_address[found] = '1'
|
||||||
|
part2_set(context, base_address, value)
|
||||||
|
base_address[found] = 'X'
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Binary representation of a decimal number
|
||||||
|
local function dectobin(value)
|
||||||
|
local t = {}
|
||||||
|
for i = 36, 1, -1 do
|
||||||
|
t[i] = math.fmod(value, 2)
|
||||||
|
value = math.floor((value - t[i]) / 2)
|
||||||
|
end
|
||||||
|
return table.concat(t)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function part2(context, name, value)
|
||||||
|
if name == 'mask' then
|
||||||
|
context.mask = value
|
||||||
|
return context
|
||||||
|
end
|
||||||
|
|
||||||
|
local base_address = dectobin(tonumber(name:match('%[(%d+)%]')))
|
||||||
|
local masked_address = {}
|
||||||
|
for i = 1, #context.mask do
|
||||||
|
local bit = context.mask:sub(i, i)
|
||||||
|
table.insert(masked_address, bit == "0" and base_address:sub(i, i) or bit)
|
||||||
|
end
|
||||||
|
|
||||||
|
part2_set(context, masked_address, value)
|
||||||
|
return context
|
||||||
|
end
|
||||||
|
|
||||||
|
print(run(part1))
|
||||||
|
print(run(part2))
|
Loading…
Reference in New Issue