Example #1
0
        public bool TryGetNextNode(char nextValue, out PatternNode nextNode, bool allowCreate = false)
        {
            switch (nextValue)
            {
            case Constants.UnplantedCharacter:
                if (UnplantedNode == null && allowCreate)
                {
                    UnplantedNode = new PatternNode(Pattern + nextValue);
                }
                nextNode = UnplantedNode;
                break;

            case Constants.PlantedCharacter:
                if (PlantedNode == null && allowCreate)
                {
                    PlantedNode = new PatternNode(Pattern + nextValue);
                }
                nextNode = PlantedNode;
                break;

            default:
                nextNode = null;
                break;
            }

            return(nextNode != null);
        }
Example #2
0
        private static void ParseInput(string inputFilePath, out string initialState, out PatternNode rootPatternNode)
        {
            initialState    = string.Empty;
            rootPatternNode = new PatternNode(string.Empty);

            using (var reader = new StreamReader(inputFilePath))
            {
                initialState = reader.ReadLine()?.Substring(Constants.InitialStatePrefix.Length);

                while (!reader.EndOfStream)
                {
                    var noteString = reader.ReadLine();
                    if (!string.IsNullOrEmpty(noteString))
                    {
                        var patternResult = noteString.Split(Constants.PatternResultDelimeter);
                        var currentNode   = rootPatternNode;
                        foreach (var value in patternResult[0])
                        {
                            currentNode.TryGetNextNode(value, out currentNode, allowCreate: true);
                        }
                        currentNode.Result = patternResult[1][0];
                    }
                }
            }
        }
Example #3
0
        /// <summary>
        /// Simulates the spreading of plants in a row of pots from their initial
        /// state based on rules/patterns defined by the rootPatternNode trie
        /// after running for the given generationCount.
        /// </summary>
        /// <remarks>
        /// For large generationCounts where the state stabilizes, this function
        /// will shortcut the pattern matching generation processing.
        /// </remarks>
        private static long SimulatePlantSpread(string state, PatternNode rootPatternNode, long generationCount)
        {
            var  stateOriginIndex             = 0L;
            long?stableStateOriginIndexOffset = null;
            var  generation = 0;

            for (; generation < generationCount && stableStateOriginIndexOffset == null; generation++)
            {
                var newState             = new StringBuilder(state.Length);
                var newOriginIndexOffset = 0L;

                for (var index = -Constants.PatternOffset;
                     index <= state.Length + Constants.PatternOffset;
                     index++)
                {
                    var currentNode = rootPatternNode;
                    for (var offset = -Constants.PatternOffset; offset <= Constants.PatternOffset; offset++)
                    {
                        var offsetIndex    = index + offset;
                        var stateCharacter = (offsetIndex < 0 || offsetIndex >= state.Length)
                                                        ? '.'
                                                        : state[offsetIndex];

                        if (!currentNode.TryGetNextNode(stateCharacter, out currentNode))
                        {
                            break;
                        }
                    }

                    if (currentNode?.Result != null)
                    {
                        newState.Append(currentNode.Result);

                        if (newOriginIndexOffset == 0 &&
                            currentNode.Result == Constants.PlantedCharacter)
                        {
                            stateOriginIndex    += index;
                            newOriginIndexOffset = index;
                        }
                    }
                    else
                    {
                        newState.Append(Constants.UnplantedCharacter);
                    }
                }

                var tempState = newState.ToString().Trim(Constants.UnplantedCharacter);
                if (state == tempState)
                {
                    stableStateOriginIndexOffset = newOriginIndexOffset;
                }
                state = tempState;
            }

            if (stableStateOriginIndexOffset != null)
            {
                stateOriginIndex += (stableStateOriginIndexOffset.Value * (generationCount - generation));
            }

            var plantedPotNumberSum = 0L;

            for (var index = 0; index < state.Length; index++)
            {
                if (state[index] == Constants.PlantedCharacter)
                {
                    plantedPotNumberSum += (index + stateOriginIndex);
                }
            }

            return(plantedPotNumberSum);
        }