removeAll seems to affect its argument - java

I have written a generic Partition class (a partition is a division of a set into disjoint subsets, called parts). Internally this is a Map<T,Integer> and a Map<Integer,Set<T>>, where the Integers are the labels of the parts. For example partition.getLabel(T t) gives the label of the part that t is in, and partition.move(T t, Integer label) moves t to the partition labelled by label (internally, it updates both the Maps).
But my method for moving a Collection of objects to a new part does not work. It seems that Set.removeAll() is affecting its argument. I think the problem is something like a ConcurrentModificationException, but I can't work it out. Sorry the code is rather long, but I have marked where the problem is (about half-way down), and the output at the bottom should make it clear what the problem is - at the end the partition is in an illegal state.
import java.util.*;
public class Partition<T> {
private Map<T,Integer> objToLabel = new HashMap<T,Integer>();
private Map<Integer,Set<T>> labelToObjs =
new HashMap<Integer,Set<T>>();
private List<Integer> unusedLabels;
private int size; // = number of elements
public Partition(Collection<T> objects) {
size = objects.size();
unusedLabels = new ArrayList<Integer>();
for (int i = 1; i < size; i++)
unusedLabels.add(i);
// Put all the objects in part 0.
Set<T> part = new HashSet<T>(objects);
for (T t : objects)
objToLabel.put(t,0);
labelToObjs.put(0,part);
}
public Integer getLabel(T t) {
return objToLabel.get(t);
}
public Set<T> getPart(Integer label) {
return labelToObjs.get(label);
}
public Set<T> getPart(T t) {
return getPart(getLabel(t));
}
public Integer newPart(T t) {
// Move t to a new part.
Integer newLabel = unusedLabels.remove(0);
labelToObjs.put(newLabel,new HashSet<T>());
move(t, newLabel);
return newLabel;
}
public Integer newPart(Collection<T> things) {
// Move things to a new part. (This assumes that
// they are all in the same part to start with.)
Integer newLabel = unusedLabels.remove(0);
labelToObjs.put(newLabel,new HashSet<T>());
moveAll(things, newLabel);
return newLabel;
}
public void move(T t, Integer label) {
// Move t to the part "label".
Integer oldLabel = getLabel(t);
getPart(oldLabel).remove(t);
if (getPart(oldLabel).isEmpty()) // if the old part is
labelToObjs.remove(oldLabel); // empty, remove it
getPart(label).add(t);
objToLabel.put(t,label);
}
public void moveAll(Collection<T> things, Integer label) {
// Move all the things from their current part to label.
// (This assumes all the things are in the same part.)
if (things.size()==0) return;
T arbitraryThing = new ArrayList<T>(things).get(0);
Set<T> oldPart = getPart(arbitraryThing);
// THIS IS WHERE IT SEEMS TO GO WRONG //////////////////////////
System.out.println(" oldPart = " + oldPart);
System.out.println(" things = " + things);
System.out.println("Now doing oldPart.removeAll(things) ...");
oldPart.removeAll(things);
System.out.println(" oldPart = " + oldPart);
System.out.println(" things = " + things);
if (oldPart.isEmpty())
labelToObjs.remove(objToLabel.get(arbitraryThing));
for (T t : things)
objToLabel.put(t,label);
getPart(label).addAll(things);
}
public String toString() {
StringBuilder result = new StringBuilder();
result.append("\nPARTITION OF " + size + " ELEMENTS INTO " +
labelToObjs.size() + " PART");
result.append((labelToObjs.size()==1 ? "" : "S") + "\n");
for (Map.Entry<Integer,Set<T>> mapEntry :
labelToObjs.entrySet()) {
result.append("PART " + mapEntry.getKey() + ": ");
result.append(mapEntry.getValue() + "\n");
}
return result.toString();
}
public static void main(String[] args) {
List<String> strings =
Arrays.asList("zero one two three".split(" "));
Partition<String> p = new Partition<String>(strings);
p.newPart(strings.get(3)); // move "three" to a new part
System.out.println(p);
System.out.println("Now moving all of three's part to the " +
"same part as zero.\n");
Collection<String> oldPart = p.getPart(strings.get(3));
//oldPart = Arrays.asList(new String[]{"three"}); // works fine!
p.moveAll(oldPart, p.getLabel(strings.get(0)));
System.out.println(p);
}
}
/* OUTPUT
PARTITION OF 4 ELEMENTS INTO 2 PARTS
PART 0: [two, one, zero]
PART 1: [three]
Now moving all of three's part to the same part as zero.
oldPart = [three]
things = [three]
Now doing oldPart.removeAll(things) ...
oldPart = []
things = []
PARTITION OF 4 ELEMENTS INTO 1 PART
PART 0: [two, one, zero]
*/

Using my debugger I place a breakpoint before the removeAll and I can see (as I suspected) that oldPart and things as the same collection so removing all elements clears that collection.

Your code is extremely confusing but as far as I can work out, oldPart and things are actually the same object. Set.removeAll() certainly doesn't affect its argument unless it is the same object as it's invoked on:
public boolean removeAll(Collection<?> c) {
boolean modified = false;
if (size() > c.size()) {
for (Iterator<?> i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
} else {
for (Iterator<?> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}
Update:
The easy way to eliminate this is to use a copy of things in the moveAll() method. Indeed such a copy already exists.
T arbitraryThing = new ArrayList<T>(things).get(0);
This line creates but then instantly discards a copy of things. So I'd suggest replacing it with:
ArrayList<T> thingsToRemove = new ArrayList<T>(things)
T arbitraryThing = thingsToRemove.get(0);
And in the rest of the method, replace all references to things to thingsToRemove.

Related

Weird Java Concurrent modification exception example [duplicate]

This question already has answers here:
Why am I not getting a java.util.ConcurrentModificationException in this example?
(10 answers)
Closed 4 years ago.
If we write like this, there is a concurrent modification exception :
public static void main(String... args) {
List<String> listOfBooks = new ArrayList<>();
listOfBooks.add("Programming Pearls");
listOfBooks.add("Clean Code");
listOfBooks.add("Effective Java");
listOfBooks.add("Code Complete");
System.err.println("Before deleting : " + listOfBooks);
for (String book : listOfBooks) {
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
System.err.println("After deleting : " + listOfBooks);
}
On the other hand, if we write like this, there is NO concurrent modification exception !
Notice that code is exact the same, except the strings for compare, in first example it is a Code, and in second it is a Java
public static void main(String... args) {
List<String> listOfBooks = new ArrayList<>();
listOfBooks.add("Programming Pearls");
listOfBooks.add("Clean Code");
listOfBooks.add("Effective Java");
listOfBooks.add("Code Complete");
System.err.println("Before deleting : " + listOfBooks);
for (String book : listOfBooks) {
if (book.contains("Java")) {
listOfBooks.remove(book);
}
}
System.err.println("After deleting : " + listOfBooks);
}
I'm using Netbeans 8.2, Windows 7 32bit, with JDK 1.8.0_131
What's wrong ?
List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.
Quoting from this Java Bug (JDK-4902078) .
When the Collections Framework was added to the platform it was deemed too expensive to check for comodification once rather than twice per iteration; the check was made on Iterator.next rather than Iterator.hasNext. Expert reviewers thought this was sufficient. They were unaware that it fails to detect one important case: if an element is removed from the list immediately prior to the final call to hasNext in an iteration, the call returns false and the iteration terminates, silently ignoring the last element on the list.
You can also check this answer :-
https://stackoverflow.com/a/8189786/1992276
There are two ways used to iterate over an collection: enumeration and iterator.
First one allows for the collection to be modified during iteration (fail slow), second does not (fail fast). In a for-each loop you are using an iterator, so any modification to the collection, during it's iteration would cause an exception.
You have 3 choices, to solve this problem:
Use an iterator instead:
Iterator<String> bookIt = listOfBooks.iterator();
while(bookIt.hasNext()){
String book = bookIt.next();
if (book.contains("Java")) {
bookIt.remove();
}
}
Create a new list with only acceptable elements (filter out the unwanted):
List<String> booksWithNoCode = listOfBooks.stream()
.filter(book-> !book.contains("Code"))
.collect(toList())
Use Collection.removeIf(), you will remove all elements from the list, that are matching given criteria.
listOfBooks.removeIf(book-> book.contains("Code"))
You can find more information in this post and here.
You can't modify the listOfBooks while you are iterating though it with the for each loop.
edit:
for (String book : listOfBooks) {
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
Is the same as:
for (Iterator<String> i = listOfBooks.iterator(); i.hasNext();) {
String book = i.next();
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java
The key in the arraylist code is:
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
and the iterator code:
public boolean hasNext() {
return cursor != size;
}
#SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
The cursor always points to the next element so when you get the "Effective Java" i = 2 but cursor is 3.
When you call the remove the cursor is at 3 and the size is 4.
The size is then decremented by the remove and now cursor == size and the next hasNext() returns false ending the loop.

Using a ListIterator

I have an assignment I am having a hard time completing. It is a two part lab which demonstrates the LinkedList and Queue classes. I have to use the offer() method and an iterator to complete the part I am having issues with. I wrote a class called BasketBallPlayer and added several objects of that type to a linkedList using add. Then I used an iterator to list those objects. However, when I use the offer() method, I am unable to list the objects with my code.
This is the snippet which throws a concurrent modification exception
LinkedList<BasketBallPlayer> list =
new LinkedList<BasketBallPlayer>();
Iterator listIterator = list.iterator();
list.offer(kyrie);
list.offer(kat) ;
list.offer(julius);
list.offer(kawhi) ;
list.offer(devin);
while(listIterator.hasNext())
System.out.println(listIterator.next());
This is the entire class from that snippet.
import java.util.Iterator;
public class Queue {
public static void main (String[] args)
{
BasketBallPlayer kyrie = new BasketBallPlayer(
"Kyrie Irving", 1, "Cavaliers");
BasketBallPlayer kat = new BasketBallPlayer(
"Karl Anthony Towns", 5, "Timberwolves");
BasketBallPlayer julius = new BasketBallPlayer(
"Julius Randle", "Power Forward", "Lakers");
BasketBallPlayer kawhi = new BasketBallPlayer(
"Kawhi Leanord", "Small Forward", "Spurs");
BasketBallPlayer devin = new BasketBallPlayer(
"Devin Booker", "Shooting Guard", "Suns");
System.out.println(kyrie);
LinkedList<BasketBallPlayer> list =
new LinkedList<BasketBallPlayer>();
Iterator listIterator = list.iterator();
list.offer(kyrie);
list.offer(kat) ;
list.offer(julius);
list.offer(kawhi) ;
list.offer(devin);
Iterator iterator = list.iterator();
while(iterator.hasNext())
{
Object player = listIterator.next();
System.out.println(player);
}
System.out.println("Which player is first?");
System.out.println(list.peek());
for(Object player: list)
{
System.out.println(list.getFirst());
list.poll();
}
}
}
lastly, the BasketballPlayer class. This class contains part 1 of the assignment. Here I demonstrate linkedList methods. This part works. I am unsure why the iterator in part 1 is not throwing exceptions while the iterator in part 2 is despite being used almost exactly the same. Can anyone educate me on how to correct my mistake?
import java.util.Locale;
import java.util.LinkedList;
import java.util.ListIterator;
public class BasketBallPlayer
{
private String name = "" , position = ""; String team = "";
private int positionNumber = 0;
public BasketBallPlayer()
{
name = "noName";
position = "noPosition";
team = "noTeam";
positionNumber = 0;
}
public BasketBallPlayer(String playersName, int thePositionNumber,
String theTeam)
{
setName(playersName); setPositionNumber(thePositionNumber);
setTeam(theTeam);
}
public BasketBallPlayer(String playersName, String playersPosition,
String theTeam)
{
setName(playersName);
setPosition(playersPosition);
setTeam(theTeam
);
}
public void setName(String theName)
{
this.name = theName;
}
public void setTeam(String theTeam)
{
this.team = theTeam;
}
public void setPosition(String playerPosition)
{
this.position = playerPosition;
if(playerPosition.contains("oint"))
this.positionNumber = 1;
else if(playerPosition.contains("hoot"))
this.positionNumber = 2;
else if(playerPosition.contains("mall"))
this.positionNumber = 3;
else if(playerPosition.contains("ower"))
this.positionNumber = 4;
else if(playerPosition.contains("enter"))
this.positionNumber = 5;
}
public void setPositionNumber(int thePositionNumber)
{
this.positionNumber = thePositionNumber;
switch(thePositionNumber){
case 1: setPosition("Point Guard");
break;
case 2: setPosition("Shooting Guard");
break;
case 3: setPosition("Small Forward");
break;
case 4: setPosition("Power Forward");
break;
case 5: setPosition("Center");
break;
}
}
public String getName()
{
return name;
}
public String getPosition()
{
return position;
}
public int getPositionNumber()
{
return positionNumber;
}
public String getTeam()
{
return team;
}
public boolean equals(Object other)
{
BasketBallPlayer objectToCompare;
if(other != null && other.getClass() == getClass())
objectToCompare = (BasketBallPlayer) other;
else
return false;
return(
(getPositionNumber() == objectToCompare.getPositionNumber()) &&
(getName() == objectToCompare.getName()) &&
getTeam() == objectToCompare.getTeam()) ;
}
public String toString()
{
if(getTeam().equals("Retired"))
return getName() + " is retired.";
else
return getName()+ " plays for the " + getTeam();
}
public static void main (String[] args)
{
// five basketball player objects
BasketBallPlayer kobe = new BasketBallPlayer("Kobe Bryant",
"Shooting Guard", "Retired");
BasketBallPlayer ben = new BasketBallPlayer(
"Ben Wallace", 5, "Retired");
BasketBallPlayer otto = new BasketBallPlayer("Otto Porter", 3,
"Wizards");
BasketBallPlayer andre = new BasketBallPlayer("Andre Drummond",
"Center", "Pistons");
BasketBallPlayer thomas = new BasketBallPlayer("Isaiah Thomas",
1, "Celtics");
BasketBallPlayer isaiah = new BasketBallPlayer("Isaiah Thomas",
"Point Guard", "Pistons");
// initialize LinkedList and add three players
LinkedList list = new LinkedList();
list.add(kobe); list.add(otto);
list.add(thomas);
// display the first one
System.out.println("First player on the list");
System.out.println(list.peek());
System.out.println();
System.out.println(kobe.getName() +
" is retired so let's remove him.");
// remove object at index 0
list.remove(0);
System.out.println();
// add andre to the top of the list
list.addFirst(andre);
// add ben to the end
list.addLast(ben);
System.out.println("New first player on the list");
System.out.println(list.peek());
// first create an Object[] which acts as a BasketBallPlayer[]
System.out.println(
"Any other retired players? Printing entire list:");
// using toArray()
Object[] other = list.toArray();
for(Object player: other)
// display each player in the array
System.out.println(player);
// demonstrate contains()
if(list.contains(ben))
list.remove(ben);
System.out.println();
System.out.println("Let's remove the retired player");
System.out.println("Is " + ben.getName() +
" still on the list?");
if(list.contains(ben))
System.out.println(ben.getName() + " is still on the list");
else
{
System.out.println(ben.getName() + " is not on the list");
System.out.println("How many players after removing? "
+ list.size());
}
System.out.println();
System.out.println(otto.getName() + " is " +
// demonstrate indexOf()
(list.indexOf(otto) + 1) + " on the list");
// create an iterator
ListIterator listIterator = list.listIterator();
System.out.println("Printing list using iterator:");
// print out the list using the iterator
while(listIterator.hasNext())
{
Object player = listIterator.next();
System.out.println(player);
}
}
One problem with the standard collections in java (and also in C#) is that you may not modify them while iterating over them.
If no extra steps are taken, and if you are unlucky, you may get no exception, just erratic program behavior. To remedy this, java does actually take an extra step: iterators actually check to make sure that you do not modify the collection while iterating, and throw a ConcurrentModificationException if you do so, as soon as possible after you do so.
This feature is called "fail-fast" iterators, that's a term you can look up.
So, from the moment you instantiate an iterator, until the moment you stop using it, you may not modify the collection from which the iterator was created.
Can you spot the place in your code where you do that?
Also, regarding what your professor said: either you did not understand what your professor said, or what they said is wrong. Iterators that offer means of modifying the collection while iterating do actually work. For example, you can do iterator.remove() to remove the current element. That works, because if you modify the collection via the iterator, then the iterator is in charge, so it can take whatever measures are necessary to prevent data corruption. What does not work, is modifying the collection by invoking any mutator methods directly on the collection itself while an iterator is active on the collection, because in that case the iterator has no knowledge of the fact that the collection is being modified at the moment that the collection is modified. The iterator throws a ConcurrentModificationException later, when it gets invoked to do anything, and it finds out that the collection had been modified in the mean time.

algorithm to find the largest area

................................
.XXXXXXXXXXXXXXX.....XXXXXXXXXX.
.X.....X.......X.....X........X.
.X.....X.......XXXXXXX........X.
.XXXXXXXXXXXX.................X.
.X....X.....X.................X.
.X....X.....XXXX..............X.
.XXXXXX........X..............X.
......X........X..............X.
......X........X..............X.
......X........X..............X.
......XXXXXXXXXXXXXXXXXXXXXXXXX.
................................
Looking for an algorithm to find the largest area. Here, "area" is defined as a number of dots (.) bounded by Xs.
private static void readFile(File inputFile) throws IOException {
Scanner fileScanner = new Scanner(inputFile);
Point previousPoint = null;
int rowCount = 0;
while(fileScanner.hasNext()){
String line = fileScanner.next();
String[] points = line.split(" ");
for(int columnCount=0;columnCount<points.length;columnCount++){
if(points[columnCount].equalsIgnoreCase("x")){
Point currentPoint = new Point();
currentPoint.setxValue(columnCount);
currentPoint.setyValue(rowCount);
}
}
rowCount++;
}
}
This is my first and struggling to move further.
This algorithm should work. You just need to implement it in Java.
Load the file into a char[][]. (1 char[] per line)
Loop through the char[][] (2 dimensionally)
upon finding a '.', perform flood fill, changing all '.' to ',', also incrementing a counter on every change.
At the end of flood fill, compare this counter with a globally set maximum. If it's higher, then set it as the new highest. (If the edges are not a proper boundary, then do not set this counter if you reached an edge during flood fill by setting a flag during 3)
Return the highest you set.
If you have any specific problems with the Java implementation, then let me know
Geobits:
Note: If you want to exclude the area "outside" any boxes, flood as
usual, but discard any area that hits the edge during the fill(skip
step 2.2 for that flood).
When doing the flood fill, you have 2 types of boundaries. A wall ('X'), and the edge of the array(which you need to explicitly check for to avoid OutOfBounds exceptions). If you hit an out of bounds, keep doing the fill, but set a flag so you know later to not consider the number you counted for the biggest box.
I was given this as assignment in an interview process and this is the compile and running code
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class FindArea {
public static void main(String[] args)
{
String fileName="C:\\map.txt";
FindArea area = new FindArea();
try{
FileReader inputFile = new FileReader(fileName);
BufferedReader bufferReader = new BufferedReader(inputFile);
char[][] twoArray= new char[100][100];
String line;
int i=0;
while ((line = bufferReader.readLine()) != null) {
twoArray[i] = line.toCharArray();
System.out.println(line);
i++;
}
bufferReader.close();
System.out.println("file read");
System.out.println("Max area: " + area.getMaxArea(twoArray));
} catch(Exception e) {
System.out.println("error : " + e.getMessage());
}
}
/**
* Get the maximum area from the given map
*
* #param charArray
* #return
*/
private int getMaxArea(char[][] charArray) {
HashMap<Integer, ArrayList<String>> numberOfBoxes = convertToBoxes(charArray);
numberOfBoxes = mergeOverlapAreas(numberOfBoxes);
int largeSize = 0;
for (Integer key : numberOfBoxes.keySet()) {
ArrayList<String> list = numberOfBoxes.get(key);
System.out.println("Key : " + key + " Size : " + list.size());
if (largeSize < list.size()) {
largeSize = list.size();
}
}
return largeSize;
}
/**
* Convert the 2d Array to HashMap
* Key being the count of boxes and
* Value being the list of indexes associations
*
* #param charArray
* #return
*/
private HashMap<Integer, ArrayList<String>> convertToBoxes(char[][] charArray) {
HashMap<Integer, ArrayList<String>> numberOfBoxes = new HashMap<Integer, ArrayList<String>>();
int boxes = 0;
for(int i=1; i<charArray.length; i++) {
for (int j=0; j<charArray[i].length; j++) {
if (charArray[i][j] == '.') {
boolean isExists = false;
for(Integer key : numberOfBoxes.keySet()) {
ArrayList<String> arrList = numberOfBoxes.get(key);
if(arrList != null) {
if(arrList.contains((i-1) + "-" + j) ||
arrList.contains(i + "-" + (j-1))) {
isExists = true;
arrList.add(i + "-" + j);
numberOfBoxes.put(key, arrList);
}
}
}
if (!isExists) {
ArrayList<String> list = new ArrayList<String>();
list.add(i + "-" + j);
numberOfBoxes.put(boxes, list);
boxes++;
}
}
}
}
return numberOfBoxes;
}
/**
* Check for the points exists in more than one area
* #param numberOfBoxes
* #return
*/
private HashMap<Integer, ArrayList<String>> mergeOverlapAreas( HashMap<Integer, ArrayList<String>> numberOfBoxes) {
for(Integer key : numberOfBoxes.keySet()) {
ArrayList<String> list1 = numberOfBoxes.get(key);
for (Integer key2 : numberOfBoxes.keySet()) {
if (key < key2) {
ArrayList<String> list2 = numberOfBoxes.get(key2);
Iterator<String> listIter = list2.iterator();
while(listIter.hasNext()) {
if (list1.contains(listIter.next())) {
list1.addAll(list2);
Set<String> noDuplicates = new HashSet<String>(list1);
numberOfBoxes.put(key, new ArrayList<String>(noDuplicates));
break;
}
}
}
}
}
return numberOfBoxes;
}
}
Here's an algorithm that's an alternative to flood fill. This method sweeps through the 2d array and whenever you encounter a node(pixel) that's outside to the left (right, top, bottom), it flags the current node as outside, ie if your neighbour is 'outside', you're marked 'outside' too.
The algorithm continues like this until there're no more updates. That means that all the nodes that are reachable from the 'outside' have been flagged. BTW, this is a very similar problem to level sets functions and updating them (where flood fill is also used). The nice this about this method is that it is ideal for parallelization.
1. Load 2D Symbol Array from File
2. hasupdates = false
3. Create 'isinside' bool array -> {
if(symbolarray[row][col] == '.' and row or col is at boundary)
isinside[row][col] = false
else
isinside[row][col] = true
}
4. do{
Do a sweep from left to right (for all rows) -> //This loop can be run parallely on all rows.
If (!isinside[row][col-1] and symbolarray[row][col] == '.'){
isinside[row][col] = false //mark current value as 'outside'
hasupdates = true
}
Do similar sweeps from right to left, top to bottom(all columns) and bottom to top.
}while(hasupdates)
5. Go through 'isinside' array and count the number of falses.
If you have huge files where you have to do this area calculation, you can have the sweeps along the rows and columns run parallely, because each row update (column update) is independent of the other updates.

Generating power set recursively without any loops

How do you write a recursive method PowerSet(String input) that prints out all possible combinations of a string that is passed to it?
For example: PowerSet("abc") will print out abc, ab, ac, bc, a, b, c
I have seen some recursive solutions with loops, but in this case no loops are allowed.
Any ideas?
Edit: The required method has only one parameter, i.e. String input.
The powerset of abcd is the union of the power-sets of abc, abd, acd (plus the set abcd itself*).
P(`abcd`) = {`abcd`} + P(`abc`) + P(`abd`) + P(`acd`) + P(`bcd`)
* Note that the empty set, which is a member of P(abcd) is also a member of P(abc), P(abd), ... so the equivalence stated above holds.
Recursively, P(abc) = {abc} + P(ab) + P(ac), and so on
A first approach, in pseudocode, could be:
powerset(string) {
add string to set;
for each char in string {
let substring = string excluding char,
add powerset(substring) to set
}
return set;
}
The recursion ends when the string is empty (because it never enters the loop).
If your really want no loops, you will have to convert that loop to another recursion.
Now we want to generate ab, ac and cb from abc
powerset(string) {
add string to set;
add powerset2(string,0) to set;
return set
}
powerset2(string,pos) {
if pos<length(string) then
let substring = (string excluding the char at pos)
add powerset(substring) to set
add powerset2(string,pos+1) to set
else
add "" to set
endif
return set
}
Another approach implement a recursive function P that either removes the first character from its argument, or does not. (Here + means set union, . means concatenation and λ is the empty string)
P(abcd) = P(bcd) + a.P(bcd)
P(bcd) = P(cd) + b.P(cd)
P(cd) = P(d) + c.P(d)
P(d) = λ+d //particular case
Then
P(d) = λ+d
R(cd) = P(d) + c.P(d) = λ + d + c.(λ+d) = λ + d + c + cd
R(bcd) = P(cd) + b.P(cd) = λ + d + c + cd + b.(λ + d + c + cd)
= λ + d + c + cd + b + bd + bc + bcd
P(abcd) = λ + d + c + cd + b + bd + bc + bcd
+ aλ + ad + ac + acd + ab + abd + abc + abcd
If loops were allowed, then P is out power-set function. Otherwise, we would need a one-parameter loopless function for concatenating a given character to a given set of strings (which obviously are two things).
Some tweak could be possible by playing with String.replace (if a String result is desired, or by replacing Set with List (so that the "additional" parameter is actually the first element in the list).
This will also do the trick:
var powerset = function(arr, prefix, subsets) {
subsets = subsets || [];
prefix = prefix || [];
if (arr.length) {
powerset(arr.slice(1), prefix.concat(arr[0]), subsets);
powerset(arr.slice(1), prefix, subsets);
} else {
subsets.push(prefix);
}
return subsets;
};
powerset('abc');
Well if you don't have loops, emulate one with recursion, using iterators this is acutally quite simple.
public final Set<Set<Integer>> powerSet(Set<Integer> set) {
Set<Set<Integer>> powerSet = new HashSet<>();
powerSet(set, powerSet, set.iterator());
return powerSet;
}
public final void powerSet(Set<Integer> set, Set<Set<Integer>> powerSet, Iterator<Integer> iterator) {
if(iterator.hasNext()) {
Integer exlude = iterator.next();
Set<Integer> powThis = new HashSet<Integer>();
powThis.addAll(set);
powThis.remove(exlude);
powerSet.add(powThis);
powerSet(powThis, powerSet, powThis.iterator());
powerSet(set, powerSet, iterator);
}
}
//usage
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
set.add(4);
log.error(powerSet(set).toString());
A recursive version of the generic solution proposed by João Silva :
public static <T> Set<Set<T>> powerSet2(Set<T> originalSet) {
Set<Set<T>> sets = new HashSet<Set<T>>();
if (originalSet.isEmpty()) {
sets.add(new HashSet<T>());
return sets;
}
List<T> list = new ArrayList<T>(originalSet);
T head = list.get(0);
Set<T> rest = new HashSet<T>(list.subList(1, list.size()));
addSets(sets, powerSet(rest), head);
return sets;
}
private static <T> void addSets(Set<Set<T>> sets, Set<Set<T>> setsToAdd, T head) {
Iterator<Set<T>> iterator = setsToAdd.iterator();
if (iterator.hasNext()) {
Set<T> set = iterator.next();
iterator.remove();
Set<T> newSet = new HashSet<T>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
addSets(sets, setsToAdd, head);
}
}
I extract the recursive addSets method to transform the original for loop:
for (Set<T> set : powerSet(rest)) {
Set<T> newSet = new HashSet<T>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
void powerSet(int * ar, int *temp, int n, int level,int index)
{
if(index==n) return;
int i,j;
for(i=index;i<n;i++)
{
temp[level]=ar[i];
for(j=0;j<=level;j++)
printf("%d ",temp[j]);
printf(" - - - t\n");
powerSet(ar, temp, n, level+1,i+1);
}
}
int main()
{
int price[] = {1,2,3,7};
int temp[4] ={0};
int n = sizeof(price)/sizeof(price[0]);
powerSet(price, temp, n, 0,0);
return 0;
}
Simple solution but with poor time complexity(2^n) is as following(just keep one thing in mind once we have to avoid(i.e. 0) and once we have to take it(i.e. 1):
public HashSet<int[]> powerSet(int n) {
return calcPowerSet(n-1, new HashSet<int[]>(), new int[n]);
}
private HashSet<int[]> calcPowerSet(int n, HashSet<int[]> result, int []set) {
if(n < 0) {
result.add(set.clone());
return null;
}
else {
set[n] = 0;
calcPowerSet(n-1, result, set);
set[n] = 1;
calcPowerSet(n-1, result, set);
return result;
}
}
Just for fun, a version that does powersets of any set stored in a LinkedList (to make it easy to remove the head element). Java 8 streams do the functional part:
static <T> LinkedList<LinkedList<T>> powerset(LinkedList<T> elements) {
if (elements.isEmpty())
return copyWithAddedElement(new LinkedList<>(), new LinkedList<>());
T first = elements.pop();
LinkedList<LinkedList<T>> powersetOfRest = powerset(elements);
return Stream.concat(
powersetOfRest.stream(),
powersetOfRest.stream().map(list -> copyWithAddedElement(list, first)))
.collect(Collectors.toCollection(LinkedList::new));
}
static <T> LinkedList<T> copyWithAddedElement(LinkedList<T> list, T elt) {
list = new LinkedList<>(list);
list.push(elt);
return list;
}
This is inspired by the following Common Lisp, which shows that the right language can make things simpler:
(defun powerset (set)
(cond ((null set) '(()))
(t (let ((powerset-of-rest (powerset (cdr set))))
(append powerset-of-rest
(mapcar #'(lambda (x) (cons (car set) x))
powerset-of-rest))))))
Based on the info here, here is solution in C#.
NOTE: the loop in the main function is just to print the result into the console value. No loops used in the PowerSet method.
public static void Main(string[] args)
{
string input = "abbcdd";
Dictionary < string, string> resultSet = new Dictionary<string, string>();
PowerSet(input, "", 0, resultSet);
//apply sorting
var resultSorted = resultSet.OrderBy(l => l.Key.Length).ThenBy(l=>l.Key);
//print values
foreach(var keyValue in resultSorted)
{
Console.Write("{{{0}}}, ",keyValue.Key);
}
}
/// <summary>
/// Computes the powerset of a string recursively
/// based on the Algorithm http://www.ideserve.co.in/learn/generate-all-subsets-of-a-set-recursion
/// </summary>
/// <param name="input">Original input string</param>
/// <param name="temp">Temporary variable to store the current char for the curr call</param>
/// <param name="depth">The character position we are evaluating to add to the set</param>
/// <param name="resultSet">A hash list to store the result</param>
public static void PowerSet(string input, string temp, int depth, Dictionary<string, string> resultSet)
{
//base case
if(input.Length == depth)
{
//remove duplicate characters
string key = new string(temp.ToCharArray().Distinct().ToArray());
//if the character/combination is already in the result, skip it
if (!resultSet.ContainsKey(key))
resultSet.Add(key, key);
return;//exit
}
//left
PowerSet(input, temp, depth + 1, resultSet);
//right
PowerSet(input, temp + input[depth], depth + 1, resultSet);
}
PowerSet will print all combinations of elements
for example [123] will forms 123,12,13,23,1,2,3
We can find the powerset values easily by using the concept of tree
let add an element or remove an element every time
abc
a " "
ab a b " "
abc ab ac a bc b c " "
here first have added a and not added a so tree form "a" and " " subelements
now take a constant and add 'b' to it and don't add 'b' then it will create another sub tree for 'a' in the same way the we add and remove element utill we reach the end .
here the method to add element and to remove element
powerset(str,i+1,cur+str.charAt(i));
powerset(str,i+1,cur);
import java.io.*;
import java.util.*;
import java.lang.Math;
class Demo{
public static void main(String args[]) {
String str="123";
String str1="";
int r=0;
powerset(str,r,str1);
}
public static void powerset(String str,int i,String cur){
if(i==str.length()){
System.out.println(cur);
return;
}
powerset(str,i+1,cur+str.charAt(i));
powerset(str,i+1,cur);
}
}
Power set (P) of string "abc" contains 2 types of elements: character 'a' itself and its combination with elements of P('bc').
Similarly P('bc') contains character 'b' and its combination with elements of P('c').
And also P('c') contains character 'c' and its combination with null string.
Now make function powerSet(string input, string substring="") This will print the substring and it denotes the combination of first element of input string with substring.
Base Condition: When length of input string is 0 then prints the substring.
Recursive condition:
1). Call powerSet( input[1: input.length()], substring ) #this is for elements of power set of string exluding 0th index character
2). Call powerSet( input[1: input.length()], substring+input[0]) # this is for combination.
#include<iostream>
#include<string>
using namespace std;
void powerSet(string input,string substring){
if(input.length()==0){
cout<<substring<<", ";
return;
}
string op1=substring;
string op2=substring + input[0];
powerSet(input.substr(1),op1);
powerSet(input.substr(1),op2);
return;
}
int main(){
string input="abc";
powerSet(input);
}

How to leftshift an ArrayList

I'm using an ArrayList to hold a history of objects. Each new object I add using the .add method, like:
if(event.getAction() == MotionEvent.ACTION_UP)
{
if(currentWord != null)
{
wordHist.add(currentWord);
}
if(wordHist.size() > WORDHIST_MAX_COUNT)
{
wordHist.remove(0);
}
}
However I don't want this to grow indefinitely, but to be limited to a certain value. If it reaches this maximum value, I want the oldest object (index 0) to be removed, and the rest to be left shifted, so previous index 1 is now index 0, etc.
How can this be done?
Thanks
ArrayList is not really a good choice in this case, but it can by done by calling remove(0) method. But if you want to do that efficiently, a linked list is better
(edited to make it clear that LinkedList is not generally better than ArrayList, but only in this case)
If it reaches this maximum value, I want the oldest object (index 0) to be removed
Then do wordHist.remove(0). That will remove the element at index 0.
To be precise:
wordHist.add(new Word("hello"));
if (wordHist.size() > MAX_SIZE)
wordHist.remove(0);
As user658991 states however, you should be aware of that this is a linear operation, i.e., takes time proportional to the number of elements in the list.
You could do this in constant time using LinkedList methods add and removeFirst.
Another option would be to wrap an array, or ArrayList in a class called something like CircularArrayList. In circular list structures you'll override the oldest element when adding a new one.
Edit:
Your code works fine:
import java.util.*;
class Test {
static int WORDHIST_MAX_COUNT = 3;
static List<String> wordHist = new ArrayList<String>();
public static void add(String currentWord) {
// VERBATIM COPY OF YOUR CODE
if (true/*event.getAction() == MotionEvent.ACTION_UP*/)
{
if(currentWord != null)
{
wordHist.add(currentWord);
}
if(wordHist.size() > WORDHIST_MAX_COUNT)
{
wordHist.remove(0);
}
}
}
public static void main(String[] args) {
add("a");
add("b");
add("c");
for (int i = 0; i < wordHist.size(); i++)
System.out.printf("i: %d, word: %s%n", i, wordHist.get(i));
System.out.println();
add("d");
for (int i = 0; i < wordHist.size(); i++)
System.out.printf("i: %d, word: %s%n", i, wordHist.get(i));
}
}
Prints:
i: 0, word: a
i: 1, word: b
i: 2, word: c
i: 0, word: b <-- b is now at index 0.
i: 1, word: c
i: 2, word: d
Use the remove( ) method.
Using remove(0) will remove the element from the 0th index.
U can use list.remove(index)// here index being '0', this internally shifts rest of the array up. An alternative solution wud be to use a queue or dequeue.
One simple implementation of what Op De Cirkel suggested
import java.util.ArrayList;
import java.util.List;
public class SimpleCircularHistory {
private int sizeLimit, start = 0, end = 0;
boolean empty = false;
private List<String> history;
public SimpleCircularHistory(int sizeLimit) {
this.sizeLimit = sizeLimit;
history = new ArrayList<String>(sizeLimit);
}
public void add(String state){
empty = false;
end = (end + 1) % sizeLimit;
if(history.size() < sizeLimit){
history.add(state);
}else {
history.set(end, state);
start = (end + 1) % sizeLimit;
}
}
public String rollBack(){
if(empty){ // Empty
return null;
}else {
String state = history.get(end);
if(start == end){
empty = true;
}else {
end = (end + sizeLimit - 1) % sizeLimit;
}
return state;
}
}
public void print(){
if(empty){
System.out.println("Empty");
}else {
for(int i = start;; i = (i + 1) % sizeLimit){
System.out.println(history.get(i));
if(i == end) break;
}
System.out.println();
}
}
public static void main(String[] args) {
SimpleCircularHistory h = new SimpleCircularHistory(3);
h.add("a");
h.add("b");
h.add("c");
h.add("d");
h.add("e");
h.add("f");
h.print();
h.add("X");
h.add("Y");
h.rollBack();
h.rollBack();
h.print();
h.add("t");
h.add("v");
h.add("w");
h.print();
h.rollBack();
h.rollBack();
h.rollBack();
h.print();
h.rollBack();
h.print();
}
}
This would print out :
d
e
f
f
t
v
w
Empty
Empty
Yeah, I've noticed this behaviour in adroid's lists too. It's REALLY irritating.
Anyway, there is a way to get around it if I don't mind object creation/destruction and the resulting garbage collection (NEVER do this in a onDraw of a surfaceview or something).
What I do is basically have two tracking int's; one to place the new object, and one to remove it:
int trackInt = 0;
int removeInt = 0;
//and then, in the method/class you use this:
Object newobject = new Object();
//add to list
objectList.add(trackInt, newobject);
trackInt++;
if (bugList.size() > 20) //20 is the max number of object you want, ie the maximum size of the list
{
objectList.remove(removeInt);
trackInt = removeInt;
removeInt++;
if (removeInt > 19) //remember, the list is zero indexed!
{
removeInt = 0;
}
}
Commons-collections has exactly what you're looking for:
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/buffer/CircularFifoBuffer.html

Categories

Resources