Skip to content

Commit d3b1a95

Browse files
committed
feat: Solving day 9
1 parent 2a31566 commit d3b1a95

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

docs/day9.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
url: "https://adventofcode.com/2024/day/9"
3+
---
4+
5+
# Day 9: Disk Fragmenter ---
6+
Another push of the button leaves you in the familiar hallways of some friendly amphipods! Good thing you each somehow got your own personal mini submarine. The Historians jet away in search of the Chief, mostly by driving directly into walls.
7+
8+
While The Historians quickly figure out how to pilot these things, you notice an amphipod in the corner struggling with his computer. He's trying to make more contiguous free space by compacting all of the files, but his program isn't working; you offer to help.
9+
10+
He shows you the disk map (your puzzle input) he's already generated. For example:
11+
12+
```txt
13+
2333133121414131402
14+
```
15+
16+
The disk map uses a dense format to represent the layout of files and free space on the disk. The digits alternate between indicating the length of a file and the length of free space.
17+
18+
So, a disk map like `12345` would represent a one-block file, two blocks of free space, a three-block file, four blocks of free space, and then a five-block file. A disk map like `90909` would represent three nine-block files in a row (with no free space between them).
19+
20+
Each file on disk also has an ID number based on the order of the files as they appear before they are rearranged, starting with ID `0`.
21+
22+
So, the disk map `12345` has three files: a one-block file with ID `0`, a three-block file with ID `1`, and a five-block file with ID `2`. Using one character for each block where digits are the file ID and `.` is free space, the disk map `12345` represents these individual blocks:
23+
24+
```txt
25+
0..111....22222
26+
```
27+
28+
The first example above, `2333133121414131402`, represents these individual blocks:
29+
30+
```txt
31+
00...111...2...333.44.5555.6666.777.888899
32+
```
33+
34+
The amphipod would like to move file blocks one at a time from the end of the disk to the leftmost free space block (until there are no gaps remaining between file blocks). For the disk map `12345`, the process looks like this:
35+
36+
```txt
37+
0..111....22222
38+
02.111....2222.
39+
022111....222..
40+
0221112...22...
41+
02211122..2....
42+
022111222......
43+
```
44+
45+
The first example requires a few more steps:
46+
47+
```txt
48+
00...111...2...333.44.5555.6666.777.888899
49+
009..111...2...333.44.5555.6666.777.88889.
50+
0099.111...2...333.44.5555.6666.777.8888..
51+
00998111...2...333.44.5555.6666.777.888...
52+
009981118..2...333.44.5555.6666.777.88....
53+
0099811188.2...333.44.5555.6666.777.8.....
54+
009981118882...333.44.5555.6666.777.......
55+
0099811188827..333.44.5555.6666.77........
56+
00998111888277.333.44.5555.6666.7.........
57+
009981118882777333.44.5555.6666...........
58+
009981118882777333644.5555.666............
59+
00998111888277733364465555.66.............
60+
0099811188827773336446555566..............
61+
```
62+
63+
The final step of this file-compacting process is to update the filesystem checksum. To calculate the checksum, add up the result of multiplying each of these blocks' position with the file ID number it contains. The leftmost block is in position `0`. If a block contains free space, skip it instead.
64+
65+
Continuing the first example, the first few blocks' position multiplied by its file ID number are `0 * 0 = 0, 1 * 0 = 0, 2 * 9 = 18, 3 * 9 = 27, 4 * 8 = 32`, and so on. In this example, the checksum is the sum of these, `1928`.
66+
67+
Compact the amphipod's hard drive using the process he requested. What is the resulting filesystem checksum?

src/day9/day9.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package day9
2+
3+
import (
4+
"strconv"
5+
)
6+
7+
const ZERO_RUNE = '0'
8+
const EMPTY_RUNE = '.'
9+
const EMPTY_STRING = string(EMPTY_RUNE)
10+
11+
func Solve(input string) int {
12+
return checksum(compress(expand(input)))
13+
}
14+
15+
func expand(input string) string {
16+
var result string
17+
blankSpace := false
18+
id := 0
19+
for _, fileSize := range input {
20+
for i := 0; i < runeToInt(fileSize); i++ {
21+
if blankSpace {
22+
result += EMPTY_STRING
23+
} else {
24+
result += strconv.Itoa(id)
25+
}
26+
}
27+
if !blankSpace {
28+
id += 1
29+
}
30+
blankSpace = !blankSpace
31+
}
32+
return result
33+
}
34+
35+
func compress(input string) string {
36+
result := []byte(input)
37+
ptr, tailPtr := 0, len(input)-1
38+
for {
39+
if result[tailPtr] != EMPTY_RUNE || tailPtr <= 0 {
40+
break
41+
}
42+
tailPtr--
43+
}
44+
45+
for {
46+
if ptr >= tailPtr {
47+
break
48+
}
49+
if result[ptr] != EMPTY_RUNE {
50+
ptr++
51+
continue
52+
}
53+
result[ptr] = result[tailPtr]
54+
result[tailPtr] = EMPTY_RUNE
55+
ptr++
56+
for {
57+
tailPtr--
58+
if result[tailPtr] != EMPTY_RUNE {
59+
break
60+
}
61+
}
62+
}
63+
return string(result)
64+
}
65+
66+
func checksum(input string) int {
67+
result := 0
68+
for i, d := range input {
69+
if d == EMPTY_RUNE {
70+
break
71+
}
72+
result += i * runeToInt(d)
73+
}
74+
return result
75+
}
76+
77+
func runeToInt(r rune) int {
78+
return int(r - ZERO_RUNE)
79+
}

src/day9/day9_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package day9
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestSample(t *testing.T) {
8+
input := `2333133121414131402`
9+
result := Solve(input)
10+
if result != 1928 {
11+
t.Errorf("Calculated solution was not expected")
12+
}
13+
}

0 commit comments

Comments
 (0)