├── priv └── input_files │ ├── 2016_5.txt │ ├── 2020_23.txt │ ├── 2017_3.txt │ ├── 2017_17.txt │ ├── 2015_10.txt │ ├── 2015_11.txt │ ├── 2015_20.txt │ ├── 2017_14.txt │ ├── 2017_6.txt │ ├── 2015_21.txt │ ├── 2018_9.txt │ ├── 2017_10.txt │ ├── 2017_15.txt │ ├── 2021_21.txt │ ├── 2023_6.txt │ ├── 2015_25.txt │ ├── 2015_17.txt │ ├── 2020_13.txt │ ├── 2015_24.txt │ ├── 2016_12.txt │ ├── 2015_15.txt │ ├── 2019_2.txt │ ├── 2020_22.txt │ ├── 2017_23.txt │ ├── 2017_13.txt │ ├── 2015_23.txt │ ├── 2017_18.txt │ ├── 2021_6.txt │ ├── 2016_1.txt │ ├── 2018_6.txt │ ├── 2015_14.txt │ ├── 2020_10.txt │ ├── 2015_9.txt │ ├── 2017_2.txt │ ├── 2015_19.txt │ ├── 2019_1.txt │ ├── 2019_10.txt │ ├── 2021_16.txt │ └── 2022_11.txt ├── .tool-versions ├── test ├── 2015 │ ├── day_01_test.exs │ ├── day_03_test.exs │ ├── day_05_test.exs │ ├── day_09_test.exs │ ├── day_18_test.exs │ ├── day_02_test.exs │ ├── day_06_test.exs │ ├── day_07_test.exs │ ├── day_12_test.exs │ ├── day_14_test.exs │ ├── day_10_test.exs │ ├── day_13_test.exs │ ├── day_16_test.exs │ ├── day_17_test.exs │ ├── day_19_test.exs │ ├── day_21_test.exs │ ├── day_23_test.exs │ ├── day_08_test.exs │ ├── day_15_test.exs │ ├── day_25_test.exs │ ├── day_11_test.exs │ ├── day_24_test.exs │ ├── day_20_test.exs │ └── day_04_test.exs ├── 2016 │ ├── day_03_test.exs │ ├── day_04_test.exs │ ├── day_07_test.exs │ ├── day_10_test.exs │ ├── day_01_test.exs │ ├── day_08_test.exs │ ├── day_06_test.exs │ ├── day_12_test.exs │ ├── day_05_test.exs │ ├── day_02_test.exs │ └── day_09_test.exs ├── 2017 │ ├── day_01_test.exs │ ├── day_02_test.exs │ ├── day_09_test.exs │ ├── day_03_test.exs │ ├── day_05_test.exs │ ├── day_06_test.exs │ ├── day_08_test.exs │ ├── day_11_test.exs │ ├── day_12_test.exs │ ├── day_13_test.exs │ ├── day_14_test.exs │ ├── day_17_test.exs │ ├── day_18_test.exs │ ├── day_23_test.exs │ ├── day_07_test.exs │ ├── day_15_test.exs │ ├── day_16_test.exs │ ├── day_10_test.exs │ └── day_04_test.exs ├── 2018 │ ├── day_01_test.exs │ ├── day_03_test.exs │ ├── day_04_test.exs │ ├── day_08_test.exs │ ├── day_09_test.exs │ ├── day_05_test.exs │ ├── day_06_test.exs │ └── day_02_test.exs ├── 2019 │ ├── intcode_test.exs │ ├── day_04_test.exs │ ├── day_08_test.exs │ ├── day_10_test.exs │ ├── day_02_test.exs │ ├── day_03_test.exs │ ├── day_05_test.exs │ ├── day_06_test.exs │ └── day_01_test.exs ├── 2020 │ ├── day_02_test.exs │ ├── day_04_test.exs │ ├── day_05_test.exs │ ├── day_07_test.exs │ ├── day_19_test.exs │ ├── day_06_test.exs │ ├── day_08_test.exs │ ├── day_11_test.exs │ ├── day_12_test.exs │ ├── day_03_test.exs │ ├── day_16_test.exs │ ├── day_24_test.exs │ ├── day_25_test.exs │ ├── day_09_test.exs │ ├── day_22_test.exs │ ├── day_01_test.exs │ ├── day_10_test.exs │ ├── day_13_test.exs │ ├── day_20_test.exs │ ├── day_14_test.exs │ ├── day_18_test.exs │ ├── day_21_test.exs │ ├── day_15_test.exs │ └── day_23_test.exs ├── 2021 │ ├── day_01_test.exs │ ├── day_04_test.exs │ ├── day_05_test.exs │ ├── day_09_test.exs │ ├── day_15_test.exs │ ├── day_07_test.exs │ ├── day_25_test.exs │ ├── day_02_test.exs │ ├── day_03_test.exs │ ├── day_16_test.exs │ ├── day_06_test.exs │ └── day_21_test.exs ├── 2022 │ ├── day_04_test.exs │ ├── day_03_test.exs │ ├── day_06_test.exs │ ├── day_08_test.exs │ ├── day_09_test.exs │ ├── day_10_test.exs │ ├── day_12_test.exs │ ├── day_13_test.exs │ ├── day_14_test.exs │ ├── day_18_test.exs │ ├── day_01_test.exs │ ├── day_02_test.exs │ ├── day_07_test.exs │ ├── day_11_test.exs │ ├── day_22_test.exs │ ├── day_05_test.exs │ ├── day_20_test.exs │ ├── day_15_test.exs │ ├── day_23_test.exs │ ├── day_24_test.exs │ ├── day_25_test.exs │ ├── day_19_test.exs │ └── day_21_test.exs ├── 2023 │ ├── day_02_test.exs │ ├── day_10_test.exs │ ├── day_16_test.exs │ ├── day_22_test.exs │ ├── day_01_test.exs │ ├── day_04_test.exs │ ├── day_13_test.exs │ ├── day_14_test.exs │ ├── day_15_test.exs │ ├── day_03_test.exs │ ├── day_05_test.exs │ ├── day_06_test.exs │ ├── day_09_test.exs │ ├── day_07_test.exs │ ├── day_08_test.exs │ ├── day_11_test.exs │ ├── day_12_test.exs │ ├── day_18_test.exs │ ├── day_24_test.exs │ ├── day_19_test.exs │ ├── day_23_test.exs │ └── day_25_test.exs ├── 2024 │ ├── day_05_test.exs │ ├── day_12_test.exs │ ├── day_01_test.exs │ └── day_03_test.exs ├── test_helper.exs ├── advent_of_code_test.exs ├── algorithms │ ├── grid_test.exs │ ├── geometry_test.exs │ ├── subset_sum_test.exs │ ├── arithmetics_test.exs │ ├── combinatorics_test.exs │ ├── bi_circular_list_test.exs │ ├── chinese_remainder_test.exs │ └── disjoint_set_test.exs └── helpers │ └── transformers_test.exs ├── .formatter.exs ├── native └── aoc │ ├── .cargo │ └── config.toml │ ├── src │ ├── util │ │ ├── parsers.rs │ │ ├── result.rs │ │ └── io_helpers.rs │ ├── year_2018 │ │ ├── solver.rs │ │ └── day_18_01.rs │ ├── year_2019 │ │ ├── solver.rs │ │ └── day_19_01.rs │ ├── year_2022 │ │ ├── solver.rs │ │ └── day_22_01.rs │ ├── year_2023 │ │ └── solver.rs │ ├── year_2020 │ │ └── solver.rs │ ├── year_2021 │ │ ├── solver.rs │ │ └── day_21_01.rs │ ├── year_2015 │ │ ├── solver.rs │ │ └── day_15_01.rs │ ├── year_2016 │ │ └── solver.rs │ └── year_2017 │ │ ├── solver.rs │ │ ├── day_17_01.rs │ │ └── day_17_02.rs │ ├── Cargo.toml │ ├── README.md │ ├── .gitignore │ └── gen.sh ├── lib ├── 2015 │ ├── day_01.ex │ ├── day_04.ex │ ├── day_10.ex │ ├── day_08.ex │ ├── day_24.ex │ ├── day_17.ex │ ├── day_25.ex │ ├── day_20.ex │ └── day_12.ex ├── 2016 │ ├── day_06.ex │ └── day_03.ex ├── 2017 │ ├── day_04.ex │ ├── day_01.ex │ ├── day_02.ex │ ├── day_14.ex │ ├── day_05.ex │ ├── day_17.ex │ ├── day_08.ex │ ├── day_06.ex │ ├── day_03.ex │ ├── day_07.ex │ └── day_11.ex ├── 2018 │ ├── day_05.ex │ └── day_01.ex ├── 2019 │ ├── day_05.ex │ ├── day_01.ex │ ├── day_04.ex │ ├── day_02.ex │ └── day_06.ex ├── 2020 │ ├── day_25.ex │ ├── day_15.ex │ ├── day_06.ex │ ├── day_05.ex │ ├── day_01.ex │ ├── day_09.ex │ ├── day_03.ex │ ├── day_02.ex │ ├── day_10.ex │ ├── day_07.ex │ ├── day_24.ex │ └── day_13.ex ├── 2021 │ ├── day_01.ex │ ├── day_06.ex │ ├── day_07.ex │ ├── day_25.ex │ └── day_05.ex ├── 2022 │ ├── day_08.ex │ ├── day_09.ex │ ├── day_23.ex │ ├── day_10.ex │ ├── day_11.ex │ ├── day_24.ex │ ├── day_15.ex │ ├── day_19.ex │ ├── day_18.ex │ ├── day_06.ex │ ├── day_01.ex │ ├── day_04.ex │ ├── day_25.ex │ └── day_02.ex ├── 2023 │ ├── day_01.ex │ ├── day_06.ex │ └── day_09.ex ├── 2024 │ ├── day_01.ex │ ├── README.md │ └── day_05.ex ├── rust_nif.ex ├── helpers │ ├── templates │ │ ├── test.eex │ │ └── code.eex │ ├── input_reader.ex │ ├── helpers.ex │ └── input_parser.ex ├── mix │ └── tasks │ │ ├── gen_tags.ex │ │ ├── gen_difficulties.ex │ │ ├── gen_stats.ex │ │ ├── gen.ex │ │ ├── gen_readme.ex │ │ └── solve.ex ├── algorithms │ ├── arithmetics.ex │ ├── geometry.ex │ └── chinese_remainder.ex └── advent_of_code.ex ├── .gitignore └── mix.exs /priv/input_files/2016_5.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /priv/input_files/2020_23.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /priv/input_files/2017_3.txt: -------------------------------------------------------------------------------- 1 | 312051 -------------------------------------------------------------------------------- /priv/input_files/2017_17.txt: -------------------------------------------------------------------------------- 1 | 394 2 | -------------------------------------------------------------------------------- /priv/input_files/2015_10.txt: -------------------------------------------------------------------------------- 1 | 1113122113 2 | -------------------------------------------------------------------------------- /priv/input_files/2015_11.txt: -------------------------------------------------------------------------------- 1 | cqjxjnds 2 | -------------------------------------------------------------------------------- /priv/input_files/2015_20.txt: -------------------------------------------------------------------------------- 1 | 34000000 2 | -------------------------------------------------------------------------------- /priv/input_files/2017_14.txt: -------------------------------------------------------------------------------- 1 | ljoxqyyw 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | elixir 1.19.2-otp-28 2 | erlang 28.1.1 3 | -------------------------------------------------------------------------------- /priv/input_files/2017_6.txt: -------------------------------------------------------------------------------- 1 | 14 0 15 12 11 11 3 5 1 6 8 4 9 1 8 4 2 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start(exclude: [:skip, :skip_slow]) 2 | -------------------------------------------------------------------------------- /priv/input_files/2015_21.txt: -------------------------------------------------------------------------------- 1 | Hit Points: 109 2 | Damage: 8 3 | Armor: 2 4 | -------------------------------------------------------------------------------- /priv/input_files/2018_9.txt: -------------------------------------------------------------------------------- 1 | 473 players; last marble is worth 70904 points 2 | -------------------------------------------------------------------------------- /priv/input_files/2017_10.txt: -------------------------------------------------------------------------------- 1 | 206,63,255,131,65,80,238,157,254,24,133,2,16,0,1,3 2 | -------------------------------------------------------------------------------- /priv/input_files/2017_15.txt: -------------------------------------------------------------------------------- 1 | Generator A starts with 873 2 | Generator B starts with 583 3 | -------------------------------------------------------------------------------- /priv/input_files/2021_21.txt: -------------------------------------------------------------------------------- 1 | Player 1 starting position: 2 2 | Player 2 starting position: 8 3 | -------------------------------------------------------------------------------- /.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["mix.exs", "{lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /priv/input_files/2023_6.txt: -------------------------------------------------------------------------------- 1 | Time: 42 68 69 85 2 | Distance: 284 1005 1122 1341 3 | -------------------------------------------------------------------------------- /priv/input_files/2015_25.txt: -------------------------------------------------------------------------------- 1 | To continue, please consult the code grid in the manual. Enter the code at row 2947, column 3029. 2 | -------------------------------------------------------------------------------- /test/2019/intcode_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.IntCodeTest do 2 | use ExUnit.Case, async: true 3 | @moduletag :intcode 4 | end 5 | -------------------------------------------------------------------------------- /native/aoc/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(target_os = "macos")'] 2 | rustflags = [ 3 | "-C", "link-arg=-undefined", 4 | "-C", "link-arg=dynamic_lookup", 5 | ] 6 | -------------------------------------------------------------------------------- /test/advent_of_code_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCodeTest do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | doctest AdventOfCode.Helpers.InputParser 5 | end 6 | -------------------------------------------------------------------------------- /priv/input_files/2015_17.txt: -------------------------------------------------------------------------------- 1 | 33 2 | 14 3 | 18 4 | 20 5 | 45 6 | 35 7 | 16 8 | 35 9 | 1 10 | 13 11 | 18 12 | 13 13 | 50 14 | 44 15 | 48 16 | 6 17 | 24 18 | 41 19 | 30 20 | 42 21 | -------------------------------------------------------------------------------- /native/aoc/src/util/parsers.rs: -------------------------------------------------------------------------------- 1 | pub fn read_line_ints(raw_input: &str) -> Vec { 2 | raw_input 3 | .split('\n') 4 | .map(|x| x.parse::().unwrap()) 5 | .collect() 6 | } 7 | -------------------------------------------------------------------------------- /priv/input_files/2020_13.txt: -------------------------------------------------------------------------------- 1 | 1006605 2 | 19,x,x,x,x,x,x,x,x,x,x,x,x,37,x,x,x,x,x,883,x,x,x,x,x,x,x,23,x,x,x,x,13,x,x,x,17,x,x,x,x,x,x,x,x,x,x,x,x,x,797,x,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,29 -------------------------------------------------------------------------------- /test/algorithms/grid_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.GridTest do 2 | use ExUnit.Case, async: true 3 | 4 | alias AdventOfCode.Algorithms.Grid 5 | 6 | doctest AdventOfCode.Algorithms.Grid 7 | end 8 | -------------------------------------------------------------------------------- /test/algorithms/geometry_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.GeometryTest do 2 | use ExUnit.Case, async: true 3 | alias AdventOfCode.Algorithms.Geometry 4 | doctest AdventOfCode.Algorithms.Geometry 5 | end 6 | -------------------------------------------------------------------------------- /native/aoc/src/util/result.rs: -------------------------------------------------------------------------------- 1 | use rustler::NifTaggedEnum; 2 | 3 | #[derive(NifTaggedEnum)] 4 | pub enum Solution { 5 | BothString((String, String)), 6 | BothInt32((i32, i32)), 7 | BothUSize((usize, usize)), 8 | } 9 | -------------------------------------------------------------------------------- /test/algorithms/subset_sum_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.SubsetSumTest do 2 | use ExUnit.Case, async: true 3 | alias AdventOfCode.Algorithms.SubsetSum 4 | 5 | doctest AdventOfCode.Algorithms.SubsetSum 6 | end 7 | -------------------------------------------------------------------------------- /test/algorithms/arithmetics_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.ArithmeticsTest do 2 | use ExUnit.Case, async: true 3 | 4 | alias AdventOfCode.Algorithms.Arithmetics 5 | 6 | doctest AdventOfCode.Algorithms.Arithmetics 7 | end 8 | -------------------------------------------------------------------------------- /test/algorithms/combinatorics_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.CombinatoricsTest do 2 | use ExUnit.Case, async: true 3 | 4 | alias AdventOfCode.Algorithms.Combinatorics 5 | 6 | doctest AdventOfCode.Algorithms.Combinatorics 7 | end 8 | -------------------------------------------------------------------------------- /priv/input_files/2015_24.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 5 5 | 7 6 | 13 7 | 17 8 | 19 9 | 23 10 | 29 11 | 31 12 | 37 13 | 41 14 | 43 15 | 53 16 | 59 17 | 61 18 | 67 19 | 71 20 | 73 21 | 79 22 | 83 23 | 89 24 | 97 25 | 101 26 | 103 27 | 107 28 | 109 29 | 113 30 | -------------------------------------------------------------------------------- /test/algorithms/bi_circular_list_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.BiCircularListTest do 2 | use ExUnit.Case, async: true 3 | @moduletag :bi_circular_list 4 | 5 | alias AdventOfCode.Algorithms.BiCircularList 6 | doctest BiCircularList 7 | end 8 | -------------------------------------------------------------------------------- /test/algorithms/chinese_remainder_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.ChineseRemainderTest do 2 | use ExUnit.Case, async: true 3 | 4 | alias AdventOfCode.Algorithms.ChineseRemainder 5 | 6 | doctest AdventOfCode.Algorithms.ChineseRemainder 7 | end 8 | -------------------------------------------------------------------------------- /test/helpers/transformers_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Helpers.TransformersTest do 2 | use ExUnit.Case, async: true 3 | @moduletag :transformers 4 | 5 | alias AdventOfCode.Helpers.Transformers 6 | 7 | doctest AdventOfCode.Helpers.Transformers 8 | end 9 | -------------------------------------------------------------------------------- /test/algorithms/disjoint_set_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.DisjointSetTest do 2 | use ExUnit.Case, async: true 3 | @moduletag :algorithm_disjoint_set 4 | 5 | alias AdventOfCode.Algorithms.DisjointSet 6 | 7 | doctest AdventOfCode.Algorithms.DisjointSet 8 | end 9 | -------------------------------------------------------------------------------- /lib/rust_nif.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.RustNif do 2 | @moduledoc """ 3 | Module to list all NIFs used from Rust 4 | """ 5 | use Rustler, 6 | otp_app: :advent_of_code, 7 | crate: :aoc 8 | 9 | def solve(_year, _day), do: :erlang.nif_error(:nif_not_loaded) 10 | end 11 | -------------------------------------------------------------------------------- /priv/input_files/2016_12.txt: -------------------------------------------------------------------------------- 1 | cpy 1 a 2 | cpy 1 b 3 | cpy 26 d 4 | jnz c 2 5 | jnz 1 5 6 | cpy 7 c 7 | inc d 8 | dec c 9 | jnz c -2 10 | cpy a c 11 | inc a 12 | dec b 13 | jnz b -2 14 | cpy c b 15 | dec d 16 | jnz d -6 17 | cpy 19 c 18 | cpy 14 d 19 | inc a 20 | dec d 21 | jnz d -2 22 | dec c 23 | jnz c -5 -------------------------------------------------------------------------------- /priv/input_files/2015_15.txt: -------------------------------------------------------------------------------- 1 | Sprinkles: capacity 5, durability -1, flavor 0, texture 0, calories 5 2 | PeanutButter: capacity -1, durability 3, flavor 0, texture 0, calories 1 3 | Frosting: capacity 0, durability -1, flavor 4, texture 0, calories 6 4 | Sugar: capacity -1, durability 0, flavor 0, texture 2, calories 8 5 | -------------------------------------------------------------------------------- /test/2015/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day01Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1501 5 | 6 | alias AdventOfCode.Y2015.Day01, as: Solution 7 | 8 | test "Year 2015, Day 1" do 9 | assert Solution.run() == {232, 1783} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2015/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day03Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1503 5 | 6 | alias AdventOfCode.Y2015.Day03, as: Solution 7 | 8 | test "Year 2015, Day 3" do 9 | assert Solution.run() == {2081, 2341} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2015/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day05Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1505 5 | 6 | alias AdventOfCode.Y2015.Day05, as: Solution 7 | 8 | test "Year 2015, Day 5" do 9 | assert Solution.run() == {255, 55} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2016/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day03Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1603 5 | 6 | alias AdventOfCode.Y2016.Day03, as: Solution 7 | 8 | test "Year 2016, Day 3" do 9 | assert Solution.run() == {993, 1849} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2017/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day01Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1701 5 | 6 | alias AdventOfCode.Y2017.Day01, as: Solution 7 | 8 | test "Year 2017, Day 1" do 9 | assert Solution.run() == {1089, 1156} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2019/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day04Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1904 5 | 6 | alias AdventOfCode.Y2019.Day04, as: Solution 7 | 8 | test "Year 2019, Day 4" do 9 | assert Solution.run() == {1099, 710} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2019/day_08_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day08Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1908 5 | 6 | alias AdventOfCode.Y2019.Day08, as: Solution 7 | 8 | test "Year 2019, Day 8" do 9 | assert Solution.run() == {1572, :ok} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2019/day_10_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day10Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1910 5 | 6 | alias AdventOfCode.Y2019.Day10, as: Solution 7 | 8 | test "Year 2019, Day 10" do 9 | assert Solution.run() == {263, 1110} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2015/day_09_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day09Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1509 6 | 7 | alias AdventOfCode.Y2015.Day09, as: Solution 8 | 9 | test "Year 2015, Day 9" do 10 | assert Solution.run() == {117, 909} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_18_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day18Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1518 6 | 7 | alias AdventOfCode.Y2015.Day18, as: Solution 8 | 9 | test "Year 2015, Day 18" do 10 | assert Solution.run() == {814, 924} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2016/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day04Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1604 5 | 6 | alias AdventOfCode.Y2016.Day04, as: Solution 7 | 8 | test "Year 2016, Day 4" do 9 | assert Solution.run() == {158_835, 993} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2016/day_07_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day07Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1607 6 | 7 | alias AdventOfCode.Y2016.Day07, as: Solution 8 | 9 | test "Year 2016, Day 7" do 10 | assert Solution.run() == {105, 258} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2016/day_10_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day10Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case 5 | @moduletag :y1610 6 | 7 | alias AdventOfCode.Y2016.Day10, as: Solution 8 | 9 | test "Year 2016, Day 10, both parts" do 10 | assert Solution.run() == {56, 7847} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day02Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1702 5 | 6 | alias AdventOfCode.Y2017.Day02, as: Solution 7 | 8 | test "Year 2017, Day 2" do 9 | assert Solution.run() == {32_020, 236} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2018/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day01Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1801 5 | 6 | alias AdventOfCode.Y2018.Day01, as: Solution 7 | 8 | test "Year 2018, Day 1" do 9 | assert Solution.run() == {590, 83_445} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2018/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day03Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1803 5 | 6 | alias AdventOfCode.Y2018.Day03, as: Solution 7 | 8 | test "Year 2018, Day 3" do 9 | assert Solution.run() == {110_389, 552} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2018/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day04Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1804 5 | 6 | alias AdventOfCode.Y2018.Day04, as: Solution 7 | 8 | test "Year 2018, Day 4" do 9 | assert Solution.run() == {74_743, 132_484} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2019/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day02Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1902 5 | 6 | alias AdventOfCode.Y2019.Day02, as: Solution 7 | 8 | test "Year 2019, Day 2" do 9 | assert Solution.run() == {3_562_624, 8298} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2019/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day03Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1903 5 | 6 | alias AdventOfCode.Y2019.Day03, as: Solution 7 | 8 | test "Year 2019, Day 3" do 9 | assert Solution.run() == {1195, 91_518} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2019/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day05Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1905 5 | 6 | alias AdventOfCode.Y2019.Day05, as: Solution 7 | 8 | test "Year 2019, Day 5" do 9 | assert Solution.run() == {6_745_903, nil} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2019/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day06Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1906 5 | 6 | alias AdventOfCode.Y2019.Day06, as: Solution 7 | 8 | test "Year 2019, Day 6" do 9 | assert Solution.run() == {147_807, 229} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2020/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day02Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2002 6 | 7 | alias AdventOfCode.Y2020.Day02, as: Solution 8 | 9 | test "Year 2020, Day 2" do 10 | assert Solution.run() == {607, 321} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day04Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2004 6 | 7 | alias AdventOfCode.Y2020.Day04, as: Solution 8 | 9 | test "Year 2020, Day 4" do 10 | assert Solution.run() == {233, 111} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day05Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2005 6 | 7 | alias AdventOfCode.Y2020.Day05, as: Solution 8 | 9 | test "Year 2020, Day 5" do 10 | assert Solution.run() == {930, 515} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_07_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day07Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2007 6 | 7 | alias AdventOfCode.Y2020.Day07, as: Solution 8 | 9 | test "Year 2020, Day 7" do 10 | assert Solution.run() == {355, 5312} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_19_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day19Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2019 6 | 7 | alias AdventOfCode.Y2020.Day19, as: Solution 8 | 9 | test "Year 2020, Day 19" do 10 | assert Solution.run() == {248, 381} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day02Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1502 5 | 6 | alias AdventOfCode.Y2015.Day02, as: Solution 7 | 8 | test "Year 2015, Day 2" do 9 | assert Solution.run() == {1_606_483, 3_842_356} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2015/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day06Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1506 5 | 6 | alias AdventOfCode.Y2015.Day06, as: Solution 7 | 8 | test "Year 2015, Day 6" do 9 | assert Solution.run() == {377_891, 14_110_788} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2015/day_07_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day07Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1507 6 | 7 | alias AdventOfCode.Y2015.Day07, as: Solution 8 | 9 | test "Year 2015, Day 7" do 10 | assert Solution.run() == {46_065, 14_134} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_12_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day12Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1512 5 | 6 | alias AdventOfCode.Y2015.Day12, as: Solution 7 | 8 | test "Year 2015, Day 12" do 9 | assert Solution.run() == {119_433, 68_466} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2015/day_14_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day14Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1514 6 | 7 | alias AdventOfCode.Y2015.Day14, as: Solution 8 | 9 | test "Year 2015, Day 14" do 10 | assert Solution.run() == {2640, 1102} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2016/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day01Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1601 5 | 6 | alias AdventOfCode.Y2016.Day01, as: Solution 7 | 8 | test "Year 2016, Day 1, Part 1" do 9 | assert Solution.run() == {253, 126} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2016/day_08_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day08Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1608 6 | 7 | alias AdventOfCode.Y2016.Day08, as: Solution 8 | 9 | test "Year 2016, Day 8 run/1" do 10 | assert Solution.run() == {115, :ok} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_09_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day09Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1709 6 | 7 | alias AdventOfCode.Y2017.Day09, as: Solution 8 | 9 | test "Year 2017, Day 9" do 10 | assert Solution.run() == {7616, 3838} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2018/day_08_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day08Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1808 6 | 7 | alias AdventOfCode.Y2018.Day08, as: Solution 8 | 9 | test "Year 2018, Day 8" do 10 | assert Solution.run() == {40_701, nil} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2019/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day01Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1901 5 | 6 | alias AdventOfCode.Y2019.Day01, as: Solution 7 | 8 | test "Year 2019, Day 1" do 9 | assert Solution.run() == {3_421_505, 5_129_386} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2020/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day06Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2006 6 | 7 | alias AdventOfCode.Y2020.Day06, as: Solution 8 | 9 | test "Year 2020, Day 6" do 10 | assert Solution.run() == {6885, 3550} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_08_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day08Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2008 6 | 7 | alias AdventOfCode.Y2020.Day08, as: Solution 8 | 9 | test "Year 2020, Day 8" do 10 | assert Solution.run() == {2080, 2477} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_11_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day11Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2011 6 | 7 | alias AdventOfCode.Y2020.Day11, as: Solution 8 | 9 | test "Year 2020, Day 11" do 10 | assert Solution.run() == {2427, 2199} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_12_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day12Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2012 6 | 7 | alias AdventOfCode.Y2020.Day12, as: Solution 8 | 9 | test "Year 2020, Day 12" do 10 | assert Solution.run() == {439, 12_385} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day01Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2101 6 | 7 | alias AdventOfCode.Y2021.Day01, as: Solution 8 | 9 | test "Year 2021, Day 1" do 10 | assert Solution.run() == {1139, 1103} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day04Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2104 6 | 7 | alias AdventOfCode.Y2021.Day04, as: Solution 8 | 9 | test "Year 2021, Day 4" do 10 | assert Solution.run() == {11_774, 4495} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day05Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2105 6 | 7 | alias AdventOfCode.Y2021.Day05, as: Solution 8 | 9 | test "Year 2021, Day 5" do 10 | assert Solution.run() == {4655, 20_500} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_09_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day09Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2109 6 | 7 | alias AdventOfCode.Y2021.Day09, as: Solution 8 | 9 | test "Year 2021, Day 9" do 10 | assert Solution.run() == {528, 920_448} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_15_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day15Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2115 6 | 7 | alias AdventOfCode.Y2021.Day15, as: Solution 8 | 9 | test "Year 2021, Day 15" do 10 | assert Solution.run() == {583, 2927} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day04Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2204 6 | 7 | alias AdventOfCode.Y2022.Day04, as: Solution 8 | 9 | test "Year 2022, Day 4 run/1" do 10 | assert Solution.run() == {518, 909} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_10_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day10Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1510 6 | 7 | alias AdventOfCode.Y2015.Day10, as: Solution 8 | 9 | test "Year 2015, Day 10" do 10 | assert Solution.run() == {360_154, 5_103_798} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_13_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day13Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1513 6 | 7 | alias AdventOfCode.Y2015.Day13, as: Solution 8 | 9 | test "Year 2015, Day 13, Both" do 10 | assert Solution.run() == {733, 725} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_16_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day16Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1516 6 | 7 | alias AdventOfCode.Y2015.Day16, as: Solution 8 | 9 | test "Year 2015, Day 16, Both" do 10 | assert Solution.run() == {213, 323} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_17_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day17Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1517 6 | 7 | alias AdventOfCode.Y2015.Day17, as: Solution 8 | 9 | test "Year 2015, Day 17, Both" do 10 | assert Solution.run() == {1304, 18} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_19_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day19Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1519 6 | 7 | alias AdventOfCode.Y2015.Day19, as: Solution 8 | 9 | test "Year 2015, Day 19 run/1" do 10 | assert Solution.run() == {535, 212} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_21_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day21Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1521 6 | 7 | alias AdventOfCode.Y2015.Day21, as: Solution 8 | 9 | test "Year 2015, Day 21 run/1" do 10 | assert Solution.run() == {111, 188} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_23_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day23Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1523 6 | 7 | alias AdventOfCode.Y2015.Day23, as: Solution 8 | 9 | test "Year 2015, Day 23 run/1" do 10 | assert Solution.run() == {170, 247} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2016/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day06Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1606 5 | 6 | alias AdventOfCode.Y2016.Day06, as: Solution 7 | 8 | test "Year 2016, Day 6" do 9 | assert Solution.run() == {"qzedlxso", "ucmifjae"} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/2016/day_12_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day12Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1612 6 | 7 | alias AdventOfCode.Y2016.Day12, as: Solution 8 | 9 | test "Year 2016, Day 12" do 10 | assert Solution.run() == {318_077, 9_227_731} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day03Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1703 6 | 7 | alias AdventOfCode.Y2017.Day03, as: Solution 8 | 9 | test "Year 2017, Day 3 run/1" do 10 | assert Solution.run() == {430, 312_453} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day05Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1705 6 | 7 | alias AdventOfCode.Y2017.Day05, as: Solution 8 | 9 | test "Year 2017, Day 5" do 10 | assert Solution.run() == {372_671, 25_608_480} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day06Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1706 6 | 7 | alias AdventOfCode.Y2017.Day06, as: Solution 8 | 9 | test "Year 2017, Day 6 run/1" do 10 | assert Solution.run() == {11_137, 1037} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_08_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day08Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1708 6 | 7 | alias AdventOfCode.Y2017.Day08, as: Solution 8 | 9 | test "Year 2017, Day 8 run/1" do 10 | assert Solution.run() == {2971, 4254} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_11_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day11Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1711 6 | 7 | alias AdventOfCode.Y2017.Day11, as: Solution 8 | 9 | test "Year 2017, Day 11 run/1" do 10 | assert Solution.run() == {808, 1556} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_12_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day12Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1712 6 | 7 | alias AdventOfCode.Y2017.Day12, as: Solution 8 | 9 | test "Year 2017, Day 12 run/1" do 10 | assert Solution.run() == {239, 215} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day03Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2003 6 | 7 | alias AdventOfCode.Y2020.Day03, as: Solution 8 | 9 | test "Year 2020, Day 3" do 10 | assert Solution.run() == {272, 3_898_725_600} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_16_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day16Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2016 6 | 7 | alias AdventOfCode.Y2020.Day16, as: Solution 8 | 9 | test "Year 2020, Day 16" do 10 | assert Solution.run() == {32_835, {:todo, 2}} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_24_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day24Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2024 6 | 7 | alias AdventOfCode.Y2020.Day24, as: Solution 8 | 9 | test "Year 2020, Day 24" do 10 | assert Solution.run() == {307, {:todo, 2}} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_25_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day25Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2025 6 | 7 | alias AdventOfCode.Y2020.Day25, as: Solution 8 | 9 | test "Year 2020, Day 25" do 10 | assert Solution.run() == {3_286_137, "🎉"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_07_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day07Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2107 6 | 7 | alias AdventOfCode.Y2021.Day07, as: Solution 8 | 9 | test "Year 2021, Day 7" do 10 | assert Solution.run() == {344_138, 94_862_124} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_25_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day25Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2125 6 | 7 | alias AdventOfCode.Y2021.Day25, as: Solution 8 | 9 | test "Year 2021, Day 25 run/1" do 10 | assert Solution.run() == {504, "🎉"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day03Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2203 6 | 7 | alias AdventOfCode.Y2022.Day03, as: Solution 8 | 9 | test "Year 2022, Day 3 run/1" do 10 | assert Solution.run() == {8233, 2821} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day06Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2206 6 | 7 | alias AdventOfCode.Y2022.Day06, as: Solution 8 | 9 | test "Year 2022, Day 6 run/1" do 10 | assert Solution.run() == {1651, 3837} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_08_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day08Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2208 6 | 7 | alias AdventOfCode.Y2022.Day08, as: Solution 8 | 9 | test "Year 2022, Day 8 run/1" do 10 | assert Solution.run() == {1763, 671_160} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_09_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day09Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2209 6 | 7 | alias AdventOfCode.Y2022.Day09, as: Solution 8 | 9 | test "Year 2022, Day 9 run/1" do 10 | assert Solution.run() == {5907, 2303} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_10_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day10Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2210 6 | 7 | alias AdventOfCode.Y2022.Day10, as: Solution 8 | 9 | test "Year 2022, Day 10 run/1" do 10 | assert Solution.run() == {11_820, :ok} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_12_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day12Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2212 6 | 7 | alias AdventOfCode.Y2022.Day12, as: Solution 8 | 9 | test "Year 2022, Day 12 run/1" do 10 | assert Solution.run() == {528, 522} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_13_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day13Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2213 6 | 7 | alias AdventOfCode.Y2022.Day13, as: Solution 8 | 9 | test "Year 2022, Day 13 run/1" do 10 | assert Solution.run() == {5503, 20_952} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_14_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day14Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2214 6 | 7 | alias AdventOfCode.Y2022.Day14, as: Solution 8 | 9 | test "Year 2022, Day 14 run/1" do 10 | assert Solution.run() == {793, 24_166} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_18_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day18Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2218 6 | 7 | alias AdventOfCode.Y2022.Day18, as: Solution 8 | 9 | test "Year 2022, Day 18 run/1" do 10 | assert Solution.run() == {3650, 2118} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day02Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2302 6 | 7 | alias AdventOfCode.Y2023.Day02, as: Solution 8 | 9 | test "Year 2023, Day 2 run/1" do 10 | assert Solution.run() == {2085, 79_315} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_10_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day10Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2310 6 | 7 | alias AdventOfCode.Y2023.Day10, as: Solution 8 | 9 | test "Year 2023, Day 10 run/1" do 10 | assert Solution.run() == {7107, 258} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_16_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day16Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2316 6 | 7 | alias AdventOfCode.Y2023.Day16, as: Solution 8 | 9 | test "Year 2023, Day 16 run/1" do 10 | assert Solution.run() == {6855, 7513} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_22_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day22Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2322 6 | 7 | alias AdventOfCode.Y2023.Day22, as: Solution 8 | 9 | test "Year 2023, Day 22 run/1" do 10 | assert Solution.run() == {490, 96_356} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2024/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2024.Day05Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2405 6 | 7 | alias AdventOfCode.Y2024.Day05, as: Solution 8 | 9 | test "Year 2024, Day 5 run/1" do 10 | assert Solution.run() == {5391, 6142} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /native/aoc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc" 3 | version = "0.1.0" 4 | authors = [] 5 | edition = "2021" 6 | 7 | [lib] 8 | name = "aoc" 9 | path = "src/lib.rs" 10 | crate-type = ["cdylib"] 11 | 12 | [dependencies] 13 | rustler = "0.37.0" 14 | itertools = "0.14.0" 15 | clap = { version = "4.5.11", features = ["derive"] } 16 | -------------------------------------------------------------------------------- /test/2015/day_08_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day08Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1508 6 | 7 | alias AdventOfCode.Y2015.Day08, as: Solution 8 | 9 | test "Year 2015, Day 8, Both Parts" do 10 | assert Solution.run() == {1333, 2046} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_15_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day15Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1515 6 | 7 | alias AdventOfCode.Y2015.Day15, as: Solution 8 | 9 | test "Year 2015, Day 15" do 10 | assert Solution.run() == {13_882_464, 11_171_160} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_25_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day25Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1525 6 | 7 | alias AdventOfCode.Y2015.Day25, as: Solution 8 | 9 | test "Year 2015, Day 25 run/1" do 10 | assert Solution.run() == {19_980_801, "🎉"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_13_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day13Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1713 6 | 7 | alias AdventOfCode.Y2017.Day13, as: Solution 8 | 9 | test "Year 2017, Day 13 run/1" do 10 | assert Solution.run() == {2604, 3_941_460} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_14_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day14Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1714 6 | 7 | alias AdventOfCode.Y2017.Day14, as: Solution 8 | 9 | test "Year 2017, Day 14 run/1" do 10 | assert Solution.run() == {8316, {:todo, 2}} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_17_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day17Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1717 6 | 7 | alias AdventOfCode.Y2017.Day17, as: Solution 8 | 9 | test "Year 2017, Day 17 run/1" do 10 | assert Solution.run() == {926, 10_150_888} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_18_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day18Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1718 6 | 7 | alias AdventOfCode.Y2017.Day18, as: Solution 8 | 9 | test "Year 2017, Day 18 run/1" do 10 | assert Solution.run() == {3188, {:todo, 2}} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_23_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day23Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1723 6 | 7 | alias AdventOfCode.Y2017.Day23, as: Solution 8 | 9 | test "Year 2017, Day 23 run/1" do 10 | assert Solution.run() == {6241, {:todo, 2}} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_09_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day09Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2009 6 | 7 | alias AdventOfCode.Y2020.Day09, as: Solution 8 | 9 | test "Year 2020, Day 9" do 10 | assert Solution.run() == {15_353_384, 2_466_556} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_22_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day22Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2022 6 | 7 | alias AdventOfCode.Y2020.Day22, as: Solution 8 | 9 | test "Year 2020, Day 22, Part 1" do 10 | assert Solution.run() == {32_162, 32_534} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day02Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2102 6 | 7 | alias AdventOfCode.Y2021.Day02, as: Solution 8 | 9 | test "Year 2021, Day 2" do 10 | assert Solution.run() == {1_660_158, 1_604_592_846} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day03Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2103 6 | 7 | alias AdventOfCode.Y2021.Day03, as: Solution 8 | 9 | test "Year 2021, Day 3" do 10 | assert Solution.run() == {1_540_244, 4_203_981} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_16_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day16Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2116 6 | 7 | alias AdventOfCode.Y2021.Day16, as: Solution 8 | 9 | test "Year 2021, Day 16" do 10 | assert Solution.run() == {879, 539_051_801_941} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day01Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2201 6 | 7 | alias AdventOfCode.Y2022.Day01, as: Solution 8 | 9 | test "Year 2022, Day 1 run/1" do 10 | assert Solution.run() == {70_720, 207_148} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day02Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2202 6 | 7 | alias AdventOfCode.Y2022.Day02, as: Solution 8 | 9 | test "Year 2022, Day 2 run/1" do 10 | assert Solution.run() == {12_645, 11_756} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day01Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2201 6 | 7 | alias AdventOfCode.Y2023.Day01, as: Solution 8 | 9 | test "Year 2023, Day 1 run/1" do 10 | assert Solution.run() == {53_194, 54_249} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day04Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2304 6 | 7 | alias AdventOfCode.Y2023.Day04, as: Solution 8 | 9 | test "Year 2023, Day 4 run/1" do 10 | assert Solution.run() == {24_542, 8_736_438} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_13_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day13Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2313 6 | 7 | alias AdventOfCode.Y2023.Day13, as: Solution 8 | 9 | test "Year 2023, Day 13 run/1" do 10 | assert Solution.run() == {33_047, 28_806} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_14_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day14Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2314 6 | 7 | alias AdventOfCode.Y2023.Day14, as: Solution 8 | 9 | test "Year 2023, Day 14 run/1" do 10 | assert Solution.run() == {110_565, 89_845} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_15_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day15Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2315 6 | 7 | alias AdventOfCode.Y2023.Day15, as: Solution 8 | 9 | test "Year 2023, Day 15 run/1" do 10 | assert Solution.run() == {510_273, 212_449} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2024/day_12_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2024.Day12Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2412 6 | 7 | alias AdventOfCode.Y2024.Day12, as: Solution 8 | 9 | test "Year 2024, Day 12 run/1" do 10 | assert Solution.run() == {1_304_764, nil} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_07_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day07Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1707 6 | 7 | alias AdventOfCode.Y2017.Day07, as: Solution 8 | 9 | test "Year 2017, Day 7 run/1" do 10 | assert Solution.run() == {"hmvwl", {:todo, 2}} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2018/day_09_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day09Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1809 6 | 7 | alias AdventOfCode.Y2018.Day09, as: Solution 8 | 9 | test "Year 2018, Day 9 run/1" do 10 | assert Solution.run() == {371_284, 3_038_972_494} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day01Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2001 6 | 7 | alias AdventOfCode.Y2020.Day01, as: Solution 8 | 9 | test "Year 2020, Day 1, Part 1" do 10 | assert Solution.run() == {1_014_624, 80_072_256} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_10_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day10Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2010 6 | 7 | alias AdventOfCode.Y2020.Day10, as: Solution 8 | 9 | test "Year 2020, Day 10" do 10 | assert Solution.run() == {2030, 42_313_823_813_632} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_13_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day13Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2013 6 | 7 | alias AdventOfCode.Y2020.Day13, as: Solution 8 | 9 | test "Year 2020, Day 13" do 10 | assert Solution.run() == {4782, 1_118_684_865_113_056} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day06Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2106 6 | 7 | alias AdventOfCode.Y2021.Day06, as: Solution 8 | 9 | test "Year 2021, Day 6" do 10 | assert Solution.run() == {350_149, 1_590_327_954_513} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_07_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day07Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2207 6 | 7 | alias AdventOfCode.Y2022.Day07, as: Solution 8 | 9 | test "Year 2022, Day 7 run/1" do 10 | assert Solution.run() == {1_297_159, 3_866_390} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_11_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day11Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2211 6 | 7 | alias AdventOfCode.Y2022.Day11, as: Solution 8 | 9 | test "Year 2022, Day 11 run/1" do 10 | assert Solution.run() == {78_678, 15_333_249_714} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_22_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day22Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2222 6 | 7 | alias AdventOfCode.Y2022.Day22, as: Solution 8 | 9 | test "Year 2022, Day 22 run/1" do 10 | assert Solution.run() == {123_046, {:todo, 2}} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day03Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2303 6 | 7 | alias AdventOfCode.Y2023.Day03, as: Solution 8 | 9 | test "Year 2023, Day 3 run/1" do 10 | assert Solution.run() == {539_713, 84_159_075} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day05Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2305 6 | 7 | alias AdventOfCode.Y2023.Day05, as: Solution 8 | 9 | test "Year 2023, Day 5 run/1" do 10 | assert Solution.run() == {3_374_647, 6_082_852} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day06Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2306 6 | 7 | alias AdventOfCode.Y2023.Day06, as: Solution 8 | 9 | test "Year 2023, Day 6 run/1" do 10 | assert Solution.run() == {440_000, 26_187_338} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_09_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day09Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2309 6 | 7 | alias AdventOfCode.Y2023.Day09, as: Solution 8 | 9 | test "Year 2023, Day 9 run/1" do 10 | assert Solution.run() == {1_939_607_039, 1041} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2024/day_01_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2024.Day01Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2401 6 | 7 | alias AdventOfCode.Y2024.Day01, as: Solution 8 | 9 | test "Year 2024, Day 1 run/1" do 10 | assert Solution.run() == {2_742_123, 21_328_497} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2024/day_03_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2024.Day03Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2403 6 | 7 | alias AdventOfCode.Y2024.Day03, as: Solution 8 | 9 | test "Year 2024, Day 3 run/1" do 10 | assert Solution.run() == {190_604_937, 82_857_512} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_11_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day11Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1511 6 | 7 | alias AdventOfCode.Y2015.Day11, as: Solution 8 | 9 | test "Year 2015, Day 11, Part 1" do 10 | assert Solution.run() == {"cqjxxyzz", "cqkaabcc"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2015/day_24_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day24Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1524 6 | 7 | alias AdventOfCode.Y2015.Day24, as: Solution 8 | 9 | test "Year 2015, Day 24 run/1" do 10 | assert Solution.run() == {10_723_906_903, 74_850_409} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_20_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day20Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2020 6 | 7 | alias AdventOfCode.Y2020.Day20, as: Solution 8 | 9 | test "Year 2020, Day 20" do 10 | assert Solution.run() == {29_125_888_761_511, {:todo, 2}} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2021/day_21_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day21Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2121 6 | 7 | alias AdventOfCode.Y2021.Day21, as: Solution 8 | 9 | test "Year 2021, Day 21" do 10 | assert Solution.run() == {1_196_172, 106_768_284_484_217} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day05Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2205 6 | 7 | alias AdventOfCode.Y2022.Day05, as: Solution 8 | 9 | test "Year 2022, Day 5 run/1" do 10 | assert Solution.run() == {"VPCDMSLWJ", "TPWCGNCCG"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_20_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day20Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2220 6 | 7 | alias AdventOfCode.Y2022.Day20, as: Solution 8 | 9 | test "Year 2022, Day 20 run/1" do 10 | assert Solution.run() == {7228, 4_526_232_706_281} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_07_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day07Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2307 6 | 7 | alias AdventOfCode.Y2023.Day07, as: Solution 8 | 9 | test "Year 2023, Day 7 run/1" do 10 | assert Solution.run() == {255_048_101, 253_718_286} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_08_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day08Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2308 6 | 7 | alias AdventOfCode.Y2023.Day08, as: Solution 8 | 9 | test "Year 2023, Day 8 run/1" do 10 | assert Solution.run() == {20_093, 22_103_062_509_257} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_11_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day11Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2311 6 | 7 | alias AdventOfCode.Y2023.Day11, as: Solution 8 | 9 | test "Year 2023, Day 11 run/1" do 10 | assert Solution.run() == {9_795_148, 650_672_493_820} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_12_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day12Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2312 6 | 7 | alias AdventOfCode.Y2023.Day12, as: Solution 8 | 9 | test "Year 2023, Day 12 run/1" do 10 | assert Solution.run() == {7191, 6_512_849_198_636} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_18_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day18Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2318 6 | 7 | alias AdventOfCode.Y2023.Day18, as: Solution 8 | 9 | test "Year 2023, Day 18 run/1" do 10 | assert Solution.run() == {72_821, 127_844_509_405_501} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_24_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day24Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2324 6 | 7 | alias AdventOfCode.Y2023.Day24, as: Solution 8 | 9 | test "Year 2023, Day 24 run/1" do 10 | assert Solution.run() == {13_965, 578_177_720_733_043} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2017/day_15_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day15Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1715 6 | 7 | alias AdventOfCode.Y2017.Day15, as: Solution 8 | 9 | @tag :skip_slow 10 | test "Year 2017, Day 15 run/1" do 11 | assert Solution.run() == {631, 279} 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/2020/day_14_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day14Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2014 6 | 7 | alias AdventOfCode.Y2020.Day14, as: Solution 8 | 9 | test "Year 2020, Day 14" do 10 | assert Solution.run() == {9_967_721_333_886, 4_355_897_790_573} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_15_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day15Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2215 6 | 7 | alias AdventOfCode.Y2022.Day15, as: Solution 8 | 9 | test "Year 2022, Day 15 run/1" do 10 | assert Solution.run() == {4_725_496, 12_051_287_042_458} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_23_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day23Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2223 6 | 7 | alias AdventOfCode.Y2022.Day23, as: Solution 8 | 9 | @tag :skip_slow 10 | test "Year 2022, Day 23 run/1" do 11 | assert Solution.run() == {4116, 984} 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/2022/day_24_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day24Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2224 6 | 7 | alias AdventOfCode.Y2022.Day24, as: Solution 8 | 9 | @tag :skip_slow 10 | test "Year 2022, Day 24 run/1" do 11 | assert Solution.run() == {332, 942} 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/2022/day_25_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day25Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2225 6 | 7 | alias AdventOfCode.Y2022.Day25, as: Solution 8 | 9 | test "Year 2022, Day 25 run/1" do 10 | assert Solution.run() == {"2-==10===-12=2-1=-=0", "🎉"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2023/day_19_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day19Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2319 6 | 7 | alias AdventOfCode.Y2023.Day19, as: Solution 8 | 9 | test "Year 2023, Day 19 run/1" do 10 | assert Solution.run() == {432_427, 143_760_172_569_135} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2016/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day05Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1605_slow 5 | 6 | alias AdventOfCode.Y2016.Day05, as: Solution 7 | 8 | @tag :skip_slow 9 | test "Year 2016, Day 5" do 10 | assert Solution.run() == {"f77a0e6e", "999828ec"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_18_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day18Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2018 6 | 7 | alias AdventOfCode.Y2020.Day18, as: Solution 8 | 9 | test "Year 2020, Day 18" do 10 | assert Solution.run() == {50_956_598_240_016, 535_809_575_344_339} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_19_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day19Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2219 6 | 7 | alias AdventOfCode.Y2022.Day19, as: Solution 8 | 9 | @tag :skip_slow 10 | test "Year 2022, Day 19 run/1" do 11 | assert Solution.run() == {1599, 14_112} 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/2023/day_23_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day23Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2323 6 | 7 | alias AdventOfCode.Y2023.Day23, as: Solution 8 | 9 | @tag :skip_slow 10 | test "Year 2023, Day 23 run/1" do 11 | assert Solution.run() == {2042, 6466} 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/2023/day_25_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day25Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2325 6 | 7 | alias AdventOfCode.Y2023.Day25, as: Solution 8 | 9 | @tag :skip_slow 10 | test "Year 2023, Day 25 run/1" do 11 | assert Solution.run() == {558_376, "🎉"} 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/2015/day_20_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day20Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1520 6 | 7 | alias AdventOfCode.Y2015.Day20, as: Solution 8 | 9 | @tag :skip_slow 10 | test "Year 2015, Day 20 run/1" do 11 | assert Solution.run() == {786_240, 831_600} 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/2017/day_16_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day16Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1716 6 | 7 | alias AdventOfCode.Y2017.Day16, as: Solution 8 | 9 | test "Year 2017, Day 16 run/1" do 10 | assert Solution.run() == {"ehdpincaogkblmfj", "bpcekomfgjdlinha"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2022/day_21_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day21Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2221 6 | 7 | alias AdventOfCode.Y2022.Day21, as: Solution 8 | 9 | test "Year 2022, Day 21 run/1" do 10 | assert Solution.run() == {282_285_213_953_670, 3_699_945_358_564} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/2020/day_21_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day21Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2021 6 | 7 | alias AdventOfCode.Y2020.Day21, as: Solution 8 | 9 | test "Year 2020, Day 21," do 10 | assert Solution.run() == {1679, "lmxt,rggkbpj,mxf,gpxmf,nmtzlj,dlkxsxg,fvqg,dxzq"} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /native/aoc/src/year_2018/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_18_01::solve_18_01; 4 | 5 | const YEAR: i16 = 2018; 6 | 7 | pub fn run(day: i8, input_data: String) -> Solution { 8 | match day { 9 | 1 => Solution::BothInt32(solve_18_01(input_data)), 10 | _ => panic!("Year {YEAR} day {day} has not been solved."), 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /native/aoc/src/year_2019/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_19_01::solve_19_01; 4 | 5 | const YEAR: i16 = 2019; 6 | 7 | pub fn run(day: i8, input_data: String) -> Solution { 8 | match day { 9 | 1 => Solution::BothInt32(solve_19_01(input_data)), 10 | _ => panic!("Year {YEAR} day {day} has not been solved."), 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /native/aoc/src/year_2022/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_22_01::solve_22_01; 4 | 5 | const YEAR: i16 = 2022; 6 | 7 | pub fn run(day: i8, input_data: String) -> Solution { 8 | match day { 9 | 1 => Solution::BothInt32(solve_22_01(input_data)), 10 | _ => panic!("Year {YEAR} day {day} has not been solved."), 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /native/aoc/src/year_2023/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_23_01::solve_23_01; 4 | 5 | const YEAR: i16 = 2023; 6 | 7 | pub fn run(day: i8, input_data: String) -> Solution { 8 | match day { 9 | 1 => Solution::BothInt32(solve_23_01(input_data)), 10 | _ => panic!("Year {YEAR} day {day} has not been solved."), 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/2017/day_10_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day10Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1710 6 | 7 | alias AdventOfCode.Y2017.Day10, as: Solution 8 | 9 | doctest Solution 10 | 11 | test "Year 2017, Day 10 run/1" do 12 | assert Solution.run() == {9656, "20b7b54c92bf73cf3e5631458a715149"} 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /priv/input_files/2019_2.txt: -------------------------------------------------------------------------------- 1 | 1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,10,1,19,1,5,19,23,1,23,5,27,1,27,13,31,1,31,5,35,1,9,35,39,2,13,39,43,1,43,10,47,1,47,13,51,2,10,51,55,1,55,5,59,1,59,5,63,1,63,13,67,1,13,67,71,1,71,10,75,1,6,75,79,1,6,79,83,2,10,83,87,1,87,5,91,1,5,91,95,2,95,10,99,1,9,99,103,1,103,13,107,2,10,107,111,2,13,111,115,1,6,115,119,1,119,10,123,2,9,123,127,2,127,9,131,1,131,10,135,1,135,2,139,1,10,139,0,99,2,0,14,0 -------------------------------------------------------------------------------- /test/2018/day_05_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day05Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1805 5 | 6 | alias AdventOfCode.Y2018.Day05, as: Solution 7 | 8 | test "React (1)" do 9 | assert Solution.react(~c"dabAcCaCBAcCcaDA") == 10 10 | end 11 | 12 | test "Year 2018, Day 5" do 13 | assert Solution.run() == {10_496, 5774} 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/2015/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day04Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1504 5 | 6 | alias AdventOfCode.Y2015.Day04, as: Solution 7 | 8 | test "Year 2015, Day 4, Part 1" do 9 | assert Solution.run_1() == 254_575 10 | end 11 | 12 | test "Year 2015, Day 4, Part 2" do 13 | assert Solution.run_2() == 1_038_736 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/2022/day_08.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day08 do 2 | @moduledoc """ 3 | --- Day 8: Treetop Tree House --- 4 | Problem Link: https://adventofcode.com/2022/day/8 5 | Difficulty: m 6 | Tags: erlang grid 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 8) 11 | 12 | def run(input \\ input()) do 13 | :day_22_8.solve(input) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/2022/day_09.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day09 do 2 | @moduledoc """ 3 | --- Day 9: Rope Bridge --- 4 | Problem Link: https://adventofcode.com/2022/day/9 5 | Difficulty: m 6 | Tags: erlang grid walk 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 9) 11 | 12 | def run(input \\ input()) do 13 | :day_22_9.solve(input) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /priv/input_files/2020_22.txt: -------------------------------------------------------------------------------- 1 | Player 1: 2 | 27 3 | 29 4 | 30 5 | 44 6 | 50 7 | 5 8 | 33 9 | 47 10 | 34 11 | 38 12 | 36 13 | 4 14 | 2 15 | 18 16 | 24 17 | 16 18 | 32 19 | 21 20 | 17 21 | 9 22 | 3 23 | 22 24 | 41 25 | 31 26 | 23 27 | 28 | Player 2: 29 | 25 30 | 1 31 | 15 32 | 46 33 | 6 34 | 13 35 | 20 36 | 12 37 | 10 38 | 14 39 | 19 40 | 37 41 | 40 42 | 26 43 | 43 44 | 11 45 | 48 46 | 45 47 | 49 48 | 28 49 | 35 50 | 7 51 | 42 52 | 39 53 | 8 -------------------------------------------------------------------------------- /lib/2022/day_23.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day23 do 2 | @moduledoc """ 3 | --- Day 23: Unstable Diffusion --- 4 | Problem Link: https://adventofcode.com/2022/day/23 5 | Difficulty: m 6 | Tags: erlang slow grid walk 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 23) 11 | 12 | def run(input \\ input()) do 13 | :day_22_23.solve(input) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/2020/day_15_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day15Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2015 6 | 7 | alias AdventOfCode.Y2020.Day15, as: Solution 8 | 9 | test "Year 2020, Day 15, Part 1: Process" do 10 | assert Solution.run_1() == 468 11 | end 12 | 13 | test "Year 2020, Day 15, Part 2: Process" do 14 | assert Solution.run_2() == 1_801_753 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/2022/day_10.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day10 do 2 | @moduledoc """ 3 | --- Day 10: Cathode-Ray Tube ---p 4 | Problem Link: https://adventofcode.com/2022/day/10 5 | Difficulty: m 6 | Tags: erlang visual-result op-code 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 10) 11 | 12 | def run(input \\ input()) do 13 | :day_22_10.solve(input) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/2022/day_11.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day11 do 2 | @moduledoc """ 3 | --- Day 11: Monkey in the Middle --- 4 | Problem Link: https://adventofcode.com/2022/day/11 5 | Difficulty: l 6 | Tags: erlang parse-heavy arithmetic 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 11) 11 | 12 | def run(input \\ input()) do 13 | :day_22_11.solve(input) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/2022/day_24.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day24 do 2 | @moduledoc """ 3 | --- Day 24: Blizzard Basin --- 4 | Problem Link: https://adventofcode.com/2022/day/24 5 | Difficulty: m 6 | Tags: erlang slow optimization grid search 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 24) 11 | 12 | def run(input \\ input()) do 13 | :day_22_24.solve(input) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /priv/input_files/2017_23.txt: -------------------------------------------------------------------------------- 1 | set b 81 2 | set c b 3 | jnz a 2 4 | jnz 1 5 5 | mul b 100 6 | sub b -100000 7 | set c b 8 | sub c -17000 9 | set f 1 10 | set d 2 11 | set e 2 12 | set g d 13 | mul g e 14 | sub g b 15 | jnz g 2 16 | set f 0 17 | sub e -1 18 | set g e 19 | sub g b 20 | jnz g -8 21 | sub d -1 22 | set g d 23 | sub g b 24 | jnz g -13 25 | jnz f 2 26 | sub h -1 27 | set g b 28 | sub g c 29 | jnz g 2 30 | jnz 1 3 31 | sub b -17 32 | jnz 1 -23 33 | -------------------------------------------------------------------------------- /lib/2022/day_15.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day15 do 2 | @moduledoc """ 3 | --- Day 15: Beacon Exclusion Zone --- 4 | Problem Link: https://adventofcode.com/2022/day/15 5 | Difficulty: xl 6 | Tags: erlang slow large-number geometry2d 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 15) 11 | 12 | def run(input \\ input()) do 13 | :day_22_15.solve(input) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/2020/day_23_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day23Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y2023 6 | 7 | alias AdventOfCode.Y2020.Day23, as: Solution 8 | 9 | test "Year 2020, Day 23, Part 1" do 10 | assert Solution.run_1() == "43786952" 11 | end 12 | 13 | @tag :skip 14 | test "Year 2020, Day 23, Part 2" do 15 | assert Solution.run_2() == {:not_implemented, 2} 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/2022/day_19.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day19 do 2 | @moduledoc """ 3 | --- Day 19: Not Enough Minerals --- 4 | Problem Link: https://adventofcode.com/2022/day/19 5 | Difficulty: xl 6 | Tags: erlang slow needs-improvement grid optimization 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 19) 11 | 12 | def run(input \\ input()) do 13 | :day_22_19.solve(input) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /native/aoc/src/year_2020/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_20_01::solve_20_01; 4 | use super::day_20_02::solve_20_02; 5 | 6 | const YEAR: i16 = 2020; 7 | 8 | pub fn run(day: i8, input_data: String) -> Solution { 9 | match day { 10 | 1 => Solution::BothInt32(solve_20_01(input_data)), 11 | 2 => Solution::BothUSize(solve_20_02(input_data)), 12 | _ => panic!("Year {YEAR} day {day} has not been solved."), 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /native/aoc/src/year_2021/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_21_01::solve_21_01; 4 | use super::day_21_02::solve_21_02; 5 | 6 | const YEAR: i16 = 2021; 7 | 8 | pub fn run(day: i8, input_data: String) -> Solution { 9 | match day { 10 | 1 => Solution::BothUSize(solve_21_01(input_data)), 11 | 2 => Solution::BothInt32(solve_21_02(input_data)), 12 | _ => panic!("Year {YEAR} day {day} has not been solved."), 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/2022/day_18.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day18 do 2 | @moduledoc """ 3 | --- Day 18: Boiling Boulders --- 4 | Problem Link: https://adventofcode.com/2022/day/18 5 | Difficulty: xl 6 | Tags: erlang geometry3d surface set 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 18) 11 | 12 | @spec run(binary()) :: {number(), number()} 13 | def run(input \\ input()) do 14 | :day_22_18.solve(input) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/helpers/templates/test.eex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y<%= year %>.Day<%= String.pad_leading(day, 2, "0") %>Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y<%= year |> String.split_at(2) |> elem(1) %><%= String.pad_leading(day, 2, "0") %> 6 | 7 | alias AdventOfCode.Y<%= year %>.Day<%= String.pad_leading(day, 2, "0") %>, as: Solution 8 | 9 | test "Year <%= year %>, Day <%= day %> run/1" do 10 | assert Solution.run() == {nil, nil} 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /priv/input_files/2017_13.txt: -------------------------------------------------------------------------------- 1 | 0: 5 2 | 1: 2 3 | 2: 3 4 | 4: 4 5 | 6: 6 6 | 8: 4 7 | 10: 8 8 | 12: 6 9 | 14: 6 10 | 16: 14 11 | 18: 6 12 | 20: 8 13 | 22: 8 14 | 24: 10 15 | 26: 8 16 | 28: 8 17 | 30: 10 18 | 32: 8 19 | 34: 12 20 | 36: 9 21 | 38: 20 22 | 40: 12 23 | 42: 12 24 | 44: 12 25 | 46: 12 26 | 48: 12 27 | 50: 12 28 | 52: 12 29 | 54: 12 30 | 56: 14 31 | 58: 14 32 | 60: 14 33 | 62: 20 34 | 64: 14 35 | 66: 14 36 | 70: 14 37 | 72: 14 38 | 74: 14 39 | 76: 14 40 | 78: 14 41 | 80: 12 42 | 90: 30 43 | 92: 17 44 | 94: 18 45 | -------------------------------------------------------------------------------- /priv/input_files/2015_23.txt: -------------------------------------------------------------------------------- 1 | jio a, +16 2 | inc a 3 | inc a 4 | tpl a 5 | tpl a 6 | tpl a 7 | inc a 8 | inc a 9 | tpl a 10 | inc a 11 | inc a 12 | tpl a 13 | tpl a 14 | tpl a 15 | inc a 16 | jmp +23 17 | tpl a 18 | inc a 19 | inc a 20 | tpl a 21 | inc a 22 | inc a 23 | tpl a 24 | tpl a 25 | inc a 26 | inc a 27 | tpl a 28 | inc a 29 | tpl a 30 | inc a 31 | tpl a 32 | inc a 33 | inc a 34 | tpl a 35 | inc a 36 | tpl a 37 | tpl a 38 | inc a 39 | jio a, +8 40 | inc b 41 | jie a, +4 42 | tpl a 43 | inc a 44 | jmp +2 45 | hlf a 46 | jmp -7 47 | -------------------------------------------------------------------------------- /native/aoc/README.md: -------------------------------------------------------------------------------- 1 | # NIF for Elixir.AdventOfCode 2 | 3 | ## To build the NIF module: 4 | 5 | - Your NIF will now build along with your project. 6 | 7 | ## To load the NIF: 8 | 9 | ```elixir 10 | defmodule AdventOfCode do 11 | use Rustler, otp_app: :advent_of_code, crate: "aoc" 12 | 13 | # When your NIF is loaded, it will override this function. 14 | def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded) 15 | end 16 | ``` 17 | 18 | ## Examples 19 | 20 | [This](https://github.com/rusterlium/NifIo) is a complete example of a NIF written in Rust. 21 | -------------------------------------------------------------------------------- /priv/input_files/2017_18.txt: -------------------------------------------------------------------------------- 1 | set i 31 2 | set a 1 3 | mul p 17 4 | jgz p p 5 | mul a 2 6 | add i -1 7 | jgz i -2 8 | add a -1 9 | set i 127 10 | set p 680 11 | mul p 8505 12 | mod p a 13 | mul p 129749 14 | add p 12345 15 | mod p a 16 | set b p 17 | mod b 10000 18 | snd b 19 | add i -1 20 | jgz i -9 21 | jgz a 3 22 | rcv b 23 | jgz b -1 24 | set f 0 25 | set i 126 26 | rcv a 27 | rcv b 28 | set p a 29 | mul p -1 30 | add p b 31 | jgz p 4 32 | snd a 33 | set a b 34 | jgz 1 3 35 | snd b 36 | set f 1 37 | add i -1 38 | jgz i -11 39 | snd a 40 | jgz f -16 41 | jgz a -19 42 | -------------------------------------------------------------------------------- /lib/2020/day_25.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day25 do 2 | @moduledoc """ 3 | --- Day 25: Combo Breaker --- 4 | Problem Link: https://adventofcode.com/2020/day/25 5 | Tweet: https://twitter.com/mafinar/status/1343609407201042436 6 | """ 7 | def input, do: [14_222_596, 4_057_428] 8 | def run, do: {input() |> then(fn [a, b] -> t(1, a, lp(1, b, 1)) end), "🎉"} 9 | 10 | defp lp(x, k, s), do: ((r = t1(x, 7)) == k && s) || lp(r, k, s + 1) 11 | defp t(x, p, s), do: (s == 0 && x) || t(t1(x, p), p, s - 1) 12 | defp t1(x, p), do: rem(x * p, 20_201_227) 13 | end 14 | -------------------------------------------------------------------------------- /native/aoc/src/year_2015/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_15_01::solve_15_01; 4 | use super::day_15_02::solve_15_02; 5 | use super::day_15_03::solve_15_03; 6 | 7 | const YEAR: i16 = 2015; 8 | 9 | pub fn run(day: i8, input_data: String) -> Solution { 10 | match day { 11 | 1 => Solution::BothInt32(solve_15_01(input_data)), 12 | 2 => Solution::BothInt32(solve_15_02(input_data)), 13 | 3 => Solution::BothUSize(solve_15_03(input_data)), 14 | _ => panic!("Year {YEAR} day {day} has not been solved."), 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /native/aoc/src/year_2016/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_16_01::solve_16_01; 4 | use super::day_16_02::solve_16_02; 5 | use super::day_16_04::solve_16_04; 6 | 7 | const YEAR: i16 = 2016; 8 | 9 | pub fn run(day: i8, input_data: String) -> Solution { 10 | match day { 11 | 1 => Solution::BothInt32(solve_16_01(input_data)), 12 | 2 => Solution::BothString(solve_16_02(input_data)), 13 | 4 => Solution::BothUSize(solve_16_04(input_data)), 14 | _ => panic!("Year {YEAR} day {day} has not been solved."), 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /native/aoc/src/year_2017/solver.rs: -------------------------------------------------------------------------------- 1 | use crate::util::result::Solution; 2 | 3 | use super::day_17_01::solve_17_01; 4 | use super::day_17_02::solve_17_02; 5 | use super::day_17_04::solve_17_04; 6 | 7 | const YEAR: i16 = 2017; 8 | 9 | pub fn run(day: i8, input_data: String) -> Solution { 10 | match day { 11 | 1 => Solution::BothInt32(solve_17_01(input_data)), 12 | 2 => Solution::BothInt32(solve_17_02(input_data)), 13 | 4 => Solution::BothUSize(solve_17_04(input_data)), 14 | _ => panic!("Year {YEAR} day {day} has not been solved."), 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /priv/input_files/2021_6.txt: -------------------------------------------------------------------------------- 1 | 4,1,4,1,3,3,1,4,3,3,2,1,1,3,5,1,3,5,2,5,1,5,5,1,3,2,5,3,1,3,4,2,3,2,3,3,2,1,5,4,1,1,1,2,1,4,4,4,2,1,2,1,5,1,5,1,2,1,4,4,5,3,3,4,1,4,4,2,1,4,4,3,5,2,5,4,1,5,1,1,1,4,5,3,4,3,4,2,2,2,2,4,5,3,5,2,4,2,3,4,1,4,4,1,4,5,3,4,2,2,2,4,3,3,3,3,4,2,1,2,5,5,3,2,3,5,5,5,4,4,5,5,4,3,4,1,5,1,3,4,4,1,3,1,3,1,1,2,4,5,3,1,2,4,3,3,5,4,4,5,4,1,3,1,1,4,4,4,4,3,4,3,1,4,5,1,2,4,3,5,1,1,2,1,1,5,4,2,1,5,4,5,2,4,4,1,5,2,2,5,3,3,2,3,1,5,5,5,4,3,1,1,5,1,4,5,2,1,3,1,2,4,4,1,1,2,5,3,1,5,2,4,5,1,2,3,1,2,2,1,2,2,1,4,1,3,4,2,1,1,5,4,1,5,4,4,3,1,3,3,1,1,3,3,4,2,3,4,2,3,1,4,1,5,3,1,1,5,3,2,3,5,1,3,1,1,3,5,1,5,1,1,3,1,1,1,1,3,3,1 2 | -------------------------------------------------------------------------------- /lib/2022/day_06.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day06 do 2 | @moduledoc """ 3 | --- Day 6: Tuning Trouble --- 4 | Problem Link: https://adventofcode.com/2022/day/6 5 | Difficulty: xs 6 | Tags: bitwise set 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2022, 6) 11 | def run(data \\ input()), do: {marker(data, 4), marker(data, 14)} 12 | defp uniq?(xs, len), do: len == Enum.count(MapSet.new(:binary.bin_to_list(xs))) 13 | 14 | defp marker(<<_::bytes-size(1)>> <> xs = data, len, v \\ 0), 15 | do: (uniq?(:binary.part(data, 0, len), len) && v + len) || marker(xs, len, v + 1) 16 | end 17 | -------------------------------------------------------------------------------- /priv/input_files/2016_1.txt: -------------------------------------------------------------------------------- 1 | L1, L5, R1, R3, L4, L5, R5, R1, L2, L2, L3, R4, L2, R3, R1, L2, R5, R3, L4, R4, L3, R3, R3, L2, R1, L3, R2, L1, R4, L2, R4, L4, R5, L3, R1, R1, L1, L3, L2, R1, R3, R2, L1, R4, L4, R2, L189, L4, R5, R3, L1, R47, R4, R1, R3, L3, L3, L2, R70, L1, R4, R185, R5, L4, L5, R4, L1, L4, R5, L3, R2, R3, L5, L3, R5, L1, R5, L4, R1, R2, L2, L5, L2, R4, L3, R5, R1, L5, L4, L3, R4, L3, L4, L1, L5, L5, R5, L5, L2, L1, L2, L4, L1, L2, R3, R1, R1, L2, L5, R2, L3, L5, L4, L2, L1, L2, R3, L1, L4, R3, R3, L2, R5, L1, L3, L3, L3, L5, R5, R1, R2, L3, L2, R4, R1, R1, R3, R4, R3, L3, R3, L5, R2, L2, R4, R5, L4, L3, L1, L5, L1, R1, R2, L1, R3, R4, R5, R2, R3, L2, L1, L5 2 | -------------------------------------------------------------------------------- /priv/input_files/2018_6.txt: -------------------------------------------------------------------------------- 1 | 337, 150 2 | 198, 248 3 | 335, 161 4 | 111, 138 5 | 109, 48 6 | 261, 155 7 | 245, 130 8 | 346, 43 9 | 355, 59 10 | 53, 309 11 | 59, 189 12 | 325, 197 13 | 93, 84 14 | 194, 315 15 | 71, 241 16 | 193, 81 17 | 166, 187 18 | 208, 95 19 | 45, 147 20 | 318, 222 21 | 338, 354 22 | 293, 242 23 | 240, 105 24 | 284, 62 25 | 46, 103 26 | 59, 259 27 | 279, 205 28 | 57, 102 29 | 77, 72 30 | 227, 194 31 | 284, 279 32 | 300, 45 33 | 168, 42 34 | 302, 99 35 | 338, 148 36 | 300, 316 37 | 296, 229 38 | 293, 359 39 | 175, 208 40 | 86, 147 41 | 91, 261 42 | 188, 155 43 | 257, 292 44 | 268, 215 45 | 257, 288 46 | 165, 333 47 | 131, 322 48 | 264, 313 49 | 236, 130 50 | 98, 60 51 | -------------------------------------------------------------------------------- /priv/input_files/2015_14.txt: -------------------------------------------------------------------------------- 1 | Dancer can fly 27 km/s for 5 seconds, but then must rest for 132 seconds. 2 | Cupid can fly 22 km/s for 2 seconds, but then must rest for 41 seconds. 3 | Rudolph can fly 11 km/s for 5 seconds, but then must rest for 48 seconds. 4 | Donner can fly 28 km/s for 5 seconds, but then must rest for 134 seconds. 5 | Dasher can fly 4 km/s for 16 seconds, but then must rest for 55 seconds. 6 | Blitzen can fly 14 km/s for 3 seconds, but then must rest for 38 seconds. 7 | Prancer can fly 3 km/s for 21 seconds, but then must rest for 40 seconds. 8 | Comet can fly 18 km/s for 6 seconds, but then must rest for 103 seconds. 9 | Vixen can fly 18 km/s for 5 seconds, but then must rest for 84 seconds. 10 | -------------------------------------------------------------------------------- /lib/mix/tasks/gen_tags.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.GenTags do 2 | @moduledoc """ 3 | Updates the wiki/tags.md for all years. 4 | 5 | Type `mix gen_tags` to update all `wiki/tags.md` with latest tag summary. 6 | """ 7 | 8 | alias AdventOfCode.Helpers.Summarizer 9 | 10 | use Mix.Task 11 | 12 | @usage "mix gen_tags" 13 | 14 | @filename "wiki/tags.md" 15 | 16 | @shortdoc """ 17 | Creates or updates `#{@filename}` with latest tag data. 18 | """ 19 | @impl Mix.Task 20 | def run(_) do 21 | content = Summarizer.tag_page() 22 | File.write!(@filename, content) 23 | Mix.shell().info("#{@filename} successfully updated!") 24 | rescue 25 | _ -> Mix.shell().error(@usage) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /test/2016/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day02Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1602 5 | 6 | alias AdventOfCode.Y2016.Day02, as: Solution 7 | 8 | test "Year 2016, Day 2" do 9 | assert Solution.run() == {76_792, "A7AC3"} 10 | end 11 | 12 | test "run_cmds" do 13 | matrix = Solution.to_matrix_map() 14 | assert Solution.run_cmds(matrix, ["U", "L", "L"], 2, 0) == {"5", 2, 0} 15 | assert Solution.run_cmds(matrix, ["R", "R", "D", "D", "D"], 2, 0) == {"D", 4, 2} 16 | assert Solution.run_cmds(matrix, ["L", "U", "R", "D", "L"], 4, 2) == {"B", 3, 2} 17 | assert Solution.run_cmds(matrix, ["U", "U", "U", "U", "D"], 3, 2) == {"3", 1, 2} 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/helpers/templates/code.eex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y<%= year %>.Day<%= String.pad_leading(day, 2, "0") %> do 2 | @moduledoc """ 3 | <%= title %> 4 | Problem Link: https://adventofcode.com/<%= year %>/day/<%= day %> 5 | Difficulty: 6 | Tags: 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(<%= year %>, <%= day %>) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | 15 | {run_1(input), run_2(input)} 16 | end 17 | 18 | defp run_1(_input) do 19 | {:todo, 1} 20 | end 21 | 22 | defp run_2(_input) do 23 | {:todo, 2} 24 | end 25 | 26 | def parse(data \\ input()) do 27 | data 28 | |> Transformers.lines() 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/algorithms/arithmetics.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.Arithmetics do 2 | @moduledoc """ 3 | Algorithms related to arithmetics operations 4 | """ 5 | @doc """ 6 | Returns a list of divisors of a number. 7 | 8 | ## Example 9 | 10 | iex> Arithmetics.divisors(0) 11 | :error 12 | 13 | iex> Arithmetics.divisors(1) 14 | [1] 15 | 16 | iex> Arithmetics.divisors(12) 17 | [1, 12, 2, 6, 3, 4] 18 | 19 | iex> Arithmetics.divisors(13) 20 | [1, 13] 21 | 22 | """ 23 | def divisors(0), do: :error 24 | 25 | def divisors(n) do 26 | 1..trunc(:math.sqrt(n)) 27 | |> Enum.flat_map(fn 28 | x when rem(n, x) != 0 -> [] 29 | x when x != div(n, x) -> [x, div(n, x)] 30 | x -> [x] 31 | end) 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/mix/tasks/gen_difficulties.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.GenDifficulties do 2 | @moduledoc """ 3 | Updates the wiki/difficulties.md for all years. 4 | 5 | Type `mix gen_difficulties` to update `wiki/difficulties.md` with latest difficulty summary. 6 | """ 7 | 8 | alias AdventOfCode.Helpers.Summarizer 9 | 10 | use Mix.Task 11 | 12 | @usage "mix gen_difficulties" 13 | 14 | @filename "wiki/difficulties.md" 15 | 16 | @shortdoc """ 17 | Creates or updates `#{@filename}` with latest tag data. 18 | """ 19 | @impl Mix.Task 20 | def run(_) do 21 | content = Summarizer.difficulty_page() 22 | File.write!(@filename, content) 23 | Mix.shell().info("#{@filename} successfully updated!") 24 | rescue 25 | _ -> Mix.shell().error(@usage) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/2015/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day01 do 2 | @moduledoc """ 3 | --- Day 1: Not Quite Lisp --- 4 | Problem Link: https://adventofcode.com/2015/day/1 5 | Difficulty: xs 6 | Tags: sequence rust 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2015, 1) 11 | 12 | def run, do: {floor(input(), 0), to_basement(input(), 0, 0)} 13 | 14 | defp floor("", cur), do: cur 15 | defp floor("(" <> rst, cur), do: floor(rst, cur + 1) 16 | defp floor(")" <> rst, cur), do: floor(rst, cur - 1) 17 | 18 | defp to_basement(_, pos, -1), do: pos 19 | defp to_basement("(" <> rst, pos, cur), do: to_basement(rst, pos + 1, cur + 1) 20 | defp to_basement(")" <> rst, pos, cur), do: to_basement(rst, pos + 1, cur - 1) 21 | end 22 | -------------------------------------------------------------------------------- /priv/input_files/2020_10.txt: -------------------------------------------------------------------------------- 1 | 35 2 | 111 3 | 135 4 | 32 5 | 150 6 | 5 7 | 106 8 | 154 9 | 41 10 | 7 11 | 27 12 | 117 13 | 109 14 | 63 15 | 64 16 | 21 17 | 138 18 | 98 19 | 40 20 | 71 21 | 144 22 | 13 23 | 66 24 | 48 25 | 12 26 | 55 27 | 119 28 | 103 29 | 54 30 | 78 31 | 65 32 | 112 33 | 39 34 | 128 35 | 53 36 | 140 37 | 77 38 | 34 39 | 28 40 | 81 41 | 151 42 | 125 43 | 85 44 | 124 45 | 2 46 | 99 47 | 131 48 | 59 49 | 60 50 | 6 51 | 94 52 | 33 53 | 42 54 | 93 55 | 14 56 | 141 57 | 92 58 | 38 59 | 104 60 | 9 61 | 29 62 | 100 63 | 52 64 | 19 65 | 147 66 | 49 67 | 74 68 | 70 69 | 84 70 | 113 71 | 120 72 | 91 73 | 97 74 | 17 75 | 45 76 | 139 77 | 90 78 | 116 79 | 149 80 | 129 81 | 87 82 | 69 83 | 20 84 | 24 85 | 148 86 | 18 87 | 58 88 | 123 89 | 76 90 | 118 91 | 130 92 | 132 93 | 75 94 | 110 95 | 105 96 | 1 97 | 8 98 | 86 -------------------------------------------------------------------------------- /lib/helpers/input_reader.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Helpers.InputReader do 2 | @moduledoc """ 3 | Reads input from file 4 | """ 5 | @input_dir Path.join(:code.priv_dir(:advent_of_code), "input_files") 6 | 7 | @doc """ 8 | Reads input from file. Reads from the input directory `priv/input_files` and sends 9 | a trimmed string if `trim` is true otherwise returns the data as raw. The reason `trim` 10 | is configurable because some AoC problems (i.e. Year 2017 day 19) has significant leading 11 | or trailing space(s) 12 | """ 13 | @spec read_from_file(pos_integer(), pos_integer(), boolean()) :: binary() 14 | def read_from_file(year, day, trim \\ true) do 15 | case {trim, File.read!("#{@input_dir}/#{year}_#{day}.txt")} do 16 | {true, data} -> String.trim(data) 17 | {_, data} -> data 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /priv/input_files/2015_9.txt: -------------------------------------------------------------------------------- 1 | Faerun to Tristram = 65 2 | Faerun to Tambi = 129 3 | Faerun to Norrath = 144 4 | Faerun to Snowdin = 71 5 | Faerun to Straylight = 137 6 | Faerun to AlphaCentauri = 3 7 | Faerun to Arbre = 149 8 | Tristram to Tambi = 63 9 | Tristram to Norrath = 4 10 | Tristram to Snowdin = 105 11 | Tristram to Straylight = 125 12 | Tristram to AlphaCentauri = 55 13 | Tristram to Arbre = 14 14 | Tambi to Norrath = 68 15 | Tambi to Snowdin = 52 16 | Tambi to Straylight = 65 17 | Tambi to AlphaCentauri = 22 18 | Tambi to Arbre = 143 19 | Norrath to Snowdin = 8 20 | Norrath to Straylight = 23 21 | Norrath to AlphaCentauri = 136 22 | Norrath to Arbre = 115 23 | Snowdin to Straylight = 101 24 | Snowdin to AlphaCentauri = 84 25 | Snowdin to Arbre = 96 26 | Straylight to AlphaCentauri = 107 27 | Straylight to Arbre = 14 28 | AlphaCentauri to Arbre = 46 29 | -------------------------------------------------------------------------------- /lib/2022/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day01 do 2 | @moduledoc """ 3 | --- Day 1: Calorie Counting --- 4 | Problem Link: https://adventofcode.com/2022/day/1 5 | Difficulty: xs 6 | Tags: sequence rust 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2022, 1) 11 | 12 | def run(input \\ input()) do 13 | calories = parse(input) 14 | 15 | { 16 | Enum.max(calories), 17 | calories |> Enum.sort(:desc) |> Enum.take(3) |> Enum.sum() 18 | } 19 | end 20 | 21 | def parse(data) do 22 | data 23 | |> String.split(~r{(\r\n\r\n|\r\r|\n\n)}, trim: true) 24 | |> Enum.map(fn calories -> 25 | calories 26 | |> Transformers.lines() 27 | |> Enum.map(&String.to_integer/1) 28 | |> Enum.sum() 29 | end) 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/2021/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day01 do 2 | @moduledoc """ 3 | --- Day 1: Sonar Sweep --- 4 | Problem Link: https://adventofcode.com/2021/day/1 5 | Difficulty: xs 6 | Tags: sliding-window sequence rust 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2021, 1) 11 | 12 | def run(input \\ input()) do 13 | input = Transformers.int_lines(input) 14 | {depth_increase(input), depth_increase(sliding_window(input))} 15 | end 16 | 17 | defp depth_increase(measurements) do 18 | measurements 19 | |> Enum.chunk_every(2, 1, :discard) 20 | |> Enum.count(fn [a, b] -> b - a > 0 end) 21 | end 22 | 23 | defp sliding_window(measurements) do 24 | measurements 25 | |> Enum.chunk_every(3, 1, :discard) 26 | |> Enum.map(&Enum.sum/1) 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/2015/day_04.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day04 do 2 | @moduledoc """ 3 | --- Day 4: The Ideal Stocking Stuffer --- 4 | Problem Link: https://adventofcode.com/2015/day/4 5 | Difficulty: s 6 | Tags: md5 annoying 7 | """ 8 | def run, do: {run_1(), run_2()} 9 | def run_1, do: lowest_number("bgvyzdsv", 1) 10 | def run_2, do: "bgvyzdsv" |> lowest_number_2(1) 11 | 12 | defp h(s, n), do: Base.encode16(:crypto.hash(:md5, s <> to_string(n))) 13 | defp satisfy(_, "0" <> "0" <> "0" <> "0" <> "0" <> _, n), do: n 14 | defp satisfy(s, _, n), do: lowest_number(s, n + 1) 15 | def lowest_number(s, number), do: satisfy(s, h(s, number), number) 16 | 17 | defp satisfy_2(_, "0" <> "0" <> "0" <> "0" <> "0" <> "0" <> _, n), do: n 18 | defp satisfy_2(s, _, n), do: lowest_number_2(s, n + 1) 19 | def lowest_number_2(s, number), do: satisfy_2(s, h(s, number), number) 20 | end 21 | -------------------------------------------------------------------------------- /native/aoc/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | #Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # RustRover 17 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 18 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 19 | # and can be added to the global gitignore or merged into this file. For a more nuclear 20 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 21 | .idea/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | priv/native/libaoc.so 2 | .DS_Store 3 | .envrc 4 | .iex.exs 5 | .elixir_ls 6 | .elixir-tools/ 7 | .zed/ 8 | # All tests and scratchpads are done on experiments 9 | priv/experiments/ 10 | # The directory Mix will write compiled artifacts to. 11 | /_build/ 12 | 13 | # If you run "mix test --cover", coverage assets end up here. 14 | /cover/ 15 | 16 | # The directory Mix downloads your dependencies sources to. 17 | /deps/ 18 | 19 | # Where 3rd-party dependencies like ExDoc output generated docs. 20 | /doc/ 21 | 22 | # Ignore .fetch files in case you like to edit your project deps locally. 23 | /.fetch 24 | 25 | # If the VM crashes, it generates a dump, let's ignore it too. 26 | erl_crash.dump 27 | 28 | # Also ignore archive artifacts (built via "mix archive.build"). 29 | *.ez 30 | 31 | # Ignore package tarball (built via "mix hex.build"). 32 | advent_of_code-*.tar 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /native/aoc/src/util/io_helpers.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | 3 | pub const MAX_YEAR: i16 = 2023; 4 | 5 | pub fn read_input_from_resources(year: i16, day: i8, from_elixir: bool) -> String { 6 | let input_path = if from_elixir { 7 | format!("./priv/input_files/{year}_{day}.txt") 8 | } else { 9 | format!("../../priv/input_files/{year}_{day}.txt") 10 | }; 11 | read_input_from_path(input_path) 12 | } 13 | 14 | pub fn read_input_from_path(input_path: String) -> String { 15 | fs::read_to_string(input_path).expect("File doesn't exist.") 16 | } 17 | 18 | pub fn validate_input(year: i16, day: i8) -> (bool, bool) { 19 | let mut year_ok = true; 20 | let mut day_ok = true; 21 | 22 | if !(2015..=MAX_YEAR).contains(&year) { 23 | year_ok = false; 24 | } 25 | 26 | if !(1..=25).contains(&day) { 27 | day_ok = false; 28 | } 29 | 30 | (year_ok, day_ok) 31 | } 32 | -------------------------------------------------------------------------------- /test/2017/day_04_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day04Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1704 6 | 7 | alias AdventOfCode.Y2017.Day04, as: Solution 8 | 9 | test "containes_duplicates returns true if passphrases contain duplicates" do 10 | assert Solution.duplicates?(~w/aa bb cc dd ee/) 11 | refute Solution.duplicates?(~w/aa bb cc dd aa/) 12 | assert Solution.duplicates?(~w/aa bb cc dd aaa/) 13 | end 14 | 15 | test "containes_duplicates returns true if passphrases contain anagrams" do 16 | assert Solution.anagrams?(~w/abcde fghij/) 17 | assert Solution.anagrams?(~w/a ab abc abd abf abj/) 18 | assert Solution.anagrams?(~w/iiii oiii ooii oooi oooo/) 19 | refute Solution.anagrams?(~w/oiii ioii iioi iiio/) 20 | end 21 | 22 | test "Year 2017, Day 4" do 23 | assert Solution.run() == {455, 186} 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/mix/tasks/gen_stats.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.GenStats do 2 | @moduledoc """ 3 | Updates the README.md for all years. 4 | 5 | Type `mix gen_stats` to update all `year/README.md`. 6 | 7 | For example, `mix gen_stats` will generate `lib//README.md` of all years. 8 | """ 9 | 10 | alias AdventOfCode.Helpers.Summarizer 11 | 12 | use Mix.Task 13 | 14 | @year_range 2015..AdventOfCode.get_latest_year() 15 | 16 | @usage "mix gen_stats" 17 | 18 | @shortdoc """ 19 | Creates the per year README.md with updated solution status. 20 | """ 21 | @impl Mix.Task 22 | def run(_) do 23 | for year <- @year_range do 24 | readme_content = Summarizer.yearwise_readme(year) 25 | 26 | File.write!("lib/#{year}/README.md", readme_content) 27 | 28 | Mix.shell().info("#{year}/README.md successfully updated!") 29 | end 30 | rescue 31 | _ -> Mix.shell().error(@usage) 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /native/aoc/src/year_2022/day_22_01.rs: -------------------------------------------------------------------------------- 1 | use crate::util::parsers::read_line_ints; 2 | use itertools::Itertools; 3 | pub fn solve_22_01(raw_input: String) -> (i32, i32) { 4 | let input = process(raw_input); 5 | (input[0], input[0..3].iter().sum()) 6 | } 7 | 8 | fn process(raw_input: String) -> Vec { 9 | raw_input 10 | .split("\n\n") 11 | .map(|calories| read_line_ints(calories).into_iter().sum()) 12 | .sorted() 13 | .rev() 14 | .collect() 15 | } 16 | 17 | #[cfg(test)] 18 | mod tests { 19 | use super::*; 20 | use crate::util::io_helpers::read_input_from_resources; 21 | 22 | #[test] 23 | fn test_result_22_01() { 24 | let (year, day) = (2022, 1); 25 | let expected_result = (70720, 207148); 26 | 27 | let raw_input = read_input_from_resources(year, day, false); 28 | assert_eq!(solve_22_01(raw_input), expected_result); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/2019/day_05.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day05 do 2 | @moduledoc """ 3 | --- Day 5: Sunny with a Chance of Asteroids --- 4 | Problem Link: https://adventofcode.com/2019/day/5 5 | Difficulty: xs 6 | Tags: op-code int-code 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | alias AdventOfCode.Y2019.IntCode 10 | 11 | def input, do: InputReader.read_from_file(2019, 5) 12 | 13 | def run(input \\ input()) do 14 | input = parse(input) 15 | {run_1(input), run_2(input)} 16 | end 17 | 18 | def run_1(input) do 19 | {:ok, pid} = input |> IntCode.start_link() 20 | %{output: output} = IntCode.run(pid) 21 | 22 | output 23 | |> Enum.reject(&(&1 == 0)) 24 | |> case do 25 | [data] -> data 26 | [] -> -1 27 | end 28 | end 29 | 30 | def run_2(_) do 31 | nil 32 | end 33 | 34 | def parse(data), do: data |> String.split(",") |> Enum.map(&String.to_integer/1) 35 | end 36 | -------------------------------------------------------------------------------- /lib/2020/day_15.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day15 do 2 | @moduledoc """ 3 | --- Day 15: Rambunctious Recitation --- 4 | Problem Link: https://adventofcode.com/2020/day/15 5 | """ 6 | def run_1, do: [6, 19, 0, 5, 7, 13, 1] |> play(2020) 7 | def run_2, do: [6, 19, 0, 5, 7, 13, 1] |> play(30_000_000) 8 | 9 | def play(input, stop) do 10 | tab = :ets.new(:tab, []) 11 | true = :ets.insert(tab, Enum.with_index(input, 1)) 12 | speak({List.last(input), tab, length(input)}, stop) 13 | end 14 | 15 | defp speak({last, _hist, stop}, stop), do: last 16 | 17 | defp speak({last, hist, turn}, stop) do 18 | case :ets.lookup(hist, last) do 19 | [] -> 20 | true = :ets.insert(hist, {last, turn}) 21 | speak({0, hist, turn + 1}, stop) 22 | 23 | [{_, prev_turn}] -> 24 | true = :ets.insert(hist, {last, turn}) 25 | speak({turn - prev_turn, hist, turn + 1}, stop) 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /native/aoc/src/year_2021/day_21_01.rs: -------------------------------------------------------------------------------- 1 | use crate::util::parsers::read_line_ints; 2 | 3 | pub fn solve_21_01(raw_input: String) -> (usize, usize) { 4 | let input = read_line_ints(&raw_input); 5 | (get_increments_by(&input, 1), get_increments_by(&input, 3)) 6 | } 7 | 8 | fn get_increments_by(input: &[i32], by: usize) -> usize { 9 | let mut increment = 0; 10 | for i in 0..(input.len() - by) { 11 | if input[i] < input[i + by] { 12 | increment += 1 13 | } 14 | } 15 | increment 16 | } 17 | 18 | #[cfg(test)] 19 | mod tests { 20 | use super::*; 21 | use crate::util::io_helpers::read_input_from_resources; 22 | 23 | #[test] 24 | fn test_result_21_01() { 25 | let (year, day) = (2021, 1); 26 | let expected_result = (1139, 1103); 27 | 28 | let raw_input = read_input_from_resources(year, day, false); 29 | assert_eq!(solve_21_01(raw_input), expected_result); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/2020/day_06.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day06 do 2 | @moduledoc """ 3 | --- Day 6: Custom Customs --- 4 | Problem Link: https://adventofcode.com/2020/day/6 5 | """ 6 | alias AdventOfCode.Helpers.{InputReader, Transformers} 7 | 8 | def input, do: InputReader.read_from_file(2020, 6) 9 | 10 | def run(input \\ input()) do 11 | input = parse(input) 12 | {reducer(input, &answers/1), reducer(input, &unanimous_answers/1)} 13 | end 14 | 15 | def reducer(input, mapper), do: Enum.reduce(input, 0, &(mapper.(&1) + &2)) 16 | 17 | def parse(input) do 18 | input 19 | |> String.split(~r{\n\n|\r\r|\r\n\r\n}) 20 | |> Enum.map(&Transformers.lines/1) 21 | end 22 | 23 | defp answers(group) do 24 | group 25 | |> Enum.flat_map(&String.graphemes/1) 26 | |> Enum.uniq() 27 | |> Enum.count() 28 | end 29 | 30 | defp unanimous_answers(group) do 31 | group 32 | |> Enum.map(&MapSet.new(String.graphemes(&1))) 33 | |> Enum.reduce(&MapSet.intersection/2) 34 | |> Enum.count() 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/2018/day_05.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day05 do 2 | @moduledoc """ 3 | --- Day 5: Alchemical Reduction --- 4 | Problem Link: https://adventofcode.com/2018/day/5 5 | Difficulty: l 6 | Tags: reduction 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2018, 5) 11 | 12 | def run(input \\ input()) do 13 | input = String.to_charlist(input) 14 | {run_1(input), run_2(input)} 15 | end 16 | 17 | def run_1(input), do: react(input) 18 | 19 | @units ?A..?Z 20 | def run_2(input) do 21 | Enum.min( 22 | @units 23 | |> Enum.map(fn unit -> 24 | input 25 | |> Enum.reject(&(&1 == unit or abs(&1 - unit) == 32)) 26 | |> react() 27 | end) 28 | ) 29 | end 30 | 31 | def react(polymer) do 32 | Enum.reduce(polymer, {0, []}, fn 33 | unit, {length, [top | stack]} when abs(top - unit) == 32 -> {length - 1, stack} 34 | unit, {length, stack} -> {length + 1, [unit | stack]} 35 | end) 36 | |> elem(0) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :advent_of_code, 7 | version: "0.21.0", 8 | elixir: "~> 1.19", 9 | start_permanent: Mix.env() == :prod, 10 | aliases: aliases(), 11 | deps: deps(), 12 | elixirc_options: [warnings_as_errors: true] 13 | ] 14 | end 15 | 16 | # Run "mix help compile.app" to learn about applications. 17 | def application do 18 | [ 19 | extra_applications: [:eex, :logger] 20 | ] 21 | end 22 | 23 | # Run "mix help deps" to learn about dependencies. 24 | defp deps do 25 | [ 26 | {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, 27 | {:floki, "~> 0.36"}, 28 | {:httpoison, "~> 2.2"}, 29 | {:libgraph, "~> 0.16"}, 30 | {:aja, "~> 0.7"}, 31 | {:topo, "~> 1.0"}, 32 | {:rustler, "~> 0.35"} 33 | ] 34 | end 35 | 36 | defp aliases do 37 | [ 38 | update_stats: ["gen_stats", "gen_readme", "gen_tags", "gen_difficulties"] 39 | ] 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/2021/day_06.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day06 do 2 | @moduledoc """ 3 | --- Day 6: Lanternfish --- 4 | Problem Link: https://adventofcode.com/2021/day/6 5 | Difficulty: s 6 | Tags: map 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2021, 6) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | {Enum.sum(multiply(input, 80)), Enum.sum(multiply(input, 256))} 15 | end 16 | 17 | def parse(data) do 18 | data 19 | |> String.split(",") 20 | |> Enum.map(&String.to_integer/1) 21 | |> Enum.frequencies() 22 | end 23 | 24 | def multiply(fishes, day) do 25 | (day == 0 && Map.values(fishes)) || 26 | multiply( 27 | Map.pop(fishes, 0) 28 | |> then( 29 | &Map.merge( 30 | for({k, v} <- elem(&1, 1), into: %{}, do: {k - 1, v}), 31 | %{6 => elem(&1, 0) || 0, 8 => elem(&1, 0) || 0}, 32 | fn _, a, b -> a + b end 33 | ) 34 | ), 35 | day - 1 36 | ) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/helpers/helpers.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Helpers do 2 | @moduledoc """ 3 | Various helper functions during development and testing. 4 | """ 5 | @type board :: {non_neg_integer(), any()} 6 | @type elem :: any() 7 | @type idx :: non_neg_integer() 8 | @type list_2d :: list(list(elem())) 9 | 10 | @doc """ 11 | Prints a 2D board of the format map(tuple(idx, val)). 12 | """ 13 | @spec print2d(%{required(idx()) => board()}) :: list_2d() 14 | def print2d(map) do 15 | {{min_x, min_y}, {max_x, max_y}} = map |> Map.keys() |> Enum.min_max() 16 | 17 | for i <- min_x..max_x do 18 | for j <- min_y..max_y do 19 | map[{i, j}] 20 | end 21 | end 22 | end 23 | 24 | @doc """ 25 | Prints a 2D grid in stdout. No value is returned. 26 | """ 27 | @spec print2d(%{required(idx()) => board()}) :: no_return() 28 | def print2d_io(grid) do 29 | {x, y} = grid |> Map.keys() |> Enum.max() 30 | 31 | for i <- 0..x do 32 | for j <- 0..y do 33 | IO.write(grid[{i, j}]) 34 | end 35 | 36 | IO.puts("") 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/2018/day_06_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day06Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1806 5 | 6 | alias AdventOfCode.Y2018.Day06, as: Solution 7 | 8 | @data "1, 1\n1, 6\n8, 3\n3, 4\n5, 5\n8, 9" 9 | 10 | @points [ 11 | {1, 1}, 12 | {1, 6}, 13 | {8, 3}, 14 | {3, 4}, 15 | {5, 5}, 16 | {8, 9} 17 | ] 18 | 19 | describe "parse" do 20 | test "Parses input by creating a list of points from a set of strings" do 21 | assert Solution.parse(@data) == @points 22 | end 23 | end 24 | 25 | describe "get_corners/1" do 26 | test "Computes the extreme corners of a set of points" do 27 | assert Solution.get_corners(@points) == {{1, 8}, {1, 9}} 28 | end 29 | end 30 | 31 | describe "covers_most_points/3" do 32 | assert Solution.covers_most_points(@points) == 17 33 | end 34 | 35 | describe "covers_distances_within/3" do 36 | assert Solution.covers_distances_within(@points, 32) == 16 37 | end 38 | 39 | test "Year 2018, Day 6" do 40 | assert Solution.run() == {4284, 35_490} 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/2023/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day01 do 2 | @moduledoc """ 3 | --- Day 1: Trebuchet?! --- 4 | Problem Link: https://adventofcode.com/2023/day/1 5 | Difficulty: xs 6 | Tags: regex rust 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2023, 1) 11 | 12 | def run(input \\ input()) do 13 | input 14 | |> Transformers.lines() 15 | |> then( 16 | &{solve(&1, ~r"\d"), solve(&1, ~r/(?=(one|two|three|four|five|six|seven|eight|nine|\d))/)} 17 | ) 18 | end 19 | 20 | defp solve(input, regex) do 21 | for line <- input, reduce: 0 do 22 | acc -> 23 | regex 24 | |> Regex.scan(line) 25 | |> Enum.map(&List.last/1) 26 | |> then(&(10 * tr(List.first(&1)) + tr(List.last(&1)))) 27 | |> Kernel.+(acc) 28 | end 29 | end 30 | 31 | ~w/one two three four five six seven eight nine/ 32 | |> Enum.with_index(1) 33 | |> Enum.each(fn {word, index} -> 34 | defp tr(unquote(word)), do: unquote(index) 35 | end) 36 | 37 | defp tr(numeric), do: String.to_integer(numeric) 38 | end 39 | -------------------------------------------------------------------------------- /lib/2019/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day01 do 2 | @moduledoc """ 3 | --- Day 1: The Tyranny of the Rocket Equation --- 4 | Problem Link: https://adventofcode.com/2019/day/1 5 | Difficulty: xs 6 | Tags: calculation rust 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2019, 1) 11 | 12 | def run(input \\ input()) do 13 | parsed_data = parse(input) 14 | {run_1(parsed_data), run_2(parsed_data)} 15 | end 16 | 17 | def run_1(input) do 18 | Enum.sum_by(input, &fuel_required/1) 19 | end 20 | 21 | def run_2(input) do 22 | input 23 | |> Enum.sum_by(fn mass -> 24 | required_fuel = fuel_required(mass) 25 | refuel(required_fuel, required_fuel) 26 | end) 27 | end 28 | 29 | def parse(data) do 30 | data 31 | |> Transformers.lines() 32 | |> Enum.map(&String.to_integer/1) 33 | end 34 | 35 | defp fuel_required(mass), do: Integer.floor_div(mass, 3) - 2 36 | 37 | defp refuel(fuel, total) do 38 | next = fuel_required(fuel) 39 | (next < 1 && total) || refuel(next, total + next) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/2021/day_07.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day07 do 2 | @moduledoc """ 3 | --- Day 7: The Treachery of Whales --- 4 | Problem Link: https://adventofcode.com/2021/day/7 5 | Difficulty: xs 6 | Tags: calculation 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2021, 7) 11 | 12 | def run(input \\ input()) do 13 | input = Transformers.int_words(input, ",") 14 | {run_1(input), run_2(input)} 15 | end 16 | 17 | def run_1(input), do: input |> alignments(&fixed_cost/2) |> Enum.min() 18 | def run_2(input), do: input |> alignments(&cost/2) |> Enum.min() 19 | 20 | defp alignments(positions, cost_fn) do 21 | {min, max} = Enum.min_max(positions) 22 | 23 | for cur <- min..max do 24 | for pos <- positions, reduce: 0 do 25 | cost -> cost + cost_fn.(cur, pos) 26 | end 27 | end 28 | end 29 | 30 | defp fixed_cost(current, position), do: abs(position - current) 31 | 32 | defp cost(current, position) do 33 | steps = abs(position - current) 34 | (steps == 0 && 0) || div(steps * (steps + 1), 2) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/mix/tasks/gen.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.Gen do 2 | @moduledoc """ 3 | Generates boilerplate code for solving a problem for a `year` and `day`. 4 | 5 | Type `mix gen --year --day ` to create the boilerplate files for 6 | solving the problem of the year and day . 7 | 8 | For example, `mix gen --year 2015 --day 2` will generate `lib/2015/day_2.ex`, 9 | `lib/data/inputs/2015_2.txt`, and `test/2015/day_2_test.exs` and contain the common 10 | structure (i.e. module name, file reader function, test cases etc) 11 | """ 12 | 13 | alias AdventOfCode.Helpers.{Generator, InputParser} 14 | 15 | use Mix.Task 16 | 17 | @usage "mix gen --year --day OR mix gen " 18 | 19 | @shortdoc """ 20 | Creates a boilerplate for solving a year/day's problem. 21 | """ 22 | @impl Mix.Task 23 | def run(args) do 24 | case InputParser.parse(args) do 25 | {year, day} -> 26 | {to_string(year), to_string(day)} 27 | |> Generator.run() 28 | |> Mix.shell().info() 29 | 30 | _ -> 31 | Mix.shell().error("[Usage] #{@usage}") 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/2018/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day01 do 2 | @moduledoc """ 3 | --- Day 1: Chronal Calibration --- 4 | Problem Link: https://adventofcode.com/2018/day/1 5 | Difficulty: s 6 | Tags: sequence set rust 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2018, 1) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | 15 | {run_1(input), run_2(input)} 16 | end 17 | 18 | def run_1(input) do 19 | Enum.reduce(input, 0, &Kernel.+/2) 20 | end 21 | 22 | def run_2(input) do 23 | input 24 | |> Stream.cycle() 25 | |> Enum.reduce_while({%MapSet{}, 0}, fn cur, {history, prev} -> 26 | new_frequency = prev + cur 27 | 28 | if MapSet.member?(history, new_frequency) do 29 | {:halt, new_frequency} 30 | else 31 | {:cont, {MapSet.put(history, new_frequency), new_frequency}} 32 | end 33 | end) 34 | end 35 | 36 | @spec parse(String.t()) :: [String.t()] 37 | def parse(input) do 38 | input 39 | |> Transformers.lines() 40 | |> Enum.map(&String.to_integer/1) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/2022/day_04.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day04 do 2 | @moduledoc """ 3 | --- Day 4: Camp Cleanup --- 4 | Problem Link: https://adventofcode.com/2022/day/4 5 | Difficulty: xs 6 | Tags: range set 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2022, 4) 11 | 12 | def run(input \\ input()) do 13 | with input <- parse(input), do: {run_1(input), run_2(input)} 14 | end 15 | 16 | defp run_1(data), 17 | do: Enum.reduce(data, 0, fn [a, b], acc -> acc + ((subset?(a, b) && 1) || 0) end) 18 | 19 | defp run_2(data), 20 | do: Enum.reduce(data, 0, fn [a, b], acc -> acc + ((MapSet.disjoint?(a, b) && 0) || 1) end) 21 | 22 | defp subset?(a, b), do: MapSet.subset?(a, b) || MapSet.subset?(b, a) 23 | 24 | def parse(data) do 25 | data 26 | |> Transformers.lines() 27 | |> Enum.map(fn line -> 28 | line 29 | |> String.split(",") 30 | |> Enum.map(fn range -> 31 | [from, to] = range |> String.split("-") |> Enum.map(&String.to_integer/1) 32 | MapSet.new(Range.new(from, to)) 33 | end) 34 | end) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /priv/input_files/2017_2.txt: -------------------------------------------------------------------------------- 1 | 116 1470 2610 179 2161 2690 831 1824 2361 1050 2201 118 145 2275 2625 2333 2 | 976 220 1129 553 422 950 332 204 1247 1092 1091 159 174 182 984 713 3 | 84 78 773 62 808 83 1125 1110 1184 145 1277 982 338 1182 75 679 4 | 3413 3809 3525 2176 141 1045 2342 2183 157 3960 3084 2643 119 108 3366 2131 5 | 1312 205 343 616 300 1098 870 1008 1140 1178 90 146 980 202 190 774 6 | 4368 3905 3175 4532 3806 1579 4080 259 2542 221 4395 4464 208 3734 234 4225 7 | 741 993 1184 285 1062 372 111 118 63 843 325 132 854 105 956 961 8 | 85 79 84 2483 858 2209 2268 90 2233 1230 2533 322 338 68 2085 1267 9 | 2688 2022 112 130 1185 103 1847 3059 911 107 2066 1788 2687 2633 415 1353 10 | 76 169 141 58 161 66 65 225 60 152 62 64 156 199 80 56 11 | 220 884 1890 597 3312 593 4259 222 113 2244 3798 4757 216 1127 4400 178 12 | 653 369 216 132 276 102 265 889 987 236 239 807 1076 932 84 864 13 | 799 739 75 1537 82 228 69 1397 1396 1203 1587 63 313 1718 1375 469 14 | 1176 112 1407 136 1482 1534 1384 1202 604 851 190 284 1226 113 114 687 15 | 73 1620 81 1137 812 75 1326 1355 1545 1666 1356 1681 1732 85 128 902 16 | 571 547 160 237 256 30 496 592 385 576 183 692 192 387 647 233 17 | -------------------------------------------------------------------------------- /lib/2015/day_10.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day10 do 2 | @moduledoc """ 3 | --- Day 10: Elves Look, Elves Say --- 4 | Problem Link: https://adventofcode.com/2015/day/10 5 | Difficulty: xs 6 | Tags: string-encoding sequence reduction 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2015, 10) 11 | 12 | def run(input \\ input()), do: look_and_say(String.graphemes(input), 40, 50) 13 | 14 | def encode(input), do: Enum.reverse(encode(input, nil, nil, [])) 15 | def encode([], b, n, r), do: [b, to_string(n) | r] 16 | def encode([a | input], nil, nil, []), do: encode(input, a, 1, []) 17 | def encode([a | input], a, n, r), do: encode(input, a, n + 1, r) 18 | def encode([a | input], b, n, r), do: encode(input, a, 1, [b, to_string(n) | r]) 19 | 20 | defp look_and_say(input, first_stop, second_stop) do 21 | 1..second_stop 22 | |> Enum.reduce({nil, input}, fn x, {a, b} -> 23 | case {x, encode(b)} do 24 | {^first_stop, data} -> {data, data} 25 | {_, data} -> {a, data} 26 | end 27 | end) 28 | |> then(fn {a, b} -> {length(a), length(b)} end) 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/2017/day_04.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day04 do 2 | @moduledoc """ 3 | --- Day 4: High-Entropy Passphrases --- 4 | Problem Link: https://adventofcode.com/2017/day/4 5 | Difficulty: xs 6 | Tags: validation rust 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2017, 4) 11 | 12 | def run(input \\ input()) do 13 | input = input |> Transformers.lines() |> Enum.map(&Transformers.words/1) 14 | 15 | {run_1(input), run_2(input)} 16 | end 17 | 18 | def run_1(input), do: count_valids(input, &duplicates?/1) 19 | def run_2(input), do: count_valids(input, &anagrams?/1) 20 | 21 | def count_valids(data, fun), do: data |> Enum.map(fun) |> Enum.filter(& &1) |> length() 22 | 23 | def duplicates?(words) do 24 | words 25 | |> Enum.reduce_while(%MapSet{}, fn word, set -> 26 | (word in set && {:halt, nil}) || {:cont, MapSet.put(set, word)} 27 | end) 28 | |> then(&(!is_nil(&1))) 29 | end 30 | 31 | def anagrams?(words) do 32 | words 33 | |> Enum.map(fn str -> str |> String.graphemes() |> Enum.sort() end) 34 | |> duplicates?() 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/2019/day_04.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day04 do 2 | @moduledoc """ 3 | --- Day 4: Secure Container --- 4 | Problem Link: https://adventofcode.com/2019/day/4 5 | Difficulty: xs 6 | Tags: sequence inline-input not-fast-enough 7 | """ 8 | def input, do: 245_182..790_572 9 | 10 | def run(input \\ input()), do: {run_1(input), run_2(input)} 11 | 12 | def run_1(range) do 13 | Enum.count(for n <- range, n |> adjacent() and n |> increasing(), do: n) 14 | end 15 | 16 | def run_2(range) do 17 | Enum.count(for n <- range, n |> adjacent_2() and n |> increasing(), do: n) 18 | end 19 | 20 | def adjacent(number) do 21 | number 22 | |> Integer.digits() 23 | |> Enum.dedup() 24 | |> Kernel.!=(Integer.digits(number)) 25 | end 26 | 27 | def increasing(number) do 28 | number 29 | |> Integer.digits() 30 | |> Enum.chunk_every(2, 1, :discard) 31 | |> Enum.map(fn [a, b] -> a <= b end) 32 | |> Enum.all?() 33 | end 34 | 35 | def adjacent_2(number) do 36 | number 37 | |> Integer.digits() 38 | |> Enum.chunk_by(& &1) 39 | |> Enum.filter(fn dups -> Enum.count(dups) == 2 end) 40 | |> Enum.any?() 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /native/aoc/src/year_2015/day_15_01.rs: -------------------------------------------------------------------------------- 1 | pub fn solve_15_01(raw_input: String) -> (i32, i32) { 2 | let input = process(&raw_input); 3 | (part_1(&input), part_2(&input)) 4 | } 5 | 6 | fn process(input_data: &str) -> Vec { 7 | input_data 8 | .chars() 9 | .map(|b| match b { 10 | '(' => 1, 11 | ')' => -1, 12 | _ => 0, 13 | }) 14 | .collect() 15 | } 16 | fn part_1(input_data: &[i32]) -> i32 { 17 | input_data.iter().sum() 18 | } 19 | 20 | fn part_2(input_data: &[i32]) -> i32 { 21 | let mut floor = 0; 22 | 23 | for (i, x) in input_data.iter().enumerate() { 24 | floor += x; 25 | 26 | if floor < 0 { 27 | return (i as i32) + 1; 28 | } 29 | } 30 | 31 | unreachable!() 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | use crate::util::io_helpers::read_input_from_resources; 38 | 39 | #[test] 40 | fn test_result_15_01() { 41 | let raw_input = read_input_from_resources(2015, 1, false); 42 | let expected_result = (232, 1783); 43 | 44 | assert_eq!(solve_15_01(raw_input), expected_result); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/mix/tasks/gen_readme.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.GenReadme do 2 | @moduledoc """ 3 | Updates the README.md for all years. 4 | 5 | Type `mix gen_readme` to update `README.md` with total stars gained for all years. 6 | 7 | For example, `mix gen_readme` will generate `README.md`. 8 | """ 9 | 10 | alias AdventOfCode.Helpers.Summarizer 11 | 12 | use Mix.Task 13 | 14 | @usage "mix gen_readme" 15 | 16 | @shortdoc """ 17 | Creates the per year README.md with updated solution status. 18 | """ 19 | @impl Mix.Task 20 | def run(_) do 21 | read_me_static = 22 | :advent_of_code 23 | |> :code.priv_dir() 24 | |> Path.join("partials/readme_content.md") 25 | |> File.read!() 26 | 27 | content = 28 | """ 29 | 34 | #{read_me_static} 35 | #{Summarizer.summarize()} 36 | """ 37 | 38 | File.write!("README.md", content) 39 | 40 | Mix.shell().info("README.md successfully updated.") 41 | rescue 42 | _ -> Mix.shell().error(@usage) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /priv/input_files/2015_19.txt: -------------------------------------------------------------------------------- 1 | Al => ThF 2 | Al => ThRnFAr 3 | B => BCa 4 | B => TiB 5 | B => TiRnFAr 6 | Ca => CaCa 7 | Ca => PB 8 | Ca => PRnFAr 9 | Ca => SiRnFYFAr 10 | Ca => SiRnMgAr 11 | Ca => SiTh 12 | F => CaF 13 | F => PMg 14 | F => SiAl 15 | H => CRnAlAr 16 | H => CRnFYFYFAr 17 | H => CRnFYMgAr 18 | H => CRnMgYFAr 19 | H => HCa 20 | H => NRnFYFAr 21 | H => NRnMgAr 22 | H => NTh 23 | H => OB 24 | H => ORnFAr 25 | Mg => BF 26 | Mg => TiMg 27 | N => CRnFAr 28 | N => HSi 29 | O => CRnFYFAr 30 | O => CRnMgAr 31 | O => HP 32 | O => NRnFAr 33 | O => OTi 34 | P => CaP 35 | P => PTi 36 | P => SiRnFAr 37 | Si => CaSi 38 | Th => ThCa 39 | Ti => BP 40 | Ti => TiTi 41 | e => HF 42 | e => NAl 43 | e => OMg 44 | 45 | CRnCaCaCaSiRnBPTiMgArSiRnSiRnMgArSiRnCaFArTiTiBSiThFYCaFArCaCaSiThCaPBSiThSiThCaCaPTiRnPBSiThRnFArArCaCaSiThCaSiThSiRnMgArCaPTiBPRnFArSiThCaSiRnFArBCaSiRnCaPRnFArPMgYCaFArCaPTiTiTiBPBSiThCaPTiBPBSiRnFArBPBSiRnCaFArBPRnSiRnFArRnSiRnBFArCaFArCaCaCaSiThSiThCaCaPBPTiTiRnFArCaPTiBSiAlArPBCaCaCaCaCaSiRnMgArCaSiThFArThCaSiThCaSiRnCaFYCaSiRnFYFArFArCaSiRnFYFArCaSiRnBPMgArSiThPRnFArCaSiRnFArTiRnSiRnFYFArCaSiRnBFArCaSiRnTiMgArSiThCaSiThCaFArPRnFArSiRnFArTiTiTiTiBCaCaSiRnCaCaFYFArSiThCaPTiBPTiBCaSiThSiRnMgArCaF 46 | -------------------------------------------------------------------------------- /lib/2017/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day01 do 2 | @moduledoc """ 3 | --- Day 1: Inverse Captcha --- 4 | Problem Link: https://adventofcode.com/2017/day/1 5 | Difficulty: xs 6 | Tags: sliding-window rust 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2017, 1) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | 15 | {run_1(input), run_2(input)} 16 | end 17 | 18 | defp run_1(input), do: Enum.sum(matches_with_next(input)) 19 | 20 | defp run_2(input) do 21 | half = div(length(input), 2) 22 | matching_pair_sum(Enum.split(input, half)) 23 | end 24 | 25 | def parse(input) do 26 | input 27 | |> String.graphemes() 28 | |> Enum.map(&String.to_integer/1) 29 | end 30 | 31 | defp matches_with_next([h | _] = lst) do 32 | lst 33 | |> Enum.chunk_every(2, 1, [h]) 34 | |> Enum.map(fn pair -> 35 | case pair do 36 | [a, a] -> a 37 | _ -> 0 38 | end 39 | end) 40 | end 41 | 42 | defp matching_pair_sum({a, b}) do 43 | Enum.zip(a, b) 44 | |> Enum.sum_by(fn 45 | {a, a} -> a + a 46 | _ -> 0 47 | end) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /native/aoc/src/year_2018/day_18_01.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | use crate::util::parsers::read_line_ints; 4 | 5 | pub fn solve_18_01(raw_input: String) -> (i32, i32) { 6 | let input = read_line_ints(&raw_input); 7 | (part_1(&input), part_2(&input)) 8 | } 9 | 10 | fn part_1(input: &[i32]) -> i32 { 11 | input.iter().sum() 12 | } 13 | 14 | fn part_2(input: &[i32]) -> i32 { 15 | let mut current_frequency = 0; 16 | let mut frequencies: HashSet = HashSet::new(); 17 | 18 | for i in input.iter().cycle() { 19 | current_frequency += *i; 20 | if frequencies.contains(¤t_frequency) { 21 | return current_frequency; 22 | } 23 | frequencies.insert(current_frequency); 24 | } 25 | unreachable!() 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | use crate::util::io_helpers::read_input_from_resources; 32 | 33 | #[test] 34 | fn test_result_18_01() { 35 | let (year, day) = (2018, 1); 36 | let expected_result = (590, 83445); 37 | 38 | let raw_input = read_input_from_resources(year, day, false); 39 | assert_eq!(solve_18_01(raw_input), expected_result); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/mix/tasks/solve.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.Solve do 2 | @moduledoc """ 3 | Solves a problem given `year` and `day`. 4 | 5 | Type `mix solve --year --day ` to see result for and day . 6 | """ 7 | alias AdventOfCode.Helpers.InputParser 8 | 9 | use Mix.Task 10 | 11 | @usage "mix solve --year --day OR mix solve " 12 | 13 | @shortdoc """ 14 | Provides solution for and . 15 | """ 16 | @impl Mix.Task 17 | def run(args) do 18 | case InputParser.parse(args) do 19 | {year, day} -> 20 | case AdventOfCode.solve(year, day, false) do 21 | {:ok, {time, {part_1, part_2}}} -> 22 | Mix.shell().info("Part 1: #{part_1}\tPart 2: #{part_2}\tTime: #{time} µs") 23 | 24 | {:error, :not_yet_solved} -> 25 | Mix.shell().error("#{year}/#{day} is not solved yet") 26 | 27 | {:error, :invalid_args} -> 28 | Mix.shell().error("Invalid year/day: #{year}/#{day}") 29 | end 30 | 31 | _ -> 32 | Mix.shell().error(""" 33 | [Usage] #{@usage} 34 | \tWHERE 2015 <= year <= #{AdventOfCode.get_latest_year()} and 1 <= day <= 25 35 | """) 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /priv/input_files/2019_1.txt: -------------------------------------------------------------------------------- 1 | 139301 2 | 84565 3 | 124180 4 | 133902 5 | 138726 6 | 62665 7 | 142967 8 | 95598 9 | 118044 10 | 73234 11 | 76476 12 | 51634 13 | 71582 14 | 63619 15 | 148430 16 | 134733 17 | 101537 18 | 101140 19 | 144543 20 | 102233 21 | 62048 22 | 128633 23 | 130113 24 | 92531 25 | 73820 26 | 54964 27 | 103485 28 | 96364 29 | 104119 30 | 121954 31 | 79215 32 | 99235 33 | 120179 34 | 69237 35 | 145584 36 | 79193 37 | 50684 38 | 146481 39 | 67783 40 | 112741 41 | 85024 42 | 62298 43 | 54083 44 | 137704 45 | 116561 46 | 76862 47 | 81410 48 | 96341 49 | 89992 50 | 132926 51 | 97955 52 | 74751 53 | 147553 54 | 121496 55 | 113303 56 | 119671 57 | 120871 58 | 114278 59 | 125628 60 | 144275 61 | 78826 62 | 87092 63 | 65883 64 | 87517 65 | 93974 66 | 55358 67 | 100922 68 | 113304 69 | 115728 70 | 144556 71 | 91728 72 | 86367 73 | 55283 74 | 101841 75 | 55454 76 | 140703 77 | 70706 78 | 98173 79 | 106920 80 | 126984 81 | 148960 82 | 77909 83 | 128304 84 | 140036 85 | 81044 86 | 141419 87 | 126770 88 | 52787 89 | 115783 90 | 128647 91 | 125986 92 | 124506 93 | 113935 94 | 142203 95 | 106404 96 | 78433 97 | 146573 98 | 68575 99 | 63563 100 | 115616 -------------------------------------------------------------------------------- /lib/2024/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2024.Day01 do 2 | @moduledoc """ 3 | --- Day 1: Historian Hysteria --- 4 | Problem Link: https://adventofcode.com/2024/day/1 5 | Difficulty: xs 6 | Tags: list 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2024, 1) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | 15 | {run_1(input), run_2(input)} 16 | end 17 | 18 | defp run_1({left_list, right_list, _}) do 19 | for {left, right} <- Enum.zip(left_list, right_list), reduce: 0 do 20 | acc -> acc + abs(left - right) 21 | end 22 | end 23 | 24 | defp run_2({left_list, _, tally}) do 25 | for id_value <- left_list, reduce: 0 do 26 | acc -> acc + id_value * Map.get(tally, id_value, 0) 27 | end 28 | end 29 | 30 | def parse(data \\ input()) do 31 | {left, right} = 32 | for line <- Transformers.lines(data), reduce: {[], []} do 33 | {left_list, right_list} -> 34 | [left, right] = String.split(line) 35 | {[String.to_integer(left) | left_list], [String.to_integer(right) | right_list]} 36 | end 37 | 38 | {Enum.sort(left), Enum.sort(right), Enum.frequencies(right)} 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/2020/day_05.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day05 do 2 | @moduledoc """ 3 | --- Day 5: Binary Boarding --- 4 | Problem Link: https://adventofcode.com/2020/day/5 5 | """ 6 | alias AdventOfCode.Helpers.{InputReader, Transformers} 7 | 8 | def input, do: InputReader.read_from_file(2020, 5) 9 | 10 | def run(input \\ input()) do 11 | input = ids(Transformers.lines(input)) 12 | {Enum.max(input), my_id(input)} 13 | end 14 | 15 | def walk("F" <> pass, lo, hi), do: walk(pass, lo, mid(lo, hi)) 16 | def walk("B" <> pass, lo, hi), do: walk(pass, mid(lo, hi) + 1, hi) 17 | def walk(pass, row, row) when pass != "", do: {row, walk(pass, 0, 7)} 18 | 19 | def walk("L" <> pass, lo, hi), do: walk(pass, lo, mid(lo, hi)) 20 | def walk("R" <> pass, lo, hi), do: walk(pass, mid(lo, hi) + 1, hi) 21 | def walk("", column, column), do: column 22 | 23 | defp ids(data), do: Enum.map(data, &uid(walk(&1, 0, 127))) 24 | 25 | defp mid(lo, hi), do: div(lo + hi, 2) 26 | defp uid({row, col}), do: row * 8 + col 27 | 28 | defp my_id(ids) do 29 | sorted_ids = Enum.sort(ids) 30 | 31 | sorted_ids 32 | |> Enum.zip(tl(sorted_ids)) 33 | |> Keyword.filter(fn {a, b} -> b - a != 1 end) 34 | |> then(fn [{_, b}] -> b - 1 end) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/2017/day_02.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day02 do 2 | @moduledoc """ 3 | --- Day 2: Corruption Checksum --- 4 | Problem Link: https://adventofcode.com/2017/day/2 5 | Difficulty: xs 6 | Tags: arithmetic sequence rust 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2017, 2) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | 15 | {run(input, &Enum.min_max/1, &Kernel.-/2), run(input, &evenly_divide/1, &Kernel.div/2)} 16 | end 17 | 18 | def run(input, fn_1, fn_2) do 19 | Enum.reduce(input, 0, fn line, acc -> 20 | {min, max} = fn_1.(line) 21 | acc + fn_2.(max, min) 22 | end) 23 | end 24 | 25 | def parse(input) do 26 | input 27 | |> Transformers.lines() 28 | |> Enum.map(fn line -> 29 | line 30 | |> String.split("\t") 31 | |> Enum.map(&String.to_integer/1) 32 | end) 33 | end 34 | 35 | def evenly_divide(lst) do 36 | for i <- lst do 37 | for j <- lst do 38 | if i != j and i > j and rem(i, j) == 0 do 39 | {j, i} 40 | end 41 | end 42 | |> Enum.reject(&is_nil/1) 43 | end 44 | |> Enum.flat_map(& &1) 45 | |> List.first() 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /priv/input_files/2019_10.txt: -------------------------------------------------------------------------------- 1 | .#..#..##.#...###.#............#. 2 | .....#..........##..#..#####.#..# 3 | #....#...#..#.......#...........# 4 | .#....#....#....#.#...#.#.#.#.... 5 | ..#..#.....#.......###.#.#.##.... 6 | ...#.##.###..#....#........#..#.# 7 | ..#.##..#.#.#...##..........#...# 8 | ..#..#.......................#..# 9 | ...#..#.#...##.#...#.#..#.#...... 10 | ......#......#.....#............. 11 | .###..#.#..#...#..#.#.......##..# 12 | .#...#.................###......# 13 | #.#.......#..####.#..##.###.....# 14 | .#.#..#.#...##.#.#..#..##.#.#.#.. 15 | ##...#....#...#....##....#.#....# 16 | ......#..#......#.#.....##..#.#.. 17 | ##.###.....#.#.###.#..#..#..###.. 18 | #...........#.#..#..#..#....#.... 19 | ..........#.#.#..#.###...#.....#. 20 | ...#.###........##..#..##........ 21 | .###.....#.#.###...##.........#.. 22 | #.#...##.....#.#.........#..#.### 23 | ..##..##........#........#......# 24 | ..####......#...#..........#.#... 25 | ......##...##.#........#...##.##. 26 | .#..###...#.......#........#....# 27 | ...##...#..#...#..#..#.#.#...#... 28 | ....#......#.#............##..... 29 | #......####...#.....#...#......#. 30 | ...#............#...#..#.#.#..#.# 31 | .#...#....###.####....#.#........ 32 | #.#...##...#.##...#....#.#..##.#. 33 | .#....#.###..#..##.#.##...#.#..## -------------------------------------------------------------------------------- /native/aoc/src/year_2017/day_17_01.rs: -------------------------------------------------------------------------------- 1 | pub fn solve_17_01(raw_input: String) -> (i32, i32) { 2 | let processed_input = process(raw_input); 3 | 4 | (part_1(&processed_input), part_2(&processed_input)) 5 | } 6 | 7 | fn process(raw_input: String) -> Vec { 8 | raw_input 9 | .trim() 10 | .chars() 11 | .map(|c| (c as i32) - 0x30) 12 | .collect() 13 | } 14 | 15 | fn part_1(input: &[i32]) -> i32 { 16 | captcha(input, 1) 17 | } 18 | 19 | fn part_2(input: &[i32]) -> i32 { 20 | captcha(input, input.len() / 2) 21 | } 22 | 23 | fn captcha(input: &[i32], by: usize) -> i32 { 24 | let mut rotated = input.to_owned(); 25 | rotated.rotate_left(by); 26 | input 27 | .iter() 28 | .zip(rotated.iter()) 29 | .filter_map(|(a, b)| (a == b).then_some(*a)) 30 | .sum() 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use super::*; 36 | use crate::util::io_helpers::read_input_from_resources; 37 | 38 | #[test] 39 | fn test_result_17_01() { 40 | let (year, day) = (2017, 1); 41 | let expected_result = (1089, 1156); 42 | 43 | let raw_input = read_input_from_resources(year, day, false); 44 | assert_eq!(solve_17_01(raw_input), expected_result); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/2015/day_08.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day08 do 2 | @moduledoc """ 3 | --- Day 8: Matchsticks --- 4 | Problem Link: https://adventofcode.com/2015/day/8 5 | Difficulty: m 6 | Tags: string-encoding annoying 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2015, 8) 11 | 12 | def run(input \\ input()) do 13 | input = Transformers.lines(input) 14 | 15 | {run_1(input), run_2(input)} 16 | end 17 | 18 | defp run_1(input) do 19 | Enum.reduce(input, 0, fn line, acc -> 20 | acc + String.length(line) - actual_length(line) 21 | end) 22 | end 23 | 24 | defp run_2(input) do 25 | Enum.reduce(input, 0, fn line, acc -> 26 | acc + expanded_length(line) - String.length(line) 27 | end) 28 | end 29 | 30 | @esc_regex ~r/(\\\\|\\\"|\\x[\da-f]{2})/ 31 | @empty_regex ~r/\"/ 32 | def actual_length(line) do 33 | line 34 | |> unescape(@esc_regex, "*") 35 | |> unescape(@empty_regex, "") 36 | |> String.length() 37 | end 38 | 39 | @expansion_regex ~r/(\\|\")/ 40 | def expanded_length(line), do: 2 + String.length(unescape(line, @expansion_regex, "**")) 41 | defp unescape(line, regex, replacement), do: Regex.replace(regex, line, replacement) 42 | end 43 | -------------------------------------------------------------------------------- /test/2016/day_09_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day09Test do 2 | @moduledoc false 3 | 4 | use ExUnit.Case, async: true 5 | @moduletag :y1609 6 | 7 | alias AdventOfCode.Y2016.Day09, as: Solution 8 | 9 | test "Year 2016, Day 9" do 10 | assert Solution.run() == {102_239, 10_780_403_063} 11 | end 12 | 13 | describe "Year 2016, Day 9, Part 1" do 14 | params = [ 15 | {"ADVENT", 6}, 16 | {"A(1x5)BC", 7}, 17 | {"(3x3)XYZ", 9}, 18 | {"A(2x2)BCD(2x2)EFG", 11}, 19 | {"(6x1)(1x3)A", 6}, 20 | {"X(8x2)(3x3)ABCY", 18} 21 | ] 22 | 23 | for {input, output} <- params do 24 | test "Works for #{input}" do 25 | assert Solution.decompress_v1(unquote(input)) == unquote(output) 26 | end 27 | end 28 | end 29 | 30 | describe "Year 2016, Day 9, Part 2" do 31 | params = [ 32 | {"ADVENT", 6}, 33 | {"(3x3)XYZ", 9}, 34 | {"X(8x2)(3x3)ABCY", 20}, 35 | {"(27x12)(20x12)(13x14)(7x10)(1x12)A", 241_920}, 36 | {"(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN", 445} 37 | ] 38 | 39 | for {input, output} <- params do 40 | test "Works for #{input}" do 41 | assert Solution.decompress_v2(unquote(input)) == unquote(output) 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/2016/day_06.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day06 do 2 | @moduledoc """ 3 | --- Day 6: Signals and Noise --- 4 | Problem Link: https://adventofcode.com/2016/day/6 5 | Difficulty: xs 6 | Tags: sequence optimization 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2016, 6) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | 15 | {do_run(input, :max), do_run(input, :min)} 16 | end 17 | 18 | def do_run(input, type), do: Enum.map_join(input, &frequency(&1, type)) 19 | 20 | def parse(input) do 21 | len = input |> Transformers.lines() |> hd() |> String.length() 22 | 23 | input 24 | |> String.replace("\n", "") 25 | |> String.replace("\r", "") 26 | |> String.codepoints() 27 | |> Enum.with_index() 28 | |> Enum.map(fn {k, idx} -> {k, rem(idx, len)} end) 29 | |> Enum.group_by(fn {_, group} -> group end, fn {v, _} -> v end) 30 | |> Map.values() 31 | |> Enum.map(&Enum.join/1) 32 | end 33 | 34 | defp frequency(word, by) do 35 | word 36 | |> String.codepoints() 37 | |> Enum.group_by(& &1) 38 | |> Map.values() 39 | |> Enum.min_max_by(&length/1) 40 | |> then(fn {min, max} -> hd((by == :max && max) || min) end) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/2020/day_01.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day01 do 2 | @moduledoc """ 3 | --- Day 1: Report Repair --- 4 | Problem Link: https://adventofcode.com/2020/day/1 5 | """ 6 | alias AdventOfCode.Helpers.{InputReader, Transformers} 7 | 8 | def input, do: InputReader.read_from_file(2020, 1) 9 | 10 | def run(input \\ input()) do 11 | input = Transformers.int_lines(input) 12 | {two_entries(input), three_entries(input)} 13 | end 14 | 15 | def two_entries(xs), do: two_entries(xs, MapSet.new(xs)) 16 | 17 | def two_entries(xs, set) do 18 | Enum.reduce_while(xs, nil, fn x, _ -> 19 | halt_and_get(set, x, x) 20 | end) 21 | end 22 | 23 | def three_entries(xs), do: three_entries(xs, MapSet.new(xs)) 24 | 25 | def three_entries([_ | ys] = xs, set) do 26 | Enum.reduce_while(xs, nil, fn x, _ -> 27 | Enum.reduce_while(ys, nil, fn y, _ -> 28 | halt_and_get(set, x + y, x * y) 29 | end) 30 | |> halt_and_get() 31 | end) 32 | end 33 | 34 | @year 2020 35 | defp halt_and_get(set, added, multiplied) do 36 | ((@year - added) in set && 37 | {:halt, multiplied * (@year - added)}) || 38 | {:cont, nil} 39 | end 40 | 41 | defp halt_and_get(nil), do: {:cont, nil} 42 | defp halt_and_get(result), do: {:halt, result} 43 | end 44 | -------------------------------------------------------------------------------- /lib/2015/day_24.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day24 do 2 | @moduledoc """ 3 | --- Day 24: It Hangs in the Balance --- 4 | Problem Link: https://adventofcode.com/2015/day/24 5 | Difficulty: xl 6 | Tags: not-fast-enough power-set ambiguous-solution 7 | """ 8 | alias AdventOfCode.Algorithms.SubsetSum 9 | alias AdventOfCode.Helpers.{InputReader, Transformers} 10 | 11 | def input, do: InputReader.read_from_file(2015, 24) 12 | 13 | def run(input \\ input()) do 14 | weights = Transformers.int_lines(input) 15 | total = Enum.sum(weights) 16 | 17 | part_1 = Task.async(fn -> optimal_configuration(weights, div(total, 3)) end) 18 | part_2 = Task.async(fn -> optimal_configuration(weights, div(total, 4)) end) 19 | 20 | { 21 | Task.await(part_1, 10_000), 22 | Task.await(part_2, 10_000) 23 | } 24 | end 25 | 26 | def optimal_configuration(weights, target) do 27 | configurations = SubsetSum.find_subsets(weights, target) 28 | smallest_length = smallest_length(configurations) 29 | 30 | configurations 31 | |> Enum.filter(&(length(&1) == smallest_length)) 32 | |> Enum.min_by(&Enum.product/1) 33 | |> Enum.product() 34 | end 35 | 36 | def smallest_length(list_of_list) do 37 | list_of_list |> Enum.min_by(&length/1) |> length() 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/2017/day_14.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day14 do 2 | @moduledoc """ 3 | --- Day 14: Disk Defragmentation --- 4 | Problem Link: https://adventofcode.com/2017/day/14 5 | Difficulty: m 6 | Tags: not-fast-enough half-done hash 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | alias AdventOfCode.Y2017.Day10 10 | 11 | def input, do: InputReader.read_from_file(2017, 14) 12 | 13 | def run(input \\ input()) do 14 | squares = input |> parse() |> squares() 15 | 16 | {run_1(squares), run_2(squares)} 17 | end 18 | 19 | def parse(data \\ input()), do: hd(Transformers.lines(data)) 20 | 21 | defp run_1(squares) do 22 | squares 23 | |> Enum.sum_by(&Enum.count(&1, fn i -> i == "1" end)) 24 | end 25 | 26 | defp run_2(_squares) do 27 | {:todo, 2} 28 | end 29 | 30 | defp squares(input) do 31 | 0..127 32 | |> Enum.map(fn key -> 33 | "#{input}-#{key}" 34 | |> Day10.compute_knot_hash() 35 | |> to_bits() 36 | end) 37 | end 38 | 39 | defp to_bits(hash) do 40 | hash 41 | |> String.graphemes() 42 | |> Enum.map_join(fn digit -> 43 | digit 44 | |> String.to_integer(16) 45 | |> Integer.to_string(2) 46 | |> String.pad_leading(4, "0") 47 | end) 48 | |> String.graphemes() 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/2020/day_09.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day09 do 2 | @moduledoc """ 3 | --- Day 9: Encoding Error --- 4 | Problem Link: https://adventofcode.com/2020/day/9 5 | """ 6 | alias AdventOfCode.Helpers.{InputReader, Transformers} 7 | 8 | def input, do: InputReader.read_from_file(2020, 9) 9 | 10 | def run(input \\ input()) do 11 | input = Transformers.int_lines(input) 12 | {find_invalid(input), contiguous_list(input)} 13 | end 14 | 15 | defp find_invalid(data) do 16 | {frame, [v | _] = next} = Enum.split(data, 25) 17 | (invalid?(v, MapSet.new(frame)) && v) || find_invalid(tl(frame) ++ next) 18 | end 19 | 20 | def invalid?(value, frame), do: Enum.empty?(Enum.filter(frame, &((value - &1) in frame))) 21 | 22 | defp contiguous_list(data), do: contiguous_list(find_invalid(data), data) 23 | 24 | defp contiguous_list(value, [h | rest]) do 25 | case contiguous_list(List.wrap(h), rest, value) do 26 | :bigger -> contiguous_list(value, rest) 27 | lst -> Enum.max(lst) + Enum.min(lst) 28 | end 29 | end 30 | 31 | def contiguous_list(data, [h | rest], value) do 32 | lst = [h | data] 33 | 34 | case Enum.sum(lst) do 35 | ^value -> lst 36 | n when n > value -> :bigger 37 | _ -> contiguous_list(lst, rest, value) 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/2023/day_06.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day06 do 2 | @moduledoc """ 3 | --- Day 6: Wait For It --- 4 | Problem Link: https://adventofcode.com/2023/day/6 5 | Difficulty: xs 6 | Tags: algebra 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2023, 6) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | {run_1(input), run_2(input)} 15 | end 16 | 17 | defp run_1(input), do: Enum.reduce(input, 1, &(&2 * ways_to_win(&1))) 18 | defp run_2(input), do: input |> join_numbers() |> ways_to_win() 19 | 20 | def parse(data \\ input()) do 21 | data 22 | |> Transformers.lines() 23 | |> Enum.map(&extract/1) 24 | |> then(fn [times, records] -> Enum.zip(times, records) end) 25 | end 26 | 27 | defp extract(data), 28 | do: ~r{\d+} |> Regex.scan(data) |> List.flatten() |> Enum.map(&String.to_integer/1) 29 | 30 | def ways_to_win({time, record}) do 31 | delta = :math.sqrt(time * time - 4 * record) 32 | floor((time + delta) / 2) - ceil((time - delta) / 2) + 1 33 | end 34 | 35 | defp join_numbers(data) do 36 | data 37 | |> Enum.unzip() 38 | |> Tuple.to_list() 39 | |> Enum.map(&(&1 |> Enum.join() |> String.to_integer())) 40 | |> List.to_tuple() 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /priv/input_files/2021_16.txt: -------------------------------------------------------------------------------- 1 | A052E04CFD9DC0249694F0A11EA2044E200E9266766AB004A525F86FFCDF4B25DFC401A20043A11C61838600FC678D51B8C0198910EA1200010B3EEA40246C974EF003331006619C26844200D414859049402D9CDA64BDEF3C4E623331FBCCA3E4DFBBFC79E4004DE96FC3B1EC6DE4298D5A1C8F98E45266745B382040191D0034539682F4E5A0B527FEB018029277C88E0039937D8ACCC6256092004165D36586CC013A008625A2D7394A5B1DE16C0E3004A8035200043220C5B838200EC4B8E315A6CEE6F3C3B9FFB8100994200CC59837108401989D056280803F1EA3C41130047003530004323DC3C860200EC4182F1CA7E452C01744A0A4FF6BBAE6A533BFCD1967A26E20124BE1920A4A6A613315511007A4A32BE9AE6B5CAD19E56BA1430053803341007E24C168A6200D46384318A6AAC8401907003EF2F7D70265EFAE04CCAB3801727C9EC94802AF92F493A8012D9EABB48BA3805D1B65756559231917B93A4B4B46009C91F600481254AF67A845BA56610400414E3090055525E849BE8010397439746400BC255EE5362136F72B4A4A7B721004A510A7370CCB37C2BA0010D3038600BE802937A429BD20C90CCC564EC40144E80213E2B3E2F3D9D6DB0803F2B005A731DC6C524A16B5F1C1D98EE006339009AB401AB0803108A12C2A00043A134228AB2DBDA00801EC061B080180057A88016404DA201206A00638014E0049801EC0309800AC20025B20080C600710058A60070003080006A4F566244012C4B204A83CB234C2244120080E6562446669025CD4802DA9A45F004658527FFEC720906008C996700397319DD7710596674004BE6A161283B09C802B0D00463AC9563C2B969F0E080182972E982F9718200D2E637DB16600341292D6D8A7F496800FD490BCDC68B33976A872E008C5F9DFD566490A14 2 | -------------------------------------------------------------------------------- /lib/2017/day_05.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day05 do 2 | @moduledoc """ 3 | --- Day 5: A Maze of Twisty Trampolines, All Alike --- 4 | Problem Link: https://adventofcode.com/2017/day/5 5 | Difficulty: s 6 | Tags: not-fast-enough random-access 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2017, 5) 11 | 12 | def run(input \\ input()) do 13 | {run_1(input), run_2(input)} 14 | end 15 | 16 | def run_1(input), do: input |> parse() |> then(fn _ -> jump_1(0, 0) end) 17 | def run_2(input), do: input |> parse() |> then(fn _ -> jump_2(0, 0) end) 18 | 19 | def parse(input) do 20 | input 21 | |> Transformers.lines() 22 | |> Enum.with_index() 23 | |> Enum.each(fn {v, k} -> Process.put(k, String.to_integer(v)) end) 24 | end 25 | 26 | def jump_1(x, steps), do: jump_1(Process.get(x), x, steps) 27 | def jump_1(i, _, steps) when is_nil(i), do: steps 28 | def jump_1(i, x, steps), do: Process.put(x, i + 1) |> then(fn _ -> jump_1(x + i, steps + 1) end) 29 | 30 | def jump_2(x, steps), do: jump_2(Process.get(x), x, steps) 31 | def jump_2(i, _, steps) when is_nil(i), do: steps 32 | 33 | def jump_2(i, x, steps), 34 | do: Process.put(x, (i > 2 && i - 1) || i + 1) |> then(fn _ -> jump_2(x + i, steps + 1) end) 35 | end 36 | -------------------------------------------------------------------------------- /lib/2020/day_03.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day03 do 2 | @moduledoc """ 3 | --- Day 3: Toboggan Trajectory --- 4 | Problem Link: https://adventofcode.com/2020/day/3 5 | """ 6 | alias AdventOfCode.Algorithms.Grid 7 | alias AdventOfCode.Helpers.{InputReader, Transformers} 8 | 9 | @default_slope {3, 1} 10 | @slopes [{1, 1}, {3, 1}, {5, 1}, {7, 1}, {1, 2}] 11 | 12 | def input, do: InputReader.read_from_file(2020, 3) 13 | 14 | def run(input \\ input()) do 15 | input = parse(input) 16 | {run_1(input), run_2(input)} 17 | end 18 | 19 | def run_1(input), do: traverse(input) 20 | 21 | def run_2(input) do 22 | for result <- Enum.map(@slopes, &traverse(input, &1)), reduce: 1 do 23 | acc -> 24 | acc * result 25 | end 26 | end 27 | 28 | def parse(input) do 29 | input 30 | |> Transformers.lines() 31 | |> Enum.map(&String.graphemes/1) 32 | |> then(&{Grid.grid2d(&1), length(hd(&1)), length(&1)}) 33 | end 34 | 35 | defp traverse(xy, slope \\ @default_slope), do: traverse(xy, 0, 0, 0, slope) 36 | defp traverse({_, _, cols}, r, _, res, _) when r > cols, do: res 37 | 38 | defp traverse({yx, rows, _} = world, y, x, res, {right, down} = slope) do 39 | traverse(world, y + down, rem(x + right, rows), res + ((yx[{y, x}] == "#" && 1) || 0), slope) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/2022/day_25.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day25 do 2 | @moduledoc """ 3 | --- Day 25: Full of Hot Air --- 4 | Problem Link: https://adventofcode.com/2022/day/25 5 | Difficulty: m 6 | Tags: number-system 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2022, 25) 11 | 12 | def run(input \\ input()) do 13 | { 14 | to_snafu( 15 | for snafu <- Transformers.lines(input), reduce: 0 do 16 | acc -> acc + to_decimal(snafu) 17 | end 18 | ), 19 | "🎉" 20 | } 21 | end 22 | 23 | defp to_decimal(snafu) do 24 | snafu 25 | |> String.graphemes() 26 | |> Enum.reverse() 27 | |> Enum.with_index() 28 | |> Enum.reduce(0, fn 29 | {"-", i}, acc -> -1 * 5 ** i + acc 30 | {"=", i}, acc -> -2 * 5 ** i + acc 31 | {n, i}, acc -> String.to_integer(n) * 5 ** i + acc 32 | end) 33 | end 34 | 35 | defp to_snafu(decimal), do: Enum.map_join(to_snafu(decimal, []), &to_string/1) 36 | 37 | defp to_snafu(0, xs), do: xs 38 | 39 | defp to_snafu(decimal, xs) do 40 | case rem(decimal, 5) do 41 | 3 -> to_snafu(div(decimal + 2, 5), ["=" | xs]) 42 | 4 -> to_snafu(div(decimal + 1, 5), ["-" | xs]) 43 | num -> to_snafu(div(decimal, 5), [num | xs]) 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/2015/day_17.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day17 do 2 | @moduledoc """ 3 | --- Day 17: No Such Thing as Too Much --- 4 | Problem Link: https://adventofcode.com/2015/day/17 5 | Difficulty: s 6 | Tags: slow revisit combinatorics 7 | """ 8 | alias AdventOfCode.Algorithms.Combinatorics 9 | alias AdventOfCode.Helpers.{InputReader, Transformers} 10 | 11 | def input, do: InputReader.read_from_file(2015, 17) 12 | 13 | def run(input \\ input()) do 14 | combinations = 15 | input 16 | |> parse() 17 | |> find_matching_combinations() 18 | 19 | solution_1 = Task.async(fn -> Enum.count(combinations) end) 20 | solution_2 = Task.async(fn -> minimum_bottle_count(Enum.map(combinations, &length/1)) end) 21 | 22 | { 23 | Task.await(solution_1, :infinity), 24 | Task.await(solution_2, :infinity) 25 | } 26 | end 27 | 28 | def parse(data) do 29 | data 30 | |> Transformers.lines() 31 | |> Enum.map(&String.to_integer/1) 32 | end 33 | 34 | defp find_matching_combinations(bottles) do 35 | 1..length(bottles) 36 | |> Stream.flat_map(&Combinatorics.combinations(bottles, &1)) 37 | |> Stream.filter(&(Enum.sum(&1) == 150)) 38 | end 39 | 40 | defp minimum_bottle_count(containers) do 41 | Enum.count(containers, fn container -> container == Enum.min(containers) end) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/2016/day_03.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2016.Day03 do 2 | @moduledoc """ 3 | --- Day 3: Squares With Three Sides --- 4 | Problem Link: https://adventofcode.com/2016/day/3 5 | Difficulty: xs 6 | Tags: geometry2d matrix count 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2016, 3) 11 | 12 | def run(input \\ input()) do 13 | {run_1(input), run_2(input)} 14 | end 15 | 16 | def run_1(input) do 17 | input 18 | |> Transformers.lines() 19 | |> Enum.map(&group/1) 20 | |> count_triangles() 21 | end 22 | 23 | def run_2(input), do: count_triangles(transpose_group(input)) 24 | 25 | def triangle?([a, b, c]), do: a + b > c and b + c > a and c + a > b 26 | def count_triangles(triples), do: Enum.count(triples, &triangle?/1) 27 | 28 | def group(line) do 29 | line 30 | |> String.trim() 31 | |> String.split() 32 | |> Enum.map(&String.to_integer/1) 33 | end 34 | 35 | def transpose_group(input) do 36 | input 37 | |> Transformers.lines() 38 | |> Enum.flat_map(fn d -> String.split(d, ~r{\s}, trim: true) end) 39 | |> Enum.map(&String.to_integer/1) 40 | |> then(fn data -> 41 | [data, tl(data), tl(tl(data))] 42 | |> Enum.flat_map(&(&1 |> Enum.take_every(3) |> Enum.chunk_every(3))) 43 | end) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/2017/day_17.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day17 do 2 | @moduledoc """ 3 | --- Day 17: Spinlock --- 4 | Problem Link: https://adventofcode.com/2017/day/17 5 | Difficulty: m 6 | Tags: vector random-access not-fast-enough 7 | """ 8 | alias Aja.Vector 9 | 10 | def input, do: 394 11 | 12 | def run, do: {run_1(), run_2()} 13 | 14 | @target 2017 15 | defp run_1 do 16 | Vector.new([0]) 17 | |> insert_nth(0, 0) 18 | |> then(fn buffer -> 19 | Vector.at(buffer, Aja.Enum.find_index(buffer, &(&1 == 2017)) + 1) 20 | end) 21 | end 22 | 23 | defp insert_nth(buffer, _, @target), do: buffer 24 | 25 | defp insert_nth(buffer, position, idx) do 26 | idx = idx + 1 27 | position = rem(position + input(), idx) + 1 28 | {left, right} = {Vector.take(buffer, position), Vector.drop(buffer, position)} 29 | buffer = left |> Vector.concat(Vector.new([idx])) |> Vector.concat(right) 30 | 31 | insert_nth(buffer, position, idx) 32 | end 33 | 34 | @target 50_000_000 35 | defp run_2, do: find_idx_1_after(0, 0, 0) 36 | 37 | defp find_idx_1_after(_, @target, first), do: first 38 | 39 | defp find_idx_1_after(position, idx, first) do 40 | idx = idx + 1 41 | position = rem(position + input(), idx) + 1 42 | first = (position == 1 && idx) || first 43 | find_idx_1_after(position, idx, first) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/2021/day_25.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day25 do 2 | @moduledoc """ 3 | --- Day 25: Sea Cucumber --- 4 | Problem Link: https://adventofcode.com/2021/day/25 5 | Difficulty: m 6 | Tags: vector quadratic not-fast-enough grid 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | alias Aja.Vector 10 | 11 | def input, do: InputReader.read_from_file(2021, 25) 12 | def run(input \\ input()), do: {run_1(parse(input), 1), "🎉"} 13 | 14 | def parse(data \\ input()) do 15 | data 16 | |> Transformers.lines() 17 | |> Enum.map(&(&1 |> String.graphemes() |> Vector.new())) 18 | |> then(fn [x | _] = xs -> {Vector.new(xs), {length(xs), Vector.size(x)}} end) 19 | end 20 | 21 | defp run_1({grid, dims}, step) do 22 | new_grid = grid |> move(">", dims) |> move("v", dims) 23 | (new_grid == grid && step) || run_1({new_grid, dims}, step + 1) 24 | end 25 | 26 | defp move(grid, facing, {rows, cols}) do 27 | for i <- 0..(rows - 1), 28 | j <- 0..(cols - 1), 29 | grid[i][j] == facing, 30 | {x, y} = 31 | (case facing do 32 | "v" -> {rem(i + 1, rows), j} 33 | ">" -> {i, rem(j + 1, cols)} 34 | end), 35 | grid[x][y] == ".", 36 | reduce: grid do 37 | acc -> acc |> put_in([i, j], ".") |> put_in([x, y], facing) 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/helpers/input_parser.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Helpers.InputParser do 2 | @moduledoc """ 3 | Parses and validates input given in command line 4 | """ 5 | 6 | @years 2015..AdventOfCode.get_latest_year() 7 | @days 1..25 8 | 9 | @doc """ 10 | Parses the input from option parser and returns the year and day. 11 | 12 | ## EXAMPLE 13 | iex> import AdventOfCode.Helpers.InputParser, only: [parse: 1] 14 | iex> parse(["2019", "2"]) 15 | {2019, 2} 16 | iex> parse(["2", "2019"]) 17 | nil 18 | iex> parse(["--year", "2019", "--day", "2"]) 19 | {2019, 2} 20 | iex> parse(["--year", "2", "--day", "2019"]) 21 | nil 22 | iex> parse(["2014", "20"]) 23 | nil 24 | iex> parse(["2019", "31"]) 25 | nil 26 | """ 27 | def parse(args) do 28 | case OptionParser.parse(args, strict: [year: :integer, day: :integer]) do 29 | {[], opts, _} -> opts |> Enum.map(&String.to_integer/1) |> List.to_tuple() |> validated() 30 | {opts, [], _} -> opts |> Enum.into(%{}) |> validated() 31 | _ -> nil 32 | end 33 | end 34 | 35 | defp validated(%{year: year, day: day}), do: (validate({year, day}) && {year, day}) || nil 36 | defp validated(v), do: (validate(v) && v) || nil 37 | 38 | defp validate({year, day}), do: [year in @years, day in @days] |> Enum.all?() 39 | defp validate(_), do: false 40 | end 41 | -------------------------------------------------------------------------------- /lib/2020/day_02.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day02 do 2 | @moduledoc """ 3 | --- Day 2: Password Philosophy --- 4 | Problem Link: https://adventofcode.com/2020/day/2 5 | """ 6 | alias AdventOfCode.Helpers.{InputReader, Transformers} 7 | 8 | def input, do: InputReader.read_from_file(2020, 2) 9 | 10 | def run(input \\ input()) do 11 | input = parse(input) 12 | 13 | {solve(input), solve_corrected(input)} 14 | end 15 | 16 | def parse(input) do 17 | input 18 | |> Transformers.lines() 19 | |> Enum.map(&parse_line/1) 20 | end 21 | 22 | @pattern ~r/(\d+)-(\d+) (\S): (\S+)$/ 23 | defp parse_line(line) do 24 | [_, lo, hi, char, pass] = Regex.run(@pattern, line) 25 | 26 | {String.to_integer(lo), String.to_integer(hi), char, pass} 27 | end 28 | 29 | defp solve(lines), do: Enum.count(lines, &valid?/1) 30 | defp solve_corrected(lines), do: Enum.count(lines, &valid_position?/1) 31 | 32 | defp valid?({lo, hi, char, pass}) do 33 | pass 34 | |> String.graphemes() 35 | |> Enum.frequencies() 36 | |> Map.get(char) 37 | |> then(fn freq -> freq >= lo and freq <= hi end) 38 | end 39 | 40 | defp valid_position?({lo, hi, char, pass}) do 41 | case {String.at(pass, lo - 1), String.at(pass, hi - 1)} do 42 | {a, a} -> false 43 | {a, b} when a == char or b == char -> true 44 | _ -> false 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/2015/day_25.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day25 do 2 | @moduledoc """ 3 | --- Day 25: Let It Snow --- 4 | Problem Link: https://adventofcode.com/2015/day/25 5 | Difficulty: m 6 | Tags: table-lookup modular-arithmetic 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2015, 25) 11 | 12 | def run(input \\ input()) do 13 | solution = 14 | input 15 | |> parse() 16 | |> index_of() 17 | |> nth_code() 18 | 19 | {solution, "🎉"} 20 | end 21 | 22 | def index_of({row, 1}) do 23 | 1..row 24 | |> Enum.reduce(%{0 => 1}, fn row, codes -> 25 | Map.merge(codes, %{row => Map.get(codes, row - 1) + (row - 1)}) 26 | end) 27 | |> Map.get(row) 28 | end 29 | 30 | def index_of({row, col}) do 31 | 2..col 32 | |> Enum.reduce(%{1 => index_of({row, 1})}, fn col, codes -> 33 | Map.merge(codes, %{col => Map.get(codes, col - 1) + row + (col - 1)}) 34 | end) 35 | |> Map.get(col) 36 | end 37 | 38 | def nth_code(1), do: 20_151_125 39 | 40 | def nth_code(n) do 41 | Enum.reduce(2..n, nth_code(1), fn _, code -> 42 | rem(code * 252_533, 33_554_393) 43 | end) 44 | end 45 | 46 | def parse(data) do 47 | ~r/\D+(\d+)\D+(\d+)/ 48 | |> Regex.run(data, capture: :all_but_first) 49 | |> Enum.map(&String.to_integer/1) 50 | |> List.to_tuple() 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/advent_of_code.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode do 2 | @moduledoc """ 3 | Module that solves problem given year and day. 4 | """ 5 | @latest_year 2024 6 | 7 | @type year() :: 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 8 | @type day() :: pos_integer() 9 | 10 | @doc """ 11 | Returns the latest year solved. 12 | """ 13 | def get_latest_year, do: @latest_year 14 | 15 | @doc """ 16 | Solves for `year` and `day`. 17 | """ 18 | @spec solve(year(), day()) :: {any(), any()} 19 | def solve(year, day, rust? \\ false) do 20 | solution = 21 | :timer.tc(fn -> 22 | case rust? do 23 | true -> 24 | {_, result} = AdventOfCode.RustNif.solve(year, day) 25 | result 26 | 27 | false -> 28 | Module.concat([AdventOfCode, get_year_module(year), get_day_module(day)]).run() 29 | end 30 | end) 31 | 32 | {:ok, solution} 33 | rescue 34 | _ in FunctionClauseError -> {:error, :invalid_args} 35 | _ in UndefinedFunctionError -> {:error, :not_yet_solved} 36 | end 37 | 38 | defp get_year_module(year) when year >= 2015 and year <= @latest_year do 39 | "Y" <> Integer.to_string(year) 40 | end 41 | 42 | defp get_day_module(day) when day >= 1 and day <= 25 do 43 | day 44 | |> Integer.to_string() 45 | |> String.pad_leading(2, "0") 46 | |> then(fn day -> "Day" <> day end) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /native/aoc/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | FULL_YEAR=$1 4 | YEAR=${1:(-2)} 5 | DAY=$(printf '%02d' $2) 6 | SRC_FILE=./src/year_${FULL_YEAR}/day_${YEAR}_${DAY}.rs 7 | 8 | if [[ ! -e $SRC_FILE ]]; then 9 | touch "$SRC_FILE" 10 | cat << EOF > "$SRC_FILE" 11 | pub fn solve_${YEAR}_${DAY}(raw_input: String) -> (i32, i32) { 12 | let input = process(&raw_input); 13 | (part_1(&input), part_2(&input)) 14 | } 15 | 16 | fn process(raw_input: &str) -> Vec<&str> { 17 | raw_input 18 | .trim() 19 | .split('\n') 20 | .collect() 21 | } 22 | 23 | fn part_1(input: &[&str]) -> i32 { 24 | input.len() as i32 25 | } 26 | 27 | fn part_2(input: &[&str]) -> i32 { 28 | input.len() as i32 29 | } 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use crate::util::io_helpers::read_input_from_resources; 34 | use super::*; 35 | 36 | const YEAR: i16 = $1; 37 | const DAY: i8 = $2; 38 | 39 | #[test] 40 | fn test_process() { 41 | let given = "hello\nthere"; 42 | let expected = vec!["hello", "there"]; 43 | 44 | assert_eq!(process(given), expected); 45 | } 46 | 47 | #[test] 48 | fn test_solution() { 49 | let given = read_input_from_resources(YEAR, DAY, false); 50 | let expected = (3, 3); 51 | 52 | assert_eq!(solve_${YEAR}_${DAY}(given), expected); 53 | } 54 | } 55 | EOF 56 | else 57 | echo "Source ${SRC_FILE} already exists" 58 | fi 59 | -------------------------------------------------------------------------------- /lib/2017/day_08.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day08 do 2 | @moduledoc """ 3 | --- Day 8: I Heard You Like Registers --- 4 | Problem Link: https://adventofcode.com/2017/day/8 5 | Difficulty: s 6 | Tags: op-code 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2017, 8) 11 | 12 | def run(input \\ input()) do 13 | input 14 | |> parse() 15 | |> Enum.reduce( 16 | {%{}, 0}, 17 | fn {reg, dep, updater, predicate}, {acc, highest} -> 18 | case predicate.(Map.get(acc, dep, 0)) do 19 | true -> 20 | value = updater.(Map.get(acc, reg, 0)) 21 | {Map.put(acc, reg, value), max(value, highest)} 22 | 23 | _ -> 24 | {acc, highest} 25 | end 26 | end 27 | ) 28 | |> then(fn {registers, highest} -> 29 | {Enum.max(Map.values(registers)), highest} 30 | end) 31 | end 32 | 33 | @upd %{"inc" => :+, "dec" => :-} 34 | def parse(data \\ input()) do 35 | data 36 | |> Transformers.lines() 37 | |> Enum.map(fn line -> 38 | [reg, upd, by, "if", dep, comp, val] = Transformers.words(line) 39 | 40 | { 41 | reg, 42 | dep, 43 | &apply(Kernel, @upd[upd], [&1, String.to_integer(by)]), 44 | &apply(Kernel, String.to_existing_atom(comp), [&1, String.to_integer(val)]) 45 | } 46 | end) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/2020/day_10.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day10 do 2 | @moduledoc """ 3 | --- Day 10: Adapter Array --- 4 | Problem Link: https://adventofcode.com/2020/day/10 5 | """ 6 | alias AdventOfCode.Helpers.{InputReader, Transformers} 7 | 8 | def input, do: InputReader.read_from_file(2020, 10) 9 | 10 | def run(input \\ input()) do 11 | input = Enum.sort([0 | Transformers.int_lines(input)], :desc) 12 | {multiply_1_3(rates(input)), count(input)} 13 | end 14 | 15 | defp rates(data) do 16 | my_rate = Enum.max(data) + 3 17 | data = MapSet.new(data) 18 | 19 | Stream.unfold(0, fn 20 | n when n > my_rate -> 21 | nil 22 | 23 | n -> 24 | range = MapSet.new((n + 1)..(n + 3)) 25 | jolt = MapSet.intersection(data, range) |> Enum.to_list() 26 | if Enum.empty?(jolt), do: diffs(my_rate, n), else: diffs(Enum.min(jolt), n) 27 | end) 28 | end 29 | 30 | defp diffs(a, b) when a - b == 1, do: {{a, 1, 0}, a} 31 | defp diffs(a, b) when a - b == 3, do: {{a, 0, 1}, a} 32 | defp diffs(_, _), do: nil 33 | 34 | defp multiply_1_3(r), 35 | do: apply(&Kernel.*/2, Enum.reduce(r, [0, 0], fn {_, a, b}, [x, y] -> [x + a, y + b] end)) 36 | 37 | defp count(data), do: count(data, %{(hd(data) + 3) => 1}) 38 | defp count([], cache), do: cache[0] 39 | 40 | defp count([h | rst], m), 41 | do: count(rst, Map.put(m, h, Enum.sum(Enum.map(1..3, &Map.get(m, h + &1, 0))))) 42 | end 43 | -------------------------------------------------------------------------------- /lib/2017/day_06.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day06 do 2 | @moduledoc """ 3 | --- Day 6: Memory Reallocation --- 4 | Problem Link: https://adventofcode.com/2017/day/6 5 | Difficulty: m 6 | Tags: sequence reduction 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2017, 6) 11 | 12 | def run(input \\ input()) do 13 | blocks = parse(input) 14 | {visited, blocks} = distribute_largest(blocks, MapSet.new([])) 15 | {second_visit, _} = distribute_largest(blocks, MapSet.new([])) 16 | 17 | {Enum.count(visited) + 1, Enum.count(second_visit)} 18 | end 19 | 20 | def distribute_largest(blocks, visited) do 21 | blocks = do_distribute_largest(blocks) 22 | 23 | case MapSet.member?(visited, blocks) do 24 | true -> {visited, blocks} 25 | _ -> distribute_largest(blocks, MapSet.put(visited, blocks)) 26 | end 27 | end 28 | 29 | def do_distribute_largest(blocks) do 30 | {idx, value} = Enum.max_by(blocks, fn {_, v} -> v end) 31 | 32 | Enum.reduce(0..(value - 1), Map.put(blocks, idx, 0), fn i, acc -> 33 | Map.update(acc, rem(idx + i + 1, Enum.count(blocks)), nil, &(&1 + 1)) 34 | end) 35 | end 36 | 37 | def parse(data \\ input()) do 38 | data 39 | |> Transformers.words("\t") 40 | |> Enum.map(&String.to_integer/1) 41 | |> Enum.with_index() 42 | |> Map.new(fn {v, k} -> {k, v} end) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/2020/day_07.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day07 do 2 | @moduledoc """ 3 | --- Day 7: Handy Haversacks --- 4 | Problem Link: https://adventofcode.com/2020/day/7 5 | """ 6 | alias AdventOfCode.Helpers.{InputReader, Transformers} 7 | 8 | def input, do: InputReader.read_from_file(2020, 7) 9 | 10 | def run(input \\ input()) do 11 | input = Map.new(Transformers.lines(input), &parse_rule/1) 12 | {ancestor(graph(input)), descendant(input) - 1} 13 | end 14 | 15 | def parse_rule(rule) do 16 | line = Regex.named_captures(~r/(?.+) bags contain (?.+)\./, rule) 17 | 18 | {line["src"], 19 | Regex.split(~r/bags?,?/, line["bags"], trim: true) 20 | |> Enum.map(fn s -> 21 | match = Regex.named_captures(~r/(?no|\d+) (?.+)/, String.trim(s)) 22 | {(match["n"] == "no" && 0) || String.to_integer(match["n"]), match["bag"]} 23 | end)} 24 | end 25 | 26 | defp graph(v), do: Enum.reduce(v, :digraph.new(), &connect(&2, &1)) 27 | 28 | defp connect(g, {vi, connections}) do 29 | Enum.each(connections, fn {n, vf} -> 30 | :digraph.add_edge(g, :digraph.add_vertex(g, vi), :digraph.add_vertex(g, vf), n) 31 | end) 32 | 33 | g 34 | end 35 | 36 | defp ancestor(g, v \\ "shiny gold"), do: length(:digraph_utils.reaching([v], g)) - 1 37 | 38 | defp descendant(g, v \\ "shiny gold"), 39 | do: Enum.reduce(g[v] || [], 1, fn {n, v}, num -> num + n * descendant(g, v) end) 40 | end 41 | -------------------------------------------------------------------------------- /lib/2020/day_24.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day24 do 2 | @moduledoc """ 3 | --- Day 24: Lobby Layout --- 4 | Problem Link: https://adventofcode.com/2020/day/24 5 | """ 6 | alias AdventOfCode.Helpers.{InputReader, Transformers} 7 | 8 | require Integer 9 | 10 | def input, do: InputReader.read_from_file(2020, 24) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | {run_1(input), {:todo, 2}} 15 | end 16 | 17 | def run_1(input) do 18 | input 19 | |> flip() 20 | |> black_tiles() 21 | |> length() 22 | end 23 | 24 | @directions ~r/e|w|se|sw|ne|nw/ 25 | def parse(input) do 26 | for line <- Transformers.lines(input) do 27 | @directions 28 | |> Regex.scan(line, capture: :first) 29 | |> List.flatten() 30 | end 31 | end 32 | 33 | defp walk("w", {x, y}), do: {x - 1, y} 34 | defp walk("e", {x, y}), do: {x + 1, y} 35 | defp walk("nw", {x, y}), do: {(Integer.is_even(y) && x) || x - 1, y - 1} 36 | defp walk("ne", {x, y}), do: {(Integer.is_even(y) && x + 1) || x, y - 1} 37 | defp walk("sw", {x, y}), do: {(Integer.is_even(y) && x) || x - 1, y + 1} 38 | defp walk("se", {x, y}), do: {(Integer.is_even(y) && x + 1) || x, y + 1} 39 | 40 | defp flip(tiles), do: Enum.map(tiles, fn sides -> Enum.reduce(sides, {0, 0}, &walk/2) end) 41 | 42 | defp black_tiles(tiles) do 43 | for {_, tile} <- Enum.frequencies(tiles), rem(tile, 2) == 1, do: tile 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /native/aoc/src/year_2019/day_19_01.rs: -------------------------------------------------------------------------------- 1 | use crate::util::parsers::read_line_ints; 2 | 3 | pub fn solve_19_01(raw_input: String) -> (i32, i32) { 4 | let input = process(raw_input); 5 | (part_1(&input), part_2(&input)) 6 | } 7 | 8 | fn process(raw_input: String) -> Vec { 9 | read_line_ints(&raw_input) 10 | } 11 | 12 | fn part_1(input: &[i32]) -> i32 { 13 | input.iter().map(|mass| get_fuel_1(*mass)).sum() 14 | } 15 | 16 | fn part_2(input: &[i32]) -> i32 { 17 | input.iter().map(|mass| get_fuel_2(*mass)).sum() 18 | } 19 | 20 | fn get_fuel_1(mass: i32) -> i32 { 21 | match (mass / 3) - 2 { 22 | i if i <= 0 => 0, 23 | fuel => fuel, 24 | } 25 | } 26 | 27 | fn get_fuel_2(mass: i32) -> i32 { 28 | let mut total_fuel = 0; 29 | let mut computed_mass = mass; 30 | 31 | loop { 32 | let fuel = get_fuel_1(computed_mass); 33 | total_fuel += fuel; 34 | if fuel == 0 { 35 | return total_fuel; 36 | } 37 | computed_mass = fuel; 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::*; 44 | use crate::util::io_helpers::read_input_from_resources; 45 | 46 | #[test] 47 | fn test_result_19_01() { 48 | let (year, day) = (2019, 1); 49 | let expected_result = (3421505, 5129386); 50 | 51 | let raw_input = read_input_from_resources(year, day, false); 52 | assert_eq!(solve_19_01(raw_input), expected_result); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/2021/day_05.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2021.Day05 do 2 | @moduledoc """ 3 | --- Day 5: Hydrothermal Venture --- 4 | Problem Link: https://adventofcode.com/2021/day/5 5 | Difficulty: xs 6 | Tags: set 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2021, 5) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | {overlaps(input, false), overlaps(input, true)} 15 | end 16 | 17 | def parse(data), do: Enum.map(Transformers.lines(data), &ranges/1) 18 | 19 | defp ranges(line) do 20 | ~r/(\d+),(\d+) -> (\d+),(\d+)/ 21 | |> Regex.run(line, capture: :all_but_first) 22 | |> Enum.map(&String.to_integer/1) 23 | |> Enum.split(2) 24 | end 25 | 26 | defp overlaps(ranges, diagonal?) do 27 | ranges 28 | |> Enum.flat_map(&points_between(&1, diagonal?)) 29 | |> Enum.frequencies() 30 | |> Enum.count(&(elem(&1, 1) >= 2)) 31 | end 32 | 33 | defp points_between({from, to}, diagonal?) do 34 | case {{from, to}, diagonal?} do 35 | {{[same, a], [same, b]}, _} -> Enum.map(a..b, &{same, &1}) 36 | {{[a, same], [b, same]}, _} -> Enum.map(a..b, &{&1, same}) 37 | {range, true} -> diagonals(range) 38 | _ -> [] 39 | end 40 | end 41 | 42 | defp diagonals({[a, b], [c, d]}) do 43 | Enum.map( 44 | 0..abs(a - c), 45 | &{(a > c && a - &1) || a + &1, (b > d && b - &1) || b + &1} 46 | ) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/2024/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Advent of Code 2024 3 | 4 | [Main Page](https://adventofcode.com/2024) | [Tests](/test/2024) 5 | 6 | [2015](/lib/2015) | [2016](/lib/2016) | [2017](/lib/2017) | [2018](/lib/2018) | [2019](/lib/2019) | [2020](/lib/2020) | [2021](/lib/2021) | [2022](/lib/2022) | [2023](/lib/2023) | 2024 7 | 8 | 9 | ## :trophy: 7/50 10 | 11 | | Day | Problem Page | Status | Difficulty | Solution Page | Test Page | Tags | 12 | | :---: | :------: | :---: | :---: | :---: | :---: | :---: | 13 | | 1 | [Historian Hysteria](https://adventofcode.com/2024/day/1) | :1st_place_medal: | :snowflake: | [day_01.ex](/lib/2024/day_01.ex) | [day_01_test.exs](/test/2024/day_01_test.exs) | [list](/wiki/tags.md#list) | 14 | | 3 | [Mull It Over](https://adventofcode.com/2024/day/3) | :1st_place_medal: | :snowflake: | [day_03.ex](/lib/2024/day_03.ex) | [day_03_test.exs](/test/2024/day_03_test.exs) | [regex](/wiki/tags.md#regex), [fsm](/wiki/tags.md#fsm) | 15 | | 5 | [Print Queue](https://adventofcode.com/2024/day/5) | :1st_place_medal: | :snowflake: | [day_05.ex](/lib/2024/day_05.ex) | [day_05_test.exs](/test/2024/day_05_test.exs) | [set](/wiki/tags.md#set), [sort](/wiki/tags.md#sort) | 16 | | 12 | [Garden Groups](https://adventofcode.com/2024/day/12) | :2nd_place_medal: | :snowflake: :snowflake: :snowflake: | [day_12.ex](/lib/2024/day_12.ex) | [day_12_test.exs](/test/2024/day_12_test.exs) | [geometry](/wiki/tags.md#geometry), [disjoint-set](/wiki/tags.md#disjoint-set) | 17 | 18 | -------------------------------------------------------------------------------- /test/2018/day_02_test.exs: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2018.Day02Test do 2 | @moduledoc false 3 | use ExUnit.Case, async: true 4 | @moduletag :y1802 5 | 6 | alias AdventOfCode.Y2018.Day02, as: Solution 7 | 8 | test "Letter Count" do 9 | assert Solution.letter_count("aabcacacdd") == %{"a" => 4, "b" => 1, "c" => 3, "d" => 2} 10 | assert Solution.letter_count("") == %{} 11 | assert Solution.letter_count("123") == %{"1" => 1, "2" => 1, "3" => 1} 12 | end 13 | 14 | test "Two or Threes" do 15 | assert Solution.two_or_three_count(%{"c" => 3, "d" => 2}) == {1, 1} 16 | assert Solution.two_or_three_count(%{"b" => 1, "d" => 2}) == {1, 0} 17 | assert Solution.two_or_three_count(%{"b" => 4, "d" => 3}) == {0, 1} 18 | assert Solution.two_or_three_count(%{"b" => 0, "d" => 0}) == {0, 0} 19 | assert Solution.two_or_three_count(%{}) == {0, 0} 20 | end 21 | 22 | test "Checksum 1" do 23 | data = [{1, 1}, {0, 0}, {0, 1}, {1, 1}] 24 | 25 | assert Solution.checksum(data) == 6 26 | assert Solution.checksum([{0, 0}]) == 0 27 | end 28 | 29 | test "Remove at" do 30 | assert Solution.remove_at("abc", 0) == "?bc" 31 | assert Solution.remove_at("abc", 1) == "a?c" 32 | assert Solution.remove_at("abc", 2) == "ab?" 33 | end 34 | 35 | test "Remove one char" do 36 | assert Solution.words_without_a_char("abc") == ["?bc", "a?c", "ab?"] 37 | end 38 | 39 | test "Year 2018, Day 2" do 40 | assert Solution.run() == {7221, "mkcdflathzwsvjxrevymbdpoq"} 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /priv/input_files/2022_11.txt: -------------------------------------------------------------------------------- 1 | Monkey 0: 2 | Starting items: 93, 98 3 | Operation: new = old * 17 4 | Test: divisible by 19 5 | If true: throw to monkey 5 6 | If false: throw to monkey 3 7 | 8 | Monkey 1: 9 | Starting items: 95, 72, 98, 82, 86 10 | Operation: new = old + 5 11 | Test: divisible by 13 12 | If true: throw to monkey 7 13 | If false: throw to monkey 6 14 | 15 | Monkey 2: 16 | Starting items: 85, 62, 82, 86, 70, 65, 83, 76 17 | Operation: new = old + 8 18 | Test: divisible by 5 19 | If true: throw to monkey 3 20 | If false: throw to monkey 0 21 | 22 | Monkey 3: 23 | Starting items: 86, 70, 71, 56 24 | Operation: new = old + 1 25 | Test: divisible by 7 26 | If true: throw to monkey 4 27 | If false: throw to monkey 5 28 | 29 | Monkey 4: 30 | Starting items: 77, 71, 86, 52, 81, 67 31 | Operation: new = old + 4 32 | Test: divisible by 17 33 | If true: throw to monkey 1 34 | If false: throw to monkey 6 35 | 36 | Monkey 5: 37 | Starting items: 89, 87, 60, 78, 54, 77, 98 38 | Operation: new = old * 7 39 | Test: divisible by 2 40 | If true: throw to monkey 1 41 | If false: throw to monkey 4 42 | 43 | Monkey 6: 44 | Starting items: 69, 65, 63 45 | Operation: new = old + 6 46 | Test: divisible by 3 47 | If true: throw to monkey 7 48 | If false: throw to monkey 2 49 | 50 | Monkey 7: 51 | Starting items: 89 52 | Operation: new = old * old 53 | Test: divisible by 11 54 | If true: throw to monkey 0 55 | If false: throw to monkey 2 56 | -------------------------------------------------------------------------------- /lib/2017/day_03.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day03 do 2 | @moduledoc """ 3 | --- Day 3: Spiral Memory --- 4 | Problem Link: https://adventofcode.com/2017/day/3 5 | Difficulty: m 6 | Tags: spiral matrix 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2017, 3) 11 | 12 | def run(input \\ input()) do 13 | input = List.first(Transformers.int_lines(input)) 14 | {run_1(input), run_2(input)} 15 | end 16 | 17 | defp run_1(input) do 18 | {x, y} = position(input) 19 | round(abs(x) + abs(y)) 20 | end 21 | 22 | defp run_2(input), do: allocations(input, 2, %{{0, 0} => 1}, 1) 23 | 24 | def position(idx) do 25 | r = div(1 + trunc(:math.sqrt(idx - 1)), 2) 26 | d = 2 * r - 1 27 | i = idx - d ** 2 - 1 28 | 29 | case {i < d, i < 2 * d + 2, i < 3 * d + 2} do 30 | {true, _, _} -> {r, i - r + 1} 31 | {_, true, _} -> {r - i + d, r} 32 | {_, _, true} -> {-r, r - i - 1 + 2 * d + 2} 33 | _ -> {i - r - 3 * d - 2, -r} 34 | end 35 | end 36 | 37 | defp allocations(idx, _i, _cache, result) when result > idx, do: result 38 | 39 | defp allocations(idx, i, cache, _result) do 40 | {x, y} = position(i) 41 | 42 | result = 43 | Enum.sum( 44 | Enum.map( 45 | -3..5, 46 | &Map.get(cache, {x + Integer.mod(&1, 3) - 1, y + Integer.floor_div(&1, 3)}, 0) 47 | ) 48 | ) 49 | 50 | allocations(idx, i + 1, Map.put(cache, {x, y}, result), result) 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/2017/day_07.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day07 do 2 | @moduledoc """ 3 | --- Day 7: Recursive Circus --- 4 | Problem Link: https://adventofcode.com/2017/day/7 5 | Difficulty: m 6 | Tags: tree 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | def input, do: InputReader.read_from_file(2017, 7) 10 | 11 | def run(input \\ input()) do 12 | input = parse(input) 13 | 14 | {run_1(input), run_2(input)} 15 | end 16 | 17 | defp run_1(input) do 18 | input 19 | |> Enum.map(fn %{name: name} -> name end) 20 | |> MapSet.new() 21 | |> MapSet.difference(get_branches(input)) 22 | |> MapSet.to_list() 23 | |> hd() 24 | end 25 | 26 | defp run_2(_input) do 27 | {:todo, 2} 28 | end 29 | 30 | @regex ~r/(?[a-z]+) \((?\d+)\)( -> (?(\s*[a-z]+\,?)+))?/ 31 | def parse(data \\ input()) do 32 | data 33 | |> Transformers.lines() 34 | |> Enum.map(fn line -> 35 | Regex.named_captures(@regex, line) 36 | end) 37 | |> Enum.map(fn %{"branches" => branches, "weight" => weight, "name" => name} -> 38 | %{ 39 | branches: (String.trim(branches) != "" && String.split(branches, ", ")) || nil, 40 | name: name, 41 | weight: String.to_integer(weight) 42 | } 43 | end) 44 | end 45 | 46 | defp get_branches(parsed_data) do 47 | parsed_data 48 | |> Enum.flat_map(fn 49 | %{branches: nil} -> [] 50 | %{branches: branches} -> branches 51 | end) 52 | |> MapSet.new() 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/algorithms/geometry.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.Geometry do 2 | @moduledoc """ 3 | Geometry related functions that mostly have to do with geometric computations and measurements. 4 | """ 5 | @type point2d :: {integer(), integer()} 6 | 7 | @doc """ 8 | Following the shoelace formula, computes the area of polygon. 9 | 10 | ## Examples 11 | 12 | iex> points = [{0, 1}, {2, 3}, {4, 7}, {0, 1}] 13 | iex> Geometry.polygon_area(points) 14 | 2.0 15 | 16 | iex> points = [{0, 0}, {4, 0}, {4, 4}, {0, 4}, {0, 0}] 17 | iex> Geometry.polygon_area(points) 18 | 16.0 19 | 20 | iex> points = [{0, 0}, {4, 0}, {2, 4}, {0, 0}] 21 | iex> Geometry.polygon_area(points) 22 | 8.0 23 | 24 | """ 25 | @spec polygon_area(list(point2d())) :: number() 26 | def polygon_area([first | points]) do 27 | points 28 | |> Enum.reduce({first, 0.0}, fn {x, y} = p, {{xi, yi}, area} -> 29 | {p, area + (x - xi) * (y + yi)} 30 | end) 31 | |> then(fn {_, area} -> abs(area / 2) end) 32 | end 33 | 34 | @doc """ 35 | Computes manhattan distance between two points 36 | 37 | ## Example 38 | 39 | iex> Geometry.manhattan_distance({0, 0}, {10, 20}) 40 | 30 41 | 42 | iex> Geometry.manhattan_distance({100, 50}, {10, 10}) 43 | 130 44 | 45 | iex> Geometry.manhattan_distance({15, 17}, {16, 19}) 46 | 3 47 | """ 48 | @spec manhattan_distance(point2d, point2d) :: integer() 49 | def manhattan_distance({x1, y1}, {x2, y2}), do: abs(x2 - x1) + abs(y2 - y1) 50 | end 51 | -------------------------------------------------------------------------------- /native/aoc/src/year_2017/day_17_02.rs: -------------------------------------------------------------------------------- 1 | use itertools::Itertools; 2 | 3 | pub fn solve_17_02(raw_input: String) -> (i32, i32) { 4 | let input = process(&raw_input); 5 | (part_1(&input), part_2(&input)) 6 | } 7 | 8 | fn process(input_data: &str) -> Vec> { 9 | input_data.trim().split('\n').map(parse_row).collect() 10 | } 11 | 12 | fn parse_row(line: &str) -> Vec { 13 | line.split('\t') 14 | .map(|cell| cell.parse::().unwrap()) 15 | .sorted() 16 | .collect() 17 | } 18 | 19 | fn part_1(input_data: &[Vec]) -> i32 { 20 | input_data 21 | .iter() 22 | .map(|row| row.last().unwrap() - row.first().unwrap()) 23 | .sum() 24 | } 25 | 26 | fn part_2(input_data: &[Vec]) -> i32 { 27 | input_data 28 | .iter() 29 | .map(|values| { 30 | for i in 0..values.len() { 31 | for j in i + 1..values.len() { 32 | if values[j] % values[i] == 0 { 33 | return values[j] / values[i]; 34 | } 35 | } 36 | } 37 | unreachable!() 38 | }) 39 | .sum() 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::*; 45 | use crate::util::io_helpers::read_input_from_resources; 46 | 47 | #[test] 48 | fn test_result_17_02() { 49 | let raw_input = read_input_from_resources(2017, 2, false); 50 | let expected_result = (32020, 236); 51 | 52 | assert_eq!(solve_17_02(raw_input), expected_result); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/2019/day_02.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day02 do 2 | @moduledoc """ 3 | --- Day 2: 1202 Program Alarm --- 4 | Problem Link: https://adventofcode.com/2019/day/2 5 | Difficulty: xs 6 | Tags: op-code not-fast-enough int-code 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | alias AdventOfCode.Y2019.IntCode 10 | 11 | def input, do: InputReader.read_from_file(2019, 2) 12 | 13 | @range 99..0//-1 14 | 15 | def run(input \\ input()), do: {run_1(input), run_2(input)} 16 | 17 | def run_1(input) do 18 | {:ok, pid} = 19 | input 20 | |> parse() 21 | |> fix1202() 22 | |> IntCode.start_link() 23 | 24 | IntCode.run(pid) 25 | IntCode.get_output(pid) 26 | end 27 | 28 | def run_2(input) do 29 | memory = input |> parse() 30 | 31 | pairs = for i <- @range, j <- @range, do: {i, j} 32 | 33 | {:ok, pid} = IntCode.start_link(memory) 34 | 35 | Enum.reduce_while(pairs, nil, fn {noun, verb}, _ -> 36 | new_memory = fix1202(memory, noun, verb) 37 | IntCode.reset(pid, new_memory) 38 | IntCode.run(pid) 39 | 40 | case IntCode.get_output(pid) do 41 | 19_690_720 -> {:halt, 100 * noun + verb} 42 | _ -> {:cont, nil} 43 | end 44 | end) 45 | end 46 | 47 | def parse(data) do 48 | data 49 | |> String.trim() 50 | |> String.split(",") 51 | |> Enum.map(&String.to_integer/1) 52 | end 53 | 54 | defp fix1202(memory, one \\ 12, two \\ 2) do 55 | memory 56 | |> List.replace_at(1, one) 57 | |> List.replace_at(2, two) 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/2023/day_09.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2023.Day09 do 2 | @moduledoc """ 3 | --- Day 9: Mirage Maintenance --- 4 | Problem Link: https://adventofcode.com/2023/day/9 5 | Difficulty: xs 6 | Tags: sequence reduction 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2023, 9) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | 15 | {extrapolate_by(input, &forward/1), extrapolate_by(input, &backward/1)} 16 | end 17 | 18 | def extrapolate_by(histories, direction_fn), 19 | do: Enum.reduce(histories, 0, fn x, acc -> acc + direction_fn.(x) end) 20 | 21 | def parse(data \\ input()) do 22 | for line <- Transformers.lines(data), do: Transformers.int_words(line) 23 | end 24 | 25 | defp forward(data) do 26 | extrapolate(data, [data], fn acc -> 27 | Enum.sum_by(acc, &List.last/1) 28 | end) 29 | end 30 | 31 | defp backward(data) do 32 | extrapolate(data, [data], fn acc -> 33 | acc 34 | |> Enum.map(&hd/1) 35 | |> Enum.reduce(fn x, acc -> 36 | x - acc 37 | end) 38 | end) 39 | end 40 | 41 | defp extrapolate(histories, acc, direction_fn) do 42 | case MapSet.size(MapSet.new(histories)) do 43 | 1 -> 44 | direction_fn.(acc) 45 | 46 | _ -> 47 | histories 48 | |> Enum.chunk_every(2, 1, :discard) 49 | |> Enum.map(fn [a, b] -> b - a end) 50 | |> then(fn record -> extrapolate(record, [record | acc], direction_fn) end) 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/2020/day_13.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2020.Day13 do 2 | @moduledoc """ 3 | --- Day 13: Shuttle Search --- 4 | Problem Link: https://adventofcode.com/2020/day/13 5 | """ 6 | alias AdventOfCode.Algorithms.ChineseRemainder 7 | alias AdventOfCode.Helpers.{InputReader, Transformers} 8 | 9 | def input, do: InputReader.read_from_file(2020, 13) 10 | 11 | @spec run(binary()) :: {any(), false | nil | integer()} 12 | def run(input \\ input()) do 13 | {run_1(input), run_2(input)} 14 | end 15 | 16 | def run_1(input), do: input |> parse_1() |> earliest_bus() |> elem(3) 17 | def run_2(input), do: input |> parse_2() |> ChineseRemainder.compute() 18 | 19 | def parse_1(input) do 20 | [time, ids] = Transformers.lines(input) 21 | 22 | {String.to_integer(time), 23 | ids 24 | |> String.split(",") 25 | |> Enum.reject(&(&1 == "x")) 26 | |> Enum.map(&String.to_integer/1)} 27 | end 28 | 29 | def parse_2(input) do 30 | input 31 | |> Transformers.lines() 32 | |> Enum.at(-1) 33 | |> String.split(",") 34 | |> Enum.with_index() 35 | |> Enum.reject(fn {x, _} -> x == "x" end) 36 | |> Enum.map(fn {v, idx} -> {String.to_integer(v), String.to_integer(v) - idx} end) 37 | end 38 | 39 | defp next_departure(id, time) do 40 | next_departure = (div(time, id) + 1) * id 41 | {id, next_departure, next_departure - time, id * (next_departure - time)} 42 | end 43 | 44 | defp earliest_bus({time, ids}) do 45 | ids 46 | |> Enum.map(&next_departure(&1, time)) 47 | |> Enum.min_by(&elem(&1, 2)) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/2017/day_11.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2017.Day11 do 2 | @moduledoc """ 3 | --- Day 11: Hex Ed --- 4 | Problem Link: https://adventofcode.com/2017/day/11 5 | Difficulty: l 6 | Tags: hexagon 7 | 8 | Help: https://www.redblobgames.com/grids/hexagons/ 9 | """ 10 | alias AdventOfCode.Helpers.{InputReader, Transformers} 11 | 12 | def input, do: InputReader.read_from_file(2017, 11) 13 | 14 | def run(input \\ input()) do 15 | dirs = parse(input) 16 | {distance, farthest, _} = journey(dirs) 17 | 18 | {distance, farthest} 19 | end 20 | 21 | def parse(data \\ input()) do 22 | data 23 | |> Transformers.words(",") 24 | |> Enum.map(&String.to_existing_atom/1) 25 | end 26 | 27 | defp journey(dirs) do 28 | Enum.reduce(dirs, {0, 0, {0, 0, 0}}, fn dir, {_, farthest, position} -> 29 | new_position = walk(dir, position) 30 | distance = get_distance(new_position) 31 | farthest = max(distance, farthest) 32 | 33 | {distance, farthest, new_position} 34 | end) 35 | end 36 | 37 | defp walk(:n, {x, y, z}), do: {x, y + 1, z - 1} 38 | defp walk(:ne, {x, y, z}), do: {x + 1, y, z - 1} 39 | defp walk(:nw, {x, y, z}), do: {x - 1, y + 1, z} 40 | defp walk(:s, {x, y, z}), do: {x, y - 1, z + 1} 41 | defp walk(:se, {x, y, z}), do: {x + 1, y - 1, z} 42 | defp walk(:sw, {x, y, z}), do: {x - 1, y, z + 1} 43 | 44 | defp get_distance(position), do: get_distance({0, 0, 0}, position) 45 | 46 | defp get_distance({x1, y1, z1}, {x2, y2, z2}) do 47 | Enum.max([abs(x2 - x1), abs(y2 - y1), abs(z2 - z1)]) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/2024/day_05.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2024.Day05 do 2 | @moduledoc """ 3 | --- Day 5: Print Queue --- 4 | Problem Link: https://adventofcode.com/2024/day/5 5 | Difficulty: xs 6 | Tags: set sort 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2024, 5) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | 15 | {run_1(input), run_2(input)} 16 | end 17 | 18 | defp run_1(input) do 19 | input 20 | |> Enum.filter(fn {a, b} -> a == b end) 21 | |> Enum.sum_by(fn {a, _} -> a |> Enum.at(div(length(a), 2)) end) 22 | end 23 | 24 | defp run_2(input) do 25 | input 26 | |> Enum.filter(fn {a, b} -> a != b end) 27 | |> Enum.sum_by(fn {_, b} -> b |> Enum.at(div(length(b), 2)) end) 28 | end 29 | 30 | def parse(data \\ input()) do 31 | [deps, updates] = Transformers.sections(data) 32 | given_sorted_pair({parse_deps(deps), parse_updates(updates)}) 33 | end 34 | 35 | defp parse_deps(deps) do 36 | for line <- Transformers.lines(deps), 37 | into: MapSet.new(), 38 | do: String.split(line, "|") |> Enum.map(&String.to_integer/1) |> List.to_tuple() 39 | end 40 | 41 | defp parse_updates(updates) do 42 | for line <- Transformers.lines(updates) do 43 | for update <- String.split(line, ","), do: String.to_integer(update) 44 | end 45 | end 46 | 47 | defp given_sorted_pair({deps, updates}) do 48 | for update <- updates do 49 | {update, Enum.sort(update, &({&1, &2} in deps))} 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/algorithms/chinese_remainder.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Algorithms.ChineseRemainder do 2 | @moduledoc """ 3 | This module implements Chinese Remainder Theorem 4 | """ 5 | 6 | @doc """ 7 | Chinese Remainder Theorem. 8 | 9 | ## Example 10 | 11 | iex> ChineseRemainder.compute([{11, 10}, {12, 4}, {13, 12}]) 12 | 1000 13 | 14 | iex> ChineseRemainder.compute([{11, 10}, {22, 4}, {19, 9}]) 15 | nil 16 | 17 | iex> ChineseRemainder.compute([{3, 2}, {5, 3}, {7, 2}]) 18 | 23 19 | 20 | """ 21 | def compute(congruences) do 22 | {modulii, residues} = Enum.unzip(congruences) 23 | mod_pi = Enum.reduce(modulii, 1, &Kernel.*/2) 24 | crt_modulii = Enum.map(modulii, &div(mod_pi, &1)) 25 | 26 | case calculate_inverses(crt_modulii, modulii) do 27 | nil -> 28 | nil 29 | 30 | inverses -> 31 | crt_modulii 32 | |> Enum.zip( 33 | residues 34 | |> Enum.zip(inverses) 35 | |> Enum.map(&Tuple.product/1) 36 | ) 37 | |> Enum.sum_by(&Tuple.product/1) 38 | |> mod(mod_pi) 39 | end 40 | end 41 | 42 | defp mod_inverse(a, b) do 43 | {_, x, y} = Integer.extended_gcd(a, b) 44 | (a * x + b * y == 1 && x) || nil 45 | end 46 | 47 | defp mod(a, m) do 48 | x = rem(a, m) 49 | (x < 0 && x + m) || x 50 | end 51 | 52 | defp calculate_inverses([], []), do: [] 53 | 54 | defp calculate_inverses([n | ns], [m | ms]) do 55 | case mod_inverse(n, m) do 56 | nil -> nil 57 | inv -> [inv | calculate_inverses(ns, ms)] 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/2019/day_06.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2019.Day06 do 2 | @moduledoc """ 3 | --- Day 6: Universal Orbit Map --- 4 | Problem Link: https://adventofcode.com/2019/day/6 5 | Difficulty: xs 6 | Tags: graph routing 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | def input, do: InputReader.read_from_file(2019, 6) 11 | 12 | def run(input \\ input()) do 13 | input = parse(input) 14 | {run_1(input), run_2(input)} 15 | end 16 | 17 | def run_1(input) do 18 | input 19 | |> to_graph(:digraph.new([:acyclic])) 20 | |> count_orbits() 21 | end 22 | 23 | def run_2(input) do 24 | input 25 | |> to_graph(:digraph.new()) 26 | |> count_orbital_transfers() 27 | end 28 | 29 | def parse(data) do 30 | data |> Transformers.lines() |> Enum.map(&String.split(&1, ")")) 31 | end 32 | 33 | defp to_graph(data, graph) do 34 | data 35 | |> Enum.each(fn [a, b] -> 36 | :digraph.add_vertex(graph, a) 37 | :digraph.add_vertex(graph, b) 38 | :digraph.add_edge(graph, b, a) 39 | :digraph.add_edge(graph, a, b) 40 | end) 41 | 42 | graph 43 | end 44 | 45 | defp count_orbits(graph) do 46 | graph 47 | |> :digraph.vertices() 48 | |> Stream.map(fn vertex -> 49 | :digraph.get_path(graph, vertex, "COM") || [] 50 | end) 51 | |> Stream.map(fn path -> length(path) - 1 end) 52 | |> Enum.sum() 53 | |> Kernel.+(1) 54 | end 55 | 56 | defp count_orbital_transfers(graph) do 57 | graph 58 | |> :digraph.get_short_path("YOU", "SAN") 59 | |> Enum.count() 60 | |> Kernel.-(3) 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/2022/day_02.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2022.Day02 do 2 | @moduledoc """ 3 | --- Day 2: Rock Paper Scissors --- 4 | Problem Link: https://adventofcode.com/2022/day/2 5 | Difficulty: xs 6 | Tags: table-lookup 7 | """ 8 | alias AdventOfCode.Helpers.{InputReader, Transformers} 9 | 10 | @pts %{rock: 1, paper: 2, scissor: 3} 11 | @to_win %{rock: :paper, paper: :scissor, scissor: :rock} 12 | @to_draw Map.new(@to_win, fn {a, _} -> {a, a} end) 13 | @to_lose Map.new(@to_win, fn {a, b} -> {b, a} end) 14 | @fate %{"X" => @to_lose, "Y" => @to_draw, "Z" => @to_win} 15 | 16 | def input, do: InputReader.read_from_file(2022, 2) 17 | 18 | def run(input \\ input()) do 19 | input = parse(input) 20 | 21 | {score_1(input), score_2(input)} 22 | end 23 | 24 | def parse(data \\ input()) do 25 | for line <- Transformers.lines(data) do 26 | [a, b] = Transformers.words(line) 27 | {to_rps(a), b} 28 | end 29 | end 30 | 31 | defp score_1(input), do: Enum.reduce(input, 0, fn x, tot -> tot + pts(x) end) 32 | 33 | defp score_2(input) do 34 | input 35 | |> Enum.reduce([], fn {a, b}, acc -> [{a, @fate[b][a]} | acc] end) 36 | |> score_1() 37 | end 38 | 39 | def pts({a, b}) when is_binary(b), do: pts({a, to_rps(b)}) 40 | def pts({:scissor, :rock}), do: 7 41 | def pts({:rock, :paper}), do: 8 42 | def pts({:paper, :scissor}), do: 9 43 | def pts({a, a}), do: 3 + @pts[a] 44 | def pts({_, b}), do: @pts[b] 45 | 46 | def to_rps(a) when a in ~w/A X/, do: :rock 47 | def to_rps(a) when a in ~w/B Y/, do: :paper 48 | def to_rps(a) when a in ~w/C Z/, do: :scissor 49 | end 50 | -------------------------------------------------------------------------------- /lib/2015/day_20.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day20 do 2 | @moduledoc """ 3 | --- Day 20: Infinite Elves and Infinite Houses --- 4 | Problem Link: https://adventofcode.com/2015/day/20 5 | Difficulty: l 6 | Tags: slow infinite-sequence sequence 7 | """ 8 | alias AdventOfCode.Algorithms.Arithmetics 9 | alias AdventOfCode.Helpers.InputReader 10 | 11 | def input, do: InputReader.read_from_file(2015, 20) 12 | 13 | def run(input \\ input()) do 14 | input = String.to_integer(input) 15 | 16 | part_1 = Task.async(fn -> run_1(input) end) 17 | part_2 = Task.async(fn -> run_2(input) end) 18 | 19 | {Task.await(part_1, 10_000), Task.await(part_2, 10_000)} 20 | end 21 | 22 | defp run_1(input) do 23 | house_with_gifts(input, &number_of_gifts/1) 24 | end 25 | 26 | defp run_2(input) do 27 | house_with_gifts(input, &number_of_gifts_below_50/1) 28 | end 29 | 30 | def house_with_gifts(limit, fun) do 31 | Stream.iterate(1, &(&1 + 1)) 32 | |> Stream.map(fun) 33 | |> Enum.take_while(fn {_, gifts} -> gifts < limit end) 34 | |> Enum.max_by(fn {house, _} -> house end) 35 | |> then(fn {house, _} -> house + 1 end) 36 | end 37 | 38 | defp number_of_gifts(house) do 39 | gifts = 40 | house 41 | |> Arithmetics.divisors() 42 | |> Enum.sum_by(&(&1 * 10)) 43 | 44 | {house, gifts} 45 | end 46 | 47 | defp number_of_gifts_below_50(house) do 48 | gifts = 49 | house 50 | |> Arithmetics.divisors() 51 | |> Enum.filter(fn divisor -> div(house, divisor) < 50 end) 52 | |> Enum.sum_by(&(&1 * 11)) 53 | 54 | {house, gifts} 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/2015/day_12.ex: -------------------------------------------------------------------------------- 1 | defmodule AdventOfCode.Y2015.Day12 do 2 | @moduledoc """ 3 | --- Day 12: JSAbacusFramework.io --- 4 | Problem Link: https://adventofcode.com/2015/day/12 5 | Difficulty: xs 6 | Tags: json 7 | """ 8 | alias AdventOfCode.Helpers.InputReader 9 | 10 | def input, do: InputReader.read_from_file(2015, 12) 11 | 12 | def run(input \\ input()) do 13 | {run_1(input), run_2(input)} 14 | end 15 | 16 | def run_1(input) do 17 | input 18 | |> String.graphemes() 19 | |> parse_json([]) 20 | |> compute() 21 | end 22 | 23 | def run_2(input) do 24 | input 25 | |> JSON.decode!() 26 | |> total() 27 | end 28 | 29 | @numbers "-0123456789" 30 | @delim " " 31 | 32 | def number?(s), do: String.contains?(@numbers, s) 33 | 34 | def parse_json([], result), do: result 35 | 36 | def parse_json([h | t], []) do 37 | (number?(h) && parse_json(t, [h])) || parse_json(t, [@delim]) 38 | end 39 | 40 | def parse_json([h | t], [x | xs] = res) do 41 | (number?(h) && parse_json(t, [x <> h | xs])) || parse_json(t, [@delim | res]) 42 | end 43 | 44 | def compute(parsed) do 45 | parsed 46 | |> Enum.join() 47 | |> String.split() 48 | |> Enum.sum_by(&String.to_integer/1) 49 | end 50 | 51 | def total(obj) when is_map(obj) do 52 | nodes = Map.values(obj) 53 | ("red" in nodes && 0) || total(nodes) 54 | end 55 | 56 | def total(obj) when is_list(obj) do 57 | obj 58 | |> Enum.sum_by(fn 59 | value when is_map(value) or is_list(value) -> total(value) 60 | value when is_integer(value) -> value 61 | _ -> 0 62 | end) 63 | end 64 | end 65 | --------------------------------------------------------------------------------