Using boolean to exit loops and then redo the loops - java

I'm fairly new to Java, so I don't know too many fancy stuff and I'm kind of stuck.
What I need to do is, take a text file; import the content into an ArrayList; check each line for a specific Char that is between two "#"; then check each line in the ArrayList again to see if one of the lines already has that Char; if it does, then I need to re-enter the whole String line and re-check it; and if it doesn't, then I need to put it at the bottom of the ArrayList and into the text file.
So far, I've gotten to the part where I need to check if the entered line's Char is repeating, but I can only do it once. If, for example, I enter it again I would get an IndexOutOfBoundsException because of one of the loops. So, I figured I'd use a boolean to exit the loops and re-enter them, but unfortunately, after entering the whole String once, it asks me to do it again in order to repeat the process because I'm exiting and entering the wrong loop, but I can't seem to figure out which.
ArrayList<String> Prices = new ArrayList<String>();
try (BufferedReader br = new BufferedReader (new FileReader("file.txt"))){
String CurrentLine;
while ((CurrentLine = br.readLine()) != null){
Prices.add(CurrentLine);
}
}catch (IOException e) {
e.printStackTrace();
}
boolean CheckSequence = true;
boolean Redo = false;
String StringArrayPrices[] = new String[Prices.size()];
Scanner sc = new Scanner (System.in);
while (CheckSequence == true){
System.out.println("Insert product in the following format, 'Product#Letter#Number': ");
String ProductString = sc.nextLine();
char ProductArray[] = ProductString.toCharArray();
for (int i = 0; i < Prices.size(); i++){
StringArrayPrices[i] = Prices.get(i);
char CharArrayPrice[] = StringArrayPrices[i].toCharArray();
for (int j = 0; j < CharArrayPrice.length && Redo == false; j++){
if (CharArrayPrice[j] == '#' && CharArrayPrice[j+2] == '#'){
char TemporaryLetter = CharArrayPrice[j];
for (int k = 0; k < ProductArray.length && Redo == false; k++){
if (ProductArray[k] == '#' && ProductArray[k+2] == '#'){
char TemporaryLetter2 = ProductArray[k];
if (TemporaryLetter == TemporaryLetter2){
System.out.println("The letter is repeating. Enter product again or exit by writing '-1': ");
ProductString = sc.nextLine();
if (ProductString == "-1"){
CheckSequence = false;
}
Redo = true;
}
if (TemporaryLetter != TemporaryLetter2){
Prices.add(ProductString);
}
}
}
}
}
}
}
Right now, when I re-enter the String, I'm greeted with the first message ""Insert product in the following format, 'Product#Letter#Number': "", instead of the ""The letter is repeating. Enter product again or exit by writing '-1': "".
The first line should only show up when I'm entering a completely new String instead of when the previous one's repeating.
I hope I didn't make this too confusing.

All of the loops is not the way to go.
I'm not entirely sure of the requirement, but I think this meets it.
Note that you should probably define a Product class to encapsulate much of this.
List<String> prices;
Set<String> letters;
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
prices = reader.lines.collect(Collectors.toList());
}
letters = prices.stream.map(p -> getLetter(p)).collect(Collectors.toSet());
Scanner scanner = new Scanner(System.in);
boolean shouldContinue = true;
while (shouldContinue) {
System.out.println("Enter Product");
String product = scanner.nextLine();
if (product.equals("-1")) {
shouldContinue = false;
} else {
String letter = getLetter(product);
if (letters.contains(letter) {
System.out.println("Repeat. Re-enter");
} else {
prices.add(product);
letters.add(letter);
}
}
}
with the helper
private String getLetter(String s) {
return s.split("#")[1]; //Or use the appropriate regex to extract the letter.
}
which could use some error handling.
To avoid java 8's streams, You can use the same code you used in the question to build prices and
Set<String> letters = new HashSet<>();
for (String price : prices) {
letters.add(getLetter(price));
}

Related

Java Poem Palindrome Checker: Iterate through array matching elements in order

Currently trying to program a poem Palindrome checker. This is not for palindromes specifically, but that the array has words in the same order both ways. For example the following is a poem palindrome
Life-
imitates nature,
always moving, traveling continuously.
Continuously traveling, moving always,
nature imitates
life
My issue is iterating through the array to match the first and last elements, as currently it compares things in the wrong order.
My code is as follows:
import java.util.Scanner;
import java.io.*;
public class WordPalindromeTest {
public static void main(String[] args) {
System.out.println("This program determines if an entered sentence/word poem is a palindrome.");
Scanner input = new Scanner(System.in);
System.out.println("Please enter a string to determine if it is a palindrome: ");
while(input.hasNextLine()) {
String palin = input.nextLine();
if(palin.equals("quit")) {
break;
}
else {
boolean isPalin = isWordPalindrome(palin);
if(isPalin == true) {
System.out.println(palin + " is a palindrome!");
}
else
System.out.println(palin + " is NOT a palindrome!");
}
}
System.out.println("Goodbye!");
input.close();
}
public static boolean isWordPalindrome(String s) {
boolean isWordPal = false;
String lowerCase = s.toLowerCase();
String replaced = lowerCase.replaceAll("[^a-zA-Z0-9\\s]", "");
String words[] = replaced.split(" ");
for(int i = 0; i < words.length; i++) {
for(int j = 0; j < words.length; j++) {
if (words[i].equals(words[j]) && i != j) {
isWordPal = true;
}
else
isWordPal = false;
}
}
return isWordPal;
}
}
With the specific point in question being
public static boolean isWordPalindrome(String s) {
boolean isWordPal = false;
String lowerCase = s.toLowerCase();
String replaced = lowerCase.replaceAll("[^a-zA-Z0-9\\s]", "");
String words[] = replaced.split(" ");
for(int i = 0; i < words.length; i++) {
for(int j = 0; j < words.length; j++) {
if (words[i].equals(words[j]) && i != j) {
isWordPal = true;
}
else
isWordPal = false;
}
}
return isWordPal;
}
I am confused on how to properly set up the loop to compare the right elements. It should compare the first element to the last, the second to the second to last, etc. until the loop is finished. I realize I have it compare the first to the entire array before moving on.
This seems like a homework assignment so I won't give you a working solution. But this of it like this:
-You don't need two loops. You only need to compare the first to the last, the second to the second to last, etc. (Hint: if you subtract i-1 from the length of the Array you'll get the corresponding element to i that you need to compare to). Also you only need to iterate over half of the length of the Array
-If ever isWordPal becomes false, you need to return false. Otherwise it might get overwritten and at the end it will return true.

Not sure why array goes out of bounds JAVA

I'm getting an Array Index Out of Bounds exception on the String weapon = dataz[1]; line at runtime. I'm not sure what is causing this as this is nearly the same code I've used on previous assignments. Any logic as to why this is happening would be greatly appreciated!
public Hero[] getHeroes(){
String file = getFilePath();
Hero[] heroPower = new Hero[5];
int i=0;
try{
Scanner data = new Scanner(file);
while(data.hasNextLine() && i < 5)
{
String next = data.nextLine();
if(!next.trim().isEmpty())
{
String[] derp = next.split(",");
String name = derp[0];
String weapon = derp[1];
int attackPoints = Integer.parseInt(derp[2]);
heroPower[i] = new Hero(name,weapon,attackPoints);
i++;
}
}
data.close();
} finally {
}
return heroPower;
}
}
Your next string probably doesn't split. It doesn't have a , and you're not checking for that option.
Your code processes empty lines correctly, but it fails when the input does not have at least three tokens: it assumes that derp[0], derp[1], and derp[2] are valid, but the validity depends on the input.
You can fix it by checking the number of tokens that you get back from next.split:
String next = data.nextLine();
String[] derp = next.split(",");
if(derp.length >= 3) {
...
}
This condition also covers the situation when the trimmed next is empty, so a separate check is not required.
You really need to make sure that the number of inputs you are inputting is the number of inputs you are expecting, a simple check would be to check the number of arguments in the derp array that you get from split.
public Hero[] getHeroes(){
String file = getFilePath();
Hero[] heroPower = new Hero[5];
int i=0;
try{
Scanner data = new Scanner(file);
while(data.hasNextLine() && i < 5)
{
String next = data.nextLine();
if(!next.trim().isEmpty())
{
String[] derp = next.split(",");
//This is the line to change
if(derp > 3){
String name = derp[0];
String weapon = derp[1];
int attackPoints = Integer.parseInt(derp[2]);
heroPower[i] = new Hero(name,weapon,attackPoints);
i++;
}else{
//throw an error
}
}
}
data.close();
} finally{
}
return heroPower;
}
}
The problem is most likely your input, it doesn't contain any , symbols:
String[] derp = next.split(","); // split by commas a word that has no commas so derp.length == 1
String name = derp[0]; // this is ok since length is 1
String weapon = derp[1]; // this is error
You should check derp.length before using it:
String[] derp = next.split(",");
if(!derp.length == 3) { // because name=derp[0], weapon=derp[1], attackPoints = derp[2]
// ... create name, weapon, points and assign to heroPower
} else {
System.out.println("Invalid input");
}

Reading from an array list and comparing to an input string

Basically I have been asked to create a small letters game in which the user picks some vowels and consonants and these are added to an array list, once that has happened, we have to print out the contents of the array list e.g. it could look like this, [T,S,I,L,Y,A,R,R,A] and then we prompt the player to input what words they think they can make from the given list of characters. What I am looking for some pointers on is how to make sure the user can only use they characters and also how to compare their answer to a dictionary file. The only code I have so far is reading in my dictionary file. Any help would be greatly appreciated.
try {
BufferedReader reader = new BufferedReader(new FileReader("dictionary.txt"));
String line = reader.readLine();
List<String> words = new ArrayList<String>();
while (line != null) {
String[] wordsLine = line.split(" ");
for (String word : wordsLine) {
words.add(word);
}
line = reader.readLine();
}
System.out.println("Here is your board again: " + genString + "\n");
System.out.println("Please enter your answer!\n");
} catch (Exception e) {
System.out.println(e);
}
genString is my, what would be the list of characters and I have still to place the scanner in for user input.
The basic idea is putting the characters from user input into some collection, then iterating over the characters of the word and checking against that collection.
Finally, if everything is kosher, look up the word in the dictionary.
List<Character> charsFromUser = new LinkedList<Character>();
Set<String> dictionary = new HashSet<String>();
boolean illegalCharUsed = false;
boolean done = false;
String wordFromUser = null;
// dictionary = // fill dictionary
// charsFromUser = // get chars from user
// wordFromUser = // get word from user
for (int i = 0, l = wordFromUser.length(); i < l && !illegalCharUsed; ++i) {
char c = wordFromUser.charAt(i);
if (!charsFromUser.contains(c)) {
illegalCharUsed = true;
} else {
charsFromUser.remove(Character.valueOf(c)); // remove this line if
// users may reuse letters
}
}
if (!dictionary.contains(wordFromUser)) {
if (!illegalCharUsed && charsFromUser.isEmpty()) { // isEmpty check if users
// must use all letters
System.out.println("well done");
} else {
System.out.println("you didn't use the correct characters");
}
} else {
System.out.println("not a legal word");
}

Enter Integers into an Array and terminating input before reaching limit

I'm doing a practice question in my textbook to add integers (negative and positive) into an array. I want the user to be able to terminate entering numbers into the array before it reaches the end [50].
This is what I've come up with:
The user enters the numbers which is stored in a string. If keepLooping is true and index < size of the array; it will parse token by token the string and place the number into the int array.
There must be an easier way to do this and I can't get my code working, any help would be much appreciated:
// Create Objects to use in program
Scanner keyboard = new Scanner(System.in);
int[] arrayOfNumbers = new int[50];
// Prompt for input
System.out.println("Enter upto 50 integers separated by a space.");
System.out.println("Type x to signal no more integers to enter.");
int index = 0;
boolean keepLooping = true;
while (index < arrayOfNumbers.length && keepLooping) {
String numToAdd = keyboard.nextLine();
if ( numToAdd.equals("x") || numToAdd.equals("X") ) {
keepLooping = false;
}
if ( !numToAdd.equals("x") || !numToAdd.equals("X") ) {
arrayOfNumbers[index] = Integer.parseInt(numToAdd);
}
}
// DEBUG, Print Array
for (int k=0; k < arrayOfNumbers.length; k++) {
System.out.println(arrayOfNumbers[k]);
}
You can simplify a little bit with a for loop, and break out of the loop to exit:
for (int index = 0; index < arrayOfNumbers.length; ++index) {
String numToAdd = keyboard.nextLine();
if (numToAdd.equals("x") || numToAdd.equals("X")) {
break;
}
arrayOfNumbers[index] = Integer.parseInt(numToAdd);
}
If you debugged your program step-by-step (e.g. Stepping with F6 in Eclipse), you would have noticed that index's value does not change. Quickest fix would be:
while (index < arrayOfNumbers.length && keepLooping) {
String numToAdd = keyboard.nextLine();
if ( numToAdd.equals("x") || numToAdd.equals("X") ) {
keepLooping = false;
}
if ( !numToAdd.equals("x") || !numToAdd.equals("X") ) {
arrayOfNumbers[index] = Integer.parseInt(numToAdd);
}
index++;
}
But of course, this solves just the filling-of-array issue. Then come the good practice in programming concerns, which are thoroughly covered by the rest of the answers.
int index = 0;
boolean keepLooping = true;
while (index < arrayOfNumbers.length && keepLooping) {
String numToAdd = keyboard.nextLine();
if (numToAdd.equalsIgnoreCase("x")) { // Use EqualsIgnoreCase to shorten it
keepLooping = false;
} else { // Use an else statement instead of evaluating the inverse
arrayOfNumbers[index] = Integer.parseInt(numToAdd);
}
index++; // Increment the index to avoid eternal loop and actually fill the array
}

Counting the letters (uppercase and lowercase) of a string

I have here a program that enters a paragraph and writes it into a file. After that, it should count the occurrences of each letters (case sensitive). However, it doesn't count the number of letter occurrences. I think I put the for loop in the wrong place.
import java.io.*;
import java.util.*;
public class Exercise1 {
public static int countLetters (String line, char alphabet) {
int count = 0;
for (int i = 0; i <= line.length()-1; i++) {
if (line.charAt(i) == alphabet)
count++;
}
return count;
}
public static void main(String[] args) throws IOException {
BufferedReader buffer = new BufferedReader (new InputStreamReader(System.in));
PrintWriter outputStream = null;
Scanner input = new Scanner (System.in);
int total;
try {
outputStream = new PrintWriter (new FileOutputStream ("par.txt"));
System.out.println("How many lines are there in the paragraph you'll enter?");
int lines = input.nextInt();
System.out.println("Enter the paragraph: ");
String paragraph = buffer.readLine();
outputStream.println(paragraph);
int j;
for (j = 1; j<lines; j++) {
paragraph = buffer.readLine();
outputStream.println(paragraph);
}
outputStream.close();
System.out.println("The paragraph is written to par.txt");
for (int k=1; k<lines; k++) {
paragraph = buffer.readLine();
total = countLetters (paragraph, 'A');
if (total != 0)
System.out.println("A: "+total);
//I'll do bruteforce here up to lowercase z
}
}
catch(FileNotFoundException e) {
System.out.println("Error opening the file par.txt");
}
}
}
Please help me fix the code. I'm new in programming and I need help. Thank you very much!
First, your initial reading user input is a bit of a waste since you read once then enter the for loop for the rest - this is not a problem, just a better code.
// your code
String paragraph = buffer.readLine();
outputStream.println(paragraph);
int j;
for (j = 1; j<lines; j++) {
paragraph = buffer.readLine();
outputStream.println(paragraph);
}
You can just put them in the loop:
// better code
String paragraph;
int j;
for (j = 0; j<lines; j++) {
paragraph = buffer.readLine();
outputStream.println(paragraph);
}
Then your first problem comes from the way you read the lines:
// your code - not working
outputStream.close();
for (int k=1; k<lines; k++) {
paragraph = buffer.readLine();
total = countLetters (paragraph, 'A');
Consider what happened above:
The input is already DONE, the output is already written and stream is closed - up to here everything is good
Then when you try to count the number of characters, you do: paragraph = buffer.readLine(); - what does this code do? It waits for another user input (instead of reading what's been inserted)
To fix the problem above: you need to read from what's already been written - not asking for another input. Then instead of brute forcing every character one by one, you can just put them into a list and write a for loop.
So now, you want to read from the existing file that you already created (ie. reading what WAS inputted by the user):
BufferedReader fileReader = new BufferedReader(new FileReader(new File("par.txt")));
String allCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
String aLineInFile;
// Read the file that was written earlier (whose content comes from user input)
// This while loop will go through line-by-line in the file
while((aLineInFile = fileReader.readLine()) != null)
{
// For every line in the file, count number of occurrences of characters
// This loop goes through every character (a-z and A-Z)
for(int i = 0; i < allCharacters.length(); i++)
{
// For each single character, check the number of occurrences in the current line
String charToLookAt = String.valueOf(allCharacters.charAt(i));
int numOfCharOccurancesInLine = countLetters (aLineInFile, charToLookAt);
System.out.println("For line: " + aLineInFile + ", Character: " + charToLookAt + " appears: " + numOfCharOccurancesInLine + " times " );
}
}
The above gives you the number of occurrences of every character in every line - now you just need to organize them to keep track of how many are in total for the whole file.
Code-wise, there might be better way to write this to have cleaner implementation, but the above is easy to understand (and I just wrote it very quickly).
Do everything in one loop:
for (j = 1; j<lines; j++) {
paragraph = buffer.readLine();
total = countLetters (paragraph, 'A');
if (total != 0)
System.out.println("A: "+total);
outputStream.println(paragraph);
}
You can use a HashTable for count each case sentitive letters :
final Pattern patt = Pattern.compile("A-Za-z]");
final HashMap<Character, Integer> tabChar = new HashMap<Character, Integer>(
52);
// replace : paragraph = buffer.readLine();
// Unless you use it outside, you can declare it 'final'
final char[] paragraph = "azera :;,\nApOUIQSaOOOF".toCharArray();
for (final Character c : paragraph ) {
if (Character.isLetter(c)) {
Integer tot = tabChar.get(c);
tabChar.put(c, (null == tot) ? 1 : ++tot);
}
}
Output :
{F=1, A=1, O=4, I=1, U=1, Q=1, S=1, e=1, a=3, r=1, p=1, z=1}
You can use final TreeSet<Character> ts = new TreeSet(tabChar.keySet()); to sort the characters and then get(c); them from tabChar
The previous answers would have solved your problem but another way of avoiding brute force might be to use a loop using ASCII character value.

Categories

Resources