This is what I have so far but I don't now what to do next. The question is as follows (sorry the coding is not all appearing in one box):
Implement a method
public void search (String searchString) { }
to iterate through the notes ArrayList until it finds a note that contains the searchString. It should then print either the item found or the message "String not found". When testing check for a String that is in the list and for one that isn't.
Code:
import java.util.ArrayList;
import java.util.Iterator;
/**
* A class to maintain an arbitrarily long list of notes.
* Notes are numbered for external reference by a human user.
* In this version, note numbers start at 0.
*
* #author David J. Barnes and Michael Kolling.
* #version 2008.03.30
*/
public class Notebook
{
// Storage for an arbitrary number of notes.
private ArrayList<String> notes;
/**
* Perform any initialization that is required for the
* notebook.
*/
public Notebook()
{
notes = new ArrayList<String>();
}
/**
* Store a new note into the notebook.
* #param note The note to be stored.
*/
public void storeNote(String note)
{
notes.add(note);
}
/**
* #return The number of notes currently in the notebook.
*/
public int numberOfNotes()
{
return notes.size();
}
/**
* Show a note.
* #param noteNumber The number of the note to be shown.
*/
public void showNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number, so we can print it.
System.out.println(notes.get(noteNumber));
}
else {
System.out.println("there are fewer items in the notebook than that");
// This is not a valid note number, so do nothing.
}
}
public void removeNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number.
notes.remove(noteNumber);
}
else {
System.out.println("there are fewer items in the notebook than that");
// This is not a valid note number, so do nothing.
}
}
public void multiplesOfFive()
{
int i = 10;
while(i < 100)
{
System.out.println(i);
i = i + 5;
}
}
public int sum(int a, int b)
{
int index = a;
int result = 0;
while(index <= b)
{
result = result + index;
index = index + 1;
}
return result;
}
public int product(int a, int b)
{
int index = a;
int result = 1;
while(index <= b)
{
result = result * index;
index = index + 1;
}
return result;
}
public boolean
isPrime (int n)
{
if (n<=1)return false;
if (n==2) return true;
for (int i = 2;i<=n-1;i++)
{
if (n%i==0)return false;
}
return true;
}
}
two ideas to consider:
When you compose your search method, consider utilizing the contains method in the String class as you iterate (see Kaleb Brasee's post).
ensure that you handle the case when a null is passed in as the search param.
Use one of the new for-each style loops to iterate over the List of notes:
for (String string : notes) {
// This will loop over all the Strings in the notes List.
// Perform your logic here.
}
If the list is not in alphabetical order you need to loop through the list comparing each string against the search string. Once you find a match you can break the loop (using a return true (or the string) would be the easiest way) then outside the loop you can place a return false to signify that a match was not found.
Some methods you will need to use:
ArrayList:
size() - gives you the size of the list so you know when you have reached the end
get( int index ) - returns the item in the list at the specified index
String: equals( String cmp ) - compares 2 strings and returns an int
It would be good to become familiar with the Java API so that you can find methods and their return values.
If the list is in alphabetical order there are more efficient ways to search.
Related
I'm trying to make a PriorityQueue without using the PriorityQueue class provided by Java. For this, I have some given methods that I have to fill in. I'm not sure where I'm making the mistake. It seems that my put and get functions are both wrong, and I'm not sure how to make a new PQ as is given in the code. What I have is the following:
class Element {
private int priority;
private String data;
Element(int priority, String data) {
// Ihr Code
this.priority = priority;
this.data = data;
}
public String getData() {
// Ihr Code
return data;
}
public int getPriority() {
// Ihr Code
return priority;
}
/**
* Return data and priority as string
* Format: Data (Priority)
* e.g: abc (7)
*/
public String toString() {
String str = data + " " + Integer.toString(priority) + ")";
return str;
}
}
public class PriorityQueue {
static final int SIZE = 32;
private Element[] data = null;
// actual number of entries
private int len = 0;
/**
* Creates a new PriorityQueue
*/
public PriorityQueue() {
// Ihr Code
}
/**
* Adds a new element into the queue as long as there is space
* Returns true if element could be added, otherwise false
*/
boolean put(Element element) {
// Ihr Code
if(len == SIZE){
return false;
}else{
int i = len-1;
while (i>=0 && element.getPriority() > data[i].getPriority()){
data[i+1] = data[i];
i--;
}
data[i+1] = element;
len++;
return true;
}
}
/**
* Returns element with the highest priority
* and removes it from the queue. Otherwise returns null
*
*/
Element get() {
// Ihr Code
if (len > 0){
Element x = q[0];
for(int i = 1; i < len; i++){
data[i-1] = data[i];
}
len--;
return x;
}else{
return null;
}
}
/**
* Number of entries
*/
int length() {
// Ihr Code
return len;
}
/**
* Returns contents of the queue as a String
* Format: data1 (priority1), data2 (priority2)
* e.g: abc (7), cde (8)
* Attention: There should be no comma at the end of the String
*/
public String toString() {
// Code
String res = new String();
//res = "(" + data + "," + ")";
if(data.length>0){
StringBuilder sb = new StringBuilder();
for(String s: data){
sb.append(s).append(",");
}
res = sb.deleteCharAt(sb.length()-1).toString;
}
return res;
}
I'm also struggling with the final toString method, to return the queue as a String in the format given, I tried something with a StringBuilder, but this doesn't compile correctly. Alternatively, I could make it with a normal for loop, but again I'm struggling with the exact syntax.
I found resources on the net to build this PQ with heap structures (which I have not had yet) and with a class called Comparator that I failed to understand. Any help would be much appreciated!
I'm mainly struggling with the
public PriorityQueue(){
//what code?}
function. How am I supposed to make a "new" PQ here? Is it supposed to be
PriorityQueue pq = new PriorityQueue();
I'm quite lost! Thanks so much for the help.
Your PriorityQueue constructor has to initialize the array and set the current number of items. That is:
public PriorityQueue() {
data = /* initialize array */
len = 0;
}
You really don't need to keep the elements in the queue in order. Just make your put method add the item as the next element in the array:
public put(Element e) {
if (len == SIZE) {
return false;
}
data[len++] = e;
return true;
}
And then your get method searches the array for the highest-priority item, saves it, replaces that with the item at the end of the array, and returns:
Element get() {
if (len == 0) {
return null;
}
int p = 0;
for (int i = 1; i < len; ++i) {
if (data[i].getPriority() < data[p].getPriority()]) {
p = i;
}
}
Element e = data[p];
// replace with the last item
data[p] = data[len-1];
--len;
return e;
}
So put is an O(1) operation and get is O(n). In your code, both are O(n).
The constructor just needs to initialise the Element[]:
public PriorityQueue() {
data = new Element[SIZE];
}
Now to put(). This method will throw an ArrayOutOfBoundsException in the while loop since you start with i = len - 1 which is the last field of data. Then you access data[i+1] which does not exist, and the exception will be thrown (unless, of course, you initialise it with data = new Element[SIZE + 1]).
Solution: just use i and i-1 instead:
boolean put(Element element) {
if (len == SIZE) {
return false;
} else {
// EDIT: I changed i = len - 1 to i = len since, otherwise,
// the last element would always be overwritten. Now, the
// last element gets copied to the first "free" element and
// so on.
i = len;
while (i > 0 && element.getPriority() > data[i-1].getPriority()) {
data[i] = data[i - 1];
i--;
}
data[i] = element;
len++;
return true;
}
}
EDIT: I said before that the element with the smallest priority would be returned. Actually, it is the greatest.
The get() method behaves as expected (except it should say Element x = data[0] instead of q[0] at the beginning). It returns the first element of the array (the one with the greatest getPriority() value) and moves the rest one index down. If, however, you want the element with the smallest value to be returned, just switch the > to < in the while loop of the put() method:
while (i > 0 && element.getPriority() < data[i-1].getPriority()) {
...
}
Last but not least, the toString() method. It looks mostly right, except for the for-each loop. This one always iterates over the whole array where it should only iterate up to data[len - 1]. So, just use an index instead and you should be fine:
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
sb.append(data[i]).append(",");
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
Alternatively, if you have at least Java 8 installed, you can use streams for this method:
public String toString() {
return Arrays.asList(data).stream()
.limit(len)
.map(Element::toString)
.collect(Collectors.joining(","));
}
This is a program that allows users to add data to a system. This is specifically the invetory class of the program where our task is to convert the object inventory into an object of an array list... I am new to array lists and I would like some assistance figuring this out.
I have tried a few times but have had no luck so far, anything helps!
public class Inventory {
/**
* List of FoodItems that represents our inventory
*/
private FoodItem[] inventory;
/**
* Number of items that a user has entered
*/
private int numItems;
/**
* Default Constructor
*/
public Inventory() {
inventory = new FoodItem[20];
}
/**
* Reads from the Scanner object passed in and fills the data member fields of the class with valid data.
* #param scanner - Scanner to use for input
* #return <code>true</code> if all data members were successfully populated, <code>false</code> otherwise
*/
public boolean addItem(Scanner scanner) {
if(numItems == 20)
{
System.out.println("Inventory full");
return false;
}
boolean valid = false;
FoodItem item = null;
while(!valid)
{
System.out.print("Do you wish to add a fruit(f), vegetable(v) or a preserve(p)? ");
if(scanner.hasNext(Pattern.compile("[fFvVpP]")))
{
String choice = scanner.next();
switch(choice.toLowerCase())
{
case "f":
item = new Fruit();
break;
case "v":
item = new Vegetable();
break;
case "p":
item = new Preserve();
break;
default: // Should not get here.
item = new FoodItem();
break;
}
valid = true;
}
else
{
System.out.println("Invalid entry");
scanner.next();
valid = false;
}
}
if(item.inputCode(scanner))
{
if(alreadyExists(item)<0)
{
if(item.addItem(scanner))
{
inventory[numItems] = item;
numItems++;
return true;
}
return false;
}
else
{
System.out.println("Item code already exists");
return false;
}
}
return true;
}
/**
* Search for a food item and see if it is already stored in the inventory
* #param item - FoodItem to look for
* #return - The index of item if it is found, -1 otherwise
*/
public int alreadyExists(FoodItem item) {
for(int i=0;i<numItems;i++)
{
if(inventory[i].isEqual(item))
return i;
}
return -1;
}
/**
* Update the quanity stored in the food item
* #param scanner - Input device to use
* #param buyOrSell - If we are to add to quantity (<code>true</code>) or remove (<code>false</code>)
* #return
*/
public boolean updateQuantity(Scanner scanner, boolean buyOrSell) {
// If there are no items then we can't update, return
if(numItems == 0)
return false;
FoodItem temp = new FoodItem();
temp.inputCode(scanner);
int index = alreadyExists(temp);
if(index != -1)
{
String buySell = buyOrSell?"buy":"sell";
System.out.print("Enter valid quantity to "+buySell+": ");
if(scanner.hasNextInt())
{
int amount = scanner.nextInt();
if(amount > 0)
{
return inventory[index].updateItem(buyOrSell? amount: amount*-1);
}
else
{
System.out.println("Invalid quantity...");
}
}
else
{
System.out.println("Invalid quantity...");
}
}
return false;
}
#Override
public String toString() {
String returnString = "Inventory:\n";
for(int i=0;i<numItems;i++)
returnString += inventory[i].toString() + "\n";
return returnString;
}
}
I could be misunderstanding the question, but I'm guessing you want to convert Inventory to use an ArrayList, rather than convert it into an ArrayList. Is that correct?
If I understood the question correctly, then the first thing you'll want to do is change the declaration of the inventory field to an ArrayList:
private List<FoodItem> inventory;
Notice that I've declared this as the List interface, rather than the concrete ArrayList implementation. Unless there's a specific feature of the ArrayList implementation you need that's not available in the generic interface, it's usually best to operate at the generic interface level to give yourself the most flexibility.
However, in the constructor, you'll actually instantiate the concrete ArrayList:
public Inventory() {
inventory = new ArrayList<>(20);
}
By switching from a bare array to an ArrayList, you'll find the first advantage of using a Collection, in that you won't need the alreadyExists() method any longer. List, and its super interface, Collection, supports the contains() method.
This:
if(alreadyExists(item)<0)
becomes:
if (!inventory.contains(item))
...and you can remove the alreadyExists() method.
The second advantage is that you'll no longer need to track the number of items in the inventory as a separate field. List already provides this for you.
This:
if(numItems == 20)
becomes:
if (inventory.size() == 20)
..and you can delete the numItems field from your class.
The third advantage is that List/Collection supports a toString() very similar to the implementation you have above.
This:
#Override
public String toString() {
String returnString = "Inventory:\n";
for(int i=0;i<numItems;i++)
returnString += inventory[i].toString() + "\n";
return returnString;
}
becomes:
#Override
public String toString() {
return "Inventory:\n" + inventory.toString();
}
The main difference between your toString() and the toString() provided by List is that you have new lines between each item, and List simply puts commas between each item. If you wanted to keep the new lines, then the looping on List/Collection is a little less cumbersome than arrays:
#Override
public String toString() {
String returnString = "Inventory:\n";
for(FoodItem item : inventory) {
returnString += item.toString() + "\n";
}
return returnString;
}
As my question describes, how to sort the list of type array in java?
This is my ListClass
package AlgorithmAndDataStructures;
public class ListClass<T>{
private static final int MAX_SIZE_OF_LIST = 100;
/**
* This class is having definitions for:-
* Generic List Class Variables
* Constructor for Creating Class Objects
* Method: Adding a Element to the End of List
* Method: Adding a Element at anywhere/ particular place
* Method: Checking List is full or not.
* Method: Checking List is Empty or Not.
* Method: Displaying All Elements of List
* Method: Making New Space for new element addition.
* Method: Sorting a List
*/
// Declaring Array and Variables
private T[] listArray;
private int totalElements;
// Constructor For ListClass
#SuppressWarnings("unchecked")
public ListClass(int listSize) { // entered by the user on runtime
totalElements = 0;
listArray = (T[]) new Object[listSize];
}
// Method For Adding an Element
public boolean addElement(T newElement)
{
boolean isElementAdded = true;
if(!isListFull()) {
listArray[totalElements] = newElement;
totalElements++;
}
else
System.out.println("Sorry, the list is full so, new element can not be added.");
isElementAdded = false;
return isElementAdded;
}
// length = totalElements
// Method for Adding/Inserting Element in any Particular Place
public boolean addSpecific(int newLocation, T newElement) {
boolean elementAdded = true;
if (!isListFull() && (newLocation >= 1) && (newLocation <= totalElements +1) )
{
newSpace(newLocation);
listArray[newLocation -1] = newElement;
totalElements++;
}
else {
elementAdded = false;
}
return elementAdded;
}
// Method for Displaying The List Elements
public void displayListElement() {
if(isListEmpty())
{
System.out.println("Sorry, there is no element in the List!");
}
else
{
for(int elements = 0; elements < totalElements; elements++ ) {
System.out.println((listArray[elements]));
}
System.out.println("All elements has been displayed!");
}
}
// Method for Checking if List is Empty or Number of elements = 0
public boolean isListEmpty() {
return totalElements == 0;
}
// Method for Checking is List is full or not.
public boolean isListFull()
{
return totalElements == MAX_SIZE_OF_LIST;
}
private void newSpace( int newLocation)
{
// assert is a method predefined; indicator for index number
assert (newLocation >=1) && (newLocation <= totalElements +1);
int newIndicator = newLocation -1;
int lastIndicator = totalElements -1;
/**
* For Shifting Elements to Next Indexes
*/
for ( int sign = lastIndicator; sign >= newIndicator; sign--)
listArray[sign +1] = listArray[sign];
}
}
And this is my DriverProgram
package AlgorithmAndDataStructures;
public class DriverListClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
ListClass<Integer> listObjectInt = new ListClass<Integer>(10);
listObjectInt.addElement(12);
listObjectInt.addElement(17);
listObjectInt.addElement(90);
listObjectInt.addElement(53);
listObjectInt.addSpecific(3, 56);
listObjectInt.displayListElement();
// String List
ListClass<String> listObjectStr = new ListClass<String>(4);
listObjectStr.addElement("Suman");
listObjectStr.addElement("Armaan");
listObjectStr.addElement("Atif");
listObjectStr.addElement("Tauseef");
listObjectStr.displayListElement();
}
}
Now, I want a generic sorting method in the ListClass that could sort the list of any type (String, Integer, Double, Float, etc) generated through driver program.
Add sort method to your class
public void sort() {
Arrays.sort(listArray, 0, totalElements);
}
And change class ListClass<T> to class ListClass<T extends Comparable<T>>.
If you want to sort by specific Comparator, add method below.
public void sort(Comparator<T> comparator) {
Arrays.sort(listArray, 0, totalElements, comparator);
}
You need to define a comparison method for the elements of a list. This is usually done by making the elements implement an interface like Comparable:
public class ListClass<T extends Comparble<T>>
I have the following code for displaying the sum of two consecutive element of ArrayList until the element left is one.for example:-
if i entered
1 2 3 4 5
output
3 7 5 //adding the two consecutive last one is as it is
10 5//doing the same thing
15
code
import java.util.*;
import java.lang.Integer;
class Substan{
ArrayList <Integer> list = new ArrayList <Integer> ();
ArrayList <Integer> newList = new ArrayList <Integer> ();// this will be the list containing the next sequence.
int index=0;
int sum=0;
Substan(){
Scanner read = new Scanner(System.in);
String choice;
System.out.println("Enter the elements of the array");
do{
int element = read.nextInt();
list.add(element);
System.out.println("More?");
choice = read.next();
}while(choice.equals("y") || choice.equals("Y"));
}
/* precondition- we have the raw list that user has enterd.
postcondition - we have displayed all the sublists,by adding two consecutives numbers and the last one is having one element.
*/
void sublist(){
while(noofElementsIsNotOneInList()){
index =0;
while(newListIsNotComplete()){
if(nextElementIsThere()){
sum = addTheConsecutive();
}
else{
sum = getLastNumber();
}
storeSumInNewList();
}
displayTheNewList();
System.out.println("");
updateTheLists();
}
displayTheNewList(); //as we have danger of Off By One Bug (OBOB)
System.out.println("");
}
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
private boolean newListIsNotComplete(){
boolean isNotComplete = true;
int listSize = list.size();
int newListSize = newList.size();
if (listSizeIsEven()){
if ( newListSize == listSize/2){
isNotComplete = false;
}
}
else{
if( newListSize == (listSize/2) +1){
isNotComplete = false;
}
}
return isNotComplete;
}
private boolean listSizeIsEven(){
if ( list.size()%2 == 0 ){
return true;
}
else{
return false;
}
}
/*
we are at some index.
returns true if we have an element at (index+1) index.
*/
private boolean nextElementIsThere(){
if ( list.size() == index+1 ){
return false;
}
else{
return true;
}
}
/* precondition-we are at index i
postcondition - we will be at index i+2 and we return sum of elements at index i and i+1.
*/
private int addTheConsecutive(){
int sum = list.get(index)+list.get(index+1);
index += 2;
return sum;
}
/* we are at last element and we have to return that element.
*/
private int getLastNumber(){
return list.get(index);
}
private void storeSumInNewList(){
newList.add(sum);
}
private void displayTheNewList(){
int size = newList.size();
for ( int i=0;i<size;i++){
System.out.print(newList.get(i)+" ");
}
}
/*precondition - we have processed all the elements in the list and added the result in newList.
postcondition - Now my list will be the newList,as we are processing in terms of list and newList reference will have a new object.
*/
private void updateTheLists(){
list = newList;
newList = new ArrayList <Integer>();// changing the newList
}
public static void main(String[] args) {
Substan s = new Substan();
s.sublist();
}
}
So i have done a lot of refinement of my code but having a problem of sharing the local variables with the other methods.for example i have used index instance for storing the index and initially i thought that i will put this as not an instance but a local variable in method sublist() but as it cannot be viewed from other methods which needed to use the index like addTheConsecutive().So considering that i put the index at class level.So is it wright approach that put the variables that are shared at class level rather than looking at only the state of the object initially before coding and stick to that and never change it?
Consider this:
An object can communicate with other(s) only by sharing its attributes. So, if you need an object to read the state of another, the only way it can be done is by giving it "permission" to read the other object attributes.
You have two ways to do that:
Declaring the object attributes public, or
Creating getXXX() methods (makes sense for private attributes)
I personally prefer option two, because the getXXX() method returns the value ("state") of a particular attribute without the risk of being modified. Of course, if you need to modify a private attribute, you should also write a setXXX() method.
Example:
public class MyClass {
private int foo;
private String bar;
/*
* Code
*/
public int getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public void setFoo(int foo) {
this.foo = foo;
}
public void setBar(String bar) {
this.bar = bar;
}
/*
* More code
*/
}
This way all the object attributes are encapsulated, and:
they cannot be read by any other object, unless you specifically call the appropriate getXXX() function, and
cannot be altered by other objects, unless you specifically call the appropriate setXXX() function.
Compare it with the non-abstracted version.
for (int index = 0; index < list.size(); index += 2) {
int sum = list.get(index);
if (index + 1 < list.size() {
sum += list.get(index + 1);
}
newList.add(sum);
}
Now, top-down refining the algorithm using names is a sound methodology, which helps in further creative programming.
As can seen, when abstracting the above again:
while (stillNumbersToProcess()) {
int sum = sumUpto2Numbers();
storeSumInNewList(sum);
}
One may keep many variables like sum as local variables, simplifying state.
One kind of helpful abstraction is the usage of conditions, in a more immediate form:
private boolean listSizeIsEven() {
return list.size() % 2 == 0;
}
private boolean nextElementIsThere() {
return index + 1 < list.size();
}
There's no point in declaring index at Class level since you dont want it to be a member or an instance of that class. Instead make it local to the method and pass it to other methods as argument where you want to access it.
I think you are asking the wrong question.
Your class variables make very little sense, as do many of the methods. This is mostly because:
Your class is doing too much
Your algorithm is a little odd
The class variables that you do have make much more sense passed as method parameters. Some methods need to see them, and some don't.
Your class is also a little odd, in that calling subList twice on the same class will not produce the same answer.
The code is littered with methods I don't quite see the point in, such as:
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
Shouldn't this be:
private boolean noofElementsIsNotOneInList(){
return list.size() == 1;
}
And it makes no sense for it to use some arbitrary List, pass one in so that you know which List you are checking:
private boolean noofElementsIsNotOneInList(final Collection<?> toCheck){
return toCheck.size() == 1;
}
The same logic can be applied to almost all of your methods.
This will remove the instance variables and make your code much more readable.
TL;DR: Using lots of short appropriately named methods: good. Having those methods do things that one wouldn't expect: bad. Having lots of redundant code that makes things very hard to read: bad.
In fact, just to prove a point, the whole class (apart from the logic to read from stdin, which shouldn't be there anyway) can transformed into one short, recursive, method that requires no instance variables at all:
public static int sumPairs(final List<Integer> list) {
if (list.size() == 1)
return list.get(0);
final List<Integer> compacted = new LinkedList<>();
final Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
final int first = iter.next();
if (iter.hasNext()) compacted.add(first + iter.next());
else compacted.add(first);
}
return sumPairs(compacted);
}
Now you could break this method apart into several appropriately named shorter methods, and that would make sense. It's sometimes more helpful to start from the other end. Sketch out the logic of your code and what it's trying to do, then find meaningful fragments to split it into. Possibly after adding unit tests to verify behaviour.
what about doing by Recursion:
public int calculateSum(List<Integer> nums) {
displayList(nums);
if (nums.size() == 1) {
return nums.get(0);
}
List<Integer> interim = new ArrayList<Integer>();
for (int i = 0; i < nums.size(); i = i + 2) {
if (i + 1 < nums.size()) {
interim.add(nums.get(i) + nums.get(i + 1));
} else {
interim.add(nums.get(i));
}
}
return calculateSum(interim);
}
public static void displayList(List<Integer> nums){
System.out.println(nums);
}
Steps:
Run calculate sum until list has 1 element
if list has more than 1 element:
iterate the list by step +2 and sum the element and put into a new List
again call calculate sum
As you may have understood with the title, I need some smart thinking here :)
I have a List<List<Object>> object. If you think of the Object objects as integers, you could see it like this :
{{1,2},{10,20,30},{100}}
I need to get all possible lists containing exactly one element of each list, that is, come up with this :
{{1,10,100},{1,20,100},{1,30,100},{2,10,100},{2,20,100},{2,30,100}}
Of course you don't know at compiling time how much items the lists will contain, so you cannot rely on an overlapping of for loops...
How would you come up with this? Time constraints are not relevant to my problem because the lists will likely contain few elements.
Iterative algorithm.
public class A {
public static List<List<Integer>> combinations(List<List<Integer>> inputList) {
List<List<Integer>> result = new LinkedList<List<Integer>>();
for (Integer i : inputList.get(0)) {
List<Integer> temp = new ArrayList<Integer>(1);
temp.add(i);
result.add(temp);
}
for (int i = 1; i < inputList.size(); i++) {
result = make(result, inputList.get(i));
}
return result;
}
private static List<List<Integer>> make(List<List<Integer>> in, List<Integer> n) {
List<List<Integer>> res = new LinkedList<List<Integer>>();
for (List<Integer> l : in) {
for (Integer i : n) {
List<Integer> cur = new ArrayList<Integer>(l.size() + 1);
cur.addAll(l);
cur.add(i);
res.add(cur);
}
}
return res;
}
public static void main(String[] args) {
List<List<Integer>> inputList = new ArrayList();
inputList.add(new ArrayList<Integer>() {{
add(1);
add(2);
}});
inputList.add(new ArrayList<Integer>() {{
add(10);
add(20);
add(30);
}});
inputList.add(new ArrayList<Integer>() {{
add(100);
}});
System.out.println(combinations(inputList));
}
}
*Notice that this code not for production! You should replace LinkedList with ArrayList with initial size, make checks and so on.
upd usage example provided. there is some code improvement. But it still only draft. I wouldn't recommend you use it in real tasks.
I won't implement it, but here's an idea for a recursive algorithm:
if we are dealing with a list containing a single list of elements (i.e.e.g {{1,2,3}}), then the result is - of course - a list of lists containing one element each (i.e.e.g. {{1},{2},{3}}
if we have more than one list in the list of lists, we do a recursive call of the algorithm. We take all resulting lists from this recursive call and combine each element of the first list of the list of lists with each list from the recursive call.
Here's raw Python code:
def combiner(ll):
if len(ll)==1:
return [[x] for x in ll[0]] # base case
firstlist = ll[0]
result = []
for i in combiner(ll[1:]): # recursive call
for firstelem in firstlist:
result.append([firstelem]+i) # combining lists
return result
Just for completeness, what you are searching is called the Cartesian product of your lists, called such since the size of our result list is the product of the sizes of the individual lists.
Edit: Here is an implementation which works for arbitrary Iterables of Iterables, and creates an Iterable of lists. It creates the elements lazily on iteration, so it works for really big products which don't fit in the memory all at one, too.
package de.fencing_game.paul.examples;
import java.util.*;
/**
* A iterable over the cartesian product of a iterable of iterables
* with some common element type.
*<p>
* The elements of the product are tuples (lists) of elements, one of
* each of the original iterables.
*<p>
* The iterator iterates the elements in lexicographic order, ordered by
* the appearance of their components in their respective iterators.
*<p>
* Since we are iterating the iterables lazily, the iterators should
* act the same each time, otherwise you'll get strange results (but it
* will still be well-defined).
*</p>
*
* Inspired by the question How to get a list of all lists containing exactly one element of each list of a list of lists on Stackoverflow (by Dunaril).
*
* #author Paŭlo Ebermann
*/
public class ProductIterable<X>
implements Iterable<List<X>>
{
private Iterable<? extends Iterable<? extends X>> factors;
public ProductIterable(Iterable<? extends Iterable<? extends X>> factors) {
this.factors = factors;
}
public Iterator<List<X>> iterator() {
return new ProductIterator();
}
private class ProductIterator
implements Iterator<List<X>>
{
/**
* an element of our stack, which contains
* an iterator, the last element returned by
* this iterator, and the Iterable which created
* this iterator.
*/
private class StackElement {
X item;
Iterator<? extends X> iterator;
Iterable<? extends X> factor;
boolean has;
StackElement(Iterable<? extends X> fac) {
this.factor = fac;
newIterator();
}
/**
* checks whether the {#link #step} call can
* get a new item.
*
*/
boolean hasNext() {
return has ||
(has = iterator.hasNext());
}
/**
* steps to the next item.
*/
void step() {
item = iterator.next();
has = false;
}
/**
* creates a new iterator.
*/
void newIterator() {
iterator = factor.iterator();
has = false;
}
/**
* for debugging: a string view of this StackElement.
*/
public String toString() {
return "SE[ i: " + item + ", f: " + factor + "]";
}
}
/**
* our stack of iterators to run through
*/
private Deque<StackElement> stack;
/**
* is our next element already produced (= contained in
* the `item`s of the stack?
*/
private boolean hasNext;
/**
* constructor.
*/
ProductIterator() {
stack = new ArrayDeque<StackElement>();
try {
fillStack();
hasNext = true;
}
catch(NoSuchElementException ex) {
hasNext = false;
}
}
/**
* creates the stack. only called from constructor.
*/
private void fillStack() {
for(Iterable<? extends X> fac : factors) {
StackElement el = new StackElement(fac);
el.step();
stack.push(el);
}
}
/**
* steps the iterator on top of the stack, and maybe the iterators
* below, too.
* #return true if more elements are available.
*/
private boolean stepIterator() {
if(stack.isEmpty())
return false;
StackElement top = stack.peek();
while(!top.hasNext()) {
stack.pop();
if (!stepIterator()) {
return false;
}
top.newIterator();
stack.push(top);
}
top.step();
return true;
}
/**
* returns true if `next` will return a next element.
*/
public boolean hasNext() {
return
hasNext ||
(hasNext = stepIterator());
}
/**
* returns the next element of the cartesian product.
*/
public List<X> next() {
if(!hasNext()) {
throw new NoSuchElementException();
}
hasNext = false;
return makeList();
}
/**
* creates a list from the StackElements in reverse order.
*/
private List<X> makeList() {
List<X> list = new ArrayList<X>(stack.size());
// TODO: more efficient reverse copying
for(StackElement se : stack) {
list.add(0, se.item);
}
return list;
}
/**
* the remove method is not supported,
* the cartesian product is immutable.
*/
public void remove() {
throw new UnsupportedOperationException();
}
} // class ProductIterator
/**
* a test method which creates a list of lists and
* from this the cartesian product.
*/
public static void main(String[] params) {
#SuppressWarnings("unchecked")
List<List<Integer>> factors =
Arrays.asList(Arrays.asList(1,2),
Arrays.asList(10,20,30),
Arrays.asList(100));
Iterable<List<Integer>> product =
new ProductIterable<Integer>(factors);
List<List<Integer>> productList =
new ArrayList<List<Integer>>();
for(List<Integer> pEl : product) {
productList.add(pEl);
System.out.println(pEl);
}
System.out.println(productList);
}
}
One more edit: here is a index-based lazy list implementation.
package de.fencing_game.paul.examples;
import java.util.*;
/**
* The cartesian product of lists, in an (unmodifiable) index-based
* implementation.
*
*<p>
* The elements of the product are tuples (lists) of elements, one from
* each of the base list's element lists.
* These are ordered in lexicographic order, by their appearance in the
* base lists.
*</p>
*<p>
* This class works lazily, creating the elements of the product only
* on demand. It needs no additional memory to the base list.
*</p>
*<p>
* This class works even after changes of the base list or its elements -
* the size of this list changes if any of the factor lists changes size.
* Such changes should not occur during calls to this method, or
* you'll get inconsistent results.
*</p>
* <p>
* The product of the sizes of the component lists should be smaller than
* Integer.MAX_INT, otherwise you'll get strange behaviour.
* </p>
*
*<p>
* Inspired by the question How to get a list of all lists containing exactly one element of each list of a list of lists on Stackoverflow (by Dunaril).
*
* #author Paŭlo Ebermann
*/
public class ProductList<X>
extends AbstractList<List<X>>
{
private List<? extends List<? extends X>> factors;
/**
* create a new product list, based on the given list of factors.
*/
public ProductList(List<? extends List<? extends X>> factors) {
this.factors = factors;
}
/**
* calculates the total size of this list.
* This method takes O(# factors) time.
*/
public int size() {
int product = 1;
for(List<?> l : factors) {
product *= l.size();
}
return product;
}
/**
* returns an element of the product list by index.
*
* This method calls the get method of each list,
* so needs needs O(#factors) time if the individual
* list's get methods are in O(1).
* The space complexity is O(#factors), since we have to store
* the result somewhere.
*
* #return the element at the given index.
* The resulting list is of fixed-length and after return independent
* of this product list. (You may freely modify it like an array.)
*/
public List<X> get(int index) {
if(index < 0)
throw new IndexOutOfBoundsException("index " + index+ " < 0");
// we can't create a generic X[], so we take an Object[]
// here and wrap it later in Arrays.asList().
Object[] array = new Object[factors.size()];
// we iteratively lookup the components, using
// modulo and division to calculate the right
// indexes.
for(int i = factors.size() - 1; i >= 0; i--) {
List<?> subList = factors.get(i);
int subIndex = index % subList.size();
array[i] = subList.get(subIndex);
index = index / subList.size();
}
if(index > 0)
throw new IndexOutOfBoundsException("too large index");
#SuppressWarnings("unchecked")
List<X> list = (List<X>)Arrays.asList(array);
return list;
}
/**
* an optimized indexOf() implementation, runs in
* O(sum n_i) instead of O(prod n_i)
* (if the individual indexOf() calls take O(n_i) time).
*
* Runs in O(1) space.
*/
public int indexOf(Object o)
{
if(!(o instanceof List))
return -1;
List<?> list = (List<?>)o;
if (list.size() != factors.size())
return -1;
int index = 0;
for(int i = 0; i < factors.size(); i++) {
List<?> subList = factors.get(i);
Object candidate = list.get(i);
int subIndex = subList.indexOf(candidate);
if(subIndex < 0)
return -1;
index = index * subList.size() + subIndex;
}
return index;
}
/**
* an optimized lastIndexOf() implementation, runs in
* O(sum n_i) time instead of O(prod n_i) time
* (if the individual indexOf() calls take O(n_i) time).
* Runs in O(1) space.
*/
public int lastIndexOf(Object o)
{
if(!(o instanceof List))
return -1;
List<?> list = (List<?>)o;
if (list.size() != factors.size())
return -1;
int index = 0;
for(int i = 0; i < factors.size(); i++) {
List<?> subList = factors.get(i);
Object candidate = list.get(i);
int subIndex = subList.lastIndexOf(candidate);
if(subIndex < 0)
return -1;
index = index * subList.size() + subIndex;
}
return index;
}
/**
* an optimized contains check, based on {#link #indexOf}.
*/
public boolean contains(Object o) {
return indexOf(o) != -1;
}
/**
* a test method which creates a list of lists and
* shows the cartesian product of this.
*/
public static void main(String[] params) {
#SuppressWarnings("unchecked")
List<List<Integer>> factors =
Arrays.asList(Arrays.asList(1,2),
Arrays.asList(10,20,30, 20),
Arrays.asList(100));
System.out.println("factors: " + factors);
List<List<Integer>> product =
new ProductList<Integer>(factors);
System.out.println("product: " + product);
List<Integer> example = Arrays.asList(2,20,100);
System.out.println("indexOf(" + example +") = " +
product.indexOf(example));
System.out.println("lastIndexOf(" + example +") = " +
product.lastIndexOf(example));
}
}
I added implementations of contains, indexOf and lastIndexOf which are quite better than the original ones from AbstractList (or AbstractCollection) (for bigger factors than in your example, at least). These are not optimized for the sublists, since the sublists are simply taken from AbstractList.
Simple iterative algorithm.
public static List<List<Object>> doStaff(List<List<Object>> objectList) {
List<List<Object>> retList = new ArrayList<List<Object>>();
int[] positions = new int[objectList.size()];
Arrays.fill(positions,0);
int idx = objectList.size() -1;
int size = idx;
boolean cont = idx > -1;
while(cont) {
idx = objectList.size() -1;
while(cont && positions[idx] == objectList.get(idx).size()) {
positions[idx] = 0;
idx--;
if(idx > -1) {
positions[idx] = positions[idx]+ 1;
} else {
cont = false;
}
}
if(cont) {
List<Object> tmp = new ArrayList<Object>(size);
for(int t = 0; t < objectList.size(); t++) {
tmp.add(t, objectList.get(t).get(positions[t]));
//System.out.print(objectList.get(t).get(positions[t])+ " ");
}
retList.add(tmp);
// System.out.println();
positions[size] = positions[size] + 1;
}
}
return retList;
}
If necessary, an explanation, just let me know.
You might use that scala code:
def xproduct (xx: List [List[_]]) : List [List[_]] =
xx match {
case aa :: bb :: Nil =>
aa.map (a => bb.map (b => List (a, b))).flatten
case aa :: bb :: cc =>
xproduct (bb :: cc).map (li => aa.map (a => a :: li)).flatten
case _ => xx
}
Since crossproduct is another name for cartesian product, it's name is xproduct.
Here is a java implementation of phimuemue's Python algorithm.
private static List<List<Item>> getAllPossibleLists(List<List<Item>> itemsLists) {
List<List<Item>> returned = new ArrayList<List<Item>>();
if(itemsLists.size() == 1){
for (Item item : itemsLists.get(0)) {
List<Item> list = new ArrayList<Item>();
list.add(item);
returned.add(list);
}
return returned;
}
List<Item> firstList = itemsLists.get(0);
for (List<Item> possibleList : getAllPossibleLists(itemsLists.subList(1, itemsLists.size()))) {
for(Item firstItem : firstList){
List<Item> addedList = new ArrayList<Item>();
addedList.add(firstItem);
addedList.addAll(possibleList);
returned.add(addedList);
}
}
return returned;
}
Feel free to comment further. Thank you for all your efforts !