Compare commits
2 Commits
72d7dc1cbb
...
0a5e5c8798
| Author | SHA1 | Date | |
|---|---|---|---|
|
0a5e5c8798
|
|||
|
73b44b1377
|
BIN
.aoc_tiles/tiles/2025/10.png
Normal file
BIN
.aoc_tiles/tiles/2025/10.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
@@ -1,6 +1,6 @@
|
||||
<!-- AOC TILES BEGIN -->
|
||||
<h1 align="center">
|
||||
2025 - 17 ⭐ - Rust
|
||||
2025 - 18 ⭐ - Rust
|
||||
</h1>
|
||||
<a href="src/day1.rs">
|
||||
<img src=".aoc_tiles/tiles/2025/01.png" width="161px">
|
||||
@@ -29,4 +29,7 @@
|
||||
<a href="src/day9.rs">
|
||||
<img src=".aoc_tiles/tiles/2025/09.png" width="161px">
|
||||
</a>
|
||||
<a href="src/day10.rs">
|
||||
<img src=".aoc_tiles/tiles/2025/10.png" width="161px">
|
||||
</a>
|
||||
<!-- AOC TILES END -->
|
||||
|
||||
197
src/day10.rs
Normal file
197
src/day10.rs
Normal file
@@ -0,0 +1,197 @@
|
||||
use std::{collections::BinaryHeap, hash::Hash, iter::repeat_n};
|
||||
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct MachineDefinition {
|
||||
desired: Vec<bool>,
|
||||
buttons: Vec<Vec<usize>>,
|
||||
joltages: Vec<u64>,
|
||||
}
|
||||
|
||||
impl MachineDefinition {
|
||||
fn create<'a>(&'a self) -> Machine<'a> {
|
||||
Machine {
|
||||
d: self,
|
||||
lights: Vec::from_iter(repeat_n(false, self.desired.len())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for MachineDefinition {
|
||||
fn from(value: &str) -> Self {
|
||||
let parse_re = Regex::new(
|
||||
r##"\[(?<desired>[.#]+)\] (?<buttons>(\([0-9,]+\) ?)+) \{(?<joltages>[0-9,]+)\}"##,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let parts = parse_re.captures(value).unwrap();
|
||||
|
||||
MachineDefinition {
|
||||
desired: parts["desired"].chars().map(|c| c == '#').collect(),
|
||||
buttons: parts["buttons"]
|
||||
.split_ascii_whitespace()
|
||||
.map(|s| {
|
||||
s[1..s.len() - 1]
|
||||
.split(',')
|
||||
.map(|n| n.parse().unwrap())
|
||||
.collect()
|
||||
})
|
||||
.collect(),
|
||||
joltages: parts["joltages"]
|
||||
.split(',')
|
||||
.map(|n| n.parse().unwrap())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Machine<'a> {
|
||||
d: &'a MachineDefinition,
|
||||
lights: Vec<bool>,
|
||||
}
|
||||
|
||||
impl<'a> Eq for Machine<'a> {}
|
||||
impl<'a> PartialEq for Machine<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.lights == other.lights
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Hash for Machine<'a> {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.lights.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Machine<'a> {
|
||||
/// Get the state after pressing `button`, returns None if the state is as desired
|
||||
fn press(&self, button: usize) -> Option<Self> {
|
||||
let mut new_state = self.lights.clone();
|
||||
for light in &self.d.buttons[button] {
|
||||
new_state[*light] = !new_state[*light]
|
||||
}
|
||||
if new_state == self.d.desired {
|
||||
None
|
||||
} else {
|
||||
Some(Machine {
|
||||
d: self.d,
|
||||
lights: new_state,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the possible states from the current position
|
||||
fn next_states(&self) -> Vec<(usize, Option<Machine<'a>>)> {
|
||||
self.d
|
||||
.buttons
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _but)| (i, self.press(i)))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct PressSet<'a> {
|
||||
machine: Machine<'a>,
|
||||
presses: usize,
|
||||
}
|
||||
|
||||
// NOTE: All compares are reversed so our max heap becomes a min heap
|
||||
impl<'a> Eq for PressSet<'a> {}
|
||||
|
||||
impl<'a> PartialEq for PressSet<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
other.presses.eq(&self.presses)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialOrd for PressSet<'a> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Ord for PressSet<'a> {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
other.presses.cmp(&self.presses)
|
||||
}
|
||||
}
|
||||
|
||||
fn find_best(md: &MachineDefinition) -> usize {
|
||||
let m = md.create();
|
||||
let mut to_check = BinaryHeap::new();
|
||||
|
||||
for next in m.next_states() {
|
||||
if let Some(new_m) = next.1 {
|
||||
to_check.push(PressSet {
|
||||
presses: 1,
|
||||
machine: new_m.clone(),
|
||||
})
|
||||
} else {
|
||||
// what we found a solution on the first move?
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
while let Some(candidate) = to_check.pop() {
|
||||
let cm = candidate.machine.clone();
|
||||
for next in cm.next_states() {
|
||||
let presses = candidate.presses + 1;
|
||||
if let Some(new_m) = next.1 {
|
||||
to_check.push(PressSet {
|
||||
presses,
|
||||
machine: new_m.clone(),
|
||||
})
|
||||
} else {
|
||||
return presses;
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!()
|
||||
}
|
||||
|
||||
#[aoc_generator(day10)]
|
||||
fn parse(input: &str) -> Vec<MachineDefinition> {
|
||||
input.lines().map(|l| l.into()).collect()
|
||||
}
|
||||
|
||||
#[aoc(day10, part1)]
|
||||
fn part1(input: &[MachineDefinition]) -> u64 {
|
||||
input
|
||||
.iter()
|
||||
.map(find_best)
|
||||
// .inspect(|sol| println!(" [{sol:?}]"))
|
||||
.map(|sol| sol as u64)
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[aoc(day10, part2)]
|
||||
fn part2(input: &[MachineDefinition]) -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rstest::rstest;
|
||||
|
||||
use super::*;
|
||||
|
||||
const EXAMPLE: &str = "[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
|
||||
[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
|
||||
[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}";
|
||||
|
||||
#[rstest]
|
||||
#[case(EXAMPLE, 7)]
|
||||
fn part1_example(#[case] input: &str, #[case] expected: u64) {
|
||||
assert_eq!(part1(&parse(input)), expected);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case(EXAMPLE, 33)]
|
||||
fn part2_example(#[case] input: &str, #[case] expected: u64) {
|
||||
assert_eq!(part2(&parse(input)), expected);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
mod day1;
|
||||
mod day10;
|
||||
mod day2;
|
||||
mod day3;
|
||||
mod day4;
|
||||
|
||||
Reference in New Issue
Block a user