Last active
December 7, 2022 21:33
-
-
Save alvises/c5e8fb5767dfe5568ea3a4073e9370b4 to your computer and use it in GitHub Desktop.
AoC 2022 in Elixir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# AoC 2022 in Elixir |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Game do | |
defstruct [:tot_score, :rounds] | |
# {me, opponent} | |
@winning [ | |
{:rock, :scissors}, | |
{:scissors, :paper}, | |
{:paper, :rock} | |
] | |
def play(%{rounds: []}=game), do: game | |
def play(%{rounds: [round | remaining_rounds]=_rounds}=game) do | |
play(%{game | tot_score: game.tot_score + score(round), rounds: remaining_rounds}) | |
end | |
# WIN | |
def score({me, opponent}) when {me, opponent} in @winning do | |
hand_score(me) + 6 | |
end | |
# DRAW | |
def score({me, opponent}) when me == opponent do | |
hand_score(me) + 3 | |
end | |
# LOSE | |
def score({me, _opponent}), do: hand_score(me) | |
def hand_score(:rock), do: 1 | |
def hand_score(:paper), do: 2 | |
def hand_score(:scissors), do: 3 | |
defp map_symbol(s) when s in ["A", "X"], do: :rock | |
defp map_symbol(s) when s in ["B", "Y"], do: :paper | |
defp map_symbol(s) when s in ["C", "Z"], do: :scissors | |
def new(input) do | |
%__MODULE__{tot_score: 0, rounds: rounds_from_input(input)} | |
end | |
defp rounds_from_input(input) do | |
input | |
|> String.split("\n") | |
|> Enum.map(&String.trim/1) | |
|> Enum.map(&String.split/1) | |
|> Enum.filter(¬ match?([], &1)) | |
|> Enum.map(fn [opponent, me] -> {map_symbol(me), map_symbol(opponent)} end) | |
end | |
end | |
"/Users/alvise/code/aoc2022/input2.txt" | |
|> File.read!() | |
|> Game.new() | |
|> Game.play() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Item do | |
defstruct [:letter, :priority] | |
@type t :: %__MODULE__{ | |
letter: String.t, | |
priority: integer | |
} | |
def new(letter) do | |
%__MODULE__{letter: letter, priority: priority_from_letter(letter)} | |
end | |
defp priority_from_letter(letter) do | |
letter | |
|> String.to_charlist() | |
|> List.first() | |
|> priority_from_ascii() | |
end | |
defp priority_from_ascii(ascii_code) when ascii_code in ?a..?z, | |
do: ascii_code - ?a + 1 | |
defp priority_from_ascii(ascii_code) when ascii_code in ?A..?Z, | |
do: ascii_code - ?A + 27 | |
end | |
defmodule Rucksack do | |
defstruct [:count, :comp1, :comp2] | |
@type t :: %__MODULE__{ | |
count: integer, | |
comp1: [Item.t], | |
comp2: [Item.t] | |
} | |
@spec parse(String.t ) :: Rucksack.t | |
def parse(line) when is_binary(line) do | |
items = | |
line | |
|> String.trim() | |
|> String.graphemes() | |
count = Enum.count(items) | |
[first_compartment, second_compartment] = Enum.chunk_every(items,trunc(count/2)) | |
%__MODULE__{ | |
count: count, | |
comp1: Enum.map(first_compartment, &Item.new/1), | |
comp2: Enum.map(second_compartment, &Item.new/1) | |
} | |
end | |
def items_in_both_compartments(rucksack) do | |
MapSet.intersection( | |
MapSet.new(rucksack.comp1), | |
MapSet.new(rucksack.comp2) | |
) | |
|> MapSet.to_list() | |
end | |
end | |
defmodule Day3 do | |
def part1(input) do | |
input | |
|> String.split("\n") | |
|> Enum.map(&String.trim/1) | |
|> Enum.filter(& String.length(&1) > 0) | |
|> Stream.map(&Rucksack.parse/1) | |
|> Stream.flat_map(&Rucksack.items_in_both_compartments/1) | |
|> Stream.map(& &1.priority) | |
|> Enum.sum() | |
end | |
end | |
"input3.txt" | |
|> File.read!() | |
|> Day3.part1() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# PART 1 | |
defmodule Cargo do | |
def parse(input) do | |
[stacks_input, moves_input] = String.split(input, "\n\n", trim: true) | |
%{ | |
stacks: parse_stacks(stacks_input), | |
moves: parse_moves(moves_input) | |
} | |
end | |
defp parse_stacks(stacks_input) do | |
stacks_input | |
|> String.split("\n", trim: true) | |
|> Enum.map(&String.graphemes/1) | |
|> Enum.zip_with(& &1) | |
|> Enum.map(&Enum.reverse/1) | |
|> Enum.filter(&(not match?([" " | _rest], &1))) | |
|> Enum.map(fn [n | stack] -> | |
stack = | |
stack | |
|> Enum.filter(&(&1 != " ")) | |
|> Enum.reverse() | |
{n, stack} | |
end) | |
|> Enum.into(%{}) | |
end | |
defp parse_moves(moves_input) do | |
moves_input | |
|> String.split("\n", trim: true) | |
|> Enum.map(&scan_move/1) | |
end | |
@action_regex ~r/\w+\s+(\d+)\s+\w+\s+(\d+)\s+\w+\s+(\d+)/ | |
@spec scan_move(String.t()) :: map | |
defp scan_move(line) do | |
[[_, count, from, to]] = Regex.scan(@action_regex, line) | |
%{count: String.to_integer(count), from: from, to: to} | |
end | |
def part1(cargo) do | |
cargo | |
|> move_crates() | |
|> top_crates() | |
|> Enum.join() | |
end | |
def top_crates(stacks) do | |
stacks | |
|> Enum.sort_by(&elem(&1, 0), :asc) | |
|> Enum.map(&(elem(&1, 1) |> hd())) | |
end | |
def move_crates(%{stacks: stacks, moves: moves} = _cargo, move_func) do | |
for move <- moves, _n <- 1..move.count, reduce: stacks do | |
acc -> move_func.(acc, move) | |
end | |
end | |
def move_crate_part1(stacks, move) do | |
{crate, updated_stacks} = Map.get_and_update!(stacks, move.from, &List.pop_at(&1, 0)) | |
Map.update!(updated_stacks, move.to, &[crate | &1]) | |
end | |
def move_crate_part2(stacks, move) do | |
{crates, updated_stacks} = Map.get_and_update!(stacks, move.from, &pop_by(&1, move.count)) | |
Map.update!(updated_stacks, to, &[crate | &1]) | |
end | |
defp pop_by(stack, amount) do | |
Enum.reduce(1..amount, {[], stack}, fn | |
_n, {acc, [crate | rest_of_stack]} -> | |
{acc ++ [crate],rest_of_stack} | |
end) | |
end | |
end | |
""" | |
[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 | |
""" | |
|> Cargo.parse() | |
|> Cargo.part1() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Cargo do | |
def parse(input) do | |
[stacks_input, moves_input] = String.split(input, "\n\n", trim: true) | |
%{ | |
stacks: parse_stacks(stacks_input), | |
moves: parse_moves(moves_input) | |
} | |
end | |
defp parse_stacks(stacks_input) do | |
stacks_input | |
|> String.split("\n", trim: true) | |
|> Enum.map(&String.graphemes/1) | |
|> Enum.zip_with(& &1) | |
|> Enum.map(&Enum.reverse/1) | |
|> Enum.filter(&(not match?([" " | _rest], &1))) | |
|> Enum.map(fn [n | stack] -> | |
stack = | |
stack | |
|> Enum.filter(&(&1 != " ")) | |
|> Enum.reverse() | |
{n, stack} | |
end) | |
|> Enum.into(%{}) | |
end | |
defp parse_moves(moves_input) do | |
moves_input | |
|> String.split("\n", trim: true) | |
|> Enum.map(&scan_move/1) | |
end | |
@action_regex ~r/\w+\s+(\d+)\s+\w+\s+(\d+)\s+\w+\s+(\d+)/ | |
@spec scan_move(String.t()) :: map | |
defp scan_move(line) do | |
[[_, count, from, to]] = Regex.scan(@action_regex, line) | |
%{count: String.to_integer(count), from: from, to: to} | |
end | |
def part2(cargo) do | |
cargo | |
|> move_crates() | |
|> top_crates() | |
|> Enum.join() | |
end | |
def top_crates(stacks) do | |
stacks | |
|> Enum.sort_by(&elem(&1, 0), :asc) | |
|> Enum.map(&(elem(&1, 1) |> hd())) | |
end | |
def move_crates(%{stacks: stacks, moves: moves} = _cargo) do | |
for move <- moves, reduce: stacks do | |
acc -> | |
{crates, updated_stacks} = Map.get_and_update!(acc, move.from, &pop_by(&1, move.count)) | |
Map.update!(updated_stacks, move.to, & crates ++ &1) | |
end | |
end | |
defp pop_by(stack, amount) do | |
Enum.reduce(1..amount, {[], stack}, fn | |
_n, {acc, [crate | rest_of_stack]} -> | |
{acc ++ [crate],rest_of_stack} | |
end) | |
end | |
end | |
""" | |
[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 | |
""" | |
|> Cargo.parse() | |
|> Cargo.part2() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
input = "tnmmpfmfzmmnsmsjmjjbvvhnhzzfmmgpmgpgbgnnwffjhffzqqmzzbnbssrqqrnnhsnngsszsqzszhzfhzfzwzfzrrmhmghgwhhjjqwqttwhttjllrtrtzzcfzfgzznfznfzfnnbddvmvzmmfsmfsmfffhlfldlqqrnrznnhmmgqqzhhmjhmhppqbpbbngnlldvvdqvvrtrdrtrnttnppfllrbbrprpnpdplpmllhwwddqpdprddzzfccqpcqpcpcbbdhdjdjwjcwcctdcttzgzmmscmsmdmttwhwzhhnjhnhlhvhlvlglpgpmmjmgmrgrddmwddjfftfwflfslffqtfqttpftppflfmmhvhvcvbvhbhggpbgbppvdpvpvfppbwwsnnhphllbdbnbvbmvvzffvsffdldmlmtmccnlnbnjbnjnhhbfhhgzzlwlfflzffdccggdcgcjjhffjfgfgcczjccvwcvvqgvvqvllqzqmqllhjjqnqggttsdddjgdjgjzzrgrfrbrssrgrgdgrgbbssmdsdfddsndnsdnsdnnmqqsspqqmrqqpmmsjmmszzqvqrvrzznnjdndtntfnttgtctqtwwnwswrrthrttsdttlhlvvdzzgqgttnppjpljplpgpvgvqqvppzmmqggtjgtgstslltjltjjgcjcmjmsshvvtppgmmlslqqshqshsllbggfpgffdsdgssncchctcwwtllgqlqblqlqvvmsvmmwnnzppqllsttgmttftvfvjjrzzswzzjvzjzljjchcshcscbbrdbrbcrrnvvtctntvtvbvjvqjqggsrspsprrbgghdghhmwwldldzdttrvrnrfftqtftrrdsszlzvvbtbffftzzrzqrrhjhghhwbhhsjsfsttdjdjnjhjmjpmplplrrdjdcdjdbjblllbqlqdlqlpqptppdhhqmqfqhqhchwwqjqfjqfqhqshsmswsbbvssdspdpsdssstntltrrgnnmttgmmsjjrlrnlrnrnwrwfwlfltlzllcjcmjcjpjhphcpcwppmvmjjzbzvbbfnfcflfddntddbmmmhnnsrnrrvdvnvcvwvcwvwrrqwqccqmmswmmjrjmmwjmjfjhwrtbjzdvlgrjmvzfmhcqsncvlhzzncjlbvcwrdwjmqjcnptqslvfzpsvltgzsvjdsjrppdrmqrbqwhddfhnftfblspsrhtdtjwdnhbcbtlwlvccsfscvczzrrqmwbwbdmwgzqntvflppqvppwrhnvtlsbzqglhsfdgssqzdtjdpwrrhbnbtwhhnmnlwfwlqffjjrndbpwwsvdrhddbjnnqzmtpvvtwbcpndjzlhcfrrdvmljswjzvmfqcdsgqwclqshwrmblszdvsnrpdgnllmlchzdjlrrpndmmgddjqgjqrhwfbwddqdfbvptrmzhtsqfsfswpnvmtswqprjhbzvntgrlzthhnqbtpplqpvcfnpgdtbhqbhflltbbtmmhcwztslmpznttmssclhmnbsbrwlblrbsdfmnpqbwwmsncvzmpqwhzjgcgdrzvglgdtswmstdhrprdjfmqtjlmplbjtzcgnrwpdvpfjjfwjfnnpmdtwtqsgfndngsbmcwjtglqwtfrclbczfcmjtgcwszhzrbcphrhwmhcwghjznzthnwpljjltdlvqtffsrbmwcsvrdmqqggbznnlzbbqtgspqvnjpbdhtzmgttrcwwszwpgdrcnfqtgrgqdrctlzwtdwqppbhnwgldnqltznnfpbfqtgmmwpcqnndbgmrrtgtvnmlfcwsldchjnnqfrhpzwtclrzftsqllgvpqbgmfjdhqjttwcvbpvfqsvhbhhtwnqnbgndbtzhcvgglbhghbzrbrmdllmgfgttqmhtdnwrpwllhnghrjctrbzrcpnjnctvmrlpjhftnfbczrjrnnbqplplcrbngbhvmmvcffmgvbhjzbhcmtwmwgmjmwjvvlqfldswpntjnsjvmdlbzqqlgbwspwvmnwtwjbczmwplrhmjgsppnmtwmvsfwnsgddgwqcvpftcpzrhpldnwmcjgtjmljjbcmjcqdbwczndnjnjgrmtjrqnnjndzqdqpcgdqptdbrqftnwrgqmrzrvsfmmmbpltlncvtgrjfjmvtgwqphczwjhdrdwtfvgztbhrndvpcbgfjfvmrrljwrvcrtdmtjndfnwgcnfrzgsnjpztbwwsbvqfnpjctgrhsflhnzbbsfqbnmtnvrmjzsbjfndvttpvpfjhqntflgbfnzcclcwmhbsgqfjdcgsvrhtstspfzgvgglgddqmclsmzgzgtncdsfmwdvtcsgwvbzjvclwppqdjgfcrcbzcwbdhrnssjbmnmfmwthdrnmlfhqlddwqrdhsdvdcsmcgjsgcmpnhlbnqftpdjswtmpbznlcrhtswgnmwjcdfmljdngzfsmlzjjnzmfzshmztdbdmcqwmlvcrzgpmbjqcghclwvdbrhgvwqchnndftnrtptmctdlhmfjvpzrpccddfpcdwmzqfhnsqzrvwblzfhcjdcjfctczwqrcbjnrpdcbbnsgnlvqqmnsfgsqschjlbzhhsrbvdbfrhvsgrlzwncgwpdbvmblgzbwbcbgqfwmdmgcrbbjfcvmqgztqpptdhwmvmsdqwplpgcjzgqzdrftzhqbltvhrmlrfffcgfpqzwrrbbtlsjgmtbjvtnmhwdpjptjwfwgjgvbfqwmflrrqzlzdcmtlnptdrpcpdnswcfscnndnrfbgwvvncdjgsdpbwptdtvrqlmrhmvvcwblhhzbjdpsbszhrftfbcgwhwrgglnjzqdhcqnvlhgqjhnddvrslhntssptsbhmqwwqqnbvfmcbgpvgjbrttnvlljdbtfplgmbwtcbcdtqdpqqdvhbmpmtszwpzblcfrtznhhtcljtdlhjdbnlhvwgjsmgvrslrfwnmzwlstpgltvrgnpdqztvfnvdhdtwwqdfsmtpbpdclsbnwcgjzchjcsjmvhbjshmjjlpgdzcgbmmchwmcsddsvhsnpqtcpnhqnbvwgwqhtjbqncgwwftnrzsbsjtvqmjzqvvncmncwflcfpcjqgdtbsmjzzsdjfvhnqbgjhmfgjghwscthbfmbndltbqzwpqtmrswvprpmgwqnqpfnmffrpdlpfqmhrthppzvzwbrtjvwvjndsqdlqtbpqwfcttggnjmcqqnmjwfhfjgcvlnmtlgbdvmctzlwbfgnflwtsflgnfbnfbhhdgjctzvvmrhdsmvmmtnqwtszmqcpsbrqrgjfrzctcbzmtdlhwjtfdqbtthdnqcrpwrhcrvjstbhpltvgmvpmvfjstgzjsgzprzcqzqztvvdcnrrqwrhddcrhhncdrlwzwqlnbbzcfmqtnwgfdscmrbwnbldlfrqchzdnlnmwncgrzdclnvcvplgwjsbzmbnnsdrsfhrlssvncnwmcrjdjbjpdtrrvlnbjvspfqbwdpcnnpjzfnmbhcdhlmdgbpvbzmfltzstnznfctcdzhbfsvnfbsjqzmwfllhtrsfghlrpjgrgzgchlwrdmqzbrncsvnwhfqmwjbnvjctzphcsftqsbmwntgvjqhhvwndvmfmjhhhmfdvrlhpvzmmhrbhbddqbdmgqqsvddsswmzqcjmvhztfqpchzpwhdshzjlmbmnsgzqhbnmrshwvtmgmgndtddpfwsjrrjdhncdhtlczdvlbvqplttnzrblthlcffdtfsdtpwzdgbldvnsttvpzmbgnqddrszftcpwrgmfzhjjvghpntmzcttcsnrjnfpqzqqqljhzlrpgwngllqjwnwfcsphqplgbzmfqfgbfsqpsrntszqbcqnhctsnbfshmlbwfflrwwsjwqwfqlgnftdwmctmclwjhjhbsspqldlshbmpbgrftpnbpsqldhrrbdqwfwvfhclrlfdjfmzgmptdjdcsplcspznfjrfhtsjndwpslrdgnllllwqjgznrhswfssdlvdpmwwgmstqbhfmdhtzvzzvhwzbrrvvsl" | |
## PART1 | |
input | |
|> String.graphemes() | |
|> Stream.chunk_every(4, 1) | |
|> Stream.map(&Enum.uniq/1) | |
|> Stream.with_index(1) | |
|> Stream.filter(&Enum.count(elem(&1, 0)) == 4) | |
|> Enum.take(1) | |
|> List.first() | |
|> elem(1) | |
|> Kernel.+(3) | |
|> IO.inspect(label: "part1") | |
## PART2 | |
# start of message marker | |
length = 14 | |
input | |
|> String.graphemes() | |
|> Stream.chunk_every(length, 1) | |
|> Stream.map(&Enum.uniq/1) | |
|> Stream.with_index(1) | |
|> Stream.filter(&Enum.count(elem(&1, 0)) == length) | |
|> Enum.take(1) | |
|> List.first() | |
|> elem(1) | |
|> Kernel.+(length - 1) | |
|> IO.inspect(label: "part2") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment