Alexander Schuc
crazy-weasel
Hi. 
Stufe 1
Die verschiedenen Verschiebungen zu "berechnen" ist jetzt nicht sonderlich schwer, darauf geh ich jetzt nicht ein.
Zur Erkennung welche Verschiebung nun die richtige ist, habe ich 2 Varianten eingebaut. Die Erste schaut sich die Häufigkeiten der Buchstaben an, die 2. nimmt sich ein paar (maximal 2) Wörter aus dem Ergebnis und fragt duden.de ob die Wörter bekannt sind.
Zum Vergleichen der Häufigkeiten sei erwähnt, dass es da sicher eine clevere Art und Weise gibt, aber.. es funktioniert.
Decoder
Verfikation über Häufigkeiten
Verifikation über duden.de
Gesamter Code ist angehängt.
Stufe 2 im nächsten Beitrag.

Stufe 1
Die verschiedenen Verschiebungen zu "berechnen" ist jetzt nicht sonderlich schwer, darauf geh ich jetzt nicht ein.
Zur Erkennung welche Verschiebung nun die richtige ist, habe ich 2 Varianten eingebaut. Die Erste schaut sich die Häufigkeiten der Buchstaben an, die 2. nimmt sich ein paar (maximal 2) Wörter aus dem Ergebnis und fragt duden.de ob die Wörter bekannt sind.

Zum Vergleichen der Häufigkeiten sei erwähnt, dass es da sicher eine clevere Art und Weise gibt, aber.. es funktioniert.

Decoder
C#:
public class CaesarDecoder : Decoder
{
public override string Name { get { return "Caesar"; } }
public override DecodingResult Decode(string phrase)
{
DecodingResult result = new DecodingResult
{
Success = false,
Ciphertext = phrase,
Plaintext = "",
Key = "",
Encryption = "Caesar",
Correctness = 0.0
};
for (int s = 1; s <= 26; s++)
{
string tempPhrase = "";
foreach (char c in phrase)
{
if (c < 97 || c > 122)
tempPhrase += c;
else
{
tempPhrase += (char)((((c - 97) + s) % 26) + 97);
}
}
var vresult = Verifier.Verify(tempPhrase);
if (Verbose)
{
Console.Error.WriteLine("#{0:00} - {1:0.00000}\r\n{2}", s, vresult.Correctness, tempPhrase);
}
if (vresult.Correctness > result.Correctness)
{
result = new DecodingResult
{
Success = true,
Ciphertext = phrase,
Plaintext = tempPhrase,
Key = (26-s).ToString(),
Encryption = "Caesar",
Correctness = vresult.Correctness
};
}
if (this.ResultMode == ResultMode.FirstAboveLimit
&& result.Correctness >= this.NeededCorrectness)
return result;
}
return result;
}
}
Verfikation über Häufigkeiten
C#:
public abstract class ProbabilityVerifier : Verifier
{
protected virtual double Threshold { get; set; }
protected Dictionary<char, double> CharPercentage { get; private set; }
public ProbabilityVerifier()
{
CharPercentage = new Dictionary<char, double>();
Threshold = 0.05;
}
protected void Add(char c, double value)
{
if (CharPercentage.ContainsKey(c))
CharPercentage[ c] = value;
else
CharPercentage.Add(c, value);
}
public override VerificationResult Verify(string phrase)
{
if (phrase.Length == 0)
return new VerificationResult { Correctness = 0 };
Dictionary<char, double> data = new Dictionary<char, double>();
foreach (char c in phrase.ToLower())
{
if (!CharPercentage.ContainsKey(c))
continue;
if (data.ContainsKey(c))
data[ c] += 1;
else
data[ c] = 1;
}
int count = 0;
for (int i = 0; i < data.Keys.Count; i++)
{
char c = data.Keys.ElementAt(i);
double value = data[ c] / phrase.Length;
double diff = Math.Abs(value - CharPercentage[ c]);
if (diff > Threshold)
{
count++;
}
}
return new VerificationResult { Correctness = 1.0 - (1.0 / data.Count) * count };
}
}
public class GermanProbabilityVerifier : ProbabilityVerifier
{
public GermanProbabilityVerifier()
{
Add('a', 0.0651); Add('b', 0.0189); Add('c', 0.0306); Add('d', 0.0508);
Add('e', 0.1740); Add('f', 0.0166); Add('g', 0.0301); Add('h', 0.0476);
Add('i', 0.0755); Add('j', 0.0027); Add('k', 0.0121); Add('l', 0.0344);
Add('m', 0.0253); Add('n', 0.0978); Add('o', 0.0251); Add('p', 0.0079);
Add('q', 0.0002); Add('r', 0.0700); Add('s', 0.0727); Add('t', 0.0615);
Add('u', 0.0435); Add('v', 0.0067); Add('w', 0.0189); Add('x', 0.0003);
Add('y', 0.0004); Add('z', 0.0113); Add('ß', 0.0031);
}
}
Verifikation über duden.de
C#:
public class DudenSpellingVerifier : Verifier
{
private readonly int wordsToCheck = 3;
private string dudenUrl = "http://www.duden-suche.de/suche/trefferliste.php?suchbegriff%5BAND%5D={0}";
public override VerificationResult Verify(string phrase)
{
string[] parts = phrase.Split(new char[] { ' ', '\r', '\n', '\t', '.', ',', ':', '!', '?' },
StringSplitOptions.RemoveEmptyEntries);
int check = parts.Length > wordsToCheck ? wordsToCheck : parts.Length;
int success = 0;
for (int i = 0; i < check; i++)
{
WebClient wc = new WebClient();
string site = wc.DownloadString(string.Format(dudenUrl, parts[i]));
if (!site.Contains(@"<strong>0</strong> Treffer in Duden"))
{
success++;
}
Thread.Sleep(1000);
}
return new VerificationResult { Correctness = (double)success / (double)check };
}
}
Gesamter Code ist angehängt.
Stufe 2 im nächsten Beitrag.