use std::env; use std::io::BufReader; use std::io::BufRead; use std::fs::File; use std::process; static ASCII_LOWER: [char; 26] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']; fn same_unit(a: &char, b: &char) -> bool { a.to_lowercase().to_string() == b.to_lowercase().to_string() } fn same_polarity(a: &char, b: &char) -> bool { (a.is_lowercase() && b.is_lowercase()) || (a.is_uppercase() && b.is_uppercase()) } fn find_removable_indices(chars: &Vec) -> Option<(usize, usize)> { let mut res: Option<(usize, usize)> = None; for (i, cur) in chars.iter().enumerate() { if i == chars.len() - 1 { // last element break; } let next = chars[i + 1]; if same_unit(&cur, &next) && !same_polarity(&cur, &next) { res = Some((i, i + 1)); break; } } res } fn react_polymer(line: &String) -> String { let mut string: Vec = line.trim().chars().collect(); loop { let indices = find_removable_indices(&string); let (rem_i1, rem_i2): (usize, usize); match indices { Some((i1, i2)) => { rem_i1 = i1; rem_i2 = i2; let s = &mut string; s.remove(rem_i2); s.remove(rem_i1); continue; } None => { break; } }; } string.into_iter().collect() } fn react_polymer_without_char(line: &String, ch: &char) -> String { let line_ref: &str = line.as_ref(); let a = *ch; let b_str = a.to_uppercase().to_string(); let b: &str = b_str.as_ref(); let replaced_line = line_ref.replace(*ch, "").replace(a, "").replace(b, ""); let res = react_polymer(&replaced_line); res } fn main() { let args: Vec = env::args().collect(); if args.len() != 2 { println!("Wrong number of arguments. Provide just a file name."); process::exit(1); } let filename = &args[1]; println!("Using file {} as input.", filename); let f = match File::open(filename) { Ok(file) => file, Err(e) => { println!("Failed to open file {}. {:?}", filename, e); process::exit(1); } }; let file = BufReader::new(&f); let mut lines: Vec = file.lines() .map(|line| line.expect("Could not parse line.")) .collect(); &lines.sort(); assert_eq!(lines.len(), 1); let line = &lines[0]; // exercise 1 println!("Solving 1..."); let result = react_polymer(&line); // println!("1. Result: {}", result); println!("1. Length: {}", result.len()); // exercise 2 println!("Solving 2..."); let mut best = line.len(); for ch in &ASCII_LOWER { let result = react_polymer_without_char(&line, ch); let len = result.len(); println!("Debug: ch: {}, len: {}", &ch, &len); if len < best { best = len; println!("Debug: new best: {}", &len); } } println!("2. Length: {}", best); }