The Codewars Sierpinski's Gasket challenge asks us to draw Sierpinski's triangle using the letter "L" and spaces. Per usual I'm trying it in both Python and Haskell; this time I solved it in Python first.
Hea come da spoilers.
def sierpinski(x): """Produce a 'triangle' of Ls, recursively x deep""" if x == 0: return "L" triangle = sierpinski(x - 1) return above(triangle, beside(triangle, triangle)) def above(top, bottom): """Combine the top and bottom triangle text.""" return top + "\n" + bottom def beside(left, right): """Combine left and right triangle text. Assumes left and right strings have same number of newlines. """ def widen_row(x, row): if x <= 0: return row return widen_row(x - 1, row + " ") left_rows = left.split("\n") right_rows = right.split("\n") width = len(left_rows[-1]) combined =  for i in range(len(left_rows)): combined.append( widen_row(width - len(left_rows[i]), left_rows[i]) + " " + right_rows[i]) return "\n".join(combined)
It was fun to allow my Python code to be somewhat influenced by things I've picked up from functional languages. My use of small, internal helper functions and recursively describing a level of the triangle in terms of "above" and "beside" other triangles was heavily influenced by work I've done in Racket.
import Data.List(intercalate) -- | Produce the Sierpinsky Triangle as a string of "L "s sierpinsky :: Integral a => a -> String sierpinsky 0 = "L" sierpinsky x = above triangle $ beside triangle triangle where triangle = sierpinsky $ x - 1 -- | Put one string above another by joining them with a newline above :: String -> String -> String above top bottom = top ++ "\n" ++ bottom -- | Place one string beside another by joining each line with a -- consistant spacing beside :: String -> String -> String beside left right = intercalate "\n" $ zipWith (nextTo width) (lines left) (lines right) where width = length $ last $ lines right nextTo x l r = l ++ replicate (x - (length l)) ' ' ++ " " ++ r
This used the same rough outline as the Python version; the spelling is consistent with that used for the Codewars challenge, not sure it's right though.
It is quite satisfying that the results almost look like descriptions throughout: can you see where it says "lines on the left, with adjusted width, next to lines on the right?"
Haskell continues to require a good deal more mental effort; composing functions is getting easier but still involves a lot of trial and error on my part.
The top Codewars solutions for Python and Haskell implemented the same concept with fewer lines. Worth mulling. In this case I do kind of like expressing the fractal in terms of "above," "beside," and "triangle" rather than the minimalist variable names they tend to favor.