summaryrefslogtreecommitdiff
path: root/3-kyu
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-05-02 19:35:09 +0800
committerMistivia <i@mistivia.com>2025-05-02 19:35:09 +0800
commit90a259febe10fb97b4d2df8aaf1d61a58d733411 (patch)
tree36273a7c706b293d6a6836dcd58e18641a10a2a5 /3-kyu
parent7a4226231cbb0b5c6801431f89f03159e7b9e739 (diff)
make a spiral
Diffstat (limited to '3-kyu')
-rw-r--r--3-kyu/make-a-spiral.hs53
1 files changed, 53 insertions, 0 deletions
diff --git a/3-kyu/make-a-spiral.hs b/3-kyu/make-a-spiral.hs
new file mode 100644
index 0000000..c0e5ec0
--- /dev/null
+++ b/3-kyu/make-a-spiral.hs
@@ -0,0 +1,53 @@
+-- https://www.codewars.com/kata/534e01fbbb17187c7e0000c6
+module Spiral where
+
+setRow :: Int -> (Int, Int) -> [[Int]] -> [[Int]]
+setRow r (from, to) mat = take r mat ++ [set oldRow] ++ drop (r+1) mat
+ where
+ oldRow = head $ drop r mat
+ set row = take from row ++ take (to - from + 1) (repeat 1) ++ drop (to+1) row
+
+setCol :: Int -> (Int, Int) -> [[Int]] -> [[Int]]
+setCol c (from, to) mat =
+ take from mat
+ ++ map (setNth c) (drop from $ take (to+1) mat)
+ ++ drop (to+1) mat
+ where
+ setNth n row = take n row ++ [1] ++ drop (n+1) row
+
+emptySquare :: Int -> [[Int]]
+emptySquare n = take n $ repeat $ take n $ repeat 0
+
+data Direction = DRight | DLeft | DDown | DUp
+
+spiralize :: Int -> [[Int]]
+spiralize n = go (emptySquare n) (0,0) [n-1,n-1,0] n DRight
+ where
+ go mat (x,y) limit prevDelta DRight =
+ if x >= head limit || prevDelta < 2 then mat
+ else go (setRow y (x,head limit) mat)
+ (head limit, y)
+ (tail limit ++ [y+2])
+ (head limit - x)
+ DDown
+ go mat (x,y) limit prevDelta DDown =
+ if y >= head limit || prevDelta < 2 then mat
+ else go (setCol x (y, head limit) mat)
+ (x, head limit)
+ (tail limit ++ [x-2])
+ (head limit - y)
+ DLeft
+ go mat (x,y) limit prevDelta DLeft =
+ if x <= head limit || prevDelta < 2 then mat
+ else go (setRow y (head limit, x) mat)
+ (head limit, y)
+ (tail limit ++ [y-2])
+ (x - head limit)
+ DUp
+ go mat (x,y) limit prevDelta DUp =
+ if y <= head limit || prevDelta < 2 then mat
+ else go (setCol x (head limit, y) mat)
+ (x, head limit)
+ (tail limit ++ [x+2])
+ (y - head limit)
+ DRight