Skip to content

Commit

Permalink
day 04: optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
sreedevk committed Dec 4, 2024
1 parent 028b21c commit a0d2dc2
Showing 1 changed file with 41 additions and 126 deletions.
167 changes: 41 additions & 126 deletions src/ceres_search.gleam
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import gleam/dict.{type Dict}
import gleam/int
import gleam/io
import gleam/list
import gleam/pair
import gleam/result
Expand All @@ -10,159 +9,75 @@ type Point =
#(Int, Int)

type Grid =
Dict(#(Int, Int), String)
Dict(Point, String)

fn parse_grid(input: String) -> Grid {
fn process_grid(input: String, f: fn(Grid) -> Int) -> Int {
input
|> string.trim()
|> string.split("\n")
|> list.map(string.to_graphemes)
|> list.index_map(fn(line, y) {
list.index_fold(line, dict.new(), fn(grid, char, x) {
dict.insert(grid, #(x, y), char)
})
use grid, char, x <- list.index_fold(line, dict.new())
dict.insert(grid, #(x, y), char)
})
|> list.reduce(dict.merge)
|> result.unwrap(dict.new())
|> f
}

fn forward(point: Point) -> List(Point) {
[
point,
#(pair.first(point) + 1, pair.second(point)),
#(pair.first(point) + 2, pair.second(point)),
#(pair.first(point) + 3, pair.second(point)),
]
}

fn backward(point: Point) -> List(Point) {
[
point,
#(pair.first(point) - 1, pair.second(point)),
#(pair.first(point) - 2, pair.second(point)),
#(pair.first(point) - 3, pair.second(point)),
]
}

fn upward(point: Point) -> List(Point) {
[
point,
#(pair.first(point), pair.second(point) - 1),
#(pair.first(point), pair.second(point) - 2),
#(pair.first(point), pair.second(point) - 3),
]
}

fn downward(point: Point) -> List(Point) {
[
point,
#(pair.first(point), pair.second(point) + 1),
#(pair.first(point), pair.second(point) + 2),
#(pair.first(point), pair.second(point) + 3),
]
fn word(points: List(Point), grid: Grid) -> String {
use word, point <- list.fold(points, "")
string.append(word, result.unwrap(dict.get(grid, point), ""))
}

fn upward_left(point: Point) -> List(Point) {
[
point,
#(pair.first(point) - 1, pair.second(point) - 1),
#(pair.first(point) - 2, pair.second(point) - 2),
#(pair.first(point) - 3, pair.second(point) - 3),
]
fn all_neighbors(point: Point, word: String) -> List(List(Point)) {
let id = fn(x, _d) { x }
use f <- list.map([
#(int.add, id),
#(int.subtract, id),
#(id, int.subtract),
#(id, int.add),
#(int.subtract, int.subtract),
#(int.add, int.subtract),
#(int.subtract, int.add),
#(int.add, int.add),
])
use d <- list.map(list.range(0, string.length(word) - 1))
let #(x, y) = point
#(pair.first(f)(x, d), pair.second(f)(y, d))
}

fn upward_right(point: Point) -> List(Point) {
fn x_neighbors(point: #(Int, Int)) {
let #(x, y) = point
[
point,
#(pair.first(point) + 1, pair.second(point) - 1),
#(pair.first(point) + 2, pair.second(point) - 2),
#(pair.first(point) + 3, pair.second(point) - 3),
[#(x - 1, y - 1), point, #(x + 1, y + 1)],
[#(x + 1, y - 1), point, #(x - 1, y + 1)],
]
}

fn downward_left(point: Point) -> List(Point) {
[
point,
#(pair.first(point) - 1, pair.second(point) + 1),
#(pair.first(point) - 2, pair.second(point) + 2),
#(pair.first(point) - 3, pair.second(point) + 3),
]
}

fn downward_right(point: Point) -> List(Point) {
[
point,
#(pair.first(point) + 1, pair.second(point) + 1),
#(pair.first(point) + 2, pair.second(point) + 2),
#(pair.first(point) + 3, pair.second(point) + 3),
]
}

fn neighbors(point: Point) -> List(List(Point)) {
[
forward(point),
backward(point),
upward(point),
downward(point),
upward_left(point),
upward_right(point),
downward_left(point),
downward_right(point),
]
}

fn x_neighbors(point: Point) -> List(List(Point)) {
[
[
#(pair.first(point) - 1, pair.second(point) - 1),
point,
#(pair.first(point) + 1, pair.second(point) + 1),
],
[
#(pair.first(point) + 1, pair.second(point) - 1),
point,
#(pair.first(point) - 1, pair.second(point) + 1),
],
]
}

fn fetch(points: List(Point), grid: Grid) -> String {
list.fold(points, "", fn(word, point) {
result.unwrap(dict.get(grid, point), "")
|> string.append(word)
})
}

fn word_count_at_point(grid: Grid, point: Point) -> Int {
neighbors(point)
|> list.map(fetch(_, grid))
|> list.count(fn(word) { word == "XMAS" })
fn xmas_count_at_point(grid: Grid, point: Point) -> Int {
all_neighbors(point, "XMAS")
|> list.map(word(_, grid))
|> list.count(fn(w) { w == "XMAS" })
}

fn point_has_x_mas(grid: Grid, point: Point) -> Bool {
x_neighbors(point)
|> list.map(fetch(_, grid))
|> list.all(fn(word) { word == "MAS" || word == "SAM" })
|> list.map(word(_, grid))
|> list.all(fn(w) { w == "MAS" || w == "SAM" })
}

fn process_grid_xmas(grid: Grid) -> Int {
dict.keys(grid)
|> list.map(fn(point) { word_count_at_point(grid, point) })
|> list.reduce(int.add)
|> result.unwrap(0)
}
pub fn solve_a(input: String) -> Int {
use grid <- process_grid(input)

fn process_grid_x_mas(grid: Grid) -> Int {
dict.keys(grid)
|> list.count(fn(point) { point_has_x_mas(grid, point) })
}

pub fn solve_a(input: String) -> Int {
parse_grid(input)
|> process_grid_xmas()
|> list.map(xmas_count_at_point(grid, _))
|> list.fold(0, int.add)
}

pub fn solve_b(input: String) -> Int {
parse_grid(input)
|> process_grid_x_mas()
use grid <- process_grid(input)

dict.keys(grid)
|> list.count(point_has_x_mas(grid, _))
}

0 comments on commit a0d2dc2

Please sign in to comment.