We are trying to compile our program, but we keep getting a NoSuchElementException. Anyone that has a clue on why this keeps occurring? Thanks in advance. In the following I will attach both the code where we implement the exception and also the main method.
EDIT - whole code in the following:
import java.util.Iterator;
import edu.princeton.cs.algs4.*;
public class RandomQueue<Item> implements Iterable<Item> {
private Item[] queue;
private int N;
private int size;
// Your code goes here.
public RandomQueue() { // create an empty random queue
N = 0;
size = 2;
queue = (Item[]) new Object[size];
}
public boolean isEmpty() {// is it empty?
if(N == 0) {
return true;
} else {
return false;
}
}
public int size() {// return the number of elements
return size;
}
public void resizeArray() {
if(3/4*size < N) {
size = size*2;
Item[] queueUpdated = (Item[]) new Object[size];
for(int i = 0; i < queue.length; ++i) {
queueUpdated[i] = queue[i];
}
queue = queueUpdated;
} else if (N < 1/4*size) {
size = size/2;
Item[] queueUpdated = (Item[]) new Object[size];
for(int i = 0; i < size-1; ++i) {
queueUpdated[i] = queue[i];
}
queue = queueUpdated;
}
}
public void enqueue(Item item) {// add an item
if(N < queue.length) {
queue[N++] = item;
resizeArray();
}
}
public Item sample(){ // return (but do not remove) a random item
if(isEmpty()) {
throw new RuntimeException("No such elements");
} else {
return queue[StdRandom.uniform(N)];
}
}
public Item dequeue(){ // remove and return a random item
if(isEmpty()) {
throw new RuntimeException("Queue is empty");
} else {
System.out.println(N);
int indexFraArray = StdRandom.uniform(N);
Item i = queue[indexFraArray];
queue[N] = null;
queue[indexFraArray] = queue[N--];
resizeArray();
return i;
}
}
private class RandomQueueIterator<E> implements Iterator<E> {
int i = 0;
public boolean hasNext() {
return i < N;
}
public E next() {
if (!hasNext()) {
throw new java.util.NoSuchElementException(); // line 88
}
i++;
return (E) dequeue();
}
public void remove() {
throw new java.lang.UnsupportedOperationException();
}
}
public Iterator<Item> iterator() { // return an iterator over the items in
random order
return new RandomQueueIterator();
}
// The main method below tests your implementation. Do not change it.
public static void main(String args[]) {
// Build a queue containing the Integers 1,2,...,6:
RandomQueue<Integer> Q = new RandomQueue<Integer>();
for (int i = 1; i < 7; ++i) Q.enqueue(i); // autoboxing! cool!
// Print 30 die rolls to standard output
StdOut.print("Some die rolls: ");
for (int i = 1; i < 30; ++i) StdOut.print(Q.sample() +" ");
StdOut.println();
// Let's be more serious: do they really behave like die rolls?
int[] rolls= new int [10000];
for (int i = 0; i < 10000; ++i)
rolls[i] = Q.sample(); // autounboxing! Also cool!
StdOut.printf("Mean (should be around 3.5): %5.4f\n", StdStats.mean(rolls));
StdOut.printf("Standard deviation (should be around 1.7): %5.4f\n",
StdStats.stddev(rolls));
// Now remove 3 random values
StdOut.printf("Removing %d %d %d\n", Q.dequeue(), Q.dequeue(), Q.dequeue());
// Add 7,8,9
for (int i = 7; i < 10; ++i) Q.enqueue(i);
// Empty the queue in random order
while (!Q.isEmpty()) StdOut.print(Q.dequeue() +" ");
StdOut.println();
// Let's look at the iterator. First, we make a queue of colours:
RandomQueue<String> C= new RandomQueue<String>();
C.enqueue("red"); C.enqueue("blue"); C.enqueue("green");
C.enqueue("yellow");
Iterator<String> I = C.iterator();
Iterator<String> J = C.iterator();
StdOut.print("Two colours from first shuffle: "+I.next()+" "+I.next()+" ");
StdOut.print("\nEntire second shuffle: ");
while (J.hasNext()) StdOut.print(J.next()+" ");
StdOut.println("\nRemaining two colours from first shuffle: "+I.next()+" "+I.next()); // line 142
}
}
I compile in cmd and this is the error I get
the error happens here:
enter image description here
and here:
enter image description here
Your iterator is modifying your collection. This is non-standard at least and seems to confuse yourself.
You are creating two iterators over your queue C, which has 4 elements in it at this time:
Iterator<String> I = C.iterator();
Iterator<String> J = C.iterator();
You ask the former iterator for two elements:
StdOut.print("Two colours from first shuffle: "+I.next()+" "+I.next()+" ");
This removes (dequeues) those two elements through this line:
return (E) dequeue();
Now your queue has 2 elements in it. N is 2.
Your try to remove the remaining 2 elements here:
StdOut.print("\nEntire second shuffle: ");
while (J.hasNext()) StdOut.print(J.next()+" ");
However, after one element has been removed, J.i is 1 and N is 1, so the iterator J considers the queue exhausted and only gives you this one element. There’s one left. N is 1. Yet you try to remove another two elements:
StdOut.println("\nRemaining two colours from first shuffle: "+I.next()+" "+I.next()); // line 142
This is bound to fail. Fortunately it does. next calls hasNext, which in turn compares:
return i < N;
I.i is 2 (since we had previously taken 2 elements from I) and N is 1, so hasNext returns false, which causes next to throw the exception.
The solution is simple and maybe not so simple: Your iterator should not remove any elements from your queue, only return the elements in order.
And the real answer: You should learn to use a debugger. It will be a good investment for you.
Related
Learning about Arrays. I am not able to figure out why a new number is not added to the back of my existing array. I read in two textfiles in file_1.txt are the numbers '1 2 3' and in file_2.txt is the number '91'. Basically without the method of Void addBack() the program does what I expect, however by adding the method it seems not make a new Array. Even when I go over the elements[i] = elements[i-1] it won't print it as a whole. I am expecting to print for the first part
The numbers are: 1 2 3 and the second part The numbers are: 1 2 3 91.
public class ExampleLecture {
IntRow readIntRow(Scanner input) {
IntRow result = new IntRow();
while (input.hasNext()) {
result.add(input.nextInt());
}
return result;
}
IntRow setBack(Scanner input) {
IntRow result = new IntRow();
while(input.hasNext()) {
result.addBack(input.nextInt());
System.out.println("here");
}
return result;
}
void print(IntRow row) {
for (int i = 0; i < row.numberOfElements; i++) {
System.out.printf("%d ", row.elements[i]);
}
System.out.printf("\n");
}
void start() {
Scanner in = UIAuxiliaryMethods.askUserForInput().getScanner();
Scanner in2 =UIAuxiliaryMethods.askUserForInput().getScanner();
IntRow row = readIntRow(in);
IntRow row2 = setBack(in2);
System.out.printf("the numbers are: ");
print (row);
System.out.printf("the new numbers are: ");
print (row2);
}
public static void main(String[] args) {
new ExampleLecture().start();
}
}
package examplelecture;
class IntRow {
static final int MAX_NUMBER_OF_ELEMENTS = 250;
int[] elements;
int numberOfElements;
IntRow() {
elements = new int[MAX_NUMBER_OF_ELEMENTS];
numberOfElements = 0;
}
void add(int number) {
elements[numberOfElements] = number;
numberOfElements += 1;
}
void addBack(int number) {
for (int i = numberOfElements; i>0; i--) {
elements[i] = elements[i-1];
elements[i] = number;
}
}
}
You have 2 successive assignments which write to the same position:
elements[i] = elements[i-1];
elements[i] = number;
The value is alway overwritten with number, so the first statement has no effect.
Also in your addBack method your for cycle:
for (int i = numberOfElements; i>0; i--) {
What happens if numberOfElements is 0?
You call it addBack but it looks like a better name for the method is addFirst. Usually index 0 is considered the front, not the back.
First off, both the readIntRow() and setBack() methods create new IntRow objects row and row2. If you want the result to be appended to the first IntRow object created i.e. to row , you should call:
IntRow row = readIntRow(in);
IntRow row2 = row.setBack(in2);
and setBack() needs to be modified to:
IntRow setBack(Scanner input) {
while(input.hasNext()) {
this.add(input.nextInt());
System.out.println("here");
}
return this;
}
Note that in setBack(), if you are trying to append numbers to the end of the IntRow object, you should call add() instead of addBack() as above. If you are trying to add to the front, you should call addBack() [and it might be better to call it addFront() instead].
Also, in the implementation of addBack(), if you are trying to add to the front of the IntRow object, the element[i] = number operation should take place only once, after the loop. Otherwise all the values in indices <= numberOfElements would be overwritten with number.
void addBack(int number) {
for (int i = numberOfElements; i>0; i--) {
elements[i] = elements[i-1];
}
elements[0] = number;
}
Admittedly it is not entirely clear what you are trying to accomplish. But you may have several problems. The first is as follows:
IntRow setBack(Scanner input) {
IntRow result = new IntRow();
while (input.hasNext()) {
result.addBack(input.nextInt());
System.out.println("here");
}
return result;
}
IntRow has nothing in it since it is new. So all you are doing is iterating over the new file which has just 91 in it. Remember, result has no items. So it won't even iterate once in addBack.
So just do the following:
Change your addBack method to just add the numbers. Why use a loop to cascade down the elements since you are doing this within the same instance of IntRow? Just add it on to the end using the numberofElements as the next index.
void addBack(int number) {
elements[numberOfElements++] = number;
}
If you want to copy the contents of one IntRow object to another you would need another method in the IntRow class. Something like:
public void copy(IntRow r) {
for (int i = 0; i < r.numerOfElements; i++) {
elements[i] = r.elements[i];
}
numerOfElements = r.numberOfElements;
}
And keeping with good design it might be better to return numberOfElements in a method such as public int size();
public class MyArrayList<T> implements MyList<T>{
int num; //number of things in the list
T[] vals; //to store the contents
#SuppressWarnings("unchecked")
public MyArrayList() {
num = 0;
vals = (T[]) new Object[3];
}
public T getUnique(){
T distinct = null;
int count = 0;
for (int i=0; i<vals.length; i++){
distinct = vals[i];
for (int j = 0; j<vals.length; j++){
if (vals[j] == vals[i]){
count++;
}
if (count == 1){
return distinct;
}
}
}
if (distinct == null){
throw new IllegalArgumentException();
}
return distinct;
}
I am trying to work on a get Unique Method. A method getUnique that takes no arguments and returns the first value in the list that appears only once. (For example, calling the method on the list [1,2,3,1,2,4] would return 3 since 1 and
2 both appear more than once.) If the list is empty or all its values appear more than once, the method throws a NoSuchElementException
I have added some FIXME's to your code:
public T getUnique(){
T distinct = null;
int count = 0; // FIXME: move this initialization inside the i loop
for (int i=0; i<vals.length; i++){
distinct = vals[i];
for (int j = 0; j<vals.length; j++){
if (vals[j] == vals[i]){ // FIXME: use .equals() not ==
count++;
}
if (count == 1){ // FIXME: move this check outside the j loop
return distinct;
}
}
}
if (distinct == null){ //FIXME: no check needed, just throw it
throw new IllegalArgumentException();
}
return distinct; //FIXME: no valid return can reach this point
}
Patrick Parker's advice will fix your code, but I wanted to provide a cleaner and faster solution to the problem of finding a unique element in a list. This algorithm runs in time O(n) instead of O(n^2).
public static <T> Optional<T> getUnique(List<T> ls) {
// Create a map whose keys are elements of the list and whose values are
// lists of their occurences. E.g. [1,2,3,1,2,4] becomes {1->[1, 1],
// 2->[2, 2], 3->[3], 4->[4]}. Then elements.get(x).size() tells us how
// many times x occured in ls.
Map<T, List<T>> elements = ls.stream()
.collect(Collectors.groupingBy(x -> x));
// Find the first element that occurs exactly one time in ls.
return ls.stream().filter(x -> elements.get(x).size() == 1)
.findFirst();
}
You might call it like this:
Integer[] vals = {1,2,3,1,2,4};
System.out.println(getUnique(Arrays.asList(vals))
.orElseThrow(NoSuchElementException::new));
This code uses Java 8 streams and Optional. Below is another implementation of the same algorithm that doesn't use Java 8 language features; if you've never encountered streams, you may find it more understandable.
private static <T> T getUnique(List<T> arr) {
Map<T, Integer> numOccurrences = new HashMap<>();
for (T item : arr) {
numOccurrences.put(item, 1 + numOccurrences.getOrDefault(item, 0));
}
for (T item : arr) {
if (numOccurrences.get(item) == 1) {
return item;
}
}
throw new NoSuchElementException();
}
im very confused as to why my queue is not working, i believe that there is a problem in the enqueue and dequeue methods. but im not sure, i am supposed to Implement the class with the initial array size set to 8. The array size will be doubled once the number of the elements exceeds the size. After an element is removed from the beginning of the array, you need to shift all elements in the array one position the left. Write a test program that adds 20 numbers from 1 to 20 into the queue and removes these numbers and displays them. here is my code
public class Queue {
private int[] elements;
private int size;
private int first;
private int last;
public static final int DEFAULT_CAPACITY = 8;
public Queue(){
this (DEFAULT_CAPACITY);
}
public Queue (int capacity){
elements = new int[capacity];
first = 0;
last = 0;
size = 8;
}
public void Enqueue(int v){ //fills queue and lengthens if necessary
if (last>=size){
int[] temp = new int[elements.length*2];
System.arraycopy(elements, 0, temp, 0, elements.length);
elements = temp;
}
elements[last]=v;
last++;
}
public int Dequeue(){
int output = elements[first];
System.out.print(output + " ");
while(last != 0){
for(int i = 0; i<last;i++){
elements[i]= elements[i-1];
}
last--;
}
return output ;
}
public boolean empty(){ // tests for empty queue
return last==first;
}
public int getSize(){
size=last;
return size;
}
}
and here is the tester class.
public class QueueTester {
public static void main(String[] args){
Queue q = new Queue();
q.Enqueue(1);
q.Enqueue(2);
q.Enqueue(3);
q.Enqueue(4);
q.Enqueue(5);
q.Enqueue(6);
q.Enqueue(7);
q.Enqueue(8);
q.Enqueue(9);
q.Enqueue(10);
q.Enqueue(11);
q.Enqueue(12);
q.Enqueue(13);
q.Enqueue(14);
q.Enqueue(15);
q.Enqueue(16);
q.Enqueue(17);
q.Enqueue(18);
q.Enqueue(19);
q.Enqueue(20);
while (q.empty()){
q.Dequeue();
while(last != 0){
for(int i = 0; i<last;i++){
elements[i]= elements[i-1];
}
last--;
}
Remove the while loop. If you're trying to make sure it's not dequeueing an empty queue have an if condition check to ensure that the size is > 0.
public int Dequeue(){
if (getSize() == 0) {
// throw an error or something
}
int output = elements[first];
System.out.print(output + " ");
for(int i = 0; i<last;i++){
elements[i]= elements[i-1];
}
last--;
return output ;
}
Additionally you need to print the output in your tester class, and I assume you want to dequeue while the queue is NOT empty:
while (!q.empty()){
System.out.println(q.Dequeue());
Mmm, think the algorithm you are using is not correct try referring this http://projectyogisha.com/implementing-queues/ , its in C though.
In my Java program, I am simulating a parking garage. Suppose there are a random number of cars, let's say 7. Car number 1 is referred to by the value 1, car 2 is referred to by the value 2, and so on. Each car value is randomly stored in an array that represents the parking garage. Each element of the array represents a parking spot. I am trying to write a method that does the following: Suppose you want to know what parking space car number 4 is in. The value "4" is passed to the method, and the method will search the array for that value. I want the method to tell me which element of the array the value "4" was found in. Here is what I have so far for the method:
public int findBayOfCar(int carNumber)
{
int index = -1;
boolean found = false;
while (!found)
{
if (cars[index] == carNumber)
{
}
index++;
}
}
Obviously it will not work because Java cannot compare cars[index] (which is an array of the Car type) to carNumber, which is an int. What can I do to correct this?
You had many errors in such a small code.
while (!found) this means that you will continue searching until you found something, but what happens if the element we're searching is not on the array ? We will get the infamous ArrayOutOfBoundsException due the fact we will try to access non-existing array cell. Solution: for (int i = 0; i < cars.length; i++) in order to run from the start until the size of the array.
Found, now what ? you didn't stopped when finding the car you were looking for, now we're setting it as found = true and stopping the search.
Code:
public int findBayOfCar(int carNumber)
{
int foundAtBay = -1;
for (int i = 0; i < cars.length; i++)
{
if (cars[i].number == carNumber) // or whatever .Number or .number which identify the car number.
{
foundAtBay = i;
break;
}
}
return foundAtBay;
}
You should of reference your Car object to obtain its number:
public static int findBayOfCar(int carNumber, Car[] cars)
{
int index = -1;
boolean found = false;
while (!found && index < cars.length -1)
{
index++;
if (cars[index].getNumber() == carNumber)
{
found = true;
}
}
return found ? index : -1;
}
A simple and a brute-force solution to it would be LinearSearch:
for(int i=0; i < your_array_length; i++){
if(cars[i] == carNumber){
return i;
}
}
return -1; //-1 represents that the car was not parked in any of the slots
If your cars are just numbers, then:
int[] cars = new int[] { 1, 2, 3 } ;
public int indexOf(int carNumber) {
return Arrays.binarySearch(cars, carNumber);
}
If your cars are strings, then
String[] cars = new String[] { "car1", "car2", "car2" };
public int indexOf(int carNumber) {
return Arrays.asList(cars).indexOf("car" + carNumber);
}
If your cars are objects, then
Car[] cars = new Car[] { new Car(), new Car(), new Car() };
public Car indexOf(int carNumber) {
return IntStream.range(0, cars.length).filter(c -> carNumber == cars[c].number).mapToObj(i -> cars[i]).findFirst().orElse(null);
}
Or, with an ordinary loop:
Car[] cars = new Car[] { new Car(), new Car(), new Car() };
public int indexOf(int carNumber) {
for (int i = 0; i < cars.length; i++) {
if (cars[i].number == carNumber) {
return i;
}
}
return -1;
}
I have to make a custom iterator that iterators through an array endlessly. I have no clue how to do this considering I've never worked with iterators in java before. If anyone could help me out at all and explain to me, I'd appreciate it very much.
public class Numbers{
private int[] array;
public Numbers(int[] array){
this.array = array
}
public static void main(String[] args) {
Numbers n = new Numbers();
Iterator num = n.sequence();
for(int i = 0; i < 10; i++){
if (num.hasNext()){
System.out.print(num.next() + " ");
System.out.println();
}
}
}
}
See below:
public class Numbers implements Iterable<Integer> {
private int[] array;
private int i;
public Numbers(int[] array) {
this.array = array;
i = 0;
}
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
#Override
public boolean hasNext() { return true; }
#Override
public Integer next() {
int j = i;
i = (i + 1) % array.length;
return array[j];
}
#Override
public void remove() {}
};
}
}
You could then do:
Numbers n = new Numbers(new int[]{1,2,3});
for (int i : n)
System.out.println(i); // or anything else
This would result in the infinite loop:
1
2
3
1
2
3
1
2
...
Relevant javadocs:
- Iterator
- Iterable
Another way to do it is just to have an infinite while-loop as such:
int[] array = new int[]{1, 2, 3};
int i = 0;
while (true) {
System.out.println(array[i]); // or anything else
i = (i + 1) % array.length;
}
This is basically how an iterator works. This example uses a List, but you can use an iterator against any collection that implements java.lang.Iterable.
List<String> someList; // assume this has been instantiated and has values in it
ListIterator<String> it = someList.listIterator();
while (it.hasNext()) {
String value = it.next();
// do something with value
}
Pretty much, you instantiate the iterator by telling the collection to give you a reference to its iterator. Then you loop by calling hasNext(), which will keep you going until you have no more elements. The call to next() pulls the next item from the iterator and increments its position by one. A call to remove() will remove from the list the last item returned by next() (or previous().)
Note, of course, that I've been using java.util.ListIterator instead of java.util.Iterator because the ListIterator is a special implementation of Iterator optimized for use against lists, like in the example I gave above.
You cannot use an iterator against an array. You'd need to use a vanilla for-loop or convert it into a List or another object that implements Iterable.
To loop through the above list endlessly, your loop would look something like this:
while(it.hasNext()) {
String value = it.next();
// do processing
if (!it.hasNext()) {
it = someList.listIterator(); // reset the iterator
}
}
To loop through the array using a for-loop endlessly:
for (int i = 0; i < myArray.length; i++) {
myArray[i];
// do something
if (i == myArray.length - 1) {
i = 0; // reset the index
}
}
Alteratively you could have your Numbers class implement Iterable directly.
Work with iterators is basically always the same.
First get the iterator from your array:
Iterator iterator = yourArray.iterator();
Second iterate while it has items:
while(iterator.hasNext()) {
Object element = iterator.next();
}