縁あって、東京ですけど、fukuoka.ex でElixir楽しーと叫んでるYOSUKENAKAO.meです。
普段は、ハッカソン等のイベントの運営をしたり、新規事業が中々うまく進まないといった悩みに対して、バックキャスティング思考のプロセスを導入する事で、社員とチームの生産性を高める教育をし、その後、企業の文化にあったオリジナル教材を開発して定着化させる事の支援をしています。
現在は、世界で活躍できるエンジニアの育成を目指して事業を仕込み中です。
仲間募集中なので、是非、今の日本に一石を投じたい方はDMください。
fukuoka.exのpiacereさんが書かれたElixirのチュートリアルExcelから関数型言語マスター1回目:データ行の”並べ替え”と”絞り込み”
は非常に入りやすい教材なのでお勧めです。第7回まであるので、まだやっていない方は是非トライしてみてください。
言語処理100本ノック
東北大学の 乾・岡崎研究室のトレーニング教材である「言語処理100本ノック」というものを見つけて、学習教材として良さげだったので、Elixirで挑戦して見ました。
言語処理100本ノック
長いので、ちょっとずつ進めて行きます。
ぜひ、皆さん、チャレンジして見てください。そして、こんなやり方もあるよーと教えてください。
第1章: 準備運動
00.文字列の逆順
文字列"stressed"の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.
String.reverse("stressed")
"desserts"
01.「パタトクカシーー」
「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.
String.codepoints("パタトクカシーー")
|> Enum.take_every(2)
|> Enum.join
"パトカー"
02.「パトカー」+「タクシー」=「パタトクカシーー」
「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.
input = String.codepoints("パトカー")
input2 = String.codepoints("タクシー")
Enum.zip([input, input2])
|> Enum.map(zip, fn x -> (Tuple.to_list(x))end)
|> List.flatten
|> List.to_string
"パタトクカシーー”
03.円周率
"Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.
input = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
String.replace(input,~r/[,.]/,"")
|> String.split(" ")
|> Enum.map(fn x -> String.length(x)end)
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]
04.元素記号
"Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭に2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.
以下のモジュールと関数を作成
defmodule Element_symbol do
def list_map(input, instruction) do
String.replace(input,~r/[,.]/,"")
|> String.split(" ")
|> Enum.with_index(1)
|>
Enum.map(fn { key, value } ->
(if value in instruction do
%{ String.at(key,0) |> String.to_atom => value}
else
%{ String.slice(key, 0..1) |> String.to_atom => value}
end)
end )
end
end
実行
input = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
instruction = [1, 5, 6, 7, 8, 9, 15, 16, 19]
Element_symbol.list_map(input, instruction)
[
%{H: 1},
%{He: 2},
%{Li: 3},
%{Be: 4},
%{B: 5},
%{C: 6},
%{N: 7},
%{O: 8},
%{F: 9},
%{Ne: 10},
%{Na: 11},
%{Mi: 12},
%{Al: 13},
%{Si: 14},
%{P: 15},
%{S: 16},
%{Cl: 17},
%{Ar: 18},
%{K: 19},
%{Ca: 20}
]
ちなみに、リストの中のマップにした理由は、全体をマップ型にすると順番を持たない為、元素記号の順番が崩れてしまうから今回はリストの中のマップにして見ました。
全体をマップ化したパターン
def to_map(input,instruction) do
String.replace(input,~r/[,.]/,"")
|> String.split(" ")
|> Enum.with_index(1)
|> Enum.map(fn { key, value } ->
(if value in instruction do
{ String.at(key,0) , value}
else
{ String.slice(key, 0..1) , value}
end)
end )
|> Enum.into(%{})
end
おまけ、
なるべくifを使いたくなかったので試したのがこちら、せっかくなので、キーワードリスト型にしてます。
お試しで書いたので、関数名がtestなのはご愛嬌でw
def test() do
input = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
instruction = [1, 5, 6, 7, 8, 9, 15, 16, 19]
String.replace(input,~r/[,.]/,"")
|> String.split(" ")
|> Enum.with_index(1)
|> Enum.map(fn {key, value} -> keyword_list(key,value,instruction) end)
end
defp keyword_list(key,value,list) do
case Enum.member?(list,value) do
true -> { String.first(key) |> String.to_atom, value}
false -> { String.slice(key, 0..1) |> String.to_atom, value}
end
end
終わりに
Elixirの面白さは、パズルを解くかのような実装体験にあるので、このような問題集のチャレンジもオススメです。
このような良質な問いを、他にも知っている方がいたら、是非!教えてください。