static void DebugGetCharProportion() { Console.Write("Text> "); string text = Console.ReadLine().ToUpper(); Dictionary <char, int> charFrequency = FrequencyAnalysis.GetTextCharFrequency(text); Console.WriteLine("Frequencies:"); foreach (char c in charFrequency.Keys) { Console.WriteLine($"{c} : {charFrequency[c]}"); } Dictionary <char, double> charProportion = FrequencyAnalysis.CharFrequencyToCharProportion(charFrequency); Console.WriteLine("Proportions:"); foreach (char c in charProportion.Keys) { Console.WriteLine($"{c} : {charProportion[c]}"); } }
public static string RunDeciphering(string originalText, int keyLength, out string keyword) { //TODO: allow for keyLength bigger than seperateKeyColors.Length Debug.Assert(keyLength < seperateKeyColors.Length); string[] originalSelections = FrequencyAnalysis.SplitTextByOffset(originalText, keyLength); int[] selectionShifts = new int[originalSelections.Length]; for (int i = 0; i < originalSelections.Length; i++) { selectionShifts[i] = 0; } #region Instructions PrintSeperator(); Console.WriteLine("To shift a selection with id i by n (n can be negative), use \"{i}:{n}\""); Console.WriteLine("To set the current mapping to a calculated optimal mapping, use SET OPTIMAL"); Console.WriteLine("To print the text in one color, use PRINT PLAIN"); PrintSeperator(); for (int i = 0; i < keyLength; i++) { Console.ForegroundColor = seperateKeyColors[i]; Console.Write(i + " "); } Console.ForegroundColor = defaultConsoleColor; Console.WriteLine(); PrintSeperator(); #endregion bool running = true; while (running) { Console.WriteLine("Current Keyword: " + ProgramMath.GetKeywordFromOffsets(selectionShifts)); Console.WriteLine("Current Text:"); PrintColoredTextByKey(ConstructCurrentDeciphering(originalSelections, selectionShifts), keyLength); Console.Write("> "); string inputRequest = Console.ReadLine().ToUpper(); if (inputRequest == "" || inputRequest == "END") { running = false; } else if (Regex.IsMatch(inputRequest, @"^\d+:-?\d+$", RegexOptions.IgnoreCase)) { string[] parts = inputRequest.Split(':'); Debug.Assert(parts.Length == 2); int selectionId = int.Parse(parts[0]); int shiftAmount = int.Parse(parts[1]); if (selectionId < 0 || selectionId >= originalSelections.Length) { Console.WriteLine("Invalid selection id"); } else { selectionShifts[selectionId] = (selectionShifts[selectionId] + shiftAmount + Program.validCharacters.Length) % Program.validCharacters.Length; } } else if (inputRequest == "SET OPTIMAL" || inputRequest == "SETOPTIMAL") { for (int selectionIndex = 0; selectionIndex < originalSelections.Length; selectionIndex++) { string selection = originalSelections[selectionIndex]; Dictionary <char, double> selectionProportions = FrequencyAnalysis.CharFrequencyToCharProportion(FrequencyAnalysis.GetTextCharFrequency(selection)); double _; int optimalShiftAmount; FrequencyAnalysis.GetOptimalCharacterMapping(selectionProportions, EnglishLetterFrequency.GetLetterProportions(), out _, out optimalShiftAmount); selectionShifts[selectionIndex] = optimalShiftAmount; } } else if (inputRequest == "PRINT PLAIN" || inputRequest == "PRINTPLAIN") { Console.WriteLine(ConstructCurrentDeciphering(originalSelections, selectionShifts)); } else { Console.WriteLine("Unknown Request"); } } keyword = ProgramMath.GetKeywordFromOffsets(selectionShifts); return(ConstructCurrentDeciphering(originalSelections, selectionShifts)); }
static void ReleaseMain(string[] args) { Console.Write("Text> "); string text; string input = Console.ReadLine().ToUpper().Replace(" ", "").ToUpper(); if (input[0] == '\\') { text = GetTextFromFile(input.Substring(1)).ToUpper(); } else { text = input; } foreach (char c in text) { if (!validCharacters.Contains(c)) { Console.WriteLine($"Error: Invalid character in text ({c})"); return; } } int keyLengthSelection = KeyLengthSelection(text); Console.Write("Automatically decipher text (0/1)?> "); bool autoDecipher = int.Parse(Console.ReadLine()) != 0; if (autoDecipher) { string[] offsetTextSelections = FrequencyAnalysis.SplitTextByOffset(text, keyLengthSelection); string[] decipheredStrings = new string[offsetTextSelections.Length]; int[] shiftAmounts = new int[offsetTextSelections.Length]; for (int i = 0; i < decipheredStrings.Length; i++) { string selection = offsetTextSelections[i]; double _; Dictionary <char, double> selectionProportions = FrequencyAnalysis.CharFrequencyToCharProportion(FrequencyAnalysis.GetTextCharFrequency(selection)); Dictionary <char, char> optimalMapping = FrequencyAnalysis.GetOptimalCharacterMapping(selectionProportions, EnglishLetterFrequency.GetLetterProportions(), out _, out shiftAmounts[i]); decipheredStrings[i] = FrequencyAnalysis.DecipherTextByMapping(selection, optimalMapping); } string fullDeciphering = FrequencyAnalysis.ReconstructTextFromOffsetSelections(decipheredStrings); Console.WriteLine("Keyword: " + ProgramMath.GetKeywordFromOffsets(shiftAmounts)); Console.WriteLine("Deciphered Text:"); Console.WriteLine(fullDeciphering); } else { string keyword; string fullDeciphering = ManualMappingDeciphering.RunDeciphering(text, keyLengthSelection, out keyword); Console.WriteLine("Keyword: " + keyword); Console.WriteLine("Deciphered Text:"); Console.WriteLine(fullDeciphering); } }
static void DebugOptimalCharacterMappingFull() { Console.Write("Text> "); string text = Console.ReadLine().ToUpper(); const bool discardSingle = true; Repetition[] repetitions = Repetition.GetTextRepetitions(text); Dictionary <int, int> keyLengthWeightings = KeyLengthDeduction.GetKeyLengthWeights(repetitions, discardSingle); Dictionary <int, int> factoredWeightings = KeyLengthDeduction.GetFactoredKeyLengthWeights(keyLengthWeightings); const int topLengthsCount = 7; Dictionary <int, int> topLengths = ProgramMath.GetTopDictionaryKeysByValue(factoredWeightings, topLengthsCount); Console.WriteLine(); Console.WriteLine("Top Key Lengths:"); foreach (int length in topLengths.Keys) { Console.WriteLine($"{length} (weighting = {topLengths[length]})"); } Console.Write("Select chosen key length> "); int keyLengthSelection = int.Parse(Console.ReadLine()); string[] selections = FrequencyAnalysis.SplitTextByOffset(text, keyLengthSelection); Console.WriteLine(); Console.WriteLine("Text Offset Selections:"); for (int i = 0; i < selections.Length; i++) { Console.WriteLine(i + ") " + selections[i]); } Console.Write("Select text offset selection> "); int offsetSelectionIndex = int.Parse(Console.ReadLine()); Debug.Assert(0 <= offsetSelectionIndex && offsetSelectionIndex < selections.Length); string selectedTextOffsetSelection = selections[offsetSelectionIndex]; Dictionary <char, double> selectionCharacterProportion = FrequencyAnalysis.CharFrequencyToCharProportion(FrequencyAnalysis.GetTextCharFrequency(selectedTextOffsetSelection)); Dictionary <char, double> englishCharacterProportions = EnglishLetterFrequency.GetLetterProportions(); double mappingDifference; int _; Dictionary <char, char> optimalMapping = FrequencyAnalysis.GetOptimalCharacterMapping(selectionCharacterProportion, englishCharacterProportions, out mappingDifference, out _); Console.WriteLine(); Console.WriteLine($"Mapping Difference: {mappingDifference}"); foreach (char textChar in optimalMapping.Keys) { Console.WriteLine($"{textChar} -> {optimalMapping[textChar]}"); } }
static Dictionary <char, char> GetMonoalphabeticMapping(string selectedTextOffsetSelection) { int graphHeight = 20; Dictionary <char, char> currentMapping = new Dictionary <char, char>(); foreach (char c in validCharacters) { currentMapping.Add(c, c); } bool editing = true; while (editing) { Console.WriteLine("\n\n"); string currentDeciphering = FrequencyAnalysis.DecipherTextByMapping(selectedTextOffsetSelection, currentMapping); Dictionary <char, double> englishCharacterProportions = EnglishLetterFrequency.GetLetterProportions(); Dictionary <char, double> selectionCharacterProportion = FrequencyAnalysis.CharFrequencyToCharProportion(FrequencyAnalysis.GetTextCharFrequency(currentDeciphering)); PrintSeperator(); Console.WriteLine("English Language Average Character Proportions (Target Proportions):"); FrequencyAnalysis.DrawConsoleCharFrequencyGraph(englishCharacterProportions, graphHeight, forcedContainChars: validCharacters); PrintSeperator(); Console.WriteLine(); PrintSeperator(); Console.WriteLine("Current Character Proportions:"); FrequencyAnalysis.DrawConsoleCharFrequencyGraph(selectionCharacterProportion, graphHeight, forcedContainChars: validCharacters); PrintSeperator(); Console.WriteLine("Request mapping swap ({character 1}:{character 2}) or leave blank to finish or +/- to increase/decrease graph magnification"); Console.Write("> "); string inputRequest = Console.ReadLine().ToUpper(); if (inputRequest.Length == 0) { editing = false; } else if (InputIsCharacterRemapping(inputRequest)) { char requestCharA = inputRequest[0]; char requestCharB = inputRequest[2]; Debug.Assert(inputRequest[1] == ':'); char currentInputCharToRequestCharA = ' '; char currentInputCharToRequestCharB = ' '; foreach (char c in currentMapping.Keys) { if (currentMapping[c] == requestCharA) { currentInputCharToRequestCharA = c; } if (currentMapping[c] == requestCharB) { currentInputCharToRequestCharB = c; } } if (currentInputCharToRequestCharA == ' ' || currentInputCharToRequestCharB == ' ') { Debug.Fail("Error: Failed to locate char mapping to request char"); } char requestInputCharOldMapping = currentMapping[currentInputCharToRequestCharA]; currentMapping[currentInputCharToRequestCharA] = requestCharB; currentMapping[currentInputCharToRequestCharB] = requestInputCharOldMapping; } else if (inputRequest == "+") { graphHeight += 5; } else if (inputRequest == "-") { if (graphHeight > 5) { graphHeight -= 5; } else { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Unable to further reduce graph height"); Console.ForegroundColor = ConsoleColor.White; } } else { Console.WriteLine("Unknown request"); } List <char> outputCharsUnique = new List <char>(); List <char> warnedCharsNonUnique = new List <char>(); foreach (char c in currentMapping.Keys) { char outputChar = currentMapping[c]; if (outputCharsUnique.Contains(outputChar) && !warnedCharsNonUnique.Contains(outputChar)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"WARNING: duplicate mapping to character '{outputChar}'"); Console.ForegroundColor = ConsoleColor.White; warnedCharsNonUnique.Add(outputChar); } else { outputCharsUnique.Add(outputChar); } } } return(currentMapping); }