Chapter 11
Mix.install([
{:kino, "~> 0.8"}
])
Exercise: StringsAndBinaries-1, 2, 4
defmodule CharList do
def printable([]), do: true
def printable([head | tail]) when head in ?\s..?~, do: printable(tail)
def printable(_), do: false
def anagram?(word1, word2), do: normalize(word1) == normalize(word2)
defp normalize(word), do: word |> :string.lowercase() |> :lists.sort() |> :string.trim()
def calculate(expression) do
[term1, operator, term2] = :re.split(expression, ' ')
calculate(String.to_integer(term1), String.to_integer(term2), operator)
end
defp calculate(term1, term2, "+"), do: term1 + term2
defp calculate(term1, term2, "-"), do: term1 - term2
defp calculate(term1, term2, "*"), do: term1 * term2
defp calculate(term1, term2, "/"), do: term1 / term2
end
true = CharList.printable('Hello, world!')
false = CharList.printable('Hello, world!' ++ [0])
true = CharList.anagram?('New York Times', 'monkeys write')
false = CharList.anagram?('hello', 'world')
CharList.calculate('123 + 27')
Exercise: StringsAndBinaries-3
'cat'
itself is not a codepoint. Therefore, ['cat', 100, 111, 103]
, which is [[99, 97, 116], 100, 111, 103]
, is not shown as a string.
Exercise: StringsAndBinaries-5 & 6
defmodule MyString do
def center(strings) do
width = strings |> Enum.map(&String.length/1) |> Enum.max()
strings |> Enum.map(&indent_to_centre(&1, width)) |> Enum.each(&IO.puts/1)
end
defp indent_to_centre(str, width) do
intents = div(width - String.length(str), 2)
String.duplicate(" ", intents) <> str
end
def capitalize_sentences(str) do
str
|> String.split(". ")
|> Enum.map_join(". ", &String.capitalize/1)
end
end
MyString.center(["cat", "zebra", "elephant"])
"Oh. A dog. Woof. " = MyString.capitalize_sentences("oh. a DOG. woof. ")
Exercise: StringsAndBinaries-7
defmodule Order do
@tax_rates [NC: 0.075, TX: 0.08]
def calculate(file_path) do
file_path
|> File.stream!()
|> Stream.drop(1)
|> Stream.map(&String.trim/1)
|> Stream.map(&parse/1)
|> sales_tax()
# Enum version
# file_path
# |> File.read!()
# |> String.split("\n", trim: true)
# |> Enum.drop(1)
# |> Enum.map(&parse/1)
# |> sales_tax()
end
defp parse(row) do
[id, ship_to, net_amount] = String.split(row, ",")
[
id: String.to_integer(id),
ship_to: ship_to |> String.trim_leading(":") |> String.to_atom(),
net_amount: String.to_float(net_amount)
]
end
def sales_tax(orders, tax_rates \\ @tax_rates) do
for order <- orders do
tax_rate = Keyword.get(tax_rates, order[:ship_to], 0)
total_amount = order[:net_amount] * (1 + tax_rate)
order ++ [total_amount: total_amount]
end
end
end
file_input = Kino.Input.file("Sales information")
value = Kino.Input.read(file_input)
Order.calculate(value.path)