Run this notebook

Use Livebook to open this notebook and explore new ideas.

It is easy to get started, on your machine or the cloud.

Click below to open and run it in your Livebook at .

(or change your Livebook location)

# Advent of Code 2022 ```elixir Mix.install([ {:memoize, "~> 1.4"}, {:tesla, "~> 1.4"}, {:hackney, "~> 1.18"} ]) defmodule Api do use Tesla use Memoize @session System.get_env("AOC_SESSION") adapter(Tesla.Adapter.Hackney) plug(Tesla.Middleware.BaseUrl, "https://adventofcode.com/2022/day/") plug(Tesla.Middleware.Headers, [{"cookie", "session=#{@session}"}]) defmemo get_input(day) do {:ok, response} = get("#{day}/input") response.body end end :ok ``` ## Task 1 ```elixir test_input = """ 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 """ solve1 = fn input -> input |> String.split("\n\n") |> Enum.map(fn cals -> cals |> String.split("\n", trim: true) |> Enum.map(&String.to_integer/1) |> Enum.sum() end) |> Enum.max() end 24000 = solve1.(test_input) solve1.(Api.get_input(1)) |> IO.inspect(label: "1.1") solve2 = fn input -> input |> String.split("\n\n") |> Enum.map(fn cals -> cals |> String.split("\n", trim: true) |> Enum.map(&String.to_integer/1) |> Enum.sum() end) |> Enum.sort(&>=/2) |> Enum.take(3) |> Enum.sum() end 45000 = solve2.(test_input) solve2.(Api.get_input(1)) |> IO.inspect(label: "1.2") :ok ``` ## Task 2 ```elixir test_input = """ A Y B X C Z """ solve1 = fn input -> input |> String.split("\n", trim: true) |> Enum.map(fn round -> String.split(round, " ") |> case do ["A", "X"] -> 1 + 3 ["A", "Y"] -> 2 + 6 ["A", "Z"] -> 3 + 0 ["B", "X"] -> 1 + 0 ["B", "Y"] -> 2 + 3 ["B", "Z"] -> 3 + 6 ["C", "X"] -> 1 + 6 ["C", "Y"] -> 2 + 0 ["C", "Z"] -> 3 + 3 end end) |> Enum.sum() end 15 = solve1.(test_input) solve1.(Api.get_input(2)) |> IO.inspect(label: "2.1") solve2 = fn input -> input |> String.split("\n", trim: true) |> Enum.map(fn round -> String.split(round, " ") |> case do ["A", "X"] -> 3 + 0 ["A", "Y"] -> 1 + 3 ["A", "Z"] -> 2 + 6 ["B", "X"] -> 1 + 0 ["B", "Y"] -> 2 + 3 ["B", "Z"] -> 3 + 6 ["C", "X"] -> 2 + 0 ["C", "Y"] -> 3 + 3 ["C", "Z"] -> 1 + 6 end end) |> Enum.sum() end 12 = solve2.(test_input) solve2.(Api.get_input(2)) |> IO.inspect(label: "2.2") :ok ``` ## Task 3 ```elixir test_input = """ vJrwpWtwJgWrhcsFMMfFFhFp jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL PmmdzqPrVvPwwTWBwg wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn ttgJtRGJQctTZtZT CrZsJsPPZsGzwwsLwLmpwMDw """ priorities = [?a..?z, ?A..?Z] |> Enum.flat_map(fn chars -> Enum.map(chars, &<<&1::utf8>>) end) |> Enum.with_index(1) |> Enum.into(%{}) solve1 = fn input -> input |> String.split("\n", trim: true) |> Enum.map(fn rucksack -> with [first_half, second_half] <- rucksack |> String.split_at(div(String.length(rucksack), 2)) |> Tuple.to_list() |> Enum.map(&(&1 |> String.split("", trim: true) |> MapSet.new())), [common] <- MapSet.intersection(first_half, second_half) |> MapSet.to_list() do Map.get(priorities, common) end end) |> Enum.sum() end 157 = solve1.(test_input) solve1.(Api.get_input(3)) |> IO.inspect(label: "3.1") solve2 = fn input -> input |> String.split("\n", trim: true) |> Enum.chunk_every(3) |> Enum.map(fn rucksacks -> with [first, second, third] <- Enum.map(rucksacks, &(&1 |> String.split("", trim: true) |> MapSet.new())), [common] <- first |> MapSet.intersection(second) |> MapSet.intersection(third) |> MapSet.to_list() do Map.get(priorities, common) end end) |> Enum.sum() end 70 = solve2.(test_input) solve2.(Api.get_input(3)) |> IO.inspect(label: "3.2") :ok ``` ## Task 4 ```elixir test_input = """ 2-4,6-8 2-3,4-5 5-7,7-9 2-8,3-7 6-6,4-6 2-6,4-8 """ solve1 = fn input -> input |> String.split("\n", trim: true) |> Enum.map(fn pair_assignments -> pair_assignments |> String.split(",") |> Enum.map(fn elf -> elf |> String.split("-") |> Enum.map(&String.to_integer/1) |> then(fn [first, last] -> Range.new(first, last) |> Enum.to_list() |> MapSet.new() end) end) |> then(fn [first_elf_assignments, second_elf_assignments] -> MapSet.subset?(first_elf_assignments, second_elf_assignments) or MapSet.subset?(second_elf_assignments, first_elf_assignments) end) end) |> Enum.count(& &1) end 2 = solve1.(test_input) solve1.(Api.get_input(4)) |> IO.inspect(label: "4.1") solve2 = fn input -> input |> String.split("\n", trim: true) |> Enum.map(fn pair_assignments -> pair_assignments |> String.split(",") |> Enum.map(fn elf -> elf |> String.split("-") |> Enum.map(&String.to_integer/1) |> then(fn [first, last] -> Range.new(first, last) end) end) |> then(fn [first_elf_assignments, second_elf_assignments] -> Range.disjoint?(first_elf_assignments, second_elf_assignments) end) end) |> Enum.count(&(!&1)) end 4 = solve2.(test_input) solve2.(Api.get_input(4)) |> IO.inspect(label: "4.2") :ok ``` ## Task 5 ```elixir test_input = """ [D] [N] [C] [Z] [M] [P] 1 2 3 move 1 from 2 to 1 move 3 from 1 to 3 move 2 from 2 to 1 move 1 from 1 to 2 """ parse_input = fn input -> with [stacks_input, moves_input] <- input |> String.split("\n\n", trim: true), stacks <- stacks_input |> String.split("\n", trim: true) |> Enum.flat_map( &(&1 |> String.split("", trim: true) |> Enum.with_index() |> Enum.filter(fn {c, _} -> c =~ ~r/[A-Z]/ end)) ) |> Enum.group_by(fn {_, i} -> i end, fn {c, _} -> c end) |> Map.values() |> Enum.map(&Enum.reverse/1) |> Enum.with_index(1) |> Enum.into(%{}, fn {stack, index} -> {index, stack} end), moves <- moves_input |> String.split("\n", trim: true) |> Enum.map( &(~r/\d+/ |> Regex.scan(&1) |> Enum.map(fn [v] -> String.to_integer(v) end)) ) do {stacks, moves} end end solve1 = fn input -> {input_stacks, moves} = parse_input.(input) moves |> Enum.reduce(input_stacks, fn [count, from, to], stacks -> {crates_left, crates_to_move} = Enum.split(stacks[from], -count) stacks |> Map.put(from, crates_left) |> Map.update!(to, &(&1 ++ Enum.reverse(crates_to_move))) end) |> Map.values() |> Enum.map(&List.last/1) |> Enum.join() end "CMZ" = solve1.(test_input) solve1.(Api.get_input(5)) |> IO.inspect(label: "5.1") solve2 = fn input -> {input_stacks, moves} = parse_input.(input) moves |> Enum.reduce(input_stacks, fn [count, from, to], stack -> {crates_left, crates_to_move} = Enum.split(stack[from], -count) stack |> Map.put(from, crates_left) |> Map.update!(to, &(&1 ++ crates_to_move)) end) |> Map.values() |> Enum.map(&List.last/1) |> Enum.join() end "MCD" = solve2.(test_input) solve2.(Api.get_input(5)) |> IO.inspect(label: "5.2") :ok ``` ## Task 6 ```elixir test_inputs = [ "mjqjpqmgbljsphdztnvjfqwrcgsmlb", "bvwbjplbgvbhsrlpgdmjqwftvncz", "nppdvjthqldpwncqszvftbrmjlhg", "nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg", "zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw" ] solve = fn input, marker_length -> input |> String.to_charlist() |> Stream.chunk_every(marker_length, 1) |> Stream.take_while(&(&1 |> Enum.uniq() |> length() != marker_length)) |> Enum.count() |> Kernel.+(marker_length) end [7, 5, 6, 10, 11] = Enum.map(test_inputs, &solve.(&1, 4)) solve.(Api.get_input(6), 4) |> IO.inspect(label: "6.1") [19, 23, 23, 29, 26] = Enum.map(test_inputs, &solve.(&1, 14)) solve.(Api.get_input(6), 14) |> IO.inspect(label: "6.2") ``` ## Task 7 ```elixir test_input = """ $ cd / $ ls dir a 14848514 b.txt 8504156 c.dat dir d $ cd a $ ls dir e 29116 f 2557 g 62596 h.lst $ cd e $ ls 584 i $ cd .. $ cd .. $ cd d $ ls 4060174 j 8033020 d.log 5626152 d.ext 7214296 k """ solve1 = fn input -> input |> String.split("\n", trim: true) |> Enum.reduce({[], %{}}, fn "$ cd ..", {dir_stack, sizes} -> {tl(dir_stack), sizes} "$ cd " <> dir, {dir_stack, sizes} -> uuid = :crypto.strong_rand_bytes(32) |> Base.url_encode64() |> binary_part(0, 32) {["#{dir}::#{uuid}" | dir_stack], sizes} command, {dir_stack, sizes} -> command |> Integer.parse() |> case do {size, _} -> {dir_stack, dir_stack |> Enum.into(%{}, fn dir -> {dir, size} end) |> Map.merge(sizes, fn _k, v1, v2 -> v1 + v2 end)} _ -> {dir_stack, sizes} end end) |> elem(1) |> Enum.filter(fn {_, size} -> size <= 100_000 end) |> Enum.map(&elem(&1, 1)) |> Enum.sum() end 95437 = solve1.(test_input) solve1.(Api.get_input(7)) |> IO.inspect(label: "7.1") solve2 = fn input -> input |> String.split("\n", trim: true) |> Enum.reduce({[], %{}}, fn "$ cd ..", {dir_stack, sizes} -> {tl(dir_stack), sizes} "$ cd " <> dir, {dir_stack, sizes} -> uuid = :crypto.strong_rand_bytes(32) |> Base.url_encode64() |> binary_part(0, 32) {["#{dir}::#{uuid}" | dir_stack], sizes} command, {dir_stack, sizes} -> command |> Integer.parse() |> case do {size, _} -> {dir_stack, dir_stack |> Enum.into(%{}, fn dir -> {dir, size} end) |> Map.merge(sizes, fn _k, v1, v2 -> v1 + v2 end)} _ -> {dir_stack, sizes} end end) |> elem(1) |> Enum.sort_by(fn {_, size} -> -size end) |> then(fn [{_, all} | rest] -> rest |> Enum.reverse() |> Enum.find(fn {_, size} -> 70_000_000 - all + size > 30_000_000 end) |> elem(1) end) end 24_933_642 = solve2.(test_input) solve2.(Api.get_input(7)) |> IO.inspect(label: "7.2") :ok ``` ## Task 8 ```elixir test_input = """ 30373 25512 65332 33549 35390 """ solve1 = fn input -> with trees_rows <- String.split(input, "\n", trim: true), size <- length(trees_rows), trees <- trees_rows |> Enum.flat_map(fn row -> row |> String.split("", trim: true) |> Enum.map(&String.to_integer/1) end) |> Enum.with_index() do trees |> Enum.map(fn {curr_height, curr_idx} -> row_idx = trunc(curr_idx / size) col_idx = rem(curr_idx, size) top = Enum.slice(trees, col_idx..curr_idx//size) |> Enum.reverse() |> tl left = Enum.slice(trees, (row_idx * size)..curr_idx) |> Enum.reverse() |> tl right = Enum.slice(trees, curr_idx..(row_idx * size + size - 1)) |> tl bottom = Enum.slice(trees, curr_idx..(size * size)//size) |> tl Enum.any?([top, left, right, bottom], fn trees_slice -> trees_slice == [] || Enum.all?(trees_slice, &(elem(&1, 0) < curr_height)) end) end) |> Enum.count(& &1) end end 21 = solve1.(test_input) solve1.(Api.get_input(8)) |> IO.inspect(label: "8.1") solve2 = fn input -> with trees_rows <- String.split(input, "\n", trim: true), size <- length(trees_rows), trees <- trees_rows |> Enum.flat_map(fn row -> row |> String.split("", trim: true) |> Enum.map(&String.to_integer/1) end) |> Enum.with_index() do trees |> Enum.map(fn {curr_height, curr_idx} -> row_idx = trunc(curr_idx / size) col_idx = rem(curr_idx, size) top = Enum.slice(trees, col_idx..curr_idx//size) |> Enum.reverse() |> tl left = Enum.slice(trees, (row_idx * size)..curr_idx) |> Enum.reverse() |> tl right = Enum.slice(trees, curr_idx..(row_idx * size + size - 1)) |> tl bottom = Enum.slice(trees, curr_idx..(size * size)//size) |> tl Enum.map([top, left, right, bottom], fn trees_slice -> Enum.reduce_while(trees_slice, 0, fn {height, _}, score when height >= curr_height -> {:halt, score + 1} _, score -> {:cont, score + 1} end) end) |> Enum.product() end) |> Enum.max() end end 8 = solve2.(test_input) solve2.(Api.get_input(8)) |> IO.inspect(label: "8.2") :ok ``` ## Task 9 ```elixir defmodule Task9 do def solve1(input) do input |> parse_input |> Enum.reduce( [{0, 0}, {0, 0}, MapSet.new([{0, 0}])], fn step, [head, tail, tail_positions] -> new_head = move_head(head, step) new_tail = move_tail(new_head, tail, step) [new_head, new_tail, MapSet.put(tail_positions, new_tail)] end ) |> then(fn [_, _, tail_positions] -> Enum.count(tail_positions) end) end defp parse_input(input) do input |> String.split("\n", trim: true) |> Enum.flat_map( &(&1 |> String.split(" ") |> then(fn [direction, count] -> List.duplicate(direction, String.to_integer(count)) end)) ) end defp move_head({x, y}, "R"), do: {x + 1, y} defp move_head({x, y}, "U"), do: {x, y + 1} defp move_head({x, y}, "L"), do: {x - 1, y} defp move_head({x, y}, "D"), do: {x, y - 1} defp move_tail({h_x, h_y} = _head, {t_x, t_y} = tail, step) do cond do t_x == h_x and t_y - h_y == 2 -> {t_x, t_y - 1} t_y == h_y and h_x - t_x == 2 -> {t_x + 1, t_y} t_x == h_x and h_y - t_y == 2 -> {t_x, t_y + 1} t_y == h_y and t_x - h_x == 2 -> {t_x - 1, t_y} t_y - h_y == 2 or h_x - t_x == 2 or h_y - t_y == 2 or t_x - h_x == 2 -> case step do "R" -> {h_x - 1, h_y} "U" -> {h_x, h_y - 1} "L" -> {h_x + 1, h_y} "D" -> {h_x, h_y + 1} end true -> tail end end end test_input = """ R 4 U 4 L 3 D 1 R 4 D 1 L 5 R 2 """ 13 = Task9.solve1(test_input) Task9.solve1(Api.get_input(9)) |> IO.inspect(label: "9.1") :ok ```
See source

Have you already installed Livebook?

If you already installed Livebook, you can configure the default Livebook location where you want to open notebooks.
Livebook up Checking status We can't reach this Livebook (but we saved your preference anyway)
Run notebook

Not yet? Install Livebook in just a minute

Livebook is open source, free, and ready to run anywhere.

Run on your machine

with Livebook Desktop

Run in the cloud

on select platforms

To run on Linux, Docker, embedded devices, or Elixir’s Mix, check our README.

PLATINUM SPONSORS
SPONSORS
Code navigation with go to definition of modules and functions Read More ×