This commit is contained in:
2016-12-22 13:57:16 +01:00
parent add430bbef
commit 831acafd8c
5 changed files with 506 additions and 0 deletions

105
2016/21/Cargo.lock generated Normal file
View File

@@ -0,0 +1,105 @@
[root]
name = "21"
version = "0.1.0"
dependencies = [
"lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "thread-id"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

8
2016/21/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "21"
version = "0.1.0"
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
[dependencies]
lazy_static = "0.1"
regex = "0.1"

8
2016/21/example.txt Normal file
View File

@@ -0,0 +1,8 @@
swap position 4 with position 0
swap letter d with letter b
reverse positions 0 through 4
rotate left 1 step
move position 1 to position 4
move position 3 to position 0
rotate based on position of letter b
rotate based on position of letter d

100
2016/21/input.txt Normal file
View File

@@ -0,0 +1,100 @@
move position 0 to position 3
rotate right 0 steps
rotate right 1 step
move position 1 to position 5
swap letter h with letter b
reverse positions 1 through 3
swap letter a with letter g
swap letter b with letter h
rotate based on position of letter c
swap letter d with letter c
rotate based on position of letter c
swap position 6 with position 5
rotate right 7 steps
swap letter b with letter h
move position 4 to position 3
swap position 1 with position 0
swap position 7 with position 5
move position 7 to position 1
swap letter c with letter a
move position 7 to position 5
rotate right 4 steps
swap position 0 with position 5
move position 3 to position 1
swap letter c with letter h
rotate based on position of letter d
reverse positions 0 through 2
rotate based on position of letter g
move position 6 to position 7
move position 2 to position 5
swap position 1 with position 0
swap letter f with letter c
rotate right 1 step
reverse positions 2 through 4
rotate left 1 step
rotate based on position of letter h
rotate right 1 step
rotate right 5 steps
swap position 6 with position 3
move position 0 to position 5
swap letter g with letter f
reverse positions 2 through 7
reverse positions 4 through 6
swap position 4 with position 1
move position 2 to position 1
move position 3 to position 1
swap letter b with letter a
rotate based on position of letter b
reverse positions 3 through 5
move position 0 to position 2
rotate based on position of letter b
reverse positions 4 through 5
rotate based on position of letter g
reverse positions 0 through 5
swap letter h with letter c
reverse positions 2 through 5
swap position 7 with position 5
swap letter g with letter d
swap letter d with letter e
move position 1 to position 2
move position 3 to position 2
swap letter d with letter g
swap position 3 with position 7
swap letter b with letter f
rotate right 3 steps
move position 5 to position 3
move position 1 to position 2
rotate based on position of letter b
rotate based on position of letter c
reverse positions 2 through 3
move position 2 to position 3
rotate right 1 step
move position 7 to position 0
rotate right 3 steps
move position 6 to position 3
rotate based on position of letter e
swap letter c with letter b
swap letter f with letter d
swap position 2 with position 5
swap letter f with letter g
rotate based on position of letter a
reverse positions 3 through 4
rotate left 7 steps
rotate left 6 steps
swap letter g with letter b
reverse positions 3 through 6
rotate right 6 steps
rotate based on position of letter c
rotate based on position of letter b
rotate left 1 step
reverse positions 3 through 7
swap letter f with letter g
swap position 4 with position 1
rotate based on position of letter d
move position 0 to position 4
swap position 7 with position 6
rotate right 6 steps
rotate based on position of letter e
move position 7 to position 3
rotate right 3 steps
swap position 1 with position 2

285
2016/21/src/main.rs Normal file
View File

@@ -0,0 +1,285 @@
#[macro_use] extern crate lazy_static;
extern crate regex;
use std::io::{self, BufRead};
use std::str::FromStr;
use regex::Regex;
#[derive(Debug)]
pub enum Operation {
SwapPosition(usize, usize),
SwapLetter(char, char),
RotateLeft(usize),
RotateRight(usize),
RotatePosition(char),
ReversePosition(usize, usize),
MovePosition(usize, usize)
}
impl FromStr for Operation {
type Err = String;
fn from_str(s: &str) -> Result<Operation, Self::Err> {
lazy_static! {
static ref SWAP_P: Regex = Regex::new(r"^swap position (\d+) with position (\d+)$").unwrap();
static ref SWAP_L: Regex = Regex::new(r"^swap letter ([a-z]) with letter ([a-z])$").unwrap();
static ref ROTATE_L: Regex = Regex::new(r"^rotate left (\d+) steps?$").unwrap();
static ref ROTATE_R: Regex = Regex::new(r"^rotate right (\d+) steps?$").unwrap();
static ref ROTATE_P: Regex = Regex::new(r"^rotate based on position of letter ([a-z])$").unwrap();
static ref REVERSE: Regex = Regex::new(r"^reverse positions (\d+) through (\d+)$").unwrap();
static ref MOVE: Regex = Regex::new(r"^move position (\d+) to position (\d+)$").unwrap();
}
if let Some(caps) = SWAP_P.captures(s) {
let x = caps.at(1).unwrap().parse::<usize>().unwrap();
let y = caps.at(2).unwrap().parse::<usize>().unwrap();
return Ok(Operation::SwapPosition(x, y));
}
if let Some(caps) = SWAP_L.captures(s) {
let x = caps.at(1).unwrap().chars().nth(0).unwrap();
let y = caps.at(2).unwrap().chars().nth(0).unwrap();
return Ok(Operation::SwapLetter(x, y));
}
if let Some(caps) = ROTATE_L.captures(s) {
let x = caps.at(1).unwrap().parse::<usize>().unwrap();
return Ok(Operation::RotateLeft(x));
}
if let Some(caps) = ROTATE_R.captures(s) {
let x = caps.at(1).unwrap().parse::<usize>().unwrap();
return Ok(Operation::RotateRight(x));
}
if let Some(caps) = ROTATE_P.captures(s) {
let x = caps.at(1).unwrap().chars().nth(0).unwrap();
return Ok(Operation::RotatePosition(x));
}
if let Some(caps) = REVERSE.captures(s) {
let x = caps.at(1).unwrap().parse::<usize>().unwrap();
let y = caps.at(2).unwrap().parse::<usize>().unwrap();
return Ok(Operation::ReversePosition(x, y));
}
if let Some(caps) = MOVE.captures(s) {
let x = caps.at(1).unwrap().parse::<usize>().unwrap();
let y = caps.at(2).unwrap().parse::<usize>().unwrap();
return Ok(Operation::MovePosition(x, y));
}
Err(s.to_owned())
}
}
pub fn op_swap_position(input: &str, x: usize, y: usize) -> String {
let chars = input.chars()
.enumerate()
.filter(|&(i, _)| i == x || i == y)
.map(|(_, c)| c)
.collect::<Vec<_>>();
input.chars()
.enumerate()
.map(|(i, c)| {
if i == x {
chars[if x < y { 1 } else { 0 }]
} else if i == y {
chars[if x < y { 0 } else { 1 }]
} else {
c
}
})
.collect::<String>()
}
pub fn op_swap_letter(input: &str, x: char, y: char) -> String {
input.chars()
.map(|c| {
if c == x {
y
} else if c == y {
x
} else {
c
}
})
.collect::<String>()
}
pub fn op_rotate_left(input: &str, x: usize) -> String {
let (left, right) = input.split_at(x % input.len());
right.to_owned() + left
}
pub fn op_rotate_right(input: &str, x: usize) -> String {
op_rotate_left(input, input.len() - (x % input.len()))
}
pub fn op_rotate_position(input: &str, x: char) -> String {
if let Some(position) = input.find(x) {
let delta = if position < 4 { 1 } else { 2 };
op_rotate_right(input, position + delta)
} else {
input.to_owned()
}
}
pub fn op_reverse_position(input: &str, x: usize, y: usize) -> String {
let (center, right) = input.split_at(y + 1);
let (left, center) = center.split_at(x);
left.to_owned() + center.chars().rev().collect::<String>().as_str() + right
}
pub fn op_move_position(input: &str, x: usize, y: usize) -> String {
let mut output = input.to_owned();
let c = output.remove(x);
output.insert(y, c);
output
}
fn main() {
let input = "abcdefgh";
let stdin = io::stdin();
let operations = stdin.lock().lines()
.filter_map(|line| line.ok())
.map(|line| line.parse::<Operation>().unwrap())
.collect::<Vec<_>>();;
// Part 1.
let mut output = input.to_owned();
for operation in operations.iter() {
output = match operation {
&Operation::SwapPosition(x, y) => op_swap_position(&output, x, y),
&Operation::SwapLetter(x, y) => op_swap_letter(&output, x, y),
&Operation::RotateLeft(x) => op_rotate_left(&output, x),
&Operation::RotateRight(x) => op_rotate_right(&output, x),
&Operation::RotatePosition(x) => op_rotate_position(&output, x),
&Operation::ReversePosition(x, y) => op_reverse_position(&output, x, y),
&Operation::MovePosition(x, y) => op_move_position(&output, x, y),
};
}
println!("output={}", output);
// Part 2.
let mut state = "aaaaaaaa".to_owned();
loop {
let mut output = state.clone();
for operation in operations.iter() {
output = match operation {
&Operation::SwapPosition(x, y) => op_swap_position(&output, x, y),
&Operation::SwapLetter(x, y) => op_swap_letter(&output, x, y),
&Operation::RotateLeft(x) => op_rotate_left(&output, x),
&Operation::RotateRight(x) => op_rotate_right(&output, x),
&Operation::RotatePosition(x) => op_rotate_position(&output, x),
&Operation::ReversePosition(x, y) => op_reverse_position(&output, x, y),
&Operation::MovePosition(x, y) => op_move_position(&output, x, y),
};
}
if output == "fbgdceah".to_owned() {
break;
}
state = state.chars()
.rev()
.scan(true, |rotate, c| {
if *rotate {
if c < 'h' {
*rotate = false;
Some(((c as u8) + 1) as char)
} else {
Some('a')
}
} else {
Some(c)
}
})
.collect::<Vec<_>>()
.iter()
.rev()
.map(|c| *c)
.collect::<String>();
}
println!("input={}", state);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_op_swap_position() {
assert_eq!("ebcda".to_owned(), op_swap_position("abcde", 4, 0));
assert_eq!("ebcda".to_owned(), op_swap_position("abcde", 0, 4));
assert_eq!("adcbe".to_owned(), op_swap_position("abcde", 1, 3));
assert_eq!("adcbe".to_owned(), op_swap_position("abcde", 3, 1));
}
#[test]
fn test_op_swap_letter() {
assert_eq!("edcba".to_owned(), op_swap_letter("ebcda", 'd', 'b'));
}
#[test]
fn test_op_rotate_left() {
assert_eq!("ebcda".to_owned(), op_rotate_left("ebcda", 0));
assert_eq!("bcdae".to_owned(), op_rotate_left("ebcda", 1));
}
#[test]
fn test_op_rotate_right() {
assert_eq!("ebcda".to_owned(), op_rotate_right("ebcda", 0));
assert_eq!("aebcd".to_owned(), op_rotate_right("ebcda", 1));
}
#[test]
fn test_op_rotate_position() {
assert_eq!("ecabd".to_owned(), op_rotate_position("abdec", 'b'));
assert_eq!("decab".to_owned(), op_rotate_position("ecabd", 'd'));
}
#[test]
fn test_op_reverse_position() {
assert_eq!("abcde".to_owned(), op_reverse_position("edcba", 0, 4));
assert_eq!("ebcda".to_owned(), op_reverse_position("edcba", 1, 3));
assert_eq!("decba".to_owned(), op_reverse_position("edcba", 0, 1));
}
#[test]
fn test_op_move_position() {
assert_eq!("bdeac".to_owned(), op_move_position("bcdea", 1, 4));
assert_eq!("abdec".to_owned(), op_move_position("bdeac", 3, 0));
}
}