多段階選抜 (Clojure/Lisp)


|多段階選抜|解答日|シリーズ:yieldの練習/ジェネレータを入れ子に/整数平方根・立方根の実装|
|:--|:--|:--|
|問題|　|http://nabetani.sakura.ne.jp/hena/ord24eliseq/<br>https://qiita.com/Nabetani/items/1c83005a854d2c6cbb69|
|Ruby|2014/8/2(当日)|https://qiita.com/cielavenir/items/9f15e29b73ecf98968a5|
|C#/Python|2014/8/4|https://qiita.com/cielavenir/items/a1156e6a4f71ddbe5dcb|
| |　|ここから上はdrop_prev_square/drop_prev_cubicをまとめる前の答案|
|Go/C#/Ruby/Python|2014/8/5|https://qiita.com/cielavenir/items/2a685d3080862f2c2c47|
|PHP/JavaScript|2014/9/9|https://qiita.com/cielavenir/items/28d613ac3823afbf8407|
|VB|2014/9/10|https://qiita.com/cielavenir/items/cb7266abd30eadd71c04|
|D|2015/12/21|https://qiita.com/cielavenir/items/47c9e50ee60bef2847ec|
|Perl|2017/3/10|https://qiita.com/cielavenir/items/6dfbff749d833c0fd423|
|Lua|2017/3/13|https://qiita.com/cielavenir/items/c60fe7e8da73487ba062|
|C++20(TS)|2017/3/15|https://qiita.com/cielavenir/items/e1129ca185008f49cbab (MSVC)<br>https://qiita.com/cielavenir/items/1cfa90d73d11bb7dc3d4 (clang)|
|F#|2017/3/17|https://qiita.com/cielavenir/items/a698d6a26824ff53de81|
|Boo/Nemerle|2017/5/13|https://qiita.com/cielavenir/items/e2a783f0fe4b0fe0ed48|
|Perl6|2017/5/15|https://qiita.com/cielavenir/items/656ea17fa96c865c4498|
|Kotlin|2017/5/25|https://qiita.com/cielavenir/items/9c46ce8d9d12e51de285|
|Crystal|2018/5/8|https://qiita.com/cielavenir/items/1815bfa6a860fd1f90db|
|MoonScript|2018/6/16|https://qiita.com/cielavenir/items/8b03cce0386f4537b5ad|
|Julia/Rust|2018/12/20|https://qiita.com/cielavenir/items/3ddf72b06d625da0c4a5|
|Nim|2018/12/26|https://qiita.com/cielavenir/items/5728944867e609fd52a7|
|Tcl|2018/12/31|https://qiita.com/cielavenir/items/76cbd9c2022b48c9a2c9|
|Pascal/Cobra|2019/1/16|https://qiita.com/cielavenir/items/81b81baf8dfc1f877903|
|Icon|2019/1/17|https://qiita.com/cielavenir/items/889622dcc721f5a4da24|
|Swift|2020/5/31|https://qiita.com/cielavenir/items/3b0b84a218e35d538f7f|
|Java/Groovy/Scala|2020/5/31|https://qiita.com/cielavenir/items/7f058203a8fd03b65870|
|V|2020/10/17|https://qiita.com/cielavenir/items/df30a6c101a97a713df5|
|Zig/Zen|2020/10/17|https://qiita.com/cielavenir/items/9cced9e4a94dcd70df0f|
|Pike|2020/11/2|https://qiita.com/cielavenir/items/3a8248f41611302b34fd|
|Vala/Smalltalk|2020/11/29|https://qiita.com/cielavenir/items/085dabe593cd916af5e8|
|Objective-C|2020/11/30|https://qiita.com/cielavenir/items/a1736e38789a3dd5cc5a|
|Ruby(Ractor)|2021/1/2|https://qiita.com/cielavenir/items/f493c6d512b63cc571cc|
|Python(_xxsubinterpreters)|2021/6/29|https://qiita.com/cielavenir/items/f1f581a055db918954f1|
|Falcon/Scheme|2021/9/5|https://qiita.com/cielavenir/items/c13d12cf44f0d17f4a94|
|Clojure/Lisp|2021/9/7|https://qiita.com/cielavenir/items/7458ba076f4e5bc0f196|
|(icbrtの実装に関する)補題|2017/5/11|整数除算であってもn/(x*y)はn/x/yに等しい(ことの証明)<br>https://qiita.com/cielavenir/items/21a6711afd6be8c18c55|

思ったより難しくなかったな!?

## Clojure

reset!の使い方、間違っているかもしれぬ(テストは通るが)。

```clojure:tyama_hena24.clj
#!/usr/bin/env clojure
;http://nabetani.sakura.ne.jp/hena/ord24eliseq/

(defn expt_impl [r n k]
	(if (<= k 0) r (recur (* r (if (> (mod k 2) 0) n 1)) (* n n) (quot k 2)))
)

(defn expt [n k]
	(expt_impl 1 n k)
)

(defn isqrt_impl [n x y]
	(if (or (= x y) (= (+ x 1) y)) x
		(recur n y (quot (+ (quot n y) y) 2))
	)
)

(defn isqrt [n]
	(if (<= n 0) 0
		(if (< n 4) 1
			(isqrt_impl n 0 n)
		)
	)
)

(defn icbrt_impl [n x y]
	(if (or (= x y) (= (+ x 1) y)) x
		(recur n y (quot (+ (quot (quot n y) y) (* y 2)) 3))
	)
)

(defn icbrt [n]
	(if (< n 0) (- 0 (icbrt (- 0 n)))
		(if (= n 0) 0
			(if (< n 8) 1
				(icbrt_impl n 0 n)
			)
		)
	)
)

(defn generate []
	(let [i (atom 0)]
		(fn []
			(reset! i (+ @i 1))
			@i
		)
	)
)

(defn drop_prev [check prev]
	(let [a (atom 0) b (atom (prev))]
		(fn []
			(reset! a @b)
			(reset! b (prev))
			(while (check @b)
				(reset! a @b)
				(reset! b (prev))
			)
			@a
		)
	)
)

(defn drop_next [check prev]
	(let [a (atom 0) b (atom 0) first (atom true)]
		(fn []
			(reset! a @b)
			(reset! b (prev))
			(while (and (not @first) (check @a))
				(reset! a @b)
				(reset! b (prev))
			)
			(reset! first false)
			@b
		)
	)
)

(defn drop_n [check n prev]
	(let [i (atom 0) a (atom 0)]
		(fn []
			(reset! i (+ @i 1))
			(reset! a (prev))
			(while (check @i n)
				(reset! i (+ @i 1))
				(reset! a (prev))
			)
			@a
		)
	)
)

(defn is_sq [n]
	(= (expt (isqrt n) 2) n)
)
(defn is_cb [n]
	(= (expt (icbrt n) 3) n)
)
(defn is_multiple [i n]
	(= (mod i n) 0)
)
(defn is_le [i n]
	(<= i n)
)

(def f {
	\S (fn [prev] (drop_next is_sq prev))
	\s (fn [prev] (drop_prev is_sq prev))
	\C (fn [prev] (drop_next is_cb prev))
	\c (fn [prev] (drop_prev is_cb prev))
	\h (fn [prev] (drop_n is_le 100 prev))
	\2 (fn [prev] (drop_n is_multiple 2 prev))
	\3 (fn [prev] (drop_n is_multiple 3 prev))
	\4 (fn [prev] (drop_n is_multiple 4 prev))
	\5 (fn [prev] (drop_n is_multiple 5 prev))
	\6 (fn [prev] (drop_n is_multiple 6 prev))
	\7 (fn [prev] (drop_n is_multiple 7 prev))
	\8 (fn [prev] (drop_n is_multiple 8 prev))
	\9 (fn [prev] (drop_n is_multiple 9 prev))
})

(with-local-vars [line (read-line)]
	(while (not (= @line nil))
		(let [g (reduce (fn [s e] ((get f e) s)) (generate) (seq @line))]
		 	(with-local-vars [i 0]
				(while (< @i 10)
					(if (> @i 0) (print ","))
					(print (g))
					(var-set i (+ @i 1))
				)
				(println)
			)
		)
		(var-set line (read-line))
	)
)
```

## Lisp

`clisp`と`sbcl --script`に対応しています。

```lisp:tyama_hena24_enum.l
#!/usr/bin/sbcl --script
;http://nabetani.sakura.ne.jp/hena/ord24eliseq/

(defun isqrt_impl (n x y)
	(if (or (= x y) (= (+ x 1) y)) x
		(isqrt_impl n y (truncate (+ (truncate n y) y) 2))
	)
)

(defun myisqrt (n)
	(if (<= n 0) 0
		(if (< n 4) 1
			(isqrt_impl n 0 n)
		)
	)
)

(defun icbrt_impl (n x y)
	(if (or (= x y) (= (+ x 1) y)) x
		(icbrt_impl n y (truncate (+ (truncate (truncate n y) y) (* y 2)) 3))
	)
)

(defun icbrt (n)
	(if (< n 0) (- 0 (icbrt (- 0 n)))
		(if (= n 0) 0
			(if (< n 8) 1
				(icbrt_impl n 0 n)
			)
		)
	)
)

(defun generate ()
	(let ((i 0))
		(lambda ()
			(setf i (+ i 1))
			i
		)
	)
)

(defun drop_prev (check prev)
	(let ((a 0) (b (funcall prev)))
		(lambda ()
			(setf a b)
			(setf b (funcall prev))
			(loop while (funcall check b) do
				(setf a b)
				(setf b (funcall prev))
			)
			a
		)
	)
)

(defun drop_next (check prev)
	(let ((a 0) (b 0) (first t))
		(lambda ()
			(setf a b)
			(setf b (funcall prev))
			(loop while (and (not first) (funcall check a)) do
				(setf a b)
				(setf b (funcall prev))
			)
			(setf first nil)
			b
		)
	)
)

(defun drop_n (check n prev)
	(let ((i 0) (a 0))
		(lambda ()
			(setf i (+ i 1))
			(setf a (funcall prev))
			(loop while (funcall check i n) do
				(setf i (+ i 1))
				(setf a (funcall prev))
			)
			a
		)
	)
)

(defun is_sq (n)
	(= (expt (myisqrt n) 2) n)
)
(defun is_cb (n)
	(= (expt (icbrt n) 3) n)
)
(defun is_multiple (i n)
	(= (mod i n) 0)
)
(defun is_le (i n)
	(<= i n)
)

(let ((f (make-hash-table)))
	(setf (gethash #\S f) (lambda (prev) (drop_next 'is_sq prev)))
	(setf (gethash #\s f) (lambda (prev) (drop_prev 'is_sq prev)))
	(setf (gethash #\C f) (lambda (prev) (drop_next 'is_cb prev)))
	(setf (gethash #\c f) (lambda (prev) (drop_prev 'is_cb prev)))
	(setf (gethash #\h f) (lambda (prev) (drop_n 'is_le 100 prev)))
	(setf (gethash #\2 f) (lambda (prev) (drop_n 'is_multiple 2 prev)))
	(setf (gethash #\3 f) (lambda (prev) (drop_n 'is_multiple 3 prev)))
	(setf (gethash #\4 f) (lambda (prev) (drop_n 'is_multiple 4 prev)))
	(setf (gethash #\5 f) (lambda (prev) (drop_n 'is_multiple 5 prev)))
	(setf (gethash #\6 f) (lambda (prev) (drop_n 'is_multiple 6 prev)))
	(setf (gethash #\7 f) (lambda (prev) (drop_n 'is_multiple 7 prev)))
	(setf (gethash #\8 f) (lambda (prev) (drop_n 'is_multiple 8 prev)))
	(setf (gethash #\9 f) (lambda (prev) (drop_n 'is_multiple 9 prev)))

	(loop
		(let ((line (read-line *standard-input* nil nil)))
			(if (not line) (exit))
			(let ((g (reduce (lambda (s e) (funcall (gethash e f) s)) (coerce line 'list) :initial-value (generate))))
				(let ((i 0))
					(loop while (< i 10) do
						(if (> i 0) (princ #\,))
						(write (funcall g))
						(setf i (+ i 1))
					)
				)
	  			(fresh-line)
			)
		)
	)
)
```