Skip to content

Commit

Permalink
vine: add aoc_2024 tests (#156)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjjfvi authored Jan 2, 2025
1 parent 04c96ce commit d6b4e11
Show file tree
Hide file tree
Showing 127 changed files with 15,874 additions and 3 deletions.
2 changes: 1 addition & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"**/*.vi",
"**/*.iv"
],
"ignorePaths": ["tests/snaps"],
"ignorePaths": ["tests/snaps", "tests/programs/aoc_2024"],
"ignoreRegExpList": [
"HexValues"
],
Expand Down
47 changes: 47 additions & 0 deletions tests/programs/aoc_2024/day_01.vi
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

use std::option::Option::Some;

pub fn main(&io: &IO) {
let input = io.full_input();

let lines = input.split_trim("\n").map(fn(line: String) {
let parts = line.split(" ");
let left = N32::parse(parts.pop_front().unwrap()).unwrap();
let right = N32::parse(parts.pop_front().unwrap()).unwrap();
(left, right)
});

let left = lines.map(fn((left, _)) left);
let right = lines.map(fn((_, right)) right);

left.sort_by(N32::ascending);
right.sort_by(N32::ascending);

let total_dist = 0;
let iter_a = left.into_iter();
let iter_b = right.into_iter();
while iter_a.next() is Some(a) && iter_b.next() is Some(b) {
total_dist += if a > b {
a - b
} else {
b - a
};
}

io.println("Total Distance: " ++ total_dist.to_string());

let similarity = 0;
let iter_a = left.into_iter();
while iter_a.next() is Some(a) {
let count = 0;
let iter_b = right.into_iter();
while iter_b.next() is Some(b) {
if a == b {
count += 1;
}
}
similarity += a * count;
}

io.println("Similarity Score: " ++ similarity.to_string());
}
61 changes: 61 additions & 0 deletions tests/programs/aoc_2024/day_02.vi
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

use std::{option::Option::{Option, Some, None}, result::Result::{Result, Ok, Err}};

pub fn main(&io: &IO) {
let input = io.full_input();

let lines = input.split_trim("\n");

let safe_count = 0;
let dampened_safe_count = 0;

let iter = lines.into_iter();
while iter.next() is Some(line) {
let report = line.split(" ").map(fn(x) N32::parse(x).unwrap());
if is_safe(report) {
safe_count += 1;
dampened_safe_count += 1;
} else if problem_dampener(report) {
dampened_safe_count += 1;
}
}

io.println("Safe Count: " ++ safe_count.to_string());
io.println("Dampened Safe Count: " ++ dampened_safe_count.to_string());
}

fn is_safe(report: List[N32]) -> Bool {
let last = None[N32];
let order = None[Bool];
let iter = report.into_iter();
while iter.next() is Some(level) {
if last is Some(last) {
let diff = if last > level {
last - level
} else {
level - last
};
if !(1 <= diff <= 3) {
return false;
}
if order is Some(order) && order != (last > level) {
return false;
}
order = Some((last > level));
}
last = Some(level);
}
true
}

fn problem_dampener(report: List[N32]) -> Bool {
let prefix = [];
let suffix = report;
while suffix.pop_front() is Some(level) {
if is_safe(prefix ++ suffix) {
return true;
}
prefix ++= [level];
}
false
}
36 changes: 36 additions & 0 deletions tests/programs/aoc_2024/day_03.vi
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

use std::{option::Option::{Option, Some, None}, result::Result::{Result, Ok, Err}};

pub fn main(&io: &IO) {
let input = io.full_input();

let part1 = get_muls(input);

io.println("Part 1: " ++ part1.to_string());

let part2 = get_muls(input.split("do()").map(fn(x: String) {
let (a, _) = x.split_once("don't()");
a
}).join(""));

io.println("Part 2: " ++ part2.to_string());
}

fn get_muls(input: String) -> N32 {
let segments = input.split("mul(");
segments.pop_front();

let sum = 0;
while segments.pop_front() is Some(segment) {
if segment.split_once(")") is (args, Some(_)) {
if args.split_once(",") is (first, Some(second)) {
if N32::parse(first) is Some(a) {
if N32::parse(second) is Some(b) {
sum += a * b;
}
}
}
}
}
sum
}
174 changes: 174 additions & 0 deletions tests/programs/aoc_2024/day_04.vi
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@

use std::{option::Option::{Option, Some, None}, result::Result::{Result, Ok, Err}};

pub fn main(&io: &IO) {
let lines = [];
while io.read_line() is Some(line) {
lines ++= [line];
}

let matches = diamond(
lines,
fn(char: Char, Neighbors(nw, n, ne, w, e, sw, s, se): Neighbors[Char], &matches: &N32) {
if char == 'X' {
nw.send('X');
n.send('X');
ne.send('X');
w.send('X');
e.send('X');
sw.send('X');
s.send('X');
se.send('X');
} else if char == 'M' || char == 'A' {
let recv = if char == 'M' {
'X'
} else {
'M'
};
relay(nw, se, recv, char);
relay(n, s, recv, char);
relay(ne, sw, recv, char);
relay(w, e, recv, char);
} else if char == 'S' {
matches += check(nw, 'A') + check(ne, 'A') + check(sw, 'A') + check(se, 'A');
let x = check(n, 'A') + check(s, 'A') + check(w, 'A') + check(e, 'A');
matches += x;
}
},
'.',
0,
);

io.println("XMAS: " ++ matches.to_string());

let matches = diamond(
lines,
fn(char: Char, Neighbors(nw, _, ne, _, _, sw, _, se): Neighbors[Char], &matches: &N32) {
if char == 'A' {
let nw = nw.send('A');
let ne = ne.send('A');
let sw = sw.send('A');
let se = se.send('A');
if ((nw == 'M' && se == 'S') || (nw == 'S' && se == 'M')) && (
(sw == 'M' && ne == 'S') || (sw == 'S' && ne == 'M')
) {
matches += 1;
}
} else {
nw.send(char);
ne.send(char);
sw.send(char);
se.send(char);
}
},
'.',
0,
);

io.println("X-MAS: " ++ matches.to_string());
}

struct Channel[M](M, ~M);

mod Channel {
pub fn send[M](Channel(got, ~out): Channel[M], value: M) -> M {
out = value;
got
}

pub fn get[M](&Channel(i, _): &Channel[M]) -> M {
i
}
}

fn relay(Channel(ai, ~ao): Channel[Char], Channel(bi, ~bo): Channel[Char], recv: Char, send: Char) {
bo = if ai == recv {
send
} else {
'_'
};
ao = if bi == recv {
send
} else {
'_'
};
}

fn check(Channel(i, ~o): Channel[Char], recv: Char) -> N32 {
o = '_';
if i == recv {
1
} else {
0
}
}

struct Neighbors[M](
Channel[M],
Channel[M],
Channel[M],
Channel[M],
Channel[M],
Channel[M],
Channel[M],
Channel[M],
);

fn diamond[T, M, X](grid: List[List[T]], f: fn(T, Neighbors[M], &X), d: M, state: X) -> X {
let width = (*grid.get(0)).len();
let north = List::new(width, neglect_channel(d));
let north_west = List::new(width, neglect_channel(d));
let north_east = List::new(width, neglect_channel(d));
while grid.pop_front() is Some(row) {
let west = neglect_channel(d);
{
let north = north.iter();
let north_west = north_west.iter();
let ~north_east = north_east.iter();
(~north_east).drop()
while row.pop_front() is Some(cell) {
let (w, e) = foo_channel(&west);
let (n, s) = foo_channel(north.next().unwrap());
let (nw, se) = foo_channel(north_west.next().unwrap());
let (ne, sw) = foo_channel((~north_east).next().unwrap());
f(cell, Neighbors(nw, n, ne, w, e, sw, s, se), &state);
}
north.drop()
north_west.drop()
}
west.send(d);
north_west.pop_front().unwrap().send(d);
north_west ++= [neglect_channel(d)];
north_east.pop_front().unwrap().send(d);
north_east ++= [neglect_channel(d)];
}
drop_all(north, d);
drop_all(north_west, d);
drop_all(north_east, d);
state
}

fn drop_all[M](c: List[Channel[M]], d: M) {
while c.pop_front() is Some(c) {
c.send(d);
}
}

fn foo_channel[M](&c: &Channel[M]) -> (Channel[M], Channel[M]) {
let x = c;
let (a, b) = new_channel();
c = a;
(x, b)
}

fn new_channel[M]() -> (Channel[M], Channel[M]) {
let a;
let b;
let x = ~a;
let y = ~b;
(Channel(a, y), Channel(b, x))
}

fn neglect_channel[M](d: M) -> Channel[M] {
Channel(d, ~_)
}
Loading

0 comments on commit d6b4e11

Please sign in to comment.