あけましておめでとうございます 2011

古来より日本のプログラマの間には、「正月はフラクタル」という風習があります。
フラクタルについて、知識としては知っていても、実際にプログラムを書いたことはない人も結構いると思います。そんなフラクタルに、年に一度くらいは想いを馳せたり、手を動かしたりしてみよう、という風習です (去年の例: (1) (2)) 。
ちなみになぜ正月かと言うと、毎日と毎年が自己相似して末永く平穏に暮らせることを祈念するとか、もちに生えたカビがマンデルブロ集合に見えたとか、門松が L-system を想起させたとか、諸説ありますがわかっていません。

今年はコッホ曲線してみました。難読化などはしませんでした。

R3 = Math.sqrt(3)
AA = " _,_ _,_..,_wypy _,_>qjgrq,gwamg _;_~ypyrrrLmmmy~~~g~qmgrmpgmmmm _,_\
],_..,_4ZZy']/_4]j]/Z/Z44#g'_;_GGpyf{f{mm$$^^^gWN$$##\#$\#@$$```_`\\`_``,_\
kyLy```_N]}gPqPgwa#g`\\[_\\\\\\yFL[[kmmy^^^gNNNNPWP$W@$$'''_']]]'Z[[TZZZ']\
']]]}]7Z7Z#Z#ZFF[[TS5SFF[[M$$$^^^MMNM$MMM$M@$$"

def koch(x0, y0, x4, y4, scr)
  if Math.hypot(x0 - x4, y0 - y4) >= 1
    x1, y1 = (x0 * 2 + x4) / 3, (y0 * 2 + y4) / 3
    x3, y3 = (x0 + x4 * 2) / 3, (y0 + y4 * 2) / 3
    vx, vy = (x4 - x0) / 3, (y4 - y0) / 3
    x2, y2 = (vx + R3 * vy) / 2 + x1, (vy - R3 * vx) / 2 + y1
    a = [[x0, y0], [x1, y1], [x2, y2], [x3, y3], [x4, y4]]
    a.each_cons(2) {|(x0, y0), (x1, y1)| koch(x0, y0, x1, y1, scr) }
  else
    x, y = (x0 + x4) / 2, (y0 + y4) / 2
    scr[y][x] = "1" if (0...158) === x && y < 88
  end
end

def asciiart(scr)
  (0...22).map do |y|
    (0...79).map do |x|
      AA[(0..3).map {|i| scr[y * 4 + i][x * 2, 2] }.join.to_i(2)]
    end.join.rstrip
  end
end

t = Time.now
55.times do |k|
  k = k - 55
  scr = (0...88).map { "0" * 158 }
  koch(-k, (55 + k) * R3, 165.0 + k * 2, 0.0, scr)
  koch(165.0 + k * 2, 0.0, 165.0 + k * 2, (55 + k) * 2 * R3, scr)
  koch(165.0 + k * 2, (55 + k) * 2 * R3, -k, (55 + k) * R3, scr)
  puts "-- koch curve in ascii-art --  (c) Yusuke Endoh 2011", *asciiart(scr)
  s = (t += 0.125) - Time.now
  sleep s if s > 0
end
loop do
  t = Time.now
  110.times do |k|
    k = 109 - k
    scr = (0...88).map { "0" * 158 }
    koch(-k, (55 + k) * R3, 165.0 + k * 2, 0.0, scr)
    puts "-- koch curve in ascii-art --  (c) Yusuke Endoh 2011", *asciiart(scr)
    sleep (t += 0.125) - Time.now
  end
end