diff --git a/2019/17/src/main.rs b/2019/17/src/main.rs index 94c088c..88d781f 100644 --- a/2019/17/src/main.rs +++ b/2019/17/src/main.rs @@ -1,10 +1,10 @@ use grid::*; use intcode::*; use std::char; -use std::collections::HashMap; +use std::collections::{HashMap,HashSet}; use std::fmt; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq, Hash, Clone)] struct Movement { rotation: i8, distance: u8, @@ -62,6 +62,7 @@ fn test_input() -> HashMap { ....#...#...... ....#####......" .lines() + .rev() .enumerate() .flat_map(move |(y, s)| s.chars().enumerate().map(move |(x, c)| ((x, y).into(), c))) .collect() @@ -70,16 +71,19 @@ fn test_input() -> HashMap { fn main() { // The main reason I use a hashmap here (instead of a 2D vector) is that my abstractions for // ascii stuff all use maps ヽ( ゚ヮ・)ノ - let field: HashMap = IntComputer::without_params(read_input()) + let mut input = read_input(); + let field: HashMap = IntComputer::without_params(input.clone()) .get_all_outputs() .iter() .map(|n| char::from_u32(*n as u32).unwrap()) .collect::() .lines() + // this rev breaks part 1 but is necessary for part 2 + .rev() .enumerate() .flat_map(move |(y, s)| s.chars().enumerate().map(move |(x, c)| ((x, y).into(), c))) .collect(); - // let field = test_input(); + //let field = test_input(); let p1 = field .iter() .filter(|(pos, obj)| { @@ -94,7 +98,99 @@ fn main() { println!("{}", draw_ascii(&field, '.')); let commands = find_commands(&field); - for c in &commands { - print!("{}", c); + println!("Commands: {}", commands.len()); + for c in commands.iter() { println!("{}", c); } + let mut pos = 0; + //let mut segments = Vec::new(); + let segments = vec![ + vec![ + Movement{ rotation: -1, distance: 8 }, + Movement{ rotation: 1, distance: 12 }, + Movement{ rotation: 1, distance: 12 }, + Movement{ rotation: 1, distance: 10 }, + ], + vec![ + Movement{ rotation: 1, distance: 10 }, + Movement{ rotation: 1, distance: 12 }, + Movement{ rotation: 1, distance: 10 }, + ], + vec![ + Movement{ rotation: -1, distance: 10 }, + Movement{ rotation: 1, distance: 10 }, + Movement{ rotation: -1, distance: 6 }, + ] + ]; + /* + while pos < commands.len() { + if let Some((n, mov)) = (1..=5) + .filter_map(|i| { + let reference = commands[pos..].windows(i).next(); + let dupes = commands[pos..] + .windows(i) + .filter(|&w| Some(w) == reference) + .count(); + if dupes > 0 { + Some(((i, dupes), reference)) + } else { + None + } + }) + .max_by_key(|((x, y), _)| x + y*2) + { + pos += n.0; + segments.push(mov.unwrap()); + } } + let filtered: HashSet<_> = segments.clone().into_iter().map(|mut curr| { + for s in &segments { + if curr.len() <= s.len() { + continue + } + let index_after = curr.len() - s.len(); + if s == &&curr[index_after..] { + curr = &curr[..index_after]; + } + if s == &&curr[..index_after] { + curr = &curr[index_after..]; + } + } + curr + }) + .filter(|s| !s.is_empty()) + .collect(); + //dbg!(&segments, segments.len()); + dbg!(filtered.len()); + println!( + "{}", + filtered + .iter() + .map(|s| s.iter().map(|m| m.to_string()).collect::() + "\n") + .collect::() + ); + */ + let filtered = segments; + let mut instructions = Vec::new(); + let mut pos = 0; + while pos < commands.len() { + for i in 1.. { + if filtered.contains(&commands[pos..pos+i].to_vec()) { + instructions.push(&commands[pos..pos+i]); + pos += i; + println!("match for {}..{}", pos, i); + break; + } else { + println!("no match for {}..{}", pos, i); + } + } + } + for i in instructions { + println!("{}", i.iter().map(|m| m.to_string()).collect::()); + } + + // it’s surprisingly easy to do this manually with enough debug prints above. + // proper solution once the headache is gone. fml + input[0] = 2; + let mut path: Vec = "A,B,A,B,C,C,B,A,B,C\nL,8,R,12,R,12,R,10\nR,10,R,12,R,10\nL,10,R,10,L,6\nn\n".chars().map(|c| c as i64).collect(); + path.reverse(); + println!("Part 2: {:?}", IntComputer::new(input, 0, path).get_all_outputs()); }