Advent of Code 2022 - Day 5: Supply Stacks Solution

Transform (the hard part) and mutate

Part 1

Transform the raw data

1[D]
2[N] [C]
3[Z] [M] [P]
4 1 2 3
5
6move 1 from 2 to 1
7move 3 from 1 to 3
8move 2 from 2 to 1
9move 1 from 1 to 2

into the following format

1{
2 stackData: [ [ 'Z', 'N' ], [ 'M', 'C', 'D' ], [ 'P' ] ],
3 moveData: [
4 { numberOfItemsToMove: 1, srcStack: 1, destStack: 0 },
5 { numberOfItemsToMove: 3, srcStack: 0, destStack: 2 },
6 { numberOfItemsToMove: 2, srcStack: 1, destStack: 0 },
7 { numberOfItemsToMove: 1, srcStack: 0, destStack: 1 }
8 ]
9}

With every move

  • Grab itemsToMove from srcStack
  • Reverse it
  • Push to destStack

Implementation

1const fs = require("fs")
2
3const transpose = matrix => {
4 return matrix[0].map((_, colIdx) =>
5 matrix
6 .map(row => row[colIdx])
7 .reverse()
8 .filter(Boolean)
9 )
10}
11
12const readData = () => {
13 const data = fs.readFileSync("./sample-input", "utf-8").split(/\r?\n/)
14
15 let rawStackData = []
16
17 let i = 0
18
19 while (data[i] !== "") {
20 rawStackData.push(data[i++].split("").map(char => char.replace(" ", "")))
21 }
22 rawStackData.pop() // remove emply line
23
24 // take N as the numberOfStacks
25 // total character in one line is:
26 // each item in the stack, for example, "[X]" takes 3 characters
27 // N-1 spaces between items
28 // in total, we have 3N + (N-1) = 4N - 1 characters
29 const numberOfStacks = (rawStackData[0].length + 1) / 4
30
31 // [ Z ] S [ M ] S [ P ] (S means "space")
32 // 0 1 2 3 4 5 6 7 8 9 10
33 // item indexes will be 1 5 9
34 // which are even-index element of odd numbers (1, 3, 5, 7, 9,..)
35 let itemIndexes = Array.from(
36 { length: rawStackData[0].length },
37 (_, i) => 2 * i + 1
38 )
39 .filter((_, i) => i % 2 === 0)
40 .slice(0, numberOfStacks)
41
42 let stackData = transpose(
43 rawStackData.map(data => itemIndexes.map(i => data[i]))
44 )
45
46 let moveData = data
47 .slice(i)
48 .filter(Boolean)
49 .map(moveStatement =>
50 moveStatement
51 .replace(/move (\d+) from (\d+) to (\d+)/g, "$1 $2 $3")
52 .split(" ")
53 .map(Number)
54 )
55 .map(([numberOfItemsToMove, srcStack, destStack]) => ({
56 numberOfItemsToMove,
57 srcStack: srcStack - 1,
58 destStack: destStack - 1,
59 }))
60
61 return [stackData, moveData]
62}
63
64const main = () => {
65 const [stackData, moveData] = readData()
66
67 console.log({ stackData, moveData })
68
69 for (const { numberOfItemsToMove, srcStack, destStack } of moveData) {
70 const itemsToMove = stackData[srcStack].slice(-numberOfItemsToMove)
71 stackData[srcStack] = stackData[srcStack].slice(0, -numberOfItemsToMove)
72 stackData[destStack] = [...stackData[destStack], ...itemsToMove.reverse()]
73 }
74
75 const res = stackData.map(data => data.slice(-1)[0]).join("")
76
77 console.log(res)
78}
79
80main()

Part 2

Similar to Part 1, but no need to reverse itemsToMove

Implementation

1const fs = require("fs")
2
3const transpose = matrix => {
4 return matrix[0].map((_, colIdx) =>
5 matrix
6 .map(row => row[colIdx])
7 .reverse()
8 .filter(Boolean)
9 )
10}
11
12const readData = () => {
13 const data = fs.readFileSync("./sample-input", "utf-8").split(/\r?\n/)
14
15 let rawStackData = []
16
17 let i = 0
18
19 while (data[i] !== "") {
20 rawStackData.push(data[i++].split("").map(char => char.replace(" ", "")))
21 }
22 rawStackData.pop() // remove emply line
23
24 // take N as the numberOfStacks
25 // total character in one line is:
26 // each item in the stack, for example, "[X]" takes 3 characters
27 // N-1 spaces between items
28 // in total, we have 3N + (N-1) = 4N - 1 characters
29 const numberOfStacks = (rawStackData[0].length + 1) / 4
30
31 // [ Z ] S [ M ] S [ P ] (S means "space")
32 // 0 1 2 3 4 5 6 7 8 9 10
33 // item indexes will be 1 5 9
34 // which are even-index element of odd numbers (1, 3, 5, 7, 9,..)
35 let itemIndexes = Array.from(
36 { length: rawStackData[0].length },
37 (_, i) => 2 * i + 1
38 )
39 .filter((_, i) => i % 2 === 0)
40 .slice(0, numberOfStacks)
41
42 let stackData = transpose(
43 rawStackData.map(data => itemIndexes.map(i => data[i]))
44 )
45
46 let moveData = data
47 .slice(i)
48 .filter(Boolean)
49 .map(moveStatement =>
50 moveStatement
51 .replace(/move (\d+) from (\d+) to (\d+)/g, "$1 $2 $3")
52 .split(" ")
53 .map(Number)
54 )
55 .map(([numberOfItemsToMove, srcStack, destStack]) => ({
56 numberOfItemsToMove,
57 srcStack: srcStack - 1,
58 destStack: destStack - 1,
59 }))
60
61 return [stackData, moveData]
62}
63
64const main = () => {
65 const [stackData, moveData] = readData()
66
67 console.log({ stackData, moveData })
68
69 for (const { numberOfItemsToMove, srcStack, destStack } of moveData) {
70 const itemsToMove = stackData[srcStack].slice(-numberOfItemsToMove)
71 stackData[srcStack] = stackData[srcStack].slice(0, -numberOfItemsToMove)
72 stackData[destStack] = [...stackData[destStack], ...itemsToMove]
73 }
74
75 const res = stackData.map(data => data.slice(-1)[0]).join("")
76
77 console.log(res)
78}
79
80main()

References

Original problem

Comments

Loading comments...

Tags

adventofcode

stack

Next Post

Advent of Code 2022 - Day 6: Tuning Trouble

Use a Set to check if all is different

Previous Post

HoningJS

Search Posts