Skip to content

Instantly share code, notes, and snippets.

@jswanner
Forked from faried/day2parser.ex
Last active December 3, 2023 00:17
Show Gist options
  • Save jswanner/20691a8cab278907d155edf2c0ead0ae to your computer and use it in GitHub Desktop.
Save jswanner/20691a8cab278907d155edf2c0ead0ae to your computer and use it in GitHub Desktop.
AoC 2023 Day 2 NimbleParsec Parser
defmodule Parser do
import NimbleParsec
game_id = ignore(string("Game ")) |> integer(min: 1, max: 4) |> unwrap_and_tag(:id)
red = replace(string("red"), :red)
green = replace(string("green"), :green)
blue = replace(string("blue"), :blue)
color = choice([red, green, blue])
cube_separator = optional(string(", "))
cube =
integer(min: 1, max: 4)
|> ignore(string(" "))
|> concat(color)
|> ignore(optional(cube_separator))
round_separator = optional(string("; "))
round =
times(cube, min: 1)
|> ignore(round_separator)
|> reduce(:reduce_round)
rounds = times(round, min: 1) |> tag(:rounds)
game_separator = ascii_string([?\n], 1)
game =
game_id
|> ignore(string(": "))
|> concat(rounds)
|> ignore(game_separator)
|> wrap()
|> map({Map, :new, []})
games = times(game, min: 1)
defparsec(:parse, games |> eos())
defp reduce_round(cubes) do
cubes
|> Enum.chunk_every(2)
|> Enum.reduce(%{}, fn [count, color], acc ->
Map.update(acc, color, count, &(&1 + count))
end)
end
end
Parser.parse("""
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
""")
{:ok,
[
%{id: 1, rounds: [%{red: 4, blue: 3}, %{green: 2, red: 1, blue: 6}, %{green: 2}]},
%{id: 2, rounds: [%{green: 2, blue: 1}, %{green: 3, red: 1, blue: 4}, %{green: 1, blue: 1}]},
%{
id: 3,
rounds: [%{green: 8, red: 20, blue: 6}, %{green: 13, red: 4, blue: 5}, %{green: 5, red: 1}]
},
%{
id: 4,
rounds: [%{green: 1, red: 3, blue: 6}, %{green: 3, red: 6}, %{green: 3, red: 14, blue: 15}]
},
%{id: 5, rounds: [%{green: 3, red: 6, blue: 1}, %{green: 2, red: 1, blue: 2}]}
], "", %{}, {6, 321}, 321}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment