-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOffsetCipher.java
More file actions
91 lines (80 loc) · 3.66 KB
/
OffsetCipher.java
File metadata and controls
91 lines (80 loc) · 3.66 KB
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package org.example;
import java.util.*;
public class OffsetCipher implements Cipher {
private Character[] referenceTable;
public OffsetCipher() {
referenceTable = new Character[] {
//inline char array for faster instantiation than list, plus it is a size-immutable reference table
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'(', ')', '*', '+', ',', '-', '.', '/'
};
}
public Character[] getReferenceTable() {
return referenceTable;
}
public void setReferenceTable(Character[] referenceTable) {
this.referenceTable = referenceTable;
}
public char getOffset(String target) {
char offset = target.toCharArray()[0];
if (!isCharValid(offset))
throw new IllegalArgumentException("Input character array is not valid given the reference table.");
else
return offset;
}
public String getString(String target) {
return target.substring(1);
}
public String encode (String plainText){
char[] plainTextChar = getString(plainText).toCharArray();
int offsetIdx = findIdxInReferenceTable(getOffset(plainText));
Map<Character,Character> encodeMapper = getMapper(offsetIdx,true);
////debug here if needed
//displayMapper(encodeMapper);
return getOffset(plainText) + constructProcessedString(plainTextChar,encodeMapper);
}
public String decode (String encodedText){
char[] encodedTextChar = getString(encodedText).toCharArray();
int offsetIdx = findIdxInReferenceTable(getOffset(encodedText));
Map<Character,Character> decodeMapper = getMapper(offsetIdx,false);
return getOffset(encodedText) + constructProcessedString(encodedTextChar,decodeMapper);
}
private Map<Character,Character> getMapper(int offsetIdx, boolean isEncoding){
Map<Character,Character> mapper = new HashMap<>();
int referenceTableRange = referenceTable.length;
for (int i=0; i<referenceTableRange; i++) {
int newIdx;
if (isEncoding)
newIdx = ((i-offsetIdx) % referenceTableRange + referenceTableRange) % referenceTableRange;
else
newIdx = ((i+offsetIdx) % referenceTableRange);
mapper.put(referenceTable[i],referenceTable[newIdx]);
}
return mapper;
}
private String constructProcessedString(char[] unprocessedCharArray, Map<Character,Character> mapper){
StringBuilder decodedString = new StringBuilder();
for (int i=0;i<unprocessedCharArray.length;i++){
if(isCharValid(unprocessedCharArray[i]))
decodedString.append(mapper.get(unprocessedCharArray[i]));
else
decodedString.append(unprocessedCharArray[i]);
}
return decodedString.toString();
}
private int findIdxInReferenceTable(Character character){
for (int i=0;i<referenceTable.length;i++){
if (referenceTable[i] == character)
return i;
}
throw new IllegalArgumentException("Input character array is not valid given the reference array.");
}
private boolean isCharValid(Character target){
return Arrays.stream(referenceTable).anyMatch(element -> element == target);
}
private void displayMapper(Map<Character,Character> mapper){
mapper.entrySet().stream().sorted(Comparator.comparingInt(entry -> findIdxInReferenceTable(entry.getKey()))).forEach(System.out::println);
}
}