-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcarpet.hs
52 lines (45 loc) · 1.51 KB
/
carpet.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
module Main where
import System.Environment
import Control.Applicative
import Safe (readMay)
data Size = Size Int Int
type Tile = Bool
type Carpet = [Tile]
-- given width and height as arguments
-- prints an ascii sierpinski carpet
main :: IO ()
main = do
args <- getArgs
if length args /= 2 then
putStrLn "Usage: carpet <width> <height>"
else do
let maybeSize = do
w <- readMay $ head args
h <- readMay $ args !! 1
return $ Size w h
maybeCarpet maybeSize
-- if arguments are valid, create and show carpet
maybeCarpet :: Maybe Size -> IO ()
maybeCarpet Nothing = putStrLn "You've provided an invalid argument"
maybeCarpet (Just s) = showCarpet s $ carpet s
-- prints a carpet to the screen
showCarpet :: Size -> Carpet -> IO ()
showCarpet _ [] = return ()
showCarpet s @ (Size w _) c = do
let (line, rest) = splitAt w c
mapM_ (putChar . showTile) line
putStrLn ""
showCarpet s rest
-- convert Tile to String
showTile :: Tile -> Char
showTile True = '#'
showTile False = ' '
-- create a Carpet of given Size
carpet :: Size -> Carpet
carpet (Size w h) = isInCarpet <$> [1..h] <*> [1..w]
-- check whether a point (x, y) is in the Carpet
isInCarpet :: Int -> Int -> Bool
isInCarpet x y
| x > 0 || y > 0 = not ((x `mod` 3 == 1) && (y `mod` 3 == 1))
&& isInCarpet (x `div` 3) (y `div` 3)
| otherwise = True