def build_grid(%Identicon.Image{hex: hex} = image) do
grid =
hex
|> Enum.chunk(3)
**|> Enum.map(&mirror_row/1)**
# &: call the reference of function,
# /1: number of argument to differentiate different function with same name.
**|> List.flatten** # no nested logic
**|> Enum.with_index**
# every element turns into Tuple of {value, index}
# Elixir doesn't provide the index so it's Elixir-style of indexing
%Identicon.Image{image | grid: grid}
end
def mirror_row(row) do
[first, second | _tail] = row
row ++ [second, first]
end
One meets the condition, it passes
iex> Enum.filter([1,2,3], fn(x) -> rem(x, 2) == 0 end)
[2]
Enum.filter(grid, fn(square) -> end)
# is often written in the form of below
Enum.filter grid, fn(square) -> end
# and also
Enum.filter grid, fn(square) ->
# you can write everything you want here
end
# Just for the context
defmodule Identicon.Image do
defstruct hex: nil, color: nil
end
defmodule Identicon do
def main(input) do
input
|> hash_input
|> pick_color
|> build_grid
**|> filter_odd_squares**
end
**def filter_odd_squares(%Identicon.Image{grid: grid} = image) do
Enum.filter grid, fn({code, _index}) ->
rem(code, 2) == 0 # divisible by 2, then it's 0
end**
def build_grid(%Identicon.Image{hex: hex} = image) do
grid =
hex
|> Enum.chunk(3)
|> Enum.map(&mirror_row/1)
|> List.flatten # no nested logic
|> Enum.with_index
%Identicon.Image{image | grid: grid}
end
def mirror_row(row) do
[first, second | _tail] = row
row ++ [second, first]
end
def pick_color(%Identicon.Image{hex: [r,g,b | _tail} = image ) do
%Identicon.Image{image | color: {r, g, b}}
end
def hash_input(input) do
hex = :crypto.hash(:md5, input)
|> :binary.bin_to_list
%Identicon.Image{hex: hex}
end
end
def build_grid(%Identicon.Image{hex: hex} = image) do
grid =
hex
|> Enum.chunk(3)
|> Enum.map(&mirror_row/1)
|> List.flatten
|> Enum.with_index
%Identicon.Image{image | grid: grid}
end
def mirror_row(row) do
[first, second | _tail] = row
row ++ [second, first]
end