Created
December 21, 2020 09:36
-
-
Save object/5caffafe05637d7618b23bd77f366116 to your computer and use it in GitHub Desktop.
AdventOfCode 2020, December 21
This file contains hidden or 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
| 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