diff --git a/2017/rust/src/day_16.rs b/2017/rust/src/day_16.rs
index 5bd0feb..14d0112 100644
--- a/2017/rust/src/day_16.rs
+++ b/2017/rust/src/day_16.rs
@@ -1,45 +1,82 @@
+use std::collections::HashMap;
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
+ let moves = 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())
-}
+ let programs = (b'a'..=b'p').map(|c| c as char).collect();
+ let dance = Dance { moves, programs };
-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);
+ // dance.next();
+ // Ok(dance.next().unwrap().iter().collect::<String>())
+
+ let history = dance
+ .enumerate()
+ .scan(HashMap::new(), |state, (i, programs)| {
+ if state.contains_key(&programs) {
+ None
+ } else {
+ state.insert(programs, i);
+ Some(state.clone())
}
- 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);
+ })
+ .last()
+ .unwrap();
+ let index = 1_000_000_000 % history.len();
+ Ok(history
+ .iter()
+ .find(|(_, &v)| v == &index)
+ .map(|(k, _)| k)
+ .unwrap()
+ .iter()
+ .collect())
+}
+
+struct Dance {
+ moves: Vec<Move>,
+ programs: Vec<char>,
+}
+
+impl Iterator for Dance {
+ type Item = Vec<char>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let item = self.programs.clone();
+
+ for m in &self.moves {
+ match m {
+ Move::Spin(size) => {
+ let len = self.programs.len();
+ self.programs.rotate(len - size);
+ }
+ Move::Exchange(a, b) => {
+ self.programs.swap(*a, *b);
+ }
+ Move::Partner(a, b) => {
+ let a = self.programs.iter().position(|x| x == a).unwrap();
+ let b = self.programs.iter().position(|x| x == b).unwrap();
+ self.programs.swap(a, b);
+ }
}
}
+
+ Some(item)
}
}
#[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);
+ let programs = (b'a'..=b'e').map(|c| c as char).collect();
+ let mut dance = Dance { moves, programs };
- assert_eq!(programs, vec!['b', 'a', 'e', 'd', 'c']);
+ assert_eq!(dance.next().unwrap(), vec!['a', 'b', 'c', 'd', 'e']);
+ assert_eq!(dance.next().unwrap(), vec!['b', 'a', 'e', 'd', 'c']);
}
#[derive(Debug, Eq, PartialEq)]