11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4- using System . Text ;
54
65public class Crypto
76{
8- public string NormalizePlaintext { get ; private set ; }
7+ public Crypto ( string input )
8+ {
9+ this . NormalizePlaintext = GetNormalizedPlaintext ( input ) ;
10+ this . Size = this . CalculateSize ( ) ;
11+ }
12+
913 public int Size { get ; private set ; }
1014
11- public Crypto ( string value )
15+ public string NormalizePlaintext { get ; private set ; }
16+
17+ public string NormalizeCiphertext ( )
1218 {
13- NormalizePlaintext = NormalizeText ( value ) ;
14- Size = GetSquareSize ( NormalizePlaintext ) ;
19+ return string . Join ( " " , Transpose ( this . PlaintextSegments ( ) ) ) ;
1520 }
1621
17- private static string NormalizeText ( string text )
22+ public string Ciphertext ( )
1823 {
19- return string . Concat ( text . ToLower ( ) . Where ( char . IsLetterOrDigit ) ) ;
24+ return string . Join ( "" , Transpose ( this . PlaintextSegments ( ) ) ) ;
2025 }
2126
22- private static int GetSquareSize ( string text )
27+ public IEnumerable < string > PlaintextSegments ( )
2328 {
24- return ( int ) Math . Ceiling ( Math . Sqrt ( text . Length ) ) ;
29+ return Chunks ( this . NormalizePlaintext , this . Size ) ;
2530 }
2631
27- public string [ ] PlaintextSegments ( )
32+ private int CalculateSize ( )
2833 {
29- return SegmentText ( NormalizePlaintext , Size ) ;
34+ return ( int ) Math . Ceiling ( Math . Sqrt ( this . NormalizePlaintext . Length ) ) ;
3035 }
3136
32- private static string [ ] SegmentText ( string text , int size )
37+ private static string GetNormalizedPlaintext ( string input )
3338 {
34- var segments = new List < string > ( ) ;
35- var idx = 0 ;
36- while ( idx < text . Length )
37- {
38- if ( idx + size < text . Length )
39- segments . Add ( text . Substring ( idx , size ) ) ;
40- else
41- segments . Add ( text . Substring ( idx ) ) ;
42- idx += size ;
43- }
44- return segments . ToArray ( ) ;
39+ return new string ( input . ToLowerInvariant ( ) . Where ( char . IsLetterOrDigit ) . ToArray ( ) ) ;
4540 }
4641
47- public string Ciphertext ( )
42+ private static IEnumerable < string > Chunks ( string str , int chunkSize )
4843 {
49- var ciphertext = new StringBuilder ( NormalizePlaintext . Length ) ;
50-
51- for ( int i = 0 ; i < Size ; i ++ )
52- {
53- foreach ( var segment in PlaintextSegments ( ) )
54- {
55- if ( i < segment . Length )
56- ciphertext . Append ( segment [ i ] ) ;
57- }
58- }
59- return ciphertext . ToString ( ) ;
44+ return Enumerable . Range ( 0 , ( int ) Math . Ceiling ( str . Length / ( double ) chunkSize ) )
45+ . Select ( i => str . Substring ( i * chunkSize , Math . Min ( str . Length - i * chunkSize , chunkSize ) ) ) ;
6046 }
61-
62- public string NormalizeCiphertext ( )
47+
48+ private static IEnumerable < string > Transpose ( IEnumerable < string > input )
6349 {
64- string cipher = Ciphertext ( ) ;
65- int size = cipher . Length == Size * Size - Size ? Size : Size - 1 ;
66- return string . Join ( " " , SegmentText ( cipher , size ) ) ;
50+ return input . SelectMany ( s => s . Select ( ( c , i ) => Tuple . Create ( i , c ) ) )
51+ . GroupBy ( x => x . Item1 )
52+ . Select ( g => new string ( g . Select ( t => t . Item2 ) . ToArray ( ) ) ) ;
6753 }
6854}
0 commit comments