my solutions to advent of code
aoc advent-of-code

Compare changes

Choose any two refs to compare.

Changed files
+832 -31
2015
16
19
rust
src
20
2025
template
rust
src
+9
.gitignore
···
target
zig-out
.zig-cache
+
out
+
*.ppm
+
*.pgm
+
*.pbm
+
*.bmp
+
*.png
+
*.gif
+
*.qoi
+
*.txt
-10
2015/16/sue.txt
···
-
children: 3
-
cats: 7
-
samoyeds: 2
-
pomeranians: 3
-
akitas: 0
-
vizslas: 0
-
goldfish: 5
-
trees: 3
-
cars: 2
-
perfumes: 1
+40 -18
2015/19/rust/src/main.rs
···
-
struct Combination {
-
original: String,
-
target: String,
-
}
+
use std::collections::{HashMap, HashSet};
fn main() {
-
let input: String = std::fs::read_to_string("../input.txt").expect("invalid input!!");
-
let input: Vec<&str> = input.split("\n").collect();
-
let combinations: Vec<Combination> = &input[..input.len() - 2].iter().map(|v| {
-
let v: Vec<&str> = v.split(" ").collect();
-
match v[..] {
-
[original, _, target] => Combination {
-
original: original.to_string(),
-
target: target.to_string(),
-
},
-
_ => Combination {
-
original: "".to_string(),
-
target: "".to_string(),
-
},
+
let input = include_str!("../../input.txt");
+
let input: Vec<&str> = input.trim().split("\n").collect();
+
+
let combinations: HashMap<String, Vec<String>> = {
+
let mut combinations = HashMap::new();
+
input[..input.len() - 2].iter().for_each(|v| {
+
let v: Vec<&str> = v.split(" ").collect();
+
match v[..] {
+
[original, "=>", target] => {
+
let entry = combinations
+
.entry(original.to_string())
+
.or_insert(Vec::with_capacity(1));
+
entry.push(target.to_string());
+
}
+
_ => panic!("{:?}", v),
+
}
+
});
+
combinations
+
};
+
+
let medicine_mol = input.last().unwrap();
+
+
// part 1
+
{
+
let mol_len = medicine_mol.len();
+
let mut possibilities: HashSet<String> = HashSet::new();
+
for i in 0..mol_len {
+
let (a, b) = medicine_mol.split_at(i);
+
combinations.iter().for_each(|(from, to)| {
+
to.iter().for_each(|to| {
+
possibilities.insert(format!(
+
"{}{}",
+
a,
+
b.replacen(from, to, 1)
+
));
+
})
+
});
}
-
}).
+
println!("Part 1: {}", possibilities.len() - 1)
+
}
}
+7
2015/20/rust/Cargo.lock
···
+
# This file is automatically @generated by Cargo.
+
# It is not intended for manual editing.
+
version = 4
+
+
[[package]]
+
name = "rust"
+
version = "0.1.0"
+6
2015/20/rust/Cargo.toml
···
+
[package]
+
name = "rust"
+
version = "0.1.0"
+
edition = "2024"
+
+
[dependencies]
+33
2015/20/rust/src/main.rs
···
+
fn main() {
+
let input: u64 = include_str!("../../input.txt")
+
.trim()
+
.parse()
+
.expect("bad input");
+
let input = input / 10;
+
+
let mut highest_house = (0, 0);
+
let mut house: u64 = 1;
+
// while highest_house.1 < input {
+
while house < 10 {
+
let presents = if house % 2 == 0 {
+
(1..house + 1).fold(0, |acc, elf| {
+
if house % elf == 0 { acc + elf } else { acc }
+
})
+
} else {
+
(1..house.div_ceil(2) + 1).fold(0, |acc, elf| {
+
if house % (elf * 2) == 0 {
+
acc + elf
+
} else {
+
acc
+
}
+
})
+
};
+
if presents > highest_house.1 {
+
highest_house = (house, presents);
+
}
+
house += 1;
+
println!("{} {}", house, presents);
+
}
+
+
println!("Part 1: {:?}", highest_house);
+
}
+2 -2
2025/4/gleam/src/main.gleam
···
case roll, neighbours < 4 {
1, True -> #(total + 1, bit_array.append(new_map, <<".">>))
-
0, _ -> #(total, bit_array.append(new_map, <<".">>))
-
1, _ | _, _ -> #(total, bit_array.append(new_map, <<"@">>))
+
1, _ -> #(total, bit_array.append(new_map, <<"@">>))
+
_, _ -> #(total, bit_array.append(new_map, <<".">>))
}
})
+7
2025/4/rust/Cargo.lock
···
+
# This file is automatically @generated by Cargo.
+
# It is not intended for manual editing.
+
version = 4
+
+
[[package]]
+
name = "rust"
+
version = "0.1.0"
+6
2025/4/rust/Cargo.toml
···
+
[package]
+
name = "rust"
+
version = "0.1.0"
+
edition = "2024"
+
+
[dependencies]
+106
2025/4/rust/src/main.rs
···
+
use std::{
+
fs::{self, File},
+
io::Write,
+
mem::swap,
+
};
+
+
fn to_img(warehouse: &Vec<u8>, size: usize, name: usize) {
+
let mut bytes: Vec<u8> = [].to_vec();
+
bytes.extend(format!("P5\n{size} {size}\n1\n").as_bytes());
+
let mut i = size + 3;
+
for _ in 0..size {
+
for _ in 0..size {
+
bytes.push(*warehouse.get(i).unwrap());
+
i += 1;
+
}
+
i += 2;
+
}
+
let mut file = File::create(format!("out/{name}.pgm")).unwrap();
+
file.write_all(&bytes).unwrap();
+
}
+
+
fn solve(
+
mut warehouse: Vec<u8>,
+
size: usize,
+
part_2: bool,
+
visualise: bool,
+
) -> u32 {
+
if visualise {
+
fs::create_dir_all("out").unwrap();
+
}
+
+
let pos = |x, y| y * (size + 2) + x;
+
+
let sizep = size + 1;
+
+
let mut new_warehouse = vec![0_u8; (size + 2).pow(2)];
+
+
let mut rolls = 0;
+
+
let mut i = 0;
+
loop {
+
for yo in 1..sizep {
+
let ym = yo - 1;
+
let yp = yo + 1;
+
for xo in 1..sizep {
+
let xm = xo - 1;
+
let xp = xo + 1;
+
+
unsafe {
+
let was = *warehouse.get_unchecked(pos(xo, yo)) == 1;
+
let neighbours = warehouse.get_unchecked(pos(xm, ym))
+
+ warehouse.get_unchecked(pos(xo, ym))
+
+ warehouse.get_unchecked(pos(xp, ym))
+
+ warehouse.get_unchecked(pos(xm, yo))
+
+ warehouse.get_unchecked(pos(xp, yo))
+
+ warehouse.get_unchecked(pos(xm, yp))
+
+ warehouse.get_unchecked(pos(xo, yp))
+
+ warehouse.get_unchecked(pos(xp, yp));
+
*new_warehouse.get_unchecked_mut(pos(xo, yo)) =
+
match (was, neighbours < 4) {
+
(true, true) => {
+
rolls += 1;
+
0
+
}
+
(true, false) => 1,
+
(_, _) => 0,
+
};
+
}
+
}
+
}
+
+
if !part_2 || warehouse == new_warehouse {
+
break;
+
}
+
+
swap(&mut warehouse, &mut new_warehouse);
+
i += 1;
+
if visualise {
+
to_img(&warehouse, size, i);
+
}
+
}
+
rolls
+
}
+
+
fn main() {
+
let input = include_str!("../../input.txt").trim();
+
let size = input.split_once("\n").expect("invalid input").0.len();
+
// reads the input but adds a line of buffer on the sides
+
let buffer_line = ".".repeat(size);
+
let input: Vec<u8> = format!("{buffer_line}\n{input}\n{buffer_line}")
+
.split("\n")
+
.map(|line| -> Vec<u8> {
+
format!(".{}.", line)
+
.chars()
+
.map(|v| (v == '@') as u8)
+
.collect()
+
})
+
.flatten()
+
.collect();
+
+
let part_1 = solve(input.clone(), size, false, false);
+
println!("Part 1: {}", part_1);
+
+
let part_2 = solve(input.clone(), size, true, true);
+
println!("Part 2: {}", part_2);
+
}
+20
2025/5/gleam/gleam.toml
···
+
name = "main"
+
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.44.0 and < 2.0.0"
+
simplifile = ">= 2.3.0 and < 3.0.0"
+
+
[dev-dependencies]
+
gleeunit = ">= 1.0.0 and < 2.0.0"
+14
2025/5/gleam/manifest.toml
···
+
# This file was generated by Gleam
+
# You typically do not need to edit this file
+
+
packages = [
+
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+
{ name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
+
{ name = "gleeunit", version = "1.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "CD701726CBCE5588B375D157B4391CFD0F2F134CD12D9B6998A395484DE05C58" },
+
{ name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" },
+
]
+
+
[requirements]
+
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
+
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+
simplifile = { version = ">= 2.3.0 and < 3.0.0" }
+117
2025/5/gleam/src/main.gleam
···
+
import gleam/int
+
import gleam/io
+
import gleam/list
+
import gleam/order.{Eq, Gt, Lt}
+
import gleam/set
+
import gleam/string
+
import simplifile as file
+
+
pub fn main() {
+
let assert Ok(input) = file.read(from: "../input.txt")
+
as "Input file not found"
+
let assert [fresh_ranges, available] =
+
input |> string.trim |> string.split("\n\n")
+
let fresh_ranges =
+
fresh_ranges
+
|> string.trim
+
|> string.split("\n")
+
// |> list.reverse
+
// |> list.drop(5)
+
// |> list.take(12)
+
// |> list.reverse
+
|> list.map(fn(i) {
+
let assert [from, to] = i |> string.trim |> string.split("-")
+
let assert Ok(from) = int.parse(from)
+
let assert Ok(to) = int.parse(to)
+
// #(from / 100_000_000, to / 100_000_000)
+
#(from, to)
+
})
+
let available =
+
available
+
|> string.split("\n")
+
|> list.map(fn(i) {
+
let assert Ok(id) = int.parse(i)
+
id
+
})
+
+
available
+
|> list.fold(0, fn(acc, i) {
+
acc
+
+ case list.any(fresh_ranges, fn(range) { i >= range.0 && i <= range.1 }) {
+
True -> 1
+
False -> 0
+
}
+
})
+
|> int.to_string
+
|> io.println
+
+
// nicer looking but idc
+
// |> list.filter(fn(i) {
+
// list.any(fresh_ranges, fn(range) { i >= range.0 && i <= range.1 })
+
// })
+
// |> list.length
+
+
// this thing crashed my computer btw im stupid
+
// let haha =
+
// fresh_ranges
+
// |> list.fold(set.new(), fn(acc, i) {
+
// list.range(i.0, i.1) |> list.fold(acc, fn(acc, i) { set.insert(acc, i) })
+
// })
+
// io.println(set.size(haha) |> int.to_string)
+
+
let base_set: set.Set(#(Int, Int)) = set.new()
+
fresh_ranges
+
|> list.fold(base_set, fn(prev_seen_ranges, range) {
+
let #(range, seen_ranges) =
+
prev_seen_ranges
+
|> set.fold(#(range, prev_seen_ranges), fn(acc, seen_range) {
+
let #(range, seen_ranges) = acc
+
// echo #(
+
// range,
+
// seen_range,
+
// int.compare(range.0, seen_range.0),
+
// int.compare(range.1, seen_range.1),
+
// int.compare(range.0, seen_range.1),
+
// int.compare(range.1, seen_range.0),
+
// )
+
// btw im refusing to ever do something better than this idc about your sorting and whatever this is the way shut the fuck up i spent three hours on this i will be using it
+
case
+
int.compare(range.0, seen_range.0),
+
int.compare(range.1, seen_range.1),
+
int.compare(range.0, seen_range.1),
+
int.compare(range.1, seen_range.0)
+
{
+
// if there's no touching
+
Gt, Gt, Gt, Gt | Lt, Lt, Lt, Lt -> #(range, seen_ranges)
+
// if it's inside of the other one
+
Gt, Lt, _, _ | Eq, Lt, _, _ | Gt, Eq, _, _ | Eq, Eq, _, _ -> #(
+
#(-1, -1),
+
seen_ranges,
+
)
+
// if the other one is inside it
+
Lt, Gt, _, _ | Eq, Gt, _, _ | Lt, Eq, _, _ -> #(
+
range,
+
set.delete(seen_ranges, seen_range),
+
)
+
// if it's touching on the left side make them touch
+
Lt, Lt, _, _ -> #(
+
#(range.0, seen_range.1),
+
set.delete(seen_ranges, seen_range),
+
)
+
// if it's touching on the right size make them touch
+
Gt, Gt, _, _ -> #(
+
#(seen_range.0, range.1),
+
set.delete(seen_ranges, seen_range),
+
)
+
}
+
})
+
+
case range == #(-1, -1) {
+
False -> seen_ranges |> set.insert(range)
+
True -> seen_ranges
+
}
+
})
+
|> set.fold(0, fn(acc, range) { acc + range.1 - range.0 + 1 })
+
|> int.to_string
+
|> io.println
+
}
+7
2025/5/rust/Cargo.lock
···
+
# This file is automatically @generated by Cargo.
+
# It is not intended for manual editing.
+
version = 4
+
+
[[package]]
+
name = "rust"
+
version = "0.1.0"
+6
2025/5/rust/Cargo.toml
···
+
[package]
+
name = "rust"
+
version = "0.1.0"
+
edition = "2024"
+
+
[dependencies]
+75
2025/5/rust/src/main.rs
···
+
use std::{
+
cmp::Ordering::{Equal as Eq, Greater as Gt, Less as Lt},
+
collections::HashSet,
+
};
+
+
fn main() {
+
let input = include_str!("../../input.txt").trim();
+
let (fresh_ranges, available) = input.split_once("\n\n").unwrap();
+
let fresh_ranges: Vec<(u64, u64)> = fresh_ranges
+
.split("\n")
+
.map(|i| {
+
let (a, b) = i.split_once("-").unwrap();
+
(a.parse().unwrap(), b.parse().unwrap())
+
})
+
.collect();
+
let available = available.split("\n").map(|i| {
+
let i: u64 = i.parse().unwrap();
+
i
+
});
+
+
let part_1 = available.fold(0, |acc, i| {
+
acc + fresh_ranges
+
.iter()
+
.any(|(start, end)| &i >= start && &i <= end) as u64
+
});
+
println!("Part 1: {}", part_1);
+
+
let mut seen_ranges: HashSet<(u64, u64)> =
+
HashSet::with_capacity(fresh_ranges.len());
+
fresh_ranges.iter().for_each(|range| {
+
let range = seen_ranges.clone().iter().try_fold(
+
*range,
+
|range: (u64, u64), seen_range: &(u64, u64)| {
+
// btw im refusing to ever do something better than this idc about your sorting and whatever this is the way shut the fuck up i spent three hours on this i will be using it
+
match (
+
range.0.cmp(&seen_range.0),
+
range.1.cmp(&seen_range.1),
+
range.0.cmp(&seen_range.1),
+
range.1.cmp(&seen_range.0),
+
) {
+
// if there's no touching
+
(Gt, Gt, Gt, Gt) | (Lt, Lt, Lt, Lt) => Some(range),
+
// if it's inside of the other one
+
(Gt, Lt, _, _)
+
| (Eq, Lt, _, _)
+
| (Gt, Eq, _, _)
+
| (Eq, Eq, _, _) => None,
+
// if the other one is inside it
+
(Lt, Gt, _, _) | (Eq, Gt, _, _) | (Lt, Eq, _, _) => {
+
seen_ranges.remove(seen_range);
+
Some(range)
+
}
+
// if it's touching on the left side make them touch
+
(Lt, Lt, _, _) => {
+
seen_ranges.remove(seen_range);
+
Some((range.0, seen_range.1))
+
}
+
// if it's touching on the right size make them touch
+
(Gt, Gt, _, _) => {
+
seen_ranges.remove(seen_range);
+
Some((seen_range.0, range.1))
+
}
+
}
+
},
+
);
+
+
if range.is_some() {
+
seen_ranges.insert(range.unwrap());
+
}
+
});
+
let part_2 = seen_ranges
+
.into_iter()
+
.fold(0, |acc, range| acc + range.1 - range.0 + 1);
+
println!("Part 2: {}", part_2);
+
}
+20
2025/6/gleam/gleam.toml
···
+
name = "main"
+
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.44.0 and < 2.0.0"
+
simplifile = ">= 2.3.0 and < 3.0.0"
+
+
[dev-dependencies]
+
gleeunit = ">= 1.0.0 and < 2.0.0"
+14
2025/6/gleam/manifest.toml
···
+
# This file was generated by Gleam
+
# You typically do not need to edit this file
+
+
packages = [
+
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+
{ name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
+
{ name = "gleeunit", version = "1.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "CD701726CBCE5588B375D157B4391CFD0F2F134CD12D9B6998A395484DE05C58" },
+
{ name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" },
+
]
+
+
[requirements]
+
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
+
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+
simplifile = { version = ">= 2.3.0 and < 3.0.0" }
+140
2025/6/gleam/src/main.gleam
···
+
import gleam/dict
+
import gleam/int
+
import gleam/io
+
import gleam/list
+
import gleam/result
+
import gleam/string
+
import simplifile as file
+
+
type Part2Dict =
+
dict.Dict(Int, Int)
+
+
type Align {
+
Left
+
Right
+
}
+
+
type Operation {
+
Sum
+
Mul
+
}
+
+
type Part2Line {
+
Part2Line(align: Align, op: Operation, numbers: List(String))
+
}
+
+
pub fn main() {
+
let assert Ok(input) = file.read(from: "../input.txt")
+
as "Input file not found"
+
let input = input |> string.trim
+
let input_pt_1 =
+
list.fold(list.range(1, 10), input, fn(acc, _) {
+
acc |> string.replace(" ", " ")
+
})
+
+
input_pt_1
+
|> string.split("\n")
+
|> list.map(fn(i) { string.trim(i) |> string.split(" ") })
+
|> list.transpose
+
|> list.map(fn(i) {
+
let i = list.reverse(i)
+
let assert Ok(s) = list.first(i)
+
let i =
+
list.drop(i, 1) |> list.map(fn(i) { int.parse(i) |> result.unwrap(0) })
+
let r = case s {
+
"+" -> int.sum(i)
+
"*" -> list.reduce(i, int.multiply) |> result.unwrap(0)
+
_ -> panic as "invalid"
+
}
+
r
+
})
+
|> int.sum
+
|> int.to_string
+
|> io.println
+
+
let lines =
+
input
+
|> string.split("\n")
+
|> list.reverse
+
let assert Ok(last_line) = list.first(lines)
+
let #(_, bounds) =
+
{ last_line <> " *" }
+
|> string.to_graphemes
+
|> list.index_fold(#(0, list.new()), fn(acc, char, i) {
+
let #(bound_start, bounds) = acc
+
case char {
+
"*" | "+" if i > 0 -> #(i, list.append([#(bound_start, i - 1)], bounds))
+
_ -> acc
+
}
+
})
+
bounds
+
|> list.index_fold(dict.new(), fn(d, bound, i) {
+
let numbers =
+
list.map(lines, fn(line) {
+
string.slice(line, bound.0, bound.1 - bound.0)
+
})
+
let align =
+
numbers
+
|> list.drop(1)
+
|> list.fold_until(Left, fn(res, number) {
+
case
+
string.trim(number) == number,
+
string.trim_start(number) == number
+
{
+
True, _ -> list.Continue(res)
+
_, True -> list.Stop(Left)
+
_, _ -> list.Stop(Right)
+
}
+
})
+
let assert Ok(sign) = list.first(numbers)
+
let sign = case string.trim(sign) {
+
"*" -> Mul
+
"+" -> Sum
+
_ -> panic as sign
+
}
+
dict.insert(
+
d,
+
i,
+
Part2Line(
+
align,
+
sign,
+
numbers |> list.drop(1) |> list.map(string.trim) |> list.reverse,
+
),
+
)
+
})
+
|> dict.to_list
+
|> list.map(fn(i) { i.1 })
+
|> list.map(fn(line) {
+
let d: Part2Dict = dict.new()
+
let d =
+
line.numbers
+
|> list.fold(d, fn(d, number) {
+
let number_len = string.length(number)
+
string.to_graphemes(number)
+
|> list.index_fold(d, fn(d, digit, index) {
+
let assert Ok(digit) = digit |> int.parse
+
let pos = case line.align {
+
Right -> number_len - index
+
Left -> index
+
}
+
dict.insert(
+
d,
+
pos,
+
{ dict.get(d, pos) |> result.unwrap(0) } * 10 + digit,
+
)
+
})
+
})
+
let numbers =
+
dict.to_list(d)
+
|> list.map(fn(n) { n.1 })
+
+
let r = case line.op {
+
Sum -> int.sum(numbers)
+
Mul -> list.reduce(numbers, int.multiply) |> result.unwrap(0)
+
}
+
r
+
})
+
|> int.sum
+
|> int.to_string
+
|> io.println
+
}
+20
2025/7/gleam/gleam.toml
···
+
name = "main"
+
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.44.0 and < 2.0.0"
+
simplifile = ">= 2.3.0 and < 3.0.0"
+
+
[dev-dependencies]
+
gleeunit = ">= 1.0.0 and < 2.0.0"
+14
2025/7/gleam/manifest.toml
···
+
# This file was generated by Gleam
+
# You typically do not need to edit this file
+
+
packages = [
+
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+
{ name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
+
{ name = "gleeunit", version = "1.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "CD701726CBCE5588B375D157B4391CFD0F2F134CD12D9B6998A395484DE05C58" },
+
{ name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" },
+
]
+
+
[requirements]
+
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
+
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+
simplifile = { version = ">= 2.3.0 and < 3.0.0" }
+93
2025/7/gleam/src/main.gleam
···
+
import gleam/dict
+
import gleam/int
+
import gleam/io
+
import gleam/list
+
import gleam/set
+
import gleam/string
+
import simplifile as file
+
+
pub fn main() {
+
let assert Ok(input) = file.read(from: "../input.txt")
+
as "Input file not found"
+
let input = input |> string.trim |> string.split("\n")
+
let assert Ok(start) = input |> list.first
+
let start =
+
start
+
|> string.to_graphemes
+
|> list.index_fold(0, fn(acc, v, i) {
+
case v {
+
"S" -> i
+
_ -> acc
+
}
+
})
+
let splitters_map =
+
input
+
|> list.drop(1)
+
|> list.index_map(fn(line, i) {
+
case i % 2 {
+
0 -> ""
+
_ -> line
+
}
+
})
+
|> list.filter(fn(line) { line != "" })
+
|> list.map(fn(line) {
+
line
+
|> string.to_graphemes
+
|> list.index_fold(set.new(), fn(d, char, i) {
+
case char {
+
"^" -> set.insert(d, i)
+
_ -> d
+
}
+
})
+
})
+
let #(_beams, times) =
+
splitters_map
+
|> list.fold(#(set.new() |> set.insert(start), 0), fn(acc, splitters) {
+
let #(beams, times) = acc
+
beams
+
|> set.fold(#(beams, times), fn(acc, beam) {
+
let #(beams, times) = acc
+
case splitters |> set.contains(beam) {
+
False -> acc
+
True -> #(
+
beams
+
|> set.delete(beam)
+
|> set.insert(beam - 1)
+
|> set.insert(beam + 1),
+
times + 1,
+
)
+
}
+
})
+
})
+
+
times
+
|> int.to_string
+
|> io.println
+
+
let timelines =
+
splitters_map
+
|> list.index_fold(
+
dict.new() |> dict.insert("", start),
+
fn(timelines, splitters, i) {
+
echo i
+
// echo #(timelines, splitters)
+
timelines
+
|> dict.fold(timelines, fn(timelines, timeline, beam) {
+
case splitters |> set.contains(beam) {
+
False -> timelines
+
True -> {
+
timelines
+
|> dict.delete(timeline)
+
|> dict.insert(timeline <> "-", beam - 1)
+
|> dict.insert(timeline <> "+", beam + 1)
+
}
+
}
+
})
+
},
+
)
+
echo timelines
+
timelines
+
|> dict.size
+
|> int.to_string
+
|> io.println
+
}
+7
2025/7/rust/Cargo.lock
···
+
# This file is automatically @generated by Cargo.
+
# It is not intended for manual editing.
+
version = 4
+
+
[[package]]
+
name = "rust"
+
version = "0.1.0"
+6
2025/7/rust/Cargo.toml
···
+
[package]
+
name = "rust"
+
version = "0.1.0"
+
edition = "2024"
+
+
[dependencies]
+62
2025/7/rust/src/main.rs
···
+
use std::{
+
collections::{HashMap, HashSet},
+
mem::swap,
+
};
+
+
fn main() {
+
let input = include_str!("../../input.txt").trim();
+
+
let input: Vec<&str> = input.trim().split("\n").collect();
+
// let width = input[0].len() as u64;
+
let start = input[0].find("S").unwrap() as u64;
+
let splitters_map: Vec<HashSet<u64>> = input[0..input.len()]
+
.iter()
+
.enumerate()
+
.map(|(i, line)| if i % 2 != 0 { "" } else { line })
+
.filter(|line| line != &"")
+
.map(|line| {
+
line.chars()
+
.enumerate()
+
.fold(HashSet::new(), |mut s, (i, char)| {
+
if char == '^' {
+
s.insert(i as u64);
+
}
+
s
+
})
+
})
+
.collect();
+
+
let timelines = {
+
let mut timelines: HashMap<u64, u64> = HashMap::new();
+
timelines.insert(start, 1);
+
let mut timelines_new: HashMap<u64, u64> = HashMap::new();
+
for splitters in splitters_map {
+
for (pos, amount) in &timelines {
+
if splitters.contains(&pos) {
+
let m1 = timelines_new.entry(pos - 1).or_insert(0);
+
*m1 += amount;
+
let p1 = timelines_new.entry(pos + 1).or_insert(0);
+
*p1 += amount;
+
} else {
+
let e = timelines_new.entry(*pos).or_insert(0);
+
*e += amount;
+
}
+
}
+
// for pos in 0..width as u64 {
+
// if splitters.contains(&pos) {
+
// print!("^");
+
// } else if timelines_new.contains_key(&pos) {
+
// print!("|");
+
// } else {
+
// print!(".");
+
// }
+
// }
+
// print!("\n\n");
+
swap(&mut timelines, &mut timelines_new);
+
timelines_new.clear();
+
}
+
timelines
+
};
+
// println!("{:?}", timelines);
+
println!("{}", timelines.iter().fold(0, |acc, v| { acc + v.1 }))
+
}
+1 -1
template/rust/src/main.rs
···
fn main() {
-
let input = include_str!("../../input.txt");
+
let input = include_str!("../../input.txt").trim();
println!("{}", &input);
}