ArrayList in reverse order - java

I need to start with the first occurence of the first element argument and end with the next occurence of the second argument, putting them in reverse order.
I.e.:
ArrayList<String> food
tomato cheese chips fruit pie butter tea buns
and the two arguments are chips and buns
the new ArrayList should be
buns tea butter pie fruit chips
this is what I've got, but when printed the arraylist is empty
public static void main (String[] args){
ArrayList<String> food = new ArrayList<String>();
food.add(new String("tomato"));
food.add(new String("cheese"));
food.add(new String("chips"));
food.add(new String("fruit"));
food.add(new String("pie"));
food.add(new String("butter"));
food.add(new String("tea"));
food.add(new String("buns"));
ArrayList<String> f1 = reverseOrder(food,"chips","buns");
}
public static ArrayList<String> reverseOrder(ArrayList<String> a, String w1, String w2){
ArrayList<String> food = new ArrayList<String>();
int startingPos = 0;
int endingPos = 0;
boolean startAdding = false;
for(int i=0; i<a.size(); i++){
String n = a.get(i);
if(n.equals(w1)){
endingPos = i;
}
if(n.equals(w2)){
startingPos = i;
}
}
for(int j = startingPos; j<=endingPos; j--){
String p = a.get(j);
food.add(p);
}
System.out.print(food);
return food;
}

The problem you are trying to solve is really two. First, you need to identify the range (indices) that you care about. Then perform the reverse in place.
You have the first part. The 2nd part can be done by repeatedly removing and inserting values, but I would recommend swapping instead.
ArrayList l;
int begin, end;
//reverse everything from "begin" to "end".
while(begin<end){
Object tmp = l.get(begin);
l.set(begin, l.get(end));
l.set(end, tmp);
begin++;end--;
}
You should also know that Java Collections already gives you easy ways to reverse a list.
Collections.reverse(list);
Also, if you need different lists and not modify the original as you did, you can grab a sublist like this.
list.subList(fromIndex, toIndex)
With this, you can easily perform your task with a combination of the above.

You can use indexOf and lastIndexOf to get the proper positions of the elements.
Those methods will return -1 if the element cannot be found, though, so just be aware of that.
public static void main(String[] args) throws Exception {
List<String> food = Arrays.asList("tomato", "cheese", "chips", "fruit", "pie", "butter", "tea", "buns");
ArrayList<String> lst = reverseOrder(food, "chips", "buns");
System.out.println(lst);
}
private static ArrayList<String> reverseOrder(List<String> food, String start, String end) throws Exception {
int startIndex = food.indexOf(start);
if (startIndex < 0) {
throw new Exception(start + " not found");
}
int endIndex = food.lastIndexOf(end);
if (endIndex < 0) {
throw new Exception(end + " not found");
}
ArrayList<String> lst = new ArrayList<>();
while (endIndex >= startIndex) {
lst.add(food.get(endIndex--));
}
return lst;
}
Output [buns, tea, butter, pie, fruit, chips]

This part of the code is wrong:
for(int j = startingPos; j<=endingPos; j--){
String p = a.get(j);
food.add(p);
}
Why? Some examples:
Imagine that you pass these arguments ("tomato", "cheese") => the starting position will be 1 and the ending position will be 0. In the validation of your loop you have "starting with j=1 do the loop while j<=0" meaning that it will never enter in the cycle
Imagine that you pass these arguments ("cheese", "tomato") => the starting position will be 0 and the ending position will be 1. In the validation of your loop you have "starting with j=0 do the loop while j<=1 and in each iteration reduce 1 to j" meaning that after the first iteration j=-1 and you will have an an index out of bounds exception
Here's a code, based on yours (for your better understanding), that will give you the result that you want:
//this code is case sensitive
public ArrayList<String> reverseOrder(ArrayList<String> food, String w1, String w2) {
String startingEl = null;
String endingEl = null;
for(int i=0; i<food.size(); i++){
String n = food.get(i);
//verify if it's equal and if it's really the first occurrence
if(n.equals(w1) && endingEl==null){
endingEl = n;
}
//verify if it's equal and if it's really the first occurrence
if(n.equals(w2) && startingEl==null){
startingEl = n;
}
//if both are found, save some time by interrupting the loop
if(startingEl!=null && endingEl!=null) break;
}
//Protect here your code in case of the first or last elements is not found
ArrayList<String> food_reversed = new ArrayList<String>();
food_reversed.add(0, startingEl);
for(int j = (food.size()-1); j>=0; j--){
String p = food.get(j);
if(p==startingEl || p==endingEl) continue;
food_reversed.add(p);
}
food_reversed.add(endingEl);
System.out.println(food_reversed);
return food_reversed;
}
If I understood correctly the challenge, here's a different example of code to solve your problem:
//this code is case sensitive, is not prepared for repeated string elements
//and is not prepared if both arguments are exactly the same string
//is not prepared in cases that the any of the string arguments doesn't exist in the food array
//this code doesn't insert the same element reference on first and last element
//This code is not the perfect solution cause as you see it has a lot of ails, but it's probably a good start for your to learn more about the subject
import java.util.ArrayList;
import java.util.Collections;
public class QuestionOrderChallenge {
ArrayList<String> food = new ArrayList<String>();
public QuestionOrderChallenge() {
food.add(new String("tomato"));
food.add(new String("cheese"));
food.add(new String("chips"));
food.add(new String("fruit"));
food.add(new String("pie"));
food.add(new String("butter"));
food.add(new String("tea"));
food.add(new String("buns"));
ArrayList<String> a1 = reverseOrder(food,"chips","buns");
ArrayList<String> a2 = reverseOrder(food,"pie","tea");
ArrayList<String> a3 = reverseOrder(food,"tomato","cheese");
}
public ArrayList<String> reverseOrder(ArrayList<String> food, String last, String first) {
ArrayList<String> reversed_food = new ArrayList<String>(food);
reversed_food.remove(first);
reversed_food.remove(last);
Collections.reverse(reversed_food);
reversed_food.add(0, first);
reversed_food.add(last);
System.out.println("Array ordered according to challenge: " + reversed_food);
return reversed_food;
}
public static void main(String[] args) {
new QuestionOrderChallenge();
}
}
If you want to have the same base challenge but then order Alphabetically, here's the code:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class AlphabeticOrderChallenge {
ArrayList<String> food = new ArrayList<String>();
public AlphabeticOrderChallenge() {
food.add(new String("tomato"));
food.add(new String("cheese"));
food.add(new String("chips"));
food.add(new String("fruit"));
food.add(new String("pie"));
food.add(new String("butter"));
food.add(new String("tea"));
food.add(new String("buns"));
ArrayList<String> f1 = reverseOrder(food,"chips","buns");
System.out.println("Array ordered according to challenge: " + f1);
}
public ArrayList<String> reverseOrder(ArrayList<String> food, String end, String begin) {
Collections.sort(food, new ComparatorChallenge(end, begin));
return food;
}
private class ComparatorChallenge implements Comparator {
String endarg;
String beginarg;
public ComparatorChallenge(String beginarg, String endarg) {
this.beginarg = beginarg.toUpperCase();
this.endarg = endarg.toUpperCase();
}
#Override
public int compare(Object arg0, Object arg1) {
String a = ((String)arg0).toUpperCase();
String b = ((String)arg1).toUpperCase();
if(a.compareTo(endarg)==0 || b.compareTo(beginarg)==0) return -1;
if(b.compareTo(endarg)==0 || a.compareTo(beginarg)==0) return 1;
return b.compareTo(a);
}
}
public static void main(String[] args) {
new AlphabeticOrderChallenge();
}
}

The problem has two parts. First we need to find the sublist that satisfies the condition. Once we have the sublist, we can use Collections.reverse(List<?> list) to reverse it.
First, find the sublist between two elements, inclusive. The main idea is to identify the indices of these two elements using indexOf, then call subList on them. But we need to keep in mind the indices might be in a different order than we thought.
private static <T> List<T> inclusiveSublist(List<T> src, T from, T to) {
int start = src.indexOf(from), stop = src.indexOf(to);
if (start != -1 && stop != -1) {
// Successfully located both! But they could be in the "wrong" order
if (start <= stop)
// Element from could appear before to in the list (Plus one to include the second element)
return src.subList(start, 1 + stop);
else // Or the other way around
return src.sublist(stop, 1 + start);
}
// Return empty list if we cannot find both elements
return Collections.emptyList();
}
Now all we need is to reverse the result of inclusiveSublist:
public static <T> List<T> inclusiveReverseSublist(List<T> src, T from, T to) {
List<T> l = inclusiveSublist(src, from, to);
Collections.reverse(l);
return l;
}
And the test:
public static void main(String [] args) {
List<String> src = new ArrayList<>();
src.addAll(Arrays.asList("tomato cheese chips fruit pie butter tea buns".split("\\s")));
System.out.println(src);
System.out.println(inclusiveReverseSublist(src, "fruit", "buns"));
System.out.println(inclusiveReverseSublist(src, "cheese", "tomato"));
}
About subList()
From the Java API doc, subList
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.
So the above code will actually modify the original list, and moving the System.out.println(src); to the bottom will confirm this.

Related

Java: How to create a sorted string ArrayList based on Custom object ArrayList without using Sort()

I have a class called Word in which each instance has String, ArrayList<Character>, and a double. Let's say there are 3 instances of this class. I would like to create a new ArrayList<String> in which all 3 word strings are contained. However, the order of the Strings must go from high to low of the doubles from their original instances. The major stipulation of this project is that the Collections.sort method cannot be used. Please see the code below and let me know if you can think of a way to write this loop (a loop is needed because there is actually +50,000 words):
import java.awt.List;
import java.util.ArrayList;
import java.util.Arrays;
public class WordRecommender {
String fileName;
public WordRecommender(String fileName) {
this.fileName = fileName;
}
public static void main(String[] args) {
ArrayList<Word> objectArray = new ArrayList<Word>();
objectArray.add(new Word("people", null ,0.8));
objectArray.add(new Word("dogs", null ,0.4));
objectArray.add(new Word("cats", null ,0.6));
ArrayList<String> outputArray = new ArrayList<String>();
for (int i = 0; i < finalArray.size(); i++) {
// code here to find the value of each double and place the
// associated strings into output Array from highest to lowest
}
// ideal outputArray order = ["people", "cats", "dogs"]
}
import java.util.ArrayList;
public class Word {
String wordName;
ArrayList<Character> uniqueLetters;
double percent;
public Word(String string, double percent) {
ArrayList<Character> tempArray = new ArrayList<Character>();
for (int i = 0; i < string.length(); i++) {
tempArray.add(string.charAt(i));
}
this.wordName = string;
this.uniqueLetters = tempArray;
this.percent = percent;
}
}
The result you need to achieve can be broken in 2 major steps:
Describing how, giving 2 Words, which of them will be put before the other in the List
Using the comparing method to actually sort your list of Words.
Step 1: How can we decide which word comes first?
Java has an interface called Comparable. The name is pretty self-explanatory. When you implement this interface in your Word class, you are telling Java that instances of this class can be compared against each other.
public class Word implements Comparable<Word>{
When you edit this line in your Word class, your IDE will probably complain about a "missing compareTo() method". The compareTo() method is defined in the Comparable interface and its job is deciding, from 2 instances, which one should be considered "larger" (or in our case, should be put first in the List).
An example of a usage is: "apple".compareTo("banana");. This method call should return a positive number if the first instance ("apple") is "larger", a negative number if the second instance ("banana") is "larger", or zero if both are of the same "value". By the way, the compareTo() method implemented by Strings in Java evaluates instances by alphabetical order.
So let's implement our version of the compareTo() method for our Word class.
#Override
public int compareTo(Word anotherWord) {
if(this.percent > anotherWord.percent) {
return 1;
} else if (this.percent < anotherWord.percent) {
return -1;
} else {
return 0;
}
}
Keep in mind that this implementation returns a positive value if the first instance is greater than the second, and a negative value in the other way around.
Now that we have a way of comparing our Words, we can move on to the sorting part.
Step 2: Sorting algorithms
There are a huge variety of sorting algorithms available on the internet. Some are less efficient, some are easier to implement. You can research some of them here.
For me, the easiest sorting algorithm is called BubbleSort. It is not very efficient, though.
ArrayList<Word> objectArray = new ArrayList<Word>();
objectArray.add(new Word("people", 0.8));
objectArray.add(new Word("dogs", 0.4));
objectArray.add(new Word("cats", 0.6));
for(int i = 0; i < objectArray.size() - 1; i++) {
for(int j = 0; j < objectArray.size() - i - 1; j++) {
// Remember: a compareTo() call returning a negative number
// means that the first instance is smaller than the second.
if(objectArray.get(j).compareTo(objectArray.get(j + 1)) < 0) {
Word auxiliary = objectArray.get(j);
objectArray.set(j, objectArray.get(j + 1));
objectArray.set(j + 1, auxiliary);
}
}
}
These two nested for loops will sort objectArray in descending order of percent.
I implemented a solution that involves a sorting algorithm and usage of java.util.Comparable both.
First, you need to implement Word class with java.util.Comparable so that you can define how to compare Word class in order to determine which one is greater or lower than the other. In this case, it will be the percent field.
public class Word implements Comparable<Word> {
String wordName;
ArrayList<Character> uniqueLetters;
double percent;
public Word(String string, double percent) {
ArrayList<Character> tempArray = new ArrayList<Character>();
for (int i = 0; i < string.length(); i++) {
tempArray.add(string.charAt(i));
}
this.wordName = string;
this.uniqueLetters = tempArray;
this.percent = percent;
}
#Override
public int compareTo(Word o) {
// It is better to delegate to built-in Double compare
// because all we need to compare doubles
return Double.compare(this.percent, o.percent);
}
#Override
public String toString() {
return this.wordName;
}
}
Second, the most important part is to implement a sorting algorithm. It can be challenging to implement them on your own so I suggest study them first.
For my solution it will be a regular implementation of Quick Sort algorithm as follows:
public class QuickSort {
private Word[] array;
public QuickSort(Word... words) {
this.array = words;
}
public Word[] sort(){
this.sort(this.array, 0, this.array.length-1);
return this.array;
}
private void sort(Word[] array, int begin, int end) {
//exit condition
if (begin >= end)
return;
Word pivot = array[end];
int sortIndex = begin;
for (int i = begin; i < end; i++) {
// instead of > we use compareTo to externalize comparison logic
// greater than (>) means we sort in descending order
if (array[i].compareTo(pivot) > 0) {
Word swap = array[sortIndex];
array[sortIndex] = array[i];
array[i] = swap;
sortIndex++;
}
}
//placing pivot to the sort index
Word swap = array[sortIndex];
array[sortIndex] = pivot;
array[end] = swap;
this.sort(array, begin, sortIndex-1);
this.sort(array, sortIndex+1, end);
}
}
Finally, you just use QuickSort helper class to sort your collection of Word and get the sorted output:
public class WordRecommender {
String fileName;
public WordRecommender(String fileName) {
this.fileName = fileName;
}
public static void main(String[] args) {
ArrayList<Word> objectArray = new ArrayList<Word>();
objectArray.add(new Word("people" ,0.8));
objectArray.add(new Word("dogs", 0.4));
objectArray.add(new Word("cats" ,0.6));
QuickSort quickSort = new QuickSort(objectArray.toArray(new Word[]{}));
Word[] sortedWordArray = quickSort.sort();
//output: [people, cats, dogs]
System.out.println(Arrays.asList(sortedWordArray));
}
}

Remove duplicates from an arraylist with strings

I have an arraylist that looks like this:
public static ArrayList<ArrayList<String[]>> x = new ArrayList<>();
I store groups of 2 persons in a pair. For example:
[Person1, Person2]
[Person3, Person4]
The algorithm I use right now still makes duplicates, I've tried out hashmaps and iterating through them with for loop but they just give me back the original list.
This is the code:
package com.company;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class createGroups
{
public static ArrayList<ArrayList<String[]>> x = new ArrayList<>();
public static void main(String[] args){
//Define names
String[] names = {"Person1", "Person2", "Person3", "Person4"};
try
{
//Create combinations. In a try catch because of the saveFile method.
combination(names, 0, 2);
//Print all the pairs in the Arraylist x
printPairs();
} catch (IOException e)
{
e.printStackTrace();
}
}
static void combination(String[] data, int offset, int group_size) throws IOException
{
if(offset >= data.length)
{
//Create new Arraylist called foo
ArrayList<String[]> foo = new ArrayList<>();
//Create a pair of 2 (data.length = 4 / group_size = 2)
for(int i = 0; i < data.length / group_size; i++)
{
//Add the pair to foo.
foo.add(Arrays.copyOfRange(data, 2 * i, 2 * (i + 1)));
}
//Add foo to x
x.add(foo);
//saveFile(foo);
}
for(int i = offset; i < data.length; i++){
for(int j = i + 1; j < data.length; j++){
swap(data, offset, i);
swap(data, offset + 1, j);
combination(data, offset + group_size, group_size);
swap(data, offset + 1, j);
swap(data, offset, i);
}
}
}
public static void printPairs(){
//Print all pairs
for(ArrayList<String[]> q : x){
for(String[] s : q){
System.out.println(Arrays.toString(s));
}
System.out.println("\n");
}
}
private static void swap(String[] data, int a, int b){
//swap the data around.
String t = data[a];
data[a] = data[b];
data[b] = t;
}
}
The output right now is this:
Output
Every group of 4 names is a 'list' of pairs (Not really a list but that's what I call it)
And this is the desired output:
Desired output
But then you can see that the first and the last list of pairs are basically the same how do I change that in my combination method
The question:
How can I change my combination method so that it doesn't create duplicate groups.
And how can I make the list smaller (The desired output) when printing the created lists.
If I wasn't clear enough or if I didn't explain what I want very well, let me know. I'll try to make it clearer.
Create an object similar to this. It takes 4 strings (2 pairs). Puts the strings into array and sorts this array. That means any combination of strings you put in will be converted into one sorted combination, but the object internaly remembers which person is person1, person2, ...
private class TwoPairs {
private final String person1;
private final String person2;
private final String person3;
private final String person4;
private final String[] persons;
TwoPairs(String person1, String person2, String person3, String person4) {
this.person1 = person1;
this.person2 = person2;
this.person3 = person3;
this.person4 = person4;
persons = new String[4];
persons[0] = person1;
persons[1] = person2;
persons[2] = person3;
persons[3] = person4;
// if we sort array of persons it will convert
// any input combination into single (sorted) combination
Arrays.sort(persons); // sort on 4 objects should be fast
// hashCode and equals will be comparing this sorted array
// and ignore the actual order of inputs
}
// compute hashcode from sorted array
#Override
public int hashCode() {
return Arrays.hashCode(persons);
}
// objects with equal persons arrays are considered equal
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
TwoPairs other = (TwoPairs) obj;
if (!Arrays.equals(persons, other.persons)) return false;
return true;
}
// add methods which you might need
// getters for individual persons
// String getPerson1() { return person1; }
// or perhaps pairs of persons
// String[] getPair1() { return new String[] {person1, person2}; }
// add sensible toString method if you need it
}
Your ArrayList x will change like this
ArrayList<TwoPairs> x = new ArrayList<TwoPairs>();
before adding new TwoPairs object into x check if this list already contains this object.
if (!x.contains(twoPairsObject)) {
x.add(twoPairsObject);
}

Remove all the odd numbers in an ArrayList

I already wrote code to remove all the odd numbers in an ArrayList.
import java.util.*;
public class Odd {
public static void main (String [] args) {
ArrayList <Integer> mylist = new ArrayList<>(Arrays.asList(1, 2, 4, 6, 7));
System.out.println(odd(mylist));
}
public static int odd(ArrayList<Integer> list) {
if (list.isEmpty()) { throw new Error(); }
int a = list.get(0);
List<Integer> toRemove = new ArrayList<>();
for (int si : list) {
if (si % 2 != 0) { toRemove.add(si); }
}
list.removeAll(toRemove);
return a;
}
}
But somehow the result is always 1.Can someone point out what is my mistake?Thank you in advance
There are two problems with your code:
(1) You need to return the list object (contains Integers) after the removal of odd numbers
(2) In order to return the list, you need to change the method signature from int to List<Integer> (as return type):
You can refer the below code with comments:
//change the method signature to return List<Integer>
public static List<Integer> odd(ArrayList<Integer> list) {
if (list.isEmpty()) { throw new Error(); }
List<Integer> toRemove = new ArrayList<>();
for (int si : list) {
if (si % 2 != 0) { toRemove.add(si); }
}
list.removeAll(toRemove);
return list;//return list, not int
}
Check this line:
int a=list.get(0);
You are reading only the first element of the list, which is 1, and not iterating through it.
Use either an iterator (for each, for example) or a regular for loop (using the item count from list).
As other people have indicated, the problem is that you're returning this:
int a = list.get(0);
Thus, you'll always get the first item in the list, regardless of what you do to it after you retrieve it.
Getting rid of a completely and just returning list will fix that issue.

Array are not selecting values randomly and split into two arrays

I have got an array list of animals, on click on 'select' button I
would like to randomly select these animals and pass animals into two
arrays (split) called 'teamA and teamB'. Here is my code, but I am getting the same array list always as per screenhot link ? Could someone please
help me to figure out the problem ?
import java.lang.Math;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class RandomExample {
private Random random = new Random();
public static void main(String[] args) {
// 'list' array list contains animals
List<String> list = new ArrayList<String>();
list.add("Tiger");
list.add("Crocodile");
list.add("Cat");
list.add("Dog");
list.add("Elephant");
list.add("Lion");
list.add("Deer");
list.add("Eagle");
RandomExample obj = new RandomExample();
for(int i = 0; i < 10; i++){
obj.getRandomList(list);
List<String> teamA = list.subList(0, 4);
List<String> teamB = list.subList(4, 8);
System.out.println(teamA);
System.out.println(teamB);
}
}
public String getRandomList(List<String> list) {
//0-4
int index = random.nextInt(list.size());
System.out.println("\nIndex :" + index );
return list.get(index);
}
}
As I asked I am not sure why you do not capture the returned string from getRandomList()… I am guessing you are thinking that the list gets returned? Another issue is that when you get a random number from the list you could get the same number. Therefore you will possibly get the same animal on both teams or even the same animal twice or more on the same team. When you put an animal on a team… you need to remove them from the list.
Below I create the two teams. Then setup two loops, one for each team. Using your getRandomList method to get a random animal then remove that animal from the list. After we have both lists, print the results. Hope this helps.
Edit: As per OP request to have a different number of animals for the teams.
Example: use 5 total animals for the teams.
Obviously it’s better to look at the amount of available data before you actually set the team sizes. Example: if you want teamB to have 5 and teamA to have 4, then there better be at least 9 animals in the list. So check the team sizes before you start the loops. If totalAnimalsForTeams is greater than the number of animals in the list or totalAnimalsForTeams is less than two , then we need to indicate this to the user and exit. This approach allows you to use only part of the list if needed. In the implementation below, if the totalAnimalsForTeams is an odd number the second loop will have the extra animal member.
public class Main
{
private static Random random = new Random();
public static void main(String[] args)
{
// 'list' array list contains animals
List<String> list = new ArrayList<String>();
list.add("Tiger");
list.add("Crocodile");
list.add("Cat");
list.add("Dog");
list.add("Elephant");
list.add("Lion");
list.add("Deer");
list.add("Eagle");
list.add("Monster");
list.add("Alien");
list.add("Vombie");
list.add("Politician");
list.add("Donkeye");
List<String> teamA = new ArrayList<String>();
List<String> teamB = new ArrayList<String>();
String newAnimal;
int totalAnimalsForTeams = 7; // <- probably get this value from the user?
if (totalAnimalsForTeams > list.size())
{
System.out.println("There are only " + list.size() + " animals in the list. Requested animals was: " + totalAnimalsForTeams);
return;
}
int firstHalf = totalAnimalsForTeams / 2;
if (firstHalf < 1)
{
System.out.println("Requested " + totalAnimalsForTeams + " animals for teams... not enough to make two teams!");
return;
}
for(int i = 0; i < firstHalf; i++)
{
newAnimal = getRandomList(list);
teamA.add(newAnimal);
list.remove(newAnimal);
}
int secondHalf = totalAnimalsForTeams - firstHalf;
for(int i = 0; i < secondHalf; i++)
{
newAnimal = getRandomList(list);
teamB.add(newAnimal);
list.remove(newAnimal);
}
System.out.println(teamA);
System.out.println(teamB);
}
public static String getRandomList(List<String> list) {
//0-4
if (list.size() > 1)
{
int index = random.nextInt(list.size());
//System.out.println("\nIndex :" + index );
return list.get(index);
}
else
{
return list.get(0);
}
}
}
try this .. it should work ..
import java.lang.Math;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Collections;
import java.util.Random;
public class RandomExample {
private Random random = new Random();
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Tiger");
list.add("Crocodile");
list.add("Cat");
list.add("Dog");
list.add("Elephant");
list.add("Lion");
list.add("Deer");
list.add("Eagle");
RandomExample obj = new RandomExample();
List<String> teamA = list.subList(0,4);
List<String> teamB = list.subList(4,8);
for(int i = 0; i < 10; i++){
obj.getRandomList(list);
teamA = list.subList(0,4);
teamB = list.subList(4,8);
Collections.rotate(teamA, 1);
Collections.rotate(teamB, 1);
System.out.println(teamA);
System.out.println(teamB);
}
}
public String getRandomList(List<String> list) {
//0-4
int index = random.nextInt(list.size());
System.out.println("\nIndex :" + index );
return list.get(index);
}
}
Calling obj.getRandomList(list); returns a String but you donot do anything with it. I know this method is supposed to return a randomly picked item.
To correctly do what you are asking for, You would have to declare a new ArrayList say temp and then assign list to it.
To avoid Repetition of the same object, you need to remove the randomly generated item from the temp ArrayList created.
Then after you are done, remove the temp ArrayList created.
I have made the necessary changes to your main method as per the suggestions I made.
public static void main(String[] args) {
// 'list' array list contains animals
List<String> list = new ArrayList<String>();
list.add("Tiger");
list.add("Crocodile");
list.add("Cat");
list.add("Dog");
list.add("Elephant");
list.add("Lion");
list.add("Deer");
list.add("Eagle");
RandomExample obj = new RandomExample();
List<String> teamA = new ArrayList<String>();
List<String> teamB = new ArrayList<String>();
List<String> temp = list;
String animal;
for(int i = 0; i < 10; i++){
if(temp.isEmpty() == false){
animal = obj.getRandomList(temp);
if(i <= 3){
teamA.add(animal);
}else{
teamB.add(animal);
}
temp.remove(animal);
//System.out.println("temp is "+temp);
}
}
temp.clear();
System.out.println(teamA);
System.out.println(teamB);
}

Find all combinations of an ArrayList of ArrayLists of user defined objects

I have defined a class Note that represents a way to play a certain note (two integers for the string and fret on a string instrument), and a class Chord which has an ArrayList of all the notes in that chord.
For every note that is played there may be multiple ways of playing that note so I have an ArrayList of Notes representing each possible way. In a chord there can be any number of notes so I have an ArrayList of ArrayLists of Notes. From this I want to create an ArrayList of chords with each possible way of playing the chord.
I have defined a constructor Chord(ArrayList<Note> notes)
eg:
Note A has 3 ways of being played and note B 2 ways of being played, from this I would want chords with:
[A1,B1], [A1,B2], [A2 B1], [A2 B2], [A3,B1], [A3,B2].
I have created a method that works under the assumption that there are always 3 notes played but can't think how to expand it to work for an unknown number
public static ArrayList<Chord> allPlayable(ArrayList<ArrayList<Note>> candidates)
{
ArrayList<Chord> allPlayable = new ArrayList<>();
for (int i = 0; i < candidates.get(0).size(); i++)
{
Note n0 = candidates.get(0).get(i);
for (int j = 0; j < candidates.get(1).size(); j++)
{
Note n1 = candidates.get(1).get(j);
for (int k = 0; k < candidates.get(2).size(); k++)
{
Note n2 = candidates.get(1).get(k);
ArrayList<Note> chordNotes = new ArrayList<>();
chordNotes.add(n0);
chordNotes.add(n1);
chordNotes.add(n2);
allPlayable.add(new Chord(chordNotes));
}
}
}
return allPlayable;
}
IT was suggested to me to use recursion - every for loop would be another recursive call and I came up with this answer
public static ArrayList<Chord> allPlayable(ArrayList<ArrayList<Note>> candidates)
{
//this will be the inner ArrayList we are on
ArrayList<Note> current = new ArrayList();
//the list of chords to return
ArrayList<Chord> allPlayable = new ArrayList();
allPlayableRecurse(candidates, 0, current, allPlayable);
return allPlayable;
}
public static void allPlayableRecurse(ArrayList<ArrayList<Note>> candidates, int index, ArrayList<Note> chordNotes, ArrayList<Chord> allPlayable)
{
ArrayList<Note> current = candidates.get(index);
//for each note in the current array list of notes
for (int i = 0; i < current.size(); i++)
{
chordNotes.add(current.get(i));
//there are more notes to add
if (index < candidates.size()-1)
{
//go to the next inner ArrayList
allPlayableRecurse(candidates, index+1, chordNotes, allPlayable);
}
else//we have reached the last note
{
//add the chord to the list
allPlayable.add(new Chord((ArrayList<Note>)chordNotes.clone()));
}
//we will now replace this note
chordNotes.remove(chordNotes.size()-1);
}
}
You could use recursion, for example:
List<List<Note>> combine(List<List<Note>> representations) {
List<Note> options = representations.get(0);
List<List<Note>> tails;
if (representations.size()==1) {
tails = new ArrayList<>();
tails.add(Collections.emptyList());
} else {
tails = combine(representations.subList(1, representations.size()));
}
List<List<Note>> combinations = new ArrayList<>(options.size());
for (Note note : options) {
for (List<Note> tail : tails) {
List<Note> chord = new ArrayList<>();
chord.add(note);
chord.addAll(tail);
combinations.add(chord);
}
}
return combinations;
}
public List<Chord> allPlayable(List<List<Note>> candidates) {
List<List<Note>> combinations = combine(candidates);
List<Chord> chords = new ArrayList<>(combinations.size());
for (List<Note> notes : combinations) chords.add(new Chord(notes));
return chords;
}
It is the old java7 style. It can be done easier with new Java8 functional operations but not sure if it is already your thing if you just started.

Categories