You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.2 KiB
Haskell

{- |
Module : Sapin
Description : Print a pine
Copyright : (c) Frédéric BISSON, 2015
License : GPL-3
Maintainer : zigazou@free.fr
Stability : experimental
Portability : POSIX
______________________________
* |
*** This is a stair |
***** |
base ------->*******___________________________|
***** | Branches
******* |
********* This is another stair |
*********** |
base ---->*************________________________|
|||
||| This is the pied
-}
module Main where
import System.Environment (getArgs)
{-|
Draw a pine stair of specific base width and height.
-}
stair :: Int -> Int -> [String]
stair width height =
reverse [ replicate width' '*' | width' <- take height [width, width-2..] ]
{-|
Gives list of the base width of each stair.
Returned list looks something like [7,13,21,29,39,49,61,73,87,101...]
Note:
- [ xx | x <- [6, 8..], xx <- [x, x] ] = [6,6,8,8,10,10,12,12,14,14...]
-}
baseWidths :: [Int]
baseWidths = tail $ scanl (+) 1 [ xx | x <- [6, 8..], xx <- [x, x] ]
{-|
Draws the branches of a pine
-}
branchs :: Int -> [String]
branchs n =
concat [ stair width (i + 3) | (width, i) <- zip baseWidths [1..n] ]
{-|
Draws the pied of a pine
(n + 1 - mod n 2) is a trick to always have an odd number. 1 - n mod 2 =
- 1 if n is even
- 0 if n is odd
-}
pied :: Int -> [String]
pied n = replicate n $ replicate (n + 1 - mod n 2) '|'
{-|
Centers a string according to a width
-}
center :: Int -> String -> String
center width s = replicate (div (width - length s) 2) ' ' ++ s
{-|
Draws a complete (branches and pied) and centered pine
(baseWidths !! (n - 1)) gives the maximum width of the pine (the largest
base width)
-}
sapin :: Int -> [String]
sapin n = concat
$ (fmap . fmap) (center (baseWidths !! (n - 1))) [branchs n, pied n]
{-|
Print a pine
-}
printSapin :: Int -> IO ()
printSapin = mapM_ putStrLn . sapin
main :: IO ()
main = do
arg:_ <- getArgs
printSapin $ read arg