Я пытаюсь создать то, что, как мне кажется, называется спиралью Улама, с помощью Haskell. Он должен выходить наружу по часовой стрелке:
6 - 7 - 8 - 9
| |
5 0 - 1 10
| | |
4 - 3 - 2 11
|
..15- 14- 13- 12
Для каждого шага, на котором я пытаюсь создать координаты, функции будет присвоено число и возвращены спиральные координаты длины входного числа, например:
mkSpiral 9
> [(0,0),(1,0),(1,-1),(0,-1),(-1,-1),(-1,0),(-1,1),(0,1),(1,1)]
(-1, 1) - (0, 1) - (1, 1)
|
(-1, 0) (0, 0) - (1, 0)
| |
(-1,-1) - (0,-1) - (1,-1)
Я видел решение «Зацикливание по спирали», но оно идет против часовой стрелки, и его входные данные должны соответствовать размеру матрицы.
Я также нашел этот код, который делает то, что Мне нужно, но кажется, что он идет против часовой стрелки, скорее увеличивая, чем шагая вправо, а затем по часовой стрелке :(
type Spiral = Int
type Coordinate = (Int, Int)
-- number of squares on each side of the spiral
sideSquares :: Spiral -> Int
sideSquares sp = (sp * 2) - 1
-- the coordinates for all squares in the given spiral
coordinatesForSpiral :: Spiral -> [Coordinate]
coordinatesForSpiral 1 = [(0, 0)]
coordinatesForSpiral sp = [(0, 0)] ++ right ++ top ++ left ++ bottom
where fixed = sp - 1
sides = sideSquares sp - 1
right = [(x, y) | x <- [fixed], y <- take sides [-1*(fixed-1)..]]
top = [(x, y) | x <- reverse (take sides [-1*fixed..]), y <- [fixed]]
left = [(x, y) | x <- [-1*fixed], y <- reverse(take sides [-1*fixed..])]
bottom = [(x, y) | x <- take sides [-1*fixed+1..], y <- [-1*fixed]]
-- an endless list of coordinates (the complete spiral)
mkSpiral :: Int -> [Coordinate]
mkSpiral x = take x endlessSpiral
endlessSpiral :: [Coordinate]
endlessSpiral = endlessSpiral' 1
endlessSpiral' start = coordinatesForSpiral start ++ endlessSpiral' (start + 1)
После долгих экспериментов мне кажется, что я не могу изменить направление вращения или начального шага, может ли кто-нибудь указать мне правильный путь или решение, которое не использует понимание списка, поскольку я считаю их сложными для декодирования?