Browse code
chore: add new demos
Ed Langley authored on 20/11/2019 18:32:16
Showing 11 changed files
Showing 11 changed files
- asdf-advice.lisp
- asdf-translation.lisp
- bodge-like.lisp
- condorcet.lisp
- docstrings.lisp
- graphql.lisp
- paredit.lisp
- password-gen.lisp
- recursion-schemes.lisp
- sqlite-environment.lisp
- triangle.lisp
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,11 @@ |
1 |
+(progn |
|
2 |
+ (defparameter *loads* ()) |
|
3 |
+ (defparameter *load-depth* 0) |
|
4 |
+ (ccl:advise asdf:operate |
|
5 |
+ (let ((current-load (list))) |
|
6 |
+ (incf *load-depth*) |
|
7 |
+ (push (cons *load-depth* arglist) |
|
8 |
+ *loads*) |
|
9 |
+ (unwind-protect (:do-it) |
|
10 |
+ (decf *load-depth*))) |
|
11 |
+ :when :around)) |
0 | 12 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,48 @@ |
1 |
+(defun homedir-translation (input dd) |
|
2 |
+ (declare (ignore dd)) |
|
3 |
+ (merge-pathnames |
|
4 |
+ (make-pathname :directory |
|
5 |
+ (list* :relative |
|
6 |
+ "build-cache" |
|
7 |
+ "homedir" |
|
8 |
+ (cdr |
|
9 |
+ (pathname-directory |
|
10 |
+ (parse-namestring |
|
11 |
+ (enough-namestring input |
|
12 |
+ (user-homedir-pathname)))))) |
|
13 |
+ :defaults input) |
|
14 |
+ (merge-pathnames "asdf-corral/Contents/Resources/" |
|
15 |
+ (user-homedir-pathname)))) |
|
16 |
+ |
|
17 |
+(defun do-translation (input dd) |
|
18 |
+ (declare (ignore dd)) |
|
19 |
+ (merge-pathnames |
|
20 |
+ (make-pathname :directory |
|
21 |
+ (list :relative |
|
22 |
+ "build-cache" |
|
23 |
+ "root" |
|
24 |
+ (format nil "~{~a~^-~}"(cdr (pathname-directory input)))) |
|
25 |
+ :defaults input) |
|
26 |
+ (merge-pathnames "asdf-corral/Contents/Resources/" |
|
27 |
+ (user-homedir-pathname)))) |
|
28 |
+ |
|
29 |
+(defun in-homedir () |
|
30 |
+ (merge-pathnames (make-pathname :directory (list :relative :wild-inferiors) |
|
31 |
+ :name :wild |
|
32 |
+ :type :wild |
|
33 |
+ :version :wild) |
|
34 |
+ (user-homedir-pathname))) |
|
35 |
+ |
|
36 |
+(asdf:initialize-output-translations |
|
37 |
+ `(:output-translations |
|
38 |
+ :ignore-inherited-configuration |
|
39 |
+ :disable-cache |
|
40 |
+ (,(in-homedir) (:function homedir-translation)) |
|
41 |
+ ("/" (:function do-translation)))) |
|
42 |
+ |
|
43 |
+(load "~/quicklisp/setup.lisp") |
|
44 |
+ |
|
45 |
+(eval-when (:compile-toplevel :load-toplevel :execute) |
|
46 |
+ (trace homedir-translation do-translation)) |
|
47 |
+ |
|
48 |
+(ql:quickload :data-lens) |
0 | 49 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,142 @@ |
1 |
+(defpackage :fwoar.bodge-like |
|
2 |
+ (:use :cl ) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :fwoar.bodge-like) |
|
5 |
+ |
|
6 |
+(defclass feature () |
|
7 |
+ ((%sym :reader sym :initarg sym))) |
|
8 |
+ |
|
9 |
+(defclass monster (feature) |
|
10 |
+ ((%position :accessor pos :initform (gamekit:vec2 (random 12) |
|
11 |
+ (random 12))))) |
|
12 |
+ |
|
13 |
+(defclass dog (monster) |
|
14 |
+ () |
|
15 |
+ (:default-initargs sym "d")) |
|
16 |
+ |
|
17 |
+(defun monster (sym) |
|
18 |
+ (make-instance 'monster 'sym sym)) |
|
19 |
+ |
|
20 |
+(defclass player (feature) |
|
21 |
+ ((%position :accessor pos :initform (gamekit:vec2 0 0))) |
|
22 |
+ (:default-initargs sym "@")) |
|
23 |
+ |
|
24 |
+(defparameter *white* (gamekit:vec4 1 1 1 1)) |
|
25 |
+(defparameter *black* (gamekit:vec4 0 0 0 0.8)) |
|
26 |
+(defparameter *tile-size* 32) |
|
27 |
+ |
|
28 |
+(gamekit:defgame bodgelike () |
|
29 |
+ ((%player :reader player :initform (make-instance 'player)) |
|
30 |
+ (%monsters :accessor monsters :initform ())) |
|
31 |
+ (:viewport-title "@") |
|
32 |
+ (:viewport-height (* 12 *tile-size*)) |
|
33 |
+ (:viewport-width (* 12 *tile-size*))) |
|
34 |
+ |
|
35 |
+(defun draw-tile (row col &optional (size *tile-size*)) |
|
36 |
+ (gamekit:draw-rect (gamekit:vec2 (* row size) |
|
37 |
+ (* col size)) |
|
38 |
+ size size |
|
39 |
+ :fill-paint *black*)) |
|
40 |
+ |
|
41 |
+(defvar *my-font*) |
|
42 |
+(defun draw-feature (feature &optional pos (tile-size *tile-size*)) |
|
43 |
+ (let* ((pos (if pos |
|
44 |
+ pos |
|
45 |
+ (pos feature))) |
|
46 |
+ (row (gamekit:x pos)) |
|
47 |
+ (col (gamekit:y pos)) |
|
48 |
+ (tile-origin (gamekit:vec2 (* row tile-size) |
|
49 |
+ (* col tile-size))) |
|
50 |
+ (feature-text (etypecase feature |
|
51 |
+ (string feature) |
|
52 |
+ (feature (sym feature))))) |
|
53 |
+ (multiple-value-bind (text-origin text-width text-height) |
|
54 |
+ (gamekit:calc-text-bounds feature-text *my-font*) |
|
55 |
+ (let ((text-origin |
|
56 |
+ (gamekit:add tile-origin |
|
57 |
+ (gamekit:mult -1 text-origin) |
|
58 |
+ (gamekit:mult 0.5 |
|
59 |
+ (gamekit:subt (gamekit:vec2 tile-size tile-size) |
|
60 |
+ (gamekit:vec2 text-width text-height)))))) |
|
61 |
+ (gamekit:draw-text feature-text text-origin |
|
62 |
+ :fill-color *white* |
|
63 |
+ :font *my-font*))))) |
|
64 |
+ |
|
65 |
+ |
|
66 |
+(gamekit:define-font :fantasy "/tmp/foo/font.ttf") |
|
67 |
+ |
|
68 |
+ |
|
69 |
+(defgeneric interact2 (game obj1 obj2) |
|
70 |
+ (:method (game obj1 obj2) nil) |
|
71 |
+ (:method (game obj1 obj2) t) |
|
72 |
+ (:method (game (obj1 player) (obj2 dog)) |
|
73 |
+ (format t "~&Ruff! ~s~%" (gamekit:subt (pos obj2) |
|
74 |
+ (pos obj1))) |
|
75 |
+ (setf (pos obj2) |
|
76 |
+ (gamekit:add (pos obj2) |
|
77 |
+ (gamekit:subt (pos obj2) |
|
78 |
+ (pos obj1)))) |
|
79 |
+ nil)) |
|
80 |
+ |
|
81 |
+(defun find-in-space (pos obj-list) |
|
82 |
+ (find pos obj-list |
|
83 |
+ :key 'pos |
|
84 |
+ :test 'bodge-math:vec=)) |
|
85 |
+ |
|
86 |
+(defun update (thing fun &rest args) |
|
87 |
+ (apply fun thing args)) |
|
88 |
+ |
|
89 |
+(define-modify-macro updatef (fun &rest args) |
|
90 |
+ update) |
|
91 |
+ |
|
92 |
+(defun move-handler (delta) |
|
93 |
+ (lambda (game player) |
|
94 |
+ (updatef (pos player) |
|
95 |
+ (lambda (old-pos) |
|
96 |
+ (let* ((new-pos (gamekit:add old-pos delta)) |
|
97 |
+ (feature-in-space (find-in-space new-pos (monsters game)))) |
|
98 |
+ (if (and feature-in-space (interact2 game player feature-in-space)) |
|
99 |
+ old-pos |
|
100 |
+ new-pos))))) ) |
|
101 |
+ |
|
102 |
+(defun move-left (game player) |
|
103 |
+ (let ((handler (move-handler (gamekit:vec2 -1 0)))) |
|
104 |
+ (lambda () |
|
105 |
+ (funcall handler game player)))) |
|
106 |
+ |
|
107 |
+(defun move-right (game player) |
|
108 |
+ (let ((handler (move-handler (gamekit:vec2 1 0)))) |
|
109 |
+ (lambda () |
|
110 |
+ (funcall handler game player)))) |
|
111 |
+ |
|
112 |
+(defun move-up (game player) |
|
113 |
+ (let ((handler (move-handler (gamekit:vec2 0 1)))) |
|
114 |
+ (lambda () |
|
115 |
+ (funcall handler game player)))) |
|
116 |
+ |
|
117 |
+(defun move-down (game player) |
|
118 |
+ (let ((handler (move-handler (gamekit:vec2 0 -1)))) |
|
119 |
+ (lambda () |
|
120 |
+ (funcall handler game player)))) |
|
121 |
+ |
|
122 |
+ |
|
123 |
+(defmethod gamekit:post-initialize ((game bodgelike)) |
|
124 |
+ (gamekit:bind-button :h :pressed |
|
125 |
+ (move-left game (player game))) |
|
126 |
+ (gamekit:bind-button :j :pressed |
|
127 |
+ (move-down game (player game))) |
|
128 |
+ (gamekit:bind-button :k :pressed |
|
129 |
+ (move-up game (player game))) |
|
130 |
+ (gamekit:bind-button :l :pressed |
|
131 |
+ (move-right game (player game)))) |
|
132 |
+ |
|
133 |
+(defmethod style ) |
|
134 |
+ |
|
135 |
+(defmethod gamekit:draw ((system bodgelike)) |
|
136 |
+ (dotimes (row 16) |
|
137 |
+ (dotimes (col 16) |
|
138 |
+ (draw-tile row col))) |
|
139 |
+ (let ((*my-font* (gamekit:make-font :fantasy (* 0.8 *tile-size*)))) |
|
140 |
+ (mapcar 'draw-feature |
|
141 |
+ (monsters system)) |
|
142 |
+ (draw-feature (player system)))) |
0 | 143 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,30 @@ |
1 |
+(defpackage :fwoar.condorcet |
|
2 |
+ (:use :cl ) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :fwoar.condorcet) |
|
5 |
+ |
|
6 |
+(defmacro define-data-class (name (&rest super-classes) &body slots) |
|
7 |
+ `(defclass ,name ,super-classes |
|
8 |
+ ,(mapcar |
|
9 |
+ (lambda (slot-name) |
|
10 |
+ `(,slot-name :initarg ,(alexandria:make-keyword slot-name) :reader ,slot-name)) |
|
11 |
+ slots))) |
|
12 |
+ |
|
13 |
+(define-data-class ballot () |
|
14 |
+ voter-name confirmation rankings) |
|
15 |
+ |
|
16 |
+(define-data-class ranking () |
|
17 |
+ rank candidates) |
|
18 |
+ |
|
19 |
+(define-data-class secret-ballot () |
|
20 |
+ confirmation rankings) |
|
21 |
+ |
|
22 |
+(define-data-class tally-election-request () |
|
23 |
+ election candidates eligible-voters ballots) |
|
24 |
+ |
|
25 |
+(define-data-class tally-election-response () |
|
26 |
+ election candidates voted did-not-vote rankings ballots preference-matrix strongest-path-matrix) |
|
27 |
+ |
|
28 |
+(define-data-class tally-election-response () |
|
29 |
+ election candidates voted did-not-vote rankings ballots) |
|
30 |
+ |
0 | 31 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,30 @@ |
1 |
+(defpackage :fwoar.docstrings |
|
2 |
+ (:use :cl ) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :fwoar.docstrings) |
|
5 |
+ |
|
6 |
+(eval-when (:load-toplevel :compile-toplevel :execute) |
|
7 |
+ (defun docstring (name &key signature return summary examples doc) |
|
8 |
+ (format nil "(~s ~{~s~^ ~}) => ~s ~a~%~%~:[~;~:*~a~%~%~]~{(~/pprint-linear/)~%~}" |
|
9 |
+ name signature return summary |
|
10 |
+ doc |
|
11 |
+ examples))) |
|
12 |
+ |
|
13 |
+(defmacro document (definition (=> return) &body (doc &rest examples)) |
|
14 |
+ (assert (eql => '=>)) |
|
15 |
+ (ecase (car definition) |
|
16 |
+ (defun (destructuring-bind (_ name arguments summary &rest __) definition |
|
17 |
+ (declare (ignore _ __)) |
|
18 |
+ `(progn ,definition |
|
19 |
+ (setf (documentation ',name 'function) |
|
20 |
+ ,(docstring name :signature arguments :return return :summary summary :examples examples :doc doc))))))) |
|
21 |
+ |
|
22 |
+(document |
|
23 |
+ (defun this-is-a-test (a b c) |
|
24 |
+ "this is a test" |
|
25 |
+ (declare (ignore a b c)) |
|
26 |
+ (values)) |
|
27 |
+ (=> values) |
|
28 |
+ "don't do nothin" |
|
29 |
+ (this-is-a-test 1 2 3) |
|
30 |
+ (this-is-a-test 'a 2 3)) |
0 | 31 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,133 @@ |
1 |
+(defpackage :fwoar.graphql |
|
2 |
+ (:import-from :data-lens :key :over :juxt) |
|
3 |
+ (:import-from :serapeum :defalias) |
|
4 |
+ (:use :cl ) |
|
5 |
+ (:export )) |
|
6 |
+(in-package :fwoar.graphql) |
|
7 |
+ |
|
8 |
+#| |
|
9 |
+;; query { |
|
10 |
+;; search(query: "topic:common-lisp", type: REPOSITORY, first: 100) { |
|
11 |
+;; edges { |
|
12 |
+;; node { |
|
13 |
+;; ... on Repository { |
|
14 |
+;; owner { |
|
15 |
+;; login |
|
16 |
+;; } |
|
17 |
+;; name |
|
18 |
+;; description |
|
19 |
+;; pushedAt |
|
20 |
+;; } |
|
21 |
+;; } |
|
22 |
+;; } |
|
23 |
+;; } |
|
24 |
+;; } |
|
25 |
+|# |
|
26 |
+ |
|
27 |
+(defun camelize (name) |
|
28 |
+ (fw.lu:with (parts (fwoar.string-utils:split #\- (string-downcase name))) |
|
29 |
+ (format nil "~a~{~:(~a~)~}" |
|
30 |
+ (elt parts 0) |
|
31 |
+ (map 'list #'string-capitalize (subseq parts 1))))) |
|
32 |
+ |
|
33 |
+(defun handle-term (term) |
|
34 |
+ (typecase term |
|
35 |
+ (symbol (camelize term)) |
|
36 |
+ (t term))) |
|
37 |
+ |
|
38 |
+(defun sexp->query (s expr) |
|
39 |
+ (destructuring-bind (op &rest body) expr |
|
40 |
+ (pprint-logical-block (s nil) |
|
41 |
+ (pprint-logical-block (s nil) |
|
42 |
+ (pprint-indent :block 4 s) |
|
43 |
+ (if (listp op) |
|
44 |
+ (format s "~a(~{~a~^, ~})" |
|
45 |
+ (handle-term (car op)) |
|
46 |
+ (loop for (key value) on (cdr op) by #'cddr |
|
47 |
+ collect (format nil "~a:~a" (handle-term key) value))) |
|
48 |
+ (princ (handle-term op) s)) |
|
49 |
+ (princ " {" s) |
|
50 |
+ (loop for expr in body |
|
51 |
+ do |
|
52 |
+ (pprint-newline :mandatory s) |
|
53 |
+ if (listp expr) do |
|
54 |
+ (sexp->query s expr) |
|
55 |
+ else do |
|
56 |
+ (princ (handle-term expr) |
|
57 |
+ s))) |
|
58 |
+ (pprint-newline :mandatory s) |
|
59 |
+ (format s "}")))) |
|
60 |
+ |
|
61 |
+(defun dive (&rest keys) |
|
62 |
+ (lambda (map) |
|
63 |
+ (declare (dynamic-extent map)) |
|
64 |
+ (fw.lu:dive keys map))) |
|
65 |
+ |
|
66 |
+(defalias <> |
|
67 |
+ 'alexandria:compose) |
|
68 |
+ |
|
69 |
+(defun %jq (&rest query) |
|
70 |
+ (lambda (map) |
|
71 |
+ (reduce (lambda (acc next) |
|
72 |
+ (typecase next |
|
73 |
+ (list (ecase (car next) |
|
74 |
+ (:juxt (funcall (apply 'juxt |
|
75 |
+ (mapcar '%jq |
|
76 |
+ (cdr next))) |
|
77 |
+ acc)) |
|
78 |
+ (:dive (funcall (apply '%jq (cdr next)) |
|
79 |
+ acc)) |
|
80 |
+ (:map (funcall (over (apply '%jq (cdr next))) |
|
81 |
+ acc)))) |
|
82 |
+ (t (gethash next acc)))) |
|
83 |
+ query |
|
84 |
+ :initial-value map))) |
|
85 |
+ |
|
86 |
+(defmacro jq (&rest query) |
|
87 |
+ `(%jq ,@(mapcar (lambda (v) `',v) |
|
88 |
+ query))) |
|
89 |
+ |
|
90 |
+(defun format-results (results) |
|
91 |
+ (format t "~:{* ~a/~a ~a~%~2t~a~%~%~}" |
|
92 |
+ results)) |
|
93 |
+ |
|
94 |
+ |
|
95 |
+;; .data.search.edges[] |
|
96 |
+;; | .node |
|
97 |
+;; | "* "+ .owner.login + "/" + .name + " " + .pushedAt + "\n " + .description + "\n"' |
|
98 |
+ |
|
99 |
+(defalias extract-data |
|
100 |
+ (jq "data" |
|
101 |
+ "search" |
|
102 |
+ "edges" |
|
103 |
+ (:map "node" |
|
104 |
+ (:juxt (:dive "owner" |
|
105 |
+ "login") |
|
106 |
+ "name" |
|
107 |
+ "pushedAt" |
|
108 |
+ "description")))) |
|
109 |
+ |
|
110 |
+(defun search-for-topic-repos (topic) |
|
111 |
+ `(query ((search query ,(format nil "\"topic:~a\"" topic) |
|
112 |
+ type "REPOSITORY" |
|
113 |
+ first "100") |
|
114 |
+ (edges |
|
115 |
+ (node |
|
116 |
+ ("... on Repository" |
|
117 |
+ (owner login) |
|
118 |
+ name |
|
119 |
+ description |
|
120 |
+ pushed-at)))))) |
|
121 |
+ |
|
122 |
+(defun github-graphql (token query) |
|
123 |
+ (let ((drakma:*text-content-types* (acons "application" "json" |
|
124 |
+ drakma:*text-content-types*))) |
|
125 |
+ (yason:parse (drakma:http-request "https://api.github.com/graphql" |
|
126 |
+ :method :post |
|
127 |
+ :content (yason:with-output-to-string* () |
|
128 |
+ (yason:with-object () |
|
129 |
+ (yason:encode-object-element |
|
130 |
+ "query" |
|
131 |
+ (with-output-to-string (s) |
|
132 |
+ (sexp->query s query))))) |
|
133 |
+ :additional-headers `(("Authorization" . ,(format nil "bearer ~a" token))))))) |
0 | 134 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,29 @@ |
1 |
+(defpackage :paredit |
|
2 |
+ (:use :cl) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :paredit) |
|
5 |
+ |
|
6 |
+(defclass cursor () |
|
7 |
+ ((%pos :initarg :pos :reader pos))) |
|
8 |
+ |
|
9 |
+(defun make-cursor (&rest path) |
|
10 |
+ (make-instance 'cursor |
|
11 |
+ :pos (copy-seq path))) |
|
12 |
+ |
|
13 |
+(defun get-exp-at-cursor (cursor exp) |
|
14 |
+ (reduce (lambda (acc next-pos) |
|
15 |
+ (elt acc next-pos)) |
|
16 |
+ (pos cursor) |
|
17 |
+ :initial-value exp)) |
|
18 |
+ |
|
19 |
+(defun barf-backward (cursor exp) |
|
20 |
+ (let* ((parent-exp-cursor (apply 'make-cursor |
|
21 |
+ (butlast (pos cursor)))) |
|
22 |
+ (parent-exp (get-exp-at-cursor parent-exp-cursor exp)) |
|
23 |
+ (grandparent-exp-cursor (apply 'make-cursor |
|
24 |
+ (butlast (pos parent-exp-cursor))))) |
|
25 |
+ |
|
26 |
+ |
|
27 |
+ |
|
28 |
+ |
|
29 |
+ )) |
0 | 30 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,57 @@ |
1 |
+;; from Rosetta code, with modifications https://rosettacode.org/wiki/Password_generator#Common_Lisp |
|
2 |
+(defpackage :fwoar.password-gen |
|
3 |
+ (:use :cl ) |
|
4 |
+ (:export )) |
|
5 |
+(in-package :fwoar.password-gen) |
|
6 |
+ |
|
7 |
+(defparameter *lowercase* |
|
8 |
+ '(#\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m #\n #\o #\p |
|
9 |
+ #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z)) |
|
10 |
+ |
|
11 |
+(defparameter *uppercase* |
|
12 |
+ '(#\A #\B #\C #\D #\E #\F #\G #\H #\I #\J #\K #\L #\M #\N #\O #\P |
|
13 |
+ #\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z)) |
|
14 |
+ |
|
15 |
+(defparameter *numbers* |
|
16 |
+ '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)) |
|
17 |
+ |
|
18 |
+(defparameter *special-characters* |
|
19 |
+ '(#\! #\\ #\# #\% #\& #\* #\+ #\, #\- #\. #\: #\< #\= #\> |
|
20 |
+ #\? #\^ #\_ #\| #\~)) |
|
21 |
+ |
|
22 |
+(defparameter *similar-characters* |
|
23 |
+ '(#\I #\l #\1 #\| #\O #\0 #\5 #\S #\2 #\Z)) |
|
24 |
+ |
|
25 |
+(defun make-readable (s) |
|
26 |
+ (remove-if (lambda (x) (member x *similar-characters*)) s)) |
|
27 |
+ |
|
28 |
+(defun shuffle-list (input-list) |
|
29 |
+ (loop with l = (length input-list) |
|
30 |
+ for i below l |
|
31 |
+ do (rotatef (nth i input-list) |
|
32 |
+ (nth (random l) input-list))) |
|
33 |
+ input-list) |
|
34 |
+ |
|
35 |
+(defun generate-password (len human-readable) |
|
36 |
+ (let* |
|
37 |
+ ((upper (if human-readable (make-readable *uppercase*) *uppercase*)) |
|
38 |
+ (lower (if human-readable (make-readable *lowercase*) *lowercase*)) |
|
39 |
+ (number (if human-readable (make-readable *numbers*) *numbers*)) |
|
40 |
+ (special (if human-readable (make-readable *special-characters*) *special-characters*)) |
|
41 |
+ (character-groups (list upper lower number special)) |
|
42 |
+ (initial-password (reduce (lambda (acc x) |
|
43 |
+ (cons (nth (random (length x)) x) acc)) |
|
44 |
+ character-groups :initial-value NIL))) |
|
45 |
+ |
|
46 |
+ (coerce (shuffle-list (reduce (lambda (acc x) |
|
47 |
+ (declare (ignore x)) |
|
48 |
+ (let ((group (nth (random (length character-groups)) character-groups))) |
|
49 |
+ (cons (nth (random (length group)) group) acc))) |
|
50 |
+ (make-list (- len 4)) :initial-value initial-password)) 'string))) |
|
51 |
+ |
|
52 |
+(defun main (len count &optional human-readable) |
|
53 |
+ (if (< len 4) |
|
54 |
+ (print "Length must be at least 4~%") |
|
55 |
+ (loop for x from 1 to count do |
|
56 |
+ (princ (generate-password len human-readable)) |
|
57 |
+ (terpri)))) |
0 | 58 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,52 @@ |
1 |
+(defpackage :fwoar.recursion-schemes |
|
2 |
+ (:use :cl) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :fwoar.recursion-schemes) |
|
5 |
+ |
|
6 |
+(defun cdr* (cons) |
|
7 |
+ (funcall (cdr cons))) |
|
8 |
+ |
|
9 |
+;; cata :: (a -> b -> b) -> b -> [a] -> b |
|
10 |
+(defun cata (fun init as) |
|
11 |
+ (if (null as) |
|
12 |
+ init |
|
13 |
+ (funcall fun |
|
14 |
+ (car as) |
|
15 |
+ (cata fun init |
|
16 |
+ (cdr as))))) |
|
17 |
+ |
|
18 |
+;; para :: (a -> [a] -> b -> b) -> b -> [a] -> b |
|
19 |
+(defun para (fun init as) |
|
20 |
+ (if (null as) |
|
21 |
+ init |
|
22 |
+ (funcall fun (car as) (cdr as) |
|
23 |
+ (para fun init (cdr as))))) |
|
24 |
+ |
|
25 |
+;; ana :: (v -> (a, () -> b)) -> b -> [a] |
|
26 |
+(defun ana (fun init) |
|
27 |
+ (destructuring-bind (a init*) |
|
28 |
+ (funcall fun init) |
|
29 |
+ (cons a (lambda () (ana fun init*))))) |
|
30 |
+ |
|
31 |
+;; ana :: (v -> Maybe (a, b)) -> b -> [a] |
|
32 |
+(defun ana* (fun init) |
|
33 |
+ (let ((v (funcall fun init))) |
|
34 |
+ (when v |
|
35 |
+ (cons (car v) |
|
36 |
+ (ana* fun (cadr v)))))) |
|
37 |
+ |
|
38 |
+;; hylo :: (a -> c -> c) -> c -> (b -> Maybe (a, b)) -> b -> c |
|
39 |
+(defun hylo (reducer reducer-init generator generator-seed) |
|
40 |
+ (flet ((partial-ana (init) |
|
41 |
+ (ana* generator init))) |
|
42 |
+ (cata reducer reducer-init |
|
43 |
+ (partial-ana generator-seed)))) |
|
44 |
+ |
|
45 |
+;; zygo (a -> b -> b) -> (a -> b -> c -> c) -> b -> c -> [a] -> c |
|
46 |
+(defun zygo (fold-1 fold-2 fold-1-init fold-2-init as) |
|
47 |
+ (second |
|
48 |
+ (cata (fw.lu:destructuring-lambda (x (p q)) |
|
49 |
+ (list (funcall fold-1 x p) |
|
50 |
+ (funcall fold-2 x p q))) |
|
51 |
+ (list fold-1-init fold-2-init) |
|
52 |
+ as))) |
0 | 53 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,16 @@ |
1 |
+(defpackage :sqlite-environment |
|
2 |
+ (:use :cl ) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :sqlite-environment) |
|
5 |
+ |
|
6 |
+(defparameter *sqlite-env* (list)) |
|
7 |
+ |
|
8 |
+(defmacro defun* (name (&rest args) &body body) |
|
9 |
+ `(progn |
|
10 |
+ (push '(list ,name ,args ,body) |
|
11 |
+ *sqlite-env*) |
|
12 |
+ (defun ,name ,args |
|
13 |
+ ,@body))) |
|
14 |
+ |
|
15 |
+(defun* do-thing () |
|
16 |
+ (asdf)) |
0 | 17 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,33 @@ |
1 |
+(defpackage :fwoar.triangle |
|
2 |
+ (:use :cl ) |
|
3 |
+ (:export )) |
|
4 |
+(in-package :fwoar.triangle) |
|
5 |
+ |
|
6 |
+(defun alternate-source () |
|
7 |
+ (let ((alternator t)) |
|
8 |
+ (lambda () |
|
9 |
+ (prog1 alternator |
|
10 |
+ (setf alternator (not alternator)))))) |
|
11 |
+ |
|
12 |
+(defun print-triangle (size) |
|
13 |
+ (let ((alt (alternate-source))) |
|
14 |
+ (dotimes (n size) |
|
15 |
+ (let ((count (1+ n))) |
|
16 |
+ (dotimes (i count) |
|
17 |
+ (format t "~:[0~;1~] " (funcall alt))) |
|
18 |
+ (terpri))))) |
|
19 |
+ |
|
20 |
+#| |
|
21 |
+TRIANGLE> (print-triangle 11) |
|
22 |
+1 |
|
23 |
+0 1 |
|
24 |
+0 1 0 |
|
25 |
+1 0 1 0 |
|
26 |
+1 0 1 0 1 |
|
27 |
+0 1 0 1 0 1 |
|
28 |
+0 1 0 1 0 1 0 |
|
29 |
+1 0 1 0 1 0 1 0 |
|
30 |
+1 0 1 0 1 0 1 0 1 |
|
31 |
+0 1 0 1 0 1 0 1 0 1 |
|
32 |
+0 1 0 1 0 1 0 1 0 1 0 |
|
33 |
+|# |