Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
## Introduction
The purpose of this project is as an extension to the [Gradle Centurion](https://github.com/Ultraviolet-Ninja/GradleCenturion) to solve more modules than those on the Centurion

This also helped me understand how to set up a multi module project with Gradle
This also helped me understand how to set up a multi-module project with Gradle

## Technologies
- Java 16
- Gradle 7.3.3
- Gradle 7.4

### Plugins
- Jacoco
- JavaFX
- Pitest
### Dependencies
- MaterialFX ver. 11.12.0
- JFoenix ver. 9.0.4
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ allprojects {
implementation 'org.jetbrains:annotations:22.0.0'

testImplementation 'org.testng:testng:7.5'
testImplementation 'org.slf4j:slf4j-api:1.7.35'
testImplementation 'org.slf4j:slf4j-api:1.7.36'
testImplementation 'org.slf4j:slf4j-simple:1.7.36'
testImplementation 'nl.jqno.equalsverifier:equalsverifier:3.9'
}
Expand Down
139 changes: 37 additions & 102 deletions core/src/main/java/core/bomb/modules/ab/boolean_venn/BooleanVenn.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,14 @@

import core.bomb.Widget;
import org.intellij.lang.annotations.Language;
import tools.filter.Regex;
import tools.logic.LogicOperator;
import org.jetbrains.annotations.NotNull;

import static tools.filter.RegexFilter.LOGIC_REGEX;
import static tools.filter.RegexFilter.LOGIC_SYMBOL_FILTER;
import static tools.filter.RegexFilter.filter;
import static tools.logic.LogicOperator.AND;
import static tools.logic.LogicOperator.IMPLIED_BY;
import static tools.logic.LogicOperator.IMPLIES;
import static tools.logic.LogicOperator.NAND;
import static tools.logic.LogicOperator.NOR;
import static tools.logic.LogicOperator.OR;
import static tools.logic.LogicOperator.LOGIC_SYMBOL_TO_ENUM_MAP;
import static tools.logic.LogicOperator.XNOR;
import static tools.logic.LogicOperator.XOR;

/**
* This class deals with the Boolean Venn Diagram module.
Expand All @@ -30,21 +23,6 @@ public class BooleanVenn extends Widget {
@Language("regexp")
private static final String AB_PRIORITY_PATTERN, BC_PRIORITY_PATTERN;

static {
AB_PRIORITY_PATTERN = "\\(A" + LOGIC_REGEX + "B\\)" + LOGIC_REGEX + "C";
BC_PRIORITY_PATTERN = "A" + LOGIC_REGEX + "\\(B" + LOGIC_REGEX + "C\\)";

TEST_CASES = new boolean[][]{
{false, false, false},
{false, false, true},
{false, true, false},
{true, false, false},
{false, true, true},
{true, false, true},
{true, true, false},
{true, true, true}};
}

/**
* Turns the String operation into a String code for the Venn Diagram to decode by choosing
* the correct method depending on which side of the operation has the priority, that being
Expand All @@ -58,113 +36,70 @@ public class BooleanVenn extends Widget {
public static @NotNull String resultCode(@NotNull String operation) throws IllegalArgumentException {
if (operation.isEmpty()) throw new IllegalArgumentException("Cannot have empty String");
return checkFormat(operation) ?
interpretAB(operation) :
interpretBC(operation);
interpretABPriority(operation) :
interpretBCPriority(operation);
}

/**
* Checks the formatting of the equation to see if it fits either of (AB)C or A(BC)
* with logic symbols in between AB and BC
*
* @param equation The valid or invalid equation
* @return Whether the equation matches the
* @throws IllegalArgumentException Format mismatch for the input equation
*/
private static boolean checkFormat(String equation) throws IllegalArgumentException {
String abPriority = filter(equation, new Regex(AB_PRIORITY_PATTERN));
String bcPriority = filter(equation, new Regex(BC_PRIORITY_PATTERN));
boolean doesMatchABPriority = equation.matches(AB_PRIORITY_PATTERN);

if (XNOR.test(abPriority.isEmpty(), bcPriority.isEmpty()))
throw new IllegalArgumentException("Format mismatch!!");
return !abPriority.isEmpty();
if (XNOR.test(doesMatchABPriority, equation.matches(BC_PRIORITY_PATTERN)))
throw new IllegalArgumentException("Format given does not match the format specified");
return doesMatchABPriority;
}

/**
* Interprets (AB)C
*
* @param operation The appropriate equation
* @return A String code that represents the state of each Venn Diagram section
* The output order is not, c, b, a, bc, ac, ab, all
*/
private static String interpretAB(String operation) {
private static String interpretABPriority(String operation) {
String logicSymbols = filter(operation, LOGIC_SYMBOL_FILTER);
StringBuilder builder = new StringBuilder();
boolean[] priorityCases = priorityOutputs(logicSymbols.substring(0, 1), A + B);
boolean[] priorityCases = priorityOutputs(logicSymbols.substring(0, 1), B);

for (int i = 0; i < TEST_CASES.length; i++)
builder.append(outsideOutputs(logicSymbols.substring(1), priorityCases[i], TEST_CASES[i][C]));
builder.append(appendCharacter(logicSymbols.substring(1), priorityCases[i], TEST_CASES[i][C]));
return builder.toString();
}

/**
* Interprets A(BC)
*
* @param operation The appropriate equation
* @return A String code that represents the state of each Venn Diagram section
* The output order is not, c, b, a, bc, ac, ab, all
*/
private static String interpretBC(String operation) {
private static String interpretBCPriority(String operation) {
String logicSymbols = filter(operation, LOGIC_SYMBOL_FILTER);
StringBuilder builder = new StringBuilder();
boolean[] priorityCases = priorityOutputs(logicSymbols.substring(1), B + C);

for (int i = 0; i < TEST_CASES.length; i++)
builder.append(outsideOutputs(logicSymbols.substring(0, 1), TEST_CASES[i][A], priorityCases[i]));
builder.append(appendCharacter(logicSymbols.substring(0, 1), TEST_CASES[i][A], priorityCases[i]));
return builder.toString();
}

/**
* Performs the operation on the two variables inside the original equation's ()
* and returns the outputs from those test cases
*
* @param func The logic selector
* @param priorityNum The determining number to reflect whether the method call came from ab or bc
* @return A set of booleans that reflect all test cases possible for the operation inside the ()
*/
private static boolean[] priorityOutputs(String func, int priorityNum) {
private static boolean[] priorityOutputs(String textOperator, int priorityNum) {
boolean[] out = new boolean[TEST_CASES.length];
if (priorityNum == 1) {
for (int i = 0; i < TEST_CASES.length; i++)
out[i] = functionMap(func, TEST_CASES[i][A], TEST_CASES[i][B]);
} else {
for (int i = 0; i < TEST_CASES.length; i++)
out[i] = functionMap(func, TEST_CASES[i][B], TEST_CASES[i][C]);
LogicOperator operator = LOGIC_SYMBOL_TO_ENUM_MAP.get(textOperator);

boolean isPriorityOnFirstTwo = priorityNum == B;
int firstIndex = isPriorityOnFirstTwo ? A : B;
int secondIndex = isPriorityOnFirstTwo ? B : C;

for (int i = 0; i < TEST_CASES.length; i++) {
out[i] = operator.test(TEST_CASES[i][firstIndex], TEST_CASES[i][secondIndex]);
}

return out;
}

/**
* Returns 0 or 1 based on the boolean operation that gets past in
*
* @param func The logic selector
* @param x 1st bit
* @param y 2nd bit
* @return 1 or 0 based on their respective booleans
*/
private static String outsideOutputs(String func, boolean x, boolean y) {
return functionMap(func, x, y) ? "1" : "0";
private static char appendCharacter(String textOperator, boolean x, boolean y) {
return LOGIC_SYMBOL_TO_ENUM_MAP.get(textOperator).test(x, y) ? '1' : '0';
}

/**
* Selects the bitwise operation to be executed
*
* @param func The number selector
* @param x 1st bit
* @param y 2nd bit
* @return The result of the operation
*/
private static boolean functionMap(String func, boolean x, boolean y) {
LogicOperator operator = switch (func) {
case "∧" -> AND;
case "∨" -> OR;
case "↓" -> NOR;
case "⊻" -> XOR;
case "|" -> NAND;
case "↔" -> XNOR;
case "→" -> IMPLIES;
default -> IMPLIED_BY;
};
static {
AB_PRIORITY_PATTERN = "\\(A" + LOGIC_REGEX + "B\\)" + LOGIC_REGEX + "C";
BC_PRIORITY_PATTERN = "A" + LOGIC_REGEX + "\\(B" + LOGIC_REGEX + "C\\)";

return operator.test(x, y);
TEST_CASES = new boolean[][]{
{false, false, false},
{false, false, true},
{false, true, false},
{true, false, false},
{false, true, true},
{true, false, true},
{true, true, false},
{true, true, true}
};
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package core.bomb.modules.c.colored_switches;

import com.opencsv.CSVReader;
import org.jetbrains.annotations.NotNull;
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleDirectedGraph;
Expand All @@ -9,27 +10,30 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@SuppressWarnings("ConstantConditions")
public class ColoredSwitchGraphFactory {
private static final byte OUTGOING_STATE = 1, COLOR_CONDITIONS = 2, SWITCH_TO_FLIP = 3;
private static final String FILENAME = "graph.csv";

public static Graph<ColoredSwitchNode, DefaultEdge> makeGraph() throws IOException {
public static @NotNull Graph<ColoredSwitchNode, DefaultEdge> makeGraph() throws IllegalStateException {
return buildGraph(createFromFile());
}

private static List<ColoredSwitchNode> createFromFile() throws IOException {
List<ColoredSwitchNode> output = new ArrayList<>();
CSVReader csvReader = createReader();
private static List<ColoredSwitchNode> createFromFile() throws IllegalStateException {
List<ColoredSwitchNode> output = new ArrayList<>(32);
Regex connectionFinder = new Regex("\\[(\\d{1,2})\\((\\d{1,3})\\)([1-5])]");
InputStream in = ColoredSwitchGraphFactory.class.getResourceAsStream(FILENAME);

csvReader.forEach(record -> output.add(buildNode(record, connectionFinder)));
csvReader.close();
return output;
try (CSVReader csvReader = new CSVReader(new InputStreamReader(in))) {
csvReader.forEach(record -> output.add(buildNode(record, connectionFinder)));
return output;
} catch (IOException e) {
throw new IllegalStateException(e);
}
}

private static Graph<ColoredSwitchNode, DefaultEdge> buildGraph(List<ColoredSwitchNode> nodeList) {
Expand All @@ -47,13 +51,6 @@ private static Graph<ColoredSwitchNode, DefaultEdge> buildGraph(List<ColoredSwit
return output;
}

@SuppressWarnings("ConstantConditions")
private static CSVReader createReader() {
InputStream in = ColoredSwitchGraphFactory.class.getResourceAsStream(FILENAME);
Reader reader = new InputStreamReader(in);
return new CSVReader(reader);
}

private static ColoredSwitchNode buildNode(String[] record, Regex connectionFinder) {
ColoredSwitchNode node = new ColoredSwitchNode(Byte.parseByte(record[0]));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import org.jgrapht.alg.shortestpath.AStarShortestPath;
import org.jgrapht.graph.DefaultEdge;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
Expand All @@ -24,11 +23,7 @@ public class ColoredSwitches extends Switches {

static {
WRONG_PATH_VALUE = Double.MAX_VALUE;
try {
INTERNAL_GRAPH = ColoredSwitchGraphFactory.makeGraph();
} catch (IOException e) {
throw new IllegalStateException(e.getMessage());
}
INTERNAL_GRAPH = ColoredSwitchGraphFactory.makeGraph();
}

public static @NotNull List<String> producePreemptiveMoveList(byte startingState) throws IllegalArgumentException {
Expand Down
39 changes: 24 additions & 15 deletions core/src/main/java/core/bomb/modules/dh/fast_math/FastMath.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,42 @@
public class FastMath extends Widget {
private static final int[][] INTERNAL_GRID;

/**
* Turns the 2 letter combination of input turns it to a 2 number combination based on certain edgework
* and what letters are set as input
*
* @param letters The 2 letters that must be input (Case insensitive)
* @return The combination of numbers that the expert gives back to the defuser
* @throws IllegalArgumentException If the input doesn't match specifications OR the serial code isn't given
*/
public static @NotNull String solve(@NotNull String letters) throws IllegalArgumentException {
checkSerialCode();
letters = letters.toUpperCase();
if (!letters.matches("[ABCDEGKNPSTXZ]{2}"))
throw new IllegalArgumentException("Input 2 of the following letters: [A B C D E G K N P S T X Z]");

int preconditions = evaluateEdgework();
int leftNum = translateLetter(letters.substring(0, 1));
int rightNum = translateLetter(letters.substring(1));
int leftNum = translateLetter(letters.charAt(0));
int rightNum = translateLetter(letters.charAt(1));

String outputValue = String.valueOf(postConditions(INTERNAL_GRID[leftNum][rightNum] + preconditions));
return (outputValue.length() == 1 ? "0" : "") + outputValue;
}

private static int translateLetter(String letter) throws IllegalArgumentException {
private static int translateLetter(char letter) {
return switch (letter) {
case "A" -> 0;
case "B" -> 1;
case "C" -> 2;
case "D" -> 3;
case "E" -> 4;
case "G" -> 5;
case "K" -> 6;
case "N" -> 7;
case "P" -> 8;
case "S" -> 9;
case "T" -> 10;
case "X" -> 11;
case 'A' -> 0;
case 'B' -> 1;
case 'C' -> 2;
case 'D' -> 3;
case 'E' -> 4;
case 'G' -> 5;
case 'K' -> 6;
case 'N' -> 7;
case 'P' -> 8;
case 'S' -> 9;
case 'T' -> 10;
case 'X' -> 11;
default -> 12;
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public class Hexamaze extends Widget {
@NotNull Grid,
@Nullable String,
@Nullable Integer,
@Nullable List<Coordinates>>solve(@NotNull List<HexNode> nodeList) throws IllegalArgumentException {
@Nullable List<Coordinates>> solve(@NotNull List<HexNode> nodeList)
throws IllegalArgumentException, IllegalStateException {
Maze maze = new Maze();
Grid original = new Grid(new HexagonalPlane(nodeList));

Expand Down
Loading