How to resolve the algorithm Sierpinski triangle step by step in the Haskell programming language
Published on 7 June 2024 03:52 AM
How to resolve the algorithm Sierpinski triangle step by step in the Haskell programming language
Table of Contents
Problem Statement
Produce an ASCII representation of a Sierpinski triangle of order N.
The Sierpinski triangle of order 4 should look like this:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Sierpinski triangle step by step in the Haskell programming language
Haskell Source Code Analysis
Explanation
These Haskell code snippets demonstrate different ways to generate a Sierpinski triangle, a fractal pattern consisting of nested triangles.
Code 1
sierpinski 0 = ["*"]
sierpinski n = map ((space ++) . (++ space)) down ++
map (unwords . replicate 2) down
where down = sierpinski (n - 1)
space = replicate (2 ^ (n - 1)) ' '
sierpinski
function generates the triangle by recursively combining smaller triangles.space
represents the spaces used for indentation based on the level of recursion.- The base case is a single "*".
- Each recursive step generates rows by joining the previous row with spaces (using
map
and(++ space)
), and adding new rows of alternating "* " and spaces.
Code 2
sierpinski :: Int -> [String]
sierpinski 0 = ["▲"]
sierpinski n =
[ flip
intercalate
([replicate (2 ^ (n - 1))] <*> " -"),
(<>) <*> ('+' :)
]
>>= (<$> sierpinski (n - 1))
- This version generates the triangle using a different recursive pattern involving intercalation and string manipulation.
- The base case is a single "▲".
- Each recursive step generates rows by intercalating lines of "-" and "+" with spaces.
Code 3
import Data.Bits ((.&.))
sierpinski n = map row [m, m-1 .. 0] where
m = 2^n - 1
row y = replicate y ' ' ++ concatMap cell [0..m - y] where
cell x | y .&. x == 0 = " *"
| otherwise = " "
- This version uses bitwise operations to generate the pattern.
- The
m
variable represents the number of rows in the triangle. - Each row is generated using
concatMap
to check the bitwise AND of each cell, resulting in a "* *" or " " depending on the result.
Code 4
import Data.List (intersperse)
sierpinski :: Int -> String
sierpinski = fst . foldr spacing ([], []) . rule90 . (2 ^)
where
rule90 = scanl next "*" . enumFromTo 1 . subtract 1
where
next =
const
. ( (zipWith xor . (' ' :))
<*> (<> " ")
)
xor l r
| l == r = ' '
| otherwise = '*'
spacing x (s, w) =
( concat
[w, intersperse ' ' x, "\n", s],
w <> " "
)
- This version generates the triangle using a more functional approach, involving list transformations and recursive folds.
rule90
generates a list of characters using a greedy XOR pattern.spacing
indents each row based on the level of recursion.
Code 5
sierpinski :: Int -> [String]
sierpinski n =
foldr
( \i xs ->
let s = replicate (2 ^ i) ' '
in fmap ((s <>) . (<> s)) xs
<> fmap
( (<>)
<*> (' ' :)
)
xs
)
["*"]
[n - 1, n - 2 .. 0]
- This version generates the triangle by recursively combining smaller triangles with spaces.
- Each recursive step generates rows by adding spaces and joining the previous row.
- The final result is a list of strings, each representing a row of the triangle.
Source code in the haskell programming language
sierpinski 0 = ["*"]
sierpinski n = map ((space ++) . (++ space)) down ++
map (unwords . replicate 2) down
where down = sierpinski (n - 1)
space = replicate (2 ^ (n - 1)) ' '
main = mapM_ putStrLn $ sierpinski 4
import Data.List (intercalate)
sierpinski :: Int -> [String]
sierpinski 0 = ["▲"]
sierpinski n =
[ flip
intercalate
([replicate (2 ^ (n - 1))] <*> " -"),
(<>) <*> ('+' :)
]
>>= (<$> sierpinski (n - 1))
main :: IO ()
main = mapM_ putStrLn $ sierpinski 4
import Data.Bits ((.&.))
sierpinski n = map row [m, m-1 .. 0] where
m = 2^n - 1
row y = replicate y ' ' ++ concatMap cell [0..m - y] where
cell x | y .&. x == 0 = " *"
| otherwise = " "
main = mapM_ putStrLn $ sierpinski 4
import Data.List (intersperse)
-- Top down, each row after the first is an XOR / Rule90 rewrite.
-- Bottom up, each line above the base is indented 1 more space.
sierpinski :: Int -> String
sierpinski = fst . foldr spacing ([], []) . rule90 . (2 ^)
where
rule90 = scanl next "*" . enumFromTo 1 . subtract 1
where
next =
const
. ( (zipWith xor . (' ' :))
<*> (<> " ")
)
xor l r
| l == r = ' '
| otherwise = '*'
spacing x (s, w) =
( concat
[w, intersperse ' ' x, "\n", s],
w <> " "
)
main :: IO ()
main = putStr $ sierpinski 4
sierpinski :: Int -> [String]
sierpinski n =
foldr
( \i xs ->
let s = replicate (2 ^ i) ' '
in fmap ((s <>) . (<> s)) xs
<> fmap
( (<>)
<*> (' ' :)
)
xs
)
["*"]
[n - 1, n - 2 .. 0]
main :: IO ()
main = (putStrLn . unlines . sierpinski) 4
You may also check:How to resolve the algorithm First power of 2 that has leading decimal digits of 12 step by step in the Swift programming language
You may also check:How to resolve the algorithm Radical of an integer step by step in the FreeBASIC programming language
You may also check:How to resolve the algorithm Number names step by step in the Logo programming language
You may also check:How to resolve the algorithm Array length step by step in the Dyalect programming language
You may also check:How to resolve the algorithm Copy a string step by step in the Ada programming language