2023 day 10 in Nim

0.01s user 0.01s system 96% cpu 0.021 total
This commit is contained in:
aru 2023-12-11 16:45:53 +01:00
parent dd09059408
commit f298850413
4 changed files with 122 additions and 0 deletions

103
2023/10/day10.nim Normal file
View File

@ -0,0 +1,103 @@
import std/sequtils
import std/sugar
import std/strutils
import std/options
import std/sets
type Point = tuple
x: int
y: int
type Area* = ref object
data: seq[string]
x, y: int
proc charAt(a: Area, p: Point): char =
a.data[p.x][p.y]
proc findStart(a: Area): Point =
for x in 0..a.x - 1:
for y in 0..a.y - 1:
let p = (x, y)
if a.charAt(p) == 'S':
return p
proc neighbours(p: Point, c: char): seq[Point] =
case c:
of '|': @[(p.x + 1, p.y), (p.x - 1, p.y)]
of '-': @[(p.x, p.y + 1), (p.x, p.y - 1)]
of 'J': @[(p.x - 1, p.y), (p.x, p.y - 1)]
of '7': @[(p.x + 1, p.y), (p.x, p.y - 1)]
of 'F': @[(p.x + 1, p.y), (p.x, p.y + 1)]
of 'L': @[(p.x - 1, p.y), (p.x, p.y + 1)]
else: @[]
proc isWithin(p: Point, b: Area): bool =
p.x >= 0 and p.y >= 0 and p.x < b.x and p.y < b.y
proc determineStartType(start: Point, a: Area): char =
for option in "|-J7FL":
let neighs = neighbours(start, option).filterIt(it.isWithin(a))
if neighs.all(n => neighbours(n, a.charAt(n)).anyIt(it == start)):
return option
proc nextStep(a: Area, p: Point, visited: HashSet[Point]): Option[Point] =
let n = neighbours(p, a.charAt(p)).filterIt(not visited.contains(it))
if n == @[]:
none(Point)
else:
some(n[0])
proc isInside(a: Area, p: Point, v: HashSet[Point]): bool =
if v.contains(p):
return false
var inside = false
var x = p.x
var y = p.y
while (x, y).isWithin(a):
let c = a.charAt((x, y))
if v.contains((x, y)) and c != 'L' and c != '7':
inside = not inside
x += 1
y += 1
inside
proc main() =
let s = readAll(stdin)
var lines = splitLines(s)
var a = Area(data: lines, x: (len lines) - 1, y: len lines[0])
let start = a.findStart()
a.data[start.x][start.y] = determineStartType(start, a)
var visited: HashSet[Point] = initHashSet[Point]()
var np = start
while true:
visited.incl(np)
let nop = nextStep(a, np, visited)
if nop.isNone:
break
else:
np = nop.get()
let length = (len visited) div 2
for x in 0..a.x - 1:
for y in 0..a.y - 1:
if not visited.contains((x, y)):
a.data[x][y] = '.'
var counter = 0
for x in 0..a.x - 1:
for y in 0..a.y - 1:
if isInside(a, (x, y), visited):
counter += 1
echo "Part 1: $1" % [$length]
echo "Part 2: $1" % [$counter]
when isMainModule:
main()

5
2023/10/example Normal file
View File

@ -0,0 +1,5 @@
.....
.S-7.
.|.|.
.L-J.
.....

5
2023/10/example2 Normal file
View File

@ -0,0 +1,5 @@
..F7.
.FJ|.
SJ.L7
|F--J
LJ...

9
2023/10/example3 Normal file
View File

@ -0,0 +1,9 @@
...........
.S-------7.
.|F-----7|.
.||.....||.
.||.....||.
.|L-7.F-J|.
.|..|.|..|.
.L--J.L--J.
...........