まず、いくつかの再フォーマット:
(loop for e in entries do
(if (and (not (member e sub))
(not (member e col)))
(progn (setq choices (nconc choices (list e)))
(print choices)))
(if (= (length choices) 1)
(setq pick (car choices))
(if (not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
次に、 の代替句は必要ないが が必要な場合はif
、progn
次を使用できますwhen
。
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(if (= (length choices) 1)
(setq pick (car choices))
(if (not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
最後の 2 つのif
句は相互に排他的であるため、またはのいずれcond
かcase
が適切です (ここでは使用cond
します)。
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
zerop
述語があります:
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (+ 0 (length choices))) choices))))
一部の値に 0 を追加すると何が達成されるかわかりません。
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices))))
最初から賢明なデフォルトに設定されていることが確実でない限りpick
、おそらくデフォルトのケースを使用する必要があります(これは問題の1つかもしれません):
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil))
setq
andを使用する代わりにnconc
、次を使用できますpush
(これにより、新しい要素がリストの先頭に配置されますが、ランダムに選択するため、これは問題になりません)。
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(push e choices)
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil))
このスニペットの開始時は でchoices
あるはずで、このスニペットの後()
は不要choices
であり、印刷はデバッグのためだけのものであると思われるため、条件を使用して変更することchoices
により、別の方法でこれを行うことができます。remove-if
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil)))
choices
が今のように出力された場合()
、ここには選択肢が残っていないことを意味するため、バックトラックを行う必要があります (または、行き止まりに達したときにアルゴリズムが行うことは何でも)。
最後に、(length choices)
非負の整数のみを使用できるため、異なる順序でケースをテストする場合のcase
代わりに使用できます。cond
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(case (length choices)
(0 (setq pick nil))
(1 (setq pick (car choices)))
(otherwise (setq pick (nth (random (length choices)) choices)))))
リクエストにより更新。
Rainer が指摘するように、これは基本的にpick
関数の本体であるため、すべての自由変数を取り除くことができます。また、 の代わりにcar
、(リストの場合) よりわかりやすい名前 を使用できますfirst
。
(defun pick (entries sub col)
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(case (length choices)
(0 nil)
(1 (first choices))
(otherwise (nth (random (length choices)) choices)))))
この関数は別の場所で定義され、スニペットの場所では次のように呼び出されます。
(pick entries sub col)
2 回計算しないようにするために、それを (シリアル評価に必要な)(length choices)
に入れることができます。let
let*
(defun pick (entries sub col)
(let* ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries))
(choices-length (length choices)))
(print choices)
(case choices-length
(0 nil)
(1 (first choices))
(otherwise (nth (random choices-length) choices)))))
最後のステップ (実際にはオプションですが、選択肢を減らすシーケンスがさらにあることに気付くかもしれませんrow
) は、少し一般化したものです。
(defun pick (entries &rest exclusion-sequences)
(let* ((choices (remove-if (lambda (e)
(some #'identity
(mapcar (lambda (seq)
(member e seq))
exclusion-sequences)))
entries))
(choices-length (length choices)))
(print choices)
(case choices-length
(0 nil)
(1 (first choices))
(otherwise (nth (random choices-length) choices)))))
この関数の呼び出しは同じ形ですが、除外シーケンスをいくつでも使用できるようになりました。
(pick entries col sub row ver ima fou)