defmodule DaySix do def part_one(input) do coords = parse_input(input) corners = find_corners(coords) distances = distances(corners, coords) legal = filter_infinite(distances, corners) # IO.puts "Total: #{length distances} Legal: #{length legal}" length = Enum.group_by(legal, fn {_, coord} -> coord end) |> Enum.map(fn {_key, list} -> length list end) |> Enum.max length end def part_two(input) do coords = parse_input(input) {maxx, maxy, _minx, _miny} = find_corners(coords) field = gen_field({maxx * 2, maxy * 2, 0, 0}) filter_below(field, coords, 10000) |> length end def parse_input(input) do lines = String.split(input, "\n") |> Enum.filter(&(&1 != "")) lines |> Enum.map(&(String.split(&1, ", "))) |> Enum.map(fn [x, y] -> {String.to_integer(x), String.to_integer(y)} end) end def find_corners(coords) do {maxx, _} = Enum.max_by(coords, fn {x, _} -> x end) {_, maxy} = Enum.max_by(coords, fn {_, y} -> y end) {minx, _} = Enum.min_by(coords, fn {x, _} -> x end) {_, miny} = Enum.min_by(coords, fn {_, y} -> y end) {maxx, maxy, minx, miny} end def gen_field({maxx, maxy, minx, miny}) do Enum.map(minx..maxx, fn i -> Enum.map(miny..maxy, fn j -> {i, j} end) end) |> List.flatten end def distances({maxx, maxy, minx, miny}, coords) do Enum.map(minx..maxx, fn i -> Enum.map(miny..maxy, fn j -> distances = Enum.map(coords, fn {x, y} -> {{x, y}, abs(i - x) + abs(j - y)} end) {{x, y}, distance} = Enum.min_by(distances, fn {_, distance} -> distance end) if length(Enum.filter(distances, fn {_, d} -> distance == d end)) > 1 do [] else {{i, j}, {x, y}} end end) end) |> List.flatten # |> Map.new end def is_border({maxx, maxy, minx, miny}, {x, y}) when x == maxx or x == minx or y == maxy or y == miny, do: true def is_border(_, _), do: false def filter_infinite(distances, corners) do is_infinite = Enum.map(distances, fn {{i, j}, {x, y}} -> {{x, y}, is_border(corners, {i, j})} end) |> Enum.group_by(fn {coord, _} -> coord end) |> Enum.map(fn {coord, list} -> {coord, Enum.map(list, fn {_, inf} -> inf end)} end) # IO.inspect is_infinite infinites = is_infinite |> Enum.filter(fn {_, list} -> Enum.member?(list, true) end) |> Enum.map(fn {coord, _} -> coord end) # IO.puts "Infinites: #{length infinites}" Enum.filter(distances, fn {_, coord} -> not Enum.member?(infinites, coord) end) end def total_distance({i, j}, points) do Enum.map(points, fn {x, y} -> abs(x - i) + abs(y - j) end) |> List.foldl(0, &+/2) end def filter_below(coords, points, under) do total_distances = Enum.map(coords, fn coord -> {coord, total_distance(coord, points)} end) Enum.filter(total_distances, fn {_, dist} -> dist < under end) end end {:ok, content} = File.read("input6.txt") IO.puts("Part 1: #{DaySix.part_one(content)}") IO.puts("Part 2: #{DaySix.part_two(content)}")