Skip to content

Commit

Permalink
add day 11 solutions and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmckendry committed Nov 10, 2024
1 parent 9fca64d commit 88956c3
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 0 deletions.
95 changes: 95 additions & 0 deletions 2021/11p1.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package main

import "core:fmt"
import "core:strconv"
import "core:strings"
import "utils"

D11P1 :: proc() {
lines, backing := utils.read_lines("./inputs/11.txt")
defer delete(lines)
defer delete(backing)

flash_total := get_octopi_energy_flashes(lines, 100)
fmt.printfln("Total flashes after 100 steps: %v", flash_total)
}

get_octopi_energy_flashes :: proc(lines: []string, steps: int) -> int {
energy_levels := parse_octopi_energy_levels(lines)
flashes := 0
for _ in 0 ..< steps {
flashes += simulate_octopus_step(&energy_levels)
}
return flashes
}

parse_octopi_energy_levels :: proc(lines: []string) -> (energy_levels: [10][10]int) {
for line, i in lines {
energy_strings := strings.split(line, "", context.temp_allocator)
for str, j in energy_strings {
energy_levels[i][j] = strconv.atoi(str)
}
}
return
}

simulate_octopus_step :: proc(energy_levels: ^[10][10]int) -> (flashes_in_step: int) {
peak_energy_indexes: [dynamic]Vec2
defer delete(peak_energy_indexes)

for i in 0 ..< 10 {
for j in 0 ..< 10 {
energy_levels[i][j] += 1
if energy_levels[i][j] > 9 {
append(&peak_energy_indexes, Vec2{i, j})
}
}
}

flashes_in_step = simulate_octopus_energy_flash(energy_levels, &peak_energy_indexes)
return
}

simulate_octopus_energy_flash :: proc(
energy_levels: ^[10][10]int,
peak_energy_indexes: ^[dynamic]Vec2,
) -> (
flashes: int,
) {
for len(peak_energy_indexes) > 0 {
current := pop(peak_energy_indexes)
if energy_levels[current.x][current.y] == 0 {
continue
}

energy_levels[current.x][current.y] = 0
flashes += 1

neighbors := []Vec2 {
{current.x - 1, current.y},
{current.x + 1, current.y},
{current.x, current.y - 1},
{current.x, current.y + 1},
{current.x - 1, current.y - 1},
{current.x - 1, current.y + 1},
{current.x + 1, current.y - 1},
{current.x + 1, current.y + 1},
}

for neighbor in neighbors {
// check if neighbor is within bounds
if neighbor.x >= 0 && neighbor.x < 10 && neighbor.y >= 0 && neighbor.y < 10 {
if energy_levels[neighbor.x][neighbor.y] == 0 {
continue
}

energy_levels[neighbor.x][neighbor.y] += 1
if energy_levels[neighbor.x][neighbor.y] > 9 {
append(peak_energy_indexes, neighbor)
}
}
}
}

return
}
24 changes: 24 additions & 0 deletions 2021/11p2.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import "core:fmt"
import "utils"

D11P2 :: proc() {
lines, backing := utils.read_lines("./inputs/11.txt")
defer delete(lines)
defer delete(backing)

all_flash_at_step := get_all_octopi_flash_step(lines)
fmt.printfln("All Octopi flash at step: %v", all_flash_at_step)
}

get_all_octopi_flash_step :: proc(lines: []string) -> int {
energy_levels := parse_octopi_energy_levels(lines)
flashes := 0
steps := 0
for flashes != 100 {
flashes = simulate_octopus_step(&energy_levels)
steps += 1
}
return steps
}
10 changes: 10 additions & 0 deletions 2021/inputs/11.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
2478668324
4283474125
1663463374
1738271323
4285744861
3551311515
8574335438
7843525826
1366237577
3554687226
2 changes: 2 additions & 0 deletions 2021/main.odin
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ solutions: map[string]proc() = {
"09P2:Smoke Basin" = D09P2,
"10P1:Syntax Scoring" = D10P1,
"10P2:Autocomplete Scoring" = D10P2,
"11P1:Dumbo Octopus" = D11P1,
"11P2:Dumbo Octopus" = D11P2,
}

main :: proc() {
Expand Down
111 changes: 111 additions & 0 deletions 2021/tests/11_test.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package main

import "core:fmt"
import "core:testing"

octopi_engery_levels :: []string {
"5483143223",
"2745854711",
"5264556173",
"6141336146",
"6357385478",
"4167524645",
"2176841721",
"6882881134",
"4846848554",
"5283751526",
}

@(test)
d11p1 :: proc(t: ^testing.T) {
want := 1656
got := get_octopi_energy_flashes(octopi_engery_levels, 100)
testing.expect(t, got == want, fmt.tprintf("Got: %v | Want: %v", got, want))
}

@(test)
d11p2 :: proc(t: ^testing.T) {
want := 195
got := get_all_octopi_flash_step(octopi_engery_levels)
testing.expect(t, got == want, fmt.tprintf("Got: %v | Want: %v", got, want))
}

@(test)
test_parse_octopi_enegy_levels :: proc(t: ^testing.T) {
want_map := map[Vec2]int {
{0, 5} = 4,
{3, 0} = 6,
{6, 9} = 1,
{9, 2} = 8,
}

got := parse_octopi_energy_levels(octopi_engery_levels)
for key, value in want_map {
testing.expect(
t,
got[key.x][key.y] == value,
fmt.tprintf("Incorect value at %v: Got: %v | Want: %v", key, got[key.x][key.y], value),
)
}

free_all()
}

@(test)
test_octopi_state_at_step :: proc(t: ^testing.T) {
energy_levels := parse_octopi_energy_levels(octopi_engery_levels)
want_flashes := 0
got_flashes := simulate_octopus_step(&energy_levels)

want_map := map[Vec2]int {
{0, 2} = 9,
{4, 3} = 8,
}
for key, value in want_map {
testing.expect(
t,
energy_levels[key.x][key.y] == value,
fmt.tprintf(
"Incorect value at %v: Got: %v | Want: %v",
key,
energy_levels[key.x][key.y],
value,
),
)
}

testing.expect(
t,
got_flashes == want_flashes,
fmt.tprintf("Got: %v | Want: %v", got_flashes, want_flashes),
)

// add another step
want_flashes = 35
got_flashes = simulate_octopus_step(&energy_levels)

want_map = map[Vec2]int {
{0, 2} = 0,
{4, 3} = 0,
}
for key, value in want_map {
testing.expect(
t,
energy_levels[key.x][key.y] == value,
fmt.tprintf(
"Incorect value at %v: Got: %v | Want: %v",
key,
energy_levels[key.x][key.y],
value,
),
)
}

testing.expect(
t,
got_flashes == want_flashes,
fmt.tprintf("Got: %v | Want: %v", got_flashes, want_flashes),
)

free_all()
}

0 comments on commit 88956c3

Please sign in to comment.