Day 03 part two
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
This commit is contained in:
		
							parent
							
								
									098ab3f9c8
								
							
						
					
					
						commit
						6267bb6dd9
					
				@ -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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										87
									
								
								day_03/solution_03b.nim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								day_03/solution_03b.nim
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user