Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![feature(try_trait)]
- use std::io::{stdin};
- use std::collections::VecDeque;
- use std::error::Error;
- use std::str::FromStr;
- #[derive(Clone,Copy,PartialEq,Eq,Hash,Debug)]
- enum Command {
- Shuffle(usize),
- Exchange(usize, usize),
- Partner(char, char),
- }
- impl FromStr for Command {
- type Err = Box<Error>;
- fn from_str(input: &str) -> Result<Command, Box<Error>> {
- use Command::*;
- let (cmd, args) = input.split_at(1);
- match cmd.chars().next().ok_or("Empty command")? {
- 's' => args.parse().map_err(|e: ::std::num::ParseIntError| e.into())
- .map(&Shuffle),
- 'x' => {
- let mut iter = args.split('/').map(|x| x.parse::<usize>());
- let i1 = iter.next().ok_or("First arg missing")??;
- let i2 = iter.next().ok_or("Second arg missing")??;
- Ok(Exchange(i1, i2))
- }
- 'p' => {
- let mut chars = args.chars();
- let c1 = chars.next().ok_or("First partner missing")?;
- let c2 = chars.nth(1).ok_or("Second partner missing")?; // first char is gone
- Ok(Partner(c1, c2))
- },
- _ => Err("Unknown command letter")?
- }
- }
- }
- type State = VecDeque<char>;
- fn find_both<T: PartialEq>(slice: &VecDeque<T>, v1: &T, v2: &T) -> Option<(usize, usize)> {
- let mut i1 = None;
- let mut i2 = None;
- for (idx, v) in slice.iter().enumerate() {
- if v == v1 {
- i1 = Some(idx);
- }
- if v == v2 {
- i2 = Some(idx);
- }
- if i1.is_some() && i2.is_some() {
- return Some((i1.unwrap(), i2.unwrap()));
- }
- }
- None
- }
- fn eval_command(state: &mut State, command: &Command) {
- use Command::*;
- match command {
- &Shuffle(n) => {
- for _ in 0..n {
- let e = state.pop_back().expect("Elements should exist");
- state.push_front(e);
- }
- },
- &Exchange(i, j) => { state.swap(i, j); },
- &Partner(ref a, ref b) => {
- let (i1, i2) = find_both(state, a, b).expect("Partners should exist");
- state.swap(i1, i2);
- }
- }
- }
- fn init_state(n: usize) -> State {
- const A_BYTE: u8 = 97;
- let mut ret = VecDeque::with_capacity(n);
- for i in 0..n {
- ret.push_back((A_BYTE + (i as u8)) as char);
- }
- ret
- }
- fn apply_commands(state: &mut State, commands: &Vec<Command>) {
- for command in commands {
- eval_command(state, command);
- }
- }
- fn print_state(state: &State) {
- for c in state {
- print!("{}", c);
- }
- println!("");
- }
- fn cycle_length(state: &mut State, commands: &Vec<Command>) -> usize {
- // After this, `state` is unchanged
- let mut cycle_order = 0;
- let initial = init_state(state.len());
- loop {
- apply_commands(state, commands);
- if cycle_order == 0 {
- print_state(state);
- }
- cycle_order += 1;
- if state == &initial {
- break;
- }
- }
- cycle_order
- }
- fn main() {
- const PERMUTATION_LENGTH: usize = 16;
- const N_DANCES: usize = 1_000_000_000;
- let mut line: String = String::new();
- stdin().read_line(&mut line).expect("Error reading input");
- let mut state = init_state(PERMUTATION_LENGTH);
- let commands: Vec<Command> = line.trim_right().split(',')
- .map(|w| w.parse().expect("Failure parsing command")).collect();
- let order = cycle_length(&mut state, &commands);
- println!("Order of input is {}", order);
- for _ in 0..(N_DANCES % order) {
- apply_commands(&mut state, &commands);
- }
- print_state(&state);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement