如何在Haskell中实现Thistlethwaite的算法?

时间:2015-07-23 09:40:06

标签: algorithm haskell

我正在尝试在Haskell中实现Thistlethwaite的算法,遵循here的描述,但遇到了困难。

到目前为止,我已经成功地表示了立方体,让它随心所欲地移动,并在终端上显示(二维表示),但是当我尝试将一般立方体减少到一个立方体时我遇到了问题通过组中的移动(R,L,F,B,U2,D2)(链接中的符号)从标准立方体获得,因为有太多的情况需要考虑:上层有多少颜色是错误的这个只是描述的第一个阶段,但我发现我的代码已经乱了,所以我一定错过了一些东西。

由于我不确定上面的描述是否清楚,我在下面列出了相关的代码,这些代码不正确,但指出了问题。

--To intersect lists, of which the sizes are not very large, I chose to import the Data.List
import Data.List

--Some type declarations
data Colors = R | B | W | Y | G | O
type R3 = (Int, Int, Int)
type Cube = R3 -> Colors
points :: [R3] --list of coordinates of facelets of a cube; there are 48 of them.
mU :: Cube -> Cube --and other 5 moves.
type Actions = [Cube -> Cube]
turn :: Cube -> Actions -> Cube --chains the actions and turns the cube.
edges :: [R3] --The edges of cubes

criterion :: Colors -> R3 -> Bool -- determine if the edges are mis-placed.
criterion co p@(x, y, z) = case co of --W and Y are up and down faces respectively.
 R -> not (or [abs(x) == 3, abs(y) == 3])
 B -> not (or [abs(y) == 3, abs(z) == 3])
 O -> not (or [abs(x) == 3, abs(y) == 3])
 G -> not (or [abs(y) == 3, abs(z) == 3])
 _ -> True


stage1 :: Cube -> Cube 
stage1 c = turn c opes where
    wrongs = do
            res <- [[]]
            eg <- edges
            if criterion (c eg) eg
              then res
              else res ++ [eg]
    ups = filter (\(x, y, z) -> y == 3) points
    downs = filter (\(x, y, z) -> y == -3) points
    middles = filter (\(x, y, z) -> y == 0) points
    opes = do
         res <- [[]]
         case length (intersect middles wrongs) of
         0 -> case [length (intersect ups wrongs) == 0, length (intersect downs wrongs) == 0] of
            [True, True] -> res
            [True, False] -> [mD] --A quarter turn of the downside of the cube.
            [False, True] -> [mU]
            _ -> [mD, mU]
         1 -> let [(x, y, z)] = intersect middles wrongs in
                if x == 3 then case [length (intersect ups wrongs) == 0, length (intersect downs wrongs) == 0] of
                    [True, True] -> if z > 0 then [mR, mU] else [mR, mD]
                    [True, False] -> if z > 0 then [mD, mR, mU] else [mD, mR, mD]
                    [False, True] -> if z > 0 then [mU, mR, mU] else [mU, mR, mD]
                    _ -> if z > 0 then [mD, mU, mR, mU] else [mD, mU, mR, mD]
                else []

然后我意识到上面的代码是错的,因为我不能简单地做一个四分之一转U或D,这使得正确的边缘(如果有的话)变得不正确,我将根据如何讨论125 = 5 * 5 * 5的情况在立方体的三个层中的每个层上都有许多错误的边缘,我认为这不是“正确的”。

所以我的问题是如何以一种很好的方式实现一个可以处理这么多案例的算法?

如果有关于描述的内容不清楚,请告诉我,以便我可以解释我在做什么以及我的问题是什么。

非常感谢任何想法和建议,非常感谢。

P.S。我最初想要实现Korf或Kociemba的算法,但事实证明我甚至无法处理最简单的情况。

1 个答案:

答案 0 :(得分:1)

有一件事 - 这段代码:

wrongs = do
        res <- [[]]
        eg <- edges
        if criterion (c eg) eg
          then res
          else res ++ [eg]

最好写成filter (\eg -> not (criterion (c eg) eg)) edges