Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- very helpful library
- local _ = require("luadash")
- -- helper split function.
- -- returns an iterator, like pairs(...) / ipairs(...)
- function string:split(pat)
- pat = pat or '%s+'
- local st, g = 1, self:gmatch("()("..pat..")")
- local function getter(segs, seps, sep, cap1, ...)
- st = sep and seps + #sep
- return self:sub(segs, (seps or 0) - 1), cap1 or sep, ...
- end
- return function() if st then return getter(st, g()) end end
- end
- local input = {}
- -- read and parse each line of the input
- for line in io.lines("input.txt") do
- -- rip leading "[", and split by "] " to remove brackets
- local m = line:sub(2):split("] ")
- local timestamp, command = m(), m()
- -- timestamp ==> relative time
- m = timestamp:split(" ")
- local date, clock = m(), m()
- m = clock:split(":")
- local hour, minute = tonumber((m())), tonumber((m()))
- -- add command to input list
- input[#input + 1] = {
- ["date"] = date .. " " .. clock,
- ["minute"] = minute,
- ["command"] = command
- }
- end
- -- sort input by date (string comparison ftw, "1518-11-23 00:20" < "1518-11-23 00:27")
- input =_.sort_by(input, function(log)
- return log.date
- end)
- local guard = -1
- local sleep = {}
- for k, log in pairs(input) do
- local m = log.command:split(" ")
- local sw = m()
- if sw == "Guard" then
- guard = tonumber(m():sub(2))
- if not sleep[guard] then
- sleep[guard] = {
- ["guard"] = guard,
- ["sleep"] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
- ["asleep"] = false
- }
- end
- elseif sw == "falls" then
- if not sleep[guard].asleep then
- for i = log.minute+1, 60 do
- sleep[guard].sleep[i] = sleep[guard].sleep[i] + 1
- end
- sleep[guard].asleep = true
- end
- elseif sw == "wakes" then
- if sleep[guard].asleep then
- for i = log.minute+1, 60 do
- sleep[guard].sleep[i] = math.max(sleep[guard].sleep[i] - 1, 0)
- end
- end
- sleep[guard].asleep = false
- end
- end
- -- part 1
- local flat = {}
- for k,v in pairs(sleep) do
- flat[#flat+1] = v
- end
- local sorted = _.sort_by(flat, function(guard)
- local sum = 0
- for k, sleep in pairs(guard.sleep) do
- sum = sum + sleep
- end
- return sum
- end)
- local target = sorted[#sorted]
- local best_key = 0
- local best_val = -1
- for k, v in pairs(target.sleep) do
- if v > best_val then
- best_key = k
- best_val = v
- end
- end
- print("Solution #1:", target.guard * (best_key - 1))
- -- part 2
- local best_guard = -1
- local best_key = -1
- local best_val = -1
- for k, guard in pairs(sleep) do
- for minute = 1,60 do
- if guard.sleep[minute] > best_val then
- best_guard = guard.guard
- best_key = minute
- best_val = guard.sleep[minute]
- end
- end
- end
- print("Solution #2:", sleep[best_guard].guard * (best_key - 1))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement