Elixir 練習問題 StringsAndBinaries-1

defmodule ASCII do
  def is_printable(charlist) do
    charlist
    |> Enum.map(&printable?/1)
    |> Enum.all?
  end

  defp printable?(c) do
    (32 <= c) and (c <= 126)
  end
end
^o^ > iex practice_11_1.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> ASCII.is_printable('hello')
true
iex(2)> ASCII.is_printable('hello\n')
false

Elixir 練習問題 ListsAndRecursion-8

defmodule Order do
  def sales_tax(orders, tax_rates) do
    orders
    |> Enum.map(fn o -> {o, tax_rate(o, tax_rates)} end)
    |> Enum.map(fn {o, tax_rate}
        -> Keyword.put(o, :total_amount, add_tax(o, tax_rate)) end)
  end

  defp tax_rate(order, rates) do
    ship_to = Keyword.get(order, :ship_to)
    Keyword.get(rates, ship_to, 0.0)
  end

  defp add_tax(order, tax_rate) do
    Keyword.get(order, :net_amount) * (1.0 + tax_rate)
  end
end


tax_rates = [ NC: 0.075, TX: 0.08 ]

orders = [
  [ id: 123, ship_to: :NC, net_amount: 100.00 ],
  [ id: 124, ship_to: :OK, net_amount:  35.50 ],
  [ id: 125, ship_to: :TX, net_amount:  24.00 ],
  [ id: 126, ship_to: :TX, net_amount:  44.80 ],
  [ id: 127, ship_to: :NC, net_amount:  25.00 ],
  [ id: 128, ship_to: :MA, net_amount:  10.00 ],
  [ id: 129, ship_to: :CA, net_amount: 100.00 ],
  [ id: 130, ship_to: :NC, net_amount:  50.00 ] ]


Order.sales_tax(orders, tax_rates)
|> Enum.each(&IO.inspect/1)
^o^ > elixir practice_10_4.exs
[total_amount: 107.5, id: 123, ship_to: :NC, net_amount: 100.0]
[total_amount: 35.5, id: 124, ship_to: :OK, net_amount: 35.5]
[total_amount: 25.92, id: 125, ship_to: :TX, net_amount: 24.0]
[total_amount: 48.384, id: 126, ship_to: :TX, net_amount: 44.8]
[total_amount: 26.875, id: 127, ship_to: :NC, net_amount: 25.0]
[total_amount: 10.0, id: 128, ship_to: :MA, net_amount: 10.0]
[total_amount: 100.0, id: 129, ship_to: :CA, net_amount: 100.0]
[total_amount: 53.75, id: 130, ship_to: :NC, net_amount: 50.0]

total_amount が最初に追加されちゃってるのがちょっと気に入らないけど、まあいいか。

Elixir 練習問題 ListsAndRecursion-7

以前に作った span 関数と内包表記を使って 2 から n までの素数。

defmodule MyList do
  def span(from, to) when from == to, do: [to]
  def span(from, to),                 do: [from | span(from + 1, to)]

  def primes(n) do
    for x <- span(2, n), is_prime(x), do: x
  end

  defp is_prime(2), do: true
  defp is_prime(3), do: true
  defp is_prime(n) do
    m = div(n, 2)
    Enum.all?(Enum.map(span(2, m), fn x -> rem(n, x) != 0 end))
  end
end
^o^ > iex practice_10_3.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.primes(50)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Elixir 練習問題 ListsAndRecursion-6

flattenn

defmodule MyList do
  def flatten(list) do
    _flatten(list, [])
  end
  defp _flatten([], r) do
    Enum.reverse(r)
  end
  defp _flatten([head|tail], r) do
    if is_list(head) do
      _flatten(tail, Enum.reverse(flatten(head)) ++ r)
    else
      _flatten(tail, [head | r])
    end
  end
end
^o^ > iex practice_10_2.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.flatten([1, [2, 3, [4] ], 5, [[[6]]]])
[1, 2, 3, 4, 5, 6]

Elixir 練習問題 ListsAndRecursion-5

次の関数を、ライブラリやリスト内包表記を利用せずに実装しろ、と。

  • all?
  • each
  • filter
  • split
  • take
defmodule MyList do

  def all?([]), do: true
  def all?([head | tail]) when head, do: all?(tail)
  def all?(_list), do: false

  def each([], _func) do
  end
  def each([head|tail], func) do
    func.(head)
    each(tail, func)
  end

  def filter([], _prod) do
    []
  end
  def filter([head|tail], prod) do
    if prod.(head) do
      [head | filter(tail, prod)]
    else
      filter(tail, prod)
    end
  end

  def split(list, n), do: _split({[], list}, n)
  defp _split(result, 0), do: result
  defp _split(result = {_left, []}, _), do: result
  defp _split({left, [head|tail]}, n), do: _split({left ++ [head], tail}, n - 1)

  def take(list, n) do
    {result, _} = split(list, n)
    result
  end

end

順番に行ってみよう。まずは all?

^o^ > iex practice_10_1.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.all?([true, true, true])
true
iex(2)> MyList.all?([true, false, true])
false

つぎに each

iex(3)> MyList.each([1, 2, 3], &IO.puts/1)
1
2
3
nil

nileach 自体の返り値かな。
つぎ、filter

iex(4)> MyList.filter([1, 2, 3, 4, 5], &(&1 > 2))
[3, 4, 5]

split

iex(5)> MyList.split([1, 2, 3, 4, 5], 2)
{[1, 2], [3, 4, 5]}

最後に take

iex(6)> MyList.take([1, 2, 3, 4, 5], 3)
[1, 2, 3]

Elixir 練習問題 ListsAndRecursion-4

defmodule MyList do

  def map([], _func), do: []
  def map([head|tail], func), do: [func.(head) | map(tail, func)]

  def reduce([], value, _func) do
    value
  end
  def reduce([head|tail], value, func) do
    reduce(tail, func.(head, value), func)
  end

  def span(from, to) when from == to, do: [to]
  def span(from, to), do: [from | span(from + 1, to)]

end
^o^ > iex practice_7_4.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.span(3, 7)
[3, 4, 5, 6, 7]

mapreduce も使ってないな。

Elixir 練習問題 ListsAndRecursion-3

今度の練習問題はカエサル暗号だ。

defmodule MyList do

  def map([], _func), do: []
  def map([head|tail], func), do: [func.(head) | map(tail, func)]

  def reduce([], value, _func) do
    value
  end
  def reduce([head|tail], value, func) do
    reduce(tail, func.(head, value), func)
  end

  def caesar(list, n) do
    map(list, fn c -> rem(c + n - ?a, 26) + ?a end)
  end

end
^o^ > iex practice_7_3.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.caesar('ryvkve', 13)
'elixir'

Elixir 練習問題 ListsAndRecursion-2

defmodule MyList do

  def reduce([], value, _func) do
    value
  end
  def reduce([head|tail], value, func) do
    reduce(tail, func.(head, value), func)
  end

  def max([head|tail]) do
    reduce(tail, head, &_max/2)
  end

  defp _max(a, b) when a < b, do: b
  defp _max(a, _), do: a

end
^o^ > iex practice_7_2.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.max([1,2,3,4,5])
5
iex(2)> MyList.max([5,4,3,2,1])
5

Elixir 練習問題 ListsAndRecursion-1

defmodule MyList do

  def map([], _func), do: []
  def map([head|tail], func), do: [func.(head) | map(tail, func)]

  def reduce([], value, _func) do
    value
  end
  def reduce([head|tail], value, func) do
    reduce(tail, func.(head, value), func)
  end

  def mapsum(list, func) do
    map(list, func)
    |> reduce(0, &(&1 + &2))
  end

end
^o^ > iex practice_7_1.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.mapsum([1, 2, 3], &(&1 * &1))
14