Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More days #203

Merged
merged 6 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,000 changes: 1,000 additions & 0 deletions day-12/input/vanyle.txt

Large diffs are not rendered by default.

116 changes: 116 additions & 0 deletions day-12/part-1/vanyle.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from times import cpuTime
from os import paramStr

import tables, strutils, sequtils, sugar, hashes

func parseInput(s: string): seq[(string, seq[uint8])] =
let lines = s.strip.splitLines
for i in lines:
var s = i.split(" ",2)

result.add((
s[0],
s[1].split(",").map(x => x.parseInt().uint8)
))


type LinkedString = object
c: char
h: Hash
n: int32 # index to next element.

var memory: seq[LinkedString]

proc addAtEnd(ll: int32, c: char): int32 =
var lh = hashes.hash(0)
if ll != -1:
lh = memory[ll].h

var ls = LinkedString(
c: c,
n: ll,
h: lh !& hash(c)
)
memory.add(ls)
return memory.len.int32 - 1

proc toLinkedString(s: string): int32 =
var current = -1.int32
for i in s:
current = current.addAtEnd(i)
return current

proc hash(ll: int): Hash =
if ll == -1: return hash(0)
return memory[ll].h

var hints: seq[uint8]
var memoTable: Table[(int32, uint8, uint8), int]
proc possibilities(pattern: int32, hintSlice: uint8, counterSeq: uint8): int =
# Recursion, my boy!!
if (pattern, hintSlice, counterSeq) in memoTable:
return memoTable[(pattern, hintSlice, counterSeq)]

if pattern == -1:
if hintSlice > 1:
return 0
if hintSlice == 0 and counterSeq == 0:
return 1
if hintSlice == 1 and counterSeq == hints[0]:
return 1
return 0

var brokenCounter = counterSeq
var pp = pattern

while pp != -1:
var el = memory[pp]
if el.c == '#':
inc brokenCounter
elif el.c == '.':
if brokenCounter == 0:
pp = el.n
continue
if hintSlice == 0:
return 0
if hints[hintSlice-1] == brokenCounter: # ok!
var r = possibilities(el.n, hintSlice - 1, 0)
memoTable[(pattern, hintSlice, counterSeq)] = r
return r
else:
return 0 # impossible!
elif el.c == '?':
var p1 = el.n.addAtEnd('.')
var c1 = possibilities(p1, hintSlice, brokenCounter)

var p2 = el.n.addAtEnd('#')
var c2 = possibilities(p2, hintSlice, brokenCounter)

memoTable[(pattern, hintSlice, counterSeq)] = c1 + c2
return c1 + c2
pp = el.n

# make sure the counter and the hint match here.
return possibilities(-1, hintSlice, brokenCounter)

proc run(s: string): string =
var r = parseInput(s)
var res = 0
memory = newSeqOfCap[LinkedString](3000)

for i in r:
hints = i[1]
memoTable.clear()
memory.setLen(0)
var p = possibilities(i[0].toLinkedString(), i[1].len.uint8, 0)
res += p
return $res


var input: string = paramStr(1)

var t0 = cpuTime()
var output = run(input)

echo "_duration:", (cpuTime() - t0) * 1000
echo output
91 changes: 91 additions & 0 deletions day-12/part-2/vanyle.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from times import cpuTime
from os import paramStr

import tables, strutils, sequtils, sugar, hashes

func parseInput(s: string): seq[(string, seq[uint8])] =
let lines = s.strip.splitLines
for i in lines:
var s = i.split(" ",2)

result.add((
s[0],
s[1].split(",").map(x => x.parseInt().uint8)
))


var hints: seq[uint8]
var memoTable: Table[(string, int16, uint8, uint8), int]
proc possibilities(pattern: string, pslice: int16, hintSlice: uint8, counterSeq: uint8): int =
# Recursion, my boy!!
if (pattern, pslice, hintSlice, counterSeq) in memoTable:
return memoTable[(pattern, pslice, hintSlice, counterSeq)]

if pslice == -1:
if hintSlice > 1:
return 0
if hintSlice == 0 and counterSeq == 0:
return 1
if hintSlice == 1 and counterSeq == hints[0]:
return 1
return 0

var brokenCounter = counterSeq

for j in countdown(pslice, 0):
if pattern[j] == '#':
inc brokenCounter
elif pattern[j] == '.':
if brokenCounter == 0: continue
if hintSlice == 0: return 0
if hints[hintSlice-1] == brokenCounter: # ok!
var r = possibilities(pattern, j-1, hintSlice - 1, 0)
memoTable[(pattern, pslice, hintSlice, counterSeq)] = r
return r
else:
return 0 # impossible!
elif pattern[j] == '?':
var p1 = pattern[0..<j] & '.'
var c1 = possibilities(p1, j, hintSlice, brokenCounter)

p1[j] = '#'
var c2 = possibilities(p1, j, hintSlice, brokenCounter)

memoTable[(pattern, pslice, hintSlice, counterSeq)] = c1 + c2
return c1 + c2

# make sure the counter and the hint match here.
return possibilities(pattern, -1, hintSlice, brokenCounter)

proc duplicate(pattern: string, hints: seq[uint8]): (string, seq[uint8]) =
var patfive = ""
var hintfive: seq[uint8] = @[]
for i in 0..<5:
patfive &= pattern
if i != 4:
patfive.add "?"
hintfive = hintfive.concat(hints)

return (patfive, hintfive)

proc run(s: string): string =
var r = parseInput(s)
var res = 0

for i in r:
var j = duplicate(i[0], i[1])
hints = j[1]
memoTable.clear()
var p = possibilities(j[0], (j[0].len-1).int16, j[1].len.uint8, 0)
res += p

return $res


var input: string = paramStr(1)

var t0 = cpuTime()
var output = run(input)

echo "_duration:", (cpuTime() - t0) * 1000
echo output
Loading