-
Notifications
You must be signed in to change notification settings - Fork 0
/
day21.R
152 lines (126 loc) · 4.04 KB
/
day21.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
library(magrittr)
test_input <- c(
"mxmxvkd kfcds sqjhc nhms (contains dairy, fish)",
"trh fvjkl sbzzf mxmxvkd (contains dairy)",
"sqjhc fvjkl (contains soy)",
"sqjhc mxmxvkd sbzzf (contains fish)"
)
real_input <- readLines("./inputs/day21-input.txt")
#- LOGIC ----------------------------------------------------------------------#
#' returns list of objects with
#' ingredients: vector of ingredients
#' allergens: vector of allergens
parse_input <- function(input) {
input %>%
Map(f = function(x) {
ingredients <- x %>%
gregexpr(pattern = "^[a-z ]+") %>%
regmatches(x = x) %>%
unlist() %>%
trimws() %>%
strsplit(split = " ") %>%
unlist()
allergens <-
x %>%
gregexpr(pattern = "\\(contains [a-z]+(, [a-z]+)*\\)$") %>%
regmatches(x = x) %>%
unlist() %>%
substring(11, nchar(.)-1) %>%
strsplit(split = ", ") %>%
unlist()
list(ingredients = ingredients, allergens = allergens)
})
}
#' create a list of allergens that contain list of foods
foods_by_allergens <- function(foods) {
foods %>%
Reduce(f = function(z, food) {
food$allergens %>% Reduce(f = function(z, allergen) {
z[[allergen]] <- c(z[[allergen]], list(food$ingredients))
z
}, init = z)
}, init = list())
}
#' find best allergen matches
find_allergen_matches <- function(foods_by_allergens) {
allergens_sorted <-
foods_by_allergens %>%
Map(f = length) %>%
unlist() %>%
sort() %>%
rev() %>%
names()
matches <-
allergens_sorted %>%
Map(f = function(x) foods_by_allergens[[x]] %>% Reduce(f = intersect))
matches
}
#' remove ambiguous terms from list
#' by starting on list item referring to 1 element and removing that element
#' from other list items
#'
disambiguate_matches <- function(matches) {
len <- Map(matches, f = function(x) x %>% unique() %>% length()) %>% unlist()
# if we have single definition term
if (any (len == 1)) {
idx <- which(len == 1)[1]
# element name and definition
nam <- names(matches)[idx]
def <- matches[[idx]]
# exclude definition from a list of remaining terms
new_matches <-
# explicitly exclude the element with single match
matches[-idx] %>%
# exclude definition from remaining list of terms
Map(f = function(x) x[x != def])
# concatenate list of a single term
# with function call for further disambiguation
c(matches[idx], disambiguate_matches(new_matches))
} else {
matches
}
}
#- SOLUTION PART 1 ------------------------------------------------------------#
day21_part1_solution <- function(input) {
foods <- input %>% parse_input()
allergic_ingredients <-
foods %>%
foods_by_allergens() %>%
find_allergen_matches() %>%
disambiguate_matches()
allergic_ingredients_plain <- allergic_ingredients %>% Reduce(f = c)
answer <-
foods %>%
Reduce(f = function(z, food) {
bool_allergic = (food$ingredients %in% allergic_ingredients_plain)
z + sum(bool_allergic == FALSE)
}, init = 0)
answer
}
test_output_part1 <- 5
test_result <- day21_part1_solution(test_input)
print(paste(
"test result:", test_result,
"valid:", test_result == test_output_part1))
real_result_part1 <- day21_part1_solution(real_input)
print(format(real_result_part1, scientific = FALSE))
#- SOLUTION PART 2 ------------------------------------------------------------#
day21_part2_solution <- function(input) {
foods <- input %>% parse_input()
allergic_ingredients <-
foods %>%
foods_by_allergens() %>%
find_allergen_matches() %>%
disambiguate_matches()
answer <-
allergic_ingredients[names(allergic_ingredients) %>% sort] %>%
Reduce(f = function(z, x) paste(z, x, sep = ","))
answer
}
test_output_part2 <- "mxmxvkd,sqjhc,fvjkl"
test_result <- day21_part2_solution(test_input)
print(paste(
"test result:", test_result,
"valid:", test_result == test_output_part2))
real_result_part2 <- day21_part2_solution(real_input)
print(format(real_result_part2, scientific = FALSE))