Skip to content

Commit

Permalink
day 06: PART A initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sreedevk committed Dec 6, 2024
1 parent 651075f commit d4692be
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/advent_of_code.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import ceres_search as day04
import gleam/int
import gleam/io
import gleam/result
import guard_gallivant as day06
import historian_hysteria as day01
import mull_it_over as day03
import print_queue as day05
Expand Down Expand Up @@ -75,4 +76,17 @@ pub fn main() {
}),
Nil,
)

// Day 06
result.unwrap(
result.map(read("data/day6.txt"), fn(data) {
io.println(
"[6] Print Queue (Part 1): " <> int.to_string(day06.solve_a(data)),
)
io.println(
"[6] Print Queue (Part 2): " <> int.to_string(day06.solve_b(data)),
)
}),
Nil,
)
}
138 changes: 138 additions & 0 deletions src/guard_gallivant.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import gleam/dict.{type Dict}
import gleam/list
import gleam/pair
import gleam/result
import gleam/string
import utils/list as li

type Entity {
Guard
Obstacle
Path
Unknown(String)
}

type Point =
#(Int, Int)

type Grid =
Dict(Point, Entity)

type Direction {
Up
Down
Left
Right
}

type State =
#(Point, Direction, Grid, List(Point))

fn parse_line(line, y) {
use grid, char, x <- list.index_fold(line, dict.new())
dict.insert(grid, #(x, y), case char {
"." -> Path
"#" -> Obstacle
"^" -> Guard
uchr -> Unknown(uchr)
})
}

fn parse_grid(input: String) -> Grid {
input
|> string.trim()
|> string.split("\n")
|> list.map(string.to_graphemes)
|> list.index_map(parse_line)
|> list.reduce(dict.merge)
|> result.unwrap(dict.new())
}

fn is_guard_position(position) -> Bool {
case position {
#(_, entity) if entity == Guard -> True
_ -> False
}
}

fn guard_position(grid: Grid) -> Result(Point, Nil) {
dict.to_list(grid)
|> list.find(is_guard_position)
|> result.map(fn(set) { pair.first(set) })
}

fn init_state(grid: Grid) -> State {
let assert Ok(gp) = guard_position(grid)
#(gp, Up, grid, [gp])
}

fn max_x(grid: Grid) -> Int {
li.max(list.map(dict.keys(grid), pair.first))
}

fn max_y(grid: Grid) -> Int {
li.max(list.map(dict.keys(grid), pair.second))
}

fn update_coordinates(position: Point, direction: Direction) -> Point {
case direction {
Up -> #(pair.first(position), pair.second(position) - 1)
Down -> #(pair.first(position), pair.second(position) + 1)
Left -> #(pair.first(position) - 1, pair.second(position))
Right -> #(pair.first(position) + 1, pair.second(position))
}
}

fn is_obstacle(position: Point, grid: Grid) -> Bool {
case dict.get(grid, position) {
Ok(Obstacle) -> True
_ -> False
}
}

fn rotate_cw(d: Direction) -> Direction {
case d {
Up -> Right
Down -> Left
Right -> Down
Left -> Up
}
}

fn next_coordinates(pos: Point, dir: Direction, g: Grid) -> #(Point, Direction) {
let np = update_coordinates(pos, dir)
case is_obstacle(np, g) {
True -> next_coordinates(pos, rotate_cw(dir), g)
False -> #(np, dir)
}
}

fn guard_exited(pos: Point, g: Grid) -> Bool {
let #(x, y) = pos
x > max_x(g) || x < 0 || y < 0 || y > max_y(g)
}

fn emulate(state: State) -> State {
let #(gp, gd, g, vs) = state
let #(ngp, ngd) = next_coordinates(gp, gd, g)
case guard_exited(ngp, g) {
True -> state
False -> emulate(#(ngp, ngd, g, list.append(vs, [ngp])))
}
}

fn visited_count(st: State) -> Int {
let #(_, _, _, hist) = st
list.length(list.unique(hist))
}

pub fn solve_a(input: String) -> Int {
parse_grid(input)
|> init_state
|> emulate
|> visited_count
}

pub fn solve_b(_input: String) -> Int {
0
}
9 changes: 9 additions & 0 deletions src/utils/list.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,12 @@ pub fn swap(ls: List(a), ea: a, eb: a) -> List(a) {
val -> val
}
}

pub fn max(ls: List(Int)) -> Int {
li.fold(ls, 0, fn(cmx, cx) {
case cx {
cxx if cxx > cmx -> cxx
_ -> cmx
}
})
}
21 changes: 21 additions & 0 deletions test/guard_gallivant_test.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import gleam/string
import gleeunit/should
import guard_gallivant as day05

fn test_data() {
string.join(
[
"....#.....", ".........#", "..........", "..#.......", ".......#..",
"..........", ".#..^.....", "........#.", "#.........", "......#...",
],
"\n",
)
}

pub fn solve_a_test() {
should.equal(day05.solve_a(test_data()), 41)
}

pub fn solve_b_test() {
should.equal(day05.solve_b(test_data()), 0)
}

0 comments on commit d4692be

Please sign in to comment.