diff --git a/src/euler31/src/main.rs b/src/euler31/src/main.rs index bd8ed7e..8dd9fa4 100644 --- a/src/euler31/src/main.rs +++ b/src/euler31/src/main.rs @@ -1,163 +1,114 @@ #![allow(dead_code)] -use std::ops::Index; +use std::{cmp::Reverse, collections::HashSet}; const VALUE: u8 = 200; type Values = Vec; fn main() { - // let head = Tree::new(200); + let x = vec![VALUE]; + let mut cases = HashSet::new(); + cases.insert(x.clone()); + solve(x, &mut cases, -1); + let mut cases_ordered: Vec<_> = cases.iter().collect(); + cases_ordered.sort_unstable_by_key(|v| v.len()); + for case in cases_ordered { + println!("{}", case.show()); + } + println!("{}", cases.len()); } -#[derive(Debug, PartialEq)] -struct Node { - values: Values, - nodes: Vec, -} - -impl Node { - fn new(value: u8) -> Self { - Self { - values: vec![value], - nodes: vec![], - } +fn solve(x: Values, cases: &mut HashSet, max_depth: isize) { + // println!("solving {}", x.show()); + if max_depth == 0 { + return; } - - fn new_vec(values: Values) -> Self { - Self { - values, - nodes: vec![], - } - } - - fn get_value(&self, index: usize) -> Option<&u8> { - self.values.get(index) - } - - fn iter(&mut self) { - if !self.nodes.is_empty() { - self.nodes.iter_mut().for_each(|n| n.iter()) - } else { - let mut previous: Option> = None; - let mut offset = 0; - for (i, value) in self.values.iter().enumerate() { - let divided = divide_value(*value); - - let use_existing_data = previous.is_none(); - println!(); - println!(); - println!(); - for (j, combination) in divided.iter().enumerate() { - let mut new_vec; - let offset; - if use_existing_data { - println!("existing"); - new_vec = self.values.clone(); - offset = 0; - } else { - println!("previous"); - new_vec = previous.as_ref().unwrap()[j].clone(); - offset = new_vec.len() - self.values.len(); - } - println!(); - println!("{}", i + offset); - println!("{new_vec:#?}"); - println!("{combination:#?}"); - - new_vec.splice(i + offset..i + offset + 1, combination.clone()); - println!("{new_vec:#?}"); - if previous.is_none() { - previous = Some(vec![new_vec.clone()]); - } else { - let mut new = previous.unwrap().clone(); - new.push(new_vec.clone()); - previous = Some(new); - } - debug_assert_eq!(new_vec.iter().sum::(), VALUE); - self.nodes.push(Node::new_vec(new_vec)); - } + for (i, val) in x.iter().enumerate() { + for variant in divide(*val) { + let mut copy = x.clone(); + copy.splice(i..i + 1, variant); + debug_assert_eq!(copy.iter().sum::(), VALUE); + // copy.sort_unstable(); + // copy.sort_unstable_by_key(|&i| Reverse(i)); + // println!("{}", copy.show()); + let mut sorted = copy.clone(); + sorted.sort_unstable(); + if cases.contains(&sorted) { + // eprintln!("already seen: {}", copy.show()); + continue; + } else { + cases.insert(sorted); + solve(copy, cases, max_depth - 1) } } } } -fn divide_value(x: u8) -> Vec { +trait Display { + fn show(&self) -> String; +} + +impl Display for Values { + fn show(&self) -> String { + self.iter() + .map(|i| i.to_string()) + .reduce(|mut accum, elem| { + accum.push_str(", "); + accum.push_str(&elem); + accum + }) + .unwrap() + } +} + +fn divide(x: u8) -> Vec { if x == 200 { vec![vec![100, 100]] } else if x == 100 { vec![vec![50, 50]] - } else { - // x == 50 + } else if x == 50 { vec![vec![20, 20, 10], vec![20, 10, 10, 10], vec![10; 5]] - } -} - -impl Index for Node { - type Output = Node; - - fn index(&self, index: usize) -> &Self::Output { - &self.nodes[index] + } else if x == 20 { + vec![vec![10, 10]] + } else if x == 10 { + vec![vec![5, 5]] + } else if x == 5 { + vec![vec![2, 2, 1], vec![2, 1, 1, 1], vec![1; 5]] + } else if x == 2 { + vec![vec![1, 1]] + } else { + vec![vec![x]] } } #[cfg(test)] mod test { - // use crate::Node; - use crate::Node; + use crate::solve; + use std::collections::HashSet; + + use crate::VALUE; #[test] - fn test_new() { - let tree = Node::new(200); - assert_eq!(tree.values, [200]); - assert_eq!(tree.nodes.len(), 0); + fn test_1() { + let x = vec![VALUE]; + let mut hs = HashSet::new(); + hs.insert(x.clone()); + solve(x, &mut hs, 1); + assert_eq!(hs.len(), 2); + assert!(hs.contains(&vec![VALUE])); + assert!(hs.contains(&vec![100, 100])); } #[test] - fn test_iter() { - let mut tree = Node::new(200); - tree.iter(); - assert_eq!(tree.nodes.len(), 1); - assert_eq!(tree.nodes[0].values, vec![100, 100]); - } - - #[test] - fn test_iter_2() { - let mut tree = Node::new(200); - tree.iter(); - tree.iter(); - assert_eq!(tree.nodes[0][0].values, vec![50, 50, 100]); - assert_eq!(tree.nodes[0][1].values, vec![50; 4]); - assert!(tree.nodes[0].get_value(2).is_none()); - } - - #[test] - fn test_iter_3() { - let mut tree = Node::new(200); - tree.iter(); - tree.iter(); - tree.iter(); - assert_eq!(tree.nodes[0][0][0].values, vec![20, 20, 10, 50, 100]); - assert_eq!(tree.nodes[0][0][1].values, vec![20, 10, 10, 10, 50, 100]); - assert_eq!( - tree.nodes[0][0][2].values, - vec![10, 10, 10, 10, 10, 50, 100] - ); - assert_eq!( - tree.nodes[0][0][3].values, - vec![20, 20, 10, 20, 20, 10, 100] - ); - assert_eq!( - tree.nodes[0][0][4].values, - vec![20, 10, 10, 10, 20, 10, 10, 10, 100] - ); - assert_eq!( - tree.nodes[0][0][5].values, - vec![10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 100] - ); - assert_eq!( - tree.nodes[0][0][6].values, - vec![10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 50, 50] - ); - println!("{}", tree.nodes[0][0].nodes.len()) + fn test_2() { + let x = vec![VALUE]; + let mut hs = HashSet::new(); + hs.insert(x.clone()); + solve(x, &mut hs, 3); + assert_eq!(hs.len(), 4); + assert!(hs.contains(&vec![VALUE])); + assert!(hs.contains(&vec![100, 100])); + assert!(hs.contains(&vec![100, 50, 50])); + assert!(hs.contains(&vec![50, 50, 50, 50])); } }