Skip to content

Instantly share code, notes, and snippets.

@karlis
Last active December 21, 2020 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karlis/9a99a4861f775e91a62f9851f609b574 to your computer and use it in GitHub Desktop.
Save karlis/9a99a4861f775e91a62f9851f609b574 to your computer and use it in GitHub Desktop.
struct Food {
let ingredient: Set<String>
let allergens: Set<String>
}
func parse(_ input: String) -> [Food] {
return input
.components(separatedBy: .newlines)
.map {
let parts = $0.components(separatedBy: " (contains ")
let ingredient = parts[0].components(separatedBy: .whitespaces)
let allergens = Array(parts[1].components(separatedBy: .whitespaces))
.map { String($0.dropLast()) }
return Food(ingredient: Set(ingredient), allergens: Set(allergens))
}
}
let parsed = parse(d21)
var all = parsed
.reduce(into: Set<String>()) { result, food in
result = result.union(food.allergens)
}
var ingredients = parsed
.reduce(into: Set<String>()) { result, food in
result = result.union(food.ingredient)
}
var dict: [String: String] = [:]
while !all.isEmpty {
for a in all {
let matching = parsed
.filter { $0.allergens.contains(a) }
.reduce(into: ingredients) { result, food in
result = result.intersection(food.ingredient)
}
if matching.count == 1, let ingredient = matching.first {
dict[a] = ingredient
ingredients.remove(ingredient)
all.remove(a)
}
}
}
let remaining = parsed
.map { $0.ingredient.intersection(ingredients).count }
.reduce(0, + )
print("Part 1:", remaining)
let list = dict
.sorted(by: { $0.0 < $1.0 })
.map { $0.value }
.joined(separator: ",")
print("Part 2:", list)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment