I want to check for instance if string "ABCD" contains "DC" string in it in Java. But this is not a substring example, because every time my string and checking characters will change. and I store checking characters into an array, So substring failed, it only works if I have CD, or BC. and I couldn't do match since every time I call checking character from an array. SO what should I do any suggestion
here's some pseudocode to get you started
we'll call "ABCD" the source string and "DC" the target string
change source string to list of chars
change target string to list of chars
for each char in target list of char
if source list does not contain target char
return false;
return true
I use this method for char and byte array. After you got the index of the src array where the sub is matched with, you then can store it anywhere you want.
Try this:
public static int indexOf(char[] src, char[] sub) {
int limit = src.length - sub.length;
int i, j;
for(i = 0; i < limit +1; ++i) {
for(j = 0; j < sub.length; ++j) {
if (src[i+j] != sub[j]) {
break;
}
}
if (j == sub.length)
return i;
}
return -1;
}
Get all the permutation of the source string till it contains the desired sub string
Permutation Logic based on
public static void main(String[] args) {
System.out.println(Test.checkIfContains("ABCD", "DC"));
}
public static Boolean checkIfContains(String main, String check) {
return permutation("", main, check);
}
private static Boolean permutation(String prefix, String main, String check) {
int n = main.length();
if (n == 0) {
if (checkFor(prefix, check)) {
return true;
}
} else {
for (int i = 0; i < n; i++) {
if (permutation(prefix + main.charAt(i), main.substring(0, i) + main.substring(i + 1, n), check)) {
return true;
}
}
}
return false;
}
private static boolean checkFor(String prefix, String check) {
return prefix.contains(check);
}
As I understand it, you want to see if all of the characters of the second string (which I called checkString) are contained in the first string (refString). I would proceed using a function like this
private boolean checkString(String refString, String checkString) {
boolean a;
for (int i; i < checkString.length(); i++) {
for (int j; j < refString.length(); j++) {
a |= checkString.charAt(i) == refString.charAt(j);
}
if (!a) return false;
}
return true;
}
Which return true only when all the characters in checkString are in the reference string.
Related
Like in question, exercise if it is possible to create a palindromic string of minimum length 3 characters by removing 1 or 2 characters. For example string "abjchba", we can remove letters "jc" and will get palindromic, in this case program should return removed letters so "jc". I know that we can mke palindromic by removing also "ch" but in exercise is that we should remove characters that appear earlier in string. Program should always attempt to create the longest palindromic substring. I wrote methods to reverse String and method to check that string is palindromic:
private static String reverse(String string) {
return new StringBuilder(string).reverse().toString();
}
private static boolean isPalin(String string) {
return string.equals(reverse(string));
}
I also made method to create Palindromic to return symbols we should remove to make palindromic, but beacuse i'm working on sb 'temp' I got exception . Have anyone idea how to fix it and finish exercise?
private static String createPalindrome(String str) {
StringBuilder result = new StringBuilder();
StringBuilder temp = new StringBuilder(str);
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == str.charAt(str.length() - 1 - i)){
continue;
}else {
result.append(str.charAt(i));
temp.deleteCharAt(i);
if (isPalin(temp.toString())){
return result.toString();
}
}
}
return "not possible";
}
Method 1:
Find longest palindromic subsequence(LPS)
Given string: "abjchba"
Longest Palindrome Subsequence: "abhba". Others like "abjba" and "abcba" also are LPS but you want to remove chars that appear earlier so that "abhba".
If (input string length - length of LPS) > 2, return "not possible".
Remove letters from the input string that are not in the LPS.
Start matching string with LPS. 'j' and 'c' won't match. Add them to result and return.
Method 2:
Find longest common subsequence (LCS) between input string and its reverse.
String: "abjchba"
Reverse: "abhcjba"
LCS: Take "abhba" in our case
If (input string length - length of LCS) > 2, return "not possible".
Step 2 will be the same as that of in Method 1 above.
As you are trying for at most 2 deletions, I am thinking if we can do better with time complexity.
I think the simplest way to fix your code is to use recursion. When you find a char that does not match, remove it and call recursively.
// Helper function to remove a character from a string
public static String removeAt(String s, int i)
{
return s.substring(0, i) + s.substring(i + 1);
}
private static String createPalindromeRecursive(String str) {
// Only need to check half the string
for (int i = 0, j = str.length() - 1; i < j; i++, j--) {
// if (something) continue; else {} <- the else is not needed
// because the continue skips to the end of the loop
// or you can negate the condition and don't use continue
if (str.charAt(i) == str.charAt(j)){
continue;
}
String temp = createPalindrome(removeAt(str, i));
// Success. Return the new string
if (null != temp) return temp;
else return null;
}
return str;
}
private static String createPalindrome(String str) {
String palindrome = createPalindromeRecursive(str);
if (palindrome == null || palindrome.length() < str.length() - 2) {
return "not possible";
}
else {
return palindrome;
}
}
using System;
using System.Text;
class MainClass
{
public static String removeAt(String s, int i)
{
return s.Substring(0, i) + s.Substring(i + 1);
}
private static String createPalindromeRecursive(String str)
{
for (int i = 0, j = str.Length - 1; i < j; i++, j--)
{
if (str[i] == str[j])
{
continue;
}
String temp = PalindromeCreator(removeAt(str, i));
if (null != temp) return temp;
else return null;
}
return str;
}
public static string PalindromeCreator(string str)
{
String palindrome = createPalindromeRecursive(str);
StringBuilder result = new StringBuilder();
StringBuilder temp = new StringBuilder(str);
if (palindrome == null || palindrome.Length < str.Length - 2)
{
return "not possible";
}
else
{
for (int i = 0; i < str.Length; i++)
{
if (str[i] == str[(str.Length - 1 - i)])
{
continue;
}
else
{
result.Append(str[i]);
temp.Remove(i, str.Length);
return result.ToString();
}
}
return palindrome;
}
}
static void Main()
{
// keep this function call here
Console.WriteLine(PalindromeCreator(Console.ReadLine()));
}
}
Example: String a = "ACAHBBA" and String b = "ABAB" should return true, since both strings can spell ABAB.
I have tried with contains(), but that only works for equal sequences.
// The code should look like this.
public class task10 {
public static boolean contains(String a, String b) {
// check if b can be spelled using characters from a.
// if it can. return true.
// else
return false;
}
}
Posible solution?
public static boolean contains(String a, String b) {
for (int i = 0; i < b.length(); i++) {
if (a.indexOf(b.charAt(i)) == -1) {
return false;
}
}
return true;
}
Simply iterate thru one string and get the index of the character. If >= 0, replace character with non-alphabetic character and repeat. This algorithm presumes the need to match the correct number of characters. For example, hello would return false if the character set was helo.
public static boolean spelledFrom(String word, String chars) {
StringBuilder sb = new StringBuilder(chars);
for (String c : word.split("")) {
int i;
if ((i = sb.indexOf(c)) < 0) {
return false;
}
sb.setCharAt(i, '#');
}
return true;
}
You can try this:
public static boolean canSpell(String a, String b)
{
String shorter = (a.length() <= b.length()) ? a : b;
String longer = (shorter.equals(a)) ? b : a;
for(int i = 0; i < shorter.length(); i++)
{
if(!longer.contains("" + shorter.charAt(i)))
return false;
}
return true;
}
Once you've identified the shorter string, you just need to verify that each of its chars are contained in the longer string. This solution doesn't verify if a char "has already been used", which means inserting "AB" and "ABBA" will return true. If you need to do this, you just need to delete the verified char from the longer string in every loop.
we will say that two words are "charecter equale" if both of them has the same charecter, for example: baac and abac are charecter equale, I am trying to write a recursive function that gets a string s, a word w and integer k, that checks if there are exactliy k words in the string that they charecter equale to the word, for example: the function should return true for the word abac , the string aabc abdca caba xyz ab and the number k=2.
Ineed help at the recursive part, i.e the function searchMixed, my idea was first the check if the string contain only on word (base case),
the general case is to call the function searchMixed without the first word
public class recursion1 {
public static void main(String[] args) {
boolean result=searchMixed("abac","aabc abdca caba xyz ab",2);
System.out.println("result: "+result);
}
public static boolean searchMixed(String word, String s, int k)
{
if(s.indexOf(' ')==-1 && isEquale(word,s) && k==1)
return true;
if(s.indexOf(' ')==-1 && !isEquale(word,s) && k==1)
return false;
int pos=s.indexOf(' ');
System.out.println("index of"+ s.indexOf(' '));
String first_word=first_word=s.substring(0,pos);
if(isEquale(word, first_word))
searchMixed(word, s.substring(pos+1), k-1);
else
searchMixed(word, s.substring(pos+1), k);
return false;
}
.
//this function works fine, the function checks if two words are charecter equale
public static boolean isEquale(String word, String sub_string)
{
if(word.length()!=sub_string.length())
return false;
char[] s33=new char[sub_string.length()];
char[] sww=new char[word.length()];
for(int i=0;i<sub_string.length();i++)
s33[i]=sub_string.charAt(i);
for(int i=0;i<word.length();i++)
sww[i]=word.charAt(i);
for(int i=0;i<word.length();i++)
{
for(int j=0;j<sub_string.length();j++)
{
if(sww[i]==s33[j])
s33[j]='#';
}
}
for(int i=0;i<sub_string.length();i++)
if(s33[i]!='#')
return false;
return true;
}
}
YourString = YourString.replaceAll("\\s+", " ");
String[] words = YourString.split(" ");
... to split the words.
static int n = 0;
static String keyword = "aabc";
static String[] words = null;
public static void main()
{
n = 0;
// Let's assume you accept 'k' here.
String YourString = "aabc baca hjfg gabac";
words = YourString.split(" ");
rec(words[0]);
if (k <= n)
System.out.println(true);
else
System.out.println(false);
}
static int pos = 0;
public static void rec(String word)
{
boolean flag = true;
word += " ";
if(word.length() != keyword.length() + 1)
{
flag = false;
}
for(int i = 0; i < keyword.length() && flag; i++)
{
for(int j = 0; j < word.length(); j++)
{
if(word.charAt(j) == keyword.charAt(i))
{
word = word.substring(0, j) + word.substring(j+1);
break;
}
}
if(word.equals(" "))
{
n++;
break;
}
}
if(pos + 1 != words.length)
{
rec(words[++pos]);
}
}
Now, let me explain:
In the recursive method rec(String word), a space is added to it at the end of the word being checked (so that substring(j+1) does not go out of bounds)
If the keyword and the checked word are of different lengths, it stops checking, and moves on to '5'.
If the two words are of same lengths, the loop removes a single similar character from the word (That's what word = word.substring(0, j) + word.substring(j+1); does).
At the end of the loop, if all that is remaining of the word is a space, then the counter n increases by 1 and the loop exits.
If there is more than or equal to one more Strings in the array, position of the word being checked in the array increases by 1, and the next word in the array is passed to the rec(String word) method.
This is my attempt at an Anagram method, and it's not returning the correct value. It won't work for large Strings.
public boolean IsAnagram(String s,String p)
{
int flag=0;
char c[]=s.toLowerCase().toCharArray();
char d[]=p.toLowerCase().toCharArray();
if(c.length!= d.length)
{
System.out.println("no");
//return false;
}
for(int i=0;i<c.length;i++)
{
for(int j=0;j<d.length;j++)
{
if(c[i]==d[j])
{
++flag;
}
}
}
if(flag==c.length)
{
return true;
}
else
return false;
}
If you don't want to use library functions, keep it as simple as possible, e.g.
public static boolean anagram(String s1, String s2) {
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
if (c1.length != c2.length) {
return false;
}
outer:
for (char ch : c1) {
for (int i = 0; i < c2.length; i++) {
if (c2[i] == ch) {
c2[i] = '\0';
continue outer;
}
}
return false;
}
return true;
}
Here you search for every char in the first array a matching char in the second one, and "cross it out", so you don't count it twice. Of course this assumes that you don't have '\0' chars in your strings (which would be quite unusual).
Try to avoid complicated "book-keeping", counters, flags etc. Focus on small, logical steps and invariants.
You should add break here:
for (int i = 0; i < c.length; i++) {
for (int j = 0; j < d.length; j++) {
if (c[i] == d[j]) {
++flag;
break;
}
}
}
Peter Lawrey is right. You must not only check if the letter in the second array is there, you must also check that they appear same number of times. Sorting and comparing the Strings would be a good solution i think.
Here is a fancy solution: https://stackoverflow.com/a/17004897/3959856
Why do you try to solve a simple task in such a contrived way? Just use the API functions you already have:
public static boolean anagram(String s1, String s2) {
char[] c1 = s1.toLowerCase().toCharArray();
char[] c2 = s2.toLowerCase().toCharArray();
Arrays.sort(c1);
Arrays.sort(c2);
return Arrays.equals(c1,c2);
}
Sum the characters if they are equal then strings are anagram
private boolean isAnagram(String s1, String s2) {
char a[] = s1.toLowerCase().toCharArray();
char b[] = s2.toLowerCase().toCharArray();
if (a.length == b.length) {
int l = a.length; //or b.length
int total = 0;
for (int i = 0; i < l; i++) {
total += a[i];
total -= b[i];
}
if (total == 0)
return true;
}
return false;
}
public static boolean isValidNumber(String a1)
{
String x = ("0123456789");
boolean valid = false;
for (int i = 0; i < 4; i++) {
char c = a1.charAt(i);
for (int j = 0; j < 10; j++) {
if ( c == x.charAt(j)) {
valid = true;
}
else {
valid = false;
}
}
}
return valid;
}
The above method checks to see whether an input of a four character string is composed of the characters 0123456789. However, regardless of what the input is, the method always returns as false.
If I were to change the valid value in the else statement to true, the method would always return as true.
What is the error that I have made in this method?
As soon as you find a non matching character, break the loop otherwise the next matching character will set valid to true.
e.g. "123a456" is considered valid.
for (int j = 0; j < 10; j++) {
if ( c == x.charAt(j)) {
valid = true;
}
else {
valid = false;
break;
}
}
If for some reason you don't want to break the loop, you could keep an "invalid counter" and make sure that is 0 at the end.
Of course for what you are doing here, Integer.parseInt() might be your best bet ;-)
a String.equals method will check these two strings in a single statement if you are permitted to use that.
public static boolean isValidNumber(String a1)
{
String x = ("0123456789");
return x.equals(a1);
}
I would rewrite your function as given below,
String x = ("0123456789");
boolean valid = false;
for (int i = 0; i < 4; i++) {
char c = a1.charAt(i);
boolean isCharOK = false;
for (int j = 0; j < 10; j++) {
if ( c == x.charAt(j)) {
isCharOK = true;
break;
}
}
if (!isCharOK) {
valid = false;
break;
}
}
return valid;
John3136 is quite correct, but I would like to propose even better solution to your whole task:
final static String x = "0123456789";
public static boolean isValidNumber(String a1) {
for (int i = 0; i < a1.length(); ++i) {
if (x.indexOf(a1.charAt(i)) == -1) return false;
}
return true;
}
In short: the above code "looks up" every character in your parameter string a1 in the string composed of digits. If it can find it, continues. If it can't, it means a1 consist not only digits and returns false. If it passes through all a1 characters then it returns true :)
And as asked and described in the comments - handling of duplicate characters in argument string:
final static String x = "0123456789";
public static boolean isValidNumber(String a1) {
for (int i = 0; i < a1.length(); ++i) {
final char currentChar = a1.charAt(i);
if (x.indexOf(currentChar) == -1 || a1.indexOf(currentChar, i+1) != -1)
return false;
}
return true;
}
The function call a1.indexOf(currentChar, i+1) essentially checks if there is any duplicate character in the rest of the string (from position i+1 and farther). Which means if it will be able to find duplicate char, the method return false :) Hope this helps, here is more info on String.indexOf(int, int) function if you want:
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(int, int)
You can use this one liner function to check for validity of a String as Number using Regular Expression
public static boolean isValidNumber(String a1)
{
return a1.matches("[\\d]+");
}
Hope this helps.