部分列の列を行列と見なして転置する

実例でいいますと,

```
[a, b, c, d, e, f]
```

のようなデータ列と `3` という数値が与えられたときに, 長さ 3 の部分列を連続して取得した列

```
[[a, b, c], [d, e, f]]
```

を作成, さらにこの列の列を行列とみなして転置し

```
[[a, d], [b, e], [c, f]]
```

のようなデータに変換したい, ということです.

まったく同じ問題はどうか分かりませんが, 部分列の列をとりだしたいことも, 列の列を行列とみなして転置したいことも頻繁にありますから, 演習として Ruby, Haskell, Clojure でそれぞれどうなるか見てみましょう.

元のデータ列の長さが, 与えられた数値の整数倍でなかった場合に, 最後の余り部分を捨てるか使うかで詳細は変わりますが, 捨てる場合で考えましょう.

## Ruby

部分列の列を得るには `each_slice` というメソッドがあります.

```ruby
irb> ["a", "b", "c", "d", "e", "f"].each_slice(3).to_a
=> [["a", "b", "c"], ["d", "e", "f"]]
```

ただし, 余り部分を捨てるオプションはない

```ruby
irb> ["a", "b", "c", "d", "e", "f", "g", "h"].each_slice(3).to_a
=> [["a", "b", "c"], ["d", "e", "f"], ["g", "h"]]
```

ので, 手動で切り出します. ここで使える道具はいろいろ考えられますが, とりあえず `take_while` を使っておきましょう.


```ruby
irb> ["a", "b", "c", "d", "e", "f", "g", "h"].each_slice(3).take_while{|s| s.length == 3}
=> [["a", "b", "c"], ["d", "e", "f"]]
```

転置は, その名も `transpose`.

```ruby
irb> [["a", "b", "c"], ["d", "e", "f"]].transpose
=> [["a", "d"], ["b", "e"], ["c", "f"]]
```

### 結局

```ruby
def sstrans(n, s)
  return s.each_slice(n).take_while{|ss| ss.length == n}.transpose
end
```

のようなメソッドが目的に適います.

```ruby
irb> sstrans(3, ["a", "b", "c", "d", "e", "f", "g", "h"])
=> [["a", "d"], ["b", "e"], ["c", "f"]]
```

## Haskell

部分列の列そのものずばりの関数は思い当たらず (ご存知の方は教えてください), `slices n s` を「`s` の先頭から `n` 個の要素からなる列を『`s` の頭から `n` 個の要素を除外した列に再帰的に `slices n` を適用した列』の先頭に付加するような関数」として定義しました.


```Haskell:foo.hs
slices n s | length s < n = [] | otherwise = (take n s):slices n (drop n s)
```

`s` の長さ `n` 未満の場合は空列を返すことで, 余り分は除外しています.
動作は

```Haskell
Prelude> :l foo.hs
Ok, modules loaded: Main.
*Main> slices 3 ["a", "b", "c", "d", "e", "f", "g", "h"]
[["a","b","c"],["d","e","f"]]
```

のような具合です.

転置は, こちらもそのものずばり `transpose`.

```Haskell
Prelude> :m Data.List
Prelude Data.List> transpose [["a", "b", "c"], ["d", "e", "f"]]
[["a","d"],["b","e"],["c","f"]]
```

### 結局

```Haskell:foo.hs
import Data.List

sstrans n s = transpose $ slices n s
        where slices n s | length s < n = [] | otherwise = (take n s):slices n (drop n s)
```

のような関数が目的に適います.

```Haskell
Prelude> :l foo.hs
Ok, modules loaded: Main.
*Main> sstrans 3 ["a", "b", "c", "d", "e", "f", "g", "h"]
[["a","d"],["b","e"],["c","f"]]
```

## Clojure

部分列の列は `partition` がやってくれます. 余りを使う `partition-all`

```clj
user=> (partition-all 3 ["a" "b" "c" "d" "e" "f" "g" "h"])
(("a" "b" "c") ("d" "e" "f") ("g" "h"))
```

と, 余りを使わない `partition`

```clj
user=> (partition 3 ["a" "b" "c" "d" "e" "f" "g" "h"])
(("a" "b" "c") ("d" "e" "f"))
```

がありますので, 後者を使えばよいでしょう.

転置は, そのものずばりの関数は思い当たりません (どなたかご存知でしたら教えてください) が, 下記でできます.

一度でもやったことがあると簡単なのですが, 初めての場合は少々込み入って見えると思いますので, 少し丁寧に解説します.

Clojure の `map` は他の言語によくある `map` と異なり, 可変個の列を渡すことができ, 第一引数に「残りの引数で渡した列の数の引数を受け取れる関数」を指定して上げると, [全部の列の最初の要素達を引数としてその関数を呼び出した結果, 全部の列の二番目の要素達を引数としてその関数を呼び出した結果, ...] という列を返してくれます.
つまり `(map f [a1 a2 a3] [b1 b2 b3])` は `((f a1 b1) (f a2 b2) (f a3 b3))` というシーケンスになります.

```clj
user=> (map * [1 2 3] [4 5 6])
(4 10 18)
```

従って, `map` の第一引数に「引数から列を生成する関数」を渡して上げることで, 転置を行うことができます. (リストでも良いですが, ここでは結果をベクタで返す `mapv` と, 引数からベクタを作成する `vector` 関数を使います.)

```clj
user=> (mapv vector ["a" "b" "c"] ["d" "e" "f"])
[["a" "d"] ["b" "e"] ["c" "f"]]
```

しかし, このままでは, 部分列を引数に **並べて** 渡しているのであって, **部分列の列** を渡せていません.
ということで, 最後の引数がシーケンスであれば, その要素を引数に並べて適用してくれる `apply` を使います. `(apply a b c [d e f])` は `(a b c d e f)` と同等です.

```clj
user=> (apply mapv vector [["a" "b" "c"] ["d" "e" "f"]])
[["a" "d"] ["b" "e"] ["c" "f"]]
```

これで転置は O.K. です. イディオムとして覚えておくと良いでしょう.


### 結局

```clj
(defn sstrans [n s] (apply mapv vector (partition n s)))
```

と定義した関数が目的に適います.

```clj
user=> (sstrans 3 ["a" "b" "c" "d" "e" "f" "g" "h"])
[["a" "d"] ["b" "e"] ["c" "f"]]
```

### 例えば

パズル的な例で恐縮ですが, 例えば, カード群が文字列の集合として

```clj
user=> (def cards
  #{"SA" "S2" "S3" "S4" "S5" "S6" "S7" "S8" "S9" "S0" "SJ" "SQ" "SK"
    "DA" "D2" "D3" "D4" "D5" "D6" "D7" "D8" "D9" "D0" "DJ" "DQ" "DK"
    "HA" "H2" "H3" "H4" "H5" "H6" "H7" "H8" "H9" "H0" "HJ" "HQ" "HK"
    "CA" "C2" "C3" "C4" "C5" "C6" "C7" "C8" "C9" "C0" "CJ" "CQ" "CK"})
#'user/cards
```

のように定義された場合に, これをシャッフル

```clj
user=> (shuffle cards)
["D3" "CQ" "C3" "SJ" "D2" "S9" "D4" "S5" "C8" "S3" "C5" "C2" "HQ" "C4" "SQ" "DK" "S2" "H6" "D9" "H0" "S8" "SA" "SK" "C6" "S0" "H5" "D0" "CJ" "D6" "H2" "D7" "DJ" "S7" "H9" "H8" "CA" "C0" "S6" "H3" "C7" "HA" "HJ" "H7" "S4" "C9" "DQ" "DA" "CK" "D8" "HK" "H4" "D5"]
```

して, 5人のプレイヤーに同枚数ずつ配れるだけ配って余りを捨てた場合に, 各プレイヤーの持っているカードの列を得る

```clj
user=> (sstrans 5 *1) ; Clojure の REPL では *1 は直前の評価結果を参照します.
[["D3" "S9" "C5" "DK" "S8" "H5" "D7" "CA" "HA" "DQ"]
 ["CQ" "D4" "C2" "S2" "SA" "D0" "DJ" "C0" "HJ" "DA"]
 ["C3" "S5" "HQ" "H6" "SK" "CJ" "S7" "S6" "H7" "CK"]
 ["SJ" "C8" "C4" "D9" "C6" "D6" "H9" "H3" "S4" "D8"]
 ["D2" "S3" "SQ" "H0" "S0" "H2" "H8" "C7" "C9" "HK"]]
```

といった場合に使えますね. (出力は成形しています.)


## ところで皆さん

[これが10分でできない人は自分がかなりプログラミングができないというつらい事実を認識しましょう。](http://qiita.com/hisui@github/items/b47c411437d60440a605) という投稿および, 回答となる皆さんの投稿はご覧になりましたか?

* [Underscore.jsで解いてみた：これが10分でできない人は自分がかなりプログラミングができないというつらい事実を認識しましょう。](http://qiita.com/fintopo/items/481aa0ab8e5ca1f89d49)
* [解いてみた：これが10分でできない人は自分がかなりプログラミングができないというつらい事実を認識しましょう。](http://qiita.com/cof/items/8d39bacd75dbf6937bbf) (Python)
* [10分でできないとつらいらしいやつ](http://qiita.com/yagihashoo/items/9f843dc3569c4db26110) (Python)
* [Groovyでカード分配？アルゴリズム](http://qiita.com/saba1024/items/46134f3585eed3dde092)