twisted 0.1.3

A speedcubing and smart-cube library.
Documentation
// SPDX-FileCopyrightText: 2022 Declan Rixon <twisted.cubing@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-only

use crate::cube::{Face, Move};

pub fn string_from_moves(moves: &Vec<Move>) -> String {
    moves
        .iter()
        .map(|m| format!("{}", m))
        .collect::<Vec<String>>()
        .join(" ")
}

pub fn move_from_str(mv: &str) -> Option<Move> {
    let chars = mv.chars().collect::<Vec<char>>();
    let face = match chars.first()? {
        'U' => Some(Face::U),
        'D' => Some(Face::D),
        'F' => Some(Face::F),
        'B' => Some(Face::B),
        'R' => Some(Face::R),
        'L' => Some(Face::L),
        _ => None,
    }?;
    let (turn_chars, direction) = if *chars.last()? == '\'' {
        (chars.get(1..(chars.len() - 1))?, -1)
    } else {
        (chars.get(1..chars.len())?, 1)
    };
    let amount = direction
        * if turn_chars.len() == 0 {
            1
        } else {
            turn_chars.iter().collect::<String>().parse::<i32>().ok()?
        };
    Some(Move { face, amount })
}

pub fn moves_from_str(moves: &str) -> Vec<Move> {
    moves
        .split(' ')
        .flat_map(|mv| move_from_str(mv))
        .collect::<Vec<Move>>()
}

pub fn invert_even_primes(moves: &Vec<Move>) -> Vec<Move> {
    let mut new: Vec<Move> = vec![];
    for mv in moves {
        new.push(if mv.amount % 2 == 0 && mv.amount < 0 {
            Move {
                face: mv.face,
                amount: -mv.amount,
            }
        } else {
            *mv
        })
    }
    new
}

pub fn collect_moves_negating(moves: &Vec<Move>) -> Vec<Move> {
    let mut collected: Vec<Move> = vec![];
    for mv in moves {
        match &mut collected[..] {
            [.., a] if a.face == mv.face => {
                a.amount += mv.amount;
            }
            [.., b, a] if a.face.opposite() == mv.face && b.face == mv.face => {
                b.amount += mv.amount;
            }
            _ => {
                collected.push(*mv);
            }
        }
        collected.retain(|m| m.amount != 0);
    }
    collected
}

pub fn collect_moves(moves: &Vec<Move>) -> Vec<Move> {
    let mut collected: Vec<Move> = vec![];
    for mv in moves {
        match &mut collected[..] {
            [.., a] if a.face == mv.face && a.amount.signum() == mv.amount.signum() => {
                a.amount += mv.amount;
            }
            [.., b, a]
                if a.face.opposite() == mv.face
                    && b.face == mv.face
                    && b.amount.signum() == mv.amount.signum() =>
            {
                b.amount += mv.amount;
            }
            _ => {
                collected.push(*mv);
            }
        }
    }
    collected
}