Add 2018 files

This commit is contained in:
Daniel Flanagan 2019-12-01 14:55:48 -06:00
parent f50552707f
commit 38e03b1587
16 changed files with 2902 additions and 2 deletions

View file

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

26
2018/elixir/.gitignore vendored Normal file
View file

@ -0,0 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
advent_of_code_2018-*.tar
# Ignore language server files
/.elixir_ls

14
2018/elixir/README.md Normal file
View file

@ -0,0 +1,14 @@
# Advent of Code 2018
Herein lies my Elixir solutions for the Advent of Code 2018 puzzles.
## Approach
My approach to each problem involves the following procedure:
1. Write an initial solution for each puzzle with no help beyond code
documentation.
2. Rewrite initial solutions to improve the code's readability and performance.
3. Watch José Valim (the author of Elixir) solve the solutions.
4. Refactor again, keeping the core of my solution intact (unless truly awful),
but applying anything interesting learned from his solution.

View file

@ -0,0 +1,30 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config
# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for
# 3rd-party users, it should be done in your "mix.exs" file.
# You can configure your application as:
#
# config :advent_of_code_2018, key: :value
#
# and access this configuration in your application as:
#
# Application.get_env(:advent_of_code_2018, :key)
#
# You can also configure a 3rd-party app:
#
# config :logger, level: :info
#
# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env()}.exs"

1017
2018/elixir/inputs/one.txt Normal file

File diff suppressed because it is too large Load diff

1341
2018/elixir/inputs/three.txt Normal file

File diff suppressed because it is too large Load diff

250
2018/elixir/inputs/two.txt Normal file
View file

@ -0,0 +1,250 @@
bvhfawknyoqsudzrpgslecmtkj
bpufawcnyoqxldzrpgsleimtkj
bvhfawcnyoqxqdzrplsleimtkf
bvhoagcnyoqxudzrpgsleixtkj
bxvfgwcnyoqxudzrpgsleimtkj
bvqfawcngoqxudzrpgsleiktkj
bvhfawcnmoqxuyzrpgsleimtkp
bvheawcnyomxsdzrpgsleimtkj
bcdfawcnyoqxudzrpgsyeimtkj
bvhpawcnyoqxudzrpgsteimtkz
bxhfawcnyozxudzrpgsleimtoj
bvhfdwcnyozxudzrposleimtkj
bvpfawcnyotxudzrpgsleimtkq
bvhfpwccyoqxudzrpgslkimtkj
bvhfawcnyoqxudirpgsreimtsj
bvhfawcnyoqxudzppgbleemtkj
bvhzawcnyoqxudqrpgslvimtkj
bvhfawclyoqxudirpgsleimtka
bvhgawfnyoqxudzrpguleimtkj
bvhfazcnytqxudzrpgslvimtkj
bvhfawcnygxxudzrpgjleimtkj
bxhfawcnyoqxudzipgsleimtxj
bvhptwcnyoqxudzrpgsleimtmj
bzhfawcgyooxudzrpgsleimtkj
bvhjlwcnyokxudzrpgsleimtkj
bvhfawcnyoqxudbrmgslesmtkj
bvhfawcnysixudzwpgsleimtkj
bvhflwcnymqxxdzrpgsleimtkj
bvifawcnyoyxudzrpgsleimtvj
bvhfawcnyofxudlrpgsheimtkj
bvhbawcmyoqxudzrpggleimtkj
bhhxgwcnyoqxudzrpgsleimtkj
bvhfawgnyoqxbdzrpgsleimfkj
bvhfawcnyoqxudcrngsleimykj
bvhfawcnyofxudzrpgslebgtkj
bvhfaocnybqxudzapgsleimtkj
bvhxawcnyodxudzrpfsleimtkj
bchfawcnyoqxudrrtgsleimtkj
bvhfawcqyoqxudzdpgsltimtkj
bvhfawknyoqxudzrpnsleimtbj
cihfawcnyoqxudirpgsleimtkj
bvlfawpnyoqxudzrpgslgimtkj
bulfawcnyoqbudzrpgsleimtkj
bvhfajcnyoqkudzrpgsoeimtkj
bvhrakcnyoqxudzrpgsleimjkj
bvbftwcnyoqxuvzrpgsleimtkj
bvhfhwcnyoqxudzrpgslelmtbj
bvhyawcntoqxudzrpgsleimtuj
xvhuawcnyoqxuqzrpgsleimtkj
pvhfawcnyoqxudzdpglleimtkj
bvhfawsnyoqxudzrpgvlefmtkj
bvhfawcnyoqxudzrpgepeiwtkj
bvhfawcnyoqxudzrphsleittkr
dvhfawcnyoqxudzrpkslzimtkj
bvhfawpnyoqxudzrpgmlcimtkj
bvhsawcnyzqxudzrpgsaeimtkj
bdhfawcnyoqxudzrpasleiwtkj
bvhfawbnyoqxpdbrpgsleimtkj
mvhfawwnyoqxujzrpgsleimtkj
bvafawcnyoyxudzrpgsleidtkj
bvhyawcnyoqxudztpgzleimtkj
besfawcnyoqxudzrpgsleimdkj
bvhfawcnyoqxudrrpgsjeimjkj
xvhfkwcnyoqxudzcpgsleimtkj
bvhfawcnyeqdudzrpgzleimtkj
bvhfuwcnybqxudzrpgsleimttj
lvhfawcnyoqhudzdpgsleimtkj
bvhfawcnyoqxudzrpgslevwtnj
bvhfadcnzoqxxdzrpgsleimtkj
bvsfawcnyoqxpdzrpgileimtkj
bzhfaycnyoqxudzrpgsxeimtkj
bwhfdwcnyoqxudzrpgsleimtkz
bvhfawcnyoqxudzrpgsjlimtkm
bvhfawcnyoqxudsrwgsleimtlj
bbhfalynyoqxudzrpgsleimtkj
bvhfawcnyeqxudzrpglleimtkr
bvhfawnnboqxurzrpgsleimtkj
yvhfawcnyoqxudzrpgslzimtpj
bvhfjwcnyoqxqdxrpgsleimtkj
bthfawcnyoqfudzrpgslhimtkj
bvhfawchuoqxudzqpgsleimtkj
bvhfawcndoqxudzrugsleimrkj
bvhfawcnnoqxjdzrpgsleidtkj
bvhpawcnyoqkudzrpgsleimtzj
bvhfaiinyoqxudzopgsleimtkj
bvhfawcnyxqxuizrigsleimtkj
bvnfawcnyoqxudzqpgsleimbkj
bvnfawcnyoeyudzrpgsleimtkj
bvhfawcnyoqxudarpgsieimtoj
bthcawcnyoqxudlrpgsleimtkj
bvhfnwcnyozxudzrpgsleomtkj
bpwfawcnyoqxudzrpgskeimtkj
bvhfapcnyoqxudnrpgsxeimtkj
bvhfdwcnyoqxubzrxgsleimtkj
fvhfawcnyoqxjdzrpgsleirtkj
bvhfawcneoqxudzrvzsleimtkj
bvhaawcnyoqxudzrpgsleimtex
bvhfawcnyojxudvrpgsleimckj
bvlfawcnyoqxddzrpgsleimtko
bvhfawclfoqxudzrpgsleiktkj
bvhfawciyobxudzrpgkleimtkj
bvhfpwcnyoqxudzrpgsqeimtkd
bvhyawcnyyqxudzrkgsleimtkj
bvhfawcncoqxudzrphsaeimtkj
bvhfawmnyoqxudzrpgifeimtkj
bvhfawcjyoqxudzjpgszeimtkj
bohfawcnwoqxudzrpgsleimwkj
bvhfaucnyoqxudzrpgfluimtkj
bvhfawlnyoqgudzrpgwleimtkj
bmhfawcnyoqxndzrpgsleymtkj
bvhfawcngoqxudzrpzxleimtkj
bihfawcnyoqxudrrpgsleimokj
lvhfawcnylqxudzrpgsleintkj
bvhfawcnyoqvugzrqgsleimtkj
bvhfawcnyoqxudzgpgslqimtij
bvhfawcnyoqludzrpgslnimtcj
hvhfawcnyolxudzrpgsmeimtkj
nvhfawcdkoqxudzrpgsleimtkj
bvhfawcnyoqxkdzrggsneimtkj
bvhfawnnyoqxudzrpgqleibtkj
bvhfawyuyoqxudzrhgsleimtkj
wvhfbwcnyoqxtdzrpgsleimtkj
bvhfawcnyoqxedzzpgoleimtkj
bvhfawcnioqxunzrpgsleimtnj
bvhfawctyoqxudzrpgsldkmtkj
bvhfawcnyonxudzrpgsleitpkj
bvefawcnyoqaudzhpgsleimtkj
bvhfawcnyxqxudzrpgslelmbkj
bvhfamrnyoqxudzrpgsleimgkj
bvhfaqcnyoqxudzrpgsaeimekj
bvhfawcnyoqcidzrpgsleimvkj
bvhfawcnnorxudzrpgsmeimtkj
bvroawcnyoqxudzrpgsleiwtkj
bvhfwwcnyoqxudzrpaslewmtkj
bvsfawcnyoqxudzcpgszeimtkj
bkhfmwcnyoqjudzrpgsleimtkj
bvtfawcnyoqxudzrcgslecmtkj
bvhfawcnypzxudzrpgsleimtkv
bvhfawcnyoqzudzrfgtleimtkj
bvhpawcnyoqxudhrpgsleimtko
tvhfawcnyoqxudzxpfsleimtkj
bvhfawccyofxudzrpqsleimtkj
bvnfawtnyoqxuzzrpgsleimtkj
bvhfamcnuwqxudzrpgsleimtkj
bvhfawcfyoqxudjrpgsleimrkj
bvhpalcnyoqxudzrpgslexmtkj
bvhfawcnjsqxudzlpgsleimtkj
bvhfafcnioqxydzrpgsleimtkj
bvzfawcnyxqxudzgpgsleimtkj
bvhzawcnyoqxudzrpgslewctkj
bvhiawcnhoqrudzrpgsleimtkj
bvhfawcnyoqxuszrggslenmtkj
bvhfowcnyoqxudzrptseeimtkj
behfawfnyoqxudzrpgsleimlkj
lvhfawcnyoqxudsrpgvleimtkj
bvhfawnnyaqxudzrpgsqeimtkj
lvhfawcnfoqxvdzrpgsleimtkj
svhxawcnyoqxudzrpqsleimtkj
bvhfawqnfoqxudzrpgsleimkkj
bvhfafcnyoqcudzrpgsleimtcj
bvhfyfcntoqxudzrpgsleimtkj
bvhfpwcnyoqxudzrpgsleimumj
bvhfawccyoqxudzrqgrleimtkj
bvhfawqnyoqxudzbpgsleimkkj
bvhflwcnyoqxudzrpxsleemtkj
bvhfawcnyoqxuezrpgslehrtkj
bvhfawceyoqxudzrpgsleimswj
bvhfawcncohgudzrpgsleimtkj
bahfawcnyoqxgdzrpgsleamtkj
yvhfawcnyoqxudzrppslrimtkj
fvhfawcmyoqxudzrpgskeimtkj
bvylawsnyoqxudzrpgsleimtkj
bvhfswcnyyqxedzrpgsleimtkj
fvrfawcnyoqxudzrpgzleimtkj
bvhfawcnyoqxuvzrpgslermtks
bvhkawccyoqxudzcpgsleimtkj
bvhfaobnyoqxudzrprsleimtkj
bvbfawcnyoqxudirpgsleimhkj
bvhfawcnyoqxudzvpgsueimtgj
bvhxawcnyoqxudzrpgsleimtgi
svhfawcjyoqxuszrpgsleimtkj
bvnfawcnyoeyudzrpgsldimtkj
bvhfawcnyoqxuhzrpgsleimcki
bvhfvwcnyoqxudzizgsleimtkj
bvhfapznyohxudzrpgsleimtkj
bvhfaelnyosxudzrpgsleimtkj
xvhfawcnmoqxuhzrpgsleimtkj
bjhfawcnyaqxutzrpgsleimtkj
bvhfawcnyohxudzrpgslgnmtkj
bvhfawcnyoqxudzrppsreimtkx
fvhfapcnyoqyudzrpgsleimtkj
qvhfafcnyoqxudorpgsleimtkj
bvhfawcnyoqxedzrwgsleimtvj
bvhfawgnyoqxudzupgqleimtkj
bvhfowctyoqxudzrpgbleimtkj
bvhwawcnyoqxudzapgslvimtkj
bvhfadcnyoqxudzrugsleimtuj
bvhfawcnyosxudzlpgsleamtkj
bvhfawcnywqxuqzrpgsloimtkj
bvhfawcnyoqxumzrpgvlfimtkj
bvhfawcgyoqxbdzrpgsleomtkj
bvhfahcnyoqwudzrfgsleimtkj
gvbfawcnyrqxudzrpgsleimtkj
svhfawcnyoqxudlrpgsleimtkx
avhfafcnyoqxuhzrpgsleimtkj
bvhfawcsyoqxuazrpgsleimtej
bvofawcnyoqxudzrpgsteimtkf
bvhfajcnyoqxudzqpgszeimtkj
bvhfawcsyoqxudzrmgsleiktkj
mvhfawcnyoqxudzrpgkluimtkj
bvhfawcnhoqxudzrpgslwhmtkj
bmhaawsnyoqxudzrpgsleimtkj
bvhfawcnyoqxudzhpgsleimhyj
bvhfxwcnyoqxsdzypgsleimtkj
bvhpawcyyoqxuczrpgsleimtkj
bvomawcnyovxudzrpgsleimtkj
bvhfawcnjvqxudzrpgsleimtkt
nvhfawcnyqqxudzrpgsleittkj
bvhiawcnyzqxudzrpysleimtkj
bvhdawcnyoqxukzrpgsleimtuj
bvhfawcnyyxxudzrpgslzimtkj
hvhfawcnyoqxudzupgslemmtkj
byhfawknyoqxudzrpgsleimtkb
bvhfawcnyoqxudzrpasleihakj
bvafahcnyaqxudzrpgsleimtkj
bkhfawcnyoqxudzrpgllepmtkj
bghfawcnycqxuzzrpgsleimtkj
bvhfawcnyoqxudzrbgeleimtkl
bvhfascnyoqgudzrpgsveimtkj
bvhfawnnyoqxudzrpgsleimtdl
bvhqawcnyoqxudzrpgsleimgrj
bvhsawdwyoqxudzrpgsleimtkj
bvhfawcnyoqxudzrpgaleipttj
bvhfawcnrlqxudzrbgsleimtkj
bvhfdwcnyoqxudzqpcsleimtkj
bvhfawcnyoqxudzopgslexmokj
bvhfawcoyoqxudzrpghlewmtkj
bvhfozcnykqxudzrpgsleimtkj
bvhfawcnyoqxuvzrpgslrimtkr
bvhfrncnyoqrudzrpgsleimtkj
bvhfawcnyocxuizrpgslefmtkj
bvhfawywyoqxudzrpgsleimxkj
bvhfawcnyoqxugzrpgslrimtij
bvtfawcnyoqxudzcpgsleimtfj
bvhfawcnyoqxuzzspgsleimtkz
bvhfawcnzoqxvdzrpgslsimtkj
bvhfzwcnyoqxudzrpgslenmhkj
bvhfkccnyoqxudzrpgzleimtkj
bvhfawcnyoqzudzrpgslhimwkj
bzhfawvnyooxudzrpgsleimtkj

View file

@ -0,0 +1,18 @@
defmodule AdventOfCode2018 do
@moduledoc """
Documentation for AdventOfCode2018.
"""
@doc """
Hello world.
## Examples
iex> AdventOfCode2018.hello()
:world
"""
def hello do
:world
end
end

16
2018/elixir/lib/one.ex Normal file
View file

@ -0,0 +1,16 @@
defmodule One do
def part1(list, initial_freq \\ 0), do: initial_freq + Enum.sum(list)
def part2(list, initial_freq \\ 0) do
list
|> Stream.cycle()
|> Enum.reduce_while({initial_freq, MapSet.new([initial_freq])}, &part2_reducer/2)
end
def part2_reducer(i, {last, set}) do
case (i + last) in set do
true -> {:halt, i + last}
_ -> {:cont, {i + last, MapSet.put(set, i + last)}}
end
end
end

73
2018/elixir/lib/three.ex Normal file
View file

@ -0,0 +1,73 @@
defmodule Three do
@dimension_parser ~r/\#(\d+)\s@\s(\d+),(\d+):\s(\d+)x(\d+)/
def part1(input_stream) do
input_stream
|> Stream.map(&parse_dimensions/1)
|> Stream.map(&points_in_square/1)
|> Enum.to_list()
|> Enum.reduce({MapSet.new([]), MapSet.new([])}, &intersecting_squares/2)
|> elem(1)
|> MapSet.to_list()
|> length()
end
def parse_dimensions(str) do
l = Regex.run(@dimension_parser, str)
[id, x, y, w, h] = l |> tl() |> Enum.map(&String.to_integer/1)
{id, x, y, w, h}
end
def points_in_square({_, x, y, w, h}) do
x..(x + w - 1)
|> Enum.reduce([], fn x, x_set ->
y..(y + h - 1)
|> Enum.reduce(x_set, fn y, xy_set ->
[{x, y} | xy_set]
end)
end)
end
def intersecting_squares(square_set, {set, intersects}) do
square_set
|> Enum.reduce({set, intersects}, fn pos, {set, intersects} ->
case MapSet.member?(set, pos) do
true -> {set, MapSet.put(intersects, pos)}
_ -> {MapSet.put(set, pos), intersects}
end
end)
end
def intersecting_squares2({id, square_set}, {set, intersects}) do
square_set
|> Enum.reduce({set, intersects}, fn pos, {set, intersects} ->
case MapSet.member?(set, pos) do
true -> {set, MapSet.put(intersects, pos)}
_ -> {MapSet.put(set, pos), intersects}
end
end)
end
# parse input lines
# for each set of dimensions, check each point in the square
# if the point has been recorded already, remove both ids from the set
def part2(input_stream) do
square_data =
input_stream
|> Stream.map(&parse_dimensions/1)
square_id_set =
square_data
|> Stream.map(&elem(&1, 0))
|> Enum.to_list()
|> MapSet.new()
square_data
|> Enum.map(&{elem(&1, 0), points_in_square(&1)})
|> Enum.reduce({MapSet.new([]), square_id_set}, fn {id, points}, acc -> intersecting_squares2({id, points}, ))
|> elem(1)
|> MapSet.to_list()
|> length()
end
end

40
2018/elixir/lib/two.ex Normal file
View file

@ -0,0 +1,40 @@
defmodule Two do
def bool_int(true), do: 1
def bool_int(false), do: 0
def part1(id_list) do
id_list
|> Stream.map(fn id ->
id
|> String.codepoints()
|> Enum.reduce(%{}, fn l, acc -> Map.update(acc, l, 1, &(&1 + 1)) end)
|> Map.values()
|> MapSet.new()
end)
|> Enum.to_list()
|> Enum.reduce([0, 0], fn s, [x, y] ->
[x + bool_int(2 in s), y + bool_int(3 in s)]
end)
|> Enum.reduce(1, fn i, a -> a * i end)
end
def part2(id_list) do
id_list
|> Stream.map(&String.trim_trailing/1)
|> Enum.to_list()
|> permute_all_pairs()
|> List.flatten()
|> Enum.reduce_while("", fn {id1, id2}, _ ->
case String.myers_difference(id1, id2) do
[eq: p1, del: <<_x::size(8)>>, ins: <<_y::size(8)>>, eq: p2] -> {:halt, p1 <> p2}
_ -> {:cont, ""}
end
end)
end
def permute_all_pairs([]), do: []
def permute_all_pairs(list), do: [permute_pairs(list) | permute_all_pairs(tl(list))]
def permute_pairs([]), do: []
def permute_pairs([cur | rest]), do: Enum.map(rest, &{cur, &1})
end

28
2018/elixir/mix.exs Normal file
View file

@ -0,0 +1,28 @@
defmodule AdventOfCode2018.MixProject do
use Mix.Project
def project do
[
app: :advent_of_code_2018,
version: "0.1.0",
elixir: "~> 1.7",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"},
]
end
end

View file

@ -0,0 +1,41 @@
defmodule AdventOfCode2018Test do
use ExUnit.Case, async: true
@doc "https://adventofcode.com/2018/day/1"
test "Day 1" do
input_stream =
File.stream!("./inputs/one.txt", [:read])
|> Stream.map(&String.trim_trailing/1)
|> Stream.map(&String.to_integer/1)
assert One.part1(input_stream) == 416
assert One.part2(input_stream) == 56752
end
@doc "https://adventofcode.com/2018/day/2"
test "Day 2" do
input_stream = File.stream!("./inputs/two.txt", [:read])
assert Two.part1(input_stream) == 6696
assert Two.part2(input_stream) == "bvnfawcnyoeyudzrpgslimtkj"
end
@tag :current_day
@doc "https://adventofcode.com/2018/day/3"
test "Day 3" do
test_input =
"""
#1 @ 1,3: 4x4
#2 @ 3,1: 4x4
#3 @ 5,5: 2x2
"""
|> String.split("\n", trim: true)
# expected_result = MapSet.new([{4, 4}, {5, 4}, {4, 5}, {5, 5}])
expected_result_part1 = 4
expected_result_part2 = 3
assert Three.part1(test_input) == expected_result_part1
assert Three.part2(test_input) == expected_result_part2
end
end

View file

@ -0,0 +1 @@
ExUnit.start()

View file

@ -1,6 +1,7 @@
-- https://adventofcode.com/2019/day/1
require "common"
input = -> input_for_day(1)\gmatch "%d+"
mass_to_fuel = => -2 + math.floor @ / 3

View file

@ -9,8 +9,8 @@ read_whole_file = =>
input_for_day = =>
read_whole_file "input/#{@}.txt"
reduce = (iterable, initial, f) ->
reduce = (initial, f) =>
acc = initial
for e in iterable
for e in @
acc = f acc, e
acc