91 lines
2.0 KiB
Nim
91 lines
2.0 KiB
Nim
import std/[algorithm, math]
|
|
import lib/loader
|
|
|
|
|
|
type
|
|
BinSet = object
|
|
start: int
|
|
stop: int
|
|
|
|
Half = enum
|
|
hLow,
|
|
hHigh
|
|
|
|
Seat = object
|
|
row: int
|
|
col: int
|
|
|
|
|
|
proc newBinSet(size: int): BinSet =
|
|
# check to make sure size is a power of 2
|
|
var q = size
|
|
while q mod 2 == 0:
|
|
q = q div 2
|
|
if q != 1:
|
|
raise newException(ValueError, "BinSet must have a size that is a power of 2.")
|
|
result = BinSet(start: 0, stop: size - 1)
|
|
|
|
|
|
proc size(bs: BinSet): int = bs.stop - bs.start + 1 # bounds are inclusive
|
|
|
|
func seatId(s: Seat): int = s.row * 8 + s.col
|
|
|
|
func seatCmp(s1, s2: Seat): int =
|
|
let i1 = s1.seatId()
|
|
let i2 = s2.seatId()
|
|
|
|
if i1 < i2:
|
|
return -1
|
|
elif i1 == i2:
|
|
return 0
|
|
else:
|
|
return 1
|
|
|
|
|
|
proc split(bs: var BinSet, h: Half) =
|
|
if h == hLow:
|
|
bs.stop -= (bs.size div 2)
|
|
else:
|
|
bs.start += (bs.size div 2)
|
|
|
|
|
|
proc parseBinSet(spec: string; lowChar, hiChar: char): int =
|
|
var bset = newBinSet(2 ^ spec.len)
|
|
for c in spec:
|
|
if c == lowChar:
|
|
bset.split(hLow)
|
|
elif c == hiChar:
|
|
bset.split(hHigh)
|
|
else:
|
|
raise newException(ValueError, "Bad BinSet specifier: " & spec)
|
|
assert(bset.start == bset.stop) # this should never be false, but just in case
|
|
result = bset.start
|
|
|
|
|
|
proc loadSeats(): seq[Seat] =
|
|
for line in loadStrings(5):
|
|
let row = parseBinSet(line[0..6], 'F', 'B')
|
|
let col = parseBinSet(line[7..^1], 'L', 'R')
|
|
result.add(Seat(row: row, col: col))
|
|
result.sort(seatCmp)
|
|
|
|
|
|
proc partOne(seats: seq[Seat]): int =
|
|
for s in seats:
|
|
if s.seatId() > result:
|
|
result = s.seatId()
|
|
|
|
|
|
proc partTwo(seats: seq[Seat]): int =
|
|
for i, s in seats:
|
|
let curId = s.seatId()
|
|
let nextId = seats[i + 1].seatId()
|
|
if nextId - curId != 1: # i.e. if there's a gap
|
|
return curId + 1
|
|
|
|
|
|
when isMainModule:
|
|
let seats = loadSeats()
|
|
echo "One: ", partOne(seats)
|
|
echo "Two: ", partTwo(seats)
|