From 6267bb6dd9d6871a2df14dfad30087cb68b9f045 Mon Sep 17 00:00:00 2001 From: Christopher Arndt Date: Sun, 3 Dec 2023 13:33:19 +0100 Subject: [PATCH] Day 03 part two Signed-off-by: Christopher Arndt --- day_03/solution_03.nim | 39 +++++++++--------- day_03/solution_03b.nim | 87 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 19 deletions(-) create mode 100644 day_03/solution_03b.nim diff --git a/day_03/solution_03.nim b/day_03/solution_03.nim index d2f7c4a..3d249ec 100644 --- a/day_03/solution_03.nim +++ b/day_03/solution_03.nim @@ -1,18 +1,6 @@ -import std/[cmdline, sequtils, strformat, strutils] +import std/[cmdline, sequtils, strformat, strutils, sugar] -var fn: string - -if paramCount() > 0: - fn = paramStr(1) -else: - fn = "input_03.txt" - -var result = 0 -var lines = readFile(fn).strip.splitLines -var grid = newSeqWith(lines.len, newSeq[char](lines[0].strip.len)) - - -proc isAdjacentToSymbol(row, col: int): bool = +proc isAdjacentToCond(grid: seq[seq[char]], row, col: int, cond: (char) -> bool): bool = for i in @[row - 1, row, row + 1]: if i < 0 or i >= grid.len: continue @@ -22,11 +10,17 @@ proc isAdjacentToSymbol(row, col: int): bool = if j < 0 or j >= grid[i].len: continue var ch = grid[i][j] - if not ch.isDigit and ch != '.': + if cond(ch): return true return false +var fn = if paramCount() > 0: paramStr(1) else: "input_03.txt" + +var result = 0 +var lines = readFile(fn).strip.splitLines +var grid = newSeqWith(lines.len, newSeq[char](lines[0].strip.len)) + for i, line in lines: for j, ch in line.strip: grid[i][j] = ch @@ -41,19 +35,26 @@ for i, row in grid: for j, ch in row: if ch.isDigit: number &= ch - if isAdjacentToSymbol(i, j): + if isAdjacentToCond(grid, i, j, (c) => not c.isDigit and c != '.'): isPartNumber = true else: if isPartNumber: #echo number.parseInt result += number.parseInt - elif number.len > 0: - echo &"Not a part number: {number.parseInt} (row {i}, col {j})" + #elif number.len > 0: + # echo &"Not a part number: {number.parseInt} (row {i}, col {j})" + number = "" isPartNumber = false - # account for numbers going untl the end of the row + # account for numbers going until the end of the row if isPartNumber: result += number.parseInt echo &"Result: {result}" + +case fn: + of "input_03.txt": + assert result == 559667 + of "sample_input_03.txt": + assert result == 4361 diff --git a/day_03/solution_03b.nim b/day_03/solution_03b.nim new file mode 100644 index 0000000..12013ba --- /dev/null +++ b/day_03/solution_03b.nim @@ -0,0 +1,87 @@ +import std/[cmdline, sequtils, strformat, strutils, sugar, tables] + +type Position = tuple + row: int + col: int + +## Check if any of the grid cells adjacent to position (i, j) match condition cond. +proc isAdjacentToCond(grid: seq[seq[char]], row, col: int, cond: (char) -> bool): Position = + for i in @[row - 1, row, row + 1]: + if i < 0 or i >= grid.len: + continue + for j in @[col - 1, col, col + 1]: + if i == row and j == col: + continue + if j < 0 or j >= grid[i].len: + continue + var ch = grid[i][j] + if cond(ch): + return (i, j) + return (-1, -1) + + +var fn = if paramCount() > 0: paramStr(1) else: "input_03.txt" +var result = 0 +# read input file as seq of lines +var lines = readFile(fn).strip.splitLines +# allocate 2-D seq to hold ros and colums of characters +var grid = newSeqWith(lines.len, newSeq[char](lines[0].strip.len)) +# table to save positions of gears and parts connected to it +var gears = initTable[Position, seq[int]]() + +# Parse input +for i, line in lines: + for j, ch in line.strip: + grid[i][j] = ch + +#echo &"Rows: {grid.len}" +#echo &"Cols: {grid[0].len}" + +# Go through grid and find positions of gears +for i, row in grid: + var + isConnectedToGear = false + gear: Position + number = "" + + for j, ch in row: + if ch.isDigit: + number &= ch + # Scan adjacent grid cells gor a gear ('*') + var symbol = isAdjacentToCond(grid, i, j, (c) => c == '*') + + if symbol != (-1, -1): + # It's a number adjacent to a gear! + isConnectedToGear = true + gear = symbol + if not gears.hasKey(gear): + # save gear position in table + gears[gear] = newSeq[int]() + else: + if isConnectedToGear: + # add part to gear position saved above + # we can save an infinite amount of parts per gear + # but we assume that at most two parts are connected to a gear + gears[gear].add(number.parseInt) + + number = "" + isConnectedToGear = false + + # account for numbers going until the end of the row + if isConnectedToGear: + # add part to gear position saved above + gears[gear].add(number.parseInt) + +# Sum up gear ratios +for pos, parts in gears: + # Ignore gears conencted to only one part + if parts.len > 1: + result += parts[0] * parts[1] + +echo &"Result: {result}" + +case fn: + of "input_03.txt": + assert result == 86841457 + of "sample_input_03.txt": + assert result == 467835