chore: enhanced a little bit day 11 p1 but a bit stuck on p2 with the ugly bruteforce solution, obviously

This commit is contained in:
Xavier Morel
2024-11-28 17:46:00 +01:00
parent fd20763c53
commit b42ee52573
2 changed files with 107 additions and 78 deletions

View File

@@ -36,8 +36,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 8](./src/bin/08.rs) | `132.9ms` | `-` | | [Day 8](./src/bin/08.rs) | `132.9ms` | `-` |
| [Day 9](./src/bin/09.rs) | `77.2µs` | `969.4µs` | | [Day 9](./src/bin/09.rs) | `77.2µs` | `969.4µs` |
| [Day 10](./src/bin/10.rs) | `164.5µs` | `287.9µs` | | [Day 10](./src/bin/10.rs) | `164.5µs` | `287.9µs` |
| [Day 11](./src/bin/11.rs) | `30.5s` | `-` |
**Total: 17333.76ms** **Total: 47833.76ms**
<!--- benchmarking table ---> <!--- benchmarking table --->
--- ---

View File

@@ -2,6 +2,7 @@ advent_of_code::solution!(11);
use periodic_table_on_an_enum::Element; use periodic_table_on_an_enum::Element;
use itertools::Itertools; use itertools::Itertools;
use std::time::SystemTime;
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)] #[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)]
enum Item { enum Item {
@@ -13,7 +14,7 @@ impl Item {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
Item::Generator(e) => format!("[{:<2}G]", e.get_symbol()), Item::Generator(e) => format!("[{:<2}G]", e.get_symbol()),
Item::Chip(e) => format!("[{:<2}C]", e.get_symbol()), Item::Chip(e) => format!("[{:<2}M]", e.get_symbol()),
} }
} }
} }
@@ -35,7 +36,6 @@ impl std::fmt::Debug for Floor {
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
struct State { struct State {
previous: Option<Box<State>>,
floors: [Floor; 4], floors: [Floor; 4],
current_floor: usize, current_floor: usize,
} }
@@ -64,7 +64,6 @@ impl State {
panic!("Wrong number of floors !!"); panic!("Wrong number of floors !!");
} }
Self { Self {
previous: None,
current_floor: 0, current_floor: 0,
floors: floors.try_into().unwrap() floors: floors.try_into().unwrap()
} }
@@ -81,7 +80,6 @@ impl State {
floors[current_floor].items = items; floors[current_floor].items = items;
let res = State { let res = State {
previous: None,
current_floor: current_floor, current_floor: current_floor,
floors: floors, floors: floors,
}; };
@@ -98,6 +96,13 @@ impl State {
for item in &items { for item in &items {
subsets.push(vec![item.clone()]); subsets.push(vec![item.clone()]);
} }
// for comb in items.clone().iter().filter(|x| match x {Item::Generator(_) => true, _ => false}).combinations(2) {
// subsets.push(comb.into_iter().cloned().collect());
// }
// for comb in items.clone().iter().filter(|x| match x {Item::Chip(_) => true, _ => false}).combinations(2) {
// subsets.push(comb.into_iter().cloned().collect());
// }
for comb in items.iter().combinations(2) { for comb in items.iter().combinations(2) {
subsets.push(comb.into_iter().cloned().collect()); subsets.push(comb.into_iter().cloned().collect());
} }
@@ -113,61 +118,54 @@ impl State {
None None
}; };
let res = subsets.into_iter().filter_map( subsets
|set| { .into_iter()
let remaining: Vec<Item> = items .filter_map(
.clone().into_iter() |set| {
.filter(|f| !set.contains(f)) let remaining: Vec<Item> = items
.collect(); .clone().into_iter()
if is_hazardous(remaining.clone()) { .filter(|f| !set.contains(f))
None .collect();
} else { if is_hazardous(remaining.clone()) {
let mut res: Vec<State> = Vec::new(); None
if let Some(mut its) = above_items.clone() { } else {
its.extend(set.clone()); let mut res: Vec<State> = Vec::new();
its.sort(); if let Some(mut its) = above_items.clone() {
if !is_hazardous(remaining.clone()) { its.extend(set.clone());
// Build above State its.sort();
let mut new_state = State::build_from( if !is_hazardous(its.clone()) {
&self, // Build above State
remaining.clone(), res.push(
self.current_floor + 1, State::build_from(
its &self,
); remaining.clone(),
if self.previous != Some(Box::new(new_state.clone())) { self.current_floor + 1,
let mut prev = self.clone(); its
prev.previous = None; )
new_state.previous = Some(Box::new(prev)); );
res.push(new_state);
} }
} }
} if let Some(mut its) = below_items.clone() {
if let Some(mut its) = below_items.clone() { its.extend(set.clone());
its.extend(set.clone()); its.sort();
its.sort(); if !is_hazardous(its.clone()) {
if !is_hazardous(remaining.clone()) { // Build below State
// Build below State res.push(
let mut new_state = State::build_from( State::build_from(
&self, &self,
remaining.clone(), remaining.clone(),
self.current_floor - 1, self.current_floor - 1,
its its
); )
if self.previous != Some(Box::new(new_state.clone())) { );
let mut prev = self.clone();
prev.previous = None;
new_state.previous = Some(Box::new(prev));
res.push(new_state);
} }
} }
Some(res)
} }
Some(res)
} }
} )
)
.flatten() .flatten()
.collect::<Vec<State>>(); .collect::<Vec<State>>()
res
} }
fn is_complete(&self) -> bool { fn is_complete(&self) -> bool {
@@ -181,7 +179,7 @@ impl State {
} }
impl std::fmt::Debug for State { impl std::fmt::Debug for State {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
let mut floors = self.floors.clone().into_iter().enumerate().collect::<Vec<_>>(); let mut floors = self.floors.clone().into_iter().enumerate().collect::<Vec<_>>();
floors.reverse(); floors.reverse();
for (n, floor) in floors { for (n, floor) in floors {
@@ -236,14 +234,16 @@ fn parse_line(input: &str) -> Floor {
} }
} }
fn walk_through_states(iteration: usize, states: Vec<State>) -> (usize, State) { fn walk_through_states(iteration: usize, states: Vec<State>, saved_states: &mut [Vec<State>; 4], start_time: SystemTime) -> (usize, State) {
// println!("Iteration {:?}", iteration); println!(" ## after {:?}s", start_time.elapsed().unwrap().as_secs());
// println!("States: {:?}", states); println!("Iteration {:?}", iteration);
println!("States: {:?}", states.len());
println!("Saved states:");
println!(" - 4F: {:?}", saved_states[3].len());
println!(" - 3F: {:?}", saved_states[2].len());
println!(" - 2F: {:?}", saved_states[1].len());
println!(" - 1F: {:?}", saved_states[0].len());
if iteration > 10 {
return (42, states[0].clone());
}
let states = states let states = states
.into_iter() .into_iter()
.flat_map(|s| s.next_states()) .flat_map(|s| s.next_states())
@@ -258,7 +258,18 @@ fn walk_through_states(iteration: usize, states: Vec<State>) -> (usize, State) {
if !complete.is_empty() { if !complete.is_empty() {
(iteration, complete[0].clone()) (iteration, complete[0].clone())
} else { } else {
walk_through_states(iteration + 1, states) let states: Vec<State> = states
.into_iter()
.filter_map(|s| {
if saved_states[s.current_floor].contains(&s) {
None
} else {
saved_states[s.current_floor].push(s.clone());
Some(s)
}
})
.collect();
walk_through_states(iteration + 1, states, saved_states, start_time)
} }
} }
@@ -270,22 +281,39 @@ pub fn part_one(input: &str) -> Option<usize> {
.map(parse_line) .map(parse_line)
.collect(); .collect();
let state = State::init(floors); let state = State::init(floors);
let mut saved: [Vec<State>; 4] = [
// let states = state.next_states(); vec![state.clone()], vec![], vec![], vec![]
];
// println!("Ok, trying a new one:"); let (iterations, _st) = walk_through_states(1, state.next_states(), &mut saved, SystemTime::now());
// println!("{:#?}", _st);
// let next_states = states[0].next_states(); // println!("{:?}", iterations);
Some(iterations + 1)
// None
let (iterations, st) = walk_through_states(1, state.next_states());
println!("{:#?}", st);
println!("{:?}", iterations);
Some(iterations)
} }
pub fn part_two(_input: &str) -> Option<u32> { pub fn part_two(input: &str) -> Option<usize> {
// let mut floors: Vec<Floor> = input
// .strip_suffix("\n")
// .unwrap_or(input)
// .lines()
// .map(parse_line)
// .collect();
// floors[0].items.extend(
// vec![
// Item::Generator(Element::from_name("europium").unwrap()), // well ... original elements don't exist, duh...
// Item::Generator(Element::from_name("lithium").unwrap()),
// Item::Chip(Element::from_name("europium").unwrap()),
// Item::Chip(Element::from_name("lithium").unwrap()),
// ]
// );
// floors[0].items.sort();
// let state = State::init(floors);
// let mut saved: [Vec<State>; 4] = [
// vec![state.clone()], vec![], vec![], vec![],
// ];
// let (iterations, _st) = walk_through_states(1, state.next_states(), &mut saved, SystemTime::now());
// // println!("{:#?}", _st);
// // println!("{:?}", iterations);
// Some(iterations + 1)
None None
} }
@@ -296,12 +324,12 @@ mod tests {
#[test] #[test]
fn test_part_one() { fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY)); let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(42)); assert_eq!(result, Some(11));
} }
#[test] #[test]
fn test_part_two() { fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY)); let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, None); assert_eq!(result, Some(23));
} }
} }