Beispiel #1
0
        /// <summary>
        /// Implements search algorithm;
        /// </summary>
        /// <remarks>
        /// From the given input we collect only numbers that can form a valid path;
        /// each such number is stored together with calculated subtotal and
        /// is linked to a valid (parent) number from previous line;
        /// so when the last number of the input is traversed (i.e. no more input data),
        /// we will just need to choose such number selected in the last line number,
        /// that has a maximum subtotal and follow links to reach the top element,
        /// to restore all the path.
        /// </remarks>
        private Result Solve()
        {
            var root   = LineNumber.AsRoot(_numbers.Current);
            var parity = root.Value.GetParity();

            var lineNumber  = 1;
            var pathEndings = new List <LineNumber>(1)
            {
                root
            };

            while (_numbers.MoveNext())
            {
                parity = parity.InvertParity();

                pathEndings = FindNumbersInLine(++lineNumber, parity, pathEndings);

                if (pathEndings.Count == 0)
                {
                    throw new ArgumentException("The given sequence of numbers doesn't contain any valid path!");
                }
            }

            return(GetResult(pathEndings, lineNumber));
        }
Beispiel #2
0
 public LineNumber(int index, int value, LineNumber parent = null)
 {
     Index    = index;
     Value    = value;
     SubTotal = value + (parent?.SubTotal ?? 0);
     Parent   = parent;
 }
Beispiel #3
0
        public bool MoveNext()
        {
            if (++index >= items.Count)
            {
                return(false);
            }

            Current = items[index];
            return(true);
        }
Beispiel #4
0
        /// <summary>
        /// Searches for related number in previous line by given index of a number in current line
        /// </summary>
        /// <remarks>
        /// Line j-1:    N(i-1) N(i)
        /// Line  j :        N(i)
        ///
        /// here N(k) denotes some number with index k,
        ///
        /// a number N(i) from line j IS in relation only with a number N(i-1) or N(i) from line j-1,
        /// (a number N(0) as well as N(j) has only one relation, all other have two relations)
        /// </remarks>
        /// <returns>True, if was able to locate such number</returns>
        private bool TryFindRelatedNumber(int itemIndex, ref LineIterator iterator, out LineNumber related)
        {
            related = null;

            if (!iterator.CanIterate)
            {
                return(false);
            }

            do
            {
                // take a number from previous line, that is not yet linked
                var current      = iterator.Current;
                var currentIndex = current.Index;

                if (itemIndex < currentIndex)
                {
                    return(false);
                }

                if (itemIndex - 1 == currentIndex)
                {
                    // case when for a number N(i) in line j (i == itemIndex)
                    // found number N(i-1) in line j-1
                    related = iterator.Next;

                    // before return we need to check, if N(i) in line j-1 is also selected as valid;
                    // if both exists, then we choose for relation one, having bigger subtotal
                    var isNextRelated =
                        related != null &&
                        related.Index == itemIndex &&
                        related.SubTotal >= current.SubTotal;

                    if (!isNextRelated)
                    {
                        related = current;
                    }

                    return(true);
                }

                if (itemIndex == currentIndex)
                {
                    // case when for a number N(i) in line j (i == itemIndex)
                    // found number N(i) in line j-1,
                    // and if we are here, than N(i-1) is not selected as valid
                    related = current;
                    return(true);
                }
            } while (iterator.MoveNext());

            return(false);
        }
Beispiel #5
0
 public LineIterator(IReadOnlyList <LineNumber> source)
 {
     items   = source;
     index   = 0;
     Current = items[0];
 }