Get all combinations of Strings - java

I have requirement that need to get all combinations of given Strings.
For example
I have a String of digits and some special charcters
String chars="0123456789##$%&";
String guessedPw="authentic";
So I want to get combinations like this
$authentic%4
authentic##
5&authentic
authentic8
How should I improve my method to get all combinations?
This is the code that I have written.
but it doesn't give me all combinations.
private static String combination(String prefix, String s, String pw, String md5Pw) {
String pwFound = "";
if (s.length() > 0) {
// System.out.println(prefix + s.charAt(0) + pw);
String tempPw1 = prefix + s.charAt(0) + pw;
System.out.println("pw1 : " + tempPw1);
if (md5(tempPw1).equals(md5Pw)) {
// String tempPw1;
pwFound = tempPw1;
return pwFound;
}
String tempPw2 = pw + prefix + s.charAt(0);
if (md5(tempPw2).equals(md5Pw)) {
// String tempPw1;
pwFound = tempPw2;
return pwFound;
}
pwFound = combination(prefix + s.charAt(0), s.substring(1), pw, md5Pw);
pwFound = combination(prefix, s.substring(1), pw, md5Pw);
}
return pwFound;
}

Just if you don't want write own algo, you can use google.
Try to search for: "Generate Permutations".
For example, on this link: Generate all combinations from multiple lists there is a algo which you can use it (but with list).
void GeneratePermutations(List<List<Character>> Lists, List<String> result, int depth, String current)
{
if(depth == Lists.size())
{
result.add(current);
return;
}
for(int i = 0; i < Lists.get(depth).size(); ++i)
{
GeneratePermutations(Lists, result, depth + 1, current + Lists.get(depth).get(i));
}
}
But sure, there are a lot of other ways.

If you want to code everything by your own then this is how you should approach your problem =>
Have a special character say ~ to denote guessedPw, and create another string say str = chars + "~".
Now first you need to look for all possible combinations of str, finding which will take exponential time , and then for each found combination, you should generate all it's permutation , which is again factorial time complex. And then in the final string , you should replace all the occurrence of '~' with guessedPw, and get the answer string.
Here you go for the link for generating permutations and combinations :
Link : http://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/
To find out combinations , you can use bit-masking if you have at max. 64 characters in the string , combinations from which you want to extract.

To make new combination, you can add one char as prefix or add one char as suffix. To avoid repeats, stop adding prefix when suffix exists
Pseudocode:
GenPass(CurrentString, boolAllowPrefix)
check CurrentString, return it if good result
check length limit, exit if too long
for c in Chars
if (boolAllowPrefix)
GenPass(Chars[i] + CurrentString, True)
GenPass(s + Chars[i], False)
Delphi implementation to check
procedure GenPass(s: string; bPrefix: Boolean);
var
i: integer;
begin
List.Add(s);
if Length(s) = MaxLen then
Exit;
if bPrefix then
for i := 1 to Length(Chars) do
GenPass(Chars[i] + s, True);
for i := 1 to Length(Chars) do
GenPass(s + Chars[i], False);
end;

Related

String Matching for patterns

I have 2 strings of pattern a.{var1}.{var2} and b.{var1}.{var2}.
Two Strings are matching if var1 in first string is same as var1 in second string, as well as var2 in first string is same as var2 in second string.
The variables can be any order like a.{var1}.{var2} and b.{var2}.{var1}.
How do I match the two strings efficiently?
Example 1:
String pattern1 = "1.{var1}";
String pattern2 = "2.{var1}";
//Match True = (1.111,2.111)
//Match False = (1.121,2.111)
Example 2:
String pattern1 = "1.{var1}.{var2}";
String pattern2 = "2.{var1}.{var2}";
//Match True = (1.11.22,2.11.22)
//Match False = (1.11.22,2.111.22)
Example 3:
String pattern1 = "1.{var1}.{var2}";
String pattern2 = "2.{var2}.{var1}";
//Match True = (1.22.11,2.11.22)
//Match False = (1.11.22,2.111.22)
So whats the best way to match these 2 strings?
I want to match these 2 strings to find if they are related with the pattern mentioned.
Extending this problem to a set of strings i.e Set A strings has to be matched with strings in Set B. Finally pairs of strings have to be formed which satisfy this matching algorithm. The pattern will remain the same when matching for all strings in Set A to Set B.
This might not be the most efficient way of doing this, but it does give you the expected output.
01/05: Code updated after an error pointed out by Ole in the comments::
private boolean compareStr(String a, String b) {
ArrayList<String> aList = new
ArrayList<String>(Arrays.asList(a.split("\\.")));
ArrayList<String> bList = new ArrayList<String>(Arrays.asList(b.split("\\.")));
bList.remove(0);
aList.remove(0);
if(aList.size() != bList.size())
return false;
boolean aMatchFlag = false;
for(int i=0; i< aList.size(); i++){
if (!bList.contains(aList.get(i))) {
return false;
}
}
aMatchFlag = true;
System.out.println("All elements of A are present in B");
boolean bMatchFlag = false;
for(int i=0; i< bList.size(); i++){
if (!aList.contains(bList.get(i))) {
return false;
}
}
bMatchFlag = true;
System.out.println("All elements of B are present in A");
if(aMatchFlag && bMatchFlag)
return true;
else
return false;
}
For those also looking for the performance of the code
Input:1.11.11, 2.11.11.11
Compilation time: 1.45 sec, absolute running time: 0.24 sec, cpu time: 0.26 sec, memory peak: 18 Mb, absolute service time: 1,7 sec
Input:1.11.11, 2.11.22
Compilation time: 1.25 sec, absolute running time: 0.24 sec, cpu time: 0.23 sec, memory peak: 18 Mb, absolute service time: 1,49 sec
Input:1.11.2, 2.11.22
Compilation time: 1.34 sec, absolute running time: 0.24 sec, cpu time: 0.24 sec, memory peak: 18 Mb, absolute service time: 1,58 sec
Input:1.11.2, 2.11.111
Compilation time: 1.65 sec, absolute running time: 0.28 sec, cpu time: 0.32 sec, memory peak: 18 Mb, absolute service time: 1,94 sec
You can use following String class methods:
boolean regionMatches(int toffset, String other, int ooffset, int len)
Tests whether the specified region of this string matches the specified region of the String argument.
Region is of length len and begins at the index toffset for this string and ooffset for the other string.
For ignoring case:
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
More information : https://docs.oracle.com/javase/tutorial/java/data/comparestrings.html
Or try to create a Regex pattern dynamically from one string and compare with other ...though not an efficient approach
I suppose following:
string[] arr1 = pattern1.split
string[] arr2 = pattern2.split
int hash1 = arr1[0].hashCode() + arr1[1].hashCode();
int hash2 = arr2[0].hashCode() + arr2[1].hashCode();
if(hash1 = hash2)=> pattern1 == pattern2
Remove the patterns from the String, extract the vars from the String by splitting around the dot (assuming your vars has no dots inside), put them in a Set (Sets don't retain the order and hence automatically solve the problem you have with ignoring the position), Check the equality of the Sets.
Running demo: https://ideone.com/5MwOHC
Example code:
final static String pattern1head = "blablabla.";
final static String pattern2head = "yada yada.";
private static Set<String> extractVars(String v){
if (v.startsWith(pattern1head)) { v = v.replace(pattern1head,""); }
else if (v.startsWith(pattern2head)) { v = v.replace(pattern2head,""); }
else { return null; }
return new HashSet<String>(Arrays.asList(v.split("\\.")));
}
private static void checkEquality(String v1, String v2) {
System.out.println("\n"+v1+" == "+v2+" ? " + extractVars(v1).equals(extractVars(v2)));
}
public static void main (String[] args) throws java.lang.Exception {
String v1 = "blablabla.123.456";
String v2 = "yada yada.123.456";
String v3 = "yada yada.456.123";
String v4 = "yada yada.123.456789";
checkEquality(v1,v2);
checkEquality(v1,v3);
checkEquality(v1,v4);
checkEquality(v2,v3);
checkEquality(v2,v4);
}
Output:
blablabla.123.456 == yada yada.123.456 ? true
blablabla.123.456 == yada yada.456.123 ? true
blablabla.123.456 == yada yada.123.456789 ? false
yada yada.123.456 == yada yada.456.123 ? true
yada yada.123.456 == yada yada.123.456789 ? false
This can be done as follows:
While we check if the first string and the first pattern match, we extract a map of the values in the string corresponding to the placeholders (var1, var2, ...) in the pattern;
While we check if the second string and the second pattern match, we also check the second string against the values of the placeholders.
This is interesting, because the map placeholder - > value is computed once for a couple (first string, first pattern),
and can be used to check every couple (second string, second pattern).
Translation in the code: create an object of type PatternMatcher from (first string, first pattern). This object will contain a map valueByPlaceHolder
used to check other couples.
Here are the relevant parts of the code.
Check if string and pattern match + creation of the map:
private static Optional<Map<String, String>> extractValueByPlaceHolder(
String[] sChunks, String[] patternChunks) {
// string and pattern should have the same length
if (sChunks.length != patternChunks.length)
return Optional.empty();
Map<String, String> valueByPlaceHolder = new HashMap<>(sChunks.length);
for (int i = 0; i < patternChunks.length; i++) {
String patternChunk = patternChunks[i];
String sChunk = sChunks[i];
if (isAPlaceHolder(patternChunk)) { // first char = {, last char = }
valueByPlaceHolder.put(patternChunk, sChunk); // just get the value
} else if (!patternChunk.equals(sChunk)) {
// if it's not a placeholder, the chunks should be the same in the string
// and the pattern
return Optional.empty();
}
}
return Optional.of(valueByPlaceHolder);
}
Check if other string and otherpattern match + comparison with first (string, pattern) couple:
public boolean check(String[] otherChunks, String[] otherPatternChunks) {
// other string and other pattern should have the same length, other string and string too
if (otherChunks.length != this.chunks_length || otherChunks.length != otherPatternChunks.length)
return false;
for (int i = 0; i < otherChunks.length; i++) {
String otherPatternChunk = otherPatternChunks[i];
String otherChunk = otherChunks[i];
// get the value from the first string if a it's placeholder, else keep the pattern chunk
String expectedChunk = this.valueByPlaceHolder
.getOrDefault(otherPatternChunk, otherPatternChunk);
// the chunk is neither equal to the value of the placeholder, nor to the chunk of the pattern
if (!expectedChunk.equals(otherChunk))
return false;
}
return true;
}
Use String.split() and then String.equals() on the resulting array elements, handling your three cases separately.
After splitting, first check that both the resulting arrays have the same length (if not they don’t match). Also use String.equals() for checking that the first element is "1" and "2" if this is required. Then branch on whether the length is 2 or 3. If length is 2, check that the match is as in your example 1; again use String.equals() on the array elements. If length is 3, you need to check both orders of the variable parts in accordance with your two examples 2 and 3.
Remember that the argument to String.split() is a regular expression, and that the dot has a special meaning in regular expressions. So you need to use .split("\\."), not .split(".").
It should run pretty fast too. However, don’t start optimizing until you know you need better performance. Readability is king.
Edit: I present my own solution:
public static boolean match(String s1, String s2) {
String[] a1 = s1.split("\\.", 4);
String[] a2 = s2.split("\\.", 4);
if (a1.length != a2.length) {
return false;
}
if (a1[0].equals("1") && a2[0].equals("2")) {
if (a1.length == 2) {
return a1[1].equals(a2[1]);
} else if (a1.length == 3) {
return (a1[1].equals(a2[1]) && a1[2].equals(a2[2]))
|| (a1[1].equals(a2[2]) && a1[2].equals(a2[1]));
}
}
return false;
}
Trying it with the 6 examples from the question:
System.out.println("(1.111,2.111) " + match("1.111", "2.111"));
System.out.println("(1.121,2.111) " + match("1.121", "2.111"));
System.out.println("(1.11.22,2.11.22) " + match("1.11.22", "2.11.22"));
System.out.println("(1.11.22,2.111.22) " + match("1.11.22", "2.111.22"));
System.out.println("(1.22.11,2.11.22) " + match("1.22.11", "2.11.22"));
System.out.println("(1.11.22,2.111.22) " + match("1.11.22", "2.111.22"));
This prints:
(1.111,2.111) true
(1.121,2.111) false
(1.11.22,2.11.22) true
(1.11.22,2.111.22) false
(1.22.11,2.11.22) true
(1.11.22,2.111.22) false

Java Regex Match and Replace matched group with characters of same length

So I want to match credit card numbers and mask them in 6*4 format. So that only first 6 and last 4 characters will be visible. The characters between will be '*'. I tried to figure it out with a MASK like;
private static final String MASK = "$1***$3";
matcher.replaceAll(MASK);
But could not find out the way to give me back equal length of stars in the middle as the group $2.
Then I implemented the below code and it works.
But what i want to ask if there is a shorter or easier way to do this. Anyone knows it?
private static final String HIDING_MASK = "**********";
private static final String REGEX = "\\b([0-9]{6})([0-9]{3,9})([0-9]{4})\\b";
private static final int groupToReplace = 2;
private String formatMessage(String message) throws NotMatchedException {
Matcher m = Pattern.compile(REGEX).matcher(message);
if (!m.find()) throw new NotMatchedException();
else {
StringBuilder maskedMessage = new StringBuilder(message);
do {
maskedMessage.replace(m.start(groupToReplace), m.end(groupToReplace),
HIDING_MASK.substring(0, (m.end(groupToReplace) - m.start(groupToReplace))));
} while(m.find(m.end()));
return maskedMessage.toString();
}
}
EDIT: Here is an example message to process.
"2017.08.26 20:51 [Thread-Name] [Class-Name] [MethodName] Credit card holder 12345678901234567 02/2022 123 ........."
You can do it simply with this code:
str.replaceAll( "(?<=\\d{6})\\d(?=\\d{4})", "*" );
private String formatMessage(String message) throws NotMatchedException {
if (message.matches(".*\\b\\d{13,19}\\b.*")) {
return message.replaceAll("(?:[.\\b]*)(?<=\\d{6})\\d(?=\\d{4})(?:[.\\b]*)", "*");
} else {
throw new NotMatchedException() ;
}
}
Readable but uncool.
String in = "1234561231234";
String mask = in
.replaceFirst("^\\d{6}(\\d+)\\d{4}$", "$1")
.replaceAll("\\d", "\\*");
String out = in
.replaceFirst("^(\\d{6})\\d+(\\d{4})$", "$1" + mask + "$2");
You can use the following if your text contains multiple credit-card numbers with variable lengths:
str.replaceAll( "\\b(\\d{13,19})\\b", "\u0000$1\u0000" )
.replaceAll( "(?<=\\d{6})(?<=\u0000\\d{6,14})\\d(?=\\d{4,12}\u0000)(?=\\d{4})", "*" )
.replaceAll( "\u0000([\\d*]+)\u0000", "$1" );
Not really readable, though, but it's all in one go.
A simple solution for a 16 char "number":
String masked = num.substring(0,6) + "******" + num.substring(12,16);
For a string of arbitrary length ( >10 ):
String masked = num.substring(0,6)
+ stars(num.length() - 10)
+ num.substring(num.length() - 6);
... where stars(int n) returns a String of n stars. See Simple way to repeat a String in java -- or if you don't mind a limit of 9 stars, "*********".substring(0,n)
Use a StringBuffer and overwrite the desired characters:
StringBuffer buf = new StringBuffer(num);
for(int i=4; i< buf.length() - 6) {
buf.setCharAt(i, '*');
}
return buf.toString();
You could also use buf.replace(int start, int end, String str)

Using regex to add a new line to a string every time each line reaches a certain length

I'm trying to ensure text does not appear outside of the window as the window size cannot be changed.
The image above shows what happens when the string of the order numbers exceeds the length of the window. I'm trying to ensure that when the length of the string of order numbers reaches a certain length, I use regex to make a new line for the next orders.
private String listOfOrders( Map<String, List<Integer> > map, String key )
{
String res = "";
if ( map.containsKey( key ))
{
List<Integer> orders = map.get(key);
for ( Integer i : orders )
{
res += " " + i + ",";
}
} else {
res = "-No key-";
}
return res;
}
}
This is the code to display the text, it works by forming the string res and filling it with the order numbers from the array list.
I found, through researching, a cool little piece of code which replaces a string every set amount of characters with itself plus a new line.
if(res.length() >= W-10)
{
res = res.replaceAll("(.{20})", "$1\n");
}
else
{
res += " " + i + ",";
}
But this has no effect at all. And I also realised that this code can not tell how long each line is because I'm using length to determine the length of each line and not how long each line is between each "\n".
My question is, how do I go about using regex to ensure each line in the string is a certain number of characters long? As my attempt does not work. The above just provides context as to why I want lines in a string a certain legnth.
Thanks!

Reversing the order of a string

So I'm still shaky on how basic java works, and here is a method I wrote but don't fully understand how it works anyone care to explain?
It's supposed to take a value of s in and return it in its reverse order.
Edit: Mainly the for loop is what is confusing me.
So say I input "12345" I would want my output to be "54321"
Public string reverse(String s){
String r = "";
for(int i=0; i<s.length(); i++){
r = s.charAt(i) + r;
}
return r;
}
We do a for loop to the last index of String a , add tha carater of index i to the String s , add here is a concatenation :
Example
String z="hello";
String x="world";
==> x+z="world hello" #different to z+x ="hello world"
for your case :
String s="";
String a="1234";
s=a.charAt(0)+s ==> s= "1" + "" = "1" ( + : concatenation )
s=a.charAt(1)+s ==> s='2'+"1" = "21" ( + : concatenation )
s=a.charAt(2)+s ==> s='3'+"21" = "321" ( + : concatenation )
s=a.charAt(3)+s ==> s='3'+"321" = "4321" ( + : concatenation )
etc..
public String reverse(String s){
String r = ""; //this is the ouput , initialized to " "
for(int i=0; i<s.length(); i++){
r = s.charAt(i) + r; //add to String r , the caracter of index i
}
return r;
}
What this code does is the following
Create a new variable r="";
then looping for the string in input lenght it adds at the beginning of r the current character of the loop.
i=0) r="1"
i=1) r="21"
i=2) r="321"
i=3) r="4321"
i=4) r="54321"
When you enter the loop you are having empty string in r.
Now r=""
In 1st iteration, you are taking first character (i=0) and appending r to it.
r = "1" + "";
Now r=1
In 2nd iteration, you are taking second character (i=1) and appending r to it
r = "2" + "1";
Now r=21
You can trace execution on a paper like this, then you will easily understand what is happening.
What the method is doing is taking the each character from the string s and putting it at the front of the new string r. Renaming the variables may help illustrate this.
public String reverse(String s){
String alreadyReversed = "";
for(int i=0; i<s.length(); i++){
//perform the following until count i is as long as string s
char thisCharacterInTheString = s.charAt(i); // for i==0 returns first
// character in passed String
alreadyReversed = thisCharacterInTheString + alreadyReversed;
}
return alreadyReversed;
}
So in the first iteration of the for loop alreadyReversed equals 1 + itself (an empty string).
In the second iteration alreadyReversed equals 2 + itself (1).
Then 3 + itself (21).
Then 4 + 321.
Then 5 + 4321.
GO back to your problem statement (take an input string and produce an output string in reverse order). Then consider how you would do this (not how to write Java code to do this).
You would probably come up with two alternatives:
Starting at the back of the input string, get one character at a time and form a new string (thus reversing its order).
Starting at the front of the string, get a character. Then for each next character, put it in front of all the characters you have created so far.
Your pseudo code results might be like the following
Option 1
let l = the length of the input string
set the output string to ""
while l > 0
add the "lth" character of the input string to the output string
subtract 1 from l
Option 2 left as an exercise for the questioner.
Then you would consider how to write Java to handle your algorithm. You will find that there are several ways to get the "lth" character of a string. First, in Java a string of length l has characters in position 0 through l-1. You can use string.charAt(loc) or string.substring(loc,loc+1) to get the character at position loc

Java codingbat help - withoutString

I'm using codingbat.com to get some java practice in. One of the String problems, 'withoutString' is as follows:
Given two strings, base and remove, return a version of the base string where all instances of the remove string have been removed (not case sensitive).
You may assume that the remove string is length 1 or more. Remove only non-overlapping instances, so with "xxx" removing "xx" leaves "x".
This problem can be found at: http://codingbat.com/prob/p192570
As you can see from the the dropbox-linked screenshot below, all of the runs pass except for three and a final one called "other tests." The thing is, even though they are marked as incorrect, my output matches exactly the expected output for the correct answer.
Here's a screenshot of my output:
And here's the code I'm using:
public String withoutString(String base, String remove) {
String result = "";
int i = 0;
for(; i < base.length()-remove.length();){
if(!(base.substring(i,i+remove.length()).equalsIgnoreCase(remove))){
result = result + base.substring(i,i+1);
i++;
}
else{
i = i + remove.length();
}
if(result.startsWith(" ")) result = result.substring(1);
if(result.endsWith(" ") && base.substring(i,i+1).equals(" ")) result = result.substring(0,result.length()-1);
}
if(base.length()-i <= remove.length() && !(base.substring(i).equalsIgnoreCase(remove))){
result = result + base.substring(i);
}
return result;
}
Your solution IS failing AND there is a display bug in coding bat.
The correct output should be:
withoutString("This is a FISH", "IS") -> "Th a FH"
Yours is:
withoutString("This is a FISH", "IS") -> "Th a FH"
Yours fails because it is removing spaces, but also, coding bat does not display the correct expected and run output string due to HTML removing extra spaces.
This recursive solution passes all tests:
public String withoutString(String base, String remove) {
int remIdx = base.toLowerCase().indexOf(remove.toLowerCase());
if (remIdx == -1)
return base;
return base.substring(0, remIdx ) +
withoutString(base.substring(remIdx + remove.length()) , remove);
}
Here is an example of an optimal iterative solution. It has more code than the recursive solution but is faster since far fewer function calls are made.
public String withoutString(String base, String remove) {
int remIdx = 0;
int remLen = remove.length();
remove = remove.toLowerCase();
while (true) {
remIdx = base.toLowerCase().indexOf(remove);
if (remIdx == -1)
break;
base = base.substring(0, remIdx) + base.substring(remIdx + remLen);
}
return base;
}
I just ran your code in an IDE. It compiles correctly and matches all tests shown on codingbat. There must be some bug with codingbat's test cases.
If you are curious, this problem can be solved with a single line of code:
public String withoutString(String base, String remove) {
return base.replaceAll("(?i)" + remove, ""); //String#replaceAll(String, String) with case insensitive regex.
}
Regex explaination:
The first argument taken by String#replaceAll(String, String) is what is known as a Regular Expression or "regex" for short.
Regex is a powerful tool to perform pattern matching within Strings. In this case, the regular expression being used is (assuming that remove is equal to IS):
(?i)IS
This particular expression has two parts: (?i) and IS.
IS matches the string "IS" exactly, nothing more, nothing less.
(?i) is simply a flag to tell the regex engine to ignore case.
With (?i)IS, all of: IS, Is, iS and is will be matched.
As an addition, this is (almost) equivalent to the regular expressions: (IS|Is|iS|is), (I|i)(S|s) and [Ii][Ss].
EDIT
Turns out that your output is not correct and is failing as expected. See: dansalmo's answer.
public String withoutString(String base, String remove) {
String temp = base.replaceAll(remove, "");
String temp2 = temp.replaceAll(remove.toLowerCase(), "");
return temp2.replaceAll(remove.toUpperCase(), "");
}
Please find below my solution
public String withoutString(String base, String remove) {
final int rLen=remove.length();
final int bLen=base.length();
String op="";
for(int i = 0; i < bLen;)
{
if(!(i + rLen > bLen) && base.substring(i, i + rLen).equalsIgnoreCase(remove))
{
i +=rLen;
continue;
}
op += base.substring(i, i + 1);
i++;
}
return op;
}
Something things go really weird on codingBat this is just one of them.
I am adding to a previous solution, but using a StringBuilder for better practice. Most credit goes to Anirudh.
public String withoutString(String base, String remove) {
//create a constant integer the size of remove.length();
final int rLen=remove.length();
//create a constant integer the size of base.length();
final int bLen=base.length();
//Create an empty string;
StringBuilder op = new StringBuilder();
//Create the for loop.
for(int i = 0; i < bLen;)
{
//if the remove string lenght we are looking for is not less than the base length
// and the base substring equals the remove string.
if(!(i + rLen > bLen) && base.substring(i, i + rLen).equalsIgnoreCase(remove))
{
//Increment by the remove length, and skip adding it to the string.
i +=rLen;
continue;
}
//else, we add the character at i to the string builder.
op.append(base.charAt(i));
//and increment by one.
i++;
}
//We return the string.
return op.toString();
}
Taylor's solution is the most efficient one, however I have another solution that is a naive one and it works.
public String withoutString(String base, String remove) {
String returnString = base;
while(returnString.toLowerCase().indexOf(remove.toLowerCase())!=-1){
int start = returnString.toLowerCase().indexOf(remove.toLowerCase());
int end = remove.length();
returnString = returnString.substring(0, start) + returnString.substring(start+end);
}
return returnString;
}
#Daemon
your code works. Thanks for the regex explanation. Though dansalmo pointed out that codingbat is displaying the intended output incorrectly, I through in some extra lines to your code to unnecessarily account for the double spaces with the following:
public String withoutString(String base, String remove){
String result = base.replaceAll("(?i)" + remove, "");
for(int i = 0; i < result.length()-1;){
if(result.substring(i,i+2).equals(" ")){
result = result.replace(result.substring(i,i+2), " ");
}
else i++;
}
if(result.startsWith(" ")) result = result.substring(1);
return result;
}
public String withoutString(String base, String remove){
return base.replace(remove,"");
}

Categories