Java solution to Codility NumberOfDiscIntersections problem (Lesson 6 – Sorting) which scored 87%. The problem is to determine whether a triangle can be built from a given set of edges. The strategy is:
- create an ordered array of circles, each circle consisting of (leftmost x, rightmost x)
- have a custom java.util.Comparator to order the Circles based on where their radius starts and stops
- check intersection by comparing rightmost x with leftmost x of next element
References
How to use Comparator in Java to sort (Stack Overflow)
[cc lang="java" escaped="true"] package com.codility.lesson06.sorting; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class NumberOfDiscIntersections { public int solution(int[] A) { List aList = new ArrayList(); for(int i=0; i<A.length; i++) { //need explicit cast to long on right side for case when A[i] is Integer.MAX_VALUE and adding would cause overflow long leftMost = i - (long) A[i]; long rightMost = i + (long) A[i]; aList.add(new Circle(leftMost, rightMost)); } Collections.sort(aList, new CircleComparator()); Circle [] aOrderedCircles = new Circle[A.length]; int index = 0; for(Circle circle : aList) { aOrderedCircles[index++] = circle; } int intersections = 0; for(int i=0; i<aOrderedCircles.length-1; i++) { for(int j=i+1; j<aOrderedCircles.length; j++) { //check intersection by comparing rightmost x with leftmost x of next element if(aOrderedCircles[i].rightMostX >= aOrderedCircles[j].leftMostX) { intersections++; if(intersections > 10000000) return -1; } //as soon as don't find intersection, stop counting cause circles are ordered so all subsequent circles won't intersect else break; } } return intersections; } class Circle { long leftMostX; long rightMostX; Circle(long pLeftMostX, long pRightMostX) { leftMostX = pLeftMostX; rightMostX = pRightMostX; } } //reference: https://stackoverflow.com/questions/2839137/how-to-use-comparator-in-java-to-sort class CircleComparator implements Comparator { @Override public int compare(Circle pCircle1, Circle pCircle2) { if(pCircle1.leftMostX < pCircle2.leftMostX) return -1; //e.g. circle1 (-4, 6) < circle2 (-2, 9) if(pCircle2.leftMostX < pCircle1.leftMostX) return 1; //e.g. circle2 (-4, 6) < circle1 (-3, 1) if(pCircle1.rightMostX < pCircle2.rightMostX) return -1; //e.g. circle1 (-4, 3) < circle2 (-4, 6) if(pCircle2.rightMostX < pCircle1.rightMostX) return 1; //e.g. circle2 (-4, 3) < circle1 (-4, 1) return 0; //e.g. circle1 (-2, 2), circle2 (-2, 2) } } } [/cc]
TestNG test cases for this problem which all passed:
[cc lang="java" escaped="true"] package test.com.codility.lesson06.sorting; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.codility.lesson06.sorting.NumberOfDiscIntersections; public class NumberOfDiscIntersectionsTests { private NumberOfDiscIntersections solution; @BeforeTest public void setUp() { solution = new NumberOfDiscIntersections(); } @DataProvider(name = "test1") public Object [][] createData1() { return new Object [][] { new Object [] { new int [] { 1, 5, 2, 1, 4, 0 }, 11 }, new Object [] { new int [] { 2, 1, 0, 4 }, 6 }, new Object [] { new int [] { }, 0 }, new Object [] { new int [] { 1 }, 0 }, new Object [] { new int [] { 1, 2147483647, 0 }, 2 }, }; } @Test(dataProvider = "test1") public void verifySolution(int[] pA, int pExpected) { Assert.assertEquals(solution.solution(pA), pExpected); } } [/cc]