private static void AddDeadEnd(List <StringBuilder> triedTheseChains, AdapterChain testChain)
        {
            triedTheseChains.Add(new StringBuilder());
            var idx = triedTheseChains.Count - 1;

            for (int i = 0; i < testChain.Chain.Count; i++)
            {
                triedTheseChains[idx].Append(testChain.Chain[i].ToString());
            }
            return;
        }
        private static void PrintChainToConsole(AdapterChain candidateChain)
        {
            Console.WriteLine($"Item count: {candidateChain.Chain.Count}");

            // print chain
            for (int i = 0; i < candidateChain.Chain.Count; i++)
            {
                if (i < candidateChain.Chain.Count - 1)
                {
                    Console.Write($"{candidateChain.Chain[i]},");
                }
                else
                {
                    Console.WriteLine($"{candidateChain.Chain[i]}");
                }
            }
        }
        private static void FindDistribution(AdapterChain candidateChain)
        {
            Dictionary <int, int> dist = new Dictionary <int, int> {
                { 1, 0 }, { 2, 0 }, { 3, 0 }
            };

            var d = 0;
            var c = 0; // for debug count items incl in distro should equal #items in chain-1 + 1 additional item the device itself

            // for each item find joltage diff between it and its previous item
            for (int i = 1; i < candidateChain.Chain.Count; i++)
            {
                c += 1;
                d  = candidateChain.Chain[i] - candidateChain.Chain[i - 1];
                if (d > 3 || d < 1)
                {
                    Console.WriteLine("Error");
                }
                else
                {
                    dist[d] = dist[d] + 1;
                }
            }
            c      += 1;
            dist[3] = dist[3] + 1;  // add diff between device and last adapter in the chain.  it's always +3

            //print joltage distro
            foreach (KeyValuePair <int, int> entry in dist)
            {
                Console.WriteLine($"{entry.Key.ToString()}, diff {entry.Value.ToString()}");
            }

            // print product of +1 count by +3 count
            Console.WriteLine($"Product of +1 count x +3 count is {dist[1]} * {dist[3]} = {dist[1]*dist[3]}.  Items in distro is {c}");
            return;
        }
        static void Main(string[] args)
        {
            // Advent of Code 2020  Day 10 Puzzle Adapter Array   https://adventofcode.com
            // 12/10/2020

            Console.WriteLine(@"--- Day 10: Adapter Array ---");

            var rf       = new ReadPuzzleInputFile();
            var adapters = rf.ReadFile();

            // adapters is a list of integers.  Each integer represents an adapter's jolts.
            //No other info is provided and adapters are known only by their postion or index in this list.

            Console.WriteLine($"Read input file. {rf.LinesRead} lines read in.");

            AdapterChain candidateChain;

            List <StringBuilder> deadEndChains = new List <StringBuilder>();

            adapters.Sort();  // sort the adapter list ascending


            // algorithm:  Brute Force!
            // check everything and build up a list of valid chains until we find a complete chain from wall to device.
            candidateChain = new AdapterChain();
            candidateChain.Chain.Add(0); // always start at 0

            bool       testComplete = false;
            int        thisAdapter  = 0; // start at the wall always, add index of this adapter in list of adapters
            bool       foundChain   = false;
            List <int> next3;

            // build a chain one element at a time
            do
            {
                thisAdapter += 1;

                next3 = FindNext3(adapters, thisAdapter);  // List<int> with 0 to 3

                next3.Sort();

                // try to add another item
                var fail = false;  //optimistic
                if (next3.Count > 0)
                {
                    var addThisItem = 0;
                    int i;
                    for (i = 0; i < next3.Count; i++)
                    {
                        var tmpChain = new List <int>();
                        for (int j = 0; j < candidateChain.Chain.Count; j++)
                        {
                            tmpChain.Add(candidateChain.Chain[j]);
                        }
                        tmpChain.Add(next3[i]);
                        if (IsThisANewChain(deadEndChains, tmpChain))
                        {
                            addThisItem = i;
                            break;
                        }
                    }
                    if (i < next3.Count)
                    {
                        candidateChain.Chain.Add(next3[addThisItem]);
                    }
                    else
                    {
                        fail = true;
                    }
                }

                if (fail)
                {
                    // add this test case to list of those tried.
                    AddDeadEnd(deadEndChains, candidateChain);
                    testComplete = true;
                }
            } while (!testComplete && thisAdapter < adapters.Count);

            if (candidateChain.Chain.Count == adapters.Count + 1)  // candidate chain will include wall +1 for items count.
            {
                foundChain = true;
            }

            if (foundChain)
            {
                Console.WriteLine($"Found chain");

                PrintChainToConsole(candidateChain);

                FindDistribution(candidateChain);
            }
            else
            {
                Console.WriteLine($"Did not find chain");
            }



            ///////////////////////////////////////////////
            // part 2:  how many valid combos are there?
            Console.WriteLine($"\nPart 2.");

            // In part 2 adapters can be skipped over and not used. Goal is count total number of combos instead of using all the adapters.

            // algorthm:  at each node in the chain there are only so many valid adapters to choose from.
            //  record how many are available.

            adapters.Sort();  // sort the adapter list ascending

            // when a complete set of pathways from an adapter to end of list is found keep track of it here
            Dictionary <int, double> completePathsCount = new Dictionary <int, double>();

            // start with highest rated item.
            // +1 for highest rated item.

            Accumulator count = new Accumulator();

            Accumulator recursionCount = new Accumulator();

            adapters.Insert(0, 0); // add the wall outlet

            count.AddDataValue(FindPaths(adapters, 0, completePathsCount, recursionCount));

            if (count.Total != 0)
            {
                Console.WriteLine($"Count of valid adapter combos is {count.Total}");
                Console.WriteLine($"Count of recursive calls to find all paths is {recursionCount.Total}");
            }
            else
            {
                Console.WriteLine($"Count of valid adapter combos is 0 - no valid path thru this list.   ???");
            }


            Console.WriteLine("Done.");
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }