3 people like it.
Like the snippet!
Frequency Tables, Shift Cipher
Solving Ceasar shfit with frequency tables.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
|
let isalpha = System.Char.IsLetter
(* Only do lowers for now *)
let shift n c =
if isalpha c then
char ((( int c - 97 + n ) % 26 ) + 97)
else if c = ' ' then ' '
else c
let encode xs n = String.map (shift n) xs
let countSum xs c = Seq.fold (fun acc x -> if x = c then acc+1.0 else acc) 0.0 xs
let freqTab word =
let freq = Seq.map (countSum word) ['a'..'z']
let sum = Seq.sum freq
Seq.map (fun c -> c * 100.0 / sum) freq
(*
X^2 = sum i=1 .. n * (o - e)^2 / e
Where:
X^2 - is the test statistic that asymptotically approaches a x 2 (Chi) distribution.
o - an observed frequency
e - an expected (theoretical) frequency, asserted by the null hypothesis.
n - the number of possible outcomes of each event.
*)
let chisqr (a : float seq) (b : float seq) =
Seq.zip a b
|> Seq.fold (fun acc (o,e) -> acc+((o - e) * (o - e) / e)) 0.0
let freqTable = [ 8.2; 1.5; 2.8; 4.3; 12.7; 2.2; 2.0; 6.1; 7.0;
0.2; 0.8; 4.0; 2.4; 6.7; 7.5; 1.9; 0.1; 6.0;
6.3; 9.1; 2.8; 1.0; 2.4; 0.2; 2.0; 0.1 ]
let crack word =
[0..25]
|> Seq.map (fun x -> x, chisqr (freqTab (encode word x)) freqTable)
|> Seq.minBy (fun (x,y) -> y)
|> fst
|> encode word
(* Tests *)
//> let test = encode "hello how are you?" 3;;
//val test : string = "khoor krz duh brx?"
//> crack test;;
//val it : string = "hello how are you?"
|
val isalpha : arg00:char -> bool
Full name: Script.isalpha
namespace System
type Char =
struct
member CompareTo : value:obj -> int + 1 overload
member Equals : obj:obj -> bool + 1 overload
member GetHashCode : unit -> int
member GetTypeCode : unit -> TypeCode
member ToString : unit -> string + 1 overload
static val MaxValue : char
static val MinValue : char
static member ConvertFromUtf32 : utf32:int -> string
static member ConvertToUtf32 : highSurrogate:char * lowSurrogate:char -> int + 1 overload
static member GetNumericValue : c:char -> float + 1 overload
...
end
Full name: System.Char
System.Char.IsLetter(c: char) : bool
System.Char.IsLetter(s: string, index: int) : bool
val shift : n:int -> c:char -> char
Full name: Script.shift
val n : int
val c : char
Multiple items
val char : value:'T -> char (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.char
--------------------
type char = System.Char
Full name: Microsoft.FSharp.Core.char
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
val encode : xs:string -> n:int -> string
Full name: Script.encode
val xs : string
module String
from Microsoft.FSharp.Core
val map : mapping:(char -> char) -> str:string -> string
Full name: Microsoft.FSharp.Core.String.map
val countSum : xs:seq<'a> -> c:'a -> float (requires equality)
Full name: Script.countSum
val xs : seq<'a> (requires equality)
val c : 'a (requires equality)
module Seq
from Microsoft.FSharp.Collections
val fold : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> 'State
Full name: Microsoft.FSharp.Collections.Seq.fold
val acc : float
val x : 'a (requires equality)
val freqTab : word:seq<char> -> seq<float>
Full name: Script.freqTab
val word : seq<char>
val freq : seq<float>
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
val sum : float
val sum : source:seq<'T> -> 'T (requires member ( + ) and member get_Zero)
Full name: Microsoft.FSharp.Collections.Seq.sum
val c : float
val chisqr : a:seq<float> -> b:seq<float> -> float
Full name: Script.chisqr
val a : seq<float>
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = System.Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Core.Operators.seq
--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>
Full name: Microsoft.FSharp.Collections.seq<_>
val b : seq<float>
val zip : source1:seq<'T1> -> source2:seq<'T2> -> seq<'T1 * 'T2>
Full name: Microsoft.FSharp.Collections.Seq.zip
val o : float
val e : float
val freqTable : float list
Full name: Script.freqTable
val crack : word:string -> string
Full name: Script.crack
val word : string
val x : int
val minBy : projection:('T -> 'U) -> source:seq<'T> -> 'T (requires comparison)
Full name: Microsoft.FSharp.Collections.Seq.minBy
val y : float
val fst : tuple:('T1 * 'T2) -> 'T1
Full name: Microsoft.FSharp.Core.Operators.fst
More information