A Program that Checks Consecutive Letters - Java - java

I'm looking for help with a question I have. We just started learning simple java in our course after learning a tonne of C++.
One of our bonus missions for people who know code more than what was taught in class.
The mission is as follows: Write a function by the name lettersSeries which gets letters (one letter at a time, assume all letters are lower case) inputted from the user. The function stops accepting letters from the user once the user has inputted 3 consecutive letters. (Only for loops can be used without while loops)
Example: a -> b -> a -> c -> d -> e (Here is stops)
As far I don't know much and I would be happy if someone would help me with this... I tried some options but I have no idea how to trace the alphabet, and especially how to check if letters are consecutive...
Thanks!
public static void letterSeries() {
//We create a scanner for the input
Scanner letters = new Scanner(System.in);
for(Here I need the for loop to continue the letters input) {
//Here I need to know if to use a String or a Char...
String/Char letter = next.<//Char or String>();
if(Here should be the if statement to check if letters are consecutive) {
/*
Here should be
the rest of the code
I need help with
*/
Obviously, you could change the code, and not make my pattern, I would just be happier with an easier way!

Here's how I would tackle the problem, I'm going to let you fill in the blanks with this though so I don't do all of your homework for you.
private void letterSeries() {
Scanner scanner = new Scanner(System.in);
char prevChar;
char currChar;
int amountOfConsecutives = 0;
final int AMOUNT_OF_CONSECUTIVES = 2;
for(;;) {
// Take in the users input and store it in currChar
// Check if (prev + 1) == currChar
// If true, amountOfConsecutives++
// If false, amountOfConsecutives = 0;
// If amountOfConsecutives == AMOUNT_OF_CONSECUTIVES
// Break out of the loop
}
}

You can use chars' Unicode number to check if letters are consecutive: if a and b are your letters, try to check if b - a == 1. If consequentiality is intended in a case-insensitive way ('B' consecutive to 'a') then check: (b - a == 1 || b - a == 33).

Scanner letters = new Scanner(System.in);
char previousChar = '\0';
int consecutive = 1;
for(; consecutive != 3 ;){
char userInput= letters.findWithinHorizon(".", 0).charAt(0);
if (userInput - previousChar == 1){
consecutive++;
} else {
consecutive = 1;
}
previousChar = userInput;
}
I cheated a little bit with this solution. I used a for loop with only the middle part so it acts like a while loop.
Anyway, here's how it works.
The first three lines create a scanner for user input, a consecutive variable that counts how many consecutive letters the user enters, and a previousChar to store the previous character.
"Why does consecutive start at 1?" you might ask. Well if the user enters one letter, it is going to be consecutive with itself.
In the for loop, as long as consecutive != 3, the code is going to run. The first line in the loop we read a character using findWithinHorizon(".", 0).charAt(0). And then the if statement checks whether it is a consecutive letter with the previous character. If it is, add one to consecutive and if not, reset consecutive to one. Lastly, we set previousChar to userInput to prepare for the next iteration.

private void letterSeries() {
Scanner letters = new Scanner(System.in);
String last = "";
int counter = 0;
for (;counter < 2;){
if ( last.equals (last=letters.next())) counter ++;
else counter = 0
}
}

Related

Java - Read text file and store it using scanner, gives me empty ArrayList. Split words by using Delimeter

Task is to read an article of text from outside file and put each word (no signs) into and Array List as a separate String.
Although I´m sure my path is correct and readable(I can for example perform character count), no matter what I do my Array List of words from that article comes out as empty. I may be struggling with a way how to separate words from each other and other signs. Also with storing the result of reading.
I´ve been googling for the last 2 hours and reading similar answers here but no success. So decided for the first time to ask a question.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import org.w3c.dom.Text;
public class PlaceForErrors {
public static void main(String[] args) {
Scanner scan = null;
try {
scan = new Scanner(new File("\\Users\\marga\\Desktop\\objekt program\\oo2021\\w05_kontrolltoo1\\textHere.txt")).useDelimiter(" \\$ |[\\r\\n]+");
String token1 = "";
ArrayList<String> text = new ArrayList<String>();
while (scan.hasNext()) {
token1 = scan.next();
text.add(token1);
}
String[] textArray = text.toArray(new String[0]);
for(String element : textArray){
System.out.println(element);
}
//Controlling if the ArrayList is empty and it is
boolean tellme = text.isEmpty();
System.out.println(tellme);
} catch (FileNotFoundException exception) {
System.out.println(exception);
}
finally{
scan.close();
}
}
}
String[] textArray = text.toArray(new String[0]);
This line is your problem. You're trying to allocate the ArrayList into a String array of size 0, resulting in it appearing empty.
I would modify the array declaration to initialize using the ArrayList size, like so:
String[] textArray = text.toArray(new String[text.size()]);
Then you can see if your token delimiter works.
Quick recap of your steps
Your program does a lot. I counted 9 steps:
opens a (text) file as (text) input-stream to read from
create a scanner for tokens from this input-stream using a regular-expression as delimiter (= tokenizer)
scan for and iterate over each subsequent token (if any found) using a while-loop
each of this iteration adds the token to a list
if no more tokens, then iteration ends (or never started!): converts the list to array
loop over each array element using a for-each-loop and print it
check if originally collected list is empty and print true or false
catch the exception if file was not found and print the it
finally close any opened resources: the file that was read from
Now let's start to look for the step where something potentially could go wrong: the places for errors 😏️
Analysis: What can go wrong?
Look at the listed steps above and think of each from a what-could-go-wrong perspective, a quick check list (not correlated to the step-numbers above!):
Can your text-file be found, does it exist and is readable? Yes, otherwise any IOException like FileNotFoundException would have been thrown and printed.
Is the opened file empty with a size of 0 bytes? You can check using:
File textFile = new File("\\Users\\marga\\Desktop\\objekt program\\oo2021\\w05_kontrolltoo1\\textHere.txt");
System.out.println( "File size: " + textFile.length() );
// before passing the extracted file-variable to scanner
scan = new Scanner( textFile ).useDelimiter(" \\$ |[\\r\\n]+");
Does the delimiter/regex properly split/tokenize an example input string? Try:
// Just a separate test: same delimiter, with test-input
String delimiterRegex = " \\$ |[\\r\\n]+";
String testInput = " $ Hello\r\nWorld !\n\nBye.";
// so we create a new scanner
Scanner testScanner = new Scanner( testInput ).useDelimiter(delimiterRegex);
int tokenCount = 0;
while( testScanner.hasNext() ) {
tokenCount++;
System.out.println("Token " + tokenCount + ": " + testScanner.next() );
}
testScanner.close();
Should print 3 tokens (Hello, World !, Bye.) on 3 lines in console. The special sequence $ (space-dollar-space), any \n or \r (newline or carriage-return) are omitted and have split the tokens.
We should check the list directly after the while-loop:
// Not only checking if the ArrayList is empty, but its size (is 0 if empty)
System.out.println("Scanned tokens in list: " + text.size());
If it is empty, then we neither need to fill the array, nor loop to print will start (because nothing to loop).
Hope these explanations help you to perform the analysis (debugging/testing) yourself.
Let me know if it helped you to catch the issue.
Takeaway: Divide and conquer!
Why did I count the steps, above? Because all are potential places for errors.
In developer jargon we also say this main method of class PlaceForErrors has many responsibilities: counted 9.
And there is a golden principle called Single Responsibility Principle (SRP).
Put simply: It is always good to split a large problem or program (here: your large main method) into smaller pieces. These smaller pieces are easier to work with (mentally), easier to test, easier to debug if errors or unexpected happens. Divide & conquer!
If it works, start improving
You can split up this long method doing 9 steps into smaller methods.
Benefit: each method can be tested in isolation, like the testScanner.
If your program finally works as expected and your manual test went green.
Then you should post the working code to the sister-site: CodeReview.
Be curious and ask again, e.g. how to split up the methods, how to make testable, etc.
You'll get lot's of experienced advise on how to improve it even more.
Thank you for your input everyone!
Regarding the code, I went and checked everything step by step and on the way learned more about delimiters and scanner. I fixed my delimiter and everything worked just fine now.
Beside the fact that I made a newbie mistake and didn´t show the full code, as I though it would take away the attention from the main problem. I had two conflicting scanners in my main function(one I showed you and the other one was scanning again and counting letters A). And they both worked great separately(when one or the other is commented out), but refused to work together. So I found a way to combine them and use scanner only once. I will share my full code for reference now.
I learned my mistake, and will provide the my full code always in the future.
If someone is curious the full task was the following:
Read the text from a separate file using scanner and store it in an Array List.
Count how many letters "A" (small or big) there were and how big of % they made out of all the letters in the text.
Count how many words had one letter A, two letters A in them, etc.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class Trying {
public static void main(String[] args) {
Scanner scan = null;
try {
//SCANNING FILE AND CREATING AN ARRAYLIST
scan = new Scanner(new File("\\Users\\marga\\Desktop\\objekt program\\oo2021\\w05_kontrolltoo1\\textHere.txt")).useDelimiter("[.,:;()?!\"\\s]+");
int aCount = 0;
int letterCount =0;
String token1 = "";
int wordWithAtLeastOneA = 0;
int wordWithA = 0;
int word1A = 0;
int word2A = 0;
int word3A = 0;
int word4OrMoreA = 0;
ArrayList<String> text = new ArrayList<String>();
// SCANNING EVERY WORD INTO AN ARRAY LIST
while(scan.hasNext()){
token1 = scan.next();
text.add(token1);
}
System.out.println("Amount of words in the scanned list is : " + text.size());
//COUNTING HOW MANY LETTERS 'A' TEXT HAS
for(String element : text){
for (int i=0;i<=element.length()-1;i++){
if (element.charAt(i) == 'A' || element.charAt(i) == 'a') {
aCount++;
}
}
}
System.out.println("There are "+aCount+" letters 'A'. ");
//HOW MANY LETTERS IN TOTAL TEXT HAS
for(String element : text){
for (int i=0;i<=element.length()-1;i++){
letterCount++;
}
}
//COUNTING HOW MANY WORDS HAVE 'A' LETTER IN THEM
for(String element : text){
for (int i=0;i<=element.length()-1;i++){
if (element.charAt(i) == 'A' || element.charAt(i) == 'a') {
wordWithAtLeastOneA++;;
break;
}
}
}
System.out.println("There are "+wordWithAtLeastOneA+" words that have at least one letter 'A' in them.");
System.out.println();
//COUNTING NUMBER OF WORDS THAT HAVE 1/2/3 or more 'A' LETTER IN THEM
for(String element : text){
wordWithA = 0;
for (int i=0;i<=element.length()-1;i++){
if (element.charAt(i) == 'A' || element.charAt(i) == 'a') {
wordWithA++;
if(wordWithA == 1){
word1A++;
}else if (wordWithA == 2){
word2A++;
}else if (wordWithA == 3){
word3A++;
}else if (wordWithA >= 4){
word4OrMoreA++;
}
}
}
}
System.out.println("There were "+ word1A+ " words, that had one letter 'A' in them." );
System.out.println("There were "+ word2A+ " words, that had two letters 'A' in them." );
System.out.println("There were "+ word3A+ " words, that had three letters 'A' in them." );
System.out.println("There were "+ word4OrMoreA+ " words, that had 4 or more letters 'A' in them." );
//COUNTING HOW MANY LETTERS THERE ARE IN TOTAL, COMPARE TO NUMBER OF "A" LETTERS
int percentOfA = aCount*100/letterCount;
System.out.println();
System.out.println("The entire number of letters is "+ letterCount+" and letter 'A' makes " + percentOfA+ "% out of them or " +aCount+ " letters.");
// for(String element : textArray){
// System.out.println(element);
// }
} catch (FileNotFoundException exception) {
System.out.println(exception);
}
finally{
scan.close();
}
}
}
And the text is:
Computer programming is an enormously flexible tool that you can use to do amazing things that are otherwise either manual and laborsome or are just impossible.
If you are using a smartphone, a chat app or if you are unlocking your car with the push of a button,
then you must know that all these things are using some kind of programming.
You are already immersed in the programs of different types.
In fact, software is running your life. What if you learn and start running these programs according to your will?
And the output is:
There are 35 words that have at least one letter 'A' in them.
There were 35 words, that had one letter 'A' in them.
There were 3 words, that had two letters 'A' in them.
There were 0 words, that had three letters 'A' in them.
There were 0 words, that had 4 or more letters 'A' in them.
The entire number of letters is 416 and letter 'A' makes 9% out of them or 38 letters.

Chess board that will check if a piece entered onto the board is in a valid position

I am very new to Java programming in general and have just started using 2D arrays. What I am trying to do is make a program that creates a chessboard 8x8, and asks the user to input strings (pieces) to be stored on the chessboard. For now, I dont want to check whether or not the piece is a valid chess piece, but I want to make sure that the placement is valid (i.e. when prompted to place a piece and the user chooses an invalid coordinate, the program will tell the user that its wrong). Otherwise, if the coordinate is right, it will store the string, which I will use another class to print the string(s) and output them, as well as where they are placed, to the user. Since it is a chess board, I am trying to convert 8x8 to 8 followed by a character from a-g.
Heres what I have so far:
public class ChessBoard {
public static void main(String[] args) {
char rows = 'a';
String spot;
int[][] grid = new int[8][8];
for (int i = 0; i < grid.length; i++, rows++) {
for (int col = 0; col < grid[i].length; col++) {
System.out.print(rows + "" + (col + 1) + " ");
}
System.out.println();
}
}
}
This prints the layout of the chessboard, but I am not sure how to ask the user for a string in a valid coordinate, say, e5, which can then be printed in another class.
I would want my expected output to be something like:
Enter a coordinate: a5
Enter a piece to be placed here: Queen
Continue until the user wishes to see what they have placed:
You have placed a Queen at a5
Any help would be appreciated, thanks!
To get the position from the user, you can use something like
// only once, to initialize the scanner
Scanner scanner = new Scanner(System.in);
// each time you need input from the user
String input = scanner.next();
To ask for a position, you can check whether the input matches what you expect, and request a new input otherwise:
String input = null; // will be changed to a valid position
boolean iLikeThisInput = false; // will be true if position is valid
while ( ! iLikeThisInput) {
System.out.println("Enter a coordinate (for example, a5): ");
input = scanner.next();
iLikeThisInput = input.matches("[a-g][1-8]"); // this is a regular expression
};
// now we now that the input is valid
int col = (int)(input.charAt(0) - 'a'); // 'a' is column 0: 'a' - 'a' = 0.
int row = (int)(input.charAt(1) - '0'); // '0' is row 0: same trick
Regular expressions are probably new for you (if you are new to programming), but are very powerful to check if text matches a certain pattern, and found across all major programming languages.
The trick of substracting character codes (last 2 lines) works because the characters codes for digits 0123456789 and those for the alphabet abcd... are in numerical/alphabetical order, so that writing (int)('b'-'a') is the same as writing 1.
You will just be missing the code to get the piece. A regular expression for a lot of words can be built easily by using |:
input.matches("Bob|Robert|Rob"); // matches only Bob or Robert or Rob
The final piece is to convert from integers to piece-names and vice-versa. I recommend writing two methods:
public static String pieceToName(int piece) { /**/ }
and
public static int nameToPiece(String name) { /**/ }
Using the switch statement, you can quickly implement both with your preferred encoding:
switch(name) {
case "Queen": return 9;
case "Pawn": return 1;
...
}
Note that if you start to build an actual chess-playing program, you will have to distinguish between white and black pieces. One way of doing it is to use positive numbers for one color, and negative for the other.
Good luck with your program!

How to take 2 letters from input (ignoring white chars and can't use arrays)

The exercise looks simple get, get the first 2 letters from the input no matter the position on the string, it also asks to stop the program if the user doesn't put two letters (Uper or Lower case ... users choice).
I tried some stuff but the program never works right, I tried to search up a solution but couldn't find anything help full to java...
public static void main (String [] args) {
System.out.print ("2 Letras? ");
Scanner s = new Scanner(System.in);
char L1 = s.next().charAt(0);
int l1 = L1;
char L2 = s.next().charAt(1);
int l2 = L2;
char M1, M2;
if (l1<63 || l2<63 || l1>90 || l2>90 || l1<95 || l2<95 || l1>122 || l2>122)
return;
else{
if (l1>96)
M1 = (char)(l1 + 32);
else
M1 = (char)(l1);
if (l2>96)
M2 = (char)(l2 + 32);
else
M2 = (char)(l2);
}
System.out.println("" + M1 + M2);
Is expected to get the 2 letters from the user in Upercase in the end...
scanner.next().trim().substring(0, 2).toUpperCase()
Having a scanner, you take the whole input line by scanner.next(), - the result is a user input string. The subsequent next() call will wait for the next input line, wich does not look algoritmically correct.
To cut heading and tailing whitespace chars use String::trim
To cut first two symbols from the user input, use String::substring method
better way to get your char uppercased is String::toUpperCase.
So, the result of this snippet is first to chars of a user input, turned to upper case

Trying to create an Acronym out of user input

Hello I am working on an assignment and I'm running into issues I was hoping for a little direction...
The purpose is to have user input a phrase and create an acronym out of that phrase. Anything over three words will be ignored.
I'm having issues with the acronym part, I am able to get the first character and figured that I would loop through the user input and grab the character after a space, but that is not working. All I am getting is the first character, which is obvious because I grab that first, but I can't figure out how to "save" the other two characters. Any help is greatly appreciated.
*********UPDATE************************
So thanks to an answer below I have made progress with using the StringBuilder. But, now if I enter "Your Three Words" the Output is: YYYYYTYYYYYWYYYY
Which is progress but I can't understand why it's repeating those first characters so many times??
I edited the code too.
*********UPDATE*****************************
public class ThreeLetterAcronym {
public static void main(String[] args) {
String threeWords;
StringBuilder acronym = new StringBuilder();
Scanner scan = new Scanner(System.in);
System.out.println("Enter your three words: ");
threeWords = scan.nextLine();
for(int count = 0; count < threeWords.length(); count++) {
acronym.append(threeWords.charAt(0));
if(threeWords.charAt(count) == ' ') {
++count;
acronym.append(threeWords.charAt(count));
}
}
System.out.println("The acronym of the three words you entered is: " + acronym);
}
}
You can't save the other characters because char is supposed to store only one character.
You can use a StringBuilder in this case
StringBuilder acronym = new StringBuilder();
Then in your loop simply replace it with
String[] threeWordsArray = threeWords.split(" ");
for(String word : threeWordsArray) {
acronym.append( word.substring(0, 1) );
}
**updated
You store the character at the current index in space:
char space = threeWords.charAt(count);
Then you compare the value of space with the integer value 3:
if(space < 3)
This will almost certainly never be true. You are asking for the numeric value of a character. Assuming it is a letter it will be at least 65. I suspect that your intention is to store something different in the variable space.

Trouble in getting proper string input

I am writing a method in Java in which the user is supposed to enter a license plate for a car. The fist two signs must be capital letters, the third sign must be a digit between 1 and 9, and the last 4 digits must be digits between 0 and 9. If the user does not enter this properly, an error message should appear, and the user will be asked to input the license plate again.
After testing the problem I have discovered that if I deliberately make many different mistakes over and over, and then finally enter the license plate correctly, the program still informs me that my input is wrong. I am having a hard time knowing how to construct this, since it is supposed to take into account so many possible errors. My code presently looks like this for the method in question:
char sign;
System.out.print("License plate: ");
licensePlate = input.next();
for (int index = 0; index < 2; indeks++) {
sign = licensePlate.charAt(indeks);
while (sign < 'A' || sign > 'Z') {
System.out.println(licensePlate + " is not a valid license plate (two big letters + five digits where the first digit can not be 0)");
System.out.print("License plate: ");
licensePlate = input.next(); }
}
while (licensePlate.charAt(2) < '1' || licensePlate.charAt(2) > '9') {
System.out.println(licensePlate + " is not a valid license plate (two big letters + five digits where the first digit can not be 0)");
System.out.print("License plate: ");
licensePlate = input.next(); }
for (int counter = 3; counter < 7; counter++) {
sign = licensePlate.charAt(teller);
while (sign < '0' || sign > '9') {
System.out.println(licensePlate + " is not a valid license plate (two big letters + five digits where the first digit can not be 0)");
System.out.print("License plate: ");
licensePlate = input.next(); }
}
carObject.setLicensePlate(licensePlate);
If anyone can help me writing this properly I would be extremely grateful!
The problem is that you're taking new input every so often, but then not starting again. It would be worth having a separate method to perform the test, like this:
boolean gotPlate = false;
String plate = null;
while (!gotPlate) {
System.out.print("License plate: ");
plate = input.next();
gotPlate = checkPlate(plate);
}
carObject.setLicensePlate(plate);
Now put the rest of your logic into the checkPlate method:
static boolean checkPlate(String plate) {
// Fixed typos here, by the way...
for (int index = 0; index < 2; index++) {
char sign = plate.charAt(index);
if (sign < 'A' || sign > 'Z') {
System.out.println(plate + " is not a valid license plate " +
"(two big letters + five digits where the first digit" +
" can not be 0)");
return false;
}
}
// Now do the same for the next bits...
// At the end, if everything is valid, return true
return true;
}
I'll leave you to do the checking for '0' etc - but hopefully you can see the benefits in structuring the "testing" part separately from the "getting input" part.
EDIT: Original answer...
Sounds like you want a regular expression:
Pattern pattern = Pattern.compile("[A-Z]{2}[1-9][0-9]{4}");
Full sample:
import java.util.regex.*;
public class Test {
private static final Pattern PLATE_PATTERN =
Pattern.compile("[A-Z]{2}[1-9][0-9]{4}");
public static void main(String args[]) {
checkPlate("AB10000");
checkPlate("AB10000BBB");
checkPlate("AB1CCC0BBB");
}
static void checkPlate(String plate) {
boolean match = PLATE_PATTERN.matcher(plate).matches();
System.out.println(plate + " correct? " + match);
}
}
Of course, that doesn't tell you which bit was wrong. It also doesn't help you work out what was wrong with your original code... see earlier part.
Don't use a character based approach. Take the whole string and use the regex list above and either fail or pass it as a one time operation. You don't need that level of control here to get a pass/fail result.
HTH,
James
You should really use a regular expression for this.
However, if you want to fix the problem with your code: the problem with your approach is that you are asking for input again after you've done some validation.
For example, if the first two characters are correct, the second loop will validate the input single-handedly. If that's wrong and it asks for input again, the user could input the first two characters incorrectly and that check won't be done because the code will have passed the first stage and is now only checking the second stage.
If you were to continue with your approach, you should make one large loop which would repeat if anything is wrong in the input and do all of the checks again in order.

Categories