Skip to content

Instantly share code, notes, and snippets.

@futureperfect
Created September 5, 2013 03:29
Show Gist options
  • Save futureperfect/6445737 to your computer and use it in GitHub Desktop.
Save futureperfect/6445737 to your computer and use it in GitHub Desktop.
Determine whether an array is "circular".
package io.tense.interview.arrays;
import static com.google.common.base.Preconditions.checkNotNull;
public class CircularArrays {
/**
* Tests for the the complete "circularity" of an array of integers where
* traversal is performed by taking array[i] and summing the index i and
* value stored in the array to derive a new index.
*
* Circular means that we traverse a cycle where all elements in the array
* are visited once and only once and the traversal returns to where it
* began. Hamiltonian cycle might be a good way to describe it if you squint
* at this problem the right way.
*
* Null arrays throw an NPE (because don't be a dick, please)
* Empty arrays return false
*
* @param array
* @return whether the list is circular
*/
public static boolean checkIsCircular(int[] array) {
checkNotNull(array);
if (array.length == 0) {
return false;
}
int fencepost = 0;
int index = 0;
for (int i = 0; i < array.length - 1; i++) {
//behavior of modulus function here is... inconvenient. This fixes it for our purposes
index = (((index + array[index]) % array.length) + array.length) % array.length;
if (index == fencepost) {
return false;
}
}
index = (index + array[index]) % array.length;
return index == fencepost;
}
}
package io.tense.interview.arrays;
import static io.tense.interview.arrays.CircularArrays.checkIsCircular;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class CircularArraysTest {
@Test
public void testIdentityListIsCircular() {
assertTrue(checkIsCircular(new int[]{0}));
}
@Test
public void testSingleElementListIsCircular() {
assertTrue(checkIsCircular(new int[]{3}));
}
@Test
public void testTwoElementCircularListIsCircular() {
assertTrue(checkIsCircular(new int[]{1, 1}));
}
@Test
public void testLongCircularList() {
assertTrue(checkIsCircular(new int[]{1, 1, 1, 1, 1, 1}));
}
@Test
public void testNonCircularList() {
assertFalse(checkIsCircular(new int[]{1, 1, 0}));
}
@Test
public void testListThatCyclesEarly() {
assertFalse(checkIsCircular(new int[]{1, -1, 0, 0, 7, 1}));
}
@Test
public void testListThatCyclesInTheMiddle() {
assertFalse(checkIsCircular(new int[]{1, 1, 1, -1, 1, 1, 1}));
}
@Test
public void testListThatCyclesInNegativeDirection() {
assertTrue(checkIsCircular(new int[]{-1, -1, -1, -1}));
}
@Test(expected=NullPointerException.class)
public void testThrowsNPEWithNullInput() {
checkIsCircular(null);
}
@Test
public void testZeroSizedInput() {
assertFalse(checkIsCircular(new int[]{}));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment