import java.util.* ;
public class Main {
public static void main
( String [ ] args
) { int [ ] ciphertext = {
102 , 141 , 142 , 161 , 148 , 131 , 158 , 157 , 120 , 131 ,
126 , 153 , 130 , 143 , 154 , 135 , 118 , 137 , 148 , 111 ,
116 , 145 , 134 , 133 , 118 , 103 , 136 , 107 , 138 , 127 ,
102 , 131 , 194 , 99 , 114 , 200 , 202 , 127 , 120 , 105 ,
126 , 202 , 108 , 194 , 198 , 214 , 222 , 204 , 116 , 224 ,
194 , 198 , 202 , 230 , 166 , 222 , 216 , 234 , 232 , 210 ,
222 , 220 , 210 , 230 , 194 , 230 , 198 , 210 , 210 , 230 ,
234 , 218 , 222 , 204 , 194 , 216 , 216 , 224 , 216 , 194 ,
210 , 220 , 232 , 202 , 240 , 232 , 198 , 208 , 194 , 228 , 230
} ;
List< String> possibleSolutions = decryptAll( ciphertext) ;
System .
out .
println ( "\n Top possible solutions:" ) ; for ( String solution
: possibleSolutions
) { }
}
public static List< String> decryptAll( int [ ] ct) {
int length = ct.length ;
List< String> solutions = new ArrayList<> ( ) ;
Map
< Integer , String
> keyToText
= new HashMap
<> ( ) ;
System .
out .
println ( "Testing all possible keys..." ) ;
for ( int initialKey = length/ 2 ; initialKey <= length; initialKey++ ) {
StringBuilder plaintext = new StringBuilder( ) ;
boolean valid = true ;
int currentKey = initialKey;
for ( int encrypted : ct) {
boolean found = false ;
// Try all ASCII characters (0-255)
for ( int c = 0 ; c <= 255 ; c++ ) {
if ( c + ( c % currentKey) == encrypted) {
plaintext.append ( ( char ) c) ;
found = true ;
break ;
}
}
if ( ! found) {
valid = false ;
break ;
}
currentKey++;
}
if ( valid) {
String solution
= plaintext.
toString ( ) ; solutions.add ( solution) ;
keyToText.put ( initialKey, solution) ;
}
}
// Score solutions by English-like characteristics
solutions.sort ( ( a, b) -> {
int scoreA = englishScore( a) ;
int scoreB = englishScore( b) ;
return Integer .
compare ( scoreB, scoreA
) ; } ) ;
return solutions.
subList ( 0 ,
Math .
min ( 5 , solutions.
size ( ) ) ) ; }
private static int englishScore
( String text
) { int score = 0 ;
String commonLetters
= "etaoinshrdlu ETAOINSHRDLU" ;
for ( char c : text.toCharArray ( ) ) {
if ( commonLetters.indexOf ( c) >= 0 ) score += 2 ;
else if ( c >= 32 && c <= 126 ) score += 1 ;
if ( Character .
isLetterOrDigit ( c
) ) score
+= 1 ; }
return score;
}
}
aW1wb3J0IGphdmEudXRpbC4qOwoKcHVibGljIGNsYXNzIE1haW4gewogICAgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgewogICAgICAgIGludFtdIGNpcGhlcnRleHQgPSB7CiAgICAgICAgICAgIDEwMiwgMTQxLCAxNDIsIDE2MSwgMTQ4LCAxMzEsIDE1OCwgMTU3LCAxMjAsIDEzMSwgCiAgICAgICAgICAgIDEyNiwgMTUzLCAxMzAsIDE0MywgMTU0LCAxMzUsIDExOCwgMTM3LCAxNDgsIDExMSwgCiAgICAgICAgICAgIDExNiwgMTQ1LCAxMzQsIDEzMywgMTE4LCAxMDMsIDEzNiwgMTA3LCAxMzgsIDEyNywgCiAgICAgICAgICAgIDEwMiwgMTMxLCAxOTQsIDk5LCAxMTQsIDIwMCwgMjAyLCAxMjcsIDEyMCwgMTA1LCAKICAgICAgICAgICAgMTI2LCAyMDIsIDEwOCwgMTk0LCAxOTgsIDIxNCwgMjIyLCAyMDQsIDExNiwgMjI0LCAKICAgICAgICAgICAgMTk0LCAxOTgsIDIwMiwgMjMwLCAxNjYsIDIyMiwgMjE2LCAyMzQsIDIzMiwgMjEwLCAKICAgICAgICAgICAgMjIyLCAyMjAsIDIxMCwgMjMwLCAxOTQsIDIzMCwgMTk4LCAyMTAsIDIxMCwgMjMwLCAKICAgICAgICAgICAgMjM0LCAyMTgsIDIyMiwgMjA0LCAxOTQsIDIxNiwgMjE2LCAyMjQsIDIxNiwgMTk0LCAKICAgICAgICAgICAgMjEwLCAyMjAsIDIzMiwgMjAyLCAyNDAsIDIzMiwgMTk4LCAyMDgsIDE5NCwgMjI4LCAyMzAKICAgICAgICB9OwogICAgICAgIAogICAgICAgIExpc3Q8U3RyaW5nPiBwb3NzaWJsZVNvbHV0aW9ucyA9IGRlY3J5cHRBbGwoY2lwaGVydGV4dCk7CiAgICAgICAgCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJcblRvcCBwb3NzaWJsZSBzb2x1dGlvbnM6Iik7CiAgICAgICAgZm9yIChTdHJpbmcgc29sdXRpb24gOiBwb3NzaWJsZVNvbHV0aW9ucykgewogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oc29sdXRpb24pOwogICAgICAgIH0KICAgIH0KICAgIAogICAgcHVibGljIHN0YXRpYyBMaXN0PFN0cmluZz4gZGVjcnlwdEFsbChpbnRbXSBjdCkgewogICAgICAgIGludCBsZW5ndGggPSBjdC5sZW5ndGg7CiAgICAgICAgTGlzdDxTdHJpbmc+IHNvbHV0aW9ucyA9IG5ldyBBcnJheUxpc3Q8PigpOwogICAgICAgIE1hcDxJbnRlZ2VyLCBTdHJpbmc+IGtleVRvVGV4dCA9IG5ldyBIYXNoTWFwPD4oKTsKICAgICAgICAKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIlRlc3RpbmcgYWxsIHBvc3NpYmxlIGtleXMuLi4iKTsKICAgICAgICAKICAgICAgICBmb3IgKGludCBpbml0aWFsS2V5ID0gbGVuZ3RoLzI7IGluaXRpYWxLZXkgPD0gbGVuZ3RoOyBpbml0aWFsS2V5KyspIHsKICAgICAgICAgICAgU3RyaW5nQnVpbGRlciBwbGFpbnRleHQgPSBuZXcgU3RyaW5nQnVpbGRlcigpOwogICAgICAgICAgICBib29sZWFuIHZhbGlkID0gdHJ1ZTsKICAgICAgICAgICAgaW50IGN1cnJlbnRLZXkgPSBpbml0aWFsS2V5OwogICAgICAgICAgICAKICAgICAgICAgICAgZm9yIChpbnQgZW5jcnlwdGVkIDogY3QpIHsKICAgICAgICAgICAgICAgIGJvb2xlYW4gZm91bmQgPSBmYWxzZTsKICAgICAgICAgICAgICAgIC8vIFRyeSBhbGwgQVNDSUkgY2hhcmFjdGVycyAoMC0yNTUpCiAgICAgICAgICAgICAgICBmb3IgKGludCBjID0gMDsgYyA8PSAyNTU7IGMrKykgewogICAgICAgICAgICAgICAgICAgIGlmIChjICsgKGMgJSBjdXJyZW50S2V5KSA9PSBlbmNyeXB0ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcGxhaW50ZXh0LmFwcGVuZCgoY2hhciljKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGlmICghZm91bmQpIHsKICAgICAgICAgICAgICAgICAgICB2YWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBjdXJyZW50S2V5Kys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIGlmICh2YWxpZCkgewogICAgICAgICAgICAgICAgU3RyaW5nIHNvbHV0aW9uID0gcGxhaW50ZXh0LnRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgICBzb2x1dGlvbnMuYWRkKHNvbHV0aW9uKTsKICAgICAgICAgICAgICAgIGtleVRvVGV4dC5wdXQoaW5pdGlhbEtleSwgc29sdXRpb24pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIC8vIFNjb3JlIHNvbHV0aW9ucyBieSBFbmdsaXNoLWxpa2UgY2hhcmFjdGVyaXN0aWNzCiAgICAgICAgc29sdXRpb25zLnNvcnQoKGEsIGIpIC0+IHsKICAgICAgICAgICAgaW50IHNjb3JlQSA9IGVuZ2xpc2hTY29yZShhKTsKICAgICAgICAgICAgaW50IHNjb3JlQiA9IGVuZ2xpc2hTY29yZShiKTsKICAgICAgICAgICAgcmV0dXJuIEludGVnZXIuY29tcGFyZShzY29yZUIsIHNjb3JlQSk7CiAgICAgICAgfSk7CiAgICAgICAgCiAgICAgICAgcmV0dXJuIHNvbHV0aW9ucy5zdWJMaXN0KDAsIE1hdGgubWluKDUsIHNvbHV0aW9ucy5zaXplKCkpKTsKICAgIH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgaW50IGVuZ2xpc2hTY29yZShTdHJpbmcgdGV4dCkgewogICAgICAgIGludCBzY29yZSA9IDA7CiAgICAgICAgU3RyaW5nIGNvbW1vbkxldHRlcnMgPSAiZXRhb2luc2hyZGx1IEVUQU9JTlNIUkRMVSI7CiAgICAgICAgCiAgICAgICAgZm9yIChjaGFyIGMgOiB0ZXh0LnRvQ2hhckFycmF5KCkpIHsKICAgICAgICAgICAgaWYgKGNvbW1vbkxldHRlcnMuaW5kZXhPZihjKSA+PSAwKSBzY29yZSArPSAyOwogICAgICAgICAgICBlbHNlIGlmIChjID49IDMyICYmIGMgPD0gMTI2KSBzY29yZSArPSAxOwogICAgICAgICAgICBpZiAoQ2hhcmFjdGVyLmlzTGV0dGVyT3JEaWdpdChjKSApc2NvcmUgKz0gMTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgcmV0dXJuIHNjb3JlOwogICAgfQp9