diff --git a/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Baconian.java b/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Baconian.java new file mode 100644 index 0000000..4eb0364 --- /dev/null +++ b/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Baconian.java @@ -0,0 +1,134 @@ +//CipherStreamJava/src/test/java/com/mattrixwv/CipherStreamJava/Baconian.java +//Mattrixwv +// Created: 01-12-22 +//Modified: 01-12-22 +package com.mattrixwv.CipherStreamJava.monoSubstitution; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.StringJoiner; + +import com.mattrixwv.CipherStreamJava.exceptions.InvalidCharacterException; + +public class Baconian{ + private static final ArrayList code = new ArrayList(Arrays.asList( + "aaaaa", "aaaab", "aaaba", "aaabb", "aabaa", "aabab", "aabba","aabbb", "abaaa", "abaaa", "abaab", "ababa", "ababb", //A-M + "abbaa", "abbab", "abbba", "abbbb", "baaaa", "baaab", "baaba", "baabb", "baabb", "babaa", "babab", "babba", "babbb" //N-Z + )); + private String inputString; //The string that needs encoded/decoded + private String outputString; //The encoded/decoded string + private boolean leaveCapitals; //Whether to respect capitals in the output string + + //Sets the input string + private void setInputStringEncode(String inputString){ + //Remove all whitespace and symbols + inputString = inputString.replaceAll("[^A-Za-z]", ""); + if(!leaveCapitals){ + inputString = inputString.toLowerCase(); + } + + this.inputString = inputString; + } + private void setInputStringDecode(String inputString) throws InvalidCharacterException{ + if(!leaveCapitals){ + inputString = inputString.toLowerCase(); + } + + //Check each Baconian Cipher letter for validity + for(String str : inputString.split(" ")){ + //Make sure each letter contains 5 characters + if(str.length() != 5){ + throw new InvalidCharacterException("All Baconian letters contain exactly 5 characters: " + str); + } + //Make sure the letter contains only a's and b's + String temp = str.replaceAll("[^abAB]", ""); + if(!temp.equals(str)){ + throw new InvalidCharacterException("Baconian letters contain only a's and b's: " + str); + } + } + + this.inputString = inputString; + } + //Encodes the inputString and stores the result in outputString + private String encode(){ + StringJoiner output = new StringJoiner(" "); + //Go through every character in the inputString and encode it + for(char ch : inputString.toCharArray()){ + //Convert the character to a binary string with A = 0 + String binary = null; + if(Character.isUpperCase(ch)){ + binary = code.get(ch - 'A').toUpperCase(); + } + else{ + binary = code.get(ch - 'a').toLowerCase(); + } + + //Add the encoded character to the output + output.add(binary); + } + + //Save and return the output + outputString = output.toString(); + return outputString; + } + //Decodes the inputString and stores the result in outputString + private String decode(){ + StringBuilder output = new StringBuilder(); + //Go through every Baconian Cipher character in the inputString and decode it + for(String baconianCharacter : inputString.split(" ")){ + //Get the location of the Baconian character in the array + int location = code.indexOf(baconianCharacter.toLowerCase()); + + //Convert the Baconian character to an ASCII character + char ch = '\0'; + if(Character.isUpperCase(baconianCharacter.charAt(0))){ + ch = (char)(location + 'A'); + } + else{ + ch = (char)(location + 'a'); + } + + //Add the decoded character to the output + output.append(ch); + } + + //Save and return the output + outputString = output.toString(); + return outputString; + } + + //Constructor + public Baconian(){ + reset(); + leaveCapitals = false; + } + public Baconian(boolean leaveCapitals){ + reset(); + this.leaveCapitals = leaveCapitals; + } + //Returns the outputString + public String getOutputString(){ + return outputString; + } + //Returns the inputString + public String getInputString(){ + return inputString; + } + //Sets the inputString and encodes the message + public String encode(String inputString){ + reset(); + setInputStringEncode(inputString); + return encode(); + } + //Sets the inputString and decodes the message + public String decode(String inputString) throws InvalidCharacterException{ + reset(); + setInputStringDecode(inputString); + return decode(); + } + //Makes sure all of the variables are empty + public void reset(){ + inputString = ""; + outputString = ""; + } +} diff --git a/src/test/java/com/mattrixwv/CipherStreamJava/monoSubstitution/TestBaconian.java b/src/test/java/com/mattrixwv/CipherStreamJava/monoSubstitution/TestBaconian.java new file mode 100644 index 0000000..cb3a207 --- /dev/null +++ b/src/test/java/com/mattrixwv/CipherStreamJava/monoSubstitution/TestBaconian.java @@ -0,0 +1,100 @@ +//CipherStreamJava/src/test/java/com/mattrixwv/CipherStreamJava/TestBaconian.java +//Mattrixwv +// Created: 01-12-22 +//Modified: 01-12-22 +package com.mattrixwv.CipherStreamJava.monoSubstitution; + + +import static org.junit.Assert.assertEquals; + +import com.mattrixwv.CipherStreamJava.exceptions.InvalidCharacterException; + +import org.junit.Test; + + +public class TestBaconian{ + @Test + public void testDecode() throws InvalidCharacterException{ + Baconian cipher = new Baconian(true); + + //Test lowercase decoding + String inputString = "ababb aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + String correctOutput = "messagetoencode"; + String output = cipher.decode(inputString); + assertEquals("Baconian failed lowercase decoding.", correctOutput, output); + //Test uppercase decoding + inputString = "ABABB AABAA BAAAB BAAAB AAAAA AABBA AABAA BAABA ABBAB AABAA ABBAA AAABA ABBAB AAABB AABAA"; + correctOutput = "MESSAGETOENCODE"; + output = cipher.decode(inputString); + assertEquals("Baconian failed uppercase decoding.", correctOutput, output); + + //Test mixed case, whitespace, and symbol decoding + inputString = "ABABB aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + correctOutput = "Messagetoencode"; + output = cipher.decode(inputString); + assertEquals("Baconian failed mixed case, whitespace, and symbol decoding.", correctOutput, output); + } + @Test + public void testDecodeNoCapital() throws InvalidCharacterException{ + Baconian cipher = new Baconian(false); + + //Test lowercase decoding + String inputString = "ababb aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + String correctOutput = "messagetoencode"; + String output = cipher.decode(inputString); + assertEquals("Baconian failed no capital lowercase decoding.", correctOutput, output); + //Test uppercase decoding + inputString = "ABABB AABAA BAAAB BAAAB AAAAA AABBA AABAA BAABA ABBAB AABAA ABBAA AAABA ABBAB AAABB AABAA"; + correctOutput = "messagetoencode"; + output = cipher.decode(inputString); + assertEquals("Baconian failed no capital uppercase decoding.", correctOutput, output); + + //Test mixed case, whitespace, and symbol decoding + inputString = "ABABB aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + correctOutput = "messagetoencode"; + output = cipher.decode(inputString); + assertEquals("Baconian failed no capital mixed case, whitespace, and symbol decoding.", correctOutput, output); + } + @Test + public void testEncode(){ + Baconian cipher = new Baconian(true); + + //Test lowercase encoding + String inputString = "messagetoencode"; + String correctOutput = "ababb aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + String output = cipher.encode(inputString); + assertEquals("Baconian failed lowercase encoding.", correctOutput, output); + //Test uppercase encoding + inputString = "MESSAGETOENCODE"; + correctOutput = "ABABB AABAA BAAAB BAAAB AAAAA AABBA AABAA BAABA ABBAB AABAA ABBAA AAABA ABBAB AAABB AABAA"; + output = cipher.encode(inputString); + assertEquals("Baconian failed uppercase encoding.", correctOutput, output); + + //Test mixed case, whitespace, and symbol encoding + inputString = "Message to-encode"; + correctOutput = "ABABB aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + output = cipher.encode(inputString); + assertEquals("Baconian failed mixed case, whitespace, and symbol encoding.", correctOutput, output); + } + @Test + public void testEncodeNoCapital(){ + Baconian cipher = new Baconian(false); + + //Test lowercase encoding + String inputString = "messagetoencode"; + String correctOutput = "ababb aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + String output = cipher.encode(inputString); + assertEquals("Baconian failed no capital lowercase encoding.", correctOutput, output); + //Test uppercase encoding + inputString = "MESSAGETOENCODE"; + correctOutput = "ababb aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + output = cipher.encode(inputString); + assertEquals("Baconian failed no capital uppercase encoding.", correctOutput, output); + + //Test mixed case, whitespace, and symbol encoding + inputString = "Message to-encode"; + correctOutput = "ababb aabaa baaab baaab aaaaa aabba aabaa baaba abbab aabaa abbaa aaaba abbab aaabb aabaa"; + output = cipher.encode(inputString); + assertEquals("Baconian failed no capital mixed case, whitespace, and symbol encoding.", correctOutput, output); + } +}