/// <summary> /// Mutate the array of line break locations until an optimal solution is found. /// No line breaks are added or deleted, they are simply moved around. /// </summary> /// <param name="words">Array of each word.</param> /// <param name="wordBreaks">Array of line breaks.</param> /// <param name="limit">Width to wrap each line.</param> /// <returns>New array of optimal line breaks.</returns> private static JsArray <bool?> wrapMutate_(string[] words, JsArray <bool?> wordBreaks, int limit) { var bestScore = Core.utils.wrapScore_(words, wordBreaks, limit); JsArray <bool?> bestBreaks = null; // Try shifting every line break forward or backward. for (var i = 0; i < wordBreaks.Length - 1; i++) { if (wordBreaks[i] == wordBreaks[i + 1]) { continue; } var mutatedWordBreaks = new JsArray <bool?>(); wordBreaks.ForEach((a) => mutatedWordBreaks.Push(a)); mutatedWordBreaks[i] = !mutatedWordBreaks[i]; mutatedWordBreaks[i + 1] = !mutatedWordBreaks[i + 1]; var mutatedScore = Core.utils.wrapScore_(words, mutatedWordBreaks, limit); if (mutatedScore > bestScore) { bestScore = mutatedScore; bestBreaks = mutatedWordBreaks; } } if (bestBreaks != null) { // Found an improvement. See if it may be improved further. return(Core.utils.wrapMutate_(words, bestBreaks, limit)); } // No improvements found. Done. return(wordBreaks); }