package net.varkhan.base.containers;
import junit.framework.TestCase;
import net.varkhan.base.containers.array.Arrays;
import net.varkhan.base.containers.list.List;
import net.varkhan.base.containers.map.Map;
import java.util.NoSuchElementException;
import java.util.Random;
/**
* <b></b>.
* <p/>
*
* @author varkhan
* @date 11/1/13
* @time 6:27 PM
*/
public class ContainersTest extends TestCase {
public void testEmpty() throws Exception {
Container<Object> ix = new Containers.Empty<Object>();
assertTrue("isEmpty()",ix.isEmpty());
assertEquals("size()",0,ix.size());
assertEquals("visit()",0,ix.visit(new Visitable.Visitor<Object,Object>() {
@Override
public long invoke(Object obj, Object o) {
return 999;
}
}, null));
Iterator<? extends Object> ii = ix.iterator();
assertFalse("indexes().hasNext()", ii.hasNext());
}
public void testSingleton() throws Exception {
final Object val = new Object();
Container<Object> ix = new Containers.Singleton<Object>(val);
assertFalse("isEmpty()", ix.isEmpty());
assertEquals("size()",1,ix.size());
assertEquals("visit()",999,ix.visit(new Visitable.Visitor<Object,Object>() {
@Override
public long invoke(Object obj, Object o) {
return obj==val?999:888;
}
}, null));
Iterator<? extends Object> ii = ix.iterator();
assertTrue("indexes().hasNext()", ii.hasNext());
assertEquals("indexes().next()==val",val,ii.next());
assertFalse("indexes().hasNext()", ii.hasNext());
}
public void testEnumerate() throws Exception {
Object[] val0 = new Object[] {};
Container<Object> ix0 = new Containers.Enumerate<Object>(val0);
assertTrue("isEmpty()",ix0.isEmpty());
assertEquals("size()",0,ix0.size());
assertEquals("visit()",0,ix0.visit(new Visitable.Visitor<Object,Object>() {
@Override
public long invoke(Object obj, Object o) {
return 999;
}
}, null));
Iterator<? extends Object> ii0 = ix0.iterator();
assertFalse("indexes().hasNext()", ii0.hasNext());
final Object[] val1 = new Object[] {4};
Container<Object> ix1 = new Containers.Enumerate<Object>(val1);
assertFalse("isEmpty()", ix1.isEmpty());
assertEquals("size()",1,ix1.size());
assertEquals("visit()",999,ix1.visit(new Visitable.Visitor<Object,Object>() {
@Override
public long invoke(Object obj, Object o) {
return obj==val1[0]?999:888;
}
}, null));
Iterator<? extends Object> ii1 = ix1.iterator();
assertTrue("indexes().hasNext()", ii1.hasNext());
assertEquals("indexes().next()==min",val1[0],ii1.next());
assertFalse("indexes().hasNext()", ii1.hasNext());
final Object[] val2 = new Object[] {4, 5, 6};
Container<Object> ix2 = new Containers.Enumerate<Object>(val2);
assertFalse("isEmpty()", ix2.isEmpty());
assertEquals("size()",val2.length,ix2.size());
assertEquals("visit()",999+888+888,ix2.visit(new Visitable.Visitor<Object,Object>() {
@Override
public long invoke(Object obj, Object o) {
return obj==val2[0]?999:888;
}
}, null));
Iterator<? extends Object> ii2 = ix2.iterator();
assertTrue("indexes().hasNext()", ii2.hasNext());
assertEquals("indexes().next()==min",val2[0],ii2.next());
assertEquals("indexes().next()==..",val2[1],ii2.next());
assertEquals("indexes().next()==..",val2[2],ii2.next());
assertFalse("indexes().hasNext()", ii2.hasNext());
}
public static <T> void assertListEquals(String message, List<T> expected, List<T> actual) {
if(!Containers.equals(expected,actual)) fail(message+";\n expected: ["+Containers.join(",",expected)+"];\n actual: ["+Containers.join(",",actual)+"]");
}
public void testEqualsContainer() throws Exception {
Container<String> c00 = new Container<String>() {
public long size() { return 0; }
public boolean isEmpty() { return true; }
public Iterator<? extends String> iterator() { return new Iterator.Empty<String>(); }
public <Par> long visit(Visitor<String,Par> vis, Par par) { return 0; }
};
Container<String> c01 = new Container<String>() {
public long size() { return 0; }
public boolean isEmpty() { return true; }
public Iterator<? extends String> iterator() { return new Iterator.Empty<String>(); }
public <Par> long visit(Visitor<String,Par> vis, Par par) { return 0; }
};
Container<String> c02 =new ArrayContainer<String>(new String[]{});
Container<String> c10 =new ArrayContainer<String>(new String[]{ "a" });
Container<String> c11 =new ArrayContainer<String>(new String[]{ "a" });
Container<String> c12 =new ArrayContainer<String>(new String[]{ "b" });
Container<String> c21 =new ArrayContainer<String>(new String[]{ "a", "c" });
Container<String> c22 =new ArrayContainer<String>(new String[]{ "a", "c" });
Container<String> c23 =new ArrayContainer<String>(new String[]{ "a", "d" });
assertTrue("equals([],-)",Containers.equals(c00, c00));
assertTrue("equals([],[])",Containers.equals(c00, c01));
assertTrue("equals([],[[]])",Containers.equals(c00, c02));
assertFalse("!equals([],[a])", Containers.equals(c00, c10));
assertTrue("equals([a],-)", Containers.equals(c10, c10));
assertTrue("equals([a],[a])", Containers.equals(c10, c11));
assertFalse("!equals([a],[b])", Containers.equals(c10, c12));
assertFalse("!equals([a],[a,c])", Containers.equals(c10, c21));
assertTrue("equals([a,c],[a,c])", Containers.equals(c22, c21));
assertFalse("!equals([a,d],[a,c])", Containers.equals(c23, c21));
}
public void testEqualsMap() throws Exception {
Map<String,Integer> m00 =new ArrayMap<String,Integer>(new String[]{},new Integer[]{});
Map<String,Integer> m01 =new ArrayMap<String,Integer>(new String[]{},new Integer[]{});
Map<String,Integer> m10 =new ArrayMap<String,Integer>(new String[]{"a"},new Integer[]{1});
Map<String,Integer> m11 =new ArrayMap<String,Integer>(new String[]{"a"},new Integer[]{1});
Map<String,Integer> m12 =new ArrayMap<String,Integer>(new String[]{"b"},new Integer[]{2});
Map<String,Integer> m13 =new ArrayMap<String,Integer>(new String[]{"a"},new Integer[]{2});
Map<String,Integer> m20 =new ArrayMap<String,Integer>(new String[]{"a","b"},new Integer[]{1,2});
Map<String,Integer> m21 =new ArrayMap<String,Integer>(new String[]{"a","b"},new Integer[]{1,2});
Map<String,Integer> m22 =new ArrayMap<String,Integer>(new String[]{"a","b"},new Integer[]{1,3});
Map<String,Integer> m23 =new ArrayMap<String,Integer>(new String[]{"a","c"},new Integer[]{1,3});
assertTrue("equals({},-)",Containers.equals(m00,m00));
assertTrue("equals({},{})",Containers.equals(m00,m01));
assertFalse("!equals({a=>1},{})",Containers.equals(m10,m01));
assertTrue("equals({a=>1},{a=>1})",Containers.equals(m10,m11));
assertFalse("!equals({b=>2},{a=>1})",Containers.equals(m12,m11));
assertFalse("!equals({b=>2},{a=>2})",Containers.equals(m12,m13));
assertFalse("!equals({a=>1},{a=>2})",Containers.equals(m11,m13));
assertTrue("equals({a=>1,b=>2},{a=>1,b=>2})",Containers.equals(m20,m21));
assertFalse("!equals({a=>1,b=>3},{a=>1,b=>2})",Containers.equals(m22,m21));
assertFalse("!equals({a=>1,b=>3},{a=>1,c=>3})",Containers.equals(m22,m23));
}
public void testJoinA() throws Exception {
assertEquals("",Containers.join(":",Arrays.asList()));
assertEquals("0",Containers.join(":",Arrays.asList(0)));
assertEquals("1",Containers.join(":",Arrays.asList(1)));
assertEquals("null",Containers.join(":",Arrays.asList((Object)null)));
assertEquals("247",Containers.join(":",Arrays.asList(0xF7)));
assertEquals("foo",Containers.join(":",Arrays.asList("foo")));
assertEquals("0:true:2.2:null:foo",Containers.join(":",Arrays.asList(0,true,2.2,null,"foo")));
assertEquals("<0>:<true>:<2.2>:null:<foo>",Containers.join(new StringBuilder(), "<", ">", "null", ":", Arrays.asList(0,true,2.2,null,"foo")).toString());
assertEquals("<0>:<true>:<2.2>:null:<foo>",Containers.join(new StringBuffer(), "<", ">", "null", ":", Arrays.asList(0,true,2.2,null,"foo")).toString());
}
public void testJoinM() throws Exception {
assertEquals("",Containers.join((String)null,"=",null,"null",":",Arrays.asMap(String.class, Integer.class)));
assertEquals("a=0",Containers.join((String)null,"=",null,"null",":",Arrays.asMap(String.class, Integer.class, "a", 0)));
assertEquals("b=1",Containers.join((String)null,"=",null,"null",":",Arrays.asMap(String.class,Integer.class,"b",1)));
assertEquals("c=null",Containers.join((String)null,"=",null,"null",":",Arrays.asMap(String.class,Integer.class,"c",null)));
assertEquals("s=foo:b=true:d=2.2:i=0:n=null",Containers.join((String)null,"=",null,"null",":",Arrays.asMap(String.class,Object.class,"i",0,"b",true,"d",2.2,"n",null,"s","foo")));
assertEquals("<s=foo>:<b=true>:<d=2.2>:<i=0>:<n=null>",Containers.join(new StringBuilder(), "<", "=", ">", "null", ":", Arrays.asMap(String.class,Object.class,"i",0,"b",true,"d",2.2,"n",null,"s","foo")).toString());
assertEquals("<s=foo>:<b=true>:<d=2.2>:<i=0>:<n=null>",Containers.join(new StringBuffer(), "<", "=", ">", "null", ":", Arrays.asMap(String.class, Object.class, "i", 0, "b", true, "d", 2.2, "n", null, "s", "foo")).toString());
}
public void testSort() throws Exception {
List<Integer> ary = new ArrayList<Integer>(0);
Containers.sort(ary);
assertListEquals("heapSort(0)", new ArrayList<Integer>( 0 ), ary);
ary = new ArrayList<Integer>(3,2,1,1,4,4,6,5,7,2);
Containers.sort(ary);
assertListEquals("heapSort(3,2,1,1,4,4,6,5,7,2)", new ArrayList<Integer>( 1, 1, 2, 2, 3, 4, 4, 5, 6, 7 ), ary);
int N = 500; // Max number of objects that will fit in normal heap size: 16*500^2 = 4m
Integer[][] a = new Integer[N][];
List<Integer>[] a1 = new List[N];
List<Integer>[] a2 = new List[N];
Random rand = new Random();
int n = 0;
int c = 0;
for(int i=0; i<N; i++) {
int l = rand.nextInt(N);
Integer[] s = new Integer[l];
for(int j=0; j<l; j++) s[j]=rand.nextInt();
a[i] = s;
a1[i] = new ArrayList<Integer>(s.clone());
a2[i] = new ArrayList<Integer>(s.clone());
n += l;
}
System.out.println("Sorting "+N+" arrays of "+n+" elements");
long t0 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
c+=Containers.sort(a1[i]);
}
long t1 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
java.util.Arrays.sort(a[i]);
}
long t2 = System.currentTimeMillis();
for(int i=0; i<N; i++) {
assertListEquals("sort("+Arrays.join(",",a[i])+")",new ArrayList<Integer>(a[i]),a1[i]);
}
System.out.println("Sorted "+N+" arrays of "+n+" elements in "+(t1-t0)+"ms, "+c+" operations ("+(t2-t1)+"ms for java.util.Arrays.sort)");
}
protected static class ArrayContainer<T> implements Container<T> {
private final T[] a;
ArrayContainer(T... a) { this.a=a; }
public long size() { return a.length; }
public boolean isEmpty() { return a.length==0; }
public Iterator<? extends T> iterator() {
return new Iterator<T>() {
int i=0;
public boolean hasNext() { return i<a.length; }
public T next() { return a[i++]; }
public void remove() { }
};
}
public <Par> long visit(Visitor<T,Par> vis, Par par) {
long c=0;
for(T s: a) {
long p = vis.invoke(s, par);
if(p<0) return c;
c += p;
}
return c;
}
}
protected static class ArrayList<T> implements List<T> {
private final T[] array;
public ArrayList(T... array) { this.array=array; }
public long size() { return array==null?0:array.length; }
public boolean isEmpty() { return array==null||array.length==0; }
public void clear() { }
public boolean add(T elt) { return false; }
public boolean add(long idx, T elt) { return false; }
public T get(long idx) { return array[(int) idx]; }
public boolean set(long idx, T elt) { array[(int) idx] = elt; return true; }
public boolean del(long idx) { return false; }
public boolean del(T elt) { return false; }
public Iterator<? extends T> iterator() {
return new Iterator<T>() {
private volatile int pos = 0;
public boolean hasNext() { return array!=null&&pos<array.length; }
public T next() {
if(array==null||pos>=array.length) throw new NoSuchElementException();
return array[pos++];
}
public void remove() { throw new UnsupportedOperationException(); }
};
}
public <Par> long visit(Visitor<T,Par> vis, Par par) {
long ret = 0;
if(array!=null) for(T obj: array) {
long r = vis.invoke(obj, par);
if(r<0) return ret;
ret += r;
}
return ret;
}
public List<T> sublist(long beg, long len) {
return null;
}
}
protected static class ArrayMap<K,V> implements Map<K,V> {
private final K[] keys;
private final V[] vals;
ArrayMap(K[] keys, V[] vals) {
this.keys=keys;
this.vals=vals;
}
public long size() { return keys.length; }
public boolean isEmpty() { return keys.length!=0; }
public void clear() { }
public boolean has(K k) { return Arrays.indexOf((Object)k,keys)>=0; }
public V get(K k) {
int p = Arrays.indexOf((Object)k,keys);
if(p>=0) return vals[p];
return null;
}
public boolean add(Entry<K,V> item) { return false; }
public boolean add(K s, V val) { return false; }
public boolean del(K s) { return false; }
public Iterator<? extends Entry<K,V>> iterator() {
return new Iterator<Entry<K,V>>() {
int i=0;
public boolean hasNext() { return i<keys.length; }
public Entry<K,V> next() {
final K k = keys[i];
final V v = vals[i];
i++;
return new E<K,V>(k, v);
}
public void remove() { }
};
}
public Container<K> keys() { return new ArrayContainer<K>(keys); }
public Container<V> values() { return new ArrayContainer<V>(vals); }
public <Par> long visit(MapVisitor<K,V,Par> vis, Par par) {
long c=0;
for(int i=0; i<keys.length; i++) {
long p=vis.invoke(keys[i],vals[i],par);
if(p<0) return c;
c += p;
}
return c;
}
public <Par> long visit(Visitor<Entry<K,V>,Par> vis, Par par) {
long c=0;
for(int i=0; i<keys.length; i++) {
long p=vis.invoke(new E<K,V>(keys[i],vals[i]), par);
if(p<0) return c;
c += p;
}
return c;
}
private static class E<K,V> implements Map.Entry<K,V> {
private final K k;
private final V v;
public E(K k, V v) {
this.k=k;
this.v=v;
}
public K getKey() { return k; }
public V getValue() { return v; }
public V setValue(V val) { return null; }
}
}
}