This commit is contained in:
louiscklaw
2025-02-01 01:58:47 +08:00
parent b3da7aaef5
commit 04dbefcbaf
1259 changed files with 280657 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
public class DuplicateValException extends RuntimeException{
public DuplicateValException(){
super("Duplicate value");
}
}

View File

@@ -0,0 +1,5 @@
class EmptyListException extends Exception {
public EmptyListException(){
super("Empty List");
}
}

View File

@@ -0,0 +1,253 @@
public class LinkedList {
private ListNode head;
private ListNode tail;
public LinkedList() {
head = null;
tail = null;
}
public boolean isEmpty() {
return (head == null);
}
public void addToHead(Object item) {
if (isEmpty()) {
head = tail = new ListNode(item);
} else {
head = new ListNode(item, head);
}
}
public void addToTail(Object item) {
if (isEmpty()) {
head = tail = new ListNode(item);
} else {
tail.next = new ListNode(item);
tail = tail.next;
}
}
public Object removeFromHead() throws EmptyListException {
if (isEmpty()) {
throw new EmptyListException();
}
Object item = head.data;
if (head == tail) {
head = tail = null;
} else {
head = head.next;
}
return item;
}
public String toString() {
String s = "[ ";
ListNode current = head;
while (current != null) {
s += current.data + " ";
current = current.next;
}
return s + "]";
}
public Object removeFromTail() throws EmptyListException {
if (isEmpty()) {
throw new EmptyListException();
}
Object item = tail.data;
if (head == tail) {
head = tail = null;
return item;
}
ListNode current = head;
while (current.next != tail) {
current = current.next;
}
tail = current;
tail.next = null;
return item;
}
public int getCount() {
int count = 0;
ListNode current = head;
while (current != null) {
count++;
current = current.next;
}
return count;
}
public void addItemAt(Object item, int n) {
if (isEmpty() || n == 0) {
head = new ListNode(item, head);
return;
}
if (n >= getCount()) {
tail.next = new ListNode(item);
} else {
int currentPos = 0;
ListNode current = head;
while (currentPos != (n - 1)) {
current = current.next;
currentPos++;
}
ListNode newNode = new ListNode(item);
newNode.next = current.next;
current.next = newNode;
}
}
public Object removeItemAt(int n) throws EmptyListException {
if (n < 0 || n > getCount()) {
throw new IndexOutOfBoundsException();
}
if (n == 0) {
return (removeFromHead());
}
int currentPos = 0;
ListNode current = head;
while (currentPos < (n - 1)) {
current = current.next;
currentPos++;
}
Object item = current.next.data;
current.next = current.next.next;
return item;
}
public Object getItemAt(int n) {
if (n < 0 || n > getCount()) {
throw new IndexOutOfBoundsException();
}
int currentPos = 0;
ListNode current = head;
while (currentPos < n) {
current = current.next;
currentPos++;
}
return current.data;
}
public int searchItemAt(Object item) { // search the item position
ListNode current = head; // create the pointer to head
int currentPos = 0; // let the position as 0, the linkedlist with start at 0
while (current != null) { // search the item until the linkedlist tail -> null
if (current.data == item) { // if found the same data in the linkedlist will break
break;
}
current = current.next;
currentPos++; // if current data is not equal to we may found data so the position will add 1 to calculate current Node position.
}
return currentPos; // return the search item position
}
public boolean checkDup(){
ListNode current=head;
boolean checkDup = false;
while (current!=null){
ListNode currentSec = current.next;
while(currentSec !=null){
if(current.data.equals(currentSec.data)){
checkDup = true;
break;
}
currentSec= currentSec.next;
}
if(checkDup)
break;
current=current.next;
}
return checkDup;
}
public void findJokerA() throws EmptyListException { // switch the card 27 and 27 next card
if (tail.data.equals(27)) { // In special case, if the tail data is 27
Object cache = head.data; // cache the data of head data, because the tail data will replcae the head data when the card switch
tail.data = cache; // tail data will equal to head data when the card switch
head.data = 27; // head data equal the 27 when the case of 27 is tail data
} else {
ListNode current = head; // create the pointer to head of ListNode
while (!current.data.equals(27)) { // find the ListNode position and the ListNode data is 27
current = current.next; // if ListNode data is not 27 will point to next Node
}
Object cache = current.next.data; // set the cache data of next current position
current.data = cache; // current position set to data of next current position
current.next.data = 27; // the next current position set to 27
}
}
public void findJokerB() throws EmptyListException {// switch the card 28, 28 next card and 28 next next card
if (tail.data.equals(28)) { // In special case, if the tail data is 28
Object cache = head.data; // set cache data of head data, because the tail data will replcae the head data when the card switch
tail.data = cache; // tail data will set to head data
head.data = head.next.data; // The head data will set to head next data
head.next.data = 28; // The head next data will set to 28
} else if (searchItemAt(28) == 26) { // In special case, if the tail before data is 28
Object cachetail = removeFromTail(); // set the cache data of Tail data and remove tail data
tail.data = cachetail; // In currenly, the total count card is 27. The tail data set to cache data (remove tail data in line 171)
addToTail(head.data); // Add to tail of head data in the LinkedList and the total count card is 28
head.data = 28; // set the 28 is head data.
} else {
ListNode current = head; // create the pointer to head of ListNode
while (!current.data.equals(28)) { // find the ListNode position and the ListNode data is 28
current = current.next; // if ListNode data is not 28 will point to next Node
}
Object cache = current.next.data; // set cache data is current next data and current next next data
Object cacheTwo = current.next.next.data;
current.data = cache; // current data position is 28 so set the data to current next data
current.next.data = cacheTwo; // 28 after data set to current next next data
current.next.next.data = 28; // the current next next data set to 28
}
}
public void tripleCut() throws EmptyListException {
LinkedList cacheLeft = new LinkedList(); //Create the LinkedList to store cut data in Left and Right
LinkedList cacheRight = new LinkedList();
int listRightSize, listLeftSize;
if (searchItemAt(27) > searchItemAt(28)) { // search the data is 27 and 28, if the 27 position larger that of 28 position will cut right hand site(Tail), and the 28 will left hand site(Head)
listRightSize = getCount() - searchItemAt(27) - 1; // calcuate the 27 how many value should cut
listLeftSize = searchItemAt(28); // the 28 should cut the current position value
} else { // otherwise the 28 position larger that of 27 position will cut right hand site(Tail) and the 27 will cut left hand site(Head)
listRightSize = getCount() - searchItemAt(28) - 1; // calcuate the 28 how many value should cut
listLeftSize = searchItemAt(27); // the 27 should cut the current position value
}
for (int i = 0; i < listRightSize; i++) {
cacheRight.addToTail(removeFromTail()); //cut right hand sit and put the value to cacheRight LinkedList
}
for (int i = 0; i < listLeftSize; i++) {
cacheLeft.addToTail(removeFromHead()); // cut left hand sit and put the value to cacheLeft LinkedList
}
for (int i = 0; i < listRightSize; i++) {
addToHead(cacheRight.removeFromHead()); // store all value of cacheRight LinkedList to Left Hand site (Head)
}
for (int i = 0; i < listLeftSize; i++) {
addToTail(cacheLeft.removeFromHead()); // store all vale of cacheLeft LinkedList to Right Hand site (Tail)
}
}
public void countCut() throws EmptyListException {
if (tail.data.equals(28)) { // if tail data is 28
return; // Not to do
} else {
Object item = removeFromTail(); // remove the tail data and store the value to item
for (int i = 0; i < (int) item; i++) { // According the item value to put the head Node to Tail Node of number
addToTail(removeFromHead());
}
addToTail(item); // put the item value(in line 219) to Tail.
}
}
public Object topCard() throws EmptyListException {
if (head.data.equals(28)|| head.data.equals(27)) { //when the head data is 28 or 27 will return the tail data
return tail.data;
} else { // the head data is not 28 or 28 will return the search of head data position
return getItemAt((int) head.data);
}
}
}

View File

@@ -0,0 +1,16 @@
public class ListNode {
Object data;
ListNode next;
public ListNode(){
data=null;
next=null;
}
public ListNode(Object data){
this.data = data;
this.next = null;
}
public ListNode(Object data, ListNode next){
this.data = data;
this.next = next;
}
}

View File

@@ -0,0 +1,5 @@
public class NotJokerException extends RuntimeException{
public NotJokerException(){
super("Not Joker");
}
}

View File

@@ -0,0 +1,5 @@
public class NotMatchTypeException extends RuntimeException {
public NotMatchTypeException(){
super("Total card should be 28 and Integer number");
}
}

View File

@@ -0,0 +1,11 @@
# ITP4510-Assignment
ITP4510 Data Structures &amp; Algorithms: Concepts &amp; Implementation
### Setup
```
$ javac SolitaireEncryption.java
```
### Usage
```
$ java SolitaireEncryption <option(en|de|keygen)> <deck_File_Path> <message_string>
```

View File

@@ -0,0 +1,122 @@
// Name: Kwok Ho Hin
// Student ID: 180160427
// Program code-Class: IT114105-1B
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class SolitaireEncryption {
public static void main(String[] args) {
try {
LinkedList qll = new LinkedList(); //Object of LinkedList
Scanner input = new Scanner(new File(args[1]));
while (input.hasNextInt()) { //if the text file has Integer will put to qll LinkedList, when the text file contain other data type will stop input
qll.addToTail(input.nextInt());
}
input.close();
if (qll.getCount() != 28) { //check the qll whether 28 card, if not 28 card will Stop the program
throw new NotMatchTypeException();
}
if (qll.searchItemAt(27) == 28 || qll.searchItemAt(28) == 28) {
throw new NotJokerException(); // check the qll whether contain Joker
}
if (qll.checkDup()) {
throw new DuplicateValException(); // check the qll whether contain Duplicate Value
}
if (args[0].equals("keygen") || args[0].equals("en") || args[0].equals("de")) { //args[0] should be 3 type: keygen, en or de
keygen(args[2], qll, args[0]);
} else {
System.out.println("Sorry: keygen||en||de FileLocation Word"); //not keygen, en or de
}
} catch (FileNotFoundException e) {
System.out.println("File Not Found in " + args[1]); //Can not found the File so throw FileNotFoundException
} catch (IndexOutOfBoundsException e) {
System.out.println("Can not Encryption or Decryption the message"); //Encryption and Decryption use the array to store the message so it may throw IndexOutOfBoundsException
} catch (DuplicateValException e) {
System.out.println("Text file contain Duplicate value"); //Duplicate value
} catch (NotMatchTypeException e) {
System.out.println("Total card should be 28 and Integer number"); //Number of card is not 28 so throw NotMatchTypeException
} catch (NotJokerException e) {
System.out.println("Not contain all Joker (27, 28)");
} catch (EmptyListException e) {
System.out.println("Empty List"); //when the LinkedList remove the node so it may EmptyListException occure
} catch (Exception e) {
System.out.println("Unknow Error");
}
}
public static void keygen(String args, LinkedList qll, String type) throws EmptyListException {
LinkedList keystreamVal = new LinkedList(); //Create the LinkedList to store the keystream Value
args = args.replaceAll("\\s", "").toUpperCase(); //Trim the String of the args[2] and change to Upper Case.
for (int i = 0; i < args.length(); i++) { //each args[2] Sting will generate the keystream Value
qll.findJokerA(); //call the LinkedList method to findJokerA
keygenPrint("S1: ", type, qll); //check the args[0] wether "keygen"
qll.findJokerB(); //call the LinkedList method to findJokerB
keygenPrint("S2: ", type, qll); //check the args[0] wether "keygen"
qll.tripleCut(); //call the LinkedList method to cut the card
keygenPrint("S3: ", type, qll); //check the args[0] wether "keygen"
qll.countCut(); //call the LinkedList method to count cut
keygenPrint("S4: ", type, qll); //check the args[0] wether "keygen"
if (!qll.topCard().equals(28) && !qll.topCard().equals(27)) { //call the LinkedList method and return the keystream value, if keystream value not 27 or 28
keygenPrint("Key " + (i + 1) + ": ", type, qll.topCard()); //check the args[0] wether "keygen"
keystreamVal.addToTail(qll.topCard()); //add the keystreamVal to keystreamVal LinkedList
} else {
keygenPrint("Joker", type, qll); //check the args[0] wether "keygen"
i--; //if Is Joker will skip this position so i--
}
}
if (type.equals("en") || type.equals("de")) { //check wether "en" or "de" and wether keep running
message(args, keystreamVal, type);
} else {
System.out.println("Keystream values:" + keystreamVal); //Keystream values
}
}
public static void message(String args, LinkedList keystreamVal, String type) throws EmptyListException {
Object[] message = new Object[args.length()]; // set the message array to store encryption or decryption message
int sum = 0; // set each encryption or decrpytion message vale of 0
for (int i = 0; i < args.length(); i++) { // each char will encryption or decrpytion
System.out.print(args.charAt(i) + "\t" + (letter().searchItemAt(args.charAt(i)) + 1) + "\t" + keystreamVal.getItemAt(i)); // print the current char, and char number and keystream Value
if (type.equals("en")) { // Encrpytion Procedure
sum = (int) keystreamVal.getItemAt(i) + (int) (letter().searchItemAt(args.charAt(i)) + 1); // keystream + char number and store in sum Varible
if (sum > 26) { // if the sum is > 26 should be -26
sum -= 26;
}
} else if (type.equals("de")) { // Decrpytion Procedure
sum = (int) (letter().searchItemAt(args.charAt(i)) + 1) - (int) keystreamVal.getItemAt(i); // Char number - keystream Value and store in sum Varible
if (sum < 1) { // if the sum is < 0 should be +26
sum += 26;
}
}
message[i] = (letter().getItemAt((sum - 1))); // store the all encrypted or decrypted message in message array
System.out.print("\t" + sum + "\t" + (letter().getItemAt(sum - 1)) + "\n"); // print the encrypted or decrypted message and char
if (i == args.length() - 1 && type.equals("en")) { // print the encrypted or decrypted message in message array
System.out.print("Encrypted message: ");
} else if (i == args.length() - 1 && type.equals("de")) {
System.out.print("Decrypted message: ");
}
}
for (int i = 0; i < message.length; i++) {
System.out.print(message[i]);
}
}
public static void keygenPrint(String number, String type, Object qll) {
if (type.equals("keygen") && !number.equals("Joker")) { //check wether keygen and print the linkedList
System.out.println(number + ":" + qll);
} else if (type.equals("keygen") &&number.equals("Joker")) {
System.out.println(number + ": Key skipped");
}
}
public static LinkedList letter() {
LinkedList letter = new LinkedList(); //set the LinkedList to store the A-Z char
for (char alph = 'A'; alph <= 'Z'; alph++) {
letter.addToTail(alph);
}
return letter;
}
}

View File

@@ -0,0 +1 @@
1 4 7 10 13 16 19 22 25 28 3 6 9 12 15 18 21 24 27 2 5 8 11 14 17 20 23 26

View File

@@ -0,0 +1 @@
21 16 10 9 5 1 13 14 17 22 23 4 20 28 6 2 24 19 15 27 18 26 25 11 12 7 8 3

View File

@@ -0,0 +1 @@
13 10 19 25 8 12 20 18 26 1 9 22 15 3 17 24 2 21 23 27 7 14 5 4 28 11 16 6

View File

@@ -0,0 +1,2 @@
28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1

View File

@@ -0,0 +1 @@
18 27 2 8 26 23 24 17 22 21 4 25 9 15 3 19 14 12 5 13 1 7 10 16 6 1 20 28

View File

@@ -0,0 +1 @@
27 4 22 10 15 9 7 13 12 19 26 25 20 6 18 8 2 17 21 3 23 11 14 24 1 16 28 5

View File

@@ -0,0 +1,2 @@
5 4 22 10 15 9 7 13 12 19 26 25 20 6 18 8 2 17 21 3 23 11 14 24 1 28 16 27

View File

@@ -0,0 +1 @@
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