Skip to content

Commit

Permalink
add day 6 solutions and tests
Browse files Browse the repository at this point in the history
use old odin release to fix ci error
  • Loading branch information
scottmckendry committed Dec 7, 2024
1 parent 7e26732 commit b34b241
Show file tree
Hide file tree
Showing 6 changed files with 433 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
- uses: laytan/setup-odin@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
release: dev-2024-11
- name: Report
run: |
odin report ./2021
Expand All @@ -34,6 +35,7 @@ jobs:
- uses: laytan/setup-odin@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
release: dev-2024-11

- run: cd 2021 && task bench
- run: cd 2022 && go build .
Expand Down
107 changes: 107 additions & 0 deletions 2024/06p1.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package main

import "core:fmt"
import "core:strings"

vec2 :: struct {
x, y: int,
}

lab_map_coord :: struct {
is_obstacle: bool,
visited: bool,
}

D06P1 :: proc() {
input_string := #load("inputs/06.txt", string)
lines := strings.split(input_string, "\n", context.temp_allocator)

unique_guard_positions := get_unique_guard_positions(lines[:len(lines) - 1])
fmt.printf("Unique guard positions: %d\n", unique_guard_positions)
}

get_unique_guard_positions :: proc(lines: []string) -> int {
lab_map, guard_position, max_x, max_y := parse_lab_map(lines)
defer delete(lab_map)

guard_direction := vec2{0, -1}

visited_count := 1

on_map := true
for on_map {
// walk in direction until obstacle, then turn 90 degrees
for {
next_position: vec2
next_position.x, next_position.y =
guard_position.x + guard_direction.x, guard_position.y + guard_direction.y
if lab_map[next_position].is_obstacle {
break
}

if next_position.x < 0 ||
next_position.x >= max_x ||
next_position.y < 0 ||
next_position.y >= max_y {
on_map = false
break
}

guard_position = next_position
if !lab_map[guard_position].visited {
visited_count += 1
guard_map_coord := lab_map[guard_position]
guard_map_coord.visited = true
lab_map[guard_position] = guard_map_coord
}
}

// turn 90 degrees
if guard_direction.x == 0 {
if guard_direction.y == 1 {
guard_direction = vec2{-1, 0}
} else {
guard_direction = vec2{1, 0}
}
} else {
if guard_direction.x == 1 {
guard_direction = vec2{0, 1}
} else {
guard_direction = vec2{0, -1}
}
}
}

return visited_count
}

parse_lab_map :: proc(
lines: []string,
) -> (
lab_map: map[vec2]lab_map_coord,
guard_position: vec2,
max_x: int,
max_y: int,
) {
for line, y in lines {
for char, x in line {
switch char {
case '^':
guard_position = vec2{x, y}
lab_map[vec2{x, y}] = lab_map_coord {
visited = true,
}
case '#':
lab_map[vec2{x, y}] = lab_map_coord {
is_obstacle = true,
}
case:
lab_map[vec2{x, y}] = lab_map_coord{}
}
}
}

max_x = len(lines[0])
max_y = len(lines)
return
}
114 changes: 114 additions & 0 deletions 2024/06p2.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package main

import "core:fmt"
import "core:strings"

type_visited :: struct {
position, direction: vec2,
}

D06P2 :: proc() {
input_string := #load("inputs/06.txt", string)
lines := strings.split(input_string, "\n", context.temp_allocator)

loop_causing_obstacles := get_loop_causing_obstacles(lines[:len(lines) - 1])
fmt.printf("Number of loop-causing obstacle positions: %d\n", loop_causing_obstacles)
}

get_loop_causing_obstacles :: proc(lines: []string) -> int {
original_map, guard_position, max_x, max_y := parse_lab_map(lines)
defer delete(original_map)

loop_count := 0

// place a obstable at each possible position, and check if it causes a loop
for y in 0 ..< max_y {
for x in 0 ..< max_x {
if original_map[vec2{x, y}].is_obstacle ||
(x == guard_position.x && y == guard_position.y) {
continue
}

// create a new map and copy all entries
lab_map := make(map[vec2]lab_map_coord)
for k, v in original_map {
lab_map[k] = v
}
defer delete(lab_map)

// update the new position
coord_to_update := lab_map[vec2{x, y}]
coord_to_update.is_obstacle = true
lab_map[vec2{x, y}] = coord_to_update

if check_for_loop(lab_map, guard_position, max_x, max_y) {
loop_count += 1
}
}
}

return loop_count
}

check_for_loop :: proc(
lab_map: map[vec2]lab_map_coord,
guard_position: vec2,
max_x, max_y: int,
) -> bool {
guard_direction := vec2{0, -1}
guard_pos := guard_position

Position_State :: struct {
pos: vec2,
dir: vec2,
}
visited_states := make(map[Position_State]bool)
defer delete(visited_states)

on_map := true

for on_map {
current_state := Position_State{guard_pos, guard_direction}
if visited_states[current_state] {
return true
}

visited_states[current_state] = true

for {
next_position: vec2
next_position.x, next_position.y =
guard_pos.x + guard_direction.x, guard_pos.y + guard_direction.y
if lab_map[next_position].is_obstacle {
break
}

if next_position.x < 0 ||
next_position.x >= max_x ||
next_position.y < 0 ||
next_position.y >= max_y {
on_map = false
break
}

guard_pos = next_position
}

// turn 90 degrees (same as before)
if guard_direction.x == 0 {
if guard_direction.y == 1 {
guard_direction = vec2{-1, 0}
} else {
guard_direction = vec2{1, 0}
}
} else {
if guard_direction.x == 1 {
guard_direction = vec2{0, 1}
} else {
guard_direction = vec2{0, -1}
}
}
}

return false
}
Loading

0 comments on commit b34b241

Please sign in to comment.