Fixed the new algo, report almost finished
[co1314.git] / LubbersSolver.java
index a1b88a0..8a280b0 100755 (executable)
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Collections;
-import java.util.Random;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Comparator;
 import java.util.AbstractMap.SimpleEntry;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Comparator;
-import java.util.PriorityQueue;
-
+import java.util.LinkedList;
 
 /**
- * Class that implements the pot problem solver.
- *
- * @author Mart Lubbers
+ * Class that implements the pet problem solver.
+ * 
+ * @author Mart Lubbers, s4109503
  */
 public class LubbersSolver implements IPetproblemSolver {
-
-       public class Tuple implements Comparable<Tuple>
-       {
-               public int k;
-               public int v;
-
-               public Tuple(int k, int v)
-               {
-                       this.k = k;
-                       this.v = v;
-               }
-
-               /**
-                * Overrides compareTo so that the priorityqueue is ordered ascending
-                *
-                * @param a the entry to compare with
-                * @return comparison value
-                */
-               @Override
-               public int compareTo(Tuple a)
-               {
-                       //note that the values are swapped, so that the sort will be reversed
-                       return Integer.compare(a.v, this.v);
-               }
-
-               @Override
-               public String toString()
-               {
-                       return k + ": " + v;
-               }
-       }
-
        @Override
-       public int[] solve(int n, int m, int[][] compatibility)
-       {
+       public int[] solve(int n, int m, int[][] compatibility) {
+               // Create initial result list of of length n and fill with -1
                int[] result = new int[n];
-
-               // Set to -1 initially
-               for (int i = 0; i < result.length; i++)
-                       result[i] = -1;
-
-               // Sum rows and columns
-               PriorityQueue<Tuple> row_sums = new PriorityQueue<Tuple>(n);
-               PriorityQueue<Tuple> col_sums = new PriorityQueue<Tuple>(m);
-
-               int[] running_row_sums = new int[n];
-               int[] running_col_sums = new int[m];
-
-               // Sum
-               for (int j = 0; j < m; j++)
-               {
-                       for (int i = 0; i < n; i++)
-                       {
-                               running_row_sums[i] += compatibility[i][j];
-                               running_col_sums[j] += compatibility[i][j];
+               Arrays.fill(result, -1);
+
+               // Create the lists that define the sums of the rows and columns
+               LinkedList<SimpleEntry<Integer, Integer>> rows = new LinkedList<SimpleEntry<Integer, Integer>>();
+               LinkedList<SimpleEntry<Integer, Integer>> cols = new LinkedList<SimpleEntry<Integer, Integer>>();
+
+               // Calculate the sums
+               int[] col_sums = new int[m];
+               for (int i = 0, sum = 0; i < n; i++) {
+                       for (int j = 0; j < m; j++) {
+                               sum += compatibility[i][j];
+                               col_sums[j] += compatibility[i][j];
                        }
+                       rows.add(new SimpleEntry<Integer, Integer>(i, sum));
                }
-
-               // Add running sums to queues
-               for (int i = 0; i < running_row_sums.length; i++)
-                       row_sums.add(new Tuple(i, running_row_sums[i]));
-
-               for (int i = 0; i < running_col_sums.length; i++)
-                       col_sums.add(new Tuple(i, running_col_sums[i]));
-
-
-               // Select smallest sum (in rows/cols)
-               // Get 1-indices for that sum's index
-               // Select smallest from those indices
-               while (!row_sums.isEmpty() && !col_sums.isEmpty()){
-                       Tuple lowestIndexRow = row_sums.peek();
-                       Tuple lowestIndexCol = col_sums.peek();
-
-                       boolean useRow = false;
-
-                       if (lowestIndexRow.v < lowestIndexCol.v)
-                               useRow = true;
-
-                       // Get 1-indices
-                       if (useRow)
-                       {
-                               row_sums.remove();
-
-                               // Get smallest
-                               int smallestValue = Integer.MAX_VALUE;
-                               Tuple smallestKey = null;
-
-                               for (Tuple e : col_sums)
-                               {
-                                       if (e.v < smallestValue && compatibility[lowestIndexRow.k][e.k] == 1)
-                                       {
-                                               smallestKey = e;
-                                               smallestValue = e.v;
+               for (int i = 0; i < m; i++) {
+                       cols.add(new SimpleEntry<Integer, Integer>(i, col_sums[i]));
+               }
+               //Sort the lists so the rows and columns with the least amount of positive compatibilities 
+               Comparator<SimpleEntry<Integer, Integer>> comp = new Comparator<SimpleEntry<Integer, Integer>>() {
+                       @Override
+                       public int compare(SimpleEntry<Integer, Integer> a, SimpleEntry<Integer, Integer> b) {
+                               return a.getValue().compareTo(b.getValue());
+                       }
+               };
+               Collections.sort(rows, comp);
+               Collections.sort(cols, comp);
+
+               /* 1. Find the row or column with the lowest sum(least available matches)
+                *    Because the rows and columns are sorted on value the first item is the lowest
+                * 2. Find the match with the lowest sum and still positive compatibility for that row or column
+                * 3. Select smallest from those indices
+                */
+               SimpleEntry<Integer, Integer> MINIMUM = new SimpleEntry<Integer, Integer>(-1, Integer.MAX_VALUE);
+               while (!(rows.isEmpty() || cols.isEmpty())) {
+                       //1. Find the row or column with the lowest sum(least available matches)
+                       SimpleEntry<Integer, Integer> row_l = rows.peekFirst();
+                       SimpleEntry<Integer, Integer> col_l = cols.peekFirst();
+                       
+                       //2. The row is the lowest
+                       if (row_l.getValue() < col_l.getValue()) {
+                               //Remove the current lowest row sum
+                               rows.remove(row_l);
+                               //3. Find smallest column that has compatibility 1
+                               SimpleEntry<Integer, Integer> smallest = MINIMUM;
+                               for (SimpleEntry<Integer, Integer> e : cols) {
+                                       if (e.getValue() < smallest.getValue() && compatibility[row_l.getKey()][e.getKey()] == 1) {
+                                               smallest = e;
                                        }
                                }
-
-                               // No candidates in this list, continue
-                               if (smallestKey == null)
+                               //No pets left that have a positive compatibility
+                               if (smallest.getKey() == -1) {
                                        continue;
-
-                               int col_index = smallestKey.k;
-                               col_sums.remove(smallestKey);
-
-                               result[lowestIndexRow.k] = col_index;
-                       }
-                       else
-                       {
-                               col_sums.remove();
-
-                               // Get smallest
-                               int smallestValue = Integer.MAX_VALUE;
-                               Tuple smallestKey = null;
-
-                               for (Tuple e : row_sums)
-                               {
-                                       if (e.v < smallestValue && compatibility[e.k][lowestIndexCol.k] == 1)
-                                       {
-                                               smallestKey = e;
-                                               smallestValue = e.v;
+                               }
+                               cols.remove(smallest);
+                               result[row_l.getKey()] = smallest.getKey();
+                       //2. The column is the lowest
+                       } else {
+                               //Remove the current lowest column sum
+                               cols.remove(col_l);
+                               //3. Find smallest row that has compatibility 1
+                               SimpleEntry<Integer, Integer> smallest = MINIMUM;
+                               for (SimpleEntry<Integer, Integer> e : rows) {
+                                       if (e.getValue() < smallest.getValue() && compatibility[e.getKey()][col_l.getKey()] == 1) {
+                                               smallest = e;
                                        }
                                }
-
-                               // No candidates in this list, continue
-                               if (smallestKey == null)
+                               //No pets left that have a positive compatibility
+                               if (smallest.getKey() == -1) {
                                        continue;
-
-                               int row_index = smallestKey.k;
-                               row_sums.remove(smallestKey);
-
-                               result[row_index] = lowestIndexCol.k;
+                               }
+                               rows.remove(smallest);
+                               result[smallest.getKey()] = col_l.getKey();
                        }
                }
-
-               int score = 0;
-
-               for (int i = 0; i < result.length; i++)
-                       score += result[i] == -1 ? 0 : 1;
-
-               System.out.println("Score: " + score);
-
                return result;
        }
-
 }