Initial commit
authorMart Lubbers <mart@martlubbers.net>
Wed, 18 Jun 2014 17:50:15 +0000 (19:50 +0200)
committerMart Lubbers <mart@martlubbers.net>
Wed, 18 Jun 2014 17:50:15 +0000 (19:50 +0200)
.gitignore [new file with mode: 0644]
IPetproblemSolver.java [new file with mode: 0755]
LubbersSolver.java [new file with mode: 0755]
PetTest.java [new file with mode: 0755]
RandomSolver.java [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..915f7c2
--- /dev/null
@@ -0,0 +1,5 @@
+build/*
+build.xml
+dist/*
+make.sh
+*.class
diff --git a/IPetproblemSolver.java b/IPetproblemSolver.java
new file mode 100755 (executable)
index 0000000..e6748f4
--- /dev/null
@@ -0,0 +1,14 @@
+public interface IPetproblemSolver {
+       /**
+        * Solves the Pet Problem.
+        * @param n The number of children.
+        * @param m The number of pets.
+        * @param compatibility Matrix containing for every element c[i][j] the value of f(i, j). (See assignment) 
+        *                      For the base case contains either values "0" or "1".
+        *                      For the bonus case might contain any non-negative number.
+        * @return An array with n elements, containing the index the pet assigned to each child.
+        *         Thus result[i] = j means "child i gets pet j".
+        *         If a child gets no pet, assign the value "-1".
+        */
+       int[] solve(int n, int m, final int[][] compatibility);
+}
diff --git a/LubbersSolver.java b/LubbersSolver.java
new file mode 100755 (executable)
index 0000000..dfd968c
--- /dev/null
@@ -0,0 +1,85 @@
+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;
+
+
+/* Generate a random solution which not is necessarily optimal. */
+public class LubbersSolver implements IPetproblemSolver {
+
+       private class Tuple {
+               public int[] list;
+               public int score;
+
+               public Tuple(int[] l, int s) {
+                       list = l;
+                       score = s;
+               }
+
+               @Override
+               public String toString() {
+                       return score + ": " + Arrays.toString(list);
+               }
+       }
+
+       public int factorial(int n) {
+               return n==1 ? 1 : n*factorial(n-1);
+       }
+
+       public void permute(int[] num, int start, List<int[]> result) {
+               if(start == num.length) {
+                       result.add(num.clone());
+               }
+               for(int i = start; i<num.length; i++){
+                       int t = num[start];
+                       num[start] = num[i];
+                       num[i] = t;
+                       permute(num, start+1, result);
+                       t = num[start];
+                       num[start] = num[i];
+                       num[i] = t;
+               }
+       }
+       
+       private static int computeCompatibility(int[][] matrix, int[] pairing)
+       {
+               int sum = 0;
+               for(int n_i = 0; n_i < pairing.length; n_i++)
+               {
+                       int m_i = pairing[n_i];
+                       if(m_i == -1)
+                               continue;
+                       sum += matrix[n_i][m_i];
+               }
+               
+               return sum;
+       }
+
+       @Override
+       public int[] solve(int n, int m, final int[][] compatibility) {
+               System.out.println("n: " + n + " m: " + m);
+               int[] possibilities = new int[n];
+               for(int i = 0; i<n; i++){
+                       possibilities[i] = i>=m ? -1 : i;
+               }
+
+               if(m<n){
+                       List<int[]> ps = new LinkedList<int[]>();
+                       permute(possibilities, 0, ps);
+                       return Collections.max(ps, new Comparator<int[]>(){
+                               @Override
+                               public int compare(int[] a, int[] b){
+                                       return computeCompatibility(compatibility, a) - computeCompatibility(compatibility, b);
+                               }
+                       });
+               }
+               else{
+                       System.out.println("not equal...");
+                       return null;
+               }
+               
+       }
+}
diff --git a/PetTest.java b/PetTest.java
new file mode 100755 (executable)
index 0000000..cabef3e
--- /dev/null
@@ -0,0 +1,136 @@
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Random;
+import java.util.TreeSet;
+
+import junit.framework.Assert;
+
+/**
+ * Tests conformance of a Solver to constraints.
+ * May not test whether a solution returns a correct (optimal) answer.
+ */
+@RunWith(Parameterized.class)
+public class PetTest {
+       IPetproblemSolver ps;
+       
+       public PetTest(IPetproblemSolver ps)
+       {
+               this.ps = ps;
+       }
+       
+       @Parameters
+       public static Collection<Object[]> data() {
+               Object[][] solvers = new Object[][] {
+                               { //new RandomSolver(),
+                                       new LubbersSolver()
+                               }
+               };
+               return Arrays.asList(solvers);
+       }
+       
+       /**
+        * @param n The number of children.
+        * @param m The number of pets.
+        * @param result
+        */
+       private static void checkConformance(int n, int m, final int[] result)
+       {
+               Assert.assertEquals("There should not suddenly be more or less children.", n, result.length);
+               
+               TreeSet<Integer> pets = new TreeSet<Integer>();
+               for(int i = 0; i < result.length; i++)
+               {
+                       Assert.assertTrue("Pet should exist, or be a no-pet (-1).", result[i] >= -1 && result[i] < m);
+                       Assert.assertTrue("Pet should not be assigned to multiple children.", result[i] == -1 || pets.add(result[i]));
+               }
+       }
+       
+       private static int[][] generateTestMatrix(int n, int m, int maxValue)
+       {
+               int[][] result = new int[n][m];
+               
+               Random r = new Random(n * (m+1));
+               for(int n_i = 0; n_i < n; n_i++)
+                       for(int m_i = 0; m_i < m; m_i++)
+                               result[n_i][m_i] = r.nextInt(maxValue+1);
+               
+               return result;
+       }
+       
+       private static int computeCompatibility(int[][] matrix, int[] pairing)
+       {
+               int sum = 0;
+               for(int n_i = 0; n_i < pairing.length; n_i++)
+               {
+                       int m_i = pairing[n_i];
+                       if(m_i == -1)
+                               continue;
+                       
+                       sum += matrix[n_i][m_i];
+               }
+               
+               return sum;
+       }
+       
+       /**
+        * Test whether Solver conforms for a semi-random test set.
+        * Note that these tests do not test whether a solution is optimal.
+        * (If it could do that the test would be a Solver by itself)
+        */
+       private void performGeneratedTest(int n, int m)
+       {
+               int[][] compatibility = generateTestMatrix(n, m, 1);
+               int[] result = ps.solve(n, m, compatibility);
+               checkConformance(n, m, result);
+       }
+       
+       @Test(timeout = 2000)
+       public void testExample() {
+               int n = 5, m = 4;
+               int[][] compatibility = {
+                       {1, 1, 0, 0},
+                       {0, 1, 1, 1},
+                       {0, 1, 0, 0},
+                       {1, 0, 1, 0},
+                       {0, 0, 1, 1}
+               };
+               
+               int[] result = ps.solve(n, m, compatibility);
+               checkConformance(n, m, result);
+               Assert.assertEquals("Does not give a correct answer", 4, computeCompatibility(compatibility, result));
+       }
+       
+       @Test(timeout = 2000)
+       public void testGeneratedSmall() {
+               performGeneratedTest(8, 10);
+               performGeneratedTest(10, 8);
+       }
+       
+       @Test(timeout = 2000)
+       public void testGeneratedMedium() {
+               performGeneratedTest(23, 20);
+               performGeneratedTest(20, 23);
+       }
+       
+       @Test(timeout = 5000)
+       public void testGeneratedLarge() {
+               performGeneratedTest(121, 130);
+               performGeneratedTest(130, 121);
+       }
+       
+       /**
+        * This timeout is just a suggestion,
+        * your solution is not incorrect if it takes longer,
+        * or if it is not capable to finish in a reasonable amount of time.
+        */
+       @Test(timeout = 5000) 
+       public void testGeneratedTerrible() {
+               performGeneratedTest(2910, 3102);
+               performGeneratedTest(3102, 2910);
+       }
+}
diff --git a/RandomSolver.java b/RandomSolver.java
new file mode 100755 (executable)
index 0000000..91b3bc6
--- /dev/null
@@ -0,0 +1,30 @@
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Random;
+
+/* Generate a random solution which not is necessarily optimal. */
+public class RandomSolver implements IPetproblemSolver {
+       @Override
+       public int[] solve(int n, int m, int[][] compatibility) {
+               int[] result = new int[n];
+               ArrayList<Integer> possibilities = new ArrayList<Integer>();
+               
+               // Init list of possible pets
+               for(int m_i = 0; m_i < m; m_i++)
+                       possibilities.add(m_i);
+               
+               // If number of children is bigger then number of pets
+               if(n > m) 
+                       for(int i = 0; i < n - m; i++)
+                               possibilities.add(-1); // Add possibility of drawing "no pet"
+               
+               // Shuffle the available options
+               Collections.shuffle(possibilities, new Random());
+               
+               // Assign a possible pet to all children
+               for(int n_i = 0; n_i < n; n_i++)
+                       result[n_i] = possibilities.get(n_i);
+               
+               return result;
+       }
+}