P21 (*) Insert an element at a given position into a list.
p20.cljとほぼ同じやり方(該当要素を除くか該当箇所に加えるか)なので、まずそのパターンで書いてみた。次に、
split-at
でリストを分割して、間に追加する要素を加えて再結合するパターン。P20もこれとほぼ同じやり方でも解けそうだ。
P22 (*) Create a list containing all integers within a given range.
組み込みのrange
関数は与えられた第1引数以上第2引数未満のリストを作るので、第2引数自身も含むには
(range n (inc m))
とすればよさそうだが、range関数を使わないパターンでも書いてみた。
nから始めてmに到達するまで再帰でリストを作っている。
P23 (**) Extract a given number of randomly selected elements from a list.
rand-int
関数で0以上指定した値未満の整数を生成する。まずはP20を使えとのヒントの通りに書いてみた。
my-remove-at
はp20.cljそのままでも良かったが、せっかくなのでp21-2.cljパターンに書き換えた。要素を取り除く
(my-remove-at %1 n)
と要素を取り出す(nth %1 n)
をそれぞれ呼んでいるのがイマイチだったので、my-remove-at
を、指定要素を取り除いたリストと指定要素の両方を返す関数に書き換えてそれを使用することに。また、
rand-int
を使わない別解として、shuffle
関数でリストをランダムに並び替え、その先頭を取るというやり方でも書いてみた。P24 (*) Lotto: Draw N different random numbers from the set 1..M.
1以上第2引数で指定した値以下の整数の中から、第1引数で指定した要素数のリストをランダムに作成する。まずはヒント通りP22,P23を使う。
別解として、
rand-int
でランダムな整数を生成してセットに追加、という処理を再帰で繰り返すパターンでも書いてみたが…多分効率は良くないだろう。
同一要素の重複を避けるためセットで値を保持しているが、n > m だと再帰が終わらないため、最初に
(min n m)
をすることにした。P25 (*) Generate a random permutation of the elements of a list.
P23を使って並び順をランダムにする問題だが、そもそもp23-3.cljでshuffle
を使っているので本末転倒感があり、別のやり方で解いてみた。
(rand-int 2)
で0か1を生成し、要素をリストの先頭に追加するか末尾に追加するかという処理を畳み込み処理で行っている。