The scanner would not scan the second line - java

I had this code where after reading the first three lines of input, it would just terminate the program and would not let me enter the next line. Here's the code:
import java.util.Arrays;
import java.util.Scanner;
public class cycle {
public static void main(String[] arg)
{
System.out.println("Put in numbers");
Scanner in=new Scanner(System.in);
int indicator=Integer.parseInt(in.nextLine());
if(indicator==1)
{
mission1();
}
else if(indicator==2)
{
mission2();
}
in.close();
}
static void mission1()
{
Scanner miss1=new Scanner(System.in);
int citizens=Integer.valueOf(miss1.nextLine());
String lines=miss1.nextLine();
lines=lines.replaceAll("\\s", "");
int length=lines.length();
String lines2=miss1.nextLine();
lines2=lines.replaceAll("\\s", "");
int length2=lines.length();
while(citizens!=length||citizens!=length2)
{
System.out.println("Citizens number do not match, try again" );
miss1=new Scanner(System.in);
citizens=Integer.valueOf(miss1.nextLine());
lines=miss1.nextLine();
lines=lines.replaceAll("\\s", "");
length=lines.length();
lines2=miss1.nextLine();
lines2=lines.replaceAll("\\s", "");
length2=lines.length();
miss1.close();
if(citizens!=length||citizens!=length2)
{
throw new IndexOutOfBoundsException("Numebr of citizens do not match. Please enter numbers again");
}
else if(citizens==length&&citizens==length2)
{
String[] strs=lines.trim().split("\\s");
length=lines.length();
int[] dspeed = new int[length];
for(int i=0; i<length;i++)
{
dspeed[i]=Integer.parseInt(strs[i]);
}
String[] strs2=lines2.trim().split("\\s+");
int[] pspeed = new int[length2];
for(int i=0; i<length2;i++)
{
pspeed[i]=Integer.parseInt(strs2[i]);
}
Arrays.sort(dspeed);
break;
}
}
}
static void mission2()
{
}
}
For example, with an input like this:
Put in numbers
1
3
1 3 5
1 3 5
It would just terminate the program and it is ok, but with an input like this:
Put in numbers
1
3
1 3
1 3
Citizens number does not match, try again
1
3
1 3 5
The program would terminate before I can't put in the fourth line.
As a test I put in
for(int n=0;n<length;n+=1)
{
System.out.println(dspeed[n]);
}
in between Arrays.sort(dspeed[n]) and break, and the result is like this
Put in numbers
1
3
1 3
1 3
Citizens number do not match, try again
1
3
1 3 5
3
It makes no sense since it is giving me an output of 3 while not letting me enter the second line. So it is like part of the code is being skipped. Why is this happening and how do I fix this?
Edit: For mission1 it suppose to get a number(let's say x), and then get x numbers of different numbers from the next line. Then, it should put those numbers in an array and sort them

As of writing my answer I realized what the actual cause of your error is; look at this piece of code:
lines=miss1.nextLine();
lines=lines.replaceAll("\\s", "");
length=lines.length();
lines2=miss1.nextLine();
/*Should be lines2!*/
lines2=lines.replaceAll("\\s", "");
/*Should be lines2!*/
length2=lines.length();
You're using linesfor all your variables. Changing lines to lines2 for the lines2 = ... and length2 variables fixed the issue that you posted. I also replaced
if (citizens != length || citizens != length2) {
/*If you decide to keep this, it should not be a "IndexOutOfBoundsException
(since no index was out of bounds) but should perhaps be a "IllegalArgumentException"
since you supplied it illegal arguments.*/
throw new IndexOutOfBoundsException("Numebr of citizens do not match. Please enter numbers again");
} else if (citizens == length && citizens == length2) { ... }
with
if (citizens == length && citizens == length2) { ... }
Since otherwise this would cause the program to crash if you gave it an invalid input twice in a row.
This part of the answer should be considered code-review and is here to (try to) help improve your code structure. Actual answer is above.
This is the entire class code. This seems to have resolved your error and I've also re-structured some of the code and added comments explaining what I edited and why I restructured it. Please leave a comment if anything is unclear or if it didn't actually resolve your error. Please note that the imports are left out of this answer for clarity.
public class Cycle {
/* Important! We can re-use the same scanner for all inputs. */
final Scanner in;
public Cycle() {
in = new Scanner(System.in);
run();
in.close();
}
private void run() {
System.out.println("Input mission number.");
final int indicator = Integer.parseInt(in.nextLine());
if (indicator == 1) {
mission1();
} else if (indicator == 2) {
// etc
}
}
private void mission1() {
while (true) {
System.out.println("Input number of citizens.");
final int citizens = Integer.valueOf(in.nextLine());
/* We don't edit these two first inputs just yet since we
* have to use the un-edited inputs later in our if-else
* statement. */
System.out.println("Input first number(s).");
final String inputOne = in.nextLine();
System.out.println("Input second number(s).");
final String inputTwo = in.nextLine();
final String lines = inputOne.replaceAll("\\s", "");
final int length = lines.length();
final String lines2 = inputTwo.replaceAll("\\s", "");
final int length2 = lines2.length();
if (citizens != length || citizens != length2) {
/* If the number of citizens doesn't match it just
* continues the while-loop and does it all over
* again. */
System.out.println("Citizens number do not match, try again");
} else {
/* Here we use the unedited inputs from before - which
* is why we didn't edit them. */
final int[] dspeed = createArrayFromInput(inputOne);
final int[] pspeed = createArrayFromInput(inputTwo);
break;
}
}
}
/* We shouldn't have duplicated code - use a method instead. */
private int[] createArrayFromInput(final String input) {
final String[] strs = input.trim().split("\\s+");
/* The arrays should be the same size so use 'strs.length' as
* length */
final int[] speed = new int[strs.length];
for (int i = 0; i < strs.length; i++) {
speed[i] = Integer.parseInt(strs[i]);
}
Arrays.sort(speed);
return speed;
}
public static void main(final String[] arg) {
/*We should use a class instance instead of static methods and variables.*/
new Cycle();
}
}

Related

Java: How to use a Scanner to check that input is an integer and is within a specified range

I'm having trouble with my code.
What it should do:
Check if Scanner "myScanner" is an Integer
If it is an Integer, if it is between 1 and 200 (both included)
Problem:
I need to input an Integer with the correct value twice after the the first guess wasn't correct.
Here is a screenshot of exactly what I mean: Screenshot of the problem
private static int inputGuess () {
Scanner myScanner = new Scanner(System.in);
int guess = 0;
if (myScanner.hasNextInt()) {
guess = myScanner.nextInt();
}
if (1 > guess || guess > 200) {
while (!(myScanner.hasNextInt()) || !(1 <= guess && guess <= 200)) {
while (!myScanner.hasNextInt()) {
myScanner.nextLine();
}
guess = myScanner.nextInt();
if (!(guess >= 1 && guess <= 200)) {
myScanner.nextLine();
}
}
}
return guess;
}
I have tried to apply #Hulk's (top answer) logic (at least I think I did) into a single method (is sadly a requirement for my project) and got this:
private static int inputGuess () {
Scanner myScanner = new Scanner(System.in);
int guess = 0;
while (!myScanner.hasNextInt() || guess < 1 || guess > 200) {
while (!myScanner.hasNextInt()) {
myScanner.nextLine();
}
guess = myScanner.nextInt();
if (guess >= 1 && guess <= 200) {
break;
}
}
return guess;
}
After a bit of testing still no error!
If you still find a mistake I would be happy if you shared it with me!
This gets a lot simpler if you split your problem into smaller parts. First, solve the "read until we got an integer" part and put it into a method so we can reuse it:
private static int readNumber(Scanner sc) {
while (!sc.hasNextInt()) {
sc.nextLine(); // if its not a number, consume the line and wait for new input
}
return sc.nextInt(); // always an integer
}
Now, we only need to add the range check:
private static int inputGuess () {
Scanner myScanner = new Scanner(System.in);
int n = 0;
while (n < 1 || n > 200) { // range check, only in one place
n = readNumber(myScanner); // always returns a number
}
return n;
}
You basically complicated things too much, by repeating the range check in 3 places in different ways, and it's easy to get lost with all these negations. Keep your methods simple, and only do one thing at a time!
To adress your updated question: If you absolutely need to inline these into one method, this is the result:
private static int inputGuess () {
Scanner myScanner = new Scanner(System.in);
int n = 0;
while (n < 1 || n > 200) { // loop until in valid range
while (!myScanner.hasNextInt()) {
myScanner.nextLine(); // if its not a number, consume the line and wait for new input
}
n = myScanner.nextInt(); // always an integer
}
return n; // always in valid range
}
Note that there is still only one place where there is a check for numeric input, and only one place where the range is validated. In programming, there is rarely a reason to write exactly the same thing twice - don't repeat yourself! - a 'principle'/guideline sometimes abbreviated as DRY.

How to multiply different indexes by different values?

I am creating a scrabble game, where the characters get the same values as scrabble,(q & z =10),(k=5), etc, and the main issue that I am having is that I am asking the user to input 2 ints after the word, the first being the index of the bonus tile, and the second being the multiplier to multiply the word with. The value without the multiplier is correct, but the multiplier is not working.
public class Main {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
String word = kb.next();
int bonusI = kb.nextInt();
int bonusMult = kb.nextInt();
int score=0;
for (int i=0; i<word.length();i++){
int letterScore;
String letter=word.substring(i,i+1);
if (letter.equals("d")||letter.equals("g")){
letterScore=2;
}
else if (letter.equals("k")) {
letterScore=5;
}
else if (letter.equals("j")||letter.equals("x")){
letterScore=8;
}
else if (letter.equals("q")||letter.equals("z")) {
letterScore=10;
}
else {
letterScore=1;
}
for (int j=0;j<1;j++){
if (word.substring(i,i+1).equals(bonusI)){
letterScore*=bonusMult;
}
}
score+=letterScore;
}
System.out.println(score);
}
}
For example, if the input is dog 2 3 then the correct output would be 9,(d is 2 points,o according to scrabble is 1 point, and g is 2 points, but since the 1st int inputted was 2, and g has an index of 2, it is then multiplied by the bonus of 3, which makes g=6, adding them 2+1+6=9) but instead my output is 5 because the multiplier for g is not working.
Looks like you have a mistake here.
word.substring(i,i+1).equals(bonusI)
word.substring(i,i+1) is String and gives one letter
bonusI is an int and tives one number
This will never be true
if (word.substring(i,i+1).equals(bonusI)) - This condition will be always false as you can't compare a string with int value.
Instead you can just replace the internal for loop with below code
if (bonusI == i)
{
letterScore*=bonusMult;
}

How to filter certain values of numbers from a string and return the rest

I need to create a method that takes a string as an input, like "I have 2456 balloons in 37 wilderness" and if n is set to 3 and "more" is set to false, the method would return "I have 2 balloons in wilderness". If more was set to true, it would return "I have 456 balloons in 7 wilderness"
I have been playing around with the filtering part quite a bit, but I don't know how to put the rest of this method together. Here is what I have come up with so far:
public class Test1
{
public static void main(String [] args)
{
List<Integer> lst= new ArrayList<Integer>();
//Take user input any number of times based on your condition.
System.out.println("Please enter a number :");
Scanner sc= new Scanner(System.in);
int i= sc.nextInt();
if(i==0 || i==1 || i==2 ||i==3)
{
lst.add(i);
}
//Go back
}
}
Or I could use something like this:
int input;
do {
input = sc.nextInt();
} while (input < 0 || input > 3);
I'm pretty new to Java, so progress on this task has been slow
How can I get this method to save the letters and filter numbers depending on the two values (a number and true/false for more)?
Here is a simple solution with explanation.
Take note that we used a very straightforward approach but a lot of validations are still needed. Also, there are shorter solutions but this is the one I wrote so that it's clearer for people new in Java.
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
System.out.println("Enter your string: ");
String strInput = sc.nextLine();
System.out.println("Enter n: ");
int n = sc.nextInt();
System.out.println("Do you want more? (Y/N)");
char more = sc.next().charAt(0);
String result = "";
// Loop through all the characters in the String
for(char c : strInput.toCharArray()) {
// Check if the character is a number
// If not, just append to our result string
if(!Character.isDigit(c)) {
result += c;
} else {
// Converts character to the number equivalent value
int numValue = Character.getNumericValue(c);
// If more is 'Y', we check if it's greater than the number and append
// else if more is 'N', we check if the value is less than n then append.
// Otherwise, do nothing.
if (more == 'Y' && numValue > n) {
result += c;
} else if (more == 'N' && numValue < n) {
result += c;
}
}
}
System.out.println(result);
}

Why am I getting the error in a loop that reoccurs at a single particular iteration every run-time? (Binary Queries problem from HackerEarth)

I'm trying to solve this question:
Binary Queries,
https://www.hackerearth.com/practice/data-structures/arrays/1-d/practice-problems/algorithm/range-query-2/
Question summary:
N digits of binary numbers are given; Q queries are then given.
Two types of queries:
"0 X": Flip the Xth bit
"1 L R": Print if binary no. formed by L to R(position) is odd or even.
Simple solution is to check only rightmost bit; if it's 1, the number is odd, else, even.
My code throws "Wrong answer" every time;
however, IN ALL TEST CASES, there's ONLY ONE wrong output, and this wrong output happens EXACTLY 99 lines before the total number of output lines*.
There seems to be no other pattern.
*I tried flipping output when I reach (Q-99)th query to check; however, there's no way to find number of output queries without storing all queries, since query type[0] has no output, only type1 has an output. Thus, Q cannot be used.
Images: All testcases fail Eg.1 The only line of error Eg.2 Another example.
Here's my code:
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inpArr[] = (br.readLine().split("\\s"));
int n=Integer.parseInt(inpArr[0]); //number of digits
int q=Integer.parseInt(inpArr[1]); //number of queries
//read binary digits w/o space, and store them as chars
String binArrStr=br.readLine().replace(" ","");
char[] binArr=binArrStr.toCharArray();
int i;
for(i=0;i<q;i++) //all queries
{
String query[]=br.readLine().split("\\s"); //read the query
if(query[0].equals("1")) //Flip the bit if query[0]=1
{
if(binArr[Integer.parseInt(query[1])-1]=='1') //take position(query[1]) as int and flip
binArr[Integer.parseInt(query[1])-1]='0';
else
binArr[Integer.parseInt(query[1])-1]='0';
}
else //Print odd or even if query[0]=0
{
//query[1] is leftmost bit.
//Sufficient to check only the bit in rightmost position, given by
//3rd argument(Rightmost bit) which is query[2]
//If rightmost bit==1, ODD, else EVEN
if(binArr[Integer.parseInt(query[2])-1]=='1')
System.out.println("ODD");
else
System.out.println("EVEN");
}
}
}
I could skip this problem, but it's better to know why exactly this happens, I think.
if(query[0].equals("1")) //Flip the bit if query[0]=1
{
if(binArr[Integer.parseInt(query[1])-1]=='1') //take position(query[1]) as int and flip
binArr[Integer.parseInt(query[1])-1]='0';
else
binArr[Integer.parseInt(query[1])-1]='0';
}
in your if statement you checked that if it's 1 then flip it to 0 but in your else block you are not flipping the number to 1 because else block will come to action if the number is 0. Hence you are only partially flipping.
Here is my solution
import java.util.Scanner;
class TestClass {
public static void main(String args[]) throws Exception {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int q = scan.nextInt();
int[] bits = new int[n + 1];
for (int i = 1; i <= n; i++) {
bits[i] = scan.nextInt();
}
for (int i = 1; i <= q; i++) {
if (scan.nextInt() == 1) {
int index = scan.nextInt();
if (bits[index] == 0) bits[index]++;
else bits[index]--;
} else {
int lIndex = scan.nextInt();
int rIndex = scan.nextInt();
System.out.println(bits[rIndex] == 0 ? "EVEN" : "ODD");
}
}
}
}

storing multiple user inputs into an integer array

So here's what i'm trying to do. Have user input numbers, store them in an array, then print all those numbers out on one line. I must use a method/function as well. I think i have done quite well so far, it shows no errors in eclipse. What im stuck on is storing their input into an array. i want them to keep inputting numbers one at a time until they're satisifed and type 'quit'. i just havent read about how to store things in an array despite looking around, particularly storing more than one thing, progressively. here is my code so far, and thank you in advance for any help!
import java.util.Scanner;
public class intarray {
public static void main(String[] args) {
System.out.println("Enter a number then hit enter. You may then enter another number or end by typing quit.");
String x;
Scanner input = new Scanner(System.in);
while (true) {
x=input.next();
if (x.equalsIgnoreCase("quit")) {break;}
if (x.equals(null)) throw new Error("You entered nothing. Try again.");
int stringLength = x.trim().length();
if (stringLength == 0) throw new Error("Seems you only entered spaces. Try again.");
isNum(x);
int goingintoarray = Integer.parseInt(x);
int array[];
}
}
public static String isNum(String t) {
int user=Integer.parseInt(t);
String convertback = Integer.toString(user);
return convertback;
}
}
Since you don't know how many elements there will be an array is a bad idea since you will have to resize it quite often as new elements appear (copying arrays is expensive!) or instantiate a large enough array at the beginning (which is a waste and still doesn't protect you in 100% from having to resize it eventually).
Instead using Java's List (preferably LinkedList) sounds like a good idea since you can add elements dynamically without resizing the data structure.
List<Integer> numbers = new LinkedList<>();
while(true) {
// something
numbers.add(goingintoarray);
// something
}
Be careful of other implementations - for instance ArrayList uses an array (d'uh ;-) ) to store the elements so you would have the same problem but the resizing part would be taken care of for you by the implementation.
#Edit: by convention classes in Java are written using CamelCase starting with an uppercase letter.
ArrayList<Integer> inputs = new ArrayList<Integer>();
while (true) {
Scanner input = new Scanner(System.in);
x=input.next();
if (x.equalsIgnoreCase("quit")) {break;}
if (x.equals(null)) throw new Error("You entered nothing. Try again.");
int stringLength = x.trim().length();
if (stringLength == 0) throw new Error("Seems you only entered spaces. Try again.");
inputs.add(Integer.parseInt(x));
}
You don't want the isNum method since it gives same exception here if it gets wrong input for x.
import java.util.Scanner;
public class intarray {
public static int initSize = 5;
public static void main(String[] args) {
System.out.println("Enter a number then hit enter. You may then enter another number or end by typing quit.");
int array[] = new int[initSize];
int pos = 0;
int maxSize = initSize;
String x = null;
Scanner input = new Scanner(System.in);
while (true) {
x = input.next();
if (x.equalsIgnoreCase("quit")) {
break;
}
//input empty string, java io can filter. So , x impossible "null" or null.
//if (x.equals(null))
// throw new Error("You entered nothing. Try again.");
int stringLength = x.trim().length();
if (stringLength == 0)
throw new Error("Seems you only entered spaces. Try again.");
Integer numX = isNum(x);
// if the array is full, extend it
if(pos == maxSize){
int[] newArray = new int[2 * maxSize];
System.arraycopy(array, 0, newArray, 0, maxSize);
array = newArray;
maxSize = array.length;
}
if(null == numX)
System.out.println(x + " isn't a number."); //choose notify or throw error
else
array[pos++] = numX;
}
printArray(array, pos);
}
public static Integer isNum(String t) {
try {
return Integer.parseInt(t);
} catch (NumberFormatException e) {
return null;
}
}
public static void printArray(int[] array, int pos) {
if(null == array || array.length == 0 || pos <= 0)
return ;
for(int i = 0 ; i < pos; i++)
System.out.print(array[i] + " ");
}
}

Categories