Java algorithm palindrome& - java

/**
* #(#)palindrome1.java
*
* palindrome1 application
*
* #author
* #version 1.00 2013/11/15
*/
public class palindrome1 {
static boolean isPalindrome(String str) {
int count=0;
//check all characters of sequence is palindrome
for(int i = 0; i < str.length();i++)
{
if(str.charAt(i)!=str.charAt(str.length()-1-i))
{
return false;
}
}
//if it is return true otherwise return false
return true;
}
public static void main(String[] args) {
// TODO, add your application code
String sentence= "bob gave that pop race car to me." ;
String sentenceMax="";
String sentenceNew="";
sentence = sentence.replace( " ","");
for(int i = 0;i<sentence.length();i++)
{
for(int k=0;k<i;k++)
{
sentenceNew = sentence.substring(k,i);
if(isPalindrome(sentenceNew)&&sentenceNew.length()>sentenceMax.length());
{
sentenceMax=sentenceNew;
sentenceNew="";
}
}
}
System.out.println(sentenceMax);
}
}
The question is:t should ask a sentence from user and find the longest palindrome substring in the sentence ignoring the spaces in the sentence and print the longest palindrome substring. You MUST use the function you wrote in Part B. The sentences must be case-insensitive.
and part B is the first method named isPalindrome() in mycode.
The output should be:
racecar
but my code outputs:
e
What is wrong at my code?

You have in your code :
if(isPalindrome(sentenceNew)&&sentenceNew.length()>sentenceMax.length());
And ; is at the bad place. Since it is there it treats it as a if with an empty block, so your real block {} is calculated all the time.
It should be:
if(isPalindrome(sentenceNew)&&sentenceNew.length()>sentenceMax.length())

You are assigning a new value to sentenceMax each iteration. Try this instead
sentenceMax += sentenceNew;

Why did you not use the StringBuffer methods ?
StringBuffer.reverse() can reverse the String
after that you can search each substring in the reverted Source string using StringBuffer.indexOf(subString).
Isnt that a much simpler approach ?

Related

Java Palindrome Program (am I on track)?

I have only 6 months of Java experience (and I'm also new here) so please bear with me if things don't look entirely right in my code. Please note that it's still a work in progress. I'm trying to write a program that takes in strings and prints only the ones that are palindromes.
I'm supposed to:
- create a method named isPalindrome, which has a String parameter and
- returns a Boolean based on whether the string is a palindrome or not. Then
- modify the main method to use isPalindrome to print only the palindromes.
For example, if I type: "madam James apple mom timer", it should print "madam" and "mom".
This is basically the program I am trying to write:
Ex: Let's use the word "madam". The program will check if the first and last letters match ("madam"). If that is true, then it'll check the next letters, this time "a" and "a" ("madam). And so on and so forth.
This is the Java code I have so far:
public class Palindrome
{
private String theWord; //Error: The value of the field Palindrome.theWord is not used
public boolean isPalindrome( String theWord ) {
int firstPointer = 0;
int secondPointer = theWord.length() - 1;
for ( int i = 0; i < theWord.length( ); i++ ) {
if ( theWord.charAt[0] == theWord.charAt (theWord.length() - 1) ) { //Error: charAt cannot be resolved or is not a field
return true;
}
return false;
}
}
public static void main( String[] theWord ) {
Palindrome = new Palindrome( ); //Error: Palindrome cannot be resolved to a variable
for ( int i = 0; i < theWord.length; i++ ) {
while (firstPointer < secondPointer) { //Error: "firstPointer" cannot be resolved to a variable. "secondPointer" cannot be resolved to a variable
if ( theWord.charAt[0] == theWord.charAt (theWord.length() - 1) ) { //Error: charAt cannot be resolved to a variable or is not a field. Cannot invoke length() on the array type String[]
firstPointer++; //Error: "firstPointer" cannot be resolved to a variable
secondPointer++; //Error: "secondPointer" cannot be resolved to a variable
}
System.out.println(theWord);
}
}
}
}
Any bit of help knowing where I've gone wrong would be greatly appreciated. Please don't just give me the right code. I would like to figure this out. Thank you very much.
**EDIT: I've included the errors as comments in the code now. I'm using Eclipse by the way.
-->**EDIT 2: Okay guys. I've read most of your answers and have been able to correct most of my code so far (Thank you all so much so far). The only part I'm still having an issue with right now is this part:
if ( theWord.charAt(i) == theWord.charAt (theWord.length() - i - 1) ) {
leftPointer++;
rightPointer--;
I'm now getting a "Cannot invoke charAt(int) on the array type String[]"
and "Cannot invoke length() on the array type String[]".
Those are the only two errors remaining, then I'll test the code out. I've been trying to resolve them for a while now but I'm still not entirely sure what those errors mean.
Eclipse is suggesting that I change theWord.charAt(i) to theWord.length which is not what I want. It is also suggesting I remove "( )" from length but I don't think that's right either.
Looking at your isPalindrome method :
if ( theWord.charAt(0) == theWord.charAt (theWord.length() - 1)
here you always compare the first character to the last character. In each iteration you should compare a different pair of characters, until you find a pair that doesn't match, or reach the middle of the word.
You should use the i variable of your loop :
if ( theWord.charAt(i) == theWord.charAt (theWord.length() - i - 1)
And the return value should be the exact opposite. If you find a pair of characters that don't match, you return false. Only if the loop ends without returning false, you return true.
Okay, let's break everything down into little sizable chunks.
Input a string
Parse the string, check if it is a palindrome.
Print out the words in the string which were palindromes.
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a sentence: ");
String sentence = scan.nextLine(); // 1.
String[] words = sentence.split(" ");
for (String word : words) { // 3.
if (isPalindrome(word)) {
System.out.println(word);
}
}
}
/**
* Check if the string is a palindrome.
* #param string
* #return True if string is palindrome.
*/
public static boolean isPalindrome(String string) { // 2.
for (int i = 0; i < string.length() / 2; i++) {
if (string.charAt(i) != string.charAt(string.length() - i - 1)) {
return false;
}
}
return true;
}}
Some explanation
The method/function isPalindrome is static because we are calling it from a static context, that is the main function. If you want to use it non-statically you would place it in a class and create a object from that class. The rest should be understandable. :-)
A better isPalindrome method
The shortest way is probably just following the definition:
If you reverse the string, and it's still the same, then it's a palindrome:
public static boolean isPalindrome(String input)
{
String reverse = new StringBuilder(input).reverse().toString();
return input.equalsIgnoreCase(reverse);
}
But if there is an educational goal (?), and iterators should be used for some reason then, imho it makes more sense to iterate from the outside towards the inside of the string.
public static boolean isPalindrome(String input)
{
int length = input.length();
for (int i = 0; i < length/2 ; i++)
{
if (input.charAt(i) != (input.charAt(length-1-i))) return false;
}
return true;
}
Phrase parsing
In your example you used the input of the main String[] parameter. Here is just some information in case you wanted to split it to words manually.
Equivalent to what you got now:
String[] words = phrase.split("\\s+");
for (String word : words)
{
// do stuff
}
The split method uses a delimiter to split a String into a String[]. The delimiter \\s is a regex that represents all kinds of whitespace (not only spaces, but also tabs, new-line characters, etc ...).
But it's not perfect (and neither is your way), there can still be commas, dots and other marks in the phrase. You could filter these characters in an iteration, using the Character.isLetterOrDigit method. Alternatively, you could just perform a replace(...) to remove comma's, points and other marks. Or you could use more complex regular expressions as well.
About your code
The first error message : "The value of the field is not used".
The error message is caused by the global private field theWord, because it is never used. It's not used because you also have a parameter with the same name inside the method isPalindrom(String theWord). Whenever you reference theWord inside that method, it will always give advantage to method arguments before considering global variables.
It looks like you are stuck here with a design contradiction.
What exactly is the class Palindrome ? There are 2 options:
Is it supposed to be a toolbox like the Math class ? like boolean value = Palindrome.isPalindrome("madam");?
Or is it supposed to be an Object that you instantiate using a constructor ? like boolean value = new Palindrome("madam").isPalindrome();
Option 1: a toolbox:
public class Palindrome
{
// removed the private field theWord
// make this method static !!
public static boolean isPalindrome( String theWord ) {
...
}
public static void main( String[] theWord ) {
// remove the Palindrome object
// inside the loop check use the static method
// which does not require an object.
if ( Palindrome.isPalindrome(word))
{
}
}
}
Option 2: an object
public class Palindrome
{
// keep the private field theWord
private String theWord;
public Palindrome(String theWord)
{
// set the value of the argument to the private field
this.theWord = theWord;
}
// don't make this method static
// also you don't need the parameter any more.
// it will now use the global field theWord instead of a parameter.
public boolean isPalindrome() {
...
}
public static void main( String[] theWord ) {
// inside the loop check use an object
Palindrome palindrome = new Palindrome(word);
if ( palindrome.isPalindrome())
{
}
}
As for the errors about the firstPointer and secondPointer. You need to define and initialize those variables. I.e. put int firstPointer = 0; before the loop.
In the loop check it out this way:
boolean isPalin = true;
for ( int i = 0; i < theWord.length( )/2; i++ ) { // loop goes till half since no need to check after that
if ( !(theWord.charAt(i) == theWord.charAt (theWord.length() - 1 - i)) ) { // will check each letter with each end letter
isPalin = false;
break;
}
}
return isPalin;
Another things to add -
1 -firstPointer secondPointer are local variables to isPalindrome
2 - When u have decalared theWord as global variable there doent seems a need to pass it. You can use it within the same class.
3 - theWord in main(String[] theWord) would require you to provide input as arguments, it better you go for console input at runtime.
4 - In main you should split each word and pass it to isPalindrome. In your code you are not calling isPalindrome to check anywhere.

Removing leading zero in java code

May I know how can I remove the leading zero in JAVA code? I tried several methods like regex tools
"s.replaceFirst("^0+(?!$)", "") / replaceAll("^0*", "");`
but it's seem like not support with my current compiler compliance level (1.3), will have a red line stated the method replaceFirst(String,String)is undefined for the type String.
Part of My Java code
public String proc_MODEL(Element recElement)
{
String SEAT = "";
try
{
SEAT = setNullToString(recElement.getChildText("SEAT")); // xml value =0000500
if (SEAT.length()>0)
{
SEAT = SEAT.replaceFirst("^0*", ""); //I need to remove leading zero to only 500
}
catch (Exception e)
{
e.printStackTrace();
return "501 Exception in proc_MODEL";
}
}
}
Appreciate for help.
If you want remove leading zeros, you could parse to an Integer and convert back to a String with one line like
String seat = "001";// setNullToString(recElement.getChildText("SEAT"));
seat = Integer.valueOf(seat).toString();
System.out.println(seat);
Output is
1
Of course if you intend to use the value it's probably better to keep the int
int s = Integer.parseInt(seat);
System.out.println(s);
replaceFirst() was introduced in 1.4 and your compiler pre-dates that.
One possibility is to use something like:
public class testprog {
public static void main(String[] args) {
String s = "0001000";
while ((s.length() > 1) && (s.charAt(0) == '0'))
s = s.substring(1);
System.out.println(s);
}
}
It's not the most efficient code in the world but it'll get the job done.
A more efficient segment without unnecessary string creation could be:
public class testprog {
public static void main(String[] args) {
String s = "0001000";
int pos = 0;
int len = s.length();
while ((pos < len-1) && (s.charAt(pos) == '0'))
pos++;
s = s.substring(pos);
System.out.println(s);
}
}
Both of those also handle the degenerate cases of an empty string and a string containing only 0 characters.
Using a java method str.replaceAll("^0+(?!$)", "") would be simple;
First parameter:regex -- the regular expression to which this string is to be matched.
Second parameter: replacement -- the string which would replace matched expression.
As stated in Java documentation, 'replaceFirst' only started existing since Java 1.4 http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceFirst(java.lang.String,%20java.lang.String)
Use this function instead:
String removeLeadingZeros(String str) {
while (str.indexOf("0")==0)
str = str.substring(1);
return str;
}

java find if the string contains 2 other strings

I have 2 strings "test" "bet" and another string a="tbtetse". I need to check if the "tbtetse" contains the other two strings.
I was thinking if I could find all the anagrams of string a and and then find the other two strings in those, but it doesn't work that way and also my anagram code is failing for a lengthy string.
Could you please help with any other ways to solve it?
Assuming you're trying to test whether the letters in a can be used to form an anagram of the test strings test and bet: I recommend making a dictionary (HashMap or whatever) of character counts from string a, indexed by character. Build a similar dictionary for the words you're testing. Then make sure that a has at least as many instances of each character from the test strings as they have.
Edit: Alcanzar suggests arrays of length 26 for holding the counts (one slot for each letter). Assuming you're dealing with only English letters, that is probably less of a hassle than dictionaries. If you don't know the number of allowed characters, the dictionary route is necessary.
Check below code, it may help you.
public class StringTest {
public static void main(String[] args) {
String str1 = "test";
String str2 = "bev";
String str3 = "tbtetse";
System.out.println(isStringPresent(str1, str2, str3));
}
private static boolean isStringPresent(String str1, String str2, String str3) {
if ((str1.length() + str2.length()) != str3.length()) {
return false;
} else {
String[] str1Arr = str1.split("");
String[] str2Arr = str2.split("");
for (String string : str1Arr) {
if (!str3.contains(string)) {
return false;
}
}
for (String string : str2Arr) {
if (!str3.contains(string)) {
return false;
}
}
}
return true;
}
}
basically you need to count characters in both sets and compare them
void fillInCharCounts(String word,int[] counts) {
for (int i = 0; i<word.length(); i++) {
char ch = word.charAt(i);
int index = ch - 'a';
counts[index]++;
}
}
int[] counts1 = new int[26];
int[] counts2 = new int[26];
fillInCharCounts("test",counts1);
fillInCharCounts("bet",counts1);
fillInCharCounts("tbtese",counts2);
boolean failed = false;
for (int i = 0; i<counts1.length; i++) {
if (counts1[i] > counts2[i]) {
failed = true;
}
}
if (failed) {
whatever
} else {
something else
}
If you are generalizing it, don't forget to call .toLowerCase() on the word before sending it in (or fix the counting method).
Pseudo code:
Make a copy of string "tbtetse".
Loop through each character in "test".
Do a indexOf() search for the character in your copied string and remove it if found.
If not found, fail.
Do the same for the string "bet".
class WordLetter {
char letter;
int nth; // Occurrence of that letter
...
}
One now can use Sets
Set<WordLetter>
// "test" = { t0 e0 s0 t1 }
Then testing reduces to set operations. If both words need to be present, a union can be tested. If both words must be formed from separate letters, a set of the concatenation can be tested.

How to determine whether a string is a hash

I have to implement a Java method, which will determine, if a input string is a hash (generated by a machine) or a plain-text (written by a human).
Example:
isThisEncrypted("qwertyuiopasdfghjklzxcvbnm"); // returns true
isThisEncrypted("some normal human text"); // returns false
I thought about using the Kolmogorov-Smirnov test (jsc.goodnessfit.KolmogorovTest), which will check, if a characters in a string are from normal distribution, but I have learned, that checking only one, short string might not be conclusive.
Do you have any idea how to solve this problem in Java (preferably using a existing library)?
From your comments:
human input can be random
this method has to determin, if string comes from this method or form
user
Then there's no way to solve your problem having just the String. You need extra information.
If you're expecting Blowfish to return a String in a given format, then you're wrong. Modern encryption algorithms target high entropy, which means they have to look and feel like random.
You have stated that you only want an approximate solution (80% accuracy), that classes of the form AClassName are likely (note capitalisation) and the given sample of encrypted text has no capitals in it. So
public class Test{
public static void main(String args[]){
String[] tests=new String[5];
tests[0]="MyClass";
tests[1]="Short";
tests[2]="thsrjtyzfgnmytkzrhjstk";
tests[3]="tatm";
tests[4]="The result is good";
for(int i=0;i<tests.length;i++){
System.out.println(tests[i]+ "- Encrypted:" + isProbablyEncrypted(tests[i]));
}
}
public static boolean isProbablyEncrypted(String in){
int noOfWords= countOccurrences(in, ' ') + countCaps(in);
if (noOfWords==0){
return true;
}else{
double averageWordLength=(double)(in.length())/(noOfWords+1);
if (averageWordLength>15){
return true;
}else{
return false;
}
}
}
public static int countOccurrences(String haystack, char needle)
{
int count = 0;
for (int i=0; i < haystack.length(); i++)
{
if (haystack.charAt(i) == needle)
{
count++;
}
}
return count;
}
public static int countCaps(String in){
int caps=0;
for (int i=0; i<in.length(); i++) {
if (Character.isUpperCase(in.charAt(i)))caps++;
}
return caps;
}
}
Is this a good solution; no, does it give >80% accuracy; yes
You split your input into words and check them against a dictionary ( checking words in a dictionary ) .
From now on everything depends on your implementation. IMO, if half the words match with the dictionary, then your method should return false.

Checking to see if a string is a palindrome with String.equals()

I had a question regarding a basic program I was writing said whether a word such as racecar is a palindrome or not.
All my methods which reverse the string, strip the punctuation work but the one that determines if it is a palindrome does not.
/**
* Determines if a series of letters makes a palinedrome
*
* #param str All punctuation and spaces have been removed
* before this method is called.
* #return true if phrase is a palindrome,
* false otherwise.
*/
public boolean isPalindrome(String str)
{
String d = reverseString (str);
return( str.equals (reverseString (str) ) );
}
Okay, I'm not sure what purpose d is meant to serve in your function since it's never used but, if you want to see why your function's not working, just add debug code:
public boolean isPalindrome (String str) {
System.out.println ("DEBUG: original string = '" + str + "'");
System.out.println ("DEBUG: reverse string = '" + reverseString (str) + "'");
if (str.equals (reverseString (str)))
System.out.println ("DEBUG: returning true");
else
System.out.println ("DEBUG: returning false");
return str.equals (reverseString (str));
}
I'd bet money on there being something wrong with your reverseString function (but not much money). These debug statements should give you enough to figure out where the problem lies.
If string reverseString(String string), and all whitespace was removed then checking if something is a palindrome should be
public boolean isPalindrome(String string)
{
return string.equals(reverseString(string));
}
Granted this is case sensitive so if your palindrome definition does not care about casing, then use equalsIgnoreCase instead.
If this does not work, then you may want to check your stripping and reverseString methods again.
Your problem is the reverse string method you have not shown. If that method is working properly then your isPalindrome method should work. All you need to do is fix your reverse string method.
Java does not have a native reverse string method, and I highly recommend you write your own.
Java does, however, have a reverse method for StringBuffer and StringBuilder. StringBuilder is preferred over StringBuffer.
Use the equals method to compare your reversed string to the original string
The code should be like this:
String d = reverseString (str);
return( str.equals (d) );
You don't have to call twice reverseString()
P.S.: StringBuffer has a method that reverses a String.
I'm sure you've already submitted your homework by now, but I'm learning java and needed the practice, so here's my code for you. It uses a char array and reverses that. I'd assume the best way would be to use a StringBuilder, but the intention of your homework is probably to learn to do it yourself:
public class reverseString {
public static void main(String[] args) {
System.out.println("racecar is a palindrome: "+ isPalindrome("racecar"));
}
public static boolean isPalindrome(String str)
{
String d = reverseString (str);
return( str.equals (reverseString (str) ) );
}
private static char[] reverse(char[] input) {
int length = input.length;
char[] reversed = new char[length];
for (int i=0;i<length;i++) {
reversed[length-i-1]=input[i];
}
return reversed;
}
private static String reverseString(String input){
String reversed = new String(reverse(input.toCharArray()));
return reversed;
}
}
Output:
racecar is a palindrome: true
If anyone has any comments on why my code sucks, fire away. I'd appreciate any constructive criticism.

Categories

Resources