improve memory footprint by encoding checked cells as negative number

main
Christian Ulrich 2021-12-04 15:42:45 +01:00
parent 25ee296a57
commit 1565026e68
No known key found for this signature in database
GPG Key ID: 8241BE099775A097
2 changed files with 28 additions and 30 deletions

View File

@ -19,28 +19,27 @@ import sequtils
import strutils import strutils
type type
Cell = tuple[val: uint8, checked: bool] Board = array[5, array[5, int8]]
Board = array[5, array[5, Cell]]
iterator lines(board: Board): array[5, Cell] = iterator lines(board: Board): array[5, int8] =
for i in 0 .. high(Board): for i in 0 .. high(Board):
yield board[i] yield board[i]
iterator columns(board: Board): array[5, Cell] = iterator columns(board: Board): array[5, int8] =
for i in 0 .. high(board[0]): for i in 0 .. high(board[0]):
var column: array[5, Cell] var column: array[5, int8]
for j in 0 .. high(Board): for j in 0 .. high(Board):
column[j] = board[j][i] column[j] = board[j][i]
yield column yield column
proc check(board: var Board, val: uint8) = proc check(board: var Board, val: int8) =
for i in 0 .. high(Board): for i in 0 .. high(Board):
for cellIndex, cell in board[i].pairs(): for cellIndex, cell in board[i].pairs():
if cell.val == val: if cell == val:
board[i][cellIndex].checked = true board[i][cellIndex] = -1
proc readDrawnNumbers(): seq[uint8] = proc readDrawnNumbers(): seq[int8] =
result = readLine(stdin).split(',').mapIt(uint8(parseUint(it))) result = readLine(stdin).split(',').mapIt(int8(parseUint(it)))
proc readBoards(): seq[Board] = proc readBoards(): seq[Board] =
var var
@ -53,13 +52,13 @@ proc readBoards(): seq[Board] =
if not readLine(stdin, line): if not readLine(stdin, line):
return return
board[i][0 .. high(Board)] = line.splitWhitespace(4) board[i][0 .. high(Board)] = line.splitWhitespace(4)
.mapIt((uint8(parseUint(it)), false)) .mapIt(int8(parseUint(it)))
result.add(board) result.add(board)
proc bingoScore(board: Board, latestNumber: uint8): int = proc bingoScore(board: Board, latestNumber: int8): int =
var unmarkedSum = 0 var unmarkedSum = 0
for line in board.lines(): for line in board.lines():
unmarkedSum.inc(line.foldl(if not b.checked: a + int(b.val) else: a, 0)) unmarkedSum.inc(line.foldl(if b >= 0: a + int(b) else: a, 0))
result = unmarkedSum * int(latestNumber) result = unmarkedSum * int(latestNumber)
proc bingo(): int = proc bingo(): int =
@ -69,10 +68,10 @@ proc bingo(): int =
for board in boards.mitems(): for board in boards.mitems():
board.check(number) board.check(number)
for line in board.lines(): for line in board.lines():
if line.allIt(it.checked): if line.allIt(it < 0):
return board.bingoScore(number) return board.bingoScore(number)
for column in board.columns(): for column in board.columns():
if column.allIt(it.checked): if column.allIt(it < 0):
return board.bingoScore(number) return board.bingoScore(number)
raise newException(ValueError, "there is no winner") raise newException(ValueError, "there is no winner")

View File

@ -19,28 +19,27 @@ import sequtils
import strutils import strutils
type type
Cell = tuple[val: uint8, checked: bool] Board = array[5, array[5, int8]]
Board = array[5, array[5, Cell]]
iterator lines(board: Board): array[5, Cell] = iterator lines(board: Board): array[5, int8] =
for i in 0 .. high(Board): for i in 0 .. high(Board):
yield board[i] yield board[i]
iterator columns(board: Board): array[5, Cell] = iterator columns(board: Board): array[5, int8] =
for i in 0 .. high(board[0]): for i in 0 .. high(board[0]):
var column: array[5, Cell] var column: array[5, int8]
for j in 0 .. high(Board): for j in 0 .. high(Board):
column[j] = board[j][i] column[j] = board[j][i]
yield column yield column
proc check(board: var Board, val: uint8) = proc check(board: var Board, val: int8) =
for i in 0 .. high(Board): for i in 0 .. high(Board):
for cellIndex, cell in board[i].pairs(): for cellIndex, cell in board[i].pairs():
if cell.val == val: if cell == val:
board[i][cellIndex].checked = true board[i][cellIndex] = -1
proc readDrawnNumbers(): seq[uint8] = proc readDrawnNumbers(): seq[int8] =
result = readLine(stdin).split(',').mapIt(uint8(parseUint(it))) result = readLine(stdin).split(',').mapIt(int8(parseUint(it)))
proc readBoards(): seq[Board] = proc readBoards(): seq[Board] =
var var
@ -53,13 +52,13 @@ proc readBoards(): seq[Board] =
if not readLine(stdin, line): if not readLine(stdin, line):
return return
board[i][0 .. high(Board)] = line.splitWhitespace(4) board[i][0 .. high(Board)] = line.splitWhitespace(4)
.mapIt((uint8(parseUint(it)), false)) .mapIt(int8(parseUint(it)))
result.add(board) result.add(board)
proc bingoScore(board: Board, latestNumber: uint8): int = proc bingoScore(board: Board, latestNumber: int8): int =
var unmarkedSum = 0 var unmarkedSum = 0
for line in board.lines(): for line in board.lines():
unmarkedSum.inc(line.foldl(if not b.checked: a + int(b.val) else: a, 0)) unmarkedSum.inc(line.foldl(if b >= 0: a + int(b) else: a, 0))
result = unmarkedSum * int(latestNumber) result = unmarkedSum * int(latestNumber)
proc bingo(): int = proc bingo(): int =
@ -69,10 +68,10 @@ proc bingo(): int =
for boardIndex, board in boards.mpairs(): for boardIndex, board in boards.mpairs():
board.data.check(number) board.data.check(number)
for line in board.data.lines(): for line in board.data.lines():
if line.allIt(it.checked): if line.allIt(it < 0):
board.finished = true board.finished = true
for column in board.data.columns(): for column in board.data.columns():
if column.allIt(it.checked): if column.allIt(it < 0):
board.finished = true board.finished = true
if boards.len() == 1 and boards[0].finished: if boards.len() == 1 and boards[0].finished:
return boards[0].data.bingoScore(number) return boards[0].data.bingoScore(number)