public void ReducePotentialValues() { foreach (Node node in AllNodes) { var neighbourCombinations = Combinator.Combinations(AllNodes, node.MaxNeighbours.Value); foreach (IEnumerable <Node> combination in neighbourCombinations) { //Possible combinations are the sets that:: do not contain the node itself if (!combination.ToList().Contains(node)) //&& (node.Edges.Count == 0 || combination.Any(con => con.IsConnected(node)))) { node.Values.Add(combination.ToList()); } } //Values must contain already created edges (if any) foreach (Node child in node.Edges.Select(edge => edge.Child).ToList()) { node.Values = node.Values.FindAll(set => set.Contains(child)); } } }
public void CombinationsTest() { List <int> lst = new List <int> { 0, 1, 2, 3 }; List <List <int> > expected = new List <List <int> > { new List <int> { 0, 1 }, new List <int> { 0, 2 }, new List <int> { 0, 3 }, new List <int> { 1, 2 }, new List <int> { 1, 3 }, new List <int> { 2, 3 } }; var combinations = Combinator.Combinations(lst, 2); List <List <int> > actual = new List <List <int> >(); foreach (IEnumerable <int> combination in combinations) { actual.Add(combination.ToList()); } actual.ForEach(pair => Trace.WriteLine(string.Join(", ", pair))); for (int i = 0; i < actual.Count; i++) { CollectionAssert.AreEqual(expected[i], actual[i]); } }
/// <summary> /// Performs a Kasiski attack provided a given key length /// </summary> /// <param name="cipherText"></param> /// <param name="keyLength"></param> /// <returns></returns> public static string AttackWithKeyLength(string cipherText, int keyLength) { var cipher = new Vigenere(); var allFreqScores = new List <Dictionary <char, int> >(); for (var i = 1; i < keyLength + 1; i++) { var nthLetters = Kasiski.GetNthSubkeysLetters(i, keyLength, cipherText.ToUpper()); var frequencyScore = new Dictionary <char, int>(); foreach (var letter in Constants.Letters) { var decryptedText = cipher.Decipher(nthLetters, Char.ToString(letter)); var score = Frequency.EnglishFreqMatchScore(decryptedText); frequencyScore.Add(letter, score); } //Sort the dictionary by factor ocurrences descending var sortedCommonFactors = (from entry in frequencyScore orderby entry.Value descending select entry) .Take(4) .ToDictionary(pair => pair.Key, pair => pair.Value); allFreqScores.Add(sortedCommonFactors); } //Print our possible keys var position = 1; var possibleKeys = new List <char[]>(); foreach (var freq in allFreqScores) { _log.InfoFormat("Possible letters for letter {0} of the key: ", position); var possibleKeyOutput = new StringBuilder(); var keyStore = new char[freq.Keys.Count]; var keyPosition = 0; foreach (var keyPossible in freq.Keys) { possibleKeyOutput.AppendFormat("{0}\t", keyPossible); keyStore[keyPosition] = keyPossible; keyPosition++; } possibleKeys.Add(keyStore); _log.InfoFormat(possibleKeyOutput.ToString()); position++; } var keyCombinations = Combinator.Combinations(possibleKeys); var keyFound = false; var key = string.Empty; //Go through the possible keys with the given freqency and determine if they produce //an English sentence. Parallel.ForEach(keyCombinations, (possibleKey, loopState) => { //Stop processing if we find the possible key if (keyFound) { loopState.Break(); } _log.DebugFormat("Attempting with key: {0}", possibleKey); var decryptAttempt = cipher.Decipher(cipherText, possibleKey.ToString()); if (!English.IsEnglish(decryptAttempt)) { return; } _log.InfoFormat("Found Possible Decryption Key: {0}", possibleKey); keyFound = true; key = possibleKey.ToString(); } ); return(key); }