-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1a22a12
Showing
12 changed files
with
351 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: test | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
- main | ||
pull_request: | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: erlef/setup-beam@v1 | ||
with: | ||
otp-version: "26.0.2" | ||
gleam-version: "1.5.1" | ||
rebar3-version: "3" | ||
# elixir-version: "1.15.4" | ||
- run: gleam deps download | ||
- run: gleam test | ||
- run: gleam format --check src test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.beam | ||
*.ez | ||
/build | ||
erl_crash.dump |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# aoc2024 | ||
|
||
[](https://github.com/devries/advent_of_code_2024/actions/workflows/test.yml) | ||
[](https://adventofcode.com/2024) | ||
|
||
This year I am going to try to do Advent of Code in [Gleam](https://gleam.run). | ||
To run a day's problems use the command | ||
|
||
```sh | ||
gleam run -m day01/solution | ||
``` | ||
|
||
To run the unit tests for all the days run | ||
|
||
```sh | ||
gleam test | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name = "aoc2024" | ||
version = "1.0.0" | ||
|
||
# Fill out these fields if you intend to generate HTML documentation or publish | ||
# your project to the Hex package manager. | ||
# | ||
# description = "" | ||
# licences = ["Apache-2.0"] | ||
# repository = { type = "github", user = "", repo = "" } | ||
# links = [{ title = "Website", href = "" }] | ||
# | ||
# For a full reference of all the available options, you can have a look at | ||
# https://gleam.run/writing-gleam/gleam-toml/. | ||
|
||
[dependencies] | ||
gleam_stdlib = ">= 0.34.0 and < 2.0.0" | ||
simplifile = ">= 2.2.0 and < 3.0.0" | ||
|
||
[dev-dependencies] | ||
gleeunit = ">= 1.0.0 and < 2.0.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# This file was generated by Gleam | ||
# You typically do not need to edit this file | ||
|
||
packages = [ | ||
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" }, | ||
{ name = "gleam_stdlib", version = "0.41.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "1B2F80CB1B66B027E3198A2FF71EF3F2F31DF89ED97AD606F25FD387A4C3C1EF" }, | ||
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" }, | ||
{ name = "simplifile", version = "2.2.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0DFABEF7DC7A9E2FF4BB27B108034E60C81BEBFCB7AB816B9E7E18ED4503ACD8" }, | ||
] | ||
|
||
[requirements] | ||
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } | ||
gleeunit = { version = ">= 1.0.0 and < 2.0.0" } | ||
simplifile = { version = ">= 2.2.0 and < 3.0.0" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import gleam/io | ||
|
||
pub fn main() { | ||
io.println( | ||
"Use \"gleam run -m dayXX/solution\" to run the solution\nfrom a particular day.\n\nFor example:\n gleam run -m day01/solution", | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import gleam/result | ||
import gleam/string | ||
import simplifile | ||
|
||
/// Read Advent of Code input file and split into a list of lines. | ||
pub fn read_lines( | ||
from filepath: String, | ||
) -> Result(List(String), simplifile.FileError) { | ||
simplifile.read(from: filepath) | ||
// Be sure to get rid of final newline | ||
|> result.map(string.trim) | ||
|> result.map(string.split(_, "\n")) | ||
} | ||
|
||
pub fn solution_or_error(v: Result(String, String)) -> String { | ||
case v { | ||
Ok(solution) -> solution | ||
Error(error) -> "ERROR: " <> error | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import internal/lheap | ||
import gleam/dict | ||
import gleam/option.{type Option, None, Some} | ||
import gleam/result | ||
|
||
// Since reprioritizing nodes is difficult and expensive in a leftist heap | ||
// I track the minimum distance for each element and the previous node. | ||
// If push a value that has a distance greater than or equal to the | ||
// minimum seen, I just drop that element. If I pop one that is not the | ||
// smallest distance seen I discard it and pop another. | ||
|
||
pub opaque type Queue(element) { | ||
Queue( | ||
heap: lheap.Tree(element), | ||
minmap: dict.Dict(element, #(Int, Option(element))), | ||
) | ||
} | ||
|
||
pub fn new() -> Queue(element) { | ||
Queue(heap: lheap.new(), minmap: dict.new()) | ||
} | ||
|
||
pub fn push( | ||
queue: Queue(element), | ||
distance: Int, | ||
node: element, | ||
previous_node: Option(element), | ||
) -> Queue(element) { | ||
case dict.get(queue.minmap, node) { | ||
Ok(#(n, _)) if n <= distance -> queue | ||
_ -> { | ||
let newminmap = | ||
dict.insert(queue.minmap, node, #(distance, previous_node)) | ||
let newheap = lheap.push(queue.heap, distance, node) | ||
Queue(heap: newheap, minmap: newminmap) | ||
} | ||
} | ||
} | ||
|
||
pub fn push_list( | ||
queue: Queue(element), | ||
values: List(#(Int, element)), | ||
previous_node: Option(element), | ||
) -> Queue(element) { | ||
case values { | ||
[] -> queue | ||
[first, ..rest] -> { | ||
let newqueue = push(queue, first.0, first.1, previous_node) | ||
push_list(newqueue, rest, previous_node) | ||
} | ||
} | ||
} | ||
|
||
pub fn pop( | ||
queue: Queue(element), | ||
) -> Result(#(Queue(element), Int, element), Nil) { | ||
use #(newheap, distance, node) <- result.try(lheap.pop(queue.heap)) | ||
|
||
let newqueue = Queue(heap: newheap, minmap: queue.minmap) | ||
|
||
// check if this is the lowest distance variant of this node | ||
// if it is not go on to the next one. This eliminates leftover | ||
// elements which were added before better ones were found. | ||
let best_result = dict.get(queue.minmap, node) | ||
case best_result { | ||
Ok(#(best, _)) if best < distance -> pop(newqueue) | ||
_ -> Ok(#(newqueue, distance, node)) | ||
} | ||
} | ||
|
||
pub fn get_path( | ||
queue: Queue(element), | ||
ending: element, | ||
) -> Result(List(element), Nil) { | ||
get_path_acc(queue, ending, [ending]) | ||
} | ||
|
||
fn get_path_acc( | ||
queue: Queue(element), | ||
ending: element, | ||
acc: List(element), | ||
) -> Result(List(element), Nil) { | ||
case dict.get(queue.minmap, ending) { | ||
Error(Nil) -> Error(Nil) | ||
Ok(#(_, None)) -> Ok(acc) | ||
Ok(#(_, Some(node))) -> get_path_acc(queue, node, [node, ..acc]) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import gleam/list | ||
|
||
pub opaque type Tree(element) { | ||
Null | ||
Node( | ||
key: Int, | ||
payload: element, | ||
s: Int, | ||
left: Tree(element), | ||
right: Tree(element), | ||
) | ||
} | ||
|
||
fn merge(a: Tree(element), b: Tree(element)) -> Tree(element) { | ||
case a, b { | ||
Null, Null -> Null | ||
Null, _ -> b | ||
_, Null -> a | ||
Node(a_key, a_payload, _, a_left, a_right), Node(b_key, _, _, _, _) -> { | ||
case a_key > b_key { | ||
True -> merge(b, a) | ||
False -> { | ||
let newright = merge(a_right, b) | ||
case a_left, newright { | ||
Null, Node(_, _, _, _, _) -> | ||
Node( | ||
key: a_key, | ||
payload: a_payload, | ||
s: 1, | ||
left: newright, | ||
right: a_left, | ||
) | ||
Node(_, _, l_s, _, _), Node(_, _, r_s, _, _) if l_s < r_s -> | ||
Node( | ||
key: a_key, | ||
payload: a_payload, | ||
s: l_s + 1, | ||
left: newright, | ||
right: a_left, | ||
) | ||
_, Node(_, _, r_s, _, _) -> | ||
Node( | ||
key: a_key, | ||
payload: a_payload, | ||
s: r_s + 1, | ||
left: a_left, | ||
right: newright, | ||
) | ||
_, _ -> Null | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub fn new() -> Tree(element) { | ||
Null | ||
} | ||
|
||
pub fn push(a: Tree(element), value: Int, payload: element) -> Tree(element) { | ||
let b = Node(value, payload, 1, Null, Null) | ||
merge(a, b) | ||
} | ||
|
||
pub fn push_list( | ||
a: Tree(element), | ||
values: List(#(Int, element)), | ||
) -> Tree(element) { | ||
case values { | ||
[] -> a | ||
[first, ..rest] -> { | ||
let n = push(a, first.0, first.1) | ||
push_list(n, rest) | ||
} | ||
} | ||
} | ||
|
||
pub fn pop(a: Tree(element)) -> Result(#(Tree(element), Int, element), Nil) { | ||
case a { | ||
Null -> Error(Nil) | ||
Node(val, payload, _, left, right) -> | ||
Ok(#(merge(left, right), val, payload)) | ||
} | ||
} | ||
|
||
pub fn getall(a: Tree(element)) -> List(#(Int, element)) { | ||
popall(a, []) | ||
} | ||
|
||
fn popall(a: Tree(element), acc: List(#(Int, element))) -> List(#(Int, element)) { | ||
let r = pop(a) | ||
case r { | ||
Error(_) -> list.reverse(acc) | ||
Ok(#(t, v, p)) -> { | ||
popall(t, [#(v, p), ..acc]) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import dayXX/solution | ||
import gleam/string | ||
import gleeunit/should | ||
|
||
const testinput = "" | ||
|
||
pub fn part1_test() { | ||
let lines = string.split(testinput, "\n") | ||
solution.solve_p1(lines) | ||
|> should.equal(Ok("")) | ||
} | ||
|
||
pub fn part2_test() { | ||
let lines = string.split(testinput, "\n") | ||
solution.solve_p2(lines) | ||
|> should.equal(Ok("")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import gleam/io | ||
import internal/aoc_utils | ||
|
||
pub fn main() { | ||
let filename = "inputs/dayXX.txt" | ||
|
||
let lines_result = aoc_utils.read_lines(from: filename) | ||
case lines_result { | ||
Ok(lines) -> { | ||
// If the file was converting into a list of lines | ||
// successfully then run each part of the problem | ||
io.println("Part 1: " <> aoc_utils.solution_or_error(solve_p1(lines))) | ||
io.println("Part 2: " <> aoc_utils.solution_or_error(solve_p2(lines))) | ||
} | ||
Error(_) -> io.println("Error reading file") | ||
} | ||
} | ||
|
||
// Part 1 | ||
pub fn solve_p1(lines: List(String)) -> Result(String, String) { | ||
Error("Unimplemented") | ||
} | ||
|
||
// Part 2 | ||
pub fn solve_p2(lines: List(String)) -> Result(String, String) { | ||
Error("Unimplemented") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import gleeunit | ||
import gleeunit/should | ||
import internal/aoc_utils | ||
|
||
pub fn main() { | ||
gleeunit.main() | ||
} | ||
|
||
pub fn solution_or_error_test() { | ||
aoc_utils.solution_or_error(Ok("This is good")) | ||
|> should.equal("This is good") | ||
|
||
aoc_utils.solution_or_error(Error("This is bad")) | ||
|> should.equal("ERROR: This is bad") | ||
} |