Maybe it wants to play bingo?
Day 4a
Some new advent library functions:
const is = (x: any) => x !== '' && x !== null && x !== undefined
const parse10 = (s: string) => parseInt(s, 10)
const clean = (s: string) => s.trim().replace(/^[^\S\n]+/gm, '')
const paragraphs = (s: string) => clean(s).split(/\n{2,}/)
const ints = (s: string) => clean(s).split(/\D+/).map(parse10)
const max = (ns: number[]) => Math.max.apply(null, ns)
const min = (ns: number[]) => Math.min.apply(null, ns)
const sum = (ns: number[]) => reduce(ns, (sum, n) => sum + n, 0)
const ranks = <T>(xs: T[], n: number): T[][] =>
R.times(Math.ceil(xs.length / n), i => xs.slice(n * i, n * (i + 1)))
const files = <T>(xs: T[], n: number): T[][] =>
R.times(Math.ceil(xs.length / n), i =>
R.times(n, j => xs[i + j * n]).filter(is),
)
And my solution:
const d4 = ({
input = inputs.d4,
dbg,
pick,
}: DayProps & {pick: typeof R.last}) => {
const {draws, boards} = R.pipe(paragraphs(input), ([ds, ...bs]) => ({
draws: ints(ds),
boards: bs.map(ints),
}))
const edge = Math.sqrt(boards[0].length)
// Reverse lookup from a drawn number to its position in line.
const order = reduce.indexed(
R.uniq(draws),
(order, draw, i) => ((order[draw] = i), order),
[] as number[],
)
// Boards sorted in the order they win.
const bingos = R.pipe(
boards,
R.map.indexed((board, num) => {
const rows = [...ranks(board, edge), ...files(board, edge)]
const orders = rows.map(r => r.map(draw => order[draw]))
const turn = min(orders.map(max))
return {board, num, rows, orders, turn}
}),
R.sort((a, b) => a.turn - b.turn),
)
// Pick the winning (or losing) board.
const winning = pick(bingos)
// Unmarked numbers are those that haven't been called by the winning.turn
const unmarked = sum(winning.board.filter(x => order[x] > winning.turn))
// Which number was called on the winning turn?
const winner = draws[winning.turn]
dbg({...R.pick(winning, ['num', 'turn']), unmarked, winner})
return `Final score: ${unmarked * winner}`
}
export const d4a = (props: DayProps) => d4({...props, pick: R.first})
Sample output:
My output:
Day 4b
Got lucky here with my implementation for the first part:
export const d4b = (props: DayProps) => d4({...props, pick: R.last})
Sample output:
My output: