我有一个名为cube的类型,它代表一个物理多维数据集.我编写了一些带有立方体的代码,并生成了多维数据集所有可能方向的列表.
我使用了以下术语,假设立方体在我眼前坐在我面前.
对于立方体的面:
对于轴,立方体可以旋转:
当6个面中的每一个面朝下时,立方体可以以不同的方式(0°,90°,180°和270°)围绕其法线轴旋转.这导致24种可能的取向.
我已经开始使用立方体类型(请原谅S/O的语法着色):
type 'a cube(top:'a, bottom:'a, left:'a, right:'a, front:'a, back:'a) =
member this.Top = top
member this.Bottom = bottom
member this.Left = left
member this.Right = right
member this.Front = front
member this.Back = back
override this.ToString() =
sprintf "Top: %O, Bottom: %O, Left: %O, Right: %O Front: %O, Back: %O" top bottom left right front back
Run Code Online (Sandbox Code Playgroud)
然后我继续编写一个Cube模块,它提供了函数getOrientations.
module Cube =
let rotateNormalRight (c:'a cube) =
cube(c.Top, c.Bottom, c.Back, c.Front, c.Left, c.Right)
let rotateLongitudinalRight (c:'a cube) =
cube(c.Left, c.Right, c.Bottom, c.Top, c.Front, c.Back)
let rotateLongitudinalLeft (c:'a cube) =
cube(c.Right, c.Left, c.Top, c.Bottom, c.Front, c.Back)
let private operations =
[ rotateNormalRight; rotateNormalRight; rotateNormalRight; rotateLongitudinalRight
rotateNormalRight; rotateNormalRight; rotateNormalRight; rotateLongitudinalRight
rotateNormalRight; rotateNormalRight; rotateNormalRight; rotateLongitudinalLeft
rotateNormalRight; rotateNormalRight; rotateNormalRight; rotateLongitudinalLeft
rotateNormalRight; rotateNormalRight; rotateNormalRight; rotateLongitudinalRight
rotateNormalRight; rotateNormalRight; rotateNormalRight ]
let getOrientations startCube =
let rec getCubeInner (ops:('a cube -> 'a cube) list) (cl:'a cube list) =
match ops with
| [] -> cl
| op :: rest -> getCubeInner rest ((cl |> List.hd |> op) :: cl)
getCubeInner operations [startCube]
Run Code Online (Sandbox Code Playgroud)
该模块仅提供三种可能的90度旋转,一个旋转列表,其中每个可能的方向采用立方体,以及一个在给定单个立方体的情况下产生所有方向的函数.
如果我做:
cube(1, 2, 3, 4, 5, 6)
|> Cube.getOrientations
|> List.iter (printfn "%O")
Run Code Online (Sandbox Code Playgroud)
我明白了:
Top: 3, Bottom: 4, Left: 1, Right: 2 Front: 6, Back: 5
Top: 3, Bottom: 4, Left: 6, Right: 5 Front: 2, Back: 1
Top: 3, Bottom: 4, Left: 2, Right: 1 Front: 5, Back: 6
Top: 3, Bottom: 4, Left: 5, Right: 6 Front: 1, Back: 2
Top: 6, Bottom: 5, Left: 3, Right: 4 Front: 1, Back: 2
Top: 6, Bottom: 5, Left: 1, Right: 2 Front: 4, Back: 3
Top: 6, Bottom: 5, Left: 4, Right: 3 Front: 2, Back: 1
Top: 6, Bottom: 5, Left: 2, Right: 1 Front: 3, Back: 4
Top: 2, Bottom: 1, Left: 5, Right: 6 Front: 3, Back: 4
Top: 2, Bottom: 1, Left: 3, Right: 4 Front: 6, Back: 5
Top: 2, Bottom: 1, Left: 6, Right: 5 Front: 4, Back: 3
Top: 2, Bottom: 1, Left: 4, Right: 3 Front: 5, Back: 6
Top: 4, Bottom: 3, Left: 1, Right: 2 Front: 5, Back: 6
Top: 4, Bottom: 3, Left: 5, Right: 6 Front: 2, Back: 1
Top: 4, Bottom: 3, Left: 2, Right: 1 Front: 6, Back: 5
Top: 4, Bottom: 3, Left: 6, Right: 5 Front: 1, Back: 2
Top: 5, Bottom: 6, Left: 4, Right: 3 Front: 1, Back: 2
Top: 5, Bottom: 6, Left: 1, Right: 2 Front: 3, Back: 4
Top: 5, Bottom: 6, Left: 3, Right: 4 Front: 2, Back: 1
Top: 5, Bottom: 6, Left: 2, Right: 1 Front: 4, Back: 3
Top: 1, Bottom: 2, Left: 5, Right: 6 Front: 4, Back: 3
Top: 1, Bottom: 2, Left: 4, Right: 3 Front: 6, Back: 5
Top: 1, Bottom: 2, Left: 6, Right: 5 Front: 3, Back: 4
Top: 1, Bottom: 2, Left: 3, Right: 4 Front: 5, Back: 6
Run Code Online (Sandbox Code Playgroud)
这就是我想要的.但是Cube模块被大量的操作所占据.
是否有更好的方法可以通过更少的操作或完全不同的方法来实现这一目标?
一方面:考虑一下,如果纵向旋转立方体,然后执行其他操作,操作的顺序会更加规则。(变成[长、正常、正常、正常]乘以6)。您可以想象将其压缩为 4 个操作的列表,尤其是在一秒钟内。更重要的是,在该列表迭代 3 次之后,您最终会得到与开始时相同的立方体。
现在,考虑一下您在旋转时看到的每个方向,还有一个“相反”方向。(IE:对于每个方向(U、D、L、R、F、B),都有一个相应的方向(D、U、L、R、B、F)。(想象一下你和一个朋友在外太空,每个向上-向下相对于另一个,并且你们每个人都在立方体的相对侧。)在前 12 个操作中的每一个之后([长向左,正常,正常,正常]乘以 3),最终位于立方体上的三个边你的“顶部”永远不会在“底部”——也就是说,你所看到的和你朋友所看到的之间不会有重叠。如果你的朋友也注意到他所看到的(阅读:如果你添加你的视图和同时的“相反”视图),您将旋转次数减半。
所以(在伪代码中,因为我不知道 F#):
ops = [rotateLongLeft, rotateNormalRight, rotateNormalRight, rotateNormalRight]
for each operation in [ops times 3]:
do the operation
add the orientation
add its opposite
Run Code Online (Sandbox Code Playgroud)
最后,您应该拥有所有 24 个方向。