summaryrefslogtreecommitdiffstats
path: root/day5/src/main.rs
diff options
context:
space:
mode:
authorJan Tuomi <jan.tuomi@eficode.com>2018-12-06 16:13:16 +0200
committerJan Tuomi <jan.tuomi@eficode.com>2018-12-06 16:13:16 +0200
commitd7ed7cb411329c15e2c5457b3b1c48aa9dba22c8 (patch)
tree1fd926d34dd5b9b2c96b1bc1578f9b9973d2a654 /day5/src/main.rs
parent7514e260e406ea3706b9f3cfb167b0c8c0217798 (diff)
Solve day5
Diffstat (limited to 'day5/src/main.rs')
-rw-r--r--day5/src/main.rs114
1 files changed, 114 insertions, 0 deletions
diff --git a/day5/src/main.rs b/day5/src/main.rs
new file mode 100644
index 0000000..4b2b0bc
--- /dev/null
+++ b/day5/src/main.rs
@@ -0,0 +1,114 @@
+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<char>) -> 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<char> = 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<String> = 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<String> = 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);
+} \ No newline at end of file