Skip to content

Instantly share code, notes, and snippets.

@ralfw
Last active August 29, 2015 14:02
Show Gist options
  • Save ralfw/89640f71e95f23ab2927 to your computer and use it in GitHub Desktop.
Save ralfw/89640f71e95f23ab2927 to your computer and use it in GitHub Desktop.
Informed TDD - JUGHH 17.6.2014
/*
* Ralf Westphal, Hamburg
* info@ralfw.de, @ralfw, http://blog.ralfw.de
*/
using System;
using System.Linq;
using System.Collections.Generic;
namespace kata
{
public class RomanConverter
{
public int ConvertFromRoman(string roman)
{
Validate(roman);
var reversedRoman = Reverse_roman(roman);
var values = Map_roman_digits_to_values(reversedRoman);
return Sum_values(values);
}
private void Validate(string roman)
{
// validate 1
if (roman.IndexOf("VV") >= 0 ||
roman.IndexOf("LL") >= 0 ||
roman.IndexOf("DD") >= 0)
throw new InvalidOperationException("So gehts nicht!");
// validate 2
// validate 3
}
private IEnumerable<char> Reverse_roman(string roman)
{
var digits = roman.ToCharArray();
Array.Reverse(digits);
return digits;
}
private IEnumerable<int> Map_roman_digits_to_values(IEnumerable<char> reversedRoman)
{
var map = new Dictionary<char, int>{
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
return reversedRoman.Select(d => map[d]);
}
private int Sum_values(IEnumerable<int> values)
{
var sum = 0;
var prevValue = 0;
foreach (var v in values) {
if (v < prevValue)
sum -= v;
else
sum += v;
prevValue = v;
}
return sum;
}
}
public static class RomanExtensions
{
public static int ToArabic(this string roman)
{
var conv = new RomanConverter();
return conv.ConvertFromRoman(roman);
}
}
}
/*
* Ralf Westphal, Hamburg
* info@ralfw.de, @ralfw, http://blog.ralfw.de
*/
using System;
using NUnit.Framework;
namespace kata
{
// Informed TDD
// TDD as if you meant
// From Roman Numerals
// XLII -> 42
// XV -> 15
// MCXL -> 1140
// MMXIV -> 2014
// 1. Analyse
// I, V, X, L, C, D, M: römische Ziffern
// >0, <= 3000
// Römische Ziffern in monoton absteigender Folge - außer manchmal.
// Zehnerpotenzen können vorangestellt werden, um "negativ zu wirken",
// aber nur die jeweils nächst kleinere. Und nur 1x.
// Bsp: XL, XC - erlaubt, aber nicht: XD, XM
// Nicht mehr als 3x dieselbe röm. Zi nacheinander.
// Dieselbe Zi darf nur nacheinander stehen.
// Jede röm. Zi hat einen Wert.
// Nicht-10erpotenzen dürfen nicht mehrfach auftauchen.
// API?
// u.a. Extension Method
// Inkremente:
// #1: nur korrekte Zahlen
// #2: wir erkennen Syntaxfehler
// 2. Lösungsansatz entwerfen
// XVI
// 1. X -> 10
// 2. V -> 5
// 3. I -> 1
// 4. Summe bilden
// Röm. umdrehen: XIV -> VIX
// Röm. Ziffern bewerten: VIX -> 5, 1, 10
// Werte addieren - solange Wert nicht kleiner als Vorgänger.
// Wenn kleiner, dann subtrahieren.
// 5, 0 -> 0+5 = 5
// 1, 5 -> 5-1 = 4
// 10, 5 -> 4 + 10 = 14
[TestFixture]
public class Tests
{
[TestCase("XLII", 42)]
[TestCase("XV", 15)]
[TestCase("MCXL", 1140)]
[TestCase("MMXIV", 2014)]
[TestCase("I", 1)]
[TestCase("V", 5)]
[TestCase("X", 10)]
[TestCase("L", 50)]
[TestCase("C", 100)]
[TestCase("D", 500)]
[TestCase("M", 1000)]
public void Akzeptanztestfälle(string roman, int expectedArabic)
{
var result = roman.ToArabic();
Assert.AreEqual(expectedArabic, result);
}
[TestCase("VV")]
public void Rainy_day_Testfälle(string roman)
{
Assert.Throws<InvalidOperationException>(
() => roman.ToArabic());
}
[Test]
public void API_finden()
{
var sut = new RomanConverter();
var arabic = "XLII".ToArabic();
Assert.AreEqual(42, arabic);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment