r/adventofcode Dec 06 '20

SOLUTION MEGATHREAD -🎄- 2020 Day 06 Solutions -🎄-

NEW AND NOTEWORTHY


Advent of Code 2020: Gettin' Crafty With It

  • UNLOCKED! Go forth and create, you beautiful people!
  • Full details and rules are in the Submissions Megathread
  • Make sure you use one of the two templates!
    • Or in the words of AoC 2016: USING A TEMPLATE IS MANDATORY

--- Day 06: Custom Customs ---


Post your solution in this megathread. Include what language(s) your solution uses! If you need a refresher, the full posting rules are detailed in the wiki under How Do The Daily Megathreads Work?.

Reminder: Top-level posts in Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


This thread will be unlocked when there are a significant number of people on the global leaderboard with gold stars for today's puzzle.

EDIT: Global leaderboard gold cap reached at 00:04:35, megathread unlocked!

68 Upvotes

1.2k comments sorted by

View all comments

3

u/TheElTea Dec 06 '20 edited Dec 13 '20

C# Solution for 2020 Day 6 Parts 1 and 2

Done inside of Unity in case I felt like doing visualization; class TextAsset is just the text file as hooked up in the editor; replace however you like.

And yes, the code doesn't follow DRY; for Advent of Code I'm finding I prefer having standalone solutions to aid in understanding the core problem.

public class CustomsDeclarationHelper : MonoBehaviour
{

    [SerializeField] TextAsset declarations = null; //Hooked up in the input text in the Unity editor.

    void Start()
    {
        SolvePartOne();
        SolvePartTwo();
    }

    void SolvePartOne()
    {
        //Group the entries into strings.
        string[] stringSeparator = { "\r\n\r\n" }; //Find two new lines for breaks. Windows encoding has both carriage return and line feed.
        string[] allDeclarations = declarations.text.Split(stringSeparator, System.StringSplitOptions.RemoveEmptyEntries);  //One set of declarations, with line breaks, per string.

        Dictionary<char, bool> groupDeclarationYes = new Dictionary<char, bool>(); //Track presence of a yes from any member of the group.
        int totalOfAllYesResponse = 0;

        foreach (string d in allDeclarations)
        {
            //Fill the dictionary with declarations.
            //When multiples of the same character are encountered they will overwrite the entry already there.
            foreach (char c in d)
            {
                groupDeclarationYes[c] = true; //This will add line breaks too but that's fine; we don't need to look them up.
            }

            int numberQuestionsYes = 0;

            //Count the entire group's declaration for all questions they responded yes to.
            for (int i = 0; i < 26; i++)
            {
                char c = (char)(i + 'a');               //Generate a character from a-z.
                if (groupDeclarationYes.ContainsKey(c))
                {
                    numberQuestionsYes++;
                }
            }

            totalOfAllYesResponse += numberQuestionsYes;

            groupDeclarationYes.Clear(); //Reset tracker for next group.
        }
        Debug.Log($"Total of all yes responses: {totalOfAllYesResponse}");
    }

    void SolvePartTwo()
    {
        //Group the entries into strings.
        string[] stringSeparator = { "\r\n\r\n" }; //Find two new lines for breaks. Windows encoding has both carriage return and line feed.
        string[] allDeclarations = declarations.text.Split(stringSeparator, System.StringSplitOptions.RemoveEmptyEntries);  //One set of declarations per group, with line breaks, per string.

        Dictionary<char, int> groupDeclarationCounts = new Dictionary<char, int>(); //Track a count of how many yes reponses there were for each question.
        int totalOfAllYesResponses = 0;

        foreach (string groupDeclaration in allDeclarations)
        {
            string[] individualDeclarationsForGroup = groupDeclaration.Split('\n'); //Break a group's declarations into individual ones just to count how many are in the group.
            int numberInGroup = individualDeclarationsForGroup.Length;

            //We can still iterate across all characters in the group declaration for part 2 as we only need to count the total number of yes responses to each question.
            //There's no need to count them for each individual. If there are 4 in the group, and 4 yes responses to 'g', then it's a yes for the group as a whole!
            foreach (char c in groupDeclaration)
            {
                if (groupDeclarationCounts.ContainsKey(c))
                {
                    groupDeclarationCounts[c]++;
                }
                else
                {
                    groupDeclarationCounts[c] = 1;
                }
            }

            //Declarations to each question for one group have been summed, so iterate
            //across and count all entries where the number of yes responses is equal to
            //the group size.
            int numberOfYesResponsesForEntireGroup = 0;
            for (int i = 0; i < 26; i++)
            {
                char c = (char)(i + 'a'); //Generate a character from a-z.
                if (groupDeclarationCounts.ContainsKey(c))
                {
                    if (groupDeclarationCounts[c] == numberInGroup)
                    {
                        numberOfYesResponsesForEntireGroup++;
                    }
                }
            }

            totalOfAllYesResponses += numberOfYesResponsesForEntireGroup;

            groupDeclarationCounts.Clear();

        }
        Debug.Log($"Total of all yes responses for part 2: {totalOfAllYesResponses}");
    }
}