{- stack
--install-ghc
exec ghci
--package lens
-}
module Main where
import Control.Lens
import Data.List.Lens
import Debug.Trace
import Text.Printf
import Prelude hiding (Left, Right)
data Direction = Up | Left | Down | Right
data Location = Location Int Int
type Grid = [[Int]]
main = printClockwise 25
printClockwise :: Int -> IO ()
printClockwise n = putStrLn $ concatMap printRow grid
where
grid = walk directions center 1 emptyGrid
emptyGrid = replicate sq (take sq (repeat 0))
printRow row = concatMap (printf "%4s" . show) row ++ "\n"
-- Ex. for a 5x5 spiral the start location is (2,2)
center = Location half half
half = floor $ (fromIntegral sq) / 2
-- This will return all directions we should walk through the spiral in.
-- Something like [Right, Down, Left, Left, Up, Up, Right, Right, Right]
directions = concatMap (\(direction, steps) -> take steps $ repeat direction) (zip directionOrder steps)
directionOrder = cycle [Right, Down, Left, Up]
-- Ex. for a spiral up to 25, the steps are 1, 1, 2, 2, 3, 3, 4, 4, 5
steps = concatMap (take 2 . repeat) [1 .. sq - 1] <> [sq]
-- Assume the input is a perfect square of an odd number
sq = ceiling $ sqrt (fromIntegral n)
walk :: [Direction] -> Location -> Int -> Grid -> Grid
walk (dir : dirs) loc@(Location x y) current grid = do
let grid' = grid & (ix y . ix x) .~ current
let loc' = moveLocation dir loc
walk dirs loc' (current + 1) grid'
walk [] _ _ numbers = numbers
moveLocation Down (Location x y) = Location (x) (y + 1)
moveLocation Right (Location x y) = Location (x + 1) (y)
moveLocation Left (Location x y) = Location (x -1) (y)
moveLocation Up (Location x y) = Location (x) (y - 1)
#!/usr/bin/env stack
{- stack
--install-ghc
exec ghci
--package lens
-}
module Main where
import Control.Lens
import Data.List.Lens
import Debug.Trace
import Text.Printf
import Prelude hiding (Left, Right)
data Direction = Up | Left | Down | Right
data Location = Location Int Int
type Grid = [[Int]]
main = printClockwise 25
printClockwise :: Int -> IO ()
printClockwise n = putStrLn $ concatMap printRow grid
where
grid = walk directions center 1 emptyGrid
emptyGrid = replicate sq (take sq (repeat 0))
printRow row = concatMap (printf "%4s" . show) row ++ "\n"
-- Ex. for a 5x5 spiral the start location is (2,2)
center = Location half half
half = floor $ (fromIntegral sq) / 2
-- This will return all directions we should walk through the spiral in.
-- Something like [Right, Down, Left, Left, Up, Up, Right, Right, Right]
directions = concatMap (\(direction, steps) -> take steps $ repeat direction) (zip directionOrder steps)
directionOrder = cycle [Right, Down, Left, Up]
-- Ex. for a spiral up to 25, the steps are 1, 1, 2, 2, 3, 3, 4, 4, 5
steps = concatMap (take 2 . repeat) [1 .. sq - 1] <> [sq]
-- Assume the input is a perfect square of an odd number
sq = ceiling $ sqrt (fromIntegral n)
walk :: [Direction] -> Location -> Int -> Grid -> Grid
walk (dir : dirs) loc@(Location x y) current grid = do
let grid' = grid & (ix y . ix x) .~ current
let loc' = moveLocation dir loc
walk dirs loc' (current + 1) grid'
walk [] _ _ numbers = numbers
moveLocation Down (Location x y) = Location (x) (y + 1)
moveLocation Right (Location x y) = Location (x + 1) (y)
moveLocation Left (Location x y) = Location (x -1) (y)
moveLocation Up (Location x y) = Location (x) (y - 1)