Day 20
Mix.install([
{:kino, "~> 0.14.2"},
{:math, "~> 0.7.0"}
])
IEx.Helpers.c("/Users/johnb/dev/2015adventOfCode/advent_of_code.ex")
alias AdventOfCode, as: AOC
alias Kino.Input
require Integer
# Note: when making the next template, something like this works well:
# `cat day01.livemd | sed 's/01/02/' > day02.livemd`
#
Installation and Data
input_p1example = Kino.Input.textarea("Example Data")
input_p1puzzleInput = Kino.Input.textarea("Puzzle Input")
input_source_select =
Kino.Input.select("Source", [{:example, "example"}, {:puzzle_input, "puzzle input"}])
p1data = fn ->
(Kino.Input.read(input_source_select) == :example &&
Kino.Input.read(input_p1example)) ||
Kino.Input.read(input_p1puzzleInput)
end
Part 1
defmodule Day20 do
@presents_per_elf 10
@presents_per_elf_part2 11
# factors_of/1 cribbed from:
# https://github.com/tajacks/elixir-multitool/blob/main/lib/multitool/numbers/factors.ex
def factors_of(n) when is_integer(n) do
upper_range = floor(:math.sqrt(n))
factors = for x <- 1..upper_range, rem(n, x) == 0, do: [x, div(n, x)]
List.flatten(factors) |> Enum.dedup()
end
def solve1(text) do
target = String.to_integer(text) / @presents_per_elf
t_over_e = floor(target / Math.e())
factors = factors_of(t_over_e)
IO.inspect([target, Math.log(target), t_over_e, Enum.sum(factors)])
Enum.each(floor(t_over_e / 2)..(2 * t_over_e), fn house_num ->
factors = factors_of(house_num)
factor_sum = Enum.sum(factors)
if factor_sum >= target do
IO.puts("SUCCESS! house_num=#{house_num}")
raise String
end
end)
end
def solve2(text) do
target = ceil(String.to_integer(text) / @presents_per_elf_part2)
part1_answer = 831600
Enum.each(part1_answer..(2 * part1_answer), fn guess ->
presents = (guess
|> factors_of()
|> Enum.reject(fn x -> x < guess / 50 end)
|> Enum.sum()
)
if presents >= target do
IO.inspect([target, guess, presents], label: "Success at #{guess}!")
raise Integer
end
end)
end
end
# Example data:
# p1data.()
# |> Day20.solve1()
# |> IO.inspect(label: "\n*** Part 1 solution (example: 2)")
# 831600
p1data.()
|> Day20.solve2()
|> IO.inspect(label: "\n*** Part 2 solution (example: 2)")
# 776160 is too low
# 856800 is also too low