package sets;
import java.util.ArrayList;
import java.util.Collections;
import lipstone.joshua.parser.Parser;
import lipstone.joshua.parser.exceptions.ParserException;
import lipstone.joshua.parser.exceptions.UndefinedResultException;
import lipstone.joshua.parser.types.BigDec;
import lipstone.joshua.parser.util.ConsCell;
import lipstone.joshua.parser.util.ConsType;
public class NumberSet extends Set<BigDec> {
private static final Parser parser = new Parser();
/**
* Constructs a <tt>NumberSet</tt> with the values stored in list
*
* @param list
* a comma-separated list of numbers
* @throws ParserException
*/
public NumberSet(String list) throws ParserException {
ArrayList<String> items = Parser.fromCommaList(list);
for (String item : items)
set.add(new BigDec(item));
}
/**
* Creates a <tt>NumberSet</tt> with the values in items
*
* @param items
* the values to initially add to this <tt>NumberSet</tt>
*/
public NumberSet(ArrayList<BigDec> items) {
set.addAll(items);
}
/**
* Creates a <tt>NumberSet</tt> with the values in items
*
* @param items
* the values to initially add to this <tt>NumberSet</tt>
*/
public NumberSet(BigDec[] items) {
for (BigDec item : items)
set.add(item);
}
/**
* Creates a <tt>NumberSet</tt> with the values in items
*
* @param items
* the values to initially add to this <tt>NumberSet</tt>
*/
public NumberSet(Double[] items) {
for (Double item : items)
set.add(new BigDec(item.toString()));
}
/**
* Creates a <tt>NumberSet</tt> with the values in items
*
* @param items
* the values to initially add to this <tt>NumberSet</tt>
*/
public NumberSet(Integer[] items) {
for (Integer item : items)
set.add(new BigDec(item.toString()));
}
/**
* @return gets the arithmetic mean of this set
* @throws UndefinedResultException
*/
public BigDec getMean() throws UndefinedResultException {
if (set.size() <= 0)
return BigDec.ZERO;
BigDec total = BigDec.ZERO;
for (BigDec d : set)
total = total.add(d);
return total.divide(new BigDec(set.size()));
}
/**
* @return the median of this set NOTE: this does not sort the set prior to getting the median
*/
public BigDec getMedian() {
if (set.size() <= 0)
return BigDec.ZERO;
return set.get(set.size() / 2);
}
/**
* @return the interquartile range of this set
* @throws UndefinedResultException
*/
public BigDec getIQR() throws UndefinedResultException {
if (set.size() <= 0)
return BigDec.ZERO;
return set.get(((int) 3 * set.size() / 4)).subtract(set.get(((int) set.size() / 4)));
}
/**
* Convenience method - forwards to {@link #getSTDEV(int)} with subtracter = 1
*
* @return the standard deviation of this set
* @throws ParserException
*/
public BigDec getSTDEV() throws ParserException {
return getSTDEV(1);
}
/**
* Gets the standard deviation of this set
*
* @param subtracter
* the amount to subtract from N
* @return the standard deviation of this set
* @throws ParserException
*/
public BigDec getSTDEV(int subtracter) throws ParserException {
BigDec mean = getMean(), sigma = BigDec.ZERO;
if (set.size() <= 1)
return BigDec.ZERO;
//Construct sigma
for (BigDec d : set) {
ConsCell temp = parser.run(new ConsCell(new ConsCell(d, ConsType.NUMBER, new ConsCell('-', ConsType.OPERATOR, new ConsCell(mean, ConsType.NUMBER), ConsType.CONS_CELL), ConsType.CONS_CELL), ConsType.CONS_CELL));
sigma = sigma.add(new BigDec(temp.toString()));
}
//Run the root
return new BigDec(parser.run(new ConsCell(new ConsCell(sigma, ConsType.NUMBER, new ConsCell('/', ConsType.OPERATOR, new ConsCell(new BigDec(set.size() - subtracter), ConsType.NUMBER), ConsType.CONS_CELL), ConsType.CONS_CELL), ConsType.CONS_CELL, new ConsCell('^', ConsType.OPERATOR, new ConsCell(new BigDec(0.5), ConsType.NUMBER), ConsType.CONS_CELL), ConsType.CONS_CELL)).toString());
}
/**
* Gets the z-score of the specified item in this set. If the item is not in the set, it adds the item to this set
*
* @param item
* the item to get the z-score of
* @return the z-score of this item
* @throws ParserException
*/
public BigDec getzScore(BigDec item) throws ParserException {
boolean isInList = false;
for (BigDec d : set)
if (d.eq(item))
isInList = true;
if (!isInList)
set.add(item);
ConsCell result = parser.run(new ConsCell(new ConsCell(item, ConsType.NUMBER, new ConsCell('-', ConsType.OPERATOR, new ConsCell(getMean(), ConsType.NUMBER), ConsType.CONS_CELL), ConsType.CONS_CELL),
ConsType.CONS_CELL, new ConsCell('/', ConsType.OPERATOR, new ConsCell(getSTDEV(1), ConsType.NUMBER), ConsType.CONS_CELL), ConsType.CONS_CELL));
set.remove(item);
if (result.length() == 1 && result.getCarType() == ConsType.NUMBER)
return (BigDec) result.getCar();
else
throw new ParserException("Unable to find a numeric result to getzScore.", null);
}
/**
* Gets the mode of this set. NOTE: this method does /not/ change the order of this set
*
* @return the most common item in this set
*/
public BigDec getMode() {
ArrayList<BigDec> tempSet = new ArrayList<BigDec>(set); //Holds the old set and its order
sort();
BigDec mode = BigDec.ZERO, prev = set.get(0);
int max = 0, count = 0;
for (int i = 0; i < set.size(); i++) {
BigDec d = set.get(i);
if (d.neq(prev)) {
if (count >= max) {
max = count;
mode = set.get(i - 1);
}
count = 0;
prev = d;
}
else
count++;
}
if (count > max)
mode = set.get(set.size() - 1);
set.clear();
set.addAll(tempSet);
return mode;
}
/**
* Sorts this set using standard numeric comparisons
*/
public void sort() {
Collections.sort(set);
}
}