Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * A Generalized Lewis Carroll Cipher
- *
- * @author Sean Allred
- * @version 9 February 2012
- */
- public class Cipher {
- private static final int UPPER_CASE_SHIFT = 65;
- private static final int LOWER_CASE_SHIFT = 97;
- private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
- /**
- * The standard Tabula Recta as provided by Wikipedia
- */
- public static final char[][] stdTabulaRecta = {
- "abcdefghijklmnopqrstuvwxyz".toCharArray(),
- "bcdefghijklmnopqrstuvwxyza".toCharArray(),
- "cdefghijklmnopqrstuvwxyzab".toCharArray(),
- "defghijklmnopqrstuvwxyzabc".toCharArray(),
- "efghijklmnopqrstuvwxyzabcd".toCharArray(),
- "fghijklmnopqrstuvwxyzabcde".toCharArray(),
- "ghijklmnopqrstuvwxyzabcdef".toCharArray(),
- "hijklmnopqrstuvwxyzabcdefg".toCharArray(),
- "ijklmnopqrstuvwxyzabcdefgh".toCharArray(),
- "jklmnopqrstuvwxyzabcdefghi".toCharArray(),
- "klmnopqrstuvwxyzabcdefghij".toCharArray(),
- "lmnopqrstuvwxyzabcdefghijk".toCharArray(),
- "mnopqrstuvwxyzabcdefghijkl".toCharArray(),
- "nopqrstuvwxyzabcdefghijklm".toCharArray(),
- "opqrstuvwxyzabcdefghijklmn".toCharArray(),
- "pqrstuvwxyzabcdefghijklmno".toCharArray(),
- "qrstuvwxyzabcdefghijklmnop".toCharArray(),
- "rstuvwxyzabcdefghijklmnopq".toCharArray(),
- "stuvwxyzabcdefghijklmnopqr".toCharArray(),
- "tuvwxyzabcdefghijklmnopqrs".toCharArray(),
- "uvwxyzabcdefghijklmnopqrsq".toCharArray(),
- "vwxyzabcdefghijklmnopqrsqt".toCharArray(),
- "wxyzabcdefghijklmnopqrsqtu".toCharArray(),
- "xyzabcdefghijklmnopqrsqtuv".toCharArray(),
- "yzabcdefghijklmnopqrsqtuvw".toCharArray(),
- "zabcdefghijklmnopqrsqtuvwx".toCharArray()
- };
- /**
- * Expands a string s to have the length l
- * @param s the String to expand
- * @param l the length of the desired String
- * @return s, copied until it has length l
- */
- private static String expand(String s, int l) {
- String ret = new String(s);
- while(ret.length() < l) {
- ret += ret;
- }
- if(ret.length() > l) {
- ret = ret.substring(0, l);
- }
- return ret;
- }
- private static String trimToLen(String s, int l) {
- return (new String(s)).substring(0, l);
- }
- private static String shorten(String s) {
- String ret = new String();
- String nxt = null;
- int len = 0;
- for(len = 1; len <= s.length(); len++) {
- ret = s.substring(0, len);
- if(2*len < s.length()) {
- nxt = s.substring(len, 2*len);
- } else {
- nxt = s.substring(len);
- }
- String t = trimToLen(ret, nxt.length());
- if(t.equalsIgnoreCase(nxt)) {
- return ret;
- }
- }
- return ret;
- }
- /**
- * Gets the position of the first character in a character array
- * @param ca a character array to search
- * @param c the search character
- * @return the index of the search character within the array
- */
- private static int getPos(char[] ca, char c) {
- c = Character.toLowerCase(c);
- for(int i = 0; i < ca.length; i++)
- if(Character.toLowerCase(ca[i]) == c)
- return i;
- return -1;
- }
- public static String getKey(char[][] tr, String decoded, String encoded) {
- char[] dec = decoded.toCharArray();
- char[] enc = encoded.toCharArray();
- char[] key = new char[decoded.length()];
- if(dec.length != enc.length) {
- System.err.println("Dumbass. The decoded and encoded messages must have the same length");
- return null;
- }
- for(int i = 0; i < dec.length; i++) {
- if(Character.isLetter(dec[i])) {
- key[i] = ALPHABET.charAt(getPos(tr[ALPHABET.indexOf(Character.toLowerCase(dec[i]))],Character.toLowerCase(enc[i])));
- } else {
- key[i] = dec[i];
- }
- }
- StringBuilder ret = new StringBuilder(new String(key));
- for(int i = 0; i < ret.length(); i++) {
- if(!Character.isLetter(ret.charAt(i)))
- ret.deleteCharAt(i--);
- }
- return shorten(ret.toString());
- }
- /**
- * The Tabula Recta used in this cipher
- */
- private char[][] tabularecta;
- /**
- * The keyword this cipher is based upon
- */
- private String keyword;
- /**
- * Set the Tabula Recta
- * @param tabularecta
- */
- public void setTabulaRecta(char[][] tabularecta) {
- //TODO: validation sudoku style
- this.tabularecta = tabularecta;
- }
- /**
- * Gets the keyword for this Cipher
- * @return
- */
- public String getKeyword() {
- return keyword;
- }
- /**
- * Sets the keyword for this Cipher
- * @param keyword the new keyword
- */
- public void setKeyword(String keyword) {
- for(int i = 0; i < keyword.length(); i++) {
- if(!Character.isLetter(keyword.charAt(i))) {
- System.err.println("Invalid keyword: letters only");
- return;
- }
- }
- this.keyword = keyword;
- }
- public Cipher() {
- this.setKeyword("a");
- }
- public Cipher(String keyword) {
- this.setKeyword(keyword);
- this.setTabulaRecta(stdTabulaRecta);
- }
- public Cipher(char[][] tabularecta) {
- this.setKeyword("a");
- this.setTabulaRecta(tabularecta);
- }
- public Cipher(String keyword, char[][] tabularecta) {
- this.setKeyword(keyword);
- this.setTabulaRecta(tabularecta);
- }
- private static char encodeChar(char[][] tr, char k, char c) {
- char ret = c;
- k = Character.toUpperCase(k);
- if(Character.isUpperCase(c)) {
- ret = Character.toUpperCase(tr[k - UPPER_CASE_SHIFT][c - UPPER_CASE_SHIFT]);
- } else if(Character.isLowerCase(c)) {
- ret = Character.toLowerCase(tr[k - UPPER_CASE_SHIFT][c - LOWER_CASE_SHIFT]);
- }
- return ret;
- }
- private static char decodeChar(char[][] tr, char k, char c) {
- char ret = c;
- k = Character.toUpperCase(k);
- if(Character.isUpperCase(c)) {
- ret = Character.toUpperCase((char)(getPos(tr[k - UPPER_CASE_SHIFT], c) + UPPER_CASE_SHIFT));
- } else if(Character.isLowerCase(c)) {
- char[] t = tr[k - UPPER_CASE_SHIFT];
- int pos = getPos(t, c);
- ret = Character.toLowerCase((char)(pos + LOWER_CASE_SHIFT));
- }
- return ret;
- }
- /**
- * Encode a message
- * @param decoded the message to encode
- * @return a encoded message based upon the Tabula Recta and Keyword of this cipher
- */
- public String encode(String decoded) {
- StringBuilder ret = new StringBuilder(decoded);
- StringBuilder key = new StringBuilder(expand(this.keyword, decoded.length()));
- for(int i = 0; i < ret.length(); i++) {
- char r = ret.charAt(i);
- if(!Character.isLetter(r))
- key.insert(i, r);
- else {
- ret.setCharAt(i, encodeChar(this.tabularecta, key.charAt(i), r));
- }
- }
- return ret.toString();
- }
- /**
- * Decode (or reverse-encode) a message
- * @param encoded the message to decode
- * @return a 'decoded' message based upon the Tabula Recta and Keyword of this cipher
- */
- public String decode(String encoded) {
- StringBuilder ret = new StringBuilder(encoded);
- StringBuilder key = new StringBuilder(expand(this.keyword, encoded.length()));
- for(int i = 0; i < ret.length(); i++) {
- char r = ret.charAt(i);
- if(!Character.isLetter(r))
- key.insert(i, r);
- else {
- ret.setCharAt(i, decodeChar(this.tabularecta, key.charAt(i), r));
- }
- }
- return ret.toString();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement