예제 #1
0
        private static int NumberOfShortestCombinations(int[] list, int initialGoal)
        {
            var memo    = new SimpleMemo <ulong>();
            var lengths = new SafeDictionary <int, int>();

            Explore(list.Length, 0, initialGoal);
            var shortestCombinations = lengths.OrderBy(x => x.Key).First().Value;

            return(shortestCombinations);

            void Explore(int size, uint pickmask, int goal)
            {
                if (goal == 0)
                {
                    var len = pickmask.NumberOfSetBits();
                    lengths[len]++;
                    return;
                }

                if (goal < 0 || size == 0)
                {
                    return;
                }

                if (memo.IsSeenBefore((ulong)size << 32 | pickmask))
                {
                    return;
                }

                // For skipped item, pass 0 into the bit-mask (ie do nothing); for used item pass 1.
                Explore(size - 1, pickmask << 1, goal);
                Explore(size - 1, (pickmask << 1) + 1, goal - list[size - 1]);
            }
        }
예제 #2
0
        protected override string Part2(string[] input)
        {
            var ids = input;

            // Instead of doing the trivial N^2 set of comparisons (where each comparison
            // would even need to step through all chars to find just one mismatch) do this:
            // For every string, remember n versions of it with each letter, one at a time,
            // swapped out with a dot. If we ever come across a similar string then we've
            // found the single-letter-mismatch. The result is the string except that dot
            // at the mismatched position - very nice.
            var seen = new SimpleMemo <string>();

            foreach (var id in ids)
            {
                var letters = id.ToCharArray();
                for (var i = 0; i < letters.Length; i++)
                {
                    var tmp = letters[i];
                    letters[i] = '.';
                    var s = new string(letters);
                    if (seen.IsSeenBefore(s))
                    {
                        // We found the mismatch
                        return(s.Replace(".", ""));
                    }
                    letters[i] = tmp;
                }
            }
            throw new Exception("Not found");
        }
예제 #3
0
        private static int FindFirstCycle(int[] banks)
        {
            var memo  = new SimpleMemo <ulong>();
            var cycle = 0;

            do
            {
                Redistribute(banks);
                cycle++;
            } while (!memo.IsSeenBefore(Hashing.KnuthHash(banks)));
            return(cycle);
        }
예제 #4
0
        protected override int Part2(string[] input)
        {
            var deltas = input.Select(int.Parse).ToArray();

            // Loop deltas to build frequency, until one is reached we've
            // seen before. Using while(true) + for() is faster than %.
            var seen = new SimpleMemo <int>();
            var freq = 0;

            while (true)
            {
                foreach (var d in deltas)
                {
                    freq += d;
                    if (seen.IsSeenBefore(freq))
                    {
                        return(freq);
                    }
                }
            }
        }
예제 #5
0
        protected override int Part1(string[] input)
        {
            var claims = ReadClaims(input);

            // Fastest way seem to be to simple hash memo-tables that register
            // every square and therefore can count the first time a square is
            // seen. It's faster than counting up all the overlappings and then
            // searching for those with >1 overlap.
            var once     = new SimpleMemo <int>();
            var twice    = new SimpleMemo <int>();
            var overlaps = 0;

            foreach (var pos in claims.SelectMany(c => c.Squares()))
            {
                if (once.IsSeenBefore(pos) && !twice.IsSeenBefore(pos))
                {
                    overlaps++;
                }
            }

            return(overlaps);
        }