From 71511536a94f36b2311dcd635afbaa9e179d0b99 Mon Sep 17 00:00:00 2001 From: Trashtalk Date: Fri, 3 Jul 2020 23:24:55 +0200 Subject: [PATCH 1/5] first working version --- contents/IFS/code/clisp/ifs.lisp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 contents/IFS/code/clisp/ifs.lisp diff --git a/contents/IFS/code/clisp/ifs.lisp b/contents/IFS/code/clisp/ifs.lisp new file mode 100644 index 000000000..e1700d4f3 --- /dev/null +++ b/contents/IFS/code/clisp/ifs.lisp @@ -0,0 +1,28 @@ +;;;; Iterated Function System implementation + +(defstruct (point (:constructor make-point (x y))) x y) + +;; not a very good function some tail-end recursion would be kinda sexy here +(defun chaos-game (n shape-points) + (loop + with point = (make-point (random 1.0) (random 1.0)) + with result = (list) + for i from 1 to n do + (push point result) + (let ((rand-point (aref shape-points (random (length shape-points))))) + (setf point + (make-point + (* 0.5 (+ (point-x rand-point) (point-x point))) + (* 0.5 (+ (point-y rand-point) (point-y point)))))) + finally (return result))) + +(defparameter *shape-points* + (map + 'vector + (lambda (e) (apply #'make-point e)) + `((0 0) (0.5 ,(sqrt 0.75)) (1 0)))) ; this is basically magic + +(with-open-file (out "out.dat" :direction :output :if-exists :supersede) + (flet ((format-point (p) + (format nil "~f~c~f" (point-x p) #\tab (point-y p)))) ; this is a bit ugly, but it works + (format out "~{~a~%~}" (map 'list #'format-point (chaos-game 1000 *shape-points*))))) From f233beb9d6c585bc54426789ac73941a45afd0e0 Mon Sep 17 00:00:00 2001 From: Trashtalk Date: Sat, 4 Jul 2020 13:11:29 +0200 Subject: [PATCH 2/5] cleaned up the chaos-game function and added some helpfull comments --- contents/IFS/code/clisp/ifs.lisp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/contents/IFS/code/clisp/ifs.lisp b/contents/IFS/code/clisp/ifs.lisp index e1700d4f3..bd94be55a 100644 --- a/contents/IFS/code/clisp/ifs.lisp +++ b/contents/IFS/code/clisp/ifs.lisp @@ -2,27 +2,25 @@ (defstruct (point (:constructor make-point (x y))) x y) -;; not a very good function some tail-end recursion would be kinda sexy here -(defun chaos-game (n shape-points) +(defun chaos-game (iterations shape-points) (loop - with point = (make-point (random 1.0) (random 1.0)) - with result = (list) - for i from 1 to n do - (push point result) - (let ((rand-point (aref shape-points (random (length shape-points))))) - (setf point - (make-point - (* 0.5 (+ (point-x rand-point) (point-x point))) - (* 0.5 (+ (point-y rand-point) (point-y point)))))) - finally (return result))) + repeat iterations + for rand-point = (svref shape-points (random (length shape-points))) + for point = (make-point (random 1.0) (random 1.0)) ; starting point + then (make-point + (* 0.5 (+ (point-x rand-point) (point-x point))) + (* 0.5 (+ (point-y rand-point) (point-y point)))) ; every subsequent point + collect point)) (defparameter *shape-points* (map 'vector (lambda (e) (apply #'make-point e)) - `((0 0) (0.5 ,(sqrt 0.75)) (1 0)))) ; this is basically magic + ;; the backquote allows us to selectively evaluate (sqrt 0.75) with the comma + `((0 0) (0.5 ,(sqrt 0.75)) (1 0)))) +;; output the data to the "out.dat" file (with-open-file (out "out.dat" :direction :output :if-exists :supersede) (flet ((format-point (p) (format nil "~f~c~f" (point-x p) #\tab (point-y p)))) ; this is a bit ugly, but it works - (format out "~{~a~%~}" (map 'list #'format-point (chaos-game 1000 *shape-points*))))) + (format out "~{~a~%~}" (map 'list #'format-point (chaos-game 1000000 *shape-points*))))) From 1cdbf03e97c993dd69d9d3a1386cc291238ed2f3 Mon Sep 17 00:00:00 2001 From: Trashtalk Date: Sat, 4 Jul 2020 13:39:59 +0200 Subject: [PATCH 3/5] changed the .md file and upped iterations --- contents/IFS/IFS.md | 4 ++++ contents/IFS/code/clisp/ifs.lisp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/contents/IFS/IFS.md b/contents/IFS/IFS.md index 93c2d241f..ae32d5aaa 100644 --- a/contents/IFS/IFS.md +++ b/contents/IFS/IFS.md @@ -134,6 +134,8 @@ Here, instead of tracking children of children, we track a single individual tha [import:5-12, lang:"python"](code/python/IFS.py) {% sample lang="c" %} [import:18-29, lang:"c"](code/c/IFS.c) +{% sample lang="lisp" %} +[import:5-13, lang:"lisp"](code/clisp/ifs.lisp) {% endmethod %} If we set the initial points to the on the equilateral triangle we saw before, we can see the Sierpinski triangle again after a few thousand iterations, as shown below: @@ -203,6 +205,8 @@ In addition, we have written the chaos game code to take in a set of points so t [import, lang:"python"](code/python/IFS.py) {% sample lang="c" %} [import, lang:"c"](code/c/IFS.c) +{% sample lang="lisp" %} +[import, lang:"lisp"](code/clisp/ifs.lisp) {% endmethod %} ### Bibliography diff --git a/contents/IFS/code/clisp/ifs.lisp b/contents/IFS/code/clisp/ifs.lisp index bd94be55a..21c89b0bd 100644 --- a/contents/IFS/code/clisp/ifs.lisp +++ b/contents/IFS/code/clisp/ifs.lisp @@ -23,4 +23,4 @@ (with-open-file (out "out.dat" :direction :output :if-exists :supersede) (flet ((format-point (p) (format nil "~f~c~f" (point-x p) #\tab (point-y p)))) ; this is a bit ugly, but it works - (format out "~{~a~%~}" (map 'list #'format-point (chaos-game 1000000 *shape-points*))))) + (format out "~{~a~%~}" (map 'list #'format-point (chaos-game 10000 *shape-points*))))) From adc22946a2712f560c43655090b9a2fdfb026980 Mon Sep 17 00:00:00 2001 From: Trashtalk Date: Sun, 27 Dec 2020 19:14:14 +0100 Subject: [PATCH 4/5] Skeleton of the final solution --- contents/IFS/code/clisp/ifs.lisp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contents/IFS/code/clisp/ifs.lisp b/contents/IFS/code/clisp/ifs.lisp index 21c89b0bd..4354ab54b 100644 --- a/contents/IFS/code/clisp/ifs.lisp +++ b/contents/IFS/code/clisp/ifs.lisp @@ -3,6 +3,7 @@ (defstruct (point (:constructor make-point (x y))) x y) (defun chaos-game (iterations shape-points) + "Plays a chaos game with a certain shape for a determined amount of iterations" (loop repeat iterations for rand-point = (svref shape-points (random (length shape-points))) @@ -22,5 +23,6 @@ ;; output the data to the "out.dat" file (with-open-file (out "out.dat" :direction :output :if-exists :supersede) (flet ((format-point (p) - (format nil "~f~c~f" (point-x p) #\tab (point-y p)))) ; this is a bit ugly, but it works + ;; this is not very clean, but it's the simplest way to insert a tab into a string. + (format nil "~f~c~f" (point-x p) #\tab (point-y p)))) (format out "~{~a~%~}" (map 'list #'format-point (chaos-game 10000 *shape-points*))))) From 68cf274d58ca25933330458d7a89f506b014737d Mon Sep 17 00:00:00 2001 From: James Schloss Date: Thu, 16 Sep 2021 01:27:32 +0900 Subject: [PATCH 5/5] Update contents/IFS/IFS.md Co-authored-by: Eric Berquist --- contents/IFS/IFS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/IFS/IFS.md b/contents/IFS/IFS.md index ae32d5aaa..526ea8abd 100644 --- a/contents/IFS/IFS.md +++ b/contents/IFS/IFS.md @@ -135,7 +135,7 @@ Here, instead of tracking children of children, we track a single individual tha {% sample lang="c" %} [import:18-29, lang:"c"](code/c/IFS.c) {% sample lang="lisp" %} -[import:5-13, lang:"lisp"](code/clisp/ifs.lisp) +[import:5-14, lang:"lisp"](code/clisp/ifs.lisp) {% endmethod %} If we set the initial points to the on the equilateral triangle we saw before, we can see the Sierpinski triangle again after a few thousand iterations, as shown below: