TDD練習サイト、cyber-dojoのお題を簡単に日本語訳してみた。

# 前提の話
cyber-dojoというサイトがTDDの入門にちょうど良く、オススメです。
https://cyber-dojo.org/

# やったこと
cyber-dojoのお題選びのお手伝いのために、お題を簡単に日本語訳しました。
詳細は問題が乗っているページを参照してください。
https://cyber-dojo.org/setup_default_start_point/show/?from=individual
取り消し線が引いてあるところは、TDD向きでないと勝手に判断したところです（問題自体がテストを書くことを想定していなさそう or そもそも入力がないなど）。もちろん工夫すればTDD可能なものもあると思うので、ぜひそのトライもしてみてください。
# ~~100 doors~~
100個のドアが一列に並んでいて、すべて最初は閉じています。あなたは100回そのドアの前を通り過ぎます。1回目、あなたはすべてのドアの前に立ちドアを開け閉めします（ドアが閉じていれば開き、開いていれば閉じます）。2回目は2の倍数番目のドアごとに、3回目は3の倍数番目のドアごとに、開け閉めを繰り返していきます。
さて、100回通り過ぎた後、ドアの状態はどうなっているでしょうか？

# Anagrams
与えられた文字列の、全てのアナグラムを出力してください。
例えば、`biro`のアナグラムは以下になります。

    biro bior brio broi boir bori
    ibro ibor irbo irob iobr iorb
    rbio rboi ribo riob roib robi
    obir obri oibr oirb orbi orib
# Array Shuffle
配列をシャッフルするプログラムを書いてください。
まず、二つの数値（最小値を最大値）を引数として受け取り、二つの間の乱数を返す関数を作ってください。

    1, 7 => {1, 2, 3, 4, 5, 6}

その関数を使って配列をシャッフルします。
与えられた配列を先頭から順番に処理していきます。配列の長さを最大値とした乱数を生成し、その乱数の位置にある数値と入れ替えます。
# Balanced Parentheses
与えられた文字列の中の、()、[]、{}のバランスが取れているか判定してください。
# Bowling Game
ボウリングのスコアを算出するプログラムを書いてください。
入力例: 

    X|7/|9-|X|-8|8/|-6|X|X|X||81
# Cals Stats
数値のリストが与えられた時、以下の統計数値を算出してください

- 最小値
- 最大値
- 要素の数
- 平均値

# Closest To Zero

数値のリストが与えられた時、もっとも0に近い数値を出力してください。
同率一位がある場合は、正の数を採用してください。
# Combined Number
数値のリストが与えられた時、負でない数を採用した後、連結して作られる数の内最大のものを文字列として出力してください。
# ~~Count Coins~~
1ドルの支払いをするときに、アメリカの硬貨で支払う方法は何通りあるでしょうか？
# ~~Diversion~~
n桁のバイナリ（0と1からなる数字）に対して、1が二つ隣接しない数はいくつ存在するか導いてください。
n = 3の時、3桁のバイナリは以下の8通りあり、1が二つ隣接しない数は2行目にある5種類となります。

    000 001 010 011 100 101 110 111
    000 001 010     100 101

詳しくはこちら
http://codekata.com/kata/kata15-a-diversion/
# ~~Eight Queens~~
8体のクイーンを、互いに干渉しないように8x8のチェス盤の上に置いてください。
# Fizz Buzz
有名なFizzBuzz。
3の倍数の時にFizz
5の倍数の時にBuzz
3と5の倍数の時にFizzBuzz
を出力してください。
# Fizz Buzz Plus
Fizz Buzz と世界のナベアツゲームのMix
3の倍数と3を含む数字の時にFizz
5の倍数と5を含む数字の時にBuzz
3と5の倍数の時にFizzBuzz
を出力してください。
# ~~Friday 13th~~
毎月の13日が、金曜日になる確率がもっとも高いことを証明してください。
# Game of Life
ライフゲームの次世代の状態を出力してください。
# Gray Code
Gray code（交番二進符号）にエンコード、デコードするプログラムを書いてください。
# ~~Haiku Review~~
入力された文字列が俳句の形式に則っているかチェックするプログラムを書いてください。
# Harry Potter
5種類の本があり、異なる本をセットで買うと割引が効くようになります。
購入する本が入力されたとき、合計でいくらになるか算出してください。
（割引の詳細や値段は英語で）
# ISBN
入力された文字列がISBN-13の形式に則っているかを判定するプログラムを書いてください。
さらに、ISBN-10にも則っているかも判定してください。
# LCD Digits
入力された数字をデジタル数字にして出力してください

    ._.   ...   ._.   ._.   ...   ._.   ._.   ._.   ._.   ._.
    |.|   ..|   ._|   ._|   |_|   |_.   |_.   ..|   |_|   |_|
    |_|   ..|   |_.   ._|   ..|   ._|   |_|   ..|   |_|   ..|
# Leap Years
入力された数値が、閏年かどうかを判定するプログラムを書いてください。
# ~~Magic Square~~
3x3の魔法陣を完成させてください
# Mars Rover
火星探査機の行動プログラムを書いてください。
入力として、1行目に台座の広さが与えられます。2行目以降は、2行で一セットになっており、はじめに探査機の位置と向き、次に移動の命令が記述されています。
命令が実行された後の探査機の位置と向きを出力してください。
さらに、探査機が複数ある場合も考えてください（1台の場合は入力が3行、2台の場合は5行、3台の場合は7行…となります）
https://code.google.com/p/marsrovertechchallenge/
# Mine Field
NxMの四角形のフィールドの各点で、周囲に何個地雷（`mine`）があるか導くプログラムを書いてください。
（マインスイーパを一部実装するイメージです）
`*`: mine
`.`: no-mine
入力例: 

    3 4
    *...
    ..*.
    ....
出力例: 

    *211
    12*1
    0111
# ~~Monty Hall~~
有名なモンティーホール問題です。
選ぶドアを変えるか変えないか、最低1000回シミュレーションしてどっちがいいか判定してみてください。

# Number Chains
与えられた数値に対して、以下の操作を行ってください。
（1）降順に並べる
（2）昇順に並べる
（3）（1）から（2）を引く
（4）（3）の結果が重複するまで（1）から（3）を繰り返す
最終的に、（1）から（3）までが何回繰り返されたかを出力してください。
# Number Names
入力された数値を英語にしてください
（日本語にするアレンジでもいいかも）

# Phone Number
電話番号の文字列のリストが与えられたとき、全ての番号に電話をかけることができるか判定してください。
例えば、

    Bob 91 12 54 26
    Alice 97 625 992
    Emergency 911
というリストが与えられたとき、Bobにかけようとすると最初の3桁を打った時点でEmergencyに電話がかかってしまうので、一生Bobに電話をかけることができません。
# Poker Hands
二人がポーカーで戦っている状況で、二人の手札から、買った方とその時の役を出してください。
入力例1:

    Black: 2H 3D 5S 9C KD White: 2C 3H 4S 8C AH
出力例1:

    White wins - high card: Ace

入力例2:

    Black: 2H 4S 4C 2D 4H White: 2S 8S AS QS 3S

出力例2:

    Black wins - full house
# Prime Factors
与えられた数値を素因数分解してください
# Print Diamond
与えられたアルファベット一文字に対して、Aから始まりその文字で折り返しAで終わるダイヤモンドを描いてください
入力例:

    E

出力例:

        A
       B B
      C   C
     D     D
    E       E
     D     D
      C   C
       B B
        A
# Recently Used List
下記にしたがって、`RecentlyUsedList`クラスを成長させてあげてください。文字列を重複なしでLIFOで持つリストです。

- `RecentlyUsedList`は、はじめは何も持っていない
- 最も最近加えられたアイテムが最初、最も古いアイテムが最後
- アイテムは、0から始まる番号で取得できる
- リスト内のアイテムは重複できない。重複が起こった場合は、そのアイテムが先頭に移動する
- Nullと空文字はリストに入らない
- リストに入るアイテムの数は制限できる。キャパオーバーの場合は最も古いアイテムが抜け落ちる

# Remove Duplicate
与えられた数値のリストの、重複を取り除いた物を出力してください。
# Reordering
数値のリストが与えられた時、指定された範囲の数値を指定された場所に、他の順番を変えずに移動してください。
入力例

    list, s, e, p
    { 4, 2, 7, 5, 9, 8, 6, 4, 3, 2 }, 2, 4, 9
出力例

    { 4, 9, 8, 6, 4, 2, 7, 5, 3, 2 }
さらに、FizzまたはBuzzまたはFizzBuzzに変換される数値を、指定された場所以降に、他の順番を変えずに移動してください
入力例

    list, p
    { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }, 4
出力例

    { 1, 2, 4, 3, 5, 6, 9, 10, 12, 15, 18, 20, 7, 8, 11, 13, 14, 16, 17, 19 }
# Revers Roman
与えられたローマ数字の文字列を数値に変換してください。
対応する文字は以下

    I -> 1
    V -> 5
    X -> 10
    L -> 50
    C -> 100
    D -> 500
    M -> 1000
例

    MCMXC -> 1990
    MMVIII -> 2008
    XCIX -> 99
    XLVII -> 47
# Reversi
8x8のリバーシの盤面と次の手番が文字列で入力された時、打つことが可能な位置を0に変換して出力してください。
入力例

    ........
    ........
    ........
    ...BW...
    ...WB...
    ........
    ........
    ........
    B

出力例

    ........
    ........
    ....0...
    ...BW0..
    ..0WB...
    ...0....
    ........
    ........
    B
# Roman Numerals

与えられた数値を、ローマ数字に変換してください。
Revers Romanの逆です。

# Saddle Points

5x5の行列が5つの配列により与えられた時、「サドルポイント」を見つけ出してください。サドルポイントとは、行内では最大で列内では最小である数値です。
全てのサドルポイントの座標を出力してください。もしサドルポイントがない場合はそれと分かるようにしてください。
http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html

# Tennis

テニスのスコアを表示するプログラムを書いてください。

1. 他プレイヤーに対して2点以上差をつけた状態で4点以上獲得したプレイヤーが勝利する
2. スコアはテニス特有の表現で出力する
3. 両プレイヤーが3点以上獲得しているとき
  1. 両プレイヤーが同点であれば`deuce`とする
  2. 片方のプレイヤーが1点だけリードしている時、`advantage`とする

例:

    love - fifteen
    forty - thirty
    deuce
    advantage <player_name>
# Tiny Maze

文字列の配列の配列（行列）が、迷路として与えられるので、ゴールしてください。
入力例:

    [[:S 0 1]
     [1  0 1]
     [1  0 :E]]

出力例:

    [[:x :x 1]
     [1  :x 1]
     [1  :x :x]]
# Unsplice

与えられた文字列の中にバックスラッシュ`\`と改行コード`\n`が連続しているとき、それを取り除いてください

# ~~Wonderland Number~~

wonderland numberの見つけ方を見つけてください。
wonderland numberとは、6桁の数字のうち、2、3、4、5、6のいずれかで掛け算した時に数字の並び順だけが変わる数字のことです。
例えば100035は3倍すると300105になるので、Wonderland Numberです。
他には、下記のような具体例があります。
100350を3倍
125874を2倍
128574を2倍
102564を4倍
103845を4倍
142857を5倍
148257を5倍
106848を6倍
120267を6倍

# Word Wrap

文字列と数値が与えられた時、その文字列を改行して出力してください。
与えられた数値は、一行に入る最大文字数です。
ワープロのように、各行の右側がはみ出ないようにしてください。

# Yatzy

yatzyゲームはシンプルなサイコロのゲームです。
プレイヤーは5つの6面サイコロを振ります。その結果を見て、自分で役を選び、得点を得ることができます（複数の役に当てはまる場合は自分で選ぶことができます）。
サイコロを振った結果とプレイヤーが選んだ役が入力されるので、スコアを算出してください。
詳しいルールはこちらhttps://ja.wikipedia.org/wiki/%E3%83%A4%E3%83%83%E3%83%84%E3%82%A3%E3%83%BC

# Yatzy Cutdown

役の少ないYatzyです。

# ~~Zeckendorf Number~~

0から20までのZeckendorf Numberを作ってください。
Zeckendorf Numberとは、二進数とフィボナッチ数列を混ぜたような形の数値表現です。二進数の各桁の表す数が1、2、4、8と増えていくように、Zeckendorf Numberの各桁の表す数が1、2、3、5、8、13と増えていきます。
例えば、11は下記のように表せます。

    0*13 + 1*8 + 0*5 + 1*3 + 0*2 + 0*1
    => 10100

Zeckendorf Numberにはもう一つの制限があります。それは、1が連続してはいけない（隣り合うフィボナッチ数列の数を使ってはいけない）という制限です。
実は11の表し方はこの一通りだけではなく、下記のように3通りあります。その重複を防ぎ一意に定めるための制限です。

    10100
    10011
    1111



# 主観による難易度分け

主観で難度を分けました。難易度は、実装に関する難易度です。TDDの難易度と必ずしも一致する訳ではないのでご注意を。
個人的TDD面白そう問題は、Monty Hall、Wonderland Number、Zeckendorf Number、Array Shuffleあたり。
## ちょっと向いてない系（テストに工夫要る系・問題補正必要系など）
- 100 doors
- Count Coins
- Diversion
- Eight Queens
- Friday 13th
- Haiku Review
- Magic Square
- Monty Hall
- Wonderland Number
- Zeckendorf Number

## 難しそう系
- Reversi
- Tiny Maze

## 時間かかりそう系
- Mine Field
- Poker Hands
- Revers Roman
- Romen Numerals
- Saddle Points
- Yatzy
- Bowling Game

## よくある系
- Anagrams
- Balanced Parentheses
- Combined Number
- Game of Life
- Gray Code
- Harry Potter
- ISBN
- Mars Rover
- Prime Factors
- Recently Used List
- Reordering
- Yatzy Cutdown

## 入門系
- Array Shuffle
- Calc Stats
- Closest To Zero
- Fizz Buzz
- Fizz Buzz Plus
- LCD Digits
- Leap Year
- Number Chains
- Number Names
- Phone Number
- Print Diamond
- Remove Duplicate
- Tennis
- Unsplice
- Word Wrap