Advent of Code, Day 21

Day 21 of Advent of Code is here! This is another day I just couldn’t figure it out. I had just a hard time realizing how to even being. I understood the requirements, I could see the answer in my head, but couldn’t get coding. I was just stuck.

I reviewed many other’s code, saw that they worked, but didn’t understand why and what they were doing. I debugged, went line for line, and I see why it’s working, but not clear on how that fulfills the requirements. I started writing out the issue on paper, scribbling things out, and I just couldn’t get my head around what to do. Ugga..

I decided to just run my puzzle input through the below code to get me stars (10 days after, no points awarded).

Day 21: Allergen Assessment

Part I & II

I looked through a few different repos but found this one pretty clean and clear. Thanks lnguyenh for sharing!

// ref
const fs = require('fs');

const getInput = (fileName) => {
  let fileContent = fs.readFileSync(fileName, 'utf8');
  return fileContent.split('\n');

const INPUT_FILE = 'input.txt';
const foodLines = getInput(INPUT_FILE);

const foods = [];
let ingredients = new Set();
const allergens = new Map();
const ingredientsPart2 = new Map();

for (const line of foodLines) {
  const match = /^([(\w+) ]+) \(contains ([(\w+), ]+)\)$/.exec(line);
  const foodIngredients = match[1].split(' ');
  const foodAllergens = match[2] ? match[2].split(', ') : [];

  // Populate an array of foods, storing for each food its list of ingredients
  foods.push({ ingredients: foodIngredients });

  // Populate a set of unique ingredients
  ingredients = new Set([...ingredients, ...foodIngredients]);

  // Populate a map containing for each allergen a list of possible ingredients
  // that can contain it
  for (const allergen of foodAllergens) {
    if (allergens.has(allergen)) {
      const ingredientIntersection = allergens
        .filter((a) => foodIngredients.includes(a));
      allergens.set(allergen, ingredientIntersection);
    } else {
      allergens.set(allergen, foodIngredients);

  // Populate a map containing for each ingredient a list of possible allergens
  // it can contain
  for (const ingredient of foodIngredients) {
    if (ingredientsPart2.has(ingredient)) {
      const allergenSet = new Set([
      ingredientsPart2.set(ingredient, allergenSet);
    } else {
      ingredientsPart2.set(ingredient, new Set(foodAllergens));

const cleanIngredients = new Set(ingredients);
for (const [__, ingredientList] of allergens) {
  ingredientList.forEach((i) => cleanIngredients.delete(i));
let resultPart1 = 0;
for (const ingredient of cleanIngredients) {
  for (const food of foods) {
    if (food.ingredients.includes(ingredient)) resultPart1++;
console.log('part 1: ' + resultPart1);

for (const [allergen, ingredientSet] of allergens) {
    new Set([...ingredientSet].filter((i) => !cleanIngredients.has(i)))
const cleanedAllergens = [];
while (allergens.size > 0) {
  for (const [allergen, ingredientSet] of allergens) {
    if (ingredientSet.size === 1) {
      const ingredient = [...ingredientSet][0];
      for (const [__, iSet] of allergens) {
cleanedAllergens.sort((a, b) => a.allergen.localeCompare(b.allergen));
const resultPart2 = => a.ingredient).join(',');
console.log('part 2: ' + resultPart2);

Do you get it?

As I mentioned, this one just stumped me. I even asked on the AoC subreddit, I hope to understand it someday :D

How did it go for you?

How did you find the answer on your own? How did you do it? Anything stump you? I’d love to hear how you did! Please comment below! I have also loaded up just the challenge and code from this and my other days on github, you can follow along there too: pretty Git pages or the code in the repo.

Series Navigation

Leave a Reply

Up ↑

%d bloggers like this: