packages feed

diagrams-cairo-0.3: example/triangular-numbers.hs

{-# LANGUAGE NoMonomorphismRestriction #-}

-- Diagrams created for blog post at
--   http://mathlesstraveled.com/2011/04/14/triangular-number-equations-via-pictures-solutions/

import Diagrams.Prelude
import Diagrams.Backend.Cairo.CmdLine

import Data.Colour hiding (atop)

type D = Diagram Cairo R2

tri c n = dots `atop` (strokeT edges # lc c # lw 0.2 # fcA (c `withOpacity` 0.5))
  where rows = map (hcat' with { sep = 1 })
             . zipWith replicate [n,n-1..1]
             . repeat
             $ dot c
        dots = decorateTrail (rotateBy (1/6) edge) rows
        edge = fromOffsets . replicate (n-1) $ unitX # scale 3
        edges = close (edge <> rotateBy (1/3) edge <> rotateBy (2/3) edge)

dot c = unitCircle
      # lw 0
      # fc c

rowSpc = height (rotateBy (1/6) $ strutY 1 :: D)

-- @row k n s c@ draws a row of k size-n triangles with color c,
-- separated by enough space for @s@ dots.
row k n s c = hcat' with {sep = 1 + 3*s} (replicate k (tri c n))

-- 3 T(n) + T(n-1) = T(2n)
law1 n c1 c2 = law3 1 n c1 c2

-- 3T(n) + T(n+1) = T(2n+1)
law2 n c1 c2 = top === strutY rowSpc === (base `atop` mid)
  where base = row 2 n 1 c1
             # centerX
             # alignB
        mid  = row 1 n 0 c1
             # reflectY
             # centerX
             # alignB
        top  = tri c2 (n+1)
             # centerX

-- (2k+1)T(n) + T(kn - 1) = T((k+1)n)
law3 k n c1 c2 = top === strutY rowSpc === (mid `atop` base)
  where base = row (k+1) n 0 c1 # centerX
                                # alignB
        mid  = row k n 0 c1 # reflectY
                            # centerX
                            # alignB
                            # translateY (2 + rowSpc)
        top  = tri c2 (k*n - 1) # centerX

-- T(n) T(k) + T(n-1) T(k-1) = T(nk)
law4 k n c1 c2 = vcat' with {sep = rowSpc} (map tRow [1..k])
  where tRow k = (row k n 0 c1 # centerX # alignT)
                `atop`
                 (row (k-1) (n-1) 1 c2 # reflectY # centerX # alignT)

exampleRow f = hcat' with {sep = 4} . map (alignB . f)

law1Dia = exampleRow law1' [2..4]
  where law1' n = law1 n blue red

law2Dia = exampleRow law2' [1..3]
  where law2' n = law2 n green orange

law3Dia = exampleRow law3' [1..3]
  where law3' k = law3 k 2 saddlebrown gray

law4Dia = exampleRow law4' [2..4]
  where law4' k = law4 k 3 purple gold

main = defaultMain (pad 1.05 $ vcat' with {sep=5} . map centerXY $
                             [law1Dia -- , law2Dia, law3Dia, law4Dia
                             ])