Ёлочка, снова

Дата написания: June 24, 2013

Ёлочка, снова

“Ёлочка” это программа, которая печатает в консоль нечто похожее на ёлку указанной высоты. Выглядит это примерно так:

    *
   ***
  *****
 *******
*********

Ёлочку я пишу на языке, который изучаю. Так было и с Clojure и Haskell.

Моя ёлочка на Clojure получилась как-то так:

(defn pine-tree
  "Ёлочка"
  [x]
  {:pre [(pos? x)]}
  (letfn [(spaces [n] (repeat n " "))
          (stars  [n] (repeat n "*"))
          (row    [n] (concat (spaces (- x n))
                              (stars (+ 1 (* 2 n)))))
          (join-with [ch] (partial clojure.string/join ch))]
    ((join-with "\n")
      (map (join-with "")
           (map row
                (range 0 x))))))

(println (pine-tree 10))

Конечно тут есть и “лишние” элементы - docstring, precondition, но в целом ничего необычного, разве что длинновато.

На Haskell до этого ёлку писал так:

main = putStrLn $ pineTree 10

pineTree x = unlines $ map row ranges
  where
    ranges = zip [x - 1, x - 2..0] [1, 3..]
    stars  = repeat '*'
    spaces = repeat ' '
    row (n, m) = take n spaces ++ take m stars

Вполне читаемо, на мой взгляд!

А тут, ваяя кложурную версию, я подумал, а не запилить ли мне на хаскеле ёлку бесточечно. Удалось не сразу (я всёже не спец в хаскеле), но таки удалось!

pineTree = unlines
         . zipWith (flip (++)) (zipWith take [1,3..] (repeat (repeat '*')))
         . zipWith (flip take) (repeat (repeat ' '))
         . reverse
         . flip ($) [1,2..]
         . take

Чистая композиция! Вот за это haskell и люблю - помогает размять мозги! Само собой, реальные программы пишутся подобно первому варианту ;)

26.06.2013 ещё одна бесточечная ёлочка:

pineTree = unlines
         . takeWhile ((== ' ') . head)
         . iterate ((++ "**") . tail)
         . (++ "*")
         . (flip take) (repeat ' ')