問題5 の elixir版
http://www.softantenna.com/wp/software/5-programming-problems/
1時間以内に解けなければプログラマ失格となってしまう5つの問題が話題に
の
問題5
1,2,…,9の数をこの順序で、”+”、”-“、またはななにもせず結果が100となるあらゆる組合せを出力するプログラムを記述せよ。例えば、1 + 2 + 34 - 5 + 67 - 8 + 9 = 100となる
をelixirでやってみる。
-
- -
● お答え。17行で答が出る。
defmodule Make do def make([],[h|t]) do # 始め make( [h] , t ) end def make(prefix,[]) do # 最後 case Code.eval_string(prefix) do {100, _} -> [ prefix ] _ -> [ ] end end def make(prefix,[h|t]) do # 途中 make( prefix ++ '+' ++ [h] , t ) ++ make( prefix ++ '-' ++ [h] , t ) ++ make( prefix ++ [h] , t ) end end Make.make([],'123456789')
-
- -
● iex に放り込んで実行してみる。
[tk@NA501-33 ~]$ iex Erlang/OTP 17 [erts-6.4.1] [source] [64-bit] [async-threads:10] [kernel-poll:false] Interactive Elixir (1.0.4) - press Ctrl+C to exit (type h() ENTER for help) iex(2)> defmodule Make do ...(2)> def make([],[h|t]) do # 始め ...(2)> make( [h] , t ) ...(2)> end ...(2)> def make(prefix,[]) do # 最後 ...(2)> case Code.eval_string(prefix) do ...(2)> {100, _} -> [ prefix ] ...(2)> _ -> [ ] ...(2)> end ...(2)> end ...(2)> def make(prefix,[h|t]) do # 途中 ...(2)> make( prefix ++ '+' ++ [h] , t ) ++ ...(2)> make( prefix ++ '-' ++ [h] , t ) ++ ...(2)> make( prefix ++ [h] , t ) ...(2)> end ...(2)> end {:module, Make, <<70, 79, ...>>, {:make, 1}} iex(4)> Make.make([],'123456789') ['1+2+3-4+5+6+78+9', '1+2+34-5+67-8+9', '1+23-4+5+6+78-9', '1+23-4+56+7+8+9', '12+3+4+5-6-7+89', '12+3-4+5+67+8+9', '12-3-4+5-6+7+89', '123+4-5+67-89', '123+45-67+8-9', '123-4-5-6-7+8-9', '123-45-67+89']
何をやっているかというと・・・、
3個の make/2 関数はすべて、リスト文字列の prefix と rest を受け取って、条件にマッチしたリスト文字列のリストを返す、という点で共通。
make/2関数は再帰的に呼ばれる。最初はprefix=''、restは全部。呼ばれるに従ってprefixが延びていき、restは短くなっていく。
「途中」の「make(prefix,[h|t])」関数はprefix文字列の最後に、「+」「-」「」を挟んで、rest文字列の先頭の文字(h)を追加して、下位のmake/2関数を呼び出す。「+」「-」「」を挟むので3回呼び出して、それぞれが返して来た文字列のリストを合成して返す。
「最後」の「make(prefix,[])」関数は、受け取った prefix が条件にマッチした場合には、その文字列が一つだけ入ったリストを返す。マッチしない場合には空リストを返す。もしマッチ判断をせずに全て返した場合には、最初の make/2 関数は3の8乗(=6561)個の文字列のリストを返すことになる。
-
- -
◎ elixir って、超おもしろい。