Solve 07
This commit is contained in:
parent
53e172f9c6
commit
2759b7e1f6
1 changed files with 95 additions and 0 deletions
95
src/bin/07.rs
Normal file
95
src/bin/07.rs
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
use aoc::*;
|
||||||
|
use cached::{proc_macro::cached, stores::UnboundCache};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
const INPUT: &str = include_str!("../../input/07");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Part 1: {}", part1(INPUT));
|
||||||
|
println!("Part 2: {}", part2(INPUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example() {
|
||||||
|
assert_example!(part1, "07-test", 21);
|
||||||
|
assert_example!(part2, "07-test", 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> usize {
|
||||||
|
let (start, splitters) = parse_input(input);
|
||||||
|
|
||||||
|
let mut sum = 0;
|
||||||
|
let mut beams = HashSet::from([start]);
|
||||||
|
|
||||||
|
for splitters in splitters {
|
||||||
|
let (count, new) = split_count(&splitters, beams);
|
||||||
|
beams = new;
|
||||||
|
sum += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> usize {
|
||||||
|
let (start, splitters) = parse_input(input);
|
||||||
|
timelines(start, 0, &splitters)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn split_count(splitters: &HashSet<i32>, beams: HashSet<i32>) -> (usize, HashSet<i32>) {
|
||||||
|
let mut result = HashSet::new();
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
for beam in beams {
|
||||||
|
if splitters.contains(&beam) {
|
||||||
|
result.insert(beam + 1);
|
||||||
|
result.insert(beam - 1);
|
||||||
|
count += 1;
|
||||||
|
} else {
|
||||||
|
result.insert(beam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(count, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cached(
|
||||||
|
type = "UnboundCache<(i32, usize), usize>",
|
||||||
|
create = "{ UnboundCache::new() }",
|
||||||
|
convert = r#"{ (beam, depth) }"#
|
||||||
|
)]
|
||||||
|
fn timelines(beam: i32, depth: usize, splitters: &[HashSet<i32>]) -> usize {
|
||||||
|
if depth >= splitters.len() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let splitter = &splitters[depth];
|
||||||
|
|
||||||
|
if splitter.contains(&beam) {
|
||||||
|
timelines(beam - 1, depth + 1, splitters) + timelines(beam + 1, depth + 1, splitters)
|
||||||
|
} else {
|
||||||
|
timelines(beam, depth + 1, splitters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns (start, lines of splitter positions)
|
||||||
|
fn parse_input(input: &str) -> (i32, Vec<HashSet<i32>>) {
|
||||||
|
let mut lines = input.lines();
|
||||||
|
|
||||||
|
let first_line = lines.next().unwrap();
|
||||||
|
let start = first_line.chars().position(|c| c == 'S').unwrap() as i32;
|
||||||
|
|
||||||
|
let splitters = lines
|
||||||
|
.map(parse_line)
|
||||||
|
.filter(|line| !line.is_empty())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(start, splitters)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_line(line: &str) -> HashSet<i32> {
|
||||||
|
line.chars()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(_, c)| c == '^')
|
||||||
|
.map(|(i, _)| i as i32)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue