kociemba 0.5.1

crate for solving the 3x3 Rubik's cube with Kociemba's two phase algorithm
Documentation
use std::str::FromStr;
use rand::random;

use crate::cubie::CubieCube;
use crate::facelet::FaceCube;
use crate::{error::Error, Move};

pub fn scramble_from_str(s: &str) -> Result<Vec<Move>, Error> {
    s.split_whitespace()
        .map(|word| Move::from_str(word.trim()))
        .collect()
}

pub fn scramble_to_str(s: &Vec<Move>) -> Result<String, Error> {
    let result: String = s
        .iter()
        .map(|m| Move::to_string(m))
        .fold("".to_string(), |acc, x| format!("{} {}", acc, x));
    Ok(result.trim_start().to_string())
}

pub fn gen_scramble(length: usize) -> Result<Vec<Move>, Error> {
    let mut cc = CubieCube::default();
    cc.randomize();
    let fc = FaceCube::try_from(&cc)?;
    let mut ss = "".to_string();
    let mut ps = ' ';
    for s in fc.to_string().chars() {
        if s != ps {
            if ps == ' ' {
                ps = s;
                continue;
            }
            let suffix = match random::<u16>() % 3 {
                0 => "",
                1 => "2",
                _ => "'",
            };
            ss = ss + ps.to_string().as_str() + suffix.to_string().as_str() + " ";
        }
        ps = s;
    }
    let mut scramble = scramble_from_str(&ss)?;
    scramble.truncate(length);
    Ok(scramble)
}

#[cfg(test)]
mod test {
    use crate::moves::Move::*;
    use super::*;

    #[test]
    fn test_scramble_from_str() {
        let m = vec![R, U, R3, U3, F, L3, D3, B2, R3, U3];
        assert_eq!(scramble_from_str("R U R' U' F L' D' B2 R' U'").unwrap(), m);
    }

    #[test]
    fn test_scramble_to_str() {
        let m = vec![R, U, R3, U3, F, L3, D3, B2, R3, U3];
        assert_eq!(scramble_to_str(&m).unwrap(), "R U R' U' F L' D' B2 R' U'");
    }

    #[test]
    fn test_gen_scramble() {
        let ss = gen_scramble(25).unwrap();
        assert_eq!(ss.len(), 25);
    }
}