関数型プログラミングの練習問題として 99 Haskel Problems というのがあります。
この記事では、Elixir を用いて問題の解答例を紹介します。
Problem 1
問題
Find the last element of a list.
リストの末尾要素を見つけよ。
iex> Prob01.my_last([1, 2, 3, 4])
4
iex> Prob01.my_string_last("elixir")
"r"解答例
defmodule Prob01 do
def my_last([]), do: nil
def my_last([x]), do: x
def my_last([_ | tail]), do: my_last(tail)
def my_string_last(string), do: string |> String.graphemes() |> my_last()
end標準ライブラリでの実行例
iex> List.last([1, 2, 3, 4])
4
iex> String.last("elixir")
"r"Problem 2
問題
Find the last-but-one (or second-last) element of a list.
リストの末尾からひとつ手前の要素を見つけよ。
iex> Prob02.my_but_last([1, 2, 3, 4])
3
iex> Prob02.my_string_but_last("elixir")
"i"解答例1
defmodule Prob02 do
def my_but_last([]), do: nil
def my_but_last([_]), do: nil
def my_but_last([x, _]), do: x
def my_but_last([_ | tail]), do: my_but_last(tail)
def my_string_but_last(string), do: string |> String.graphemes() |> my_but_last()
end解答例2
defmodule Prob02 do
def my_but_last(list), do: list |> Enum.drop(-1) |> List.last()
def my_string_but_last(string), do: string |> String.graphemes() |> my_but_last()
endProblem 3
問題
Find the K’th element of a list.
リストの K番目の要素を見つけよ。
iex> Prob03.my_at([1, 2, 3, 4], 2)
3
iex> Prob03.my_string_at("elixir", 3)
"x"解答例
defmodule Prob03 do
def my_at([], _), do: nil
def my_at([head | _], 0), do: head
def my_at([_ | tail], n), do: my_at(tail, n - 1)
def my_string_at(string, n), do: string |> String.graphemes() |> my_at(n)
end標準ライブラリでの実行例
Problem 4
問題
Find the number of elements in a list.
リストの要素数を求めよ。
iex> Prob04.my_length([1, 2, 3, 4])
4
iex> Prob04.my_string_length("elixir")
6解答例
defmodule Prob04 do
def my_length([]), do: 0
def my_length([_ | tail]), do: 1 + length(tail)
def my_string_length(string), do: string |> String.graphemes() |> my_length()
end標準ライブラリでの実行例
iex> length([1, 2, 3, 4])
4
iex> String.length("elixir")
6Problem 5
問題
Reverse a list.
リストを反転せよ。
iex> Prob05.my_reverse([1, 2, 3, 4])
[4, 3, 2, 1]
iex> Prob05.my_string_reverse("A man, a plan, a canal, panama!")
"!amanap ,lanac a ,nalp a ,nam A"解答例
defmodule Prob05 do
def my_reverse(list), do: List.foldl(list, [], fn x, acc -> [x | acc] end)
def my_string_reverse(string) do
string |> String.graphemes() |> my_reverse() |> List.to_string()
end
end標準ライブラリでの実行例
iex> Enum.reverse([1, 2, 3, 4])
[4, 3, 2, 1]
iex> String.reverse("A man, a plan, a canal, panama!")
"!amanap ,lanac a ,nalp a ,nam A"Problem 6
問題
Find out whether a list is a palindrome.
リストが回文構造になっているかどうか判別せよ。
iex> Prob06.is_palindrome([1, 2, 3])
false
iex> Prob06.is_palindrome([1, 2, 4, 8, 16, 8, 4, 2, 1])
true解答例
defmodule Prob06 do
def is_palindrome(list), do: list == Enum.reverse(list)
endProblem 7
問題
Flatten a nested list structure.
ネスト構造のリストをフラットにせよ。
iex> Prob07.my_flatten([1, [2, [3, 4], 5]])
[1, 2, 3, 4, 5]解答例
defmodule Prob07 do
def my_flatten([]), do: []
def my_flatten([head | tail]) do
cond do
is_list(head) -> my_flatten(head) ++ my_flatten(tail)
true -> [head | my_flatten(tail)]
end
end
end標準ライブラリでの実行例
iex> List.flatten([1, [2, [3, 4], 5]])
[1, 2, 3, 4, 5]Problem 8
問題
Eliminate consecutive duplicates of list elements.
リストから連続した重複要素を除去せよ。
iex> Prob08.compress("aaaabccaadeeee")
"abcade"解答例
defmodule Prob08 do
def compress(string) do
string
|> String.graphemes()
|> Enum.chunk_by(&Function.identity/1)
|> Enum.map(&List.first/1)
|> List.to_string()
end
endProblem 9
問題
Pack consecutive duplicates of list elements into sublists.
リストから連続した重複要素をサブリストとしてまとめよ。
iex> Prob09.pack("aaaabccaadeeee")
"abcade"解答例
defmodule Prob09 do
def pack(string) do
string
|> String.graphemes()
|> Enum.chunk_by(&Function.identity/1)
|> Enum.map(&List.to_string/1)
end
endProblem 10
問題
Run-length encoding of a list.
リストに対してランレングス圧縮を施せ。
iex> Prob10.encode("aaaabccaadeeee")
[{4, "a"}, {1, "b"}, {2, "c"}, {2, "a"}, {1, "d"}, {4, "e"}]解答例
defmodule Prob10 do
def encode(string) do
string
|> String.graphemes()
|> Enum.chunk_by(&Function.identity/1)
|> Enum.map(fn x -> {length(x), List.first(x)} end)
end
end



コメント