commit 8390e8dd7c3a1b24d720df464643230767658d4f Author: SowinskiBraeden Date: Sat Jan 31 18:25:49 2026 -0800 assignment 01 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..13275f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ +.kotlin + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..ab1f416 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..1e3ab51 --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..89ee753 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..83eb5a8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/comp3760.iml b/comp3760.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/comp3760.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/data/data0.txt b/data/data0.txt new file mode 100644 index 0000000..996a66e --- /dev/null +++ b/data/data0.txt @@ -0,0 +1,6 @@ +5 +3 2 6 1 2 +4 6 8 8 5 +4 6 1 2 7 +7 9 2 9 2 +7 4 9 5 1 diff --git a/data/data1.txt b/data/data1.txt new file mode 100644 index 0000000..df7c902 --- /dev/null +++ b/data/data1.txt @@ -0,0 +1,8 @@ +7 +7 9 7 8 4 3 7 +9 8 8 4 5 6 7 +8 7 1 4 4 1 8 +1 3 6 1 9 9 9 +5 7 2 4 5 2 2 +9 7 1 8 3 9 7 +9 6 7 2 3 3 1 diff --git a/data/data2.txt b/data/data2.txt new file mode 100644 index 0000000..8afbac8 --- /dev/null +++ b/data/data2.txt @@ -0,0 +1,11 @@ +10 +773 215 756 276 746 979 172 268 273 830 +636 248 658 510 203 743 974 455 687 654 +285 495 769 247 726 422 646 696 659 903 +348 974 825 100 833 625 299 289 591 433 +527 510 802 779 884 861 877 834 379 437 +539 557 196 778 234 991 147 200 350 812 +507 629 158 467 670 523 335 788 466 845 +323 856 370 400 529 728 926 366 113 185 +716 762 339 832 405 767 190 904 986 276 +641 953 277 499 373 863 716 446 397 238 diff --git a/data/data3.txt b/data/data3.txt new file mode 100644 index 0000000..80c3d06 --- /dev/null +++ b/data/data3.txt @@ -0,0 +1,11 @@ +10 +1 13 9 30 35 23 34 35 24 18 +25 11 22 4 11 36 2 29 31 17 +15 23 30 32 1 6 13 12 28 9 +29 32 34 11 34 1 19 18 15 21 +3 31 20 12 13 30 19 26 17 9 +37 15 32 2 1 4 9 29 16 3 +7 33 23 11 33 18 7 24 25 29 +16 34 37 37 31 8 10 34 2 13 +8 33 11 8 29 17 35 23 30 29 +3 16 33 31 2 28 15 11 28 24 diff --git a/data/data4.txt b/data/data4.txt new file mode 100644 index 0000000..cf15836 --- /dev/null +++ b/data/data4.txt @@ -0,0 +1,7 @@ +6 +1 8 6 1 4 6 +6 9 6 4 3 4 +2 1 4 1 2 4 +3 8 2 4 3 8 +7 5 9 4 4 8 +5 4 5 9 7 8 diff --git a/data/data5.txt b/data/data5.txt new file mode 100644 index 0000000..8c8c6ba --- /dev/null +++ b/data/data5.txt @@ -0,0 +1,10 @@ +9 +3 3 7 3 6 3 2 9 5 +7 9 4 3 8 7 4 4 3 +5 7 4 5 7 6 1 7 1 +6 2 3 9 8 5 7 2 7 +9 6 3 1 1 5 9 9 2 +2 5 5 7 1 2 2 8 3 +1 6 4 9 5 1 4 7 3 +9 3 5 2 3 2 5 8 8 +7 4 7 9 7 9 5 9 2 diff --git a/src/ca/bcit/comp3760/assign1/JobAssignmentFinder.java b/src/ca/bcit/comp3760/assign1/JobAssignmentFinder.java new file mode 100644 index 0000000..05912c3 --- /dev/null +++ b/src/ca/bcit/comp3760/assign1/JobAssignmentFinder.java @@ -0,0 +1,232 @@ +package ca.bcit.comp3760.assign1; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +/** + * JobAssignmentFinder is a simple program that reads in a file that contains + * a 2D matrix of values indicating the benefit of a person doing a job. + * From the read benefit matrix, the program finds the maximum benefit + * from the matrix by checking all permutations generated for a matrix of size + * NxN. Program provides methods to get the maximum benefit value as well as the + * permutation for the maximum benefit and helper methods such as string representations + * of the 2D benefit matrix. + * + * @version 1.0.0 + * @author Braeden Sowinski + */ +public class JobAssignmentFinder +{ + private int[][] benefitMatrix; + + /** + * Recursive decrease-and-conquer algorithm to generate a list of all + * permutations of the numbers 0..N-1. This follows the "decrease by 1" pattern + * of decrease and conquer algorithms. + * This method returns an ArrayList of ArrayLists. One permutation is an + * ArrayList containing 0,1,2,...,N-1 in some order. The final result is an + * ArrayList containing N! of those permutations. + * + * @param N size to generate permutations + * @return permutations + */ + @SuppressWarnings("unchecked") + private ArrayList> getPermutations(final int N) + { + final ArrayList> results; + results = new ArrayList<>(); + + /* + * This isn't a "base case", it's a "null case". This function does not call + * itself with an argument of zero, but we can't prevent another caller from + * doing so. It's a weird result, though. The list of permutations has one + * permutation, but the one permutation is empty (0 elements). + */ + if (N == 0) + { + final ArrayList emptyList; + emptyList = new ArrayList(); + results.add(emptyList); + } + else if (N == 1) + { + /* + * Now THIS is the base case. Create an ArrayList with a single integer, and add + * it to the results list. + */ + final ArrayList singleton; + singleton = new ArrayList(); + singleton.add(0); + results.add(singleton); + } + else + { + /* + * And: the main part. First a recursive call (this is a decrease and conquer + * algorithm) to get all the permutations of length N-1. + */ + final ArrayList> smallList; + smallList = getPermutations(N - 1); + + /* + * Iterate over the list of smaller permutations and insert the value 'N-1' into + * every permutation in every possible position, adding each new permutation to + * the big list of permutations. + */ + for (final ArrayList perm : smallList) + { + /* + * Add 'N-1' -- the biggest number in the new permutation -- at each of the + * positions from ..N-1. + */ + for (int i = 0; i < perm.size(); i++) + { + final ArrayList newPerm; + newPerm = (ArrayList) perm.clone(); + newPerm.add(i, N - 1); + results.add(newPerm); + } + + /* + * Add 'N-1' at the end (i.e. at position "size"). + */ + final ArrayList newPerm; + newPerm = (ArrayList) perm.clone(); + newPerm.add(N - 1); + results.add(newPerm); + } + } + + return results; + } + + /** + * readDataFile takes an input string of a filename in order to read + * the data into the benefitMatrix for processing + * @param filename to read matrix data + */ + public void readDataFile(final String filename) + { + final BufferedReader reader; + final int size; + String line; + + try + { + reader = new BufferedReader(new FileReader(filename)); + size = Integer.parseInt(reader.readLine()); + + this.benefitMatrix = new int[size][size]; + + int row = 0; + while ((line = reader.readLine()) != null) + { + this.benefitMatrix[row] = Arrays.stream(line.split(" ")) + .mapToInt(Integer::parseInt).toArray(); + row++; + } + + reader.close(); + } + catch (final IOException e) + { + System.err.println("Failed to open file \"" + filename + "\""); + } + } + + /** + * getInputSize returns the dimensions of the benefit matrix, + * i.e. if matrix is NxN then size is N + * @return the size of the benefit matrix + */ + public int getInputSize() + { + return this.benefitMatrix == null ? -1 : this.benefitMatrix.length; + } + + /** + * getBenefitMatrix that was read in from an input file + * @return benefit matrix + */ + public int[][] getBenefitMatrix() + { + return this.benefitMatrix; + } + + /** + * benefitMatrixToString constructs a string representation + * of the 2d benefit matrix + * @return string representation of benefit matrix + */ + public String benefitMatrixToString() + { + final StringBuilder str; + str = new StringBuilder(); + + for (final int[] row : this.benefitMatrix) + { + for (final int i : row) + { + str.append(i); + str.append(" "); + } + str.append("\n"); + } + + return str.toString(); + } + + /** + * getMaxAssignment finds the solution to get the maximum value from + * the benefit matrix by brute-force checking all permutations + * @return a list of integers indicating which person should take which assignment for maximum benefits + */ + public List getMaxAssignment() + { + return getPermutations(this.benefitMatrix.length) + .stream() + .max(Comparator.comparingInt(perm -> { + int sum = 0; + for (int i = 0; i < perm.size(); i++) + { + sum += this.getBenefit(i, perm.get(i)); + } + + return sum; + })).orElse(new ArrayList<>()); + } + + /** + * getMaxAssignmentTotalValue gets the max assignment and + * sums the value of benefits for the given max assignment solution + * @return the sum of benefits of a max assignment solution + */ + public int getMaxAssignmentTotalValue() + { + final List perm; + perm = this.getMaxAssignment(); + + int sum = 0; + for (int i = 0; i < perm.size(); i++) + { + sum += this.getBenefit(i, perm.get(i)); + } + return sum; + } + + /** + * getBenefit from benefit matrix at a given row and column + * @param row of benefit within matrix + * @param col of benefit within matrix + * @return benefit at row and col + */ + public int getBenefit(int row, int col) + { + return this.benefitMatrix[row][col]; + } +} diff --git a/src/ca/bcit/comp3760/assign1/JobAssignmentFinderDriver.java b/src/ca/bcit/comp3760/assign1/JobAssignmentFinderDriver.java new file mode 100644 index 0000000..e9a749b --- /dev/null +++ b/src/ca/bcit/comp3760/assign1/JobAssignmentFinderDriver.java @@ -0,0 +1,45 @@ +package ca.bcit.comp3760.assign1; + +import java.util.List; + +/** + * JobAssignmentFinderDriver to test JobAssignmentFinder + * @version 1.0.0 + * @author Braeden Sowinski + */ +public class JobAssignmentFinderDriver +{ + /** + * debug solution to prove it works + * @param f to call JobAssignmentFinder methods + * @param filename to read benefit data + */ + private static void debug(final JobAssignmentFinder f, final String filename) + { + final JobAssignmentFinder test; + final List maxAssign; + + f.readDataFile("./data/" + filename); + + System.out.printf("File: %s\n", filename); + maxAssign = f.getMaxAssignment(); + System.out.printf("Max Assignment: %s\n", maxAssign.toString()); + System.out.printf("Total Value: %d\n\n", f.getMaxAssignmentTotalValue()); + } + + /** + * main program entry for testing purposes + * @param args unused + */ + public static void main(final String[] args) + { + final JobAssignmentFinder test; + + test = new JobAssignmentFinder(); + + for (int i = 0; i <= 5; i++) + { + debug(test, "data" + i + ".txt"); + } + } +}