/// <summary> /// Looks for valid (according given parity) numbers and tries to link them with already found numbers in previous line /// </summary> /// <param name="lineNumber">Denotes current line number (also servses as a count of numbers in the line)</param> /// <param name="validParity">Parity that numbers have to match</param> /// <param name="previousLineNumbers">valid numbers from previous line</param> /// <returns></returns> private List <LineNumber> FindNumbersInLine(int lineNumber, Parity validParity, List <LineNumber> previousLineNumbers) { var iterator = new LineIterator(previousLineNumbers); var expectedCount = 2 * previousLineNumbers.Count; var pathEndings = new List <LineNumber>(expectedCount > lineNumber ? lineNumber : expectedCount); var itemIndex = 0; LineNumber related; do { // read a number from the input var number = _numbers.Current; // validate the number and try to link to one from previous line if (number.GetParity() == validParity && TryFindRelatedNumber(itemIndex, ref iterator, out related)) { pathEndings.Add(new LineNumber(itemIndex, number, related)); } // when all numbers of a line are traversed, we return sub-result if (++itemIndex == lineNumber) { return(pathEndings); } }while (_numbers.MoveNext()); // error: the line does not contain a proper count of numbers throw new ArgumentException("Input doesn't contain all the numbers to complete the task!"); }
/// <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); }