/// <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)); }
public LineNumber(int index, int value, LineNumber parent = null) { Index = index; Value = value; SubTotal = value + (parent?.SubTotal ?? 0); Parent = parent; }
public bool MoveNext() { if (++index >= items.Count) { return(false); } Current = items[index]; return(true); }
/// <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); }
public LineIterator(IReadOnlyList <LineNumber> source) { items = source; index = 0; Current = items[0]; }