Check if given string is interleaved of two other string - java

I wrote the code for checking if S3 is a interleaving of S1 and S2 string.
But it fails for simple strings like "AB" , "CD" -> "ACBD"
Am I missing something ?
class InterleavedString {
// error
public static boolean isInterleaved (String A, String B, String C)
{
// Iterate through all characters of C.
int a = 0, b = 0, c = 0;
while (C != null)
{
// Match first character of C with first character of A,
// If matches them move A to next
if (A.charAt(a) == C.charAt(c))
a++;
// Else Match first character of C with first character of B,
// If matches them move B to next
else if (B.charAt(b) == C.charAt(c))
b++;
// If doesn't match with either A or B, then return false
else
return false;
// Move C to next for next iteration
c++;
}
// If A or B still have some characters, then length of C is smaller
// than sum of lengths of A and B, so return false
if (A != null || B != null)
return false;
return true;
}
public static void main(String [] args) {
String A = "AB", B = "CD", C = "ACBD";
System.out.println(isInterleaved(A, B, C));
}
}
ERROR :
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: 2 at java.lang.String.charAt(Unknown
Source) at
strings.InterleavedString.isInterleaved(InterleavedString.java:14) at
strings.InterleavedString.main(InterleavedString.java:40)
EDITED :
while (c != C.length())
.....
.....
if (a != A.length() || b != B.length())

The condition of your while statement is wrong. You are never changing your value of C. Instead of while (C != null) you should use while c != C.length() or something similar.
The same problem is with your A != null and B != null statements because charAt does not remove any characters!
In addition you need to check the bounds of your Strings in your if clauses:
if (a < A.length() && A.charAt(a) == C.charAt(c))
Also if you are aiming for efficiency you should add this check at the beginning of your method and in turn remove the last if statement:
if (A.length() + B.length() != C.length())
return false;

This is wrong .. Try with "XXY", "XXZ", "XXZXXY" .. The output will be false

boolean interleaving(String s1, String s2, String s3){
char a[] = s1.toCharArray();
char b[] = s2.toCharArray();
char c[] = s3.toCharArray();
if(a.length+b.length!=c.length){
return false;
}
int i=0,j=0,k=0;
while(k<=c.length-1){
if(i<a.length && c[k]==a[i]){
i++;
}else if(j<b.length && c[k]==b[j]){
j++;
}else{
return false;
}
k++;
}
return true;
}

Related

check if char[] contains only one letter and one int

I have no idea how to check if char[] contains only one letter (a or b) on the first position and only one int (0-8) on the second position. for example a2, b2
I have some this, but I do not know, what should be instead of digital +=1;
private boolean isStringValidFormat(String s) {
boolean ret = false;
if (s == null) return false;
int digitCounter = 0;
char first = s.charAt(0);
char second = s.charAt(1);
if (first == 'a' || first == 'b') {
if (second >= 0 && second <= '8') {
digitCounter +=1;
}
}
ret = digitCounter == 2; //only two position
return ret;
}
` public char[] readFormat() {
char[] ret = null;
while (ret == null) {
String s = this.readString();
if (isStringValidFormat(s)) {
ret = s.toCharArray();
}else {
System.out.println("Incorrect. Values must be between 'a0 - a8' and 'b0 - b8'");
}
}
return new char[0];
}`
First, I would test for null and that there are two characters in the String. Then you can use a simple boolean check to test if first is a or b and the second is between 0 and 8 inclusive. Like,
private boolean isStringValidFormat(String s) {
if (s == null || s.length() != 2) {
return false;
}
char first = s.charAt(0);
char second = s.charAt(1);
return (first == 'a' || first == 'b') && (second >= '0' && second <= '8');
}
For a well understood pattern, use Regex:
private static final Pattern pattern = Pattern.compile("^[ab][0-8]$")
public boolean isStringValidFormat(String input) {
if (input != null) {
return pattern.matcher(input).matches();
}
return false;
}

Duplicate a vowel in String and add a String in-between

I have to write a method that takes in a String and returns a new string that duplicates all vowels and puts a "b" in between. Only exception goes for diphtongs where "ab" should be put in front of the diphtong.
For example: "hello" would return "hebellobo"
"hearing" would return "habearing"
I've experimented with my code for hours but I am not getting anything done.
Well, not anything, but can't make it run properly for vowels and didn't get to the diphtongs at all.
Here is my code:
static Scanner sc = new Scanner(System.in);
public static void main(String[] args)
{
System.out.print("Enter a string: ");
String s = sc.nextLine();
String originalString = s;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if ((c == 'A') || (c == 'a') || (c == 'E') || (c == 'e') || (c == 'I') || (c == 'i') || (c == 'O')
|| (c == 'o') || (c == 'U') || (c == 'u'))
{
String front = s.substring(0, i);
String back = s.substring(i + 1);
s = front + c + "b" + back;
}
}
System.out.println(originalString);
System.out.println(s);
}
Grateful for any help !
Thanks to your help I now have the following code (without Scanner):
public static boolean isVowel(char c) {
// TODO exercise 1 task b) part 1
if (c == 'a' || c == 'A' || c == 'Ä' || c == 'e' || c == 'E' || c == 'i' || c == 'I' || c == 'o' || c == 'O'
|| c == 'Ö' || c == 'u' || c == 'U' || c == 'Ü') {
return true;
} else {
return false;
}
}
public static String toB(String text) {
// TODO exercise 1 task b) part 2
StringBuilder b = new StringBuilder();
for (int i = 0; i < text.length() - 1; i++) {
char current = text.charAt(i);
char next = text.charAt(i + 1);
if (isVowel(current)) {
if (isVowel(next)) {
// 1 - Is a vowel followed by a vowel
// Prepend b
b.append("b");
// Write current
b.append(current);
// Write next
b.append(next);
i++; // Skip next vowel
} else {
// 2 - Is a vowel followed by a consonant
b.append(current);
b.append("b");
b.append(current);
}
} else {
// 3 - Is a consonant
b.append(current);
}
}
for (int i = 0; i < text.length() - 1; i++) {
char last = text.charAt(text.length() - 1);
char current = text.charAt(i);
if (isVowel(last)) {
// Case 1
b.append(current);
b.append("b");
b.append(current);
// Case 2 is not possible for last letter
} else {
// Case 3
b.append(last);
}
}
// Here b.toString() is the required string
return b.toString();
}
If you put in the word "Mother" for example, the ouput is "Mobotheberrrrr" which is perfectly fine, except that it repeats the last letter 'r' for some reason. Input "Goal" results in Output "Gboalll" unfortunately.
You need to know the current letter and also the next letter.
In your code you take in consideration only the current letter.
Here is a skeleton code to solve the problem.
Basically you need to check:
If the current letter is a vowel followed by a vowel
If the current letter is a vowel followed by a consonant
If the current letter is a consonant
String originalString = ...
StringBuilder b = new StringBuilder();
for (int i = 0; i < s.length() - 1; i++) {
char current = s.charAt(i);
char next = s.charAt(i + 1);
if (isVowel(current)) {
if (isVowel(next)) {
// 1 - Is a vowel followed by a vowel
// Prepend b
b.append("b");
// Write current
b.append(current);
// Write next
b.append(next);
i++; // Skip next vowel
} else {
// 2 - Is a vowel followed by a consonant
b.append(current);
b.append("b");
b.append(current);
}
} else {
// 3 - Is a consonant
b.append(current);
}
}
char last = s.charAt(s.length() - 1);
if (isVowel(last)) {
// Case 1
b.append(current);
b.append("b");
b.append(current);
// Case 2 is not possible for last letter
} else {
// Case 3
b.append(last);
}
// Here b.toString() is the required string
Please consider this only as a skeleton, in particular:
check for border conditions
implements the method isVowel
check for null and empty strings
Note: the use of StringBuilder is only for performance reasons, using directly the String s will give the same result
My best guess is make a chain of replaceAlls because you are basically replacing vowels with duplicates and bs so try something like so:
String original = something;
String adjusted = original.replaceAll("ea","abea").replaceAll("a","aba").replaceAll(...)...;
And just fill in the rules. Make sure to check diphthongs before checking single vowels or they will be treated as two single vowels

Using recursion to test if two strings are the same but reversed

For my assignment I have to use recursion to test if two strings are the same but reversed.
Here is the actual question:
Write a recursive method called isStringReversed which, given two String parameters, returns true if the two strings contain the same sequence of characters but in reverse order (ignoring capitalization), and false otherwise. For example, isStringReversed("piano", "oNaIp") would return true. Note: the null (empty) string and string of one letter are both the reverse of themselves.
Here's what I have made, but when I execute the program, i always get
a false return. Heres my code:
public static boolean isStringReversed(String s1, String s2) {
if (s1 == null || s2 == null || s1.length() == 1 || s2.length() == 1) {
return true;
}else if (s1.length() != s2.length()) {
return false;
}else {
char s1first = Character.toLowerCase(s1.charAt(0));
char s2last = Character.toLowerCase(s2.charAt(s2.length() - 1));
if (s1first == s2last){
String s1shorter = s1.substring(0, s1.length() - 1);
String s2shorter = s2.substring(0, s2.length() - 1);
return isStringReversed(s1shorter, s2shorter);
}else {
return false;
}
}
}
When doing substring on s1first, you should remove the first character, not the last.
Just one line above that you compare first character of s1first and last character of s2last. So once you establish that they are equal, that's what you remove and continue the recursion.
Instead of
String slshorter = sl.substring(0, s1.1ength() - l) ;
String s2shorter = s2.substring(0, s2.1ength() - l) ;
use
String slshorter = sl.substring(1) ;
String s2shorter = s2.substring(0, s2.1ength() - 1) ;
Note that the second parameter of the method substring() means to that index exclusive.
This is the recursive idea
public static bool isStringReversed(string input1, string input2)
{
string s1 = input1.ToLower();
string s2 = input2.ToLower();
if(s1 == null && s2 == null)
return true;
if (s1.Length == 1 && s2.Length == 1)
{
if (s1 == s2)
return true;
return false;
}
if (s1.Length != s2.Length)
return false;
return isStringReversedRec(s1, s2, s1.Length - 1, 0);
}
private static bool isStringReversedRec(string s1, string s2, int indexS1, int indexS2)
{
if (indexS1 < 0)
return true;
if (s1.charAt(indexS1) != s2.charAt(indexS2))
return false;
return isStringReversedRec(s1, s2, indexS1 - 1, indexS2 + 1);
}

What is wrong with my method isReverse

Write a recursive method called isReverse("word1", "word2") that accepts two Strings as parameters and returns true if the two Strings contain
the same sequence of characters as each other but in opposite order, ignoring case, and returning false otherwise.
For example, the call of:
isReverse("Desserts", "Stressed")
would return true. [So eat desserts when you are stressed?]
Null, empty and one letter strings are also to return true (if both parameters are the same value).
This is homework and I am having trouble making this code work appropriately. It returns true no matter what I do.
public static boolean isReverse(String word1, String word2)
{
if(word1 == null || word2 == null)
{
if(word1!= null && word2 != null)
{
return false;
}
return false;
}
else if(word1.length() == word2.length())
{
String firstWord = word1.substring(0, word1.length());
String secondWord = word2.substring(word2.length()-1);
if (firstWord.equalsIgnoreCase(secondWord))
{
return isReverse(word1.substring(0, word1.length()), word2.substring(word2.length() - 1));
}
}
return true;
}
First, you have this set so that it will only return false if both words are null; If they are not null you're re-calling the method(in the event that the length is equal), which will return true.
private static boolean isReverse(String a, String b) {
// make sure the strings are not null
if(a == null || b == null) return false;
// If the lengths are not equal, the strings cannot be reversed.
if(a.length() != b.length()) {
return false;
}
// Convert string b to an array;
char[] bArray = b.toCharArray();
// Create an array to write bArray into in reverse.
char[] copy = new char[bArray.length];
// Iterate through bArray in reverse and write to copy[]
for(int i = bArray.length; i < 0; i--) {
copy[bArray.length - i] = bArray[i];
}
// Convert copy[] back into a string.
String check = String.valueOf(copy);
// See if they reversed string is equal to the original string.
if(check.equalsIgnoreCase(a)) {
return true;
} else {
return false;
}
}
You are saying
if (firstWord.equalsIgnoreCase(secondWord))
{
return isReverse(word1.substring(0, word1.length()), word2.substring(word2.length() - 1));
}
which is OK. But what if firstWord does not equal second word
It falls through and returns true.
You need to add an
else
return false;
I will also add that your null checking will not work.
if(word1!= null && word2 != null)
{
return false;
}
Is not useful because you are already in an if that only happens when word1 or word2 is null. So they can't be null and null here.
It would work if you made it
if(word1 == null && word2 == null)
{
return true;
}
Is this an exercise? Recursion doesn't seems to be the best option here. Anyway, you're just trimming one word, why? You must trim both words if you expect to compare each char in each recursive call. And you're not even passing the trimmed words as parameter to the recursive function!
The basic thing you're missing is a base case. When the recursion must return? In your case, you're reducing each string size at each step of recursion, so you must have a base case to check if the size is one.
Hope that this code clear your mind:
public static boolean isReverse(String word1, String word2) {
if (word1 == null || word2 == null) {
return false;
}
if (word1.length() == 1 && word2.length() == 1) {
//Used equals just for fast compare
return word1.equals(word2);
} else if (word1.length() == word2.length()) {
if (word1.charAt(0) == word2.charAt(word2.length() - 1)) {
String firstWord = word1.substring(1, word1.length());
String secondWord = word2.substring(0, word2.length() - 1);
System.out.printf("Trimmed %s, %s to %s, %s\n", word1, word2, firstWord, secondWord);
return isReverse(firstWord, secondWord);
} else {
//Characters didn't matched
return false;
}
} else {
//Lenght doesn't match
return false;
}
}
First I have reversed one of the string(i took word1) using recursion.then compared to second string if both strings are equal result set to true.
public static boolean isReverse(String word1, String word2)
{
boolean result = false;
//check null to avoid null pointer exception
if(word1 == null | word2 == null){
result = false;
}else if(word1.length() == word2.length()){
word1 = reverseString(word1);
if(word1.equalsIgnoreCase(word2)){
result = true;
}
}
return result;
}
static String reverse = "";
public static String reverseString(String str){
if(str.length() == 1){
reverse+=str;
} else {
reverse += str.charAt(str.length()-1)
+reverseString(str.substring(0,str.length()-1));
}
return reverse;
}

Analyze a string of characters in java for format A^nB^n

I have a string of characters with As and Bs that I need to analyze for a Language A^nB^n. I can use the following code to work most of the time but when there is a letter that is not an "A" or "B" it may still return true, for example: AABACABAA should not be true, but it says it is. AABB is true; AABBAABB is not true. I have to use stacks and am not allowed to use counting.
public static boolean isL2(String line){
// set up empty stacks
Stack L2Stack = new Stack();
// initialize loop counter
int i = 0;
int n = line.length();
/* Push all 'A's to a_stack */
while ((i < line.length()) && (line.charAt(i) == 'A')) {
char ch = line.charAt(i);
L2Stack.push(ch);
i++;
}
/* Pop an 'A' for each consecutive 'B' */
while ((i < line.length()) && (line.charAt(i) == 'B')) {
if (!L2Stack.empty()){
L2Stack.pop();
i++;
}
else
return false;
}
if (i == n && !L2Stack.empty()){
return false; // more As than Bs
}
if (i != n && L2Stack.empty()){
return false; //more Bs than As
}else
return true;
}
if (i != n && L2Stack.empty()) {
return false; //more Bs than As
}
Should be
if (i != n) {
return false;
}
Since if you haven't finished reading all the characters, you can't return true, regardless of whether or not the stack is empty.
I'm assuming that AAABBBA should return false.
That change would also handle illegal characters.

Categories