Skip to content

Instantly share code, notes, and snippets.

@ralfw
Created November 5, 2012 07:50
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save ralfw/4015879 to your computer and use it in GitHub Desktop.
Kata Word Wrap mit expliziten Aspekten
using System;
using System.Dynamic;
using NUnit.Framework;
namespace KataWordWrap
{
[TestFixture()]
public class test_Wrapper
{
[TestCase("word", 4, Result="word")]
[TestCase("word", 2, Result="wo\nrd")]
[TestCase("word", 3, Result = "wor\nd")]
[TestCase("wordword", 3, Result="wor\ndwo\nrd")]
[TestCase("word word", 4, Result="word\nword")]
[TestCase("word word", 5, Result="word\nword")]
[TestCase("word word", 6, Result="word\nword")]
[TestCase("word wo-rd", 8, Result = "word wo-\nrd")]
[TestCase("word word word", 6, Result="word\nword\nword")]
[TestCase("word word word", 11, Result="word word\nword")]
public string Wrap_single_text(string text, int maxCols)
{
return Wrapper.Wrap(text, maxCols);
}
[TestCase("word11\nword21", 42, Result = "word11\nword21")]
[TestCase("word11 word12\nword21 word22", 10, Result="word11\nword12\nword21\nword22")]
public string Wrap_multiple_texts(string text, int maxCols)
{
return Wrapper.Wrap(text, maxCols);
}
[TestCase("lineRemainder", 4, "line", "Remainder")]
[TestCase("line", 4, "line", "", Description = "End of text")]
[TestCase("line", 5, "line", "", Description = "End of text with not enough chars for full line")]
[TestCase("", 1, "", "")]
public void Break_off_next_line(string text, int maxCols, string line, string remainder)
{
var t = Wrapper.Break_off_next_line(text, maxCols);
Assert.AreEqual(line, t.Line);
Assert.AreEqual(remainder, t.Remainder);
}
[TestCase("line", "remainder", "line", "remainder", Description = "Perfect break or word too long for line")]
[TestCase("line ", "remainder", "line", "remainder", Description = "Trailing space in line")]
[TestCase("line", " remainder", "line", "remainder", Description = "Leading space in remainder")]
[TestCase("line w", "ord remainder", "line", "word remainder", Description = "Word split at end of line")]
[TestCase("line w-", "ord remainder", "line w-", "ord remainder", Description = "Line ends on word breakpoint")]
[TestCase("line w-o", "rd remainder", "line w-", "ord remainder", Description = "Split word at breakpoint")]
public void Heal_split_word(string line, string remainder, string linedTrimmed, string remainderTrimmed)
{
dynamic parts = new ExpandoObject();
parts.Line = line;
parts.Remainder = remainder;
var healed = Wrapper.Heal_split_word(parts);
Assert.AreEqual(linedTrimmed, healed.Line);
Assert.AreEqual(remainderTrimmed, healed.Remainder);
}
[TestCase("", "line", "line", Description = "First line")]
[TestCase("new", "line", "new\nline", Description = "Second to last line")]
public void Append_line_to_new_text(string newText, string line, string newTextResult)
{
Assert.AreEqual(newTextResult, Wrapper.Append_text(newText, line));
}
[TestCase("a", 2, "a")]
[TestCase("a b", 3, "a b")]
[TestCase("a b", 4, "a b")]
[TestCase("a b c", 7, "a b c")]
[TestCase("a b c", 6, "a b c")]
public void Justify(string line, int maxCols, string justifiedLine)
{
Assert.AreEqual(justifiedLine, Wrapper.Justify(line, maxCols));
}
[TestCase("text1\ntext2", "text1", "text2")]
[TestCase("text", "text", "")]
public void Get_next_text(string multitext, string text, string remainder)
{
var parts = Wrapper.Get_next_text(multitext);
Assert.AreEqual(text, parts.Text);
Assert.AreEqual(remainder, parts.Remainder);
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
namespace KataWordWrap
{
// http://codingdojo.org/cgi-bin/wiki.pl?KataWordWrap
public class Wrapper
{
public static string Wrap(string text, int maxCols)
{
return Wrap_multi_text("", text, maxCols);
}
private static string Wrap_multi_text(string newText, string remainder, int maxCols)
{
if (remainder == "") return newText;
var parts = Get_next_text(remainder);
var wrapped = Wrap_remaining_text("", parts.Text, maxCols);
newText = Append_text(newText, wrapped);
return Wrap_multi_text(newText, parts.Remainder, maxCols);
}
internal static dynamic Get_next_text(string multitext)
{
dynamic parts = new ExpandoObject();
var eolIndex = multitext.IndexOf("\n");
if (eolIndex < 0)
{
parts.Text = multitext;
parts.Remainder = "";
return parts;
}
parts.Text = multitext.Substring(0, eolIndex);
parts.Remainder = multitext.Substring(eolIndex + "\n".Length);
return parts;
}
private static string Wrap_remaining_text(string newText, string remainder, int maxCols)
{
if (remainder == "") return newText;
var parts = Extract_line(remainder, maxCols);
parts.Line = Justify(parts.Line, maxCols);
newText = Append_text(newText, parts.Line);
return Wrap_remaining_text(newText, parts.Remainder, maxCols);
}
private static dynamic Extract_line(string text, int maxCols)
{
var parts = Break_off_next_line(text, maxCols);
return Heal_split_word(parts);
}
internal static string Justify(string line, int maxCols)
{
var number_of_spaces_to_insert = maxCols - line.Length;
var words = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
var wordIndex = 0;
while(words.Length > 1 && number_of_spaces_to_insert>0)
{
words[wordIndex] = words[wordIndex] + ' ';
number_of_spaces_to_insert--;
wordIndex = (wordIndex + 1) % (words.Length-1);
}
return string.Join(" ", words);
}
internal static string Append_text(string newText, string line)
{
return newText + (newText == "" ? "" : "\n") + line;
}
internal static dynamic Break_off_next_line(string text, int maxCols)
{
var line = text.Substring(0, Math.Min(maxCols, text.Length));
var remainder = maxCols < text.Length ? text.Substring(maxCols) : "";
dynamic parts = new ExpandoObject();
parts.Line = line;
parts.Remainder = remainder;
return parts;
}
internal static dynamic Heal_split_word(dynamic parts)
{
return Has_a_word_been_split(parts) ? Rejoin_head_of_word_with_body_in_remainder(parts)
: Trim_line_and_remainder(parts);
}
private static bool Has_a_word_been_split(dynamic parts)
{
return !parts.Line.EndsWith(" ") && !parts.Remainder.StartsWith(" ");
}
private static dynamic Rejoin_head_of_word_with_body_in_remainder(dynamic parts)
{
return Line_ends_with_syllable(parts.Line) ? Rejoin_syllable(parts)
: Rejoin_word(parts);
}
private static bool Line_ends_with_syllable(string line)
{
return line.LastIndexOf("-") > line.LastIndexOf(" ");
}
private static dynamic Rejoin_syllable(dynamic parts)
{
var indexOfLastHyphen = parts.Line.LastIndexOf("-");
if (!parts.Line.EndsWith("-") && indexOfLastHyphen >= 0)
{
var headOfSplitWord = parts.Line.Substring(indexOfLastHyphen + 1);
parts.Line = parts.Line.Substring(0, indexOfLastHyphen + 1);
parts.Remainder = headOfSplitWord + parts.Remainder;
}
return parts;
}
private static dynamic Rejoin_word(dynamic parts)
{
var indexOfLastSpace = parts.Line.LastIndexOf(" ");
if (indexOfLastSpace >= 0)
{
var headOfSplitWord = parts.Line.Substring(indexOfLastSpace + 1);
parts.Line = parts.Line.Substring(0, indexOfLastSpace).TrimEnd();
parts.Remainder = headOfSplitWord + parts.Remainder;
}
return parts;
}
private static dynamic Trim_line_and_remainder(dynamic parts)
{
parts.Line = parts.Line.TrimEnd();
parts.Remainder = parts.Remainder.TrimStart();
return parts;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment