星田さんの記事に対するコメント。
ここがこんがらがるので、明日じっくり追ってみる予定
ちょっとそこ、端折って書いてたかな。
と言うわけで考え方を。
これはこういう風に使うのね。
> (define lst '(1 2 3 4 5))
> (take lst 2)
'(1 2)
> (drop lst 2)
'(3 4 5)
>
takeはリスト(lst)のpos番目の要素の直前までの部分リストを返す。dropは逆にリスト(lst)のpos番目の要素以降の部分リストを返す。posは0番目から数えるので混乱せんように。
Pythonのスライスで言うとこんなカンジかな。
>>> lst = [1, 2, 3, 4, 5]
>>> lst[:2] # Racket の take にあたる
[1, 2]
>>> lst[2:] # Racket の drop にあたる
[3, 4, 5]
>>>
とまずはtakeとdropをおさえておいて。
トランプはジョーカー1枚含んで53枚ある。
今、4人でババ抜きをするとして、まずは1人頭最低何枚トランプを持つか。
53÷4 = 13 余り 1
で1人頭13枚持つ、と。
つまり、デッキから13枚ずつ(再帰的に残りが13枚以下になるまで)takeしていく。
こういう事だよね。
(13枚 13枚 13枚 13枚) あまり1枚
ここであまりが1枚ある以上、リストの先頭に余りをconsすればいいわけですが。
ここで上のリストをまたもや(余りが1なので)1だけtakeするとこうなるでしょ?
(13枚) (13枚 13枚 13枚) あまり1枚
先頭に(mapしながら)consすれば当然こうなる。
(14枚) (13枚 13枚 13枚)
あとは両方をappendすれば出来上がり。
(14枚 13枚 13枚 13枚)
これをRacketでコーディングすると「ここが非常に難しい」の部分になるわけ。
もう1個見ようか。今度は5人プレイを考える。
最初に各プレイヤーが持たなければならないトランプの枚数は
53 ÷ 5 = 10 余り 3
になる。
つまり、こういうリストになるわけ。
(10枚 10枚 10枚 10枚 10枚) あまり3枚
余りが3枚なんでこのリストから3つtakeする。
(10枚 10枚 10枚) (10枚 10枚) あまり3枚
先頭3人分に余りをmapしながらconsすればこうなる。
(11枚 11枚 11枚) (10枚 10枚)
appendして両者をくっつける。
(11枚 11枚 11枚 10枚 10枚)
これでオシマイ。
やってる事は単純なのね。コード見ると「え?」とか思うかもしれないけど、発想は極めて単純です。
終わり。