Skip to content

Instantly share code, notes, and snippets.

@object
Created December 21, 2020 09:36
Show Gist options
  • Select an option

  • Save object/5caffafe05637d7618b23bd77f366116 to your computer and use it in GitHub Desktop.

Select an option

Save object/5caffafe05637d7618b23bd77f366116 to your computer and use it in GitHub Desktop.
AdventOfCode 2020, December 21
module TwentyOne =
open System
open System.IO
let parseFood (line : string) =
let splitter = " (contains "
let splitIndex = line.IndexOf splitter
let ingredients =
line.Substring(0, splitIndex).Split(' ') |> Set
let allergens =
line.Substring(splitIndex+splitter.Length, line.Length-1-splitIndex-splitter.Length)
.Split([|' '; ','|], StringSplitOptions.RemoveEmptyEntries) |> Set
ingredients, allergens
let foods, allergens =
File.ReadAllLines "Data/input21.txt"
|> Array.fold ( fun (foods, allergens) line ->
let i,a = parseFood line
((i,a) :: foods, allergens |> Set.union a)) (List.empty, Set.empty)
let ingredients =
foods
|> List.map fst
|> Set.ofList
|> Set.unionMany
let allergensByFood =
allergens
|> Set.fold (fun acc a ->
acc |> Map.add a (foods |> List.filter (fun (i,als) -> als |> Set.contains a) |> List.map fst)) Map.empty
let allergensByIngredient =
allergensByFood
|> Map.map (fun _ ings -> ings |> Set.intersectMany)
let ingredientsWithAllergens =
allergensByIngredient
|> Map.toList
|> List.map snd
|> Set.ofList
|> Set.unionMany
let ingredientsWithoutAllergens =
Set.difference ingredients ingredientsWithAllergens
// Part One
foods
|> List.map fst
|> List.map (Set.intersect ingredientsWithoutAllergens >> Set.count)
|> List.sum
// Part Two
let rec findAllergens result algs =
match algs with
| [] -> result
| (alg, ingrs) :: algs ->
match ingrs with
| [ingr] ->
let algs =
algs
|> List.map (fun (x,y) -> (x, y |> List.filter (fun z -> z <> ingr)))
|> List.sortBy (fun (x,y) -> List.length y)
findAllergens ((alg, ingr) :: result) algs
| _ -> findAllergens result algs
let algs =
allergensByIngredient
|> Map.map (fun _ v -> v |> Set.toList)
|> Map.toList
|> List.sortBy (fun (x,y) -> List.length y)
findAllergens [] algs
|> List.sortBy fst
|> List.map snd
|> fun x -> String.Join (",", x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment