Created
August 25, 2015 16:49
-
-
Save witoong623/4ea3277eedb965c4346b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace AffineCiphers | |
{ | |
class Program | |
{ | |
private static char[] CharacterTable = new char[] | |
{ | |
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', | |
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', | |
'T', 'U', 'V', 'W', 'X', 'Y', 'Z' | |
}; | |
private static List<KeyValuePair<int, double>> CharFrequency; | |
private static string CipherText; | |
private static int[] OrdinalCipher; | |
static void Main(string[] args) | |
{ | |
string text = Console.ReadLine(); | |
for (int i = 0; i < ) | |
BuildStatic(); | |
} | |
static void BuildStatic() | |
{ | |
var temDic = new Dictionary<int, double>(); | |
temDic.Add(0, 8); | |
temDic.Add(1, 1.5); | |
temDic.Add(2, 3); | |
temDic.Add(3, 4); | |
temDic.Add(4, 12.5); | |
temDic.Add(5, 2); | |
temDic.Add(6, 2); | |
temDic.Add(7, 5.5); | |
temDic.Add(8, 7); | |
temDic.Add(9, 0.1); | |
temDic.Add(10, 0.7); | |
temDic.Add(11, 4); | |
temDic.Add(12, 2.5); | |
temDic.Add(13, 7); | |
temDic.Add(14, 8); | |
temDic.Add(15, 2); | |
temDic.Add(16, 0.1); | |
temDic.Add(17, 6); | |
temDic.Add(18, 6.5); | |
temDic.Add(19, 9); | |
temDic.Add(20, 3); | |
temDic.Add(21, 1); | |
temDic.Add(22, 2); | |
temDic.Add(23, 0.2); | |
temDic.Add(24, 2); | |
temDic.Add(25, 0.1); | |
CharFrequency = temDic.ToList(); | |
CharFrequency.Sort((firstPair, nextPair) => nextPair.Value.CompareTo(firstPair.Value)); | |
// Key is number of occurance, List int is ordinal number | |
var frequency = new SortedDictionary<int, List<int>>(); | |
foreach (var ch in CipherText) | |
{ | |
var count = CipherText.Count(x => ch == x); | |
List<int> list; | |
if (!frequency.TryGetValue(count, out list)) | |
{ | |
frequency[count] = new List<int>(); | |
} | |
if (!frequency[count].Contains(Array.FindIndex(CharacterTable, x => x == ch))) | |
{ | |
frequency[count].Add(Array.FindIndex(CharacterTable, x => x == ch)); | |
} | |
} | |
var maxFrequency = frequency.Keys.Max(); | |
var MaxChar = frequency[maxFrequency].First(); | |
var workListTemp = new List<SystemLinearCongruence>(); | |
foreach (var character in CharFrequency) | |
{ | |
if (MaxChar != character.Key) | |
{ | |
var congruence = new SystemLinearCongruence(CharacterTable, CipherText.ToCharArray()); | |
congruence.LeftSide[0] = MaxChar; | |
congruence.RightSide[0] = character.Key; | |
workListTemp.Add(congruence); | |
} | |
} | |
// list of occurance char, This is ORDINAL NUMBER | |
var secound = frequency[1]; | |
List<SystemLinearCongruence>[] workLists = new List<SystemLinearCongruence>[secound.Count]; | |
for (int i = 0; i < workLists.Length; i++) | |
{ | |
workLists[i] = new List<SystemLinearCongruence>(workListTemp); | |
} | |
foreach (var workList in workLists) | |
{ | |
foreach (int i in secound) | |
{ | |
foreach (var sysCongruence in workList) | |
{ | |
sysCongruence.LeftSide[1] = i; | |
} | |
} | |
foreach (var pair in CharFrequency) | |
{ | |
foreach (var sysCongruence in workList) | |
{ | |
if (pair.Key != sysCongruence.LeftSide[1] && pair.Key != sysCongruence.RightSide[0]) | |
{ | |
sysCongruence.RightSide[1] = pair.Key; | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.IO; | |
using System.Runtime.CompilerServices; | |
using System.Text; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace AffineCiphers | |
{ | |
public class SystemLinearCongruence | |
{ | |
private int[] _leftSide; | |
private int[] _rightSide; | |
private readonly char[] table; | |
private readonly int[] CipherText; | |
#region properties | |
public int[] LeftSide | |
{ | |
get { return _leftSide; } | |
set { _leftSide = value; } | |
} | |
public int[] RightSide | |
{ | |
get { return _rightSide; } | |
set { _rightSide = value; } | |
} | |
public int FirstPhaseLeft { get; private set; } | |
public int FirstPhaseRight { get; private set; } | |
public int LastQuatationLeft { get; private set; } | |
public int LastQuatationRight { get; private set; } | |
public int KeyA { get; private set; } | |
public int KeyK { get; private set; } | |
#endregion | |
public SystemLinearCongruence(char[] table, int[] CipherText) | |
{ | |
_leftSide = new int[2]; | |
_rightSide = new int[2]; | |
this.table = table; | |
this.CipherText = CipherText; | |
} | |
public void Decypt() | |
{ | |
if (Solve()) | |
{ | |
string fileName = "a is " + KeyA + "K is " + KeyK; | |
var sw = new StreamWriter(fileName, false, Encoding.UTF8); | |
foreach (int cipherChar in CipherText) | |
{ | |
var plainText = (cipherChar - KeyK * GetInverse(KeyA)) % 26; | |
sw.Write(plainText.ToString() + " "); | |
} | |
} | |
} | |
public bool Solve() | |
{ | |
if (_rightSide[0] > _rightSide[1]) | |
{ | |
FirstPhaseLeft = _leftSide[0] - _leftSide[1]; | |
FirstPhaseRight = _rightSide[0] - _rightSide[1]; | |
} | |
else if (_rightSide[0] < _rightSide[1]) | |
{ | |
FirstPhaseLeft = _leftSide[1] - _leftSide[0]; | |
FirstPhaseRight = _rightSide[1] - _rightSide[0]; | |
} | |
if (FirstPhaseLeft < 0) | |
{ | |
FirstPhaseLeft = ConvertToPositive(FirstPhaseLeft); | |
} | |
// If gcd not equal to 1 then can find inverse | |
if (GetGcd(FirstPhaseRight, 26) != 1) | |
{ | |
return false; | |
} | |
var inverse = GetInverse(FirstPhaseRight); | |
FirstPhaseLeft *= inverse; | |
KeyA = FirstPhaseLeft % 26; | |
// If gcd not equal to 1 then can find inverse | |
if (GetGcd(KeyA, 26) != 1) | |
{ | |
return false; | |
} | |
if (_rightSide[1] < _rightSide[0]) | |
{ | |
LastQuatationRight = _rightSide[1] * KeyA; | |
LastQuatationLeft = _leftSide[1]; | |
} | |
else if (_rightSide[0] < _rightSide[1]) | |
{ | |
LastQuatationRight = _rightSide[0] * KeyA; | |
LastQuatationLeft = _leftSide[0]; | |
} | |
KeyK = (LastQuatationLeft - LastQuatationRight) % 26; | |
if (KeyK < 0) | |
{ | |
KeyK = ConvertToPositive(KeyK); | |
} | |
return true; | |
} | |
public int ConvertToPositive(int number) | |
{ | |
return 26 + number; | |
} | |
public int GetGcd(int a, int b) | |
{ | |
return b == 0 ? a : GetGcd(b, a % b); | |
} | |
public int GetInverse(int number) | |
{ | |
return Enumerable.Range(1, int.MaxValue).First(x => number * x % 26 == 1); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment