年俸1000万の会社の試験問題

 名古屋Scala練習場の問題がTwitterに取り上げられていたので、F#で挑戦してみました。
 シーケンスの練習問題としてとてもいい問題なのではないかと思います。

お題

4種類のアルファベット "A,C,G,T" から成るn文字の文字列のうち、"AAG"という並びが含まれる文字列を全て列挙するプログラムを書きなさい。ただし、nは3以上の整数とし、文字列内に同じアルファベットが出現しても構わないものとし、出力順序は問わないものとします。

... 適性検査に合格された方はその生産性を実現可能な方です。生産性に見合う初任給として年俸1000万円をご用意しております。

元ネタはこちら
(しかしハニトラっぽいなぁこれ)っていうか、適性検査はPerlまたはJavaって書いてあるw

F#だと5行

let rec create s n = 
  match n with
  | 0 -> seq {yield s}
  | n -> seq {for c in  [|"A"; "G"; "C"; "T"|] do yield! create (s + c) (n - 1)}
let solve n = Seq.filter (fun (s : string) -> s.IndexOf("AAG") > -1 ) (create "" n)
 でもイマイチスマートじゃないなぁ・・・・もっといい方法あると思うけど。
 seqとか無理に1行に書いてるしw 

 Haskellだと4行となっていますが、実際にロジックは2行ですよね。Haskell恐るべし。
 Scala恐るるに足らず(と逃げながら言ってみるテスト)。

発展問題

 単体テストなどやっていると、全ての要素について全ての組み合わせを求めたいことが結構あります。
let dat = [ ["A"; "B"; "C"]; ["1"; "2"; "3"; "4"; "5"]; ["甲"; "乙"; "丙"; "丁"] ]
let rec create2 l a = 
  match l with
  | [] -> seq { yield a }
  | h :: t -> seq { for c in h do yield! create2 t (c :: a) }
Seq.iter (fun s -> printfn "%A" s) (create2 dat []);;
 リストのリストを引数にとって、各要素から一つずつ取り出した全ての組み合わせを返すシーケンスです。こういうのって最初はものすごく苦労するんですよね。

(文責:片山 功士  2012/01/10)

他の勇者の回答例

 ながとさんの回答例
  三種類の例を出されていますが、最初の例はの回答をブラッシュアップした形になっているようです。こうしてみると僕の使っていない書き方をいくつか使ってすっきりさせています。
  1. seq {yield s} は [s]と書いてもOK。
  2. [|"A"; "G"; "C"; "T"|]は"AGCT"と書いてもいいが、型はseq<char>となる。
  3. 最後のsolveは、パイプ演算子|>を使って書くと、filterの中のfunの引数に型を書かなくてもよくなる!
  4. String.IndexOfは、インデックスを使わないで存在チェックだけならContainsでOK。
 いげ太さんの回答例
 Haskell版のプログラムの形をあまり変えないように作っています。

 言語は違いますが、TMiya_さんのCoqでの実装例
 ぼくはCoqはちょっとかじった程度なのですが、この言語でプログラム作るって凄いと・・・


今日: -
昨日: -
トータル: -
最終更新:2012年02月03日 02:00