Given A morse String eg. aet = ".- . -" if the spaces are removed it will become an ambiguous morse string ".-.-" which can represent "aet","eta","ent","etet" etc.
the problem is to find the no.of words that the morse string without spaces can represent irrespective of the meaning of the words. The constraint is that the new word which is formed should be the same size of the input i.e "aet" = "ent" and other words like "etet" should be discarded.
i implemented a recursive solution for some reason it is not working. below is my code and thinking of converting this to DP approach to increase time efficiency. Can some one help to point out the mistake in the below code and is DP a right approach to follow for this problem? Thanks in advance!!
EDIT 1 :- The program gives me an output but not the correct one. for ex. for the morse String representing aet = ".- . -" if given without any spaces to the program ".-.-" it should give an out put "3" i.e 3 words can be formed that is of the same size as the input including the input "aet","eta","ent" but it gives me an output "1". I think there is some thing wrong with the recursive calls.
The approach used here is to simply cut the morse string in a place where first valid morse code is encountered and the repeat the process with the rest of the string untill 3 such valid morse code are found and check whether whole morse string is consumed. if consumed increment the word count and repeat the process for different values of substring size(end variable in the below code).
I hope this helps!!.Tried my best to explain as clearly as I could.
import java.util.*;
import java.io.*;
import java.math.*;
import java.text.*;
public class MorseCode2 {
static Map<String,String> morseCode;
static Map<String,String> morseCode2;
static int count = 0;
public static void main(String args[]){
String[] alpha = {"a","b","c","d","e","f","g","h","i","j","k",
"l","m","n","o","p","q","r","s","t","u","v",
"w","x","y","z"};
String[] morse = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",
".--","-..-","-.--","--.."};
morseCode = new HashMap<String,String>();
morseCode2 = new HashMap<String,String>();
for(int i = 0;i<26;i++){
morseCode.put(morse[i],alpha[i]);
}
for(int i = 0;i<26;i++){
morseCode2.put(alpha[i],morse[i]);
}
Scanner in = new Scanner(System.in);
String input = in.next();
String morseString = "";
for(int j = 0; j< input.length(); j++){
morseString += morseCode2.get(input.charAt(j)+"");
}
countPossibleWord(morseString,input.length(),0,1,0);
System.out.println(count);
in.close();
}
public static void countPossibleWord(String s,int inputSize,int start,int end,int tempCount){
if(start >= s.length() || end > s.length()){
return;
}
if(tempCount>inputSize){
return;
}
String sub = s.substring(start, end);
if(sub.length()>4){
return;
}
if(morseCode.get(sub)!=null){
tempCount++;
countPossibleWord(s,inputSize,end,end+1,tempCount);
}
else{
countPossibleWord(s,inputSize,start,end+1,tempCount);
}
if(tempCount == inputSize && end == s.length()){
count++;
}
countPossibleWord(s,inputSize,start,end+1,0);
}
}
EDIT 2 :- Thank you all for your Responses and Extremely sorry for the confusing code, will surely try to improve on writing neat and clear code. learnt a lot from your replies!!
And i also some how made the code work, the problem was I passed wrong argument which changed the state of the recursive calls. Instead of passing "tempCount-1" for the last argument in the last function call in the method "countPossibleWord" i passed "0" this altered the state. found this after running through the code manually for larger inputs. below is the corrected method
public static void countPossibleWord(String s,int inputSize,int start,int end,int tempCount){
if(start >= s.length() || end > s.length()){
return;
}
if(tempCount>inputSize){
return;
}
String sub = s.substring(start, end);
if(sub.length()>4){
return;
}
if(morseCode.get(sub)!=null){
tempCount++;
countPossibleWord(s,inputSize,end,end+1,tempCount);
}
else{
countPossibleWord(s,inputSize,start,end+1,tempCount);
}
if(tempCount == inputSize && end == s.length()){
count++;
}
countPossibleWord(s,inputSize,start,end+1,tempCount-1);
}
}
If you like to have a recursive function, you should be clear about your parameters (use as few as possible) as well as when to step down and when to go up again.
My solution would look something like
public static int countPossibleWord(String strMorse, String strAlpha, int inputSize) {
if (strMorse.length() > 0) { // still input to process
if (strAlpha.length() >= inputSize)
return 0; // String already has wrong size
int count = 0;
for (int i = 0; i < morse.length; i++) { // try all morse codes
if (strMorse.startsWith(morse[i])) { // on the beginning of the given string
count += countPossibleWord(strMorse.substring(morse[i].length()), strAlpha+alpha[i], inputSize);
}
}
return count;
} else {
if( strAlpha.length() == inputSize ) {
System.out.println( strAlpha );
return 1; // one solution has been found
} else {
return 0; // String has wrong size
}
}
}
Your morse and alpha arrays need to be static variables for this to work.
Note that there is only one situation where the recursion will step down: when there is some input left and the size limit is not reached. Then it will check for the next possible letter in the loop.
All other cases will lead the recursion to go one step up again - and when going up, it will return the number of solutions found.
Call it like this:
System.out.println(countPossibleWord(morseString, "", input.length() ));
The fact that you use a class variable instead of the returned value of the recursive function makes it extremely unclear. Even for you as #Thomas Weller said. You should clarify the possible cases when a count one more letter. I deleted eclipse, hence I coded it in C, I hope I will still help you to understand the algo :(understand char* as string)
char morse[26][5] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",
".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
int countPossibleWord(char* s, int inputSize, int start, char* buffer, int sizeBuff){
if(start == inputSize){
if(sizeBuff == 0) return 1;
else return 0;
}
char buff[sizeBuff+2]; //
strncpy(buff, buffer, sizeBuff);//
buff[sizeBuff] = s[start]; // buff = buff+s[start]
buff[sizeBuff+1] = '\0'; //
for(int i = 0; i < 26; ++i){
//run the equivalent of your map to find a match
if(strcmp(buff, morse[i]) == 0)
return countPossibleWord(s, inputSize, start+1, "", 0) + countPossibleWord(s, inputSize, start+1, buff, sizeBuff+1);
}
return countPossibleWord(s, inputSize, start+1, buff, sizeBuff+1);
}
The problem with your code is, that you don't understand it any more, because it's not clean as described by Robert C. Martin. Compare your code to the following. This is certainly still not the cleanest, but I think you can understand what it does. Tell me if you don't.
Consider this main program:
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
String morsetext = enterTextOnConsole();
MorseTable morseTable = new MorseTable();
MorseCode code = convertToMorseCodeWithoutSpaces(morsetext, morseTable);
List<String> guesses = getAllPossibleMeanings(code, morseTable);
List<String> guessesOfSameLength = filterForSameLength(morsetext, guesses);
printListOnConsole(guessesOfSameLength);
}
private static void printListOnConsole(List<String> guessesOfSameLength) {
for (String text : guessesOfSameLength) {
System.out.println(text);
}
}
private static List<String> filterForSameLength(String morsetext, List<String> guesses) {
List<String> guessesOfSameLength = new LinkedList<String>();
for (String guess : guesses) {
if (guess.length() == morsetext.length())
{
guessesOfSameLength.add(guess);
}
}
return guessesOfSameLength;
}
private static List<String> getAllPossibleMeanings(MorseCode code, MorseTable morseTable) {
MorseCodeGuesser guesser = new MorseCodeGuesser(morseTable);
List<String> guesses = guesser.guess(code);
return guesses;
}
private static MorseCode convertToMorseCodeWithoutSpaces(String morsetext, MorseTable morseTable) {
MorseCode code = new MorseCode(morseTable);
code.fromText(morsetext);
code.stripSpaces();
return code;
}
private static String enterTextOnConsole() {
Scanner scanner = new Scanner(System.in);
String text = scanner.next();
scanner.close();
return text;
}
}
and the following MorseTable class:
import java.util.HashMap;
import java.util.Map;
public class MorseTable {
private static final Map<String, String> morseTable;
private static int longestCode = -1;
static
{
morseTable = new HashMap<String, String>();
morseTable.put("a", ".-");
morseTable.put("b", "-...");
morseTable.put("c", "-.-.");
morseTable.put("e", ".");
morseTable.put("t", "-");
morseTable.put("n", "-.");
// TODO: add more codes
for (String code : morseTable.values()) {
longestCode = Math.max(longestCode, code.length());
}
}
public String getMorseCodeForCharacter(char c) throws IllegalArgumentException {
String characterString = ""+c;
if (morseTable.containsKey(characterString)) {
return morseTable.get(characterString);
}
else {
throw new IllegalArgumentException("No morse code for '"+characterString+"'.");
}
}
public int lengthOfLongestMorseCode() {
return longestCode;
}
public String getTextForMorseCode(String morseCode) throws IllegalArgumentException {
for (String key : morseTable.keySet()) {
if (morseTable.get(key).equals(morseCode)) {
return key;
}
}
throw new IllegalArgumentException("No character for morse code '"+morseCode+"'.");
}
}
and the MorseCode class
public class MorseCode {
public MorseCode(MorseTable morseTable)
{
_morseTable = morseTable;
}
final MorseTable _morseTable;
String morseCode = "";
public void fromText(String morsetext) {
for(int i=0; i<morsetext.length(); i++) {
char morseCharacter = morsetext.charAt(i);
morseCode += _morseTable.getMorseCodeForCharacter((morseCharacter));
morseCode += " "; // pause between characters
}
}
public void stripSpaces() {
morseCode = morseCode.replaceAll(" ", "");
}
public MorseCode substring(int begin, int end) {
MorseCode subcode = new MorseCode(_morseTable);
try{
subcode.morseCode = morseCode.substring(begin, end);
} catch(StringIndexOutOfBoundsException s) {
subcode.morseCode = "";
}
return subcode;
}
public MorseCode substring(int begin) {
return substring(begin, morseCode.length());
}
public String asPrintableString() {
return morseCode;
}
public boolean isEmpty() {
return morseCode.isEmpty();
}
}
and last not least, the MorseCodeGuesser
import java.util.LinkedList;
import java.util.List;
public class MorseCodeGuesser {
private final MorseTable _morseTable;
public MorseCodeGuesser(MorseTable morseTable) {
_morseTable = morseTable;
}
public List<String> guess(MorseCode code) {
List<String> wordList = new LinkedList<String>();
if (code.isEmpty()) return wordList;
for(int firstCodeLength=1; firstCodeLength<=_morseTable.lengthOfLongestMorseCode(); firstCodeLength++) {
List<String> guesses = guess(code, firstCodeLength);
wordList.addAll(guesses);
}
return wordList;
}
private List<String> guess(MorseCode code, int firstCodeLength) {
MorseCode firstCode = code.substring(0, firstCodeLength);
String firstCharacter;
try{
firstCharacter = _morseTable.getTextForMorseCode(firstCode.asPrintableString());
} catch(IllegalArgumentException i) {
return new LinkedList<String>(); // no results for invalid code
}
MorseCode remainingCode = code.substring(firstCodeLength);
if (remainingCode.isEmpty()) {
List<String> result = new LinkedList<String>();
result.add(firstCharacter); // sole result if nothing is left
return result;
}
List<String> result = new LinkedList<String>();
List<String> remainingPossibilities = guess(remainingCode);
for (String possibility : remainingPossibilities) {
result.add(firstCharacter + possibility); // combined results
}
return result;
}
}
I have pasted my own solution to it. I have followed DFS and it is giving the correct answer for the given problem statement. Please ask if there are any queries.
alpha =["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
key = [".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--",
"-..-","-.--","--.."]
dic = dict(list(zip(key,alpha)))
def morse_code(morse,count,res,char,length):
global dic
if count == length - 1:
if morse[char:] in dic:
res = res + 1
return res
word = ''
for i in range(char,len(morse)):
word = word + morse[i]
if word not in dic:
continue
else:
count = count + 1
res = morse_code(morse,count,res,i+1,length)
count = count - 1
return res
if __name__ = 'main'
inp = input()
morse = ''
for i in inp:
morse = morse + key[ord(i)-ord('a')]
result = morse_code(morse,0,0,0,len(inp))
print(result)
This question already has answers here:
Check string for palindrome
(42 answers)
Closed 7 years ago.
I want to check if a string is a palindrome or not. I would like to learn an easy method to check the same using least possible string manipulations
Using reverse is overkill because you don't need to generate an extra string, you just need to query the existing one. The following example checks the first and last characters are the same, and then walks further inside the string checking the results each time. It returns as soon as s is not a palindrome.
The problem with the reverse approach is that it does all the work up front. It performs an expensive action on a string, then checks character by character until the strings are not equal and only then returns false if it is not a palindrome. If you are just comparing small strings all the time then this is fine, but if you want to defend yourself against bigger input then you should consider this algorithm.
boolean isPalindrome(String s) {
int n = s.length();
for (int i = 0; i < (n/2); ++i) {
if (s.charAt(i) != s.charAt(n - i - 1)) {
return false;
}
}
return true;
}
For the least lines of code and the simplest case
if(s.equals(new StringBuilder(s).reverse().toString())) // is a palindrome.
Here is a simple one"
public class Palindrome {
public static void main(String [] args){
Palindrome pn = new Palindrome();
if(pn.isPalindrome("ABBA")){
System.out.println("Palindrome");
} else {
System.out.println("Not Palindrome");
}
}
public boolean isPalindrome(String original){
int i = original.length()-1;
int j=0;
while(i > j) {
if(original.charAt(i) != original.charAt(j)) {
return false;
}
i--;
j++;
}
return true;
}
}
You can try something like this :
String variable = ""; #write a string name
StringBuffer rev = new StringBuffer(variable).reverse();
String strRev = rev.toString();
if(variable.equalsIgnoreCase(strRev)) # Check the condition
Here's a good class :
public class Palindrome {
public static boolean isPalindrome(String stringToTest) {
String workingCopy = removeJunk(stringToTest);
String reversedCopy = reverse(workingCopy);
return reversedCopy.equalsIgnoreCase(workingCopy);
}
protected static String removeJunk(String string) {
int i, len = string.length();
StringBuffer dest = new StringBuffer(len);
char c;
for (i = (len - 1); i >= 0; i--) {
c = string.charAt(i);
if (Character.isLetterOrDigit(c)) {
dest.append(c);
}
}
return dest.toString();
}
protected static String reverse(String string) {
StringBuffer sb = new StringBuffer(string);
return sb.reverse().toString();
}
public static void main(String[] args) {
String string = "Madam, I'm Adam.";
System.out.println();
System.out.println("Testing whether the following "
+ "string is a palindrome:");
System.out.println(" " + string);
System.out.println();
if (isPalindrome(string)) {
System.out.println("It IS a palindrome!");
} else {
System.out.println("It is NOT a palindrome!");
}
System.out.println();
}
}
Enjoy.
public boolean isPalindrom(String text) {
StringBuffer stringBuffer = new StringBuffer(text);
return stringBuffer.reverse().toString().equals(text);
}
I guess this is simple way to check palindrome
String strToRevrse = "MOM";
strToRevrse.equalsIgnoreCase(new StringBuilder(strToRevrse).reverse().toString());
I'm new to java and I'm taking up your question as a challenge to improve my knowledge as well so please forgive me if this does not answer your question well:
import java.util.ArrayList;
import java.util.List;
public class PalindromeRecursiveBoolean {
public static boolean isPalindrome(String str) {
str = str.toUpperCase();
char[] strChars = str.toCharArray();
List<Character> word = new ArrayList<>();
for (char c : strChars) {
word.add(c);
}
while (true) {
if ((word.size() == 1) || (word.size() == 0)) {
return true;
}
if (word.get(0) == word.get(word.size() - 1)) {
word.remove(0);
word.remove(word.size() - 1);
} else {
return false;
}
}
}
}
If the string is made of no letters or just one letter, it is a
palindrome.
Otherwise, compare the first and last letters of the string.
If the first and last letters differ, then the string is not a palindrome
Otherwise, the first and last letters are the same. Strip them from the string, and determine whether the string that remains is a palindrome. Take the answer for this smaller string and use it as the answer for the original string then repeat from 1.
The only string manipulation is changing the string to uppercase so that you can enter something like 'XScsX'
check this condition
String string="//some string...//"
check this...
if(string.equals((string.reverse())
{
it is palindrome
}
public static boolean istPalindrom(char[] word){
int i1 = 0;
int i2 = word.length - 1;
while (i2 > i1) {
if (word[i1] != word[i2]) {
return false;
}
++i1;
--i2;
}
return true;
}
import java.util.Scanner;
public class FindAllPalindromes {
static String longestPalindrome;
public String oldPalindrome="";
static int longest;
public void allSubstrings(String s){
for(int i=0;i<s.length();i++){
for(int j=1;j<=s.length()-i;j++){
String subString=s.substring(i, i+j);
palindrome(subString);
}
}
}
public void palindrome(String sub){
System.out.println("String to b checked is "+sub);
StringBuilder sb=new StringBuilder();
sb.append(sub); // append string to string builder
sb.reverse();
if(sub.equals(sb.toString())){ // palindrome condition
System.out.println("the given String :"+sub+" is a palindrome");
longestPalindrome(sub);
}
else{
System.out.println("the string "+sub+"iss not a palindrome");
}
}
public void longestPalindrome(String s){
if(s.length()>longest){
longest=s.length();
longestPalindrome=s;
}
else if (s.length()==longest){
oldPalindrome=longestPalindrome;
longestPalindrome=s;
}
}
public static void main(String[] args) {
FindAllPalindromes fp=new FindAllPalindromes();
Scanner sc=new Scanner(System.in);
System.out.println("Enter the String ::");
String s=sc.nextLine();
fp.allSubstrings(s);
sc.close();
if(fp.oldPalindrome.length()>0){
System.out.println(longestPalindrome+"and"+fp.oldPalindrome+":is the longest palindrome");
}
else{
System.out.println(longestPalindrome+":is the longest palindrome`````");
}}
}