1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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);
}
|