Skip to content

Instantly share code, notes, and snippets.

@witoong623
Created August 25, 2015 16:49
Show Gist options
  • Save witoong623/4ea3277eedb965c4346b to your computer and use it in GitHub Desktop.
Save witoong623/4ea3277eedb965c4346b to your computer and use it in GitHub Desktop.
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;
}
}
}
}
}
}
}
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