I'm learning Java. I'm building this Palindrome recognizer and using two arrays with chars, I think I got a good implementation with other things I've found around but I'm breaking my head to understand why it's not working as intended so far. What is happening:
"A Santa at Nasa", palindrome, checks as a palindrome.
"I don't know, anything", not a palindrome, checks as not a palindrome.
"Not a palindrome", not a palindrome, checks as a palindrome.
I basically need some help to understand where exactly I got it wrong on my code. Thanks!
/*
"A Santa at Nasa" is an example of palindrome.
*/
import java.util.Scanner;
public class Palindrome
{
public static void main (String[] args)
{
boolean isPalindrome = false;
Scanner kb = new Scanner(System.in);
System.out.println("Enter a string:");
String userInput = kb.nextLine();
userInput = userInput.trim().replaceAll(" ", "").toLowerCase();
char[] array = new char[userInput.length()];
char[] reverseArray = new char[userInput.length()];
int i = 0;
int j = userInput.length();
do {
i++;
j--;
array[i] = userInput.charAt(i);
reverseArray[j] = userInput.charAt(j);
if (array[i] != reverseArray[j])
{
isPalindrome = false;
}
else
{
isPalindrome = true;
}
} while (j > i);
if(isPalindrome)
{
System.out.println("It's a palindrome.");
}
else
{
System.out.println("Not a palindrome.");
}
}
}
Once you've established that the input is not a palindrome, you should end the test.
Currently your algorithm is allowed to change its mind!
You are also incrementing i prematurely.
Here's the problem, you must start before the first element of the input array, because you do a i++ at the beginning of your loop:
int i = -1;
Also, the exit condition of your loop can be improved, so it exits earlier:
while (j > i && !isPalindrome);
Are you allowed to use StringBuilder? If so, you can do String reverseText = new StringBuilder(userInput).reverse().toString();
If not, why not try iterating through the array once and then compare at the end? Leave your array and reverseArray initializers as they are, but then do a for or while loop after that just faithfully copies from the userInput variable into the correct locations in both the arrays.
Then you can just use a single comparison at the end to decide what to print.
A couple things.
You should do your index changes at the end of your loop, to fix starting the lower index from 1.
With the previous change, you should start your upper index from userInput.length()-1 as that will then be the first index from the top that you check.
You should stop when you find one mismatch, as otherwise with a string of odd length, your result will always be the check of the middle character against itself (and otherwise your result will end up being the check of the two middle characters of an even string against each other).
If you'd like the full re-worked solution, I can post it, but you can probably fix it yourself from here!
Well, the problem is that you set your isPalindrome every time you check two letters. So when the last 2 letters checkt are the same, it will say it is a palindrome. Instead try this:
import java.util.Scanner;
public class Main
{
public static void main (String[] args)
{
boolean isPalindrome = true;
Scanner kb = new Scanner(System.in);
System.out.println("Enter a string:");
String userInput = kb.nextLine();
userInput = userInput.trim().replaceAll(" ", "").toLowerCase();
char[] array = new char[userInput.length()];
char[] reverseArray = new char[userInput.length()];
int i = 0;
int j = userInput.length() - 1;
while(i < j && isPalindrome) {
array[i] = userInput.charAt(i);
reverseArray[j] = userInput.charAt(j);
if (array[i] != reverseArray[j])
isPalindrome = false;
i++;
j--;
}
if(isPalindrome)
System.out.println("It's a palindrome.");
else
System.out.println("Not a palindrome.");
}
}
So now the isPalindrome boolean is set to true in the beginning, and when we find something that contradicts this (two characters that are not the same) it will set isPalindrome to false.
I have not tested this code, so there could be some other error. But this is the one I saw at first glance.
EDIT: i didn't start from the beginning of the string. And best to use a while instead of do while because the string could be empty.
Related
I have created a palindorme java program which is getting an error.the error is saying int cannot be converted to boolean.
import java.util.Scanner;
public class palindrome
{
public static void main()
{
Scanner sc = new Scanner(System.in);
int l,i;
String s,s1;
System.out.println("Enter your string");
s = sc.nextLine();
l = s.length();
for(i=0;l-i-1;i++)
{
s1 = s + s.charAt(i);
}
if(s1==s)
System.out.println("This is Palindrome");
else
System.out.println("This is not a Palindrome");
}
}
For loop condition seems wrong.
for(initial counter; condition to terminate; increase counter) {}
for(i=0; i<l; i++) {}
Along with the answer above you can try a different approach. You don't need to go all the string length to check a palindrome. A palindrome can be checked iterating half of the array length like this -
public void checkPalindrome(String strToCheck){
char[] arr = strToCheck.toCharArray();
int size = arr.length;
char [] original = Arrays.copyOf(arr,arr.length);
for (int i = 0; i < size / 2; i++) {
char temp = arr[i];
arr[i] = arr[size-i-1];
arr[size-i-1] = temp;
}
if(Arrays.equals(arr, original)) {
System.out.println("Palindrome");
} else {
System.out.println("Not a palindrome");
}
}
What are done here:
reversing the string first iterating the halfway
comparing the reversed string with the original using Arrays.equals() method.
There are quite a few things off here, first here is the fixed code:
public static void main(String [] args)
{
Scanner sc = new Scanner(System.in);
int l,i;
String s = "",s1 = "";
System.out.println("Enter your string");
s = sc.nextLine();
l = s.length();
for(i = l - 1; i >= 0; i--)
{
s1 = s1 + s.charAt(i);
}
if(s1.equals(s))
System.out.println("This is Palindrome");
else
System.out.println("This is not a Palindrome");
}
The first thing to fix was your for loop, as you saw you were getting an error. This was fixed by setting the initial i to the length minus 1, changing the loop condition to i >= 0, and using i-- to subtract 1 from i each loop.
These changes to the loop were made so that the character starting from the last position in the String is the first one being return by s.charAt(i) so you can reverse the String. I think you were attempting to do something along these lines to add the characters starting from the end to a String.
I also changed s1 = s + s.charAt(i) to s1 = s1 + s.charAt() so the correct String is being appended. (This should probably be StringBuilder however).
s and s1 now have the initial condition of "" instead of nothing.
And finally you cannot compare String equality with ==, it must be s1.equals(s).
Test Run:
Enter your string
racecar
This is Palindrome
Piglatin translator. at the end I am trying to get the location of the first vowel. Index is set to be the location of every vowel, but with pig latin you only need the location of the first vowel. When I run the program I don't always get the location of the first vowel. it seems to give me the second number and not the first.
import java.util.Scanner;
import javax.swing.JOptionPane;
public class Assignment_4_Piglatin {
public static void main(String[] args) {
Scanner userWord = new Scanner(System.in);
System.out.println("K. Caleb Swallow");
System.out.println("Welcome to the Pig Latin Translator!");
boolean run = true;
while (run) {
System.out.println("Please enter a word(or press Q to quit):");
String firstLetter = "something";
String firstVowel = "test";
String word = userWord.next();
String vowels = "aeiou";
if (word.equals("Q")) {
System.exit(0);
}
firstLetter = Character.toString(word.charAt(0));
if (firstLetter.equals("a") || firstLetter.equals("e") || firstLetter.equals("i") || firstLetter.equals("o") || firstLetter.equals("u")) {
System.out.println(word + "way");
} else {
for (int index = 0; index < word.length(); index++) {
if (vowels.contains(String.valueOf(word.charAt(index)))) {
System.out.print(index);
String firstNumber = Integer.toString(index);
firstVowel = Character.toString(firstNumber.charAt(0));
}
}
}
System.out.println(firstVowel);
The example seems to have some redundant code in if..else condition. If you want to print the first vowels then you can do it with a simple for loop, e.g.:
String word = userWord.next().toLowerCase();
String vowels = "aeiou";
for(int i=0 ; i<word.length() ; i++){
if(vowels.contains(String.valueOf(word.charAt(i)))){
System.out.println(word.charAt(i));
break;
}
}
Please note that you need to do toLowerCase on the actual word in order for contains to work.
There are a few problems I can see off the bat, but the one that is likely causing this error is in these lines:
String firstNumber = Integer.toString(index);
firstVowel = Character.toString(firstNumber.charAt(0));
Think about what this is doing. First, you are making a String out of the index value, then you are saying that the first vowel is at the 0th index of that string.
Think of this example: hello
The program will run and assign "4" to firstNumber and firstVowel which isn't what you want.
However, if you only have one vowel, your program will "work".
What happens if you have over ten vowels? I know this isn't a realistic example, but say it happens. Your program will assign the index of the last vowel to firstNumber (say it's 15), then it will assign the first character of that to firstVowel (1). This doesn't make much sense at all, does it, especially if you don't have a vowel in index 1.
The main problem you are encountering for words less than 10 letters in length is that you are not just outputting the second number, you are outputting the last one. One way I like to deal with this is to go through the code and put in print statements where I'm not sure what a certain value is. For example, I'd put another print statement in your loop which tells you what letter you're looking at, like so:
System.out.println("LETTER: "+ String.valueOf(word.charAt(index)));
This will help you avoid confusion. The proper way to do this problem would be to use a break statement, such as in Darshan's answer. Alternatively, you could use the properties of the for loop:
firstVowel = "";
for (int index = 0; index < word.length() && firstVowel == ""; index++) {
CODE
}
Note that the second part of the for loop is a conditional statement. You already know that this can be used to cycle through the word's characters, but you can insert any logical statement there that you want. For this example, I set the default value of firstVowel to "" (setting it to null is a faux-pas, but that's another story). Then, each time the loop runs, it checks to see if the value of firstVowel has been changed, which will of course happen on the first time a vowel is run through the loop.
So in short, you need to modify the two lines at the beginning of my post and you need to find a way to break your loop when you find the first vowel. One solution has been given here, and another in Darshan Mehta's post.
public static void main(String[] args) {
Scanner userWord = new Scanner(System.in);
System.out.println("K. Caleb Swallow");
System.out.println("Welcome to the Pig Latin Translator!");
boolean run = true;
while (run) {
System.out.println("Please enter a word(or press Q to quit):");
String firstLetter = "something";
String firstVowel = "test";
String word = userWord.next();
ArrayList<Character> vowels = new ArrayList<>();
vowels.add('a');
vowels.add('e');
vowels.add('i');
vowels.add('o');
vowels.add('u');
if (word.equals("Q")) {
System.exit(0);
}
firstLetter = Character.toString(word.charAt(0));
if (firstLetter.equals("a") || firstLetter.equals("e") || firstLetter.equals("i") || firstLetter.equals("o") || firstLetter.equals("u")) {
System.out.println(word + "way");
} else {
for (int index = 0; index < word.length(); index++) {
char indchar = word.charAt(index);
if (vowels.contains(word.charAt(index))) {
System.out.println(index);
firstVowel = Character.toString(word.charAt(index));
System.out.println(firstVowel);
index = word.length();
}
}
}
}
}
This is how I would do it. I changed the vowels String to an ArrayList so you can easily check if the char in the String word with the index is a vowel and the code works absolutely fine. It returns you the index where the first vowel is and what vowel it is.
I am new to java and am trying to create a palindrome word program, to check if the word backwards is the same.
public static void isPalindromeWord(){
Scanner input = new Scanner (System.in);
System.out.print("Enter a word to check: ");
String word = input.next().toLowerCase();
String reversed = new StringBuffer(word).reverse().toString();
int len = word.length();
for(int x = 0; x < len ; x++){
if(word.charAt(x) == reversed.charAt(x)){
System.out.println("True");
}else{
System.out.println("False");
}
}
}
Please excuse if I've done anything wrong, I have only started learning today.
My problem is :
With the current it outputs True for something such as "otto" which is a palindrome. But it also does True for "oplko" which isn't. So I know that it only checks the first and last letters but I thought that with the for loop it will go through each letter?
Can someone be kind enough to explain where I am going wrong and suggest how to fix it? The reason I am using a for loop is because the task is requiring me to do so.
You are very close to the solution. Since you have already reversed the string you can check if they are equal
new StringBuffer(word).reverse().equals(word);
Edit: Added one more solution for using loop
What you are doing in the loop is mostly correct. You are getting True for oplko is because you are not exiting the loop when the word.charAt(x) == reversed.charAt(x) condition fails. This can be fixed by
public static void isPalindromeWord() {
Scanner input = new Scanner(System.in);
System.out.print("Enter a word to check: ");
String word = input.next().toLowerCase();
String reversed = new StringBuffer(word).reverse().toString();
int len = word.length();
for (int x = 0; x < len; x++) {
if (word.charAt(x) != reversed.charAt(x)) {
System.out.println("False");
return;
}
}
System.out.println("True");
}
there are a lot of ways to do what you want (including Anthony C's very elegant answer), but here is a simple fix to make yours work :
public static void isPalindromeWord(){
Scanner input = new Scanner (System.in);
System.out.print("Enter a word to check: ");
String word = input.next().toLowerCase();
//you don't really need to get a reverse here
//String reversed = new StringBuffer(word).reverse().toString();
int len = (int)(word.length() / 2);//only check half (and not evnt the middle one for odd numbers
boolean isPalindrom = true;
for(int x = 0; x < len ; x++){
if(word.charAt(x) != word.charAt(word.length() - 1 - x)){
isPalindrom = false;
//at least one difference, this is not a palindrome
break;
}
}
if(isPalindrom)
System.out.println("True");//the for wasn't broken
else
System.out.println("False");
}
public static void isPalindromeWord(){
Scanner input = new Scanner (System.in);
System.out.print("Enter a word to check: ");
String word = input.next();
String reversed = input.next();
char c[]=word.toLowerCase().toCharArray();
char d[]=reversed.toLowerCase().toCharArray();
if(word.length() != reversed.length()) System.out.print("False ");
Arrays.sort(c);
Arrays.sort(d);
if(Arrays.equals(c,d)) System.out.print("True ");
else System.out.print("False ");
}
Just to describe where you have a mistake. You are writing in console on every step of loop, doesn't matter which result of comparing do you have.
boolean isPolindrom = true;
for(int x = 0; x < len ; x++){
isPolindrom = (word.charAt(x) == reversed.charAt(x)); //compare chars and store result into variable
if (!isPolindrom) { //if chars are different break a loop, because word is already not a polindrom
break;
}
}
System.out.println(isPolindrom); //output result
Solution from #AnthonyC is really better
import java.util.Scanner;
import java.util.Stack;
public class Stack_1 {
public static void main(String[] args) {
String val;
Scanner input = new Scanner(System.in);
System.out.println("Enter Text: ");
val = input.nextLine();
push(val);
}
public static void push(String str) {
Stack<Character> stk = new Stack<Character>();
for (int i = 0; i < str.length(); i++) {
stk.push(str.charAt(i));
}
System.out.println(stk);
String reverseString = "";
String original = "";
int length = original.length();
for (int i = length - 1; i >= 0; i--)
reverseString = reverseString + original.toUpperCase().charAt(i);
if (original.toUpperCase().equals(stk))
System.out.println("The string is a palindrome.");
else if (reverseString.toUpperCase().equals(stk))
System.out.println("The string is not a palindrome.");
}
}
Can anyone help me out. I didn't know where I went wrong. The question was to create a stack (Character), and display the text where it is a palindrome or not. The user had to enter input.
P.S This was one of my lab test.
If I followed the code correctly, the problem appears to be that the OP is comparing a String object (either original or reverseString) to Stack<Character> object.
So, the probable failure is the incorrect attempted comparison of a String object to a Stack object.
I think there is a 2nd failure in the if/else if logic given that an example input of "cool" is not a palindrome, but no output is produced in such a case.
EDIT: while the OP code does attempt to adjust for the case of the entered data (not given in the question as to whether that is a requirement or not), it does not account for spaces or other punctuation. According to the entry on Wikipedia about Palindromes, punctuation is also usually ignored. Again, whether being concerned about spaces, periods, dashes, etc. was part of the exercise is not defined in the question. The question is a bit under specified in terms of full requirements.
I would think a solution using a stack would take a String, push it by character to a Stack (probably correcting for case and stripping out all punctuation at that time), and then do a comparison by popping from the Stack. I think the OP code is missing part of the requirement in using a Stack.
Example code to have only characters on the Stack. There are other approaches, of course:
// push by character onto the stack; use only
// characters, and convert to lower case
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ) {
stk.push(Character.toLowerCase(c));
}
}
Example to remove all non characters from a check String:
// convert out comparison String to lower case and remove
// all non letters
String chk = str.toLowerCase().replaceAll("[^a-z]", "");
Example loop to use the Stack to check against the String:
// assume we have a palindrome
boolean palindrome = true;
// counter across the String
int i = 0;
// loop while there is more on the stack and we haven't
// failed our test
while (! stk.isEmpty() && palindrome) {
Character c = stk.pop();
palindrome = (c == chk.charAt(i++));
}
Sample Test Data:
cool is a palindrome: false
mom is a palindrome: true
Never odd or even is a palindrome: true
A man, a plan, a canal - Panama! is a palindrome: true
For a class project, we have to create a hangman game in Java (we're starting off with object oriented programming, so this is getting us used to it) and I have the class file then the main file.
Everything's working great, but I want one of my methods in the class file to tell the player if they've already guessed a particular character.
Basically, the method uses a for loop to add the guessed characters into a character array, and every time the player guesses it checks to see if that character is there (if it is, it breaks out of the loop) and if not, and the index value is 0 (this means it's unwritten, right?) it will write the character that was guessed to that index value.
The only other thing that I don't think is self explanatory in the code, is that if the player has yet to make any guesses, it makes the first value the guess, so it has something to start with in the array.
Any help would be appreciated, and if anyone has any input on how to improve my code or whatever, I'd be happy to hear that as well. Thanks so much. :)
public void makeGuess(char c) {
boolean alreadyGuessed = false, anyMatches = false;
matches = 0;
guesses++;
if (guesses == 1) {
guessedChars[0] = c;
}
for (int i = 0; i < guessedChars.length; i++) { //it goes through it and will see that it was already guessed
if (guessedChars[i] == c) {
alreadyGuessed = true;
break;
}
else if (guessedChars[i] != c && guessedChars[i] == 0) {
guessedChars[i] = c;
}
}
if (alreadyGuessed == false) {
for (int i = 0; i < word.length; i++) {
if (word[i] == c) {
anyMatches = true;
matches++;
disguisedWord[i] = c;
}
}
}
if (anyMatches == true) {
System.out.println("You guessed correctly!");
System.out.println("There were " + matches + " matches.");
}
else if (alreadyGuessed == true) {
System.out.println("You already guessed this letter, derp.");
}
else {
System.out.println("Sorry, that character is not in the word to be guessed.");
wrongGuesses++;
}
// for (int i = 0; i < guessedChars.length; i++) {
// System.out.print(guessedChars[i] + " ");
// }
}
MAIN METHOD:
import java.util.Scanner;
class HangmanDemo {
public static void main(String[] args) {
//Object initialization
Scanner keyboard = new Scanner(System.in);
Hangman word = new Hangman("jordan");
//Variable declaration
char letterGuess;
int limit;
//Interact with user
System.out.print("What would you like the limit of guesses to be: ");
limit = keyboard.nextInt();
//BEGIN ZE GAME
while (word.isFound() == false && word.getWrongGuessCount() <= limit) {
System.out.println();
System.out.print("Letter guess: ");
letterGuess = keyboard.next().charAt(0);
word.makeGuess(letterGuess);
System.out.println(word.getDisguisedWord());
}
if (word.getGuessCount() == limit) {
System.out.println("\nSorry, too many guesses.");
}
else {
System.out.println("\nCongratulations! You succesfully solved the word!");
}
}
}
So, check this out:
First time you call the method, both alreadyGuessed and and anyMatches will stay false... and that's obviously not good.
Second: OOP is NOT procedural P. More concretely: a method is not supposed to do as many things as you do. A method should have a lot of explaining to do it if plans to be larger than 10 lines. That's so full of language constructs you can't go over it fast. Split your code... less local variables, more methods.
Hope that helps.
One way to keep track of guesses would be to use either a boolean or char array (to correspond to the cardinal letter guessed; a=0, b=1, etc).
The main problem I'm seeing is in your looping logic.
This will always be true the first time because guessedChars[0] will be equal to the first entry added and you add the first entry before checking if a letter was guessed.
if (guessedChars[i] == c) {
alreadyGuessed = true;
break;
}
Also, you don't tell us how guessedChars[] is defined. Depending on how you did this you might have problems with the whole thing given that the loop is driven off of guessedChars.length and assuming that an unassigned value would be 0. The big thing I notice is that you don't break after you have determined that the letter has not yet been guessed. You at a minimum need to do this otherwise all other elements after guessedChars[i] will also be set to that guessed letter. I do recommend perhaps using a different type of loop though.
bool searchingForLetter = true;
do
{
//.... Your Logic
//.... searchingForLetter = false when you have either found the letter
//.... or placed the letter in the array
//.... or reached the end of the array
} while(searchingForLetter)
One possible solution is to use the integer value of an char, because every letter is represented by a number. For the ANSI-Standard it is useful to know, that the common letters starting a number 65 for 'A' up to 90 for 'Z'. From 97 up to 122 you will find the small letters.
You need a boolean array of 25, every value stand for one letter. Here is some code to demonstrate the functionality:
boolean[] guessedChars = new boolean[25];
char[] test = "HELLO".toCharArray();
for (char element : test) {
System.out.println(element);
System.out.println((int) element);
if (guessedChars[element - 65] == false) {
guessedChars[element - 65] = true;
} else {
System.out.println("You already guessed this letter, derp.");
}
}
'Hello' is the example string, to get the right position in the array you have to substract 66 from the element integer value. An 'A' with the value of 65 will be stored in guessedChars[0]. It is easy to extend for small letters for the hangman game, because you can changed the String to upper case with the toUpperCase()-method before checking.