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;
}
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();
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.
I wanted to know if there's a native method in array for Java to get the index of the table for a given value ?
Let's say my table contains these strings :
public static final String[] TYPES = {
"Sedan",
"Compact",
"Roadster",
"Minivan",
"SUV",
"Convertible",
"Cargo",
"Others"
};
Let's say the user has to enter the type of car and that then in the background the program takes that string and get's it's position in the array.
So if the person enters : Sedan
It should take the position 0 and store's it in the object of Cars created by my program ...
Type in:
Arrays.asList(TYPES).indexOf("Sedan");
String carName = // insert code here
int index = -1;
for (int i=0;i<TYPES.length;i++) {
if (TYPES[i].equals(carName)) {
index = i;
break;
}
}
After this index is the array index of your car, or -1 if it doesn't exist.
for (int i = 0; i < Types.length; i++) {
if(TYPES[i].equals(userString)){
return i;
}
}
return -1;//not found
You can do this too:
return Arrays.asList(Types).indexOf(userSTring);
I had an array of all English words. My array has unique items. But using…
Arrays.asList(TYPES).indexOf(myString);
…always gave me indexOutOfBoundException.
So, I tried:
Arrays.asList(TYPES).lastIndexOf(myString);
And, it worked. If your arrays don't have same item twice, you can use:
Arrays.asList(TYPES).lastIndexOf(myString);
try this instead
org.apache.commons.lang.ArrayUtils.indexOf(array, value);
Use Arrays class to do this
Arrays.sort(TYPES);
int index = Arrays.binarySearch(TYPES, "Sedan");
No built-in method. But you can implement one easily:
public static int getIndexOf(String[] strings, String item) {
for (int i = 0; i < strings.length; i++) {
if (item.equals(strings[i])) return i;
}
return -1;
}
There is no native indexof method in java arrays.You will need to write your own method for this.
An easy way would be to iterate over the items in the array in a loop.
for (var i = 0; i < arrayLength; i++) {
// (string) Compare the given string with myArray[i]
// if it matches store/save i and exit the loop.
}
There would definitely be better ways but for small number of items this should be blazing fast. Btw this is javascript but same method should work in almost every programming language.
Try this Function :
public int indexOfArray(String input){
for(int i=0;i<TYPES,length();i++)
{
if(TYPES[i].equals(input))
{
return i ;
}
}
return -1 // if the text not found the function return -1
}
Testable mockable interafce
public interface IArrayUtility<T> {
int find(T[] list, T item);
}
implementation
public class ArrayUtility<T> implements IArrayUtility<T> {
#Override
public int find(T[] array, T search) {
if(array == null || array.length == 0 || search == null) {
return -1;
}
int position = 0;
for(T item : array) {
if(item.equals(search)) {
return position;
} else {
++position;
}
}
return -1;
}
}
Test
#Test
public void testArrayUtilityFindForExistentItemReturnsPosition() {
// Arrange
String search = "bus";
String[] array = {"car", search, "motorbike"};
// Act
int position = arrayUtility.find(array, search);
// Assert
Assert.assertEquals(position, 1);
}
Use this as a method with x being any number initially.
The string y being passed in by console and v is the array to search!
public static int getIndex(int x, String y, String[]v){
for(int m = 0; m < v.length; m++){
if (v[m].equalsIgnoreCase(y)){
x = m;
}
}
return x;
}
Refactoring the above methods and showing with the use:
private String[] languages = {"pt", "en", "es"};
private Integer indexOf(String[] arr, String str){
for (int i = 0; i < arr.length; i++)
if(arr[i].equals(str)) return i;
return -1;
}
indexOf(languages, "en")
I'm doing a program where user input five numbers and in the end the numbers are printed out which is working fine. What I can't get to work is a boolean function to check for duplicates. It should check for duplicates as the user write them in, so e.g. if number one is 5 and the second numbers is also 5, you should get an error until you write in a different number. Meaning if the user input a duplicate it should NOT be saved in the array. This is obviously an assignment, so I'm just asking for a hint or two.
This program is written based on pseudo-code given to me, and therefore I have to use a boolean to check for duplicates with the public boolean duplicate( int number ) class.
I've tried getting my head around it and tried something by myself, but obviously I'm doing a stupid mistake. E.g.:
if(int i != myNumbers[i])
checkDuplicates = false
else
checkDuplicates = true;
return checkDuplicates;
DuplicatesTest class:
public class DuplicatesTest {
public final static int AMOUNT = 5;
public static void main(String[] args) {
Duplicates d = new Duplicates(AMOUNT);
d.inputNumber();
d.duplicate(AMOUNT);
d.printInputNumbers();
}
}
Duplicates class:
public class Duplicates {
private int amount;
private int[] myNumbers;
private boolean checkDuplicates;
public Duplicates(int a) {
amount = a;
myNumbers = new int[amount];
}
public void inputNumber() {
for(int i = 0; i < amount; i++ ) {
int input = Integer.parseInt(JOptionPane.showInputDialog("Input 5 numbers"));
myNumbers[i] = input;
}
}
public boolean duplicate( int number ) {
<BOOLEAN TO CHECK FOR DUPLICATES, RETURN FALSE OR TRUE>
}
public void printInputNumbers() {
JTextArea output = new JTextArea();
output.setText("Your numbers are:" + "\n");
for(int i = 0; i < myNumbers.length; i++) {
if (i % 5 == 0) {
output.append("\n");
}
output.append(myNumbers[i] + "\t");
}
JOptionPane.showMessageDialog(null, output, "Numbers", JOptionPane.PLAIN_MESSAGE);
}
}
Sorry if the code tag is messy, I had some trouble with white fields in between and such. I'm new here.
Don't store the numbers in an array. Use a Set<Integer> instead. And then do a Set#contains() operation. It's O(1) operation which is actually far better than iterating over the array to search for duplicates.
Ok, if it's a compulsion to use an array, then you should modify your current approach, to return true as soon as you find a duplicate, instead of iterating over the array again. In your current approach, since you are setting the boolean variable to false in the else block, your method will return false if the last element of the array is not the same as what you are checking. So, just modify your approach to:
// loop over the array
if (number == myNumbers[i])
return true;
// outside the loop, if you reach, return false
return false;
Note that your current if statement will not compile. You are declaring an int variable there, which you can't do.
if (int i == myNumbers[i]) // this is not a valid Java code.
int nums[] = new int[5];
int count = 0;
public boolean duplicate(int number)
{
boolean isDup = false;
for (int i = 0; i <= count; i++)
{
if (number == nums[i])
{
isDup = true;
break;
}
}
if (!isDup)
{
count++;
nums[count] = number;
}
return isDup;
}
I am trying to have a method (duplicates) return true if a given array called x (entered by user in another method), contains duplicate values. Otherwise it would return false. Rather then checking the entire array, which is initialized to 100, it will check only the amount of values entered, which is kept track of with a global counter: numElementsInX.
What is the best way to accomplish this?
public static boolean duplicates (int [] x)
I am prompting for user data like so:
public static void readData (int [] x, int i){
Scanner input = new Scanner(System.in);
System.out.println("Please enter integers, enter -999 to stop");
while (i <= 99) {
int temp = input.nextInt();
if(temp == -999){
break;
}
else {
x[i++]=temp;
}
// else
}//end while
printArray(x,i);
}//end readData
public static void printArray(int [] x, int numElementsInX){
int n = numElementsInX;
for (int i = 0; i < n; i++){
System.out.print(x[i] + " ");
}//end for
System.out.println();
}//end printArray
I am sure there is a better way to do this, but this is how I have been taught so far.
Here is a solution that:
Compiles and executes without throwing.
Uses numElementsInX as you requested.
Returns as soon as it finds a duplicate.
This approach tests whether each member of the array has been seen before. If it has, the method can return immediately. If it hasn't, then the member is added to the set seen before.
public static boolean duplicates (int [] x, int numElementsInX ) {
Set<Integer> set = new HashSet<Integer>();
for ( int i = 0; i < numElementsInX; ++i ) {
if ( set.contains( x[i])) {
return true;
}
else {
set.add(x[i]);
}
}
return false;
}
Here's a sample program containing the above code.
this should do it.
public boolean containsDuplicates(Integer[] x) {
return new HashSet<Integer>(Arrays.asList(x)).size() != x.length
}
You dont need numElementsInX as this is the same as x.length
edit after comment from Louis. Arrays.asList does not work with int arrays.
To convert int[] to Integer try this question How to convert int[] to Integer[] in Java?
or do soemthing like this (not tested but from memory)
Integer[] newArray = new Integer[a.length];
System.arraycopy(a, 0, newArray, 0, a.length);
This certainly isn't the most efficient way, but since you don't know about Sets yet, you can use two loops:
public static boolean duplicates (int [] x){
for (int i=0; i<numElementsInX; i++){
for (int j=i+1; j<numElementsInX; j++){
if (x[j]==x[i]) return true;
}
}
return false;
}
"set.add()" returns true if the element is not already present in the set and false otherwise. We could make use of that and get rid of "set.contains()" as in the above solution.
public static boolean duplicates (int[] x, int numElementsInX) {
Set<Integer> myset = new HashSet<>();
for (int i = 0; i < numElementsInX; i++) {
if (!myset.add(x[i])) {
return true;
}
}
return false;
}
For java, return true if the array contains a duplicate value,
boolean containsDuplicates(int[] a) {
HashSet<Integer> hs = new HashSet<>();
for(int i = 0; i<a.length; i++) {
if(!hs.add(a[i])){
return true;
}
}
return false;
}