1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
import std/strutils
import std/sequtils
import std/enumerate
import std/algorithm
import std/re
type
Move = tuple
Amount: int
From: int
To: int
Stack = seq[char]
Input = tuple
Stacks: seq[Stack]
Moves: seq[Move]
proc parseContent(content: string): Input =
# Parse stacks
let tokens = content.split("\n\n")
var strStacks = map(
# All lines containing characters of the stacks
# Exclude last line since it contain's each stack's id
tokens[0].splitLines()[0 .. ^2],
proc(line: string): string =
var retval = ""
# keep only the relevant characters (spaces/letters)
for i in countup(1, line.len(), 4):
retval.add(line[i])
retval
)
var Stacks = newSeq[Stack](10)
for layer in strStacks:
for i, c in enumerate(layer):
if c != ' ':
Stacks[i+1].add(c)
var strMoves = map(
# All moves described in the input
tokens[1].strip().splitLines(),
proc(line: string): seq[int] =
# Remove words and split on spaces
let tokens = line.replace(re"[a-z]+ ").split(" ")
# Parse them as integers
map(tokens, proc (num: string): int = num.parseInt())
)
var Moves: seq[Move]
for move in strMoves:
Moves.add((move[0], move[1], move[2]))
return (Stacks, Moves)
proc makeMove(stacks: var seq[Stack], move: Move, inPlace = false): void =
# copy top of the stack
var yoink = stacks[move.From][0 ..< move.Amount]
# moving in place preserves the order of the moved crates (part2)
if not inPlace:
yoink.reverse()
# remove it from origin
stacks[move.From].delete(0 ..< move.Amount)
# concat it in front of destination
stacks[move.To] = concat(yoink, stacks[move.To])
proc getAnswer(stacks: seq[Stack]): string =
var answer = ""
for stack in stacks:
if stack.len() > 0:
answer.add(stack[0])
answer
let content = readFile("./input.txt")
var input = parseContent(content)
let moves = input.Moves
var stacksPart1 = input.Stacks
var stacksPart2 = input.Stacks
for move in moves:
makeMove(stacksPart1, move)
makeMove(stacksPart2, move, true)
echo getAnswer(stacksPart1)
echo getAnswer(stacksPart2)
|