I've been following Tim Buchalka's course Java Programming Masterclass for Software Developers and I've been modifying his program from lesson 118.
I want to update my list at the runtime while using the list iterator (navigate method). The program runs fine, but if I update my list, Java throws an error: ConcurrentModificationException
I have come up with the following solution:
Whenever a user performs a modification of the list, other methods run, and update the list and pass it to the navigate() method. By doing this, my program enters multi-level nested methods, and the problem comes up when a user wants to exit from the program (case 0: in navigate() method). User has to press 0 as many times as many nested methods were ran.
My initial idea was to count how many times navigate() was nested, then using for loop return as many times as it was nested. But later I understood it does not make sense
What can I do to exit from the program by using case 0: just once?
package com.practice;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Scanner;
public class List extends Traveler {
private LinkedList<String> linkedList;
private String tripName;
public List(String travelerName, int travelerAge, String tripName) {//it has to have same amount of parameters or more with super constructor!
super(travelerName, travelerAge);
this.tripName = tripName;
this.linkedList = new LinkedList<>();
}
public List(){} //it has to have same amount of parameters or more with super constructor!
public LinkedList<String> getLinkedList() {
return linkedList;
}
public String getTripName() {
return tripName;
}
private void removeCity(LinkedList<String> cityList, String deletedCity) {
if(cityList.remove(deletedCity)) {
System.out.println(deletedCity + " has been removed");
} else System.out.println("Could not find the city you want to remove");
List.navigate(cityList);
}
//adds a new city and update the list without an error
private void noExceptionError(LinkedList<String> listOfCities, String cityName) {
ListIterator<String> listIterator = listOfCities.listIterator();
while((listIterator.hasNext())) {
int comparison = listIterator.next().compareTo(cityName);
if(comparison == 0) {
System.out.println(cityName + " has been already added to the list");
return;
} else if(comparison > 0) {
listIterator.previous();
break;
}
}
listIterator.add(cityName);
List.navigate(listOfCities);
}
private void loadToList(LinkedList<String> listOfCities) {
alphabeticallyAdd(listOfCities, "Poznan");
alphabeticallyAdd(listOfCities, "Gdansk");
alphabeticallyAdd(listOfCities, "Szczeczin");
alphabeticallyAdd(listOfCities, "Warszawa");
alphabeticallyAdd(listOfCities, "Lodz");
alphabeticallyAdd(listOfCities, "Wroclaw");
List.navigate(listOfCities);
}
private void alphabeticallyAdd(LinkedList<String> listOfCities, String cityName) {
ListIterator<String> listIterator = listOfCities.listIterator(); //just a setup; doesn't point to the 1st element
while((listIterator.hasNext())) {
//if value is greater, the word that is in the list is alphabetically bigger, thus, put it before the list element
//if equal, it is duplicate! return false
// else it is less, thus, we have to move further in the list
int comparison = listIterator.next().compareTo(cityName); //retrieves the 1st value and goes to the next
if(comparison == 0) {
System.out.println(cityName + " has been already added to the list");
return;
} else if(comparison > 0) {
listIterator.previous(); //because we've used .next() in the int comparison initialization
listIterator.add(cityName); //don't use linkedList.add because it doesn't know the int comparison, so cannot properly add!!!
return;
}
}
listIterator.add(cityName); //adding at the end of the list
}
public static void navigate(LinkedList<String> listOfCities) {
Scanner userChoice = new Scanner(System.in);
List travelListObject = new List();
ListIterator<String> listIterator = listOfCities.listIterator();
boolean goingForward = true;
while(true) {
Main.menu();
int choice = userChoice.nextInt();
userChoice.nextLine(); //takes care of enter key problem
switch(choice) {
case 0:
System.out.println("Goodbye");
//possible improvement
/* for(int i = 0; i <= List.amountNestedMethods; i++) {
return;
}*/
return;
case 1: //moving forward
if(!goingForward) {
if(listIterator.hasNext()) {
listIterator.next();
}
}
if(listIterator.hasNext()) {
System.out.println(listIterator.next());
Traveler.setNumberVisitedCities(Traveler.getNumberVisitedCities() + 1);
goingForward = true;
} else {
System.out.println("No more cities in the list");
goingForward = false;
}
break;
case 2: //moving back
if(goingForward) {
if(listIterator.hasPrevious()) {
listIterator.previous();
}
goingForward = false;
}
if(listIterator.hasPrevious()) {
Traveler.setNumberVisitedCities(Traveler.getNumberVisitedCities() + 1);
System.out.println(listIterator.previous());
} else {
System.out.println("You're at the beginning of the list");
goingForward = true;
}
break;
case 3:
Main.printCities(listOfCities);
break;
case 4:
break;
case 5:
System.out.println("Write new city");
String addedCity = userChoice.next();
travelListObject.noExceptionError(listOfCities, addedCity);
break;
case 6:
System.out.println("Write the city you want to delete");
String deletedCity = userChoice.next();
travelListObject.removeCity(listOfCities, deletedCity);
break;
case 7:
System.out.println("You have been in " + Traveler.getNumberVisitedCities() + " cities in total");
break;
case 9:
travelListObject.loadToList(listOfCities);
break;
default:
System.out.println("Something weird happened. Try to choose an option again");
}
}
}
}
If you want to exit the program you can simply call System.exit(n), where the n is an integer return code (the convention being that code 0 means normal execution and other values indicate some sort of error).
I'm trying to solve a puzzle that goes like this: 100 people stand in a circle. The first person kills the person next to him and hands the gun to the next person. Which person is left at the end?
This is what I have so far, but when I run it, it shows an out of bounds exception. I realized that when I write people.remove(i+1), the program runs to the end of the arraylist and has no way to start back at the beginning to continue the pattern. How do I do this?
Thanks for any help!
private void btnEnterActionPerformed(java.awt.event.ActionEvent evt) {
int input = Integer.parseInt(txtInput.getText());
ArrayList <Integer> people = new ArrayList <> ();
for (int i = 0; i < input; i++) {
people.add(i);
}
while (people.size() != 0) {
int i = 1;
people.remove(i+1);
i++;
}
for (int i = 0; i < people.size(); i++) {
lblOutput.setText(" " + people.get(i));
}
The reason you get an out of bound exception is that you check the size to be non-zero, but the call of remove(i+1) with i set to 1 means removing from the third spot in the list, which may not be there. Only the initial element at index zero is guaranteed to be there.
Also note that i++ has no effect, because i is reset back to 1 at the top of the loop's body.
With the condition of people.size() != 0 the only guaranteed thing is that you would be able to remove at index zero. However, this is rather inefficient, because all elements past that index need to be copied. This makes removal an O(n2), which could be slow when the list is really long.
Generally, though, the idiomatic way of managing removals from a list is using ListIterator<T> for removal of zero to a few items, or copying into a separate list and replacing the original list with the new one when you need to remove a significant portion of the list.
As I understand the problem, you need to remove every second person from the list until only one person remains.
The basic problem with your current implementation, is, first, you don't do any range checking (how do you know an element actually exists at i+1) and secondly, you loop until the list is empty, which isn't what you really want.
The basic requirement could use compounding loops, the outer loop checks the size of the list and keeps looping while the size of the List is greater then 1, the second loop processes the list, removing every other person from the list. Note, I don't reset the hasGun flag in the outer loop, this means that on each iteration of the inner loop, the gun continues to pass to the next survivor.
ArrayList<Integer> people = new ArrayList<>();
for (int i = 0; i < 10; i++) {
people.add(i);
}
boolean hasGun = true;
while (people.size() > 1) {
Iterator<Integer> iterator = people.iterator();
while (iterator.hasNext()) {
System.out.print("> " + iterator.next());
if (!hasGun) {
// You get shot...
iterator.remove();
System.out.println(" got shot");
} else {
System.out.println(" shoots");
}
hasGun = !hasGun;
}
}
for (Integer person : people) {
System.out.println(person);
}
This example also makes uses the List's Iterator, this over comes, in part, the issue of the array out of bounds, but you could also use a for-next loop and the hasGun flag as well.
To circulate through your array with indexing, use the remainder operator:
int actual = 0;
while (people.size() != 1) {
people.remove( (actual+1) % people.size() );
actual = (actual+1) % people.size();
}
I just think an ArrayList is not the best data structure for this problem. I find a LinkedList would be more fit. Actually, I found a very easy recursive solution using one. Have a look at this code:
public class Main {
public static int kill(LinkedList<Integer> people) {
assert people.size() > 0;
System.out.println("people: " + people);
if (people.size() < 3)
return people.getFirst();
else {
System.out.println("kill: " + people.remove(1));
people.addLast(people.removeFirst());
return kill(people);
}
}
public static void main(String[] args) {
LinkedList<Integer> people = new LinkedList<>();
for (int i = 0; i <=100; i++) {
people.add(i);
}
int survivor = kill(people);
System.out.println("Last survivor: " + survivor);
}
}
I just remove (kill?) the second member on the list and send the first one back to the end of the list. This process can be repeated until there are 2 people left, in which case you can guess the last survivor will be the first one in the list cause he will kill the second person.
If I had to resolve this problem, I would create my own Person class with a next property pointing to the next person.
Person class:
public class Person {
private int id;
private Person next;
public Person(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public Person getNext() {
return this.next;
}
public void setNext(Person next) {
this.next = next;
}
public void killNext() {
this.next = this.next.next;
}
}
Once that is in place, it's trivial to setup a circular set of linked persons. The algorithm then simply becomes looping each person by following the next property, killing the next person on each iteration. And the loop exits when the next property points to himself, indicating that there is no one left.
Algorithm:
public static void main(String[] args) {
// Setup 100 persons in a linked circle.
Person startingPerson = new Person(1);
Person currentPerson = startingPerson;
for (int i = 2; i <= 100; i++) {
currentPerson.setNext(new Person(i));
currentPerson = currentPerson.getNext();
}
currentPerson.setNext(startingPerson);
// Loop around until a single person is left.
currentPerson = startingPerson;
while (currentPerson != currentPerson.getNext()) {
currentPerson.killNext();
currentPerson = currentPerson.getNext();
}
System.out.println("Surviving person: " + currentPerson.getId());
}
Output:
Surviving person: 73
I have been working on something the past few days that seems to be working as intended, however I am looking for ways to improve it. I have a set of n items, and I need to put together groups of these items that MUST meet ALL of the following requirements:
2 items from Category A
2 items from Category B
2 items from Category C
2 Items from Category D
1 item from Category E
I am currently using the following recursive method to put my groups together and the isValid() method is being used to determine if the group meets the criteria.
void getGroups(String[] arr, int len, int startPosition, String[] result) {
if(len == 0) {
Group group = new Group(Arrays.asList(result));
if(group.isValid()) {
validGroups.add(group);
group.printGroup();
}
return;
}
for(int i = startPosition; i <= arr.length - len; i++) {
result[result.length - len] = arr[i];
getGroups(arr, len - 1, i + 1, result);
}
}
I am able to see valid results get printed as the program runs, however the original size of items that I am working with can be well over 100 items. This means there is a very large number of total possible groups that will be iterated through and a lot of times the program never actually completes.
I know that there are currently a bunch of wasted iterations, for example if at some point I detect a group is invalid because it has 3 items from Category A, I should be able to move on. I am not sure if my current method with a few tweaks is the best way to go about this, or if I should separate the items into their respective groups first, and then from their put only valid combinations together. Any help would be appreciated. Thanks.
EDIT: I tried to make the method a bit more simpler than my actual method. My actual method takes in an array of Objects that I've created that contain their value along with their category. I guess for the example we can assume that each category is represented by a list of Strings that it contains. The method can be called like:
String[] items = {"test1", "test2", "test3", "test4", "test5", "test6", "test7",
"test8", "test9", "test10", "test11", "test12", "test13",
"test14", "test15", "test16", "test17", "test18"};
getGroups(items, 9, 0, new String[9]);
EDIT2:
List<String> catA = new ArrayList<String>();
catA.add("test1");
catA.add("test2");
catA.add("test3");
catA.add("test4");
List<String> catB = new ArrayList<String>();
catB.add("test5");
catB.add("test6");
catB.add("test7");
catB.add("test8");
List<String> catC = new ArrayList<String>();
catC.add("test9");
catC.add("test10");
catC.add("test11");
catC.add("test12");
List<String> catS = new ArrayList<String>();
catD.add("test13");
catD.add("test14");
catD.add("test15");
catD.add("test16");
List<String> catE = new ArrayList<String>();
catE.add("test17");
catE.add("test18");
Output:
{"test1", "test2", "test5", "test6", "test9", "test10", "test13", "test14", "test17"}
{"test1", "test2", "test5", "test6", "test9", "test10", "test13", "test14", "test18"}
{"test1", "test2", "test5", "test6", "test9", "test10", "test13", "test16", "test17"}
{"test1", "test2", "test5", "test6", "test9", "test10", "test13", "test15", "test17"}
{"test1", "test2", "test5", "test6", "test9", "test10", "test14", "test15", "test17"}
etc...
This seems to work.
I use a BitPattern iterator I wrote a while ago that walks all n-bit numbers containing just k set bits and uses that to select from your categories.
Note that much of this code is building the test data to reflect your requirements.
I hold a List of Iterables which are the BitPatterns. A list of Iterators which are the currently in-use Iterators from the BitPatterns (they must be renewed every time they complete) and a List of BigIntgers that are the current values to explode into selections from the data.
public class Test {
enum Category {
A(2), B(2), C(2), D(2), E(1);
public final int required;
Category(int required) {
this.required = required;
}
}
private static final Category[] categories = Category.values();
static class Categorised {
final String name;
final Category category;
Categorised(String name, Category category) {
this.name = name;
this.category = category;
}
#Override
public String toString() {
return category.name() + ":" + name;
}
}
static final List<Categorised> data = new ArrayList<>();
static {
data.add(new Categorised("A-1", Category.A));
data.add(new Categorised("A-2", Category.A));
data.add(new Categorised("A-3", Category.A));
data.add(new Categorised("B-1", Category.B));
data.add(new Categorised("B-2", Category.B));
data.add(new Categorised("B-3", Category.B));
data.add(new Categorised("C-1", Category.C));
data.add(new Categorised("C-2", Category.C));
data.add(new Categorised("C-3", Category.C));
data.add(new Categorised("D-1", Category.D));
data.add(new Categorised("D-2", Category.D));
data.add(new Categorised("D-3", Category.D));
data.add(new Categorised("E-1", Category.E));
data.add(new Categorised("E-2", Category.E));
data.add(new Categorised("E-3", Category.E));
}
// Categorise the data.
private Map<Category, List<Categorised>> categorise(List<Categorised> data) {
Map<Category, List<Categorised>> categorised = new EnumMap<>(Category.class);
for (Categorised d : data) {
List<Categorised> existing = categorised.get(d.category);
if (existing == null) {
existing = new ArrayList<>();
categorised.put(d.category, existing);
}
existing.add(d);
}
return categorised;
}
public void test() {
// Categorise the data.
Map<Category, List<Categorised>> categorised = categorise(data);
// Build my lists.
// A source of Iteratprs.
List<BitPattern> is = new ArrayList<>(categories.length);
// The Iterators.
List<Iterator<BigInteger>> its = new ArrayList<>(categories.length);
// The current it patterns to use to select.
List<BigInteger> next = new ArrayList<>(categories.length);
for (Category c : categories) {
int k = c.required;
List<Categorised> from = categorised.get(c);
// ToDo - Make sure there are enough.
int n = from.size();
// Make my iterable.
BitPattern p = new BitPattern(k, n);
is.add(p);
// Gather an Iterator.
Iterator<BigInteger> it = p.iterator();
// Store it.
its.add(it);
// Prime it.
next.add(it.next());
}
// Walk the lists.
boolean stepped;
do {
// Interpret the current numbers.
List<Categorised> candidates = new ArrayList<>();
for ( int c = 0; c < categories.length; c++ ) {
BigInteger b = next.get(c);
List<Categorised> category = categorised.get(categories[c]);
// Step through the bits in the number.
BitSet bs = BitSet.valueOf(b.toByteArray());
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
// Pull those entries from the categorised list.
candidates.add(category.get(i));
}
}
// Print it for now.
System.out.println(candidates);
// Step again.
stepped = step(is, its, next);
} while (stepped);
}
// Take one step.
private boolean step(List<BitPattern> is, List<Iterator<BigInteger>> its, List<BigInteger> next) {
boolean stepped = false;
// Step each one until we make one successful step.
for (int i = 0; i < is.size() && !stepped; i++) {
Iterator<BigInteger> it = its.get(i);
if (it.hasNext()) {
// Done here!
stepped = true;
} else {
// Exhausted - Reset it.
its.set(i, it = is.get(i).iterator());
}
// Pull that one.
next.set(i, it.next());
}
return stepped;
}
public static void main(String args[]) {
new Test().test();
}
}
This is the BitPattern iterator.
/**
* Iterates all bit patterns containing the specified number of bits.
*
* See "Compute the lexicographically next bit permutation"
* http://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
*
* #author OldCurmudgeon
*/
public class BitPattern implements Iterable<BigInteger> {
// Useful stuff.
private static final BigInteger ONE = BigInteger.ONE;
private static final BigInteger TWO = ONE.add(ONE);
// How many bits to work with.
private final int bits;
// Value to stop at. 2^max_bits.
private final BigInteger stop;
// Should we invert the output.
private final boolean not;
// All patterns of that many bits up to the specified number of bits - invberting if required.
public BitPattern(int bits, int max, boolean not) {
this.bits = bits;
this.stop = TWO.pow(max);
this.not = not;
}
// All patterns of that many bits up to the specified number of bits.
public BitPattern(int bits, int max) {
this(bits, max, false);
}
#Override
public Iterator<BigInteger> iterator() {
return new BitPatternIterator();
}
/*
* From the link:
*
* Suppose we have a pattern of N bits set to 1 in an integer and
* we want the next permutation of N 1 bits in a lexicographical sense.
*
* For example, if N is 3 and the bit pattern is 00010011, the next patterns would be
* 00010101, 00010110, 00011001,
* 00011010, 00011100, 00100011,
* and so forth.
*
* The following is a fast way to compute the next permutation.
*/
private class BitPatternIterator implements Iterator<BigInteger> {
// Next to deliver - initially 2^n - 1
BigInteger next = TWO.pow(bits).subtract(ONE);
// The last one we delivered.
BigInteger last;
#Override
public boolean hasNext() {
if (next == null) {
// Next one!
// t gets v's least significant 0 bits set to 1
// unsigned int t = v | (v - 1);
BigInteger t = last.or(last.subtract(BigInteger.ONE));
// Silly optimisation.
BigInteger notT = t.not();
// Next set to 1 the most significant bit to change,
// set to 0 the least significant ones, and add the necessary 1 bits.
// w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
// The __builtin_ctz(v) GNU C compiler intrinsic for x86 CPUs returns the number of trailing zeros.
next = t.add(ONE).or(notT.and(notT.negate()).subtract(ONE).shiftRight(last.getLowestSetBit() + 1));
if (next.compareTo(stop) >= 0) {
// Dont go there.
next = null;
}
}
return next != null;
}
#Override
public BigInteger next() {
last = hasNext() ? next : null;
next = null;
return not ? last.not(): last;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
#Override
public String toString () {
return next != null ? next.toString(2) : last != null ? last.toString(2): "";
}
}
}
I will not write code but will list a possible approach. I say possible because it will be running and storing all data in memory and is not the best in regard to algorithms. yet, it is an approach where you don't need to eliminate invalid options. I will use an example in order to make things more clear.
suppose you have categories A,B,C. Where K=2 for A,B and K=1 for C.
you also have the input items A1,B1,B2,A2,C1,A3
1- go over the items and divide them according to their category. so you prepare an array/list for each category that has all the items that belong to it.
so now you have arrays:
Category A = [A1,A2,A3] , Category B = [B1,B2] and Category C=[C1]
2- now after preparing the lists, prepare the various legal groups that you can have for picking K items from N items found in that list . here is a link that might help in doing that efficiently: How to iteratively generate k elements subsets from a set of size n in java?
now you have:
first group belonging to category A:
[A1,A2] , [A1,A3], [A2,A3] (3 elements)
second group belonging to category B:
[B1,B2] (1 element)
third group belonging to category C:
[C1] (1 element)
3- now, if you treat each such group as an item, the question transforms to how many different ways are there for picking exactly one element from each group. and that is supposed to be easier to program recursively and will not require eliminating options. and if the number of categories is constant, it will be nested loops over the sets of groups in second point above.
EDIT
the approach works well in eliminating the need to validate bad combinations.
yet, there will still be a problem in regard of time. Here is the code that I made to demonstrate. it makes a list of 100 items. then it does the steps mentioned.
Note that I commented out the code that prints the groups.
The calculation is very fast up to that point. I have added code that prints how many legal choices can be made from each group.
package tester;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
*
* #author
*/
public class Tester {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//generate 100 random items belonging to categories
Random rand=new Random();
List<Item> items=new ArrayList<>();
int a=1,b=1,c=1,d=1,e=1;
for (int i=0;i<100;i++){
int randomNumber=rand.nextInt(5)+1;
CATEGORY_TYPE categoryType=null;
int num=0;
switch (randomNumber) {
case 1:
categoryType=CATEGORY_TYPE.A;
num=a++;
break;
case 2:
categoryType=CATEGORY_TYPE.B;
num=b++;
break;
case 3:
categoryType=CATEGORY_TYPE.C;
num=c++;
break;
case 4:
categoryType=CATEGORY_TYPE.D;
num=d++;
break;
case 5:
categoryType=CATEGORY_TYPE.E;
num=e++;
break;
}
String dummyData="Item "+categoryType.toString()+num;
Item item=new Item(dummyData,categoryType);
items.add(item);
}
//arrange the items in lists by category
List<Item> categoryAItemsList=new ArrayList<>();
List<Item> categoryBItemsList=new ArrayList<>();
List<Item> categoryCItemsList=new ArrayList<>();
List<Item> categoryDItemsList=new ArrayList<>();
List<Item> categoryEItemsList=new ArrayList<>();
for (Item item:items){
if (item.getCategoryType()==CATEGORY_TYPE.A)
categoryAItemsList.add(item);
else if (item.getCategoryType()==CATEGORY_TYPE.B)
categoryBItemsList.add(item);
else if (item.getCategoryType()==CATEGORY_TYPE.C)
categoryCItemsList.add(item);
else if (item.getCategoryType()==CATEGORY_TYPE.D)
categoryDItemsList.add(item);
else if (item.getCategoryType()==CATEGORY_TYPE.E)
categoryEItemsList.add(item);
}
//now we want to construct lists of possible groups of choosing from each category
List<Item[]> subsetStoringListA=new ArrayList<>();
List<Item[]> subsetStoringListB=new ArrayList<>();
List<Item[]> subsetStoringListC=new ArrayList<>();
List<Item[]> subsetStoringListD=new ArrayList<>();
List<Item[]> subsetStoringListE=new ArrayList<>();
processSubsets(categoryAItemsList.toArray(new Item[0]),2,subsetStoringListA);
processSubsets(categoryBItemsList.toArray(new Item[0]),2,subsetStoringListB);
processSubsets(categoryCItemsList.toArray(new Item[0]),2,subsetStoringListC);
processSubsets(categoryDItemsList.toArray(new Item[0]),2,subsetStoringListD);
processSubsets(categoryEItemsList.toArray(new Item[0]),1,subsetStoringListE);
System.out.println(" A groups number: "+subsetStoringListA.size());
System.out.println(" B groups number: "+subsetStoringListB.size());
System.out.println(" C groups number: "+subsetStoringListC.size());
System.out.println(" D groups number: "+subsetStoringListD.size());
System.out.println(" E groups number: "+subsetStoringListE.size());
//now we just print all possible combinations of picking a single group from each list.
//the group is an array with valid choices
// for (Item[] subsetA:subsetStoringListA){
// for (Item[] subsetB:subsetStoringListB){
// for (Item[] subsetC:subsetStoringListC){
// for (Item[] subsetD:subsetStoringListD){
// for (Item[] subsetE:subsetStoringListE){
// print(subsetA);
// print(subsetB);
// print(subsetC);
// print(subsetD);
// print(subsetE);
// System.out.println("\n");
// }
//
// }
// }
// }
// }
}
static void print(Item[] arr){
for (Item item:arr)
System.out.print(item.getDumyData()+" ");
}
static void processSubsets(Item[] set, int k,List<Item[]> subsetStoringList) {
Item[] subset = new Item[k];
processLargerSubsets(set, subset, 0, 0,subsetStoringList);
}
static void processLargerSubsets(Item[] set, Item[] subset, int subsetSize, int nextIndex,List<Item[]> subsetStoringList) {
if (subsetSize == subset.length) { //here we have a subset we need to store a copy from it
subsetStoringList.add(Arrays.copyOf(subset, subset.length));
} else {
for (int j = nextIndex; j < set.length; j++) {
subset[subsetSize] = set[j];
processLargerSubsets(set, subset, subsetSize + 1, j + 1,subsetStoringList);
}
}
}
public static enum CATEGORY_TYPE {A,B,C,D,E}
private static class Item{
private CATEGORY_TYPE categoryType;
private String dumyData;
public Item(String dumyData,CATEGORY_TYPE categoryType) {
this.dumyData = dumyData; //maybe bad name but i mean the object can have many other fields etc
this.categoryType = categoryType;
}
/**
* #return the categoryType
*/
public CATEGORY_TYPE getCategoryType() {
return categoryType;
}
/**
* #return the dumyData
*/
public String getDumyData() {
return dumyData;
}
}
}
in a specific run, it gave the following:
A groups number: 210
B groups number: 153
C groups number: 210
D groups number: 210
E groups number: 19
that means , if we had to print all possible choices of a single element (and here an elemnt is an array containing k choices from a category) from each of these, you will have : 210*153*210*210*19 = 26,921,727,000
now listing/printing over 26 billion variations will take time no matter what and I don't see how it will be minimized.
try setting the total items to 20 and uncomment the printing code to see that everything is working correctly. And see if you really need to list the possible combinations. please remember that every combination here is legal and there are no wasted iterations in all the parts of the code.
one final note: I did not treat edge cases like when there are no items in a category to complete K. that you can easily put in the code according to the desired behaviour in that case.
So this seems to be a constraint satisfaction problem. So maybe try backtracking?
I believe the following works, but plug in your own data to guaranteee.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Launch {
public static void main(String[] args) {
// Formulate the constraints.
int[] constraints = { 2, 1, 0, 1 };
// Create all the items.
List<boolean[]> items = new ArrayList<boolean[]>();
boolean[] i1 = { true, false, true, false };
boolean[] i2 = { true, false, false, false };
boolean[] i3 = { false, true, false, true };
boolean[] i4 = { false, false, false, true };
items.add(i1);
items.add(i2);
items.add(i3);
items.add(i4);
// Solve!
backtrack(constraints, items);
}
/**
* Recursively generate possible solutions but backtrack as soon as the constraints fail.
*/
private static void backtrack(int[] constraints, List<boolean[]> items) {
// We start with no items belonging to any categories.
List<List<boolean[]>> memberships = new ArrayList<List<boolean[]>>();
for (int i = 0; i < constraints.length; i++) {
memberships.add(new ArrayList<boolean[]>());
}
backtrack(constraints, items, memberships);
}
/**
* Recursively generate possible solutions but backtrack as soon as the constraints fail.
*/
private static void backtrack(int[] constraints, List<boolean[]> items,
List<List<boolean[]>> memberships) {
if (items.isEmpty() && !acceptable(constraints, memberships)) {
return;
} else if (acceptable(constraints, memberships)) {
display(memberships);
} else {
for (boolean[] item : items) {
int catIdx = 0;
for (boolean belongs : item) {
if (belongs) {
// The item and category were chosen so let's update
// memberships.
List<List<boolean[]>> newMemberships = new ArrayList<List<boolean[]>>();
for (List<boolean[]> old : memberships) {
newMemberships.add(new ArrayList<boolean[]>(old));
}
newMemberships.get(catIdx).add(item);
// We've placed the item so let's remove it from the
// possibilities.
List<boolean[]> newItems = new ArrayList<boolean[]>(
items);
newItems.remove(item);
// Now solve the sub-problem.
backtrack(constraints, newItems, newMemberships);
}
catIdx++;
}
}
}
}
/**
* A nice way to display the membership tables.
*/
private static void display(List<List<boolean[]>> memberships) {
System.out.println("---");
for (List<boolean[]> category : memberships) {
for (boolean[] item : category) {
System.out.print(Arrays.toString(item) + " ");
}
System.out.println();
}
}
/**
* Returns whether or not a list of memberships are accepted by the
* constraints.
*
* #param constraints
* - The number of items required per category.
* #param memberships
* - The current items per category.
*/
private static boolean acceptable(int[] constraints,
List<List<boolean[]>> memberships) {
boolean acceptable = memberships.size() == constraints.length;
for (int i = 0; i < memberships.size(); i++) {
acceptable = acceptable
&& constraints[i] == memberships.get(i).size();
}
return acceptable;
}
}
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
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.