advent-of-code/2021/four.nim

119 lines
3 KiB
Nim
Raw Normal View History

2021-12-05 10:32:03 -06:00
import std/[strutils, sequtils, options, math, parseutils, sets, strformat, algorithm]
2021-12-04 08:57:45 -06:00
import ./common
2021-12-05 08:04:39 -06:00
type Board = object
entries: seq[string]
checked: seq[int]
2021-12-05 09:01:48 -06:00
proc isBoardWinning(b: Board): bool =
let winningSets: seq[HashSet[int]] = [
[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[0, 5, 10, 15, 20],
[1, 6, 11, 16, 21],
[2, 7, 12, 17, 22],
[3, 8, 13, 18, 23],
[4, 9, 14, 19, 24]
].mapIt(it.toHashSet())
2021-12-05 08:04:39 -06:00
let s = b.checked.toHashSet()
for w in winningSets:
if w < s:
return true
return false
2021-12-04 08:57:45 -06:00
proc squidBingo(inputLines: seq[string]): int =
var input: seq[string] = inputLines
2021-12-05 08:04:39 -06:00
let calledNumbers: seq[string] = input[0].split ','
input.delete 0..1
# construct boards
var boards: seq[Board]
var board: Board = Board(entries: @[], checked: @[])
for l in input:
if l.strip() == "":
boards.add board
board = Board(entries: @[], checked: @[])
continue
2021-12-05 10:32:03 -06:00
board.entries.add l.split(' ').filterIt(it != "").mapIt(it.strip())
2021-12-05 09:01:48 -06:00
boards.add board
2021-12-05 08:04:39 -06:00
for n in calledNumbers:
2021-12-05 09:01:48 -06:00
for b in boards.mitems():
2021-12-05 08:04:39 -06:00
for i, e in b.entries:
if n == e:
b.checked.add i
if b.isBoardWinning():
2021-12-05 09:01:48 -06:00
var entriesSum = 0
for i, v in b.entries:
if not (i in b.checked): entriesSum += v.parseInt()
return entriesSum * n.parseInt()
2021-12-05 08:04:39 -06:00
2021-12-04 08:57:45 -06:00
return 0
2021-12-05 09:56:41 -06:00
proc loseSquidBingo(inputLines: seq[string]): int =
var input: seq[string] = inputLines
let calledNumbers: seq[string] = input[0].split ','
input.delete 0..1
# construct boards
var boards: seq[Board]
var board: Board = Board(entries: @[], checked: @[])
for l in input:
if l.strip() == "":
boards.add board
board = Board(entries: @[], checked: @[])
continue
2021-12-05 10:32:03 -06:00
board.entries.add l.split(' ').filterIt(it != "").mapIt(it.strip())
2021-12-05 09:56:41 -06:00
boards.add board
for n in calledNumbers:
var removeBoards: seq[int] = @[]
for bbi, b in boards.mpairs():
for i, e in b.entries:
if n == e:
b.checked.add i
if b.isBoardWinning():
if (boards.len() - removeBoards.len()) < 2:
var entriesSum = 0
for i, v in b.entries:
if not (i in b.checked): entriesSum += v.parseInt()
return entriesSum * n.parseInt()
else:
removeBoards.add(bbi)
2021-12-05 10:32:03 -06:00
for i in removeBoards.reversed():
boards.delete(i..i)
2021-12-05 09:56:41 -06:00
return 0
2021-12-04 08:57:45 -06:00
let input = 4.loadInput()
2021-12-05 10:32:03 -06:00
time("squidBingo part 1"): echo input.squidBingo()
time("loseSquidBingo part 2"): echo input.loseSquidBingo()
2021-12-04 08:57:45 -06:00
when not defined(release):
2021-12-05 10:32:03 -06:00
let testInput = """7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
2021-12-05 08:04:39 -06:00
22 13 17 11 0
2021-12-05 10:32:03 -06:00
8 2 23 4 24
2021-12-05 08:04:39 -06:00
21 9 14 16 7
2021-12-05 10:32:03 -06:00
6 10 3 18 5
1 12 20 15 19
2021-12-05 08:04:39 -06:00
2021-12-05 10:32:03 -06:00
3 15 0 2 22
9 18 13 17 5
2021-12-05 08:04:39 -06:00
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2021-12-05 10:32:03 -06:00
2 0 12 3 7""".split('\n')
doAssert testInput.squidBingo() == 4512
doAssert testInput.loseSquidBingo() == 1924