diff --git a/README.md b/README.md index 26e6656..c0f6af7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#Advent of code +# Advent of code Solutions in Elixir for www.adventofcode.com puzzles, by year. diff --git a/data/day_11/sample.txt b/data/day_11/sample.txt new file mode 100644 index 0000000..c04eddb --- /dev/null +++ b/data/day_11/sample.txt @@ -0,0 +1,27 @@ +Monkey 0: + Starting items: 79, 98 + Operation: new = old * 19 + Test: divisible by 23 + If true: throw to monkey 2 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 54, 65, 75, 74 + Operation: new = old + 6 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 79, 60, 97 + Operation: new = old * old + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 74 + Operation: new = old + 3 + Test: divisible by 17 + If true: throw to monkey 0 + If false: throw to monkey 1 \ No newline at end of file diff --git a/lib/day_11_part_1.ex b/lib/day_11_part_1.ex new file mode 100644 index 0000000..488dae7 --- /dev/null +++ b/lib/day_11_part_1.ex @@ -0,0 +1,160 @@ +defmodule Day11Part1 do + defmodule Monkey do + def start_link(id, parent_pid, map) do + Task.start_link(fn -> + loop(%{ + :id => id, + :parent_pid => parent_pid, + :items => map.items, + :down_level => fn level -> div(level, 3) end, + :op => map.op, + :condition => map.condition + }) + end) + end + + def process_items(map) do + %{parent_pid: parent_pid, down_level: down_level, id: id, op: op, condition: condition} = + map + + IO.puts("Monkey #{id}:") + for item <- map.items do + IO.puts(" Monkey inspects an item with a worry level of #{item}.") + value = op.(item) + IO.puts(" Worry level is (do op) to #{value}.") + value = down_level.(value) + IO.puts(" Monkey gets bored with item. Worry level is divided by 3 to #{value}.") + {divisible, if_true, if_false} = condition + next_monkey = if rem(value, divisible) == 0 do + IO.puts(" Current worry level is divisible by #{divisible}.") + IO.puts(" Item with worry level #{value} is thrown to monkey #{if_true}.") + if_true + else + IO.puts(" Current worry level is not divisible by #{divisible}.") + IO.puts(" Item with worry level #{value} is thrown to monkey #{if_false}.") + if_false + end + IO.puts("") + send(parent_pid, {:send_to_monkey, next_monkey, value}) + end + + if (length(map.items) > 0) do + IO.write("Monkey #{id}: ") + IO.inspect(map.items, charlists: :as_lists) + end + + if (id == 3), do: IO.puts("") + send(parent_pid, {:start_next_monkey, id}) + end + + def loop(map \\ %{}) do + receive do + {:start} -> + process_items(map) + loop(%{map | items: []}) + + {:add_item, value} -> + loop(%{map | items: map.items ++ [value]}) + + {:inspect} -> + send(map.parent_id, {:monkey_status, map}) + loop(map) + + {:exit} -> + IO.puts("Monkey #{map.id} says: bye!") + IO.inspect(map) + + {msg} -> + IO.puts("Unknown message #{msg}") + loop(map) + end + end + end + + # alias Day11Part1.Monkey + # @down_level = fn level -> div(level, 3) + # {:cond, :then, :else} = condition + # @if_as_func = fn condition, true_monkey, else_monkey -> if condition, do: true_monky, else: else_monkey en + + def sample do + # content = File.read!("data/day_10/sample.txt") + + {:ok, pid_0} = + Monkey.start_link(0, self(), %{ + :items => [79, 98], + :op => fn old -> old * 19 end, + :condition => {23, 2, 3} + }) + + {:ok, pid_1} = + Monkey.start_link(1, self(), %{ + :items => [54, 65, 75, 74], + :op => fn old -> old + 6 end, + :condition => {19, 2, 0} + }) + + {:ok, pid_2} = + Monkey.start_link(2, self(), %{ + :items => [79, 60, 97], + :op => fn old -> old * old end, + :condition => {13, 1, 3} + }) + + {:ok, pid_3} = + Monkey.start_link(3, self(), %{ + :items => [74], + :op => fn old -> old + 3 end, + :condition => {17, 0, 1} + }) + + monkeys = %{ + 0 => pid_0, + 1 => pid_1, + 2 => pid_2, + 3 => pid_3 + } + + send(Map.fetch!(monkeys, 0), {:start}) + + process_incoming_messages(monkeys, 0) + + # doit(monkeys) + end + + def process_incoming_messages(monkeys, cycle) do + receive do + {:start_next_monkey, id} -> + cycle = if id == 0, do: cycle + 1, else: cycle + next_monkey = try do + rem(id + 1, map_size(monkeys)) + rescue + ArithmeticError -> 0 + end + + if cycle <= 21 do + send(Map.fetch!(monkeys, next_monkey), {:start}) + process_incoming_messages(monkeys, cycle) + end + # IO.puts("") + + {:send_to_monkey, id, value} -> + send(Map.fetch!(monkeys, id), {:add_item, value}) + process_incoming_messages(monkeys, cycle) + + {msg} -> + IO.puts("Unknown message #{msg}") + end + end + + # def puzzle do + # doit([]) + # end + + # def doit(monkeys) do + # for monkey <- monkeys do + # IO.inspect(monkey) + # existing_items = monkey.items + # monkeys[1] = %{ monkey | items: [ existing_items | 999] } + # end + # end +end diff --git a/test/aoc_day_11_test.exs b/test/aoc_day_11_test.exs new file mode 100644 index 0000000..2d63e55 --- /dev/null +++ b/test/aoc_day_11_test.exs @@ -0,0 +1,8 @@ +defmodule Day10Test do + use ExUnit.Case + + test "day 11, part 1, sample" do + assert Day11Part1.sample() == 10605 + end + +end