Skip to content

Commit ec2aea5

Browse files
Merge pull request #84 from kloimhardt/twotiles
4Clojure puzzles with twotiles
2 parents 05b27c5 + 7a43720 commit ec2aea5

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

src/games/twotiles_4clojure.clj

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
^{:kindly/hide-code true
2+
:clay {:title "4Clojure puzzles with twotiles"
3+
:quarto {:author :kloimhardt
4+
:type :post
5+
:draft true
6+
:date "2025-09-25"
7+
:image ""
8+
:category :concepts
9+
:tags [:blockly :graphical-programming]}}}
10+
11+
(ns games.twotiles-4clojure.clj
12+
(:require [scicloj.kindly.v4.api :as kindly]
13+
[scicloj.kindly.v4.kind :as kind]))
14+
15+
^:kindly/hide-code
16+
(def md
17+
(comp kindly/hide-code kind/md))
18+
19+
^:kindly/hide-code
20+
(kind/hiccup
21+
[:div
22+
[:script {:src "https://unpkg.com/blockly/blockly_compressed.js"}]
23+
[:script {:src "https://unpkg.com/blockly/msg/en.js"}]
24+
[:script {:src "https://kloimhardt.github.io/twotiles/twotiles_core.js"}]
25+
[:script (str "var parse = scittle.core.eval_string(twotiles.parse_clj);"
26+
"var addBlocks = (ws, code) =>"
27+
"Blockly.Xml.appendDomToWorkspace(Blockly.utils.xml.textToDom(parse(code)), ws);")]
28+
[:script "Blockly.defineBlocksWithJsonArray(twotiles.blocks);"]])
29+
30+
^:kindly/hide-code
31+
(defn ws-hiccup [name height]
32+
[:div
33+
[:div {:id name, :style {:height height}}]
34+
[:script (str "var " name " = Blockly.inject('" name "',"
35+
"{'sounds': false, 'scrollbars':false, 'trashcan':false})")]])
36+
37+
^:kindly/hide-code
38+
(def create-ws (comp kindly/hide-code ws-hiccup))
39+
40+
(md "## 4Clojure Problem 110, Pronunciation")
41+
42+
(md "Produce a \"pronunciation\" of a sequence of numbers. For example, [1 1] is pronounced as [2 1] (\"two ones\"), which in turn is pronounced as [1 2 1 1] (\"one two, one one\"). The solution below is taken from the [4Clojure website](https://4clojure.oxal.org)." )
43+
44+
(defn pronounce
45+
[numbers]
46+
(mapcat (juxt count first)
47+
(partition-by identity
48+
numbers)))
49+
50+
(doall [(pronounce [1])
51+
(pronounce [1 1])
52+
(pronounce [2 1])])
53+
54+
^:kindly/hide-code
55+
(defn add-ws [ws]
56+
(fn [code]
57+
(kindly/hide-code
58+
(kind/scittle
59+
(list 'js/addBlocks
60+
ws
61+
(str code))))))
62+
63+
(md "To memorize this solution, complete the following set of graphical puzzles. The most fun is on mobile devices. Maybe you want to scroll through the workspaces first, to get the idea.")
64+
65+
^:kindly/hide-code
66+
(def add-pr1 (add-ws 'js/pr1))
67+
(add-pr1 'numbers)
68+
(add-pr1 'identity)
69+
(add-pr1 '(:tiles/vert
70+
(partition-by :tiles/slot
71+
:tiles/slot)))
72+
(kind/hiccup (create-ws "pr1" "300px"))
73+
74+
75+
(md "Step two")
76+
^:kindly/hide-code
77+
(def add-pr2 (add-ws 'js/pr2))
78+
(add-pr2 '(:tiles/vert
79+
(partition-by identity
80+
numbers)))
81+
(add-pr2 'first)
82+
(add-pr2 'count)
83+
(add-pr2 '(juxt :tiles/slot :tiles/slot))
84+
(kind/hiccup (create-ws "pr2" "300px"))
85+
86+
(md "Step three")
87+
^:kindly/hide-code
88+
(def add-pr3 (add-ws 'js/pr3))
89+
(add-pr3 '(:tiles/vert
90+
(partition-by identity numbers)))
91+
(add-pr3 '(juxt count first))
92+
(add-pr3 '(:tiles/vert
93+
(mapcat :tiles/slot
94+
:tiles/slot)))
95+
(kind/hiccup (create-ws "pr3" "300px"))
96+
97+
98+
(md "Step four")
99+
^:kindly/hide-code
100+
(def add-pr4 (add-ws 'js/pr4))
101+
(add-pr4
102+
'(:tiles/vert
103+
(mapcat (juxt count first)
104+
(:tiles/vert
105+
(partition-by identity
106+
numbers)))))
107+
(add-pr4 '[numbers])
108+
(add-pr4 'pronounce)
109+
(add-pr4 '(defn :tiles/slot
110+
:tiles/slot
111+
:tiles/slot))
112+
(kind/hiccup (create-ws "pr4" "300px"))
113+
114+
(md "The final result")
115+
((add-ws 'js/pr5)
116+
'(defn pronounce [numbers]
117+
(:tiles/vert
118+
(mapcat (juxt count first)
119+
(:tiles/vert
120+
(partition-by identity
121+
numbers))))))
122+
123+
(kind/hiccup (create-ws "pr5" "300px"))
124+
125+
126+
(md "## 4Clojure #85: Powerset")
127+
128+
(md "Write a function which generates the power set of a given set. The power set of a set x is the set of all subsets of x, including the empty set and x itself.")
129+
130+
(defn powerset
131+
[original-set]
132+
(reduce (fn [result e]
133+
(into result
134+
(map (fn [x]
135+
(conj x e))
136+
result)))
137+
(hash-set #{ })
138+
original-set))
139+
140+
(powerset (hash-set 1 2))
141+
142+
^:kindly/hide-code
143+
(kind/scittle
144+
'(set! (.-add_ps js/window)
145+
(fn [code]
146+
(js/addBlocks js/ps code))))
147+
148+
^:kindly/hide-code
149+
(defn btn-hiccup [tupels]
150+
(into [:div]
151+
(map-indexed (fn [i cs]
152+
[:button
153+
{:onClick
154+
(reduce (fn [r c]
155+
(str r "add_ps('" c "');"))
156+
""
157+
cs)}
158+
(str "Step number " (inc i))])
159+
tupels)))
160+
161+
(md "Again, complete a set of according puzzles step by step. This time, there is only one singe workspace. Start by clicking the first button.")
162+
163+
^:kindly/hide-code
164+
(kind/hiccup
165+
(btn-hiccup
166+
[['(:tiles/vert (map :tiles/slot :tiles/slot))
167+
'(:tiles/vert (fn [x] :tiles/slot))
168+
'e
169+
'x
170+
'(conj :tiles/slot :tiles/slot)
171+
'result
172+
]
173+
['(:tiles/vert (fn [result e] :tiles/slot))
174+
'(:tiles/vert (into :tiles/slot :tiles/slot))
175+
'result]
176+
['(:tiles/vert (reduce :tiles/slot :tiles/slot :tiles/slot))
177+
'(hash-set #{})
178+
'original-set]]))
179+
180+
181+
(kind/hiccup (create-ws "ps" "500px"))

0 commit comments

Comments
 (0)