This commit is contained in:
2016-12-09 11:34:07 +01:00
parent 2ebe3b0004
commit 89abf474c9
4 changed files with 215 additions and 0 deletions

204
2016/09/src/main.rs Normal file
View File

@@ -0,0 +1,204 @@
use std::io::{self, BufRead};
#[derive(Debug)]
enum MachineState {
Normal,
MarkerRange(String),
MarkerRepeat(usize, String),
Sequence(usize, usize, String),
}
fn decompressed_length_v1(input: &str) -> usize {
let mut length: usize = 0;
let mut state = MachineState::Normal;
for c in input.chars() {
state = match (c, state) {
// Normal.
('(', MachineState::Normal) => {
MachineState::MarkerRange(String::new())
}
(_, MachineState::Normal) => {
length += 1;
MachineState::Normal
}
// Marker range.
('x', MachineState::MarkerRange(buf)) => {
let range = buf.parse::<usize>().unwrap();
MachineState::MarkerRepeat(range, String::new())
}
(c @ _, MachineState::MarkerRange(mut buf)) => {
buf.push(c);
MachineState::MarkerRange(buf)
}
// Marker repeat.
(')', MachineState::MarkerRepeat(range, buf)) => {
let repeat = buf.parse::<usize>().unwrap();
MachineState::Sequence(range, repeat, String::new())
}
(c @ _, MachineState::MarkerRepeat(range, mut buf)) => {
buf.push(c);
MachineState::MarkerRepeat(range, buf)
}
// Sequence.
(c @ _, MachineState::Sequence(range, repeat, mut buf)) => {
buf.push(c);
if buf.len() == range {
length += buf.len() * repeat;
MachineState::Normal
} else {
MachineState::Sequence(range, repeat, buf)
}
}
};
}
length
}
fn decompressed_length_v2(input: &str) -> usize {
let mut length: usize = 0;
let mut state = MachineState::Normal;
for c in input.chars() {
state = match (c, state) {
// Normal.
('(', MachineState::Normal) => {
MachineState::MarkerRange(String::new())
}
(_, MachineState::Normal) => {
length += 1;
MachineState::Normal
}
// Marker range.
('x', MachineState::MarkerRange(buf)) => {
let range = buf.parse::<usize>().unwrap();
MachineState::MarkerRepeat(range, String::new())
}
(c @ _, MachineState::MarkerRange(mut buf)) => {
buf.push(c);
MachineState::MarkerRange(buf)
}
// Marker repeat.
(')', MachineState::MarkerRepeat(range, buf)) => {
let repeat = buf.parse::<usize>().unwrap();
MachineState::Sequence(range, repeat, String::new())
}
(c @ _, MachineState::MarkerRepeat(range, mut buf)) => {
buf.push(c);
MachineState::MarkerRepeat(range, buf)
}
// Sequence.
(_, MachineState::Sequence(range, repeat, mut buf)) => {
buf.push(c);
if buf.len() == range {
length += decompressed_length_v2(&buf) * repeat;
MachineState::Normal
} else {
MachineState::Sequence(range, repeat, buf)
}
}
};
}
length
}
fn main() {
let stdin = io::stdin();
let lines = stdin.lock().lines()
.filter_map(|line| line.ok())
.collect::<Vec<_>>();
let length_v1: usize = lines.iter()
.map(|line| decompressed_length_v1(&line))
.sum();
let length_v2: usize = lines.iter()
.map(|line| decompressed_length_v2(&line))
.sum();
println!("length_v1={}", length_v1);
println!("length_v2={}", length_v2);
}
#[cfg(test)]
mod tests {
use super::{decompressed_length_v1, decompressed_length_v2};
#[test]
fn example_01() {
assert_eq!(6, decompressed_length_v1("ADVENT"));
}
#[test]
fn example_02() {
assert_eq!(7, decompressed_length_v1("A(1x5)BC"));
}
#[test]
fn example_03() {
assert_eq!(9, decompressed_length_v1("(3x3)XYZ"));
}
#[test]
fn example_04() {
assert_eq!(11, decompressed_length_v1("A(2x2)BCD(2x2)EFG"));
}
#[test]
fn example_05() {
assert_eq!(6, decompressed_length_v1("(6x1)(1x3)A"));
}
#[test]
fn example_06() {
assert_eq!(18, decompressed_length_v1("X(8x2)(3x3)ABCY"));
}
#[test]
fn example_07() {
assert_eq!(9, decompressed_length_v2("(3x3)XYZ"));
}
#[test]
fn example_08() {
assert_eq!(20, decompressed_length_v2("X(8x2)(3x3)ABCY"));
}
#[test]
fn example_09() {
assert_eq!(241920, decompressed_length_v2("(27x12)(20x12)(13x14)(7x10)(1x12)A"));
}
#[test]
fn example_10() {
assert_eq!(445, decompressed_length_v2("(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN"));
}
}