Skip to main content

rcuber/solver/lbl/
eoll.rs

1use crate::cubie::Edge::{self, *};
2use crate::solver::lbl::get_put_move;
3use crate::{
4    cubie::CubieCube,
5    moves::Move::{self, *},
6};
7
8/// EOLLSolver for LBL(Layer by Layer) method, i.e, solve edge orientation of last layer's four edges(UR, UF, UL, UB).
9/// # Example
10/// ```rust
11/// use rcuber::cubie::CubieCube;
12/// use rcuber::moves::Formula;
13/// use rcuber::solver::lbl::cross::CrossSolver;
14/// use rcuber::solver::lbl::bottom::BottomCornerSolver;
15/// use rcuber::solver::lbl::middle::MiddleEdgeSolver;
16/// use rcuber::solver::lbl::eoll::EOLLSolver;
17///
18/// fn main() {
19///     let cc = CubieCube::default();
20///     let moves = Formula::scramble();
21///     let cc = cc.apply_formula(&moves);
22///     let mut cross = CrossSolver::new(cc, true);
23///     let _cs = cross.solve();
24///     let mut bottom = BottomCornerSolver { cube: cross.cube };
25///     let _bs = bottom.solve();
26///     assert!(bottom.is_solved());
27///     // let _bs = optimise_moves(&_bs);
28///     let mut middle = MiddleEdgeSolver { cube: bottom.cube };
29///     let _ms = middle.solve();
30///     assert!(middle.is_solved());
31///     // let _ms = optimise_moves(&_ms);
32///     let mut eoll = EOLLSolver { cube: middle.cube };
33///     let _eos = eoll.solve();
34///     assert!(eoll.is_solved());
35///     println!(
36///         "Scramble: {:?}\nSolution: {:?}, {:?}, {:?}, {:?}",
37///         moves, _cs, _bs, _ms, _eos
38///     );
39/// }
40/// ```
41pub struct EOLLSolver {
42    pub cube: CubieCube,
43}
44
45impl EOLLSolver {
46    /// Solve the edge orientation of last layer edges(UR, UF, UL, UB).
47    pub fn solve(&mut self) -> Vec<Move> {
48        let mut solution = Vec::new();
49        let case = self.recognise();
50        if case == 0 {
51            return solution;
52        } else if case == 4 {
53            let solution = vec![F, R, U, R3, U3, R, U, R3, U3, F3, U3, F, R, U, R3, U3, F3];
54            self.cube = self.cube.apply_moves(&solution);
55            return solution;
56        } else {
57            for i in 0..4 {
58                let u_cube = self.cube;
59                let mut u_put = get_put_move(i, U);
60                self.cube = self.cube.apply_moves(&u_put);
61                for mut _s in [
62                    vec![F, R, U, R3, U3, F3],
63                    vec![F, R, U, R3, U3, F3, U3, F, R, U, R3, U3, F3],
64                ] {
65                    let s_cube = self.cube;
66                    self.cube = self.cube.apply_moves(&_s);
67                    if self.is_solved() {
68                        solution.append(&mut u_put);
69                        solution.append(&mut _s);
70                        return solution;
71                    }
72                    self.cube = s_cube;
73                }
74                self.cube = u_cube;
75            }
76        }
77        solution
78    }
79
80    fn recognise(&self) -> u8 {
81        let edges_u = get_edges_u(&self.cube);
82        edges_u.iter().fold(0, |acc, e| acc + e.2)
83    }
84
85    /// Check if the last layer's edge orientation is solved.
86    pub fn is_solved(&self) -> bool {
87        self.recognise() == 0
88    }
89}
90
91pub fn get_edges_u(cc: &CubieCube) -> Vec<(Edge, u8, u8)> {
92    let mut edges = Vec::new();
93    for edge in [UR, UF, UL, UB] {
94        for i in 0..12 {
95            if cc.ep[i] == edge {
96                edges.push((edge, i as u8, cc.eo[i]));
97            }
98        }
99    }
100    edges
101}
102
103#[cfg(test)]
104mod tests {
105    use crate::{
106        cubie::CubieCube,
107        moves::Formula,
108        solver::lbl::{
109            bottom::BottomCornerSolver, cross::CrossSolver, eoll::EOLLSolver,
110            middle::MiddleEdgeSolver,
111        },
112    };
113
114    #[test]
115    fn test_eoll() {
116        let cc = CubieCube::default();
117        let moves =Formula::scramble();
118        let cc = cc.apply_formula(&moves);
119        let mut cross = CrossSolver::new(cc, true);
120        let _cs = cross.solve();
121        let mut bottom = BottomCornerSolver { cube: cross.cube };
122        let _bs = bottom.solve();
123        assert!(bottom.is_solved());
124        // let _bs = optimise_moves(&_bs);
125        let mut middle = MiddleEdgeSolver { cube: bottom.cube };
126        let _ms = middle.solve();
127        assert!(middle.is_solved());
128        // let _ms = optimise_moves(&_ms);
129        let mut eoll = EOLLSolver { cube: middle.cube };
130        let _eos = eoll.solve();
131        assert!(eoll.is_solved());
132        println!(
133            "Scramble: {:?}\nSolution: {:?}, {:?}, {:?}, {:?}",
134            moves, _cs, _bs, _ms, _eos
135        );
136    }
137}