/// <summary> /// If a segment has its first sequence in its entirety touching its first side, then terminate it with a False. /// Vice versa for the last sequence. /// </summary> /// <param name="segment"></param> /// <returns></returns> public override bool Execute(Segment segment) { if (!segment.HasBlanks) { return(false); } if (segment.TrueCount == 0) { return(false); } KnownStartAndEndFalses falseStartAndEndCounts = base.RemoveStartAndEndFalsesFromSegment(segment); bool cellsChanged = false; // If the sequence is small enough to fit inside and needs to be terminated somewhere, Sequence firstSequence = segment.MustHaves.First(); if (firstSequence.Count < segment.Length) { // And if it's touching the start in it's entirety if (segment.Cells.Take(firstSequence.Count).Count(cell => cell.IsTrue) == firstSequence.Count && segment.Cells[firstSequence.Count].IsUnMarked) { // Then terminate it if (segment.Cells[firstSequence.Count].MarkFalse() && !cellsChanged) { cellsChanged = true; } } } // Last Sequence lastSequence = segment.MustHaves.Last(); if (lastSequence.Count < segment.Length) { // And if it's touching the end in it's entirety if (segment.Cells.Skip(segment.Length - lastSequence.Count).Take(lastSequence.Count).Count(cell => cell.IsTrue) == lastSequence.Count && segment.Cells[lastSequence.Count].IsUnMarked) { // Then terminate it if (segment.Cells[segment.Length - lastSequence.Count - 1].MarkFalse() && !cellsChanged) { cellsChanged = true; } } } base.RecombineFalseStartsAndEndsWithSegment(falseStartAndEndCounts, segment); return(cellsChanged); }
/// <summary> /// If we have a single sequence and we know at least 1 part of it, mark anything /// out of possible bounds as False /// </summary> /// <param name="segment"></param> /// <returns></returns> public override bool Execute(Segment segment) { if (!segment.HasBlanks) { return(false); } KnownStartAndEndFalses falseStartAndEndCounts = base.RemoveStartAndEndFalsesFromSegment(segment); bool cellsChanged = false; // If there's exactly 1 sequence if (segment.MustHaves.Count == 1) { Sequence theSequence = segment.MustHaves.First(); // But there's already more than 1 known True cell, IEnumerable <Cell> trueCells = segment.Cells.Where(cell => cell.IsTrue); if (trueCells.Any()) { // Find the known bounds int minimumTrue = trueCells.Min(cell => cell.IndexIn(segment)); int maximumTrue = trueCells.Max(cell => cell.IndexIn(segment)); // Exclude known bounds below the minimum and above the maxium for (int i = 0; i < maximumTrue + 1 - theSequence.Count; i++) { if (segment.Cells[i].IsUnMarked) { if (segment.Cells[i].MarkFalse() && !cellsChanged) { cellsChanged = true; } } } for (int i = segment.Length - 1; i > minimumTrue - 1 + theSequence.Count; i--) { if (segment.Cells[i].IsUnMarked) { if (segment.Cells[i].MarkFalse() && !cellsChanged) { cellsChanged = true; } } } } } base.RecombineFalseStartsAndEndsWithSegment(falseStartAndEndCounts, segment); return(cellsChanged); }
/// <summary> /// After a cap-trim, if start or end is [unmarked][false] and [unmarked.count] < sequences.first.count, then it can't fit, so mark [unmarked] as falses /// </summary> /// <param name="segment"></param> /// <returns></returns> public override bool Execute(Segment segment) { if (!segment.HasBlanks) { return(false); } KnownStartAndEndFalses falseStartAndEndCounts = base.RemoveStartAndEndFalsesFromSegment(segment); bool cellsChanged = false; // Start int startingUnmarked = segment.Cells.TakeWhile(cell => cell.IsUnMarked).Count(); if (startingUnmarked < segment.MustHaves.First().Count&& segment.Cells.Skip(startingUnmarked).First().IsFalse) { foreach (Cell cell in segment.Cells.Take(startingUnmarked)) { if (cell.MarkFalse() && !cellsChanged) { cellsChanged = true; } } } // End segment.Cells.Reverse(); segment.MustHaves.Reverse(); startingUnmarked = segment.Cells.TakeWhile(cell => cell.IsUnMarked).Count(); if (startingUnmarked < segment.MustHaves.First().Count&& segment.Cells.Skip(startingUnmarked).First().IsFalse) { foreach (Cell cell in segment.Cells.Take(startingUnmarked)) { if (cell.MarkFalse() && !cellsChanged) { cellsChanged = true; } } } segment.Cells.Reverse(); segment.MustHaves.Reverse(); base.RecombineFalseStartsAndEndsWithSegment(falseStartAndEndCounts, segment); return(cellsChanged); }
/// <summary> /// If the sequences and their spacing adds to segment length, then just draw it out, /// separated by Falses /// </summary> /// <param name="segment"></param> /// <returns></returns> public override bool Execute(Segment segment) { if (!segment.HasBlanks) { return(false); } KnownStartAndEndFalses falseStartAndEndCounts = base.RemoveStartAndEndFalsesFromSegment(segment); bool cellsChanged = false; if (segment.MustHaves.Sum(seq => seq.Count) + segment.MustHaves.Count - 1 == segment.Length) { int i = 0; foreach (Sequence sequence in segment.MustHaves) { for (int j = 0; j < sequence.Count; j++) { // Mark the trues if (segment.Cells[i].MarkTrue() & !cellsChanged) { cellsChanged = true; } i++; } if (i < segment.Length) { // Joining with falses if (segment.Cells[i].MarkFalse() & !cellsChanged) { cellsChanged = true; } i++; } } } base.RecombineFalseStartsAndEndsWithSegment(falseStartAndEndCounts, segment); return(cellsChanged); }
/// <summary> /// If a segment starts or ends with a True, extend it outward based on first or last sequence /// </summary> /// <param name="segment"></param> /// <returns></returns> public override bool Execute(Segment segment) { if (!segment.HasBlanks) { return(false); } KnownStartAndEndFalses falseStartAndEndCounts = base.RemoveStartAndEndFalsesFromSegment(segment); bool cellsChanged = false; if (segment.TrueCount > 0) { if (segment.Cells.First().IsTrue) { foreach (Cell cell in segment.Cells.Take(segment.MustHaves.First().Count)) { if (cell.MarkTrue() && !cellsChanged) { cellsChanged = true; } } } //End if (segment.Cells.Last().IsTrue) { segment.Cells.Reverse(); foreach (Cell cell in segment.Cells.Take(segment.MustHaves.Last().Count)) { if (cell.MarkTrue() && !cellsChanged) { cellsChanged = true; } } segment.Cells.Reverse(); } } base.RecombineFalseStartsAndEndsWithSegment(falseStartAndEndCounts, segment); return(cellsChanged); }
protected void RecombineFalseStartsAndEndsWithSegment(KnownStartAndEndFalses StartAndEnd, Segment MiddleSegment) { if (StartAndEnd.StartIndexFalsesEnd != 0) { for (int i = 0; i < StartAndEnd.StartIndexFalsesEnd; i++) { Cell FalseCell = new Cell(); FalseCell.MarkFalse(); MiddleSegment.Cells.Insert(0, FalseCell); } } if (StartAndEnd.EndIndexFalsesStart != 0) { for (int i = 0; i < StartAndEnd.EndIndexFalsesStart; i++) { Cell FalseCell = new Cell(); FalseCell.MarkFalse(); MiddleSegment.Cells.Add(FalseCell); } } }
/// <summary> /// If the ENTIRE segment is either all true or all false /// </summary> /// <param name="segment"></param> /// <returns></returns> public override bool Execute(Segment segment) { if (!segment.HasBlanks) { return(false); } KnownStartAndEndFalses falseStartAndEndCounts = base.RemoveStartAndEndFalsesFromSegment(segment); bool cellsChanged = false; if (segment.MustHaves.Count == 1) { // If it's all true if (segment.MustHaves.First().Count == segment.Length) { foreach (Cell cell in segment.Cells) { if (cell.MarkTrue() && !cellsChanged) { cellsChanged = true; } } } // If it's all false else if (segment.MustHaves.First().Count == 0) { foreach (Cell cell in segment.Cells) { if (cell.MarkFalse() && !cellsChanged) { cellsChanged = true; } } } } base.RecombineFalseStartsAndEndsWithSegment(falseStartAndEndCounts, segment); return(cellsChanged); }
/// <summary> /// If there's only 1 sequence and we have more than one already True cells, /// then connect them /// </summary> /// <param name="segment"></param> /// <returns></returns> public override bool Execute(Segment segment) { if (!segment.HasBlanks) { return(false); } KnownStartAndEndFalses falseStartAndEndCounts = base.RemoveStartAndEndFalsesFromSegment(segment); bool cellsChanged = false; // If there's only 1 sequence if (segment.MustHaves.Count == 1) { // But there's already more than 1 known True cell, IEnumerable <Cell> trueCells = segment.Cells.Where(cell => cell.IsTrue); if (trueCells.Count() > 1) { // Figure out what to draw between int startDrawingAt = trueCells.Min(cell => cell.IndexIn(segment)); int endDrawingAt = trueCells.Max(cell => cell.IndexIn(segment)); // Draw between them for (; startDrawingAt < endDrawingAt; startDrawingAt++) { // startDrawingAt is the index of cell to mark as True // Mark the cells along the path as true if (segment.Cells[startDrawingAt].MarkTrue() && !cellsChanged) { cellsChanged = true; } } } } base.RecombineFalseStartsAndEndsWithSegment(falseStartAndEndCounts, segment); return(cellsChanged); }
public override bool Execute(Segment segment) { if (!segment.HasBlanks) { return(false); } KnownStartAndEndFalses falseStartAndEndCounts = base.RemoveStartAndEndFalsesFromSegment(segment: segment, onlyTrimIfNoFalses: true); bool cellsChanged = false; if (segment.MustHaves.Count == 1) { // For a single sequence in a segment, Sequence theSequence = segment.MustHaves.First(); // Check for overlap int overlapFromMiddle; if (segment.Length.IsOdd()) { overlapFromMiddle = theSequence.Count - (segment.Length / 2) - 1; } else { overlapFromMiddle = theSequence.Count - (segment.Length / 2); } if (overlapFromMiddle > 0) { // Work outwards from the middle double middleIndex = segment.Length / 2.0; // If an odd number is needed, mark the middle bool markedMiddle = false; if (segment.Length.IsOdd()) { // Mark the middle if (segment.Cells[(segment.Length - 1) / 2].MarkTrue() && !cellsChanged) { cellsChanged = true; } markedMiddle = true; } if (!markedMiddle || (markedMiddle && overlapFromMiddle >= 1)) { // Regardless, move outwards if we have to for (int i = 0; i < overlapFromMiddle; i++) { // When odd, we need to do each side from the middle equally if (segment.Length.IsOdd()) { // 2.5-> 1,3 0,4 if (segment.Cells[Convert.ToInt32(Math.Floor(middleIndex)) - (i + 1)].MarkTrue() && !cellsChanged) { cellsChanged = true; } if (segment.Cells[Convert.ToInt32(Math.Floor(middleIndex)) + (i + 1)].MarkTrue() && !cellsChanged) { cellsChanged = true; } } else { // 2 -> 1,2 0,3 if (segment.Cells[Convert.ToInt32(middleIndex) + (i)].MarkTrue() && !cellsChanged) { cellsChanged = true; } if (segment.Cells[Convert.ToInt32(middleIndex) - (i + 1)].MarkTrue() && !cellsChanged) { cellsChanged = true; } } } } } } base.RecombineFalseStartsAndEndsWithSegment(falseStartAndEndCounts, segment); return(cellsChanged); }