I need to find a fast and efficient way to create unique pairs out of array items if there is more than two of them.
My first question is that this code I came up with is throwing sometimes java.lang.StackOverflowError, why? I know it is going to deep with the recursive calls in the helper, but how to fix it?
My second question is how to make the code more efficient. I don't need to use array - it could be some other collection type.
This is what I have come up with:
import java.util.HashMap;
import java.util.concurrent.ThreadLocalRandom;
/**
* Generates unique pairs from items in array. Each item cannot occur more than
* once as key nor value.
*
* #author lkallas
*/
public class UniquePairs {
private static final String[] NAMES
= new String[]{"Aaron", "Barney", "Charlie", "Desiré", "Edward"};
private static final HashMap<String, String> PAIRS = new HashMap<>();
public static void main(String[] args) {
// Check if there is more than one item in array.
if (NAMES.length > 1) {
// Find pairs
for (String name : NAMES) {
if (!PAIRS.containsKey(name)) {
PAIRS.put(name, helper(name));
}
}
// Show results.
PAIRS.entrySet().stream().forEach((pair) -> {
System.out.println(pair.getKey() + " - " + pair.getValue());
});
} else {
System.out.println(NAMES[0]);
}
}
/**
* Helper for finding partner.
*
* #param key Name that need partner.
* #return Unique partner.
*/
private static String helper(String key) {
// Get random partner from array.
String partner = NAMES[getRandomInt(0, NAMES.length - 1)];
// Cannot pair up a name with itself. Also partner cannot occur more than once.
if (key.equals(partner) || PAIRS.containsValue(partner)) {
partner = helper(key);
}
return partner;
}
/**
* Random integer in the given range.
*
* #param min Minimum value of the random integer.
* #param max Maximum value of the random integer.
* #return Random integer in given range.
*/
private static int getRandomInt(int min, int max) {
return ThreadLocalRandom.current().nextInt(min, max + 1);
}
}
EDIT:
Using
return ThreadLocalRandom.current().nextInt(min, max + 1);
instead of
return new Random().nextInt((max - min) + 1) + min;
EDIT 2:
Created special class for this kind of operation. Feel free to use it if necessary.
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
/**
*
* #author lkallas
*/
public class MatchMaker {
private final Map<Object, Object> PAIRS;
private List<? extends Object> items;
public MatchMaker() {
this.PAIRS = new HashMap<>();
}
/**
* Pairs items uniquely and randomly so that keys nor values are repeated.
* For proper pairing of Objects it is recommended to provide your own
* implementation of <code>equals()</code> method. Also bear in mind that
* you should also override <code>hashCode()</code> if there's any chance of
* your objects being used in a hash table.
*
* #param input List with objects that are paired with each other.
* #return Map with generated pairs.
* #throws IllegalArgumentException When input List is empty or contains
* only one item.
*/
public Map<?, ?> getPairs(List<? extends Object> input)
throws IllegalArgumentException {
if (input.size() > 1) {
items = input;
for (int i = 0; i < input.size() - 1; i++) {
Object k = input.get(i);
PAIRS.put(k, getPartner(k));
}
Object k = items.get(items.size() - 1);
if (PAIRS.containsValue(k)) {
PAIRS.put(k, getPartner(k));
} else {
Object k1 = items.get(getRandomInt(0, items.size() - 1));
PAIRS.put(k, PAIRS.get(k1));
PAIRS.put(k1, k);
}
} else {
throw new IllegalArgumentException("Can't pair one or less items.");
}
return PAIRS;
}
/**
* Helper for finding a random partner.
*
* #param key Object that needs partner.
* #return Unique partner that is not used by other keys.
*/
private Object getPartner(Object key) {
// Get random partner from array.
Object partner = items.get(getRandomInt(0, items.size() - 1));
// Cannot pair up a key with itself. Also partner cannot occur more than once.
if (key.equals(partner) || PAIRS.containsValue(partner)) {
partner = getPartner(key);
}
return partner;
}
/**
* Random integer in the given range.
*
* #param min Minimum value of the random integer.
* #param max Maximum value of the random integer.
* #return Random integer in given range.
*/
private static int getRandomInt(int min, int max) {
return ThreadLocalRandom.current().nextInt(min, max + 1);
}
}
Change this
for (String name : NAMES) {
if (!PAIRS.containsKey(name)) {
PAIRS.put(name, helper(name));
}
}
to
for (int i = 0; i < NAMES.length - 1; i++) {
String name = NAMES[i];
PAIRS.put(name, helper(name));
}
String name = NAMES[NAMES.length - 1];
if (PAIRS.containsValue(name)) {
PAIRS.put(name, helper(name));
} else {
String otherKey = NAMES[ThreadLocalRandom.current().nextInt(0, NAMES.length - 1)];
PAIRS.put(name, PAIRS.get(otherKey));
PAIRS.put(otherKey, name);
}
What's going on with your version is explained in this answer. Essentially, you are running out of options at the last step, so helper calls itself repeatedly until a StackOverflowError occurs.
Related
I need to create a method which must return the partial derivative of a function in the form of a term when passed the var you want to differentiate w respect to. This is my class the method is differentiate:
package poly;
import java.util.ArrayList;
import java.util.TreeSet;
import util.Vector;
/** Implements an individual term in a polynomial. If 5x^2 + 3xy is a polynomial,
* it has two terms 5x^2 and 2xy, each of which would be represented by a different
* instance of this class.
*
* #author ssanner#mie.utoronto.ca
*
*/
public class Term {
// For term 2.1*x^4*y*z^2, the data members would take values as follows:
public double _coef; // = 2.1
public ArrayList<String> _vars; // = ["x", "y", "z"]
public ArrayList<Integer> _pows; // = [4, 1, 2]
/** This constructor has been implemented for you.
*
* #param coef -- sets the _coef member
*/
public Term(double coef) {
_coef = coef;
_vars = new ArrayList<String>();
_pows = new ArrayList<Integer>();
}
/** This constructor has been implemented for you -- it parses a term
* representation from a String into the format required by this class.
* You need two understand the following code.
*
* #param s -- String to parse
* #throws PolyException if s is malformed
*/
public Term(String s) throws PolyException {
if (s == null || s.trim().equals(""))
throw new PolyException("Empty Term, cannot read");
// Initialize this term
_coef = 1.0d; // Will multiply any constants by this
_vars = new ArrayList<String>();
_pows = new ArrayList<Integer>();
// You need to understand all lines of the following code
String[] factors = s.split("\\*");
for (String factor : factors) {
factor = factor.trim(); // Get rid of leading and trailing whitespace
try {
// If successful, multiplies in a constant (multiple constants in a product allowed)
_coef *= Double.parseDouble(factor);
} catch (NumberFormatException e) {
// If not a coefficient, must be a factor "<var>^<pow>"
// Must be a variable to a power -- parse the factor and add to list
int pow = 1; // If no power, defaults to 1
String[] var_pow = factor.split("\\^");
String var = var_pow[0];
if (var_pow.length == 2) {
try { // Second part must be exponent
pow = Integer.parseInt(var_pow[1]);
} catch (NumberFormatException f) {
throw new PolyException("ERROR: could not parse " + factor);
}
} else if (var_pow.length > 2)
throw new PolyException("ERROR: could not parse " + factor);
// Successfully parsed variable and power, add to list
if (_vars.contains(var))
throw new PolyException("ERROR: " + var + " appears twice in " + s);
_vars.add(var);
_pows.add(pow);
}
}
}
/** Produce a re-parseable representation of this Term as a String. This
* has been done for you.
*
*/
public String toString() {
// Using "+" to append Strings involves a lot of String copies since Strings are
// immutable. StringBuilder is much more efficient for append.
StringBuilder sb = new StringBuilder();
sb.append(String.format("%01.3f", _coef));
for (int i = 0; i < _vars.size(); i++) {
String var = _vars.get(i);
int pow = _pows.get(i);
sb.append("*" + var + (pow == 1 ? "" : "^" + pow));
}
return sb.toString();
}
/** Returns all of the variables used in this Term as a sorted set (TreeSet).
* This has been implemented for you, but you need to understand how it works
* since you'll write a similar method in Polynomial that uses this method.
*
* #return
*/
public TreeSet<String> getAllVars() {
// TreeSets are like HashSets but sorted alphabetically (lookup and insertion are
// a little less efficient than HashSets, but this won't matter for our sizes).
return new TreeSet<String>(_vars);
}
///////////////////////////////////////////////////////////////////////////////
// TODO: Your methods here! You should add some helper methods that facilitate
// the implementation of the methods below.
///////////////////////////////////////////////////////////////////////////////
/** If Term defines a function f(x,y) = 2xy^2 and assignments is { x=2.0 y=3.0 }
* then this method returns 36.0, which is the evaluation of f(2.0,3.0).
*
* #param assignments
* #return
* #throws PolyException
*
*
*/
public double coef(){
return _coef;
}
public Double var(int i){
return Double.parseDouble(_vars.get(i));
}
public ArrayList power(){
return _pows;
}
public double evaluate(Vector assignments) throws PolyException {
double evaluated = 0;
double sum = 0;
for(int i = 0; i < _vars.size(); i++){
sum += Math.pow(var(i), _pows.get(i));
}
evaluated *= sum;
return evaluated;
}
/** If Term defines a function f(.) then this method returns the **symbolic**
* partial derivative (which you can verify from calculus is still a Term):
*
* partial f(1.0,2.0) / partial var.
*
* Specifically, if Term defines a function f(x,y) = 2xy^2 and var = "x"
* then this method returns a **new** Term 2y^2 and if var = "y" then it
* instead returns a **new** Term 4xy.
*
* #param var
* #return partial derivative of this w.r.t. var as a new Term
*/
public Term differentiate(String var) {
// TODO: Should not return null!
return null;
}
}
I'm unsure on how the differentiate method would be called but an example of the method to differentiate a relatively simple function could be done like the following...
Please note this method could use some fine-tuning (it returns a String not a Term value) and it doesn't take into consideration logs/trig functions etc but hopefully it's a helpful start.
public static void main(String args[]) {
String differentiated = differentiate("32x^2y^3", "x");
System.out.println(differentiated);
}
public static String differentiate(String function, String var) {
StringBuilder partialDerivative = new StringBuilder();
int indexOfVar = function.indexOf(var);
boolean coefficient = false;
String coefficientValue;
double coefficientAmount = 1;
StringBuilder powerValue = new StringBuilder();
StringBuilder variable = new StringBuilder();
double powerAmount;
StringBuilder otherVariables = new StringBuilder();
//ascertains whether a coefficient is present
int k = 0;
while (Character.isDigit(function.charAt(k))) {
coefficient = true;
if (k == 0) {
coefficientValue = Character.toString(function.charAt(k));
} else {
coefficientValue = function.substring(0, k+1);
}
coefficientAmount = Double.parseDouble(coefficientValue);
k++;
}
//checks for other variables that may also have polynomials
for (int i = 0; i <= function.length() - 1; i++) {
if (Character.isLetter(function.charAt(i)) && function.charAt(i) != var.charAt(0)) {
otherVariables.append(function.charAt(i));
if (i < function.length() - 1) {
if (function.charAt(i + 1) == '^') {
findPolynomial(function, i, otherVariables);
}
}
}
}
//works out if the var value has a polynomial and therefore times the coefficient by it and reduces it by one
if (function.charAt(indexOfVar + 1) == '^') {
findPolynomial(function, indexOfVar, powerValue);
powerAmount = Double.parseDouble(powerValue.toString().substring(1));
coefficientAmount *= powerAmount;
powerAmount -= 1;
powerValue.replace(1,powerValue.length(),Double.toString(powerAmount));
if(powerAmount != 1) {
variable.append(var).append(powerValue);
} else {
variable.append(var);
}
}
//include method for ln() or exponential functions
//include method for trig functions (sin() cos() etc)
if (coefficient) {
partialDerivative.append(coefficientAmount).append(otherVariables).append(variable);
} else {
partialDerivative.append(otherVariables).append(variable);
}
return partialDerivative.toString();
}
private static void findPolynomial(String function, int indexOfVar, StringBuilder powerValue) {
powerValue.append(function.charAt(indexOfVar + 1));
int j = indexOfVar + 2;
while (Character.isDigit(function.charAt(j))) {
powerValue.append(function.charAt(j));
if (j == function.length() - 1) {
break;
} else {
j++;
}
}
}
I was given the following code to return an enumeration of the elements of a dictionary.
public class ArrayDictionary extends Dictionary implements Cloneable {
protected Object[] keys ;
protected Object[] values;
protected int incr;
protected int nelems;
public Enumeration elements() {
return new ArrayEnumeration(values,nelems);
}
ArrayEnumeration is not defined within the rest of the code, none of the methods that are defined take an Array of Objects[] and an int, we're expected to do code inspection, and the way the question is written implies we shouldn't add new methods, I'll post the full code below. The only solution my friend and I can come up with is using a for loop to go through each item in the dictionary and use the get method that is defined?
Edit: There may be many other errors in the code we've not been through it all yet, as we can't get round this problem.
public class ArrayDictionary extends Dictionary implements Cloneable {
/** The array of keys */
protected Object[] keys ;
/** The array of corresponding values */
protected Object[] values ;
/** How many real elements are in */
protected int nelems ;
/** By how much to grow */
protected int incr ;
/**
* Create an ArrayDictionary using default values for initial size and
* increment.
*/
public ArrayDictionary() {
this(10,10) ;
}
/**
* Create an ArrayDictionary using the given initial size.
* (The increment is set to the same value).
* #param init The initial size
*/
public ArrayDictionary(int init) {
this(init,init) ;
}
/**
* Clone this array dictionary.
* <p>As for hashtables, a shallow copy is made, the keys and elements
* themselves are <em>not</em> cloned.
* #return The clone.
*/
public Object clone() {
try {
ArrayDictionary cl = (ArrayDictionary) super.clone();
cl.values = new Object[values.length];
System.arraycopy(values, 0, cl.values, 0, values.length);
cl.keys = new Object[values.length];
System.arraycopy(keys, 0, cl.keys, 0, keys.length);
return cl;
} catch (CloneNotSupportedException ex) {
throw new InternalError();
}
}
/**
* Create an ArrayDictionary using the given initial size and
* the given increment for growing the array.
* #param init the initial size
* #param incr the increment
*/
public ArrayDictionary(int init, int incr) {
keys = new Object[init] ;
values = new Object[init] ;
this.incr = incr ;
nelems = 0 ;
}
/**
* Create an ArrayDictionary, contructing the arrays of keys and
* values from the two given vectors.
* The two vectors should have the same size.
* The increment is set to the number of elements.
* #param keys the vector of keys
* #param values the vector of values
*/
public ArrayDictionary(Vector keys,Vector values) {
this(keys,values,values.size()) ;
}
/**
* Create an ArrayDictionary, contructing the arrays of keys and
* values from the two given vectors.
* The two vectors should have the same size.
* #param keys the vector of keys
* #param values the vector of values
* #param incr the increment for growing the arrays
*/
public ArrayDictionary(Vector keys, Vector values, int incr) {
this.incr = incr ;
nelems = keys.size() ;
this.keys = new Object[nelems] ;
this.values = new Object[nelems] ;
keys.copyInto(this.keys) ;
values.copyInto(this.values) ;
}
/**
* Create an ArrayDicitonary, <em>using</em> (not copying) the given pair
* of arrays as keys and values. The increment is set to the length of the
* arrays.
* #param keys the array of keys
* #param values the array of values
*/
public ArrayDictionary(Object[] keys, Object[] values) {
this(keys,values,values.length) ;
}
/**
* Create an ArrayDicitonary, <em>using</em> (not copying) the given pair
* of arrays as keys and values.
* #param keys the array of keys
* #param values the array of values
* #param incr the increment for growing the arrays
*/
public ArrayDictionary(Object[] keys, Object[] values, int incr) {
this.incr = incr ;
nelems = keys.length ;
this.keys = keys ;
this.values = values ;
}
protected final void grow() {
grow(keys.length+incr) ;
}
protected void grow(int newCapacity) {
Object[] newKeys = new Object[newCapacity] ;
Object[] newVals = new Object[newCapacity] ;
System.arraycopy(keys,0,newKeys,0,keys.length) ;
System.arraycopy(values,0,newVals,0,values.length) ;
keys = newKeys ;
values = newVals ;
}
/**
* Returns an enumeration of the elements of the dictionary.
* #return the enumeration
*/
public Enumeration elements() {
return new ArrayEnumeration(values,nelems);
}
/**
* Returns the value that maps to the given key.
* #param key the key
* #return the value
*/
public Object get(Object key) {
int n,i;
for(i=0,n=0;i<keys.length;i++) {
if(n >= nelems)
break ;
if ( keys[i] == null )
continue;
if(keys[i].equals(key))
return values[i] ;
n++ ;
}
return null;
}
/**
* "Optimized" method to obtain the values
* corresponding to several keys, in one swoop.
* #param rKeys An array of requested keys
* #return An array of corresponding values
*/
public Object[] getMany(Object[] rKeys) {
Object[] rValues = new Object[rKeys.length] ;
int i,n ;
for(i=0,n=0;i<keys.length;i++) {
if(n >= nelems) break ;
if(keys[i]==null)
continue ;
inloop:
for(int j=0;j<rKeys.length;j++)
if(keys[i].equals(rKeys[j])) {
rValues[j] = values[i] ;
break inloop ;
}
n++ ;
}
return rValues ;
}
/**
* Are there any entries in the dictionary?
* #return <strong>true</strong> if there are no entries,
* <strong>false></strong> otherwise.
*/
public final boolean isEmpty() {
return nelems==0 ;
}
/**
* Increases the capacity of this dictionary to at least the
* specified number of key/value mappings.
* #param minCapacity the desired minimum capacity
*/
public final void ensureCapacity(int minCapacity) {
if(minCapacity>keys.length) grow(minCapacity) ;
}
/**
* Returns an enumeration of the keys of the dictionary.
* #return the enumeration
*/
public Enumeration keys() {
return new ArrayEnumeration(keys,nelems) ;
}
/**
* Adds a mapping between a key and a value to the dictionary.
* Will grow the arrays if necessary.
* #param key the key
* #param value the corresponding value
* #return the previous value corresponding to the key, or null if
* the key is new.
*/
public Object put(Object key,Object value) {
int empty = -1 ;
int i,n ;
for(i=0,n=0;i<keys.length;i++) {
if(n >= nelems)
break ;
if(keys[i] == null) {
empty = i ;
continue ;
}
if(keys[i].equals(key)) {
Object prev = values[i] ;
values[i]=value;
return prev ;
}
n++ ;
}
if(empty!=-1) {
keys[empty]=key ;
values[empty]=value ;
nelems++ ;
} else {
grow() ;
keys[nelems] = key ;
values[nelems++] = value ;
}
return null ;
}
/**
* Removes a key (and its value) from the dictionary;
* #param key the key to remove
* #return the value that used to map to that key
*/
public Object remove(Object key) {
int i,n ;
for(i=0,n=0;i<keys.length;i++) {
if(n >= nelems)
break ;
if(keys[i] == null)
continue ;
if(keys[i].equals(key)) {
nelems-- ;
Object prev = values[i] ;
keys[i] = values[i] = null ;
return prev ;
}
n++ ;
}
return null ;
}
/**
* Returns the number of elements in the dictionary
* #return the number of elements
*/
public final int size() { return nelems ; }
/**
* Returns the maximum number of keys the dictionary can hold
* without reallocating an array.
* #return the capacity of the dictionary
*/
public final int capacity() { return keys.length ; }
/**
* Returns the nth key.
* #param n the index of the desired key
* #return the nth key, or null if no key in that place.
*/
public final Object keyAt(int n) {
return keys[n] ;
}
/**
* Returns the nth element (value).
* #param n the index of the desired element
* #return the nth element, or null if no element in that place.
*/
public final Object elementAt(int n) {
return values[n] ;
}
/**
* Sets the element at the nth place in the array.
* #param n the index of the element to change
* #param newVal the value to change it to
* #return the old value
*/
public Object setElementAt(int n,Object newVal) {
Object prev = values[n] ;
values[n] = newVal ;
return prev ;
}
/**
* Removes the nth mapping (key/value pair) in the dictionary.
* #param n the index of the element to remove
* #return the old value of the element at the nth place
*/
public Object removeElementAt(int n) {
if(values[n]!=null) {
Object prev = values[n] ;
values[n] = keys[n] = null ;
nelems--;
return prev;
} else return null ;
}
/**
* Creates a string representation of the dictionary
* #return the string representation.
*/
public String toString() {
StringBuffer buf = new StringBuffer(100) ;
buf.append('[') ;
for(int i=0;i<keys.length;i++) {
if(keys[i]==null)
continue ;
buf.append(keys[i]) ;
buf.append('=') ;
buf.append(values[i]) ;
buf.append(' ') ;
}
buf.append(']') ;
return buf.toString() ;
}
}
I searched throughout the forums and could not find what I was looking for. I am doing an assignment for school and I need to implement some methods. I did most of them and am getting the output I need. However, I'm having trouble implementing the Cartesian Product (xproduct) method.
Here is my code so far:
import java.util.*;
public class Set
{
private ArrayList<String>elements;
/**
* creates an empty set
*/
public Set()
{
elements = null;
}
/**
* creates a set using the elements of the ArrayList s.
* #param s the ArrayList whose elements are used to create this set.
* #throws IllegalArgumentException if s contains duplicity.
*/
public Set(ArrayList<String> s)
{
int i;
elements = new ArrayList<String>();
for(i=0;i<s.size();i++)
{
if(elements.contains(s.get(i)))
{throw new IllegalArgumentException("Set(ArrayList<String>)duplicity not allowed in sets");}
elements.add(s.get(i));
}
}
/**
* creates a set using the elements of the array s.
* #param s the array whose elements are used to create this set.
* #throws illegalArgumentException if s contains duplicity.
*/
public Set(String[] s)
{
int i;
elements = new ArrayList<String>();
for(i=0; i<s.length; i++)
{
if (elements.contains(s[i]))
{throw new IllegalArgumentException("Set(String[]):duplicity not allowed in sets");}
elements.add(s[i]);
}
}
/**
* determines whether a set contains the specified element
* #param elt an element
* #return true if elt is an element of this set; otherwise, false
*/
public boolean isElement(String elt)
{
return elements.contains(elt);
}
/**
* determines the size of this set.
* #return the size of this set.
*/
public int cardinality()
{
return elements.size();
}
/**
* computes the intersection of this set and the
* specified set.
* #param s a set
* #return a set representing the intersection of this set
* and s.
*/
public Set intersect(Set s)
{
int i;
ArrayList<String> result = new ArrayList<String>();
for (i=0;i<s.cardinality();i++)
{
if (this.isElement(s.elements.get(i)))
{result.add(s.elements.get(i));}
}
return new Set(result);
}
/**
* computes the union of this set and the specified set.
* #param s a sets
* #return a set representing the union of this set
* and s.
*/
public Set union(Set s)
{
int i;
ArrayList<String> result = new ArrayList<String>();
result.addAll(this.elements);
result.addAll(s.elements);
for(i=0;i<s.cardinality();i++)
{
if (this.isElement(s.elements.get(i)))
{result.remove(s.elements.get(i));}
}
return new Set(result);
}
/**
* computes the difference between this set and the
* specified set.
* #param s a set
* #return a set representing the difference between
* this set and s.
*/
public Set diff(Set s)
{
int i;
ArrayList<String> result = new ArrayList<String>();
result.addAll(this.elements);
for(i=0;i<s.cardinality();i++)
{
if (this.isElement(s.elements.get(i)))
{result.remove(s.elements.get(i));}
}
return new Set(result);
}
/**
* computes the symmetric difference between this set
* and the specified set.
* #param s a set
* #return a set representing the symmetrical difference
* between this set and s.
*/
public Set symDiff(Set s)
{
int i;
ArrayList<String> result = new ArrayList<String>();
result.addAll(this.elements);
result.addAll(s.elements);
for(i=0;i<s.cardinality();i++)
{
if (this.isElement(s.elements.get(i)) && s.isElement(this.elements.get(i)))
{result.remove(this.elements.get(i));
result.remove(s.elements.get(i));}
}
return new Set(result);
}
/**
* computes the Cartesian product for this set
* and the specified set.
* #param s a set
* #return a set representing the Cartesian product
* of this set and s.
*/
public Set xProduct(Set s)
{
int i;
ArrayList<String> result = new ArrayList<String>();
result.addAll(this.elements);
result.addAll(s.elements);
}
/**
* determines whether a set is empty
* #return true if this set is empty; otherwise, false
*/
public boolean isEmpty()
{
return elements.isEmpty();
}
/**
* determines whether this set is equal to the specified
* set.
* #param s a set
* #return true if this set is equal to s; otherwise, false
*/
public boolean equals(Set s)
{
return elements.equals(s.elements);
}
/**
* determines whether this set is a subset of the specified set.
* #param s a set
* #return true if this set is a subset of s; otherwise, false
*/
public boolean subset(Set s)
{
return elements.containsAll(s.elements);
}
/**
* determines whether this set is a proper subset of the specified set.
* #param s a set
* #return true if this set is a proper subset of s; otherwise, false
*/
public boolean properSubset(Set s)
{
if(elements.equals(s.elements) && elements.containsAll(s.elements))
{return false;}
else{
return true;
}
}
/**
* returns a string {x1,x2,...,xn} representing this set,
* where x1,x2,...,xn are elements of this set.
* #return a string representation of this set formatted
* as specified.
*/
#Override
public String toString()
{
return "{"+this.elements+"}";
}
public static void main(String[] args)
{
String[]a1 = {"2","4","6","8"};
String[]a2 = {"2","3","5","7"};
String[]a3 = {"1","3","5"};
Set s1 = new Set(a1);
Set s2 = new Set(a2);
Set s3 = new Set(a3);
System.out.print("S1 ="); System.out.printf("%s",s1);
System.out.println();
System.out.print("S2 ="); System.out.printf("%s",s2);
System.out.println();
System.out.print("S3 ="); System.out.printf("%s",s3);
System.out.println();System.out.println();
System.out.println("(S1 \u222A S2:)");
System.out.printf("%s \u222A %s = %s%n",s1,s2,s1.union(s2));
System.out.println();
System.out.println("(S1 \u2296 S2) \u222a (S1 \u2229 S2) \u222a (S2 \u2296 S1)");
System.out.printf("%s \u2296 %s \u222a %s \u2229 %s \u222a %s \u2296 %s = %s%n",s1,s2,s1,s2,s2,s1,s1.diff(s2).union(s1.intersect(s2).union(s2.diff(s1))));
//Cartesian Product of s1 and s2
//Cartesian product of s2 and s1
}
}
Any guidance would be appreciated.
I do not understand why you have diffculties, but the cartezian product of Set1 x Set2 could be computed something like this:
Product = {}
Set1. iterate with i
Set2.iterate with j
Product.append (pair(i,j))
If you still have difficulties, please tell me to code it in Java. For now I posted only the pseudocode.
As you may have understood with the title, I need some smart thinking here :)
I have a List<List<Object>> object. If you think of the Object objects as integers, you could see it like this :
{{1,2},{10,20,30},{100}}
I need to get all possible lists containing exactly one element of each list, that is, come up with this :
{{1,10,100},{1,20,100},{1,30,100},{2,10,100},{2,20,100},{2,30,100}}
Of course you don't know at compiling time how much items the lists will contain, so you cannot rely on an overlapping of for loops...
How would you come up with this? Time constraints are not relevant to my problem because the lists will likely contain few elements.
Iterative algorithm.
public class A {
public static List<List<Integer>> combinations(List<List<Integer>> inputList) {
List<List<Integer>> result = new LinkedList<List<Integer>>();
for (Integer i : inputList.get(0)) {
List<Integer> temp = new ArrayList<Integer>(1);
temp.add(i);
result.add(temp);
}
for (int i = 1; i < inputList.size(); i++) {
result = make(result, inputList.get(i));
}
return result;
}
private static List<List<Integer>> make(List<List<Integer>> in, List<Integer> n) {
List<List<Integer>> res = new LinkedList<List<Integer>>();
for (List<Integer> l : in) {
for (Integer i : n) {
List<Integer> cur = new ArrayList<Integer>(l.size() + 1);
cur.addAll(l);
cur.add(i);
res.add(cur);
}
}
return res;
}
public static void main(String[] args) {
List<List<Integer>> inputList = new ArrayList();
inputList.add(new ArrayList<Integer>() {{
add(1);
add(2);
}});
inputList.add(new ArrayList<Integer>() {{
add(10);
add(20);
add(30);
}});
inputList.add(new ArrayList<Integer>() {{
add(100);
}});
System.out.println(combinations(inputList));
}
}
*Notice that this code not for production! You should replace LinkedList with ArrayList with initial size, make checks and so on.
upd usage example provided. there is some code improvement. But it still only draft. I wouldn't recommend you use it in real tasks.
I won't implement it, but here's an idea for a recursive algorithm:
if we are dealing with a list containing a single list of elements (i.e.e.g {{1,2,3}}), then the result is - of course - a list of lists containing one element each (i.e.e.g. {{1},{2},{3}}
if we have more than one list in the list of lists, we do a recursive call of the algorithm. We take all resulting lists from this recursive call and combine each element of the first list of the list of lists with each list from the recursive call.
Here's raw Python code:
def combiner(ll):
if len(ll)==1:
return [[x] for x in ll[0]] # base case
firstlist = ll[0]
result = []
for i in combiner(ll[1:]): # recursive call
for firstelem in firstlist:
result.append([firstelem]+i) # combining lists
return result
Just for completeness, what you are searching is called the Cartesian product of your lists, called such since the size of our result list is the product of the sizes of the individual lists.
Edit: Here is an implementation which works for arbitrary Iterables of Iterables, and creates an Iterable of lists. It creates the elements lazily on iteration, so it works for really big products which don't fit in the memory all at one, too.
package de.fencing_game.paul.examples;
import java.util.*;
/**
* A iterable over the cartesian product of a iterable of iterables
* with some common element type.
*<p>
* The elements of the product are tuples (lists) of elements, one of
* each of the original iterables.
*<p>
* The iterator iterates the elements in lexicographic order, ordered by
* the appearance of their components in their respective iterators.
*<p>
* Since we are iterating the iterables lazily, the iterators should
* act the same each time, otherwise you'll get strange results (but it
* will still be well-defined).
*</p>
*
* Inspired by the question How to get a list of all lists containing exactly one element of each list of a list of lists on Stackoverflow (by Dunaril).
*
* #author Paŭlo Ebermann
*/
public class ProductIterable<X>
implements Iterable<List<X>>
{
private Iterable<? extends Iterable<? extends X>> factors;
public ProductIterable(Iterable<? extends Iterable<? extends X>> factors) {
this.factors = factors;
}
public Iterator<List<X>> iterator() {
return new ProductIterator();
}
private class ProductIterator
implements Iterator<List<X>>
{
/**
* an element of our stack, which contains
* an iterator, the last element returned by
* this iterator, and the Iterable which created
* this iterator.
*/
private class StackElement {
X item;
Iterator<? extends X> iterator;
Iterable<? extends X> factor;
boolean has;
StackElement(Iterable<? extends X> fac) {
this.factor = fac;
newIterator();
}
/**
* checks whether the {#link #step} call can
* get a new item.
*
*/
boolean hasNext() {
return has ||
(has = iterator.hasNext());
}
/**
* steps to the next item.
*/
void step() {
item = iterator.next();
has = false;
}
/**
* creates a new iterator.
*/
void newIterator() {
iterator = factor.iterator();
has = false;
}
/**
* for debugging: a string view of this StackElement.
*/
public String toString() {
return "SE[ i: " + item + ", f: " + factor + "]";
}
}
/**
* our stack of iterators to run through
*/
private Deque<StackElement> stack;
/**
* is our next element already produced (= contained in
* the `item`s of the stack?
*/
private boolean hasNext;
/**
* constructor.
*/
ProductIterator() {
stack = new ArrayDeque<StackElement>();
try {
fillStack();
hasNext = true;
}
catch(NoSuchElementException ex) {
hasNext = false;
}
}
/**
* creates the stack. only called from constructor.
*/
private void fillStack() {
for(Iterable<? extends X> fac : factors) {
StackElement el = new StackElement(fac);
el.step();
stack.push(el);
}
}
/**
* steps the iterator on top of the stack, and maybe the iterators
* below, too.
* #return true if more elements are available.
*/
private boolean stepIterator() {
if(stack.isEmpty())
return false;
StackElement top = stack.peek();
while(!top.hasNext()) {
stack.pop();
if (!stepIterator()) {
return false;
}
top.newIterator();
stack.push(top);
}
top.step();
return true;
}
/**
* returns true if `next` will return a next element.
*/
public boolean hasNext() {
return
hasNext ||
(hasNext = stepIterator());
}
/**
* returns the next element of the cartesian product.
*/
public List<X> next() {
if(!hasNext()) {
throw new NoSuchElementException();
}
hasNext = false;
return makeList();
}
/**
* creates a list from the StackElements in reverse order.
*/
private List<X> makeList() {
List<X> list = new ArrayList<X>(stack.size());
// TODO: more efficient reverse copying
for(StackElement se : stack) {
list.add(0, se.item);
}
return list;
}
/**
* the remove method is not supported,
* the cartesian product is immutable.
*/
public void remove() {
throw new UnsupportedOperationException();
}
} // class ProductIterator
/**
* a test method which creates a list of lists and
* from this the cartesian product.
*/
public static void main(String[] params) {
#SuppressWarnings("unchecked")
List<List<Integer>> factors =
Arrays.asList(Arrays.asList(1,2),
Arrays.asList(10,20,30),
Arrays.asList(100));
Iterable<List<Integer>> product =
new ProductIterable<Integer>(factors);
List<List<Integer>> productList =
new ArrayList<List<Integer>>();
for(List<Integer> pEl : product) {
productList.add(pEl);
System.out.println(pEl);
}
System.out.println(productList);
}
}
One more edit: here is a index-based lazy list implementation.
package de.fencing_game.paul.examples;
import java.util.*;
/**
* The cartesian product of lists, in an (unmodifiable) index-based
* implementation.
*
*<p>
* The elements of the product are tuples (lists) of elements, one from
* each of the base list's element lists.
* These are ordered in lexicographic order, by their appearance in the
* base lists.
*</p>
*<p>
* This class works lazily, creating the elements of the product only
* on demand. It needs no additional memory to the base list.
*</p>
*<p>
* This class works even after changes of the base list or its elements -
* the size of this list changes if any of the factor lists changes size.
* Such changes should not occur during calls to this method, or
* you'll get inconsistent results.
*</p>
* <p>
* The product of the sizes of the component lists should be smaller than
* Integer.MAX_INT, otherwise you'll get strange behaviour.
* </p>
*
*<p>
* Inspired by the question How to get a list of all lists containing exactly one element of each list of a list of lists on Stackoverflow (by Dunaril).
*
* #author Paŭlo Ebermann
*/
public class ProductList<X>
extends AbstractList<List<X>>
{
private List<? extends List<? extends X>> factors;
/**
* create a new product list, based on the given list of factors.
*/
public ProductList(List<? extends List<? extends X>> factors) {
this.factors = factors;
}
/**
* calculates the total size of this list.
* This method takes O(# factors) time.
*/
public int size() {
int product = 1;
for(List<?> l : factors) {
product *= l.size();
}
return product;
}
/**
* returns an element of the product list by index.
*
* This method calls the get method of each list,
* so needs needs O(#factors) time if the individual
* list's get methods are in O(1).
* The space complexity is O(#factors), since we have to store
* the result somewhere.
*
* #return the element at the given index.
* The resulting list is of fixed-length and after return independent
* of this product list. (You may freely modify it like an array.)
*/
public List<X> get(int index) {
if(index < 0)
throw new IndexOutOfBoundsException("index " + index+ " < 0");
// we can't create a generic X[], so we take an Object[]
// here and wrap it later in Arrays.asList().
Object[] array = new Object[factors.size()];
// we iteratively lookup the components, using
// modulo and division to calculate the right
// indexes.
for(int i = factors.size() - 1; i >= 0; i--) {
List<?> subList = factors.get(i);
int subIndex = index % subList.size();
array[i] = subList.get(subIndex);
index = index / subList.size();
}
if(index > 0)
throw new IndexOutOfBoundsException("too large index");
#SuppressWarnings("unchecked")
List<X> list = (List<X>)Arrays.asList(array);
return list;
}
/**
* an optimized indexOf() implementation, runs in
* O(sum n_i) instead of O(prod n_i)
* (if the individual indexOf() calls take O(n_i) time).
*
* Runs in O(1) space.
*/
public int indexOf(Object o)
{
if(!(o instanceof List))
return -1;
List<?> list = (List<?>)o;
if (list.size() != factors.size())
return -1;
int index = 0;
for(int i = 0; i < factors.size(); i++) {
List<?> subList = factors.get(i);
Object candidate = list.get(i);
int subIndex = subList.indexOf(candidate);
if(subIndex < 0)
return -1;
index = index * subList.size() + subIndex;
}
return index;
}
/**
* an optimized lastIndexOf() implementation, runs in
* O(sum n_i) time instead of O(prod n_i) time
* (if the individual indexOf() calls take O(n_i) time).
* Runs in O(1) space.
*/
public int lastIndexOf(Object o)
{
if(!(o instanceof List))
return -1;
List<?> list = (List<?>)o;
if (list.size() != factors.size())
return -1;
int index = 0;
for(int i = 0; i < factors.size(); i++) {
List<?> subList = factors.get(i);
Object candidate = list.get(i);
int subIndex = subList.lastIndexOf(candidate);
if(subIndex < 0)
return -1;
index = index * subList.size() + subIndex;
}
return index;
}
/**
* an optimized contains check, based on {#link #indexOf}.
*/
public boolean contains(Object o) {
return indexOf(o) != -1;
}
/**
* a test method which creates a list of lists and
* shows the cartesian product of this.
*/
public static void main(String[] params) {
#SuppressWarnings("unchecked")
List<List<Integer>> factors =
Arrays.asList(Arrays.asList(1,2),
Arrays.asList(10,20,30, 20),
Arrays.asList(100));
System.out.println("factors: " + factors);
List<List<Integer>> product =
new ProductList<Integer>(factors);
System.out.println("product: " + product);
List<Integer> example = Arrays.asList(2,20,100);
System.out.println("indexOf(" + example +") = " +
product.indexOf(example));
System.out.println("lastIndexOf(" + example +") = " +
product.lastIndexOf(example));
}
}
I added implementations of contains, indexOf and lastIndexOf which are quite better than the original ones from AbstractList (or AbstractCollection) (for bigger factors than in your example, at least). These are not optimized for the sublists, since the sublists are simply taken from AbstractList.
Simple iterative algorithm.
public static List<List<Object>> doStaff(List<List<Object>> objectList) {
List<List<Object>> retList = new ArrayList<List<Object>>();
int[] positions = new int[objectList.size()];
Arrays.fill(positions,0);
int idx = objectList.size() -1;
int size = idx;
boolean cont = idx > -1;
while(cont) {
idx = objectList.size() -1;
while(cont && positions[idx] == objectList.get(idx).size()) {
positions[idx] = 0;
idx--;
if(idx > -1) {
positions[idx] = positions[idx]+ 1;
} else {
cont = false;
}
}
if(cont) {
List<Object> tmp = new ArrayList<Object>(size);
for(int t = 0; t < objectList.size(); t++) {
tmp.add(t, objectList.get(t).get(positions[t]));
//System.out.print(objectList.get(t).get(positions[t])+ " ");
}
retList.add(tmp);
// System.out.println();
positions[size] = positions[size] + 1;
}
}
return retList;
}
If necessary, an explanation, just let me know.
You might use that scala code:
def xproduct (xx: List [List[_]]) : List [List[_]] =
xx match {
case aa :: bb :: Nil =>
aa.map (a => bb.map (b => List (a, b))).flatten
case aa :: bb :: cc =>
xproduct (bb :: cc).map (li => aa.map (a => a :: li)).flatten
case _ => xx
}
Since crossproduct is another name for cartesian product, it's name is xproduct.
Here is a java implementation of phimuemue's Python algorithm.
private static List<List<Item>> getAllPossibleLists(List<List<Item>> itemsLists) {
List<List<Item>> returned = new ArrayList<List<Item>>();
if(itemsLists.size() == 1){
for (Item item : itemsLists.get(0)) {
List<Item> list = new ArrayList<Item>();
list.add(item);
returned.add(list);
}
return returned;
}
List<Item> firstList = itemsLists.get(0);
for (List<Item> possibleList : getAllPossibleLists(itemsLists.subList(1, itemsLists.size()))) {
for(Item firstItem : firstList){
List<Item> addedList = new ArrayList<Item>();
addedList.add(firstItem);
addedList.addAll(possibleList);
returned.add(addedList);
}
}
return returned;
}
Feel free to comment further. Thank you for all your efforts !
This is what I have so far but I don't now what to do next. The question is as follows (sorry the coding is not all appearing in one box):
Implement a method
public void search (String searchString) { }
to iterate through the notes ArrayList until it finds a note that contains the searchString. It should then print either the item found or the message "String not found". When testing check for a String that is in the list and for one that isn't.
Code:
import java.util.ArrayList;
import java.util.Iterator;
/**
* A class to maintain an arbitrarily long list of notes.
* Notes are numbered for external reference by a human user.
* In this version, note numbers start at 0.
*
* #author David J. Barnes and Michael Kolling.
* #version 2008.03.30
*/
public class Notebook
{
// Storage for an arbitrary number of notes.
private ArrayList<String> notes;
/**
* Perform any initialization that is required for the
* notebook.
*/
public Notebook()
{
notes = new ArrayList<String>();
}
/**
* Store a new note into the notebook.
* #param note The note to be stored.
*/
public void storeNote(String note)
{
notes.add(note);
}
/**
* #return The number of notes currently in the notebook.
*/
public int numberOfNotes()
{
return notes.size();
}
/**
* Show a note.
* #param noteNumber The number of the note to be shown.
*/
public void showNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number, so we can print it.
System.out.println(notes.get(noteNumber));
}
else {
System.out.println("there are fewer items in the notebook than that");
// This is not a valid note number, so do nothing.
}
}
public void removeNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number.
notes.remove(noteNumber);
}
else {
System.out.println("there are fewer items in the notebook than that");
// This is not a valid note number, so do nothing.
}
}
public void multiplesOfFive()
{
int i = 10;
while(i < 100)
{
System.out.println(i);
i = i + 5;
}
}
public int sum(int a, int b)
{
int index = a;
int result = 0;
while(index <= b)
{
result = result + index;
index = index + 1;
}
return result;
}
public int product(int a, int b)
{
int index = a;
int result = 1;
while(index <= b)
{
result = result * index;
index = index + 1;
}
return result;
}
public boolean
isPrime (int n)
{
if (n<=1)return false;
if (n==2) return true;
for (int i = 2;i<=n-1;i++)
{
if (n%i==0)return false;
}
return true;
}
}
two ideas to consider:
When you compose your search method, consider utilizing the contains method in the String class as you iterate (see Kaleb Brasee's post).
ensure that you handle the case when a null is passed in as the search param.
Use one of the new for-each style loops to iterate over the List of notes:
for (String string : notes) {
// This will loop over all the Strings in the notes List.
// Perform your logic here.
}
If the list is not in alphabetical order you need to loop through the list comparing each string against the search string. Once you find a match you can break the loop (using a return true (or the string) would be the easiest way) then outside the loop you can place a return false to signify that a match was not found.
Some methods you will need to use:
ArrayList:
size() - gives you the size of the list so you know when you have reached the end
get( int index ) - returns the item in the list at the specified index
String: equals( String cmp ) - compares 2 strings and returns an int
It would be good to become familiar with the Java API so that you can find methods and their return values.
If the list is in alphabetical order there are more efficient ways to search.