[2017][rust][16.0]
change vkmwullzpslqytsnskosxxzznvyktpuy
commit f9364cf56adababb5d9f1cfa879faabbb5bea57b
author Alpha Chen <alpha.chen@gmail.com>
date
parent ztumpkln
diff --git a/2017/rust/Cargo.lock b/2017/rust/Cargo.lock
index d6adbc5..648f6ec 100644
--- a/2017/rust/Cargo.lock
+++ b/2017/rust/Cargo.lock
@@ -5,6 +5,7 @@ dependencies = [
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -108,6 +109,11 @@ name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "redox_syscall"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "regex"
 version = "0.2.3"
@@ -166,6 +172,17 @@ dependencies = [
  "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "time"
+version = "0.1.38"
+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.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "unicode-xid"
 version = "0.0.4"
@@ -213,6 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
+"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
 "checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
 "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
@@ -220,6 +238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
 "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
 "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
+"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
diff --git a/2017/rust/Cargo.toml b/2017/rust/Cargo.toml
index 7fdc2ec..ade2bbd 100644
--- a/2017/rust/Cargo.toml
+++ b/2017/rust/Cargo.toml
@@ -7,3 +7,4 @@ authors = ["Alpha Chen <alpha.chen@gmail.com>"]
 failure = "0.1"
 lazy_static = "1.0"
 regex = "0.2"
+time = ""
diff --git a/2017/rust/src/day_06.rs b/2017/rust/src/day_06.rs
index 1464cc6..f4f1cd4 100644
--- a/2017/rust/src/day_06.rs
+++ b/2017/rust/src/day_06.rs
@@ -53,7 +53,7 @@ impl Iterator for Reallocation {
         let (start, max) = banks
             .iter()
             .max_by_key(|&&(_, x)| x)
-            .map(|&(i, x)| (i, x.clone()))?;
+            .map(|&(i, x)| (i, *x))?;
 
         let len = self.banks.len();
         self.banks[start] = 0;
diff --git a/2017/rust/src/day_16.rs b/2017/rust/src/day_16.rs
new file mode 100644
index 0000000..5bd0feb
--- /dev/null
+++ b/2017/rust/src/day_16.rs
@@ -0,0 +1,90 @@
+use std::convert::TryFrom;
+use failure::*;
+use regex::Regex;
+
+pub fn solve(input: &str) -> Result<String, Error> {
+    // let input = "s1,x3/4,pe/b";
+    let moves: Vec<_> = input
+        .split(',')
+        .map(Move::try_from)
+        .collect::<Result<_, _>>()?;
+    let mut programs = (b'a'..=b'p').map(|c| c as char).collect::<Vec<_>>();
+    dance(&moves, &mut programs);
+    Ok(programs.iter().collect())
+}
+
+fn dance(moves: &[Move], programs: &mut [char]) {
+    for m in moves {
+        match m {
+            Move::Spin(size) => {
+                let len = programs.len();
+                programs.rotate(len - size);
+            }
+            Move::Exchange(a, b) => {
+                programs.swap(*a, *b);
+            }
+            Move::Partner(a, b) => {
+                let a = programs.iter().position(|x| x == a).unwrap();
+                let b = programs.iter().position(|x| x == b).unwrap();
+                programs.swap(a, b);
+            }
+        }
+    }
+}
+
+#[test]
+fn test_dance() {
+    let moves = vec![Move::Spin(1), Move::Exchange(3, 4), Move::Partner('e', 'b')];
+    let mut programs: Vec<_> = (b'a'..=b'e').map(|c| c as char).collect();
+
+    dance(&moves, &mut programs);
+
+    assert_eq!(programs, vec!['b', 'a', 'e', 'd', 'c']);
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum Move {
+    Spin(usize),
+    Exchange(usize, usize),
+    Partner(char, char),
+}
+
+lazy_static! {
+    static ref RE_S: Regex = { Regex::new(r"s(\d+)").unwrap() };
+    static ref RE_X: Regex = { Regex::new(r"x(\d+)/(\d+)").unwrap() };
+    static ref RE_P: Regex = { Regex::new(r"p(\w)/(\w)").unwrap() };
+}
+
+impl<'a> TryFrom<&'a str> for Move {
+    type Error = Error;
+
+    fn try_from(value: &str) -> Result<Self, Self::Error> {
+        RE_S.captures(value)
+            .and_then(|c| {
+                let size = c.get(1).unwrap().as_str().parse().ok()?;
+                Some(Move::Spin(size))
+            })
+            .or_else(|| {
+                RE_X.captures(value).and_then(|c| {
+                    let a = c.get(1).unwrap().as_str().parse().ok()?;
+                    let b = c.get(2).unwrap().as_str().parse().ok()?;
+                    Some(Move::Exchange(a, b))
+                })
+            })
+            .or_else(|| {
+                RE_P.captures(value).and_then(|c| {
+                    let a = c.get(1).unwrap().as_str().chars().next()?;
+                    let b = c.get(2).unwrap().as_str().chars().next()?;
+                    Some(Move::Partner(a, b))
+                })
+            })
+            .ok_or_else(|| format_err!("invalid move: {}", value))
+    }
+}
+
+#[test]
+fn test_move_try_from() {
+    assert_eq!(Move::try_from("s1").unwrap(), Move::Spin(1));
+    assert_eq!(Move::try_from("x3/4").unwrap(), Move::Exchange(3, 4));
+    assert_eq!(Move::try_from("pe/b").unwrap(), Move::Partner('e', 'b'));
+}
diff --git a/2017/rust/src/main.rs b/2017/rust/src/main.rs
index 6eb8141..f2f01bf 100644
--- a/2017/rust/src/main.rs
+++ b/2017/rust/src/main.rs
@@ -1,9 +1,11 @@
-#![feature(conservative_impl_trait, inclusive_range_syntax)]
+#![feature(conservative_impl_trait, inclusive_range_syntax, match_default_bindings, slice_rotate,
+           try_from)]
 
 extern crate failure;
 #[macro_use]
 extern crate lazy_static;
 extern crate regex;
+extern crate time;
 
 use std::io::{self, Read};
 
@@ -16,6 +18,7 @@ mod day_04;
 mod day_05;
 mod day_06;
 mod day_15;
+mod day_16;
 
 fn main() {
     if let Err(e) = run() {
@@ -27,7 +30,7 @@ fn run() -> Result<(), Error> {
     let mut input = String::new();
     io::stdin().read_to_string(&mut input)?;
 
-    let solution = day_06::solve(&input)?;
+    let solution = day_16::solve(&input)?;
     println!("{}", solution);
 
     Ok(())