Skip to content

Instantly share code, notes, and snippets.

@sasa1977
Last active December 21, 2017 16:16
Show Gist options
  • Save sasa1977/1246dc75886faf7da6b7956d158c2420 to your computer and use it in GitHub Desktop.
Save sasa1977/1246dc75886faf7da6b7956d158c2420 to your computer and use it in GitHub Desktop.
defmodule Day21 do
def part1(), do:
enhancements() |> generate_art(5) |> count_pixels()
def part2(), do:
enhancements() |> generate_art(18) |> count_pixels()
defp count_pixels(grid), do:
Enum.count(for <<bit::1 <- grid>>, bit == 1, do: bit)
defp generate_art(enhancements, steps), do:
initial_grid()
|> Stream.iterate(&step(&1, enhancements))
|> Stream.drop(steps)
|> Enum.take(1)
|> hd
defp initial_grid(), do:
[
".#.",
"..#",
"###",
]
|> Enum.map(&encode_row/1)
|> concat_bitstrings()
defp step(grid, enhancements), do:
grid |> squares() |> Enum.map(&Map.fetch!(enhancements, &1)) |> rebuild_grid()
defp squares(grid) do
grid_size = trunc(:math.sqrt(bit_size(grid)))
square_size = if rem(grid_size, 2) == 0, do: 2, else: 3
(for <<cells::size(square_size) <- grid>>, do: <<cells::size(square_size)>>)
|> Stream.chunk_every(div(grid_size, square_size))
|> Stream.chunk_every(square_size)
|> Stream.flat_map(&Stream.zip/1)
|> Stream.map(&Tuple.to_list/1)
|> Enum.map(&concat_bitstrings/1)
end
defp rebuild_grid(squares) do
square_size = squares |> hd() |> bit_size() |> :math.sqrt() |> trunc()
squares_per_row = trunc(:math.sqrt(length(squares)))
squares
|> Stream.chunk_every(squares_per_row)
|> Stream.flat_map(&rebuild_row(&1, square_size))
|> concat_bitstrings()
end
defp rebuild_row(row_squares, square_size), do:
row_squares
|> Stream.map(&(for <<cells::size(square_size) <- &1>>, do: <<cells::size(square_size)>>))
|> Stream.zip()
|> Stream.flat_map(&Tuple.to_list/1)
defp enhancements(), do:
"input.txt"
|> File.stream!()
|> Stream.map(&String.trim/1)
|> Stream.flat_map(&String.split(&1, " => "))
|> Stream.map(&parse_square/1)
|> Stream.chunk_every(2)
|> Stream.map(&List.to_tuple/1)
|> Map.new()
|> expand_enhancements()
defp parse_square(square), do:
square
|> String.split("/")
|> Stream.map(&encode_row/1)
|> concat_bitstrings()
defp encode_row(row), do:
row
|> String.codepoints()
|> Stream.map(&to_bit/1)
|> concat_bitstrings()
defp to_bit("."), do: <<0::1>>
defp to_bit("#"), do: <<1::1>>
defp concat_bitstrings(bitstrings), do:
Enum.reduce(bitstrings, <<>>, &<<&2::bitstring, &1::bitstring>>)
defp expand_enhancements(enhancements), do:
0..15
|> Stream.map(&<<&1::4>>)
|> Stream.concat(Stream.map(0..511, &<<&1::9>>))
|> Stream.map(&{&1, transformations(&1)})
|> Stream.map(fn {input, transformations} ->
{input, Enum.find_value(transformations, &Map.get(enhancements, &1))}
end)
|> Map.new()
defp transformations(square), do:
square
|> Stream.iterate(&rotate/1)
|> Stream.take(4)
|> Stream.flat_map(fn square -> [square, flip_horizontal(square), flip_vertical(square)] end)
|> Enum.uniq()
defp rotate(
<<a::1, b::1,
c::1, d::1>>
), do:
<<c::1, a::1,
d::1, b::1>>
defp rotate(
<<a::1, b::1, c::1,
d::1, e::1, f::1,
g::1, h::1, j::1>>
), do:
<<g::1, d::1, a::1,
h::1, e::1, b::1,
j::1, f::1, c::1>>
defp flip_horizontal(
<<a::1, b::1,
c::1, d::1>>
), do:
<<c::1, d::1,
a::1, b::1>>
defp flip_horizontal(
<<a::1, b::1, c::1,
d::1, e::1, f::1,
g::1, h::1, j::1>>
), do:
<<g::1, h::1, j::1,
d::1, e::1, f::1,
a::1, b::1, c::1>>
defp flip_vertical(
<<a::1, b::1,
c::1, d::1>>
), do:
<<b::1, a::1,
d::1, c::1>>
defp flip_vertical(
<<a::1, b::1, c::1,
d::1, e::1, f::1,
g::1, h::1, j::1>>
), do:
<<c::1, b::1, a::1,
f::1, e::1, d::1,
j::1, h::1, g::1>>
end
Day21.part1() |> IO.inspect()
Day21.part2() |> IO.inspect()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment