Storing and printing consecutive characters in a String? - java

the task is to store consecutive characters in a List. Main with Input/Output looks like this:
public static void main(String[] args) {
List<String> blocks = blocks("Hello faaantastic world");
System.out.println(blocks); // => ["ll", "aaa"]
System.out.println(blocks("aaabccdeeeefaaa")); // => ["aaa", "cc", "eeee", "aaa"]
System.out.println(blocks("This is an example")); // => []
System.out.println(blocks("Another example ...")); // => [" ", "..."]
System.out.println(blocks("")); // => []
My method looks like this:
public static LinkedList<String> blocks(String s) {
LinkedList<String> list = new LinkedList<>();
String word = "";
for(char c : s.toCharArray()) {
if (c == ??) {
}
}
return list;
the String word is used to store consecutive letters. I found the toCharArray, to split each character of the String. But I have a problem with the if-block. If I do c == c+1 to check I and the following character of I, it's not working...I don't know how to solve this problem. Can someone help me? trying to solve it for 2 days now...

There are other ways to write this code, but to fully use what you have done, just cache the prevChar so you can compare c with it. How to init prevChar is tricky, either to choose something not possible in the text, or add another bool variable to indicate you are working on the first char, or peek into the array to make sure prevChar is different from the 1st char.

In this case it may be preferable to use String::charAt method to retrieve characters in the input string and their comparing to previous character.
public static LinkedList<String> blocks(String s) {
LinkedList<String> list = new LinkedList<>();
String word = "" + s.charAt(0);
for(int i = 1, n = s.length(); i < n; i++) {
if (s.charAt(i) == s.charAt(i - 1)) {
word += s.charAt(i);
} else {
if (word.length() > 1) {
list.add(word);
}
word = "" + s.charAt(i);
}
}
if (word.length() > 1) {
list.add(word);
}
return list;
}
Test
System.out.println(blocks("Hello faaantastic worlddd"));
Output
[ll, aaa, ddd]
A shorter solution is possible using a regular expression to find repeating characters (.)\1+:
public static List<String> findConsecutive(String s) {
return Pattern.compile("(.)\\1+").matcher(s).results() // Stream<MatchResult>
.map(mr -> mr.group(0)) // 0 group contains repeated characters
.collect(Collectors.toList());
}
Test
System.out.println(findConsecutive("Hello faaantastic worlddd"));
Output
[ll, , aaa, ddd]

Related

Print number of possible non-empty sequences of letters

I want to print number of possible non-empty sequences of letters .
Eg.
String str="ABC";
Expected output is
A,B,C
AB,AC,BC,BA,CA,CB
ABC,ACB,BAC,BCA,CAB,CBA`
But i get the below output which is incorrect. How to fix my code
BB CC A AB ACC BC ABC AC B BBC CCC BCC C CBC CB
I have written the below code using Recurion
String tiles = "ABC";
Set<String> ans = new HashSet<>();
solve(tiles, 0, "", ans);
public static void solve(String tiles, int idx, String output, Set<String> ans) {
ans.add(output);
if (idx >= tiles.length()) {
return;
}
for (int i = idx; i < tiles.length(); i++) {
solve(tiles, idx + 1, output + tiles.charAt(i), ans);
}
}
This is how recursion tree would look like for str="AAB"
You need to ignore the first passing of the "" from output and then you need to ignore each letter you already passed through
public static void main(String[] args) {
String tiles = "ABC";
List<String> ans = new ArrayList<>();
solve(tiles, "", ans);
System.out.println(ans);
}
public static void solve(String tiles, String output, List<String> ans) {
if (!output.equals("")) ans.add(output);
for (int i = 0; i < tiles.length(); i++) {
String str = tiles.substring(0, i) + tiles.substring(i + 1);
solve(str, output + tiles.charAt(i), ans);
}
}
Output
[A, AB, ABC, AC, ACB, B, BA, BAC, BC, BCA, C, CA, CAB, CB, CBA]
you can try this
public class Permutation {
public static List<String> getPermutations(String str) {
Set<String> permutations = new HashSet<>();
permute(str, "", permutations);
return new ArrayList<>(permutations);
}
private static void permute(String string, String prefix, Set<String> permutations) {
if (string.length() == 0) {
permutations.add(prefix);
} else {
for (int i = 0; i < string.length(); i++) {
char charAt = string.charAt(i);
String remainingString = string.substring(0, i) + string.substring(i + 1);
permute(remainingString, prefix + charAt, permutations);
}
}
}
}
The "permute" method takes in 3 parameters: a string, a prefix string and a set of permutations.
The "permute" method takes in 3 parameters: a string, a prefix string and a set of permutations.
If the input string is not empty, it uses a for loop to iterate through the characters of the input string.
For each iteration, it gets the character at the current index, creates a new string by removing that character from the input string.
it then calls the permute method 3 times:
it then calls the permute method 3 times:
One with the original string and prefix
One with the remaining string and prefix
This way, the function explores all the possible permutations of the characters in the input string, including the option of not having one of the characters in the permutation and the permutation of positions, without including an empty string as an option.
Then you use like:
Permutation p = new Permutation();
List<String> permutations = p.getPermutations("abc");
Make 1 change:
Set<String> ans = new TreeSet<>(Comparators.comparing(String::length).thenComparing(s -> s));
It's a quite popular backtracking problem. You can find almost same problem here:
https://leetcode.com/problems/subsets/
The input are numbers instead of characters but the idea is the same.
You can switch to the solution tab and explore different answers:
https://leetcode.com/problems/subsets/solutions/

How to convert given string in comma seperated characters in java?

public class StringDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String name = "String";
char[] c = name.toCharArray();
for (char ch : c) {
System.out.print(ch);
System.out.print(",");
}
}
}
This gives me output as
S,t,r,i,n,g,
I don't want that last comma, how to get output as S,t,r,i,n,g
You can also do it on a higher level without writing your own loop. It's not faster or anything, but the code is more clear about what it's doing: "Split my string into characters and join it back together, separated by commas!" ...
String name = "String";
String separated = String.join(",", name.split(""));
System.out.println(separated);
EDIT: String.join() is available from Java 1.8 and up.
I would personally use a StringBuilder for this task.
What you need, is to apply some logic that can distinguish whether or not a comma is needed. You loop through the characters just like you did and you always append a comma before the next character, except on the first iteration.
Example:
public static void main(String[] args) {
String test = "String";
StringBuilder sb = new StringBuilder();
for (char ch : test.toCharArray()) {
if (sb.length() != 0) {
sb.append(",");
}
sb.append(ch);
}
System.out.println(sb.toString());
}
Output:
S,t,r,i,n,g
Another way without StringBuilder and using just a traditional for loop, but using the same logic:
public static void main(String[] args) {
String test = "String";
char[] chars = test.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (i != 0) {
System.out.print(",");
}
System.out.print(chars[i]);
}
}
Output:
S,t,r,i,n,g
Sure, but for this you need a for loop based on the length of c, other solutions are not as straight IMHO:
String name="String";
char[] c = name.toCharArray();
for (int i = 0; i < c.length; i++){
char ch = c[i];
System.out.print(ch);
if( i != c.length -1 ){
System.out.print(",");
}
}
Some additional 2 Cents:
You can stream the character int values, map them to a List<String> where each element is a single char as String and finally use String.join(..., ...) in order to get the desired result, a comma separated String of all the characters in the original String:
public static void main(String[] args) {
// take an example String
String name = "Stringchars";
// make a list of characters as String of it by streaming the chars
List<String> nameCharsAsString = name.chars()
// mapping each one to a String
.mapToObj(e -> String.valueOf((char) e))
// and collect them in a list
.collect(Collectors.toList());
// then join the elements of that list to a comma separated String
String nameCharsCommaSeparated = String.join(",", nameCharsAsString);
// and print it
System.out.println(nameCharsCommaSeparated);
}
Running this code results in the following output:
S,t,r,i,n,g,c,h,a,r,s
This is just another possibility of getting your desired result, it is not necessarily the best solution.
You can use Stream to do that. Please check below,
String result = Arrays.stream(name.split("")).collect(Collectors.joining(","));
Output:
S,t,r,i,n,g

How to find first character after second dot java

Do you have any ideas how could I get first character after second dot of the string.
String str1 = "test.1231.asdasd.cccc.2.a.2";
String str2 = "aaa.1.22224.sadsada";
In first case I should get a and in second 2.
I thought about dividing string with dot, and extracting first character of third element. But it seems to complicated and I think there is better way.
How about a regex for this?
Pattern p = Pattern.compile(".+?\\..+?\\.(\\w)");
Matcher m = p.matcher(str1);
if (m.find()) {
System.out.println(m.group(1));
}
The regex says: find anything one or more times in a non-greedy fashion (.+?), that must be followed by a dot (\\.), than again anything one or more times in a non-greedy fashion (.+?) followed by a dot (\\.). After this was matched take the first word character in the first group ((\\w)).
Usually regex will do an excellent work here. Still if you are looking for something more customizable then consider the following implementation:
private static int positionOf(String source, String target, int match) {
if (match < 1) {
return -1;
}
int result = -1;
do {
result = source.indexOf(target, result + target.length());
} while (--match > 0 && result > 0);
return result;
}
and then the test is done with:
String str1 = "test..1231.asdasd.cccc..2.a.2.";
System.out.println(positionOf(str1, ".", 3)); -> // prints 10
System.out.println(positionOf(str1, "c", 4)); -> // prints 21
System.out.println(positionOf(str1, "c", 5)); -> // prints -1
System.out.println(positionOf(str1, "..", 2)); -> // prints 22 -> just have in mind that the first symbol after the match is at position 22 + target.length() and also there might be none element with such index in the char array.
Without using pattern, you can use subString and charAt method of String class to achieve this
// You can return String instead of char
public static char returnSecondChar(String strParam) {
String tmpSubString = "";
// First check if . exists in the string.
if (strParam.indexOf('.') != -1) {
// If yes, then extract substring starting from .+1
tmpSubString = strParam.substring(strParam.indexOf('.') + 1);
System.out.println(tmpSubString);
// Check if second '.' exists
if (tmpSubString.indexOf('.') != -1) {
// If it exists, get the char at index of . + 1
return tmpSubString.charAt(tmpSubString.indexOf('.') + 1);
}
}
// If 2 '.' don't exists in the string, return '-'. Here you can return any thing
return '-';
}
You could do it by splitting the String like this:
public static void main(String[] args) {
String str1 = "test.1231.asdasd.cccc.2.a.2";
String str2 = "aaa.1.22224.sadsada";
System.out.println(getCharAfterSecondDot(str1));
System.out.println(getCharAfterSecondDot(str2));
}
public static char getCharAfterSecondDot(String s) {
String[] split = s.split("\\.");
// TODO check if there are values in the array!
return split[2].charAt(0);
}
I don't think it is too complicated, but using a directly matching regex is a very good (maybe better) solution anyway.
Please note that there might be the case of a String input with less than two dots, which would have to be handled (see TODO comment in the code).
You can use Java Stream API since Java 8:
String string = "test.1231.asdasd.cccc.2.a.2";
Arrays.stream(string.split("\\.")) // Split by dot
.skip(2).limit(1) // Skip 2 initial parts and limit to one
.map(i -> i.substring(0, 1)) // Map to the first character
.findFirst().ifPresent(System.out::println); // Get first and print if exists
However, I recommend you to stick with Regex, which is safer and a correct way to do so:
Here is the Regex you need (demo available at Regex101):
.*?\..*?\.(.).*
Don't forget to escape the special characters with double-slash \\.
String[] array = new String[3];
array[0] = "test.1231.asdasd.cccc.2.a.2";
array[1] = "aaa.1.22224.sadsada";
array[2] = "test";
Pattern p = Pattern.compile(".*?\\..*?\\.(.).*");
for (int i=0; i<array.length; i++) {
Matcher m = p.matcher(array[i]);
if (m.find()) {
System.out.println(m.group(1));
}
}
This code prints two results on each line: a, 2 and an empty lane because on the 3rd String, there is no match.
A plain solution using String.indexOf:
public static Character getCharAfterSecondDot(String s) {
int indexOfFirstDot = s.indexOf('.');
if (!isValidIndex(indexOfFirstDot, s)) {
return null;
}
int indexOfSecondDot = s.indexOf('.', indexOfFirstDot + 1);
return isValidIndex(indexOfSecondDot, s) ?
s.charAt(indexOfSecondDot + 1) :
null;
}
protected static boolean isValidIndex(int index, String s) {
return index != -1 && index < s.length() - 1;
}
Using indexOf(int ch) and indexOf(int ch, int fromIndex) needs only to examine all characters in worst case.
And a second version implementing the same logic using indexOf with Optional:
public static Character getCharAfterSecondDot(String s) {
return Optional.of(s.indexOf('.'))
.filter(i -> isValidIndex(i, s))
.map(i -> s.indexOf('.', i + 1))
.filter(i -> isValidIndex(i, s))
.map(i -> s.charAt(i + 1))
.orElse(null);
}
Just another approach, not a one-liner code but simple.
public class Test{
public static void main (String[] args){
for(String str:new String[]{"test.1231.asdasd.cccc.2.a.2","aaa.1.22224.sadsada"}){
int n = 0;
for(char c : str.toCharArray()){
if(2 == n){
System.out.printf("found char: %c%n",c);
break;
}
if('.' == c){
n ++;
}
}
}
}
}
found char: a
found char: 2

Replace part of the string from reference string

I have a String ArrayList consisting alphabets followed by a digit as a suffix to each of the alphabet.
ArrayList <String> baseOctave = new ArrayList();
baseOctave.add("S1");
baseOctave.add("R2");
baseOctave.add("G4");
baseOctave.add("M2");
baseOctave.add("P3");
baseOctave.add("D1");
baseOctave.add("N1");
I pass the strings from this baseOctave and few other characters as input pattern for creating an object.
MyClass obj1 = new MyClass ("S1,,R2.,M2''-");
Since I frequently make use of these kind of input patterns during object instantiation, I would like to use simple characters S, R, G, M etc.
Ex:
MyClass obj1 = new MyClass ("S,,R.,M''-");
MyClass obj2 = new MyClass ("S1,G.,M,D1");
So the alphabets used during object creation may contain digits as suffix or it may not have digit as suffix.
But inside the constructor (or in separate method), I would like to replace these simple alphabets with alphabets having suffix. The suffix is taken from the baseOctave.
Ex: above two strings in obj1 and obj2 should be "S1,,R2.,M2''-" and "S1,G4.,M2,D1"
I tied to do this, but could not continue the code below. Need some help for replacing please..
static void addSwaraSuffix(ArrayList<String> pattern) {
for (int index = 0; index < pattern.size(); index++) {
// Get the patterns one by one from the arrayList and verify and manipulate if necessary.
String str = pattern.get(index);
// First see if the second character in Array List element is digit or not.
// If digit, nothing should be done.
//If not, replace/insert the corresponding index from master list
if (Character.isDigit(str.charAt(1)) != true) {
// Replace from baseOctave.
str = str.replace(str.charAt(0), ?); // replace with appropriate alphabet having suffix from baseOctave.
// Finally put the str back to arrayList.
pattern.set(index, str);
}
}
}
Edited information is below:
Thanks for the answer. I found another solution and works fine. below is the complete code that I found working. Let me know if there is any issue.
static void addSwaraSuffix(ArrayList<String> inputPattern, ArrayList<String> baseOctave) {
String temp = "";
String str;
for (int index = 0; index < inputPattern.size(); index++) {
str = inputPattern.get(index);
// First see if the second character in Array List is digit or not.
// If digit, nothing should be done. If not, replace/insert the corresponding index from master list
// Sometimes only one swara might be there. Ex: S,R,G,M,P,D,N
if (((str.length() == 1)) || (Character.isDigit(str.charAt(1)) != true)) {
// Append with index.
// first find the corresponsing element to be replaced from baseOctave.
for (int index2 = 0; index2 < baseOctave.size(); index2++) {
if (baseOctave.get(index2).startsWith(Character.toString(str.charAt(0)))) {
temp = baseOctave.get(index2);
break;
}
}
str = str.replace(Character.toString(str.charAt(0)), temp);
}
inputPattern.set(index, str);
}
}
I assume that abbreviation is only one character and that in full pattern second character is always digit. Code below relies on this assumptions, so please inform me if they are wrong.
static String replace(String string, Collection<String> patterns) {
Map<Character, String> replacements = new HashMap<Character, String>(patterns.size());
for (String pattern : patterns) {
replacements.put(pattern.charAt(0), pattern);
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
Character c = string.charAt(i);
char next = i < string.length() - 1 ? string.charAt(i + 1) : ' ';
String replacement = replacements.get(c);
if (replacement != null && (next <= '0' || next >= '9')) {
result.append(replacement);
} else {
result.append(c);
}
}
return result.toString();
}
public static void main(String[] args) {
ArrayList<String> baseOctave = new ArrayList<String>();
baseOctave.add("S1");
baseOctave.add("R2");
baseOctave.add("G4");
baseOctave.add("M2");
baseOctave.add("P3");
baseOctave.add("D1");
baseOctave.add("N1");
System.out.println(replace("S,,R.,M''-", baseOctave));
System.out.println(replace("S1,G.,M,D1", baseOctave));
System.out.println(replace("", baseOctave));
System.out.println(replace("S", baseOctave));
}
Results:
S1,,R2.,M2''-
S1,G4.,M2,D1
S1

Matching the occurrence and pattern of characters of String2 in String1

I was asked this question in a phone interview for summer internship, and tried to come up with a n*m complexity solution (although it wasn't accurate too) in Java.
I have a function that takes 2 strings, suppose "common" and "cmn". It should return True based on the fact that 'c', 'm', 'n' are occurring in the same order in "common". But if the arguments were "common" and "omn", it would return False because even though they are occurring in the same order, but 'm' is also appearing after 'o' (which fails the pattern match condition)
I have worked over it using Hashmaps, and Ascii arrays, but didn't get a convincing solution yet! From what I have read till now, can it be related to Boyer-Moore, or Levenshtein Distance algorithms?
Hoping for respite at stackoverflow! :)
Edit: Some of the answers talk about reducing the word length, or creating a hashset. But per my understanding, this question cannot be done with hashsets because occurrence/repetition of each character in first string has its own significance. PASS conditions- "con", "cmn", "cm", "cn", "mn", "on", "co". FAIL conditions that may seem otherwise- "com", "omn", "mon", "om". These are FALSE/FAIL because "o" is occurring before as well as after "m". Another example- "google", "ole" would PASS, but "google", "gol" would fail because "o" is also appearing before "g"!
I think it's quite simple. Run through the pattern and fore every character get the index of it's last occurence in the string. The index must always increase, otherwise return false.
So in pseudocode:
index = -1
foreach c in pattern
checkindex = string.lastIndexOf(c)
if checkindex == -1 //not found
return false
if checkindex < index
return false
if string.firstIndexOf(c) < index //characters in the wrong order
return false
index = checkindex
return true
Edit: you could further improve the code by passing index as the starting index to the lastIndexOf method. Then you would't have to compare checkindex with index and the algorithm would be faster.
Updated: Fixed a bug in the algorithm. Additional condition added to consider the order of the letters in the pattern.
An excellent question and couple of hours of research and I think I have found the solution. First of all let me try explaining the question in a different approach.
Requirement:
Lets consider the same example 'common' (mainString) and 'cmn'(subString). First we need to be clear that any characters can repeat within the mainString and also the subString and since its pattern that we are concentrating on, the index of the character play a great role to. So we need to know:
Index of the character (least and highest)
Lets keep this on hold and go ahead and check the patterns a bit more. For the word common, we need to find whether the particular pattern cmn is present or not. The different patters possible with common are :- (Precedence apply )
c -> o
c -> m
c -> n
o -> m
o -> o
o -> n
m -> m
m -> o
m -> n
o -> n
At any moment of time this precedence and comparison must be valid. Since the precedence plays a huge role, we need to have the index of each unique character Instead of storing the different patterns.
Solution
First part of the solution is to create a Hash Table with the following criteria :-
Create a Hash Table with the key as each character of the mainString
Each entry for a unique key in the Hash Table will store two indices i.e lowerIndex and higherIndex
Loop through the mainString and for every new character, update a new entry of lowerIndex into the Hash with the current index of the character in mainString.
If Collision occurs, update the current index with higherIndex entry, do this until the end of String
Second and main part of pattern matching :-
Set Flag as False
Loop through the subString and for
every character as the key, retreive
the details from the Hash.
Do the same for the very next character.
Just before loop increment, verify two conditions
If highestIndex(current character) > highestIndex(next character) Then
Pattern Fails, Flag <- False, Terminate Loop
// This condition is applicable for almost all the cases for pattern matching
Else If lowestIndex(current character) > lowestIndex(next character) Then
Pattern Fails, Flag <- False, Terminate Loop
// This case is explicitly for cases in which patterns like 'mon' appear
Display the Flag
N.B : Since I am not so versatile in Java, I did not submit the code. But some one can try implementing my idea
I had myself done this question in an inefficient manner, but it does give accurate result! I would appreciate if anyone can make out an an efficient code/algorithm from this!
Create a function "Check" which takes 2 strings as arguments. Check each character of string 2 in string 1. The order of appearance of each character of s2 should be verified as true in S1.
Take character 0 from string p and traverse through the string s to find its index of first occurrence.
Traverse through the filled ascii array to find any value more than the index of first occurrence.
Traverse further to find the last occurrence, and update the ascii array
Take character 1 from string p and traverse through the string s to find the index of first occurence in string s
Traverse through the filled ascii array to find any value more than the index of first occurrence. if found, return False.
Traverse further to find the last occurrence, and update the ascii array
As can be observed, this is a bruteforce method...I guess O(N^3)
public class Interview
{
public static void main(String[] args)
{
if (check("google", "oge"))
System.out.println("yes");
else System.out.println("sorry!");
}
public static boolean check (String s, String p)
{
int[] asciiArr = new int[256];
for(int pIndex=0; pIndex<p.length(); pIndex++) //Loop1 inside p
{
for(int sIndex=0; sIndex<s.length(); sIndex++) //Loop2 inside s
{
if(p.charAt(pIndex) == s.charAt(sIndex))
{
asciiArr[s.charAt(sIndex)] = sIndex; //adding char from s to its Ascii value
for(int ascIndex=0; ascIndex<256; ) //Loop 3 for Ascii Array
{
if(asciiArr[ascIndex]>sIndex) //condition to check repetition
return false;
else ascIndex++;
}
}
}
}
return true;
}
}
Isn't it doable in O(n log n)?
Step 1, reduce the string by eliminating all characters that appear to the right. Strictly speaking you only need to eliminate characters if they appear in the string you're checking.
/** Reduces the maximal subsequence of characters in container that contains no
* character from container that appears to the left of the same character in
* container. E.g. "common" -> "cmon", and "whirlygig" -> "whrlyig".
*/
static String reduceContainer(String container) {
SparseVector charsToRight = new SparseVector(); // Like a Bitfield but sparse.
StringBuilder reduced = new StringBuilder();
for (int i = container.length(); --i >= 0;) {
char ch = container.charAt(i);
if (charsToRight.add(ch)) {
reduced.append(ch);
}
}
return reduced.reverse().toString();
}
Step 2, check containment.
static boolean containsInOrder(String container, String containee) {
int containerIdx = 0, containeeIdx = 0;
int containerLen = container.length(), containeeLen == containee.length();
while (containerIdx < containerLen && containeeIdx < containeeLen) {
// Could loop over codepoints instead of code-units, but you get the point...
if (container.charAt(containerIdx) == containee.charAt(containeeIdx)) {
++containeeIdx;
}
++containerIdx;
}
return containeeIdx == containeeLen;
}
And to answer your second question, no, Levenshtein distance won't help you since it has the property that if you swap the arguments the output is the same, but the algo you want does not.
public class StringPattern {
public static void main(String[] args) {
String inputContainer = "common";
String inputContainees[] = { "cmn", "omn" };
for (String containee : inputContainees)
System.out.println(inputContainer + " " + containee + " "
+ containsCommonCharsInOrder(inputContainer, containee));
}
static boolean containsCommonCharsInOrder(String container, String containee) {
Set<Character> containerSet = new LinkedHashSet<Character>() {
// To rearrange the order
#Override
public boolean add(Character arg0) {
if (this.contains(arg0))
this.remove(arg0);
return super.add(arg0);
}
};
addAllPrimitiveCharsToSet(containerSet, container.toCharArray());
Set<Character> containeeSet = new LinkedHashSet<Character>();
addAllPrimitiveCharsToSet(containeeSet, containee.toCharArray());
// retains the common chars in order
containerSet.retainAll(containeeSet);
return containerSet.toString().equals(containeeSet.toString());
}
static void addAllPrimitiveCharsToSet(Set<Character> set, char[] arr) {
for (char ch : arr)
set.add(ch);
}
}
Output:
common cmn true
common omn false
I would consider this as one of the worst pieces of code I have ever written or one of the worst code examples in stackoverflow...but guess what...all your conditions are met!
No algorithm could really fit the need, so I just used bruteforce...test it out...
And I could just care less for space and time complexity...my aim was first to try and solve it...and maybe improve it later!
public class SubString {
public static void main(String[] args) {
SubString ss = new SubString();
String[] trueconditions = {"con", "cmn", "cm", "cn", "mn", "on", "co" };
String[] falseconditions = {"com", "omn", "mon", "om"};
System.out.println("True Conditions : ");
for (String str : trueconditions) {
System.out.println("SubString? : " + str + " : " + ss.test("common", str));
}
System.out.println("False Conditions : ");
for (String str : falseconditions) {
System.out.println("SubString? : " + str + " : " + ss.test("common", str));
}
System.out.println("SubString? : ole : " + ss.test("google", "ole"));
System.out.println("SubString? : gol : " + ss.test("google", "gol"));
}
public boolean test(String original, String match) {
char[] original_array = original.toCharArray();
char[] match_array = match.toCharArray();
int[] value = new int[match_array.length];
int index = 0;
for (int i = 0; i < match_array.length; i++) {
for (int j = index; j < original_array.length; j++) {
if (original_array[j] != original_array[j == 0 ? j : j-1] && contains(match.substring(0, i), original_array[j])) {
value[i] = 2;
} else {
if (match_array[i] == original_array[j]) {
if (value[i] == 0) {
if (contains(original.substring(0, j == 0 ? j : j-1), match_array[i])) {
value[i] = 2;
} else {
value[i] = 1;
}
}
index = j + 1;
}
}
}
}
for (int b : value) {
if (b != 1) {
return false;
}
}
return true;
}
public boolean contains(String subStr, char ch) {
for (char c : subStr.toCharArray()) {
if (ch == c) {
return true;
}
}
return false;
}
}
-IvarD
I think this one is not a test of your computer science fundamentals, more what you would practically do within the Java programming environment.
You could construct a regular expression out of the second argument, i.e ...
omn -> o.*m[^o]*n
... and then test candidate string against this by either using String.matches(...) or using the Pattern class.
In generic form, the construction of the RegExp should be along the following lines.
exp -> in[0].* + for each x : 2 -> in.lenght { (in[x-1] +
[^in[x-2]]* + in[x]) }
for example:
demmn -> d.*e[^d]*m[^e]*m[^m]*n
I tried it myself in a different way. Just sharing my solution.
public class PatternMatch {
public static boolean matchPattern(String str, String pat) {
int slen = str.length();
int plen = pat.length();
int prevInd = -1, curInd;
int count = 0;
for (int i = 0; i < slen; i++) {
curInd = pat.indexOf(str.charAt(i));
if (curInd != -1) {
if(prevInd == curInd)
continue;
else if(curInd == (prevInd+1))
count++;
else if(curInd == 0)
count = 1;
else count = 0;
prevInd = curInd;
}
if(count == plen)
return true;
}
return false;
}
public static void main(String[] args) {
boolean r = matchPattern("common", "on");
System.out.println(r);
}
}

Categories