Let's write β

プログラミング中にできたことか、思ったこととか

Syracuseアルゴリズムを可視化したい。

Syracuseアルゴリズム(3x+1問題とも)の可視化というのは色々な方法でおこなわれていてNumoebaなどがそうでしょう。(Numoebaの可視化したもののリンクがどこかにあったはずなのですが、失念してしまいました。どなたかご存知の方がいらっしゃったらコメントください)
アルゴリズムの可視化というのは色々とおもしろそうなので、やってみたのですが、
僕のはどうも綺麗にいきません。辺が重なって見えてしまうのを考慮していないからなのですが...

(defun syracuse (n)
  (if (evenp n)
    (/ n 2)
    (1+ (* 3 n))))

(defun syracuse-list (n)
  (loop for x = n then (syracuse x)
        collect x
        until (= x 1)))

(defun inter (list)
  (mapcar #'cons list (cdr list)))

(defun main (n)
  (let* ((chain (syracuse-list n))
         (connections (inter chain))
         (max-val (apply #'max chain))
         (angle (/ PI max-val)))
    (sdl:with-init ()
           (sdl:window 600 600 :title-caption "Syracuse")
           (sdl:clear-display sdl:*black*)
           (sdl:with-events ()
                (:quit-event ()
                 t)
                (:idle ()
                 ;;Clean Display
                 (sdl:clear-display sdl:*black*)
                 ;;Draw circles
                 (loop for c in chain
                       for arg = (* angle c)
                       do
                       (sdl:draw-circle-* (+ 300 (round (* 200 (cos arg))))
                                          (+ 300 (round (* 200 (sin arg))))
                                          5 
                                          :color sdl:*white*))
                 ;;Draw Connection
                 (loop for con in connections
                       for from = (* angle (car con))
                       for to = (* angle (cdr con))
                       do
                       (sdl:draw-line-*
                         (+ 300 (round (* 200 (cos from))))
                         (+ 300 (round (* 200 (sin from))))
                         (+ 300 (round (* 200 (cos to))))
                         (+ 300 (round (* 200 (sin to))))
                         :color sdl:*white*))
                 (sdl:update-display))))))

こんな感じ

(main 10)

f:id:Pocket7878_dev:20130126085150p:plain