Pattern Matcher - Split on specified length - java

I need to Split my string into some specified length(10 char).
Below is my code:
Pattern p = Pattern.compile(".{0,10}");
Matcher m = p.matcher("012345678901234567890123456");
List<String> emailStr = new ArrayList<String>();
while(m.find())
{
System.out.println(m.group());
}
As for my requirment I will get max of 3 Strings. I want to assign this "n" number of strings to separate variable. I donot have any idea on this. Please help on it.

You can use this do get what you want:
public static String[] splitter(String str, int len) {
String[] array = new String[(int) str.length() / len + 1];
for (int i = 0; i < str.length() / len + 1; i++) {
String s = "";
for (int j = 0; j < len; j++) {
int index = i * len + j;
if (index < str.length())
s += str.charAt(i * len + j);
else
break;
}
array[i] = s;
}
return array;
}

Building on the answer Jack gave:
public List<String> splitter(String str, int len) {
ArrayList<String> lst = new ArrayList<String>((str.length() - 1)/len + 1);
for (int i = 0; i < str.length(); i += len)
lst.add(str.substring(i, Math.min(str.length(), i + len)));
return lst;
}
Don't use a Pattern Matcher for this. Don't use regular expressions where they are not needed, in languages where regular expressions are not a fundamental concept. In perl, you do everything you can using regular expressions, but otherwise don't.

Related

Print the length of maximum subsequence of '1' s

import java.util.Scanner;
class Motu
{
// Returns length of the longest subsequence
// of the form 0*1*0*
public static int longestSubseq(String s)
{
int n = s.length();
int[] count_1 = new int[n + 1];
count_1[0] = 0;
for (int j = 1; j <= n; j++)
{
count_1[j] = count_1[j - 1];
if (s.charAt(j - 1) != '0')
count_1[j]++;
}
// Compute result using precomputed values
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
ans = Math.max(count_1[j] - count_1[i - 1] , ans);
return ans;
}
// Driver code
public static void main(String[] args)
{
#SuppressWarnings("resource")
Scanner sc=new Scanner(System.in);
String s =sc.next();
System.out.println(longestSubseq(s));
}
}
I am trying to make a program to get maximum sequences 1 in a string containing 0's & 1's. But I am unable to make out the logic for it, my program prints a number of 1's in the string which is not my desired output.
Sample input:- 0011100111100
output:- 4
You're quite good, but you're missing one thing : if the char is '0' : reset the counter to zero
for (int j = 1; j <= n; j++) {
if (s.charAt(j - 1) != '0')
count_1[j] = count_1[j - 1] + 1;
else
count_1[j] = 0;
}
But that can be done in one loop only, count with an int, and keep track of the max
public static int longestSubseq(String s) {
int ans = 0;
int count = 0;
for (char c : s.toCharArray()) {
if (c == '1')
count++;
else
count = 0;
ans = Math.max(ans, count);
}
return ans;
}
public static int longestSubSequence(String str, char ch) {
int res = 0;
int count = 0;
for (int i = 0; i < str.length(); i++) {
count = str.charAt(i) == ch ? count + 1 : 0;
res = Math.max(res, count);
}
return res;
}
The input string may be split by the characters that are not 1 (thus all non-1 characters are ignored and subsequences containing only 1 remain), and then the max length of the remaining parts can be found using Stream API:
public static int longestSubSequence(String str, char ch) {
return Arrays.stream(str.split("[^" + ch + "]"))
.mapToInt(String::length)
.max()
.orElse(0);
}
Similarly, a matching pattern can be created, and the max length of the group can be found:
public static int longestSubSequence(String str, char ch) {
return Pattern.compile(ch + "+")
.matcher(str)
.results()
.map(MatchResult::group)
.mapToInt(String::length)
.max()
.orElse(0);
}
Test:
System.out.println(longestSubSequence("00111011001111", '1')); // 4
It's worth mentioning that the characters other than '0' and '1' may be present in the input string, only subsequences of the given char are counted.
As an alternative to the other answers that work with a for-loop:
You could split the sequence into groups of ones with regex. Next, just iterate over the groups and update the count, if the length of the group is bigger than the previous length.
The first group will be 111 and the next one 1111. Thus the count will first be 3 and then it will be updated to 4.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class CountSubsequence {
public static void main(String []args){
String sequence = "0011100111100";
Pattern pattern = Pattern.compile("(1+)");
Matcher matcher = pattern.matcher(sequence);
int count = 0;
while (matcher.find()) {
int currentLength = matcher.group().length();
if (currentLength > count) count = currentLength;
}
System.out.println(count); // 4
}
}
Since regex is not that performant you might want to use the for-loop in case you care for performance - but that just matters if you execute it a lot.

Function is working in some cases but fails when longest sub-string "reuses" a character

I have a function called lengthOfLongestSubstring and its job is to find the longest substring without any repeated characters. For the most part, it works, but when it gets an input like "dvdf" it prints out 2 (rather than 3) and gives [dv, df] when it should be [d, vdf].
So, I first go through the string and see if there are any unique characters. If there are, I append it to the ans variable. (I think this is the part that needs some fixing). If there is a duplicate, I store it in the substrings linked list and reset the ans variable to the duplicate string.
Once the whole string has been traversed, I find the longest substring and return its length.
public static int lengthOfLongestSubstring(String s) {
String ans = "";
int len = 0;
LinkedList<String> substrings = new LinkedList<String>();
for (int i = 0; i < s.length(); i++) {
if (!ans.contains("" + s.charAt(i))) {
ans += s.charAt(i);
} else {
substrings.add(ans);
ans = "" + s.charAt(i);
}
}
substrings.add(ans); // add last seen substring into the linked list
for (int i = 0; i < substrings.size(); i++) {
if (substrings.get(i).length() >= len)
len = substrings.get(i).length();
}
System.out.println(Arrays.toString(substrings.toArray()));
return len;
}
Here are some test results:
//correct
lengthOfLongestSubstring("abcabcbb") -> 3 ( [abc, abc, b, b])
lengthOfLongestSubstring("pwwkew") -> 3 ([pw, wke, w]).
lengthOfLongestSubstring("ABDEFGABEF"); -> 6 ([ABDEFG, ABEF])
// wrong
System.out.println(lengthOfLongestSubstring("acadf")); -> 3, ([ac, adf]) *should be 4, with the linked list being [a, cadf]
Any suggestions to fix this? Do I have to redo all my logic?
Thanks!
You code is mistakenly assuming that when you find a repeated character, the next candidate substring starts at the repeated character. That is not true, it starts right after the original character.
Example: If string is "abcXdefXghiXjkl", there are 3 candidate substrings: "abcXdef", "defXghi", and "ghiXjkl".
As you can see, the candidate substrings ends before a repeating character and starts after a repeating character (and begin and end of string).
So, when you find a repeating character, the position of the previous instance of that character is needed to determine the start of the next substring candidate.
The easiest way to handle that, is to build a Map of character to last seen position. That will also perform faster than continually performing substring searches to check for repeating character, like the question code and the other answers are doing.
Something like this:
public static int lengthOfLongestSubstring(String s) {
Map<Character, Integer> charPos = new HashMap<>();
List<String> candidates = new ArrayList<>();
int start = 0, maxLen = 0;
for (int idx = 0; idx < s.length(); idx++) {
char ch = s.charAt(idx);
Integer preIdx = charPos.get(ch);
if (preIdx != null && preIdx >= start) { // found repeat
if (idx - start > maxLen) {
candidates.clear();
maxLen = idx - start;
}
if (idx - start == maxLen)
candidates.add(s.substring(start, idx));
start = preIdx + 1;
}
charPos.put(ch, idx);
}
if (s.length() - start > maxLen)
maxLen = s.length() - start;
if (s.length() - start == maxLen)
candidates.add(s.substring(start));
System.out.print(candidates + ": ");
return maxLen;
}
The candidates is only there for debugging purposes, and is not needed, so without that, the code is somewhat simpler:
public static int lengthOfLongestSubstring(String s) {
Map<Character, Integer> charPos = new HashMap<>();
int start = 0, maxLen = 0;
for (int idx = 0; idx < s.length(); idx++) {
char ch = s.charAt(idx);
Integer preIdx = charPos.get(ch);
if (preIdx != null && preIdx >= start) { // found repeat
if (idx - start > maxLen)
maxLen = idx - start;
start = preIdx + 1;
}
charPos.put(ch, idx);
}
return Math.max(maxLen, s.length() - start);
}
Test
System.out.println(lengthOfLongestSubstring(""));
System.out.println(lengthOfLongestSubstring("x"));
System.out.println(lengthOfLongestSubstring("xx"));
System.out.println(lengthOfLongestSubstring("xxx"));
System.out.println(lengthOfLongestSubstring("abcXdefXghiXjkl"));
System.out.println(lengthOfLongestSubstring("abcabcbb"));
System.out.println(lengthOfLongestSubstring("pwwkew"));
System.out.println(lengthOfLongestSubstring("ABDEFGABEF"));
Output (with candidate lists)
[]: 0
[x]: 1
[x, x]: 1
[x, x, x]: 1
[abcXdef, defXghi, ghiXjkl]: 7
[abc, bca, cab, abc]: 3
[wke, kew]: 3
[ABDEFG, BDEFGA, DEFGAB]: 6
Instead of setting ans to the current char when a character match is found
ans = "" + s.charAt(i);
You should add the current char to all the characters after the first match of the current char
ans = ans.substring(ans.indexOf(s.charAt(i)) + 1) + s.charAt(i);
The full method thus becomes
public static int lengthOfLongestSubstring(String s) {
String ans = "";
int len = 0;
LinkedList<String> substrings = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
if (!ans.contains("" + s.charAt(i))) {
ans += s.charAt(i);
} else {
substrings.add(ans);
// Only the below line changed
ans = ans.substring(ans.indexOf(s.charAt(i)) + 1) + s.charAt(i);
}
}
substrings.add(ans); // add last seen substring into the linked list
for (int i = 0; i < substrings.size(); i++) {
if (substrings.get(i).length() >= len)
len = substrings.get(i).length();
}
System.out.println(Arrays.toString(substrings.toArray()));
return len;
}
Using this code the acceptance criteria you specified passed successfully
//correct
lengthOfLongestSubstring("dvdf") -> 3 ( [dv, vdf])
lengthOfLongestSubstring("abcabcbb") -> 3 ([abc, bca, cab, abc, cb, b])
lengthOfLongestSubstring("pwwkew") -> 3 ([pw, wke, kew]).
lengthOfLongestSubstring("ABDEFGABEF"); -> 6 ([ABDEFG, BDEFGA, DEFGAB, FGABE, GABEF])
lengthOfLongestSubstring("acadf"); -> 4 ([ac, cadf])
Create a nested for loop to check at each index in the array.
public static int lengthOfLongestSubstring(String s) {
String ans = "";
int len = 0;
LinkedList<String> substrings = new LinkedList<String>();
int k = 0;
for (int i = 0; i < s.length(); i++) {
if(k == s.length()) {
break;
}
for(k = i; k < s.length(); k++) {
if (!ans.contains("" + s.charAt(k))) {
ans += s.charAt(k);
} else {
substrings.add(ans);
ans = "";
break;
}
}
}
substrings.add(ans); // add last seen substring into the linked list
for (int i = 0; i < substrings.size(); i++) {
if (substrings.get(i).length() >= len)
len = substrings.get(i).length();
}
System.out.println(Arrays.toString(substrings.toArray()));
return len;
}
Example:
lengthOfLongestSubstring("ABDEFGABEF"); -> 6 ([ABDEFG, BDEFGA, DEFGAB, EFGAB, FGABE, GABEF])

How to split a string into equal parts and store it in a string array

I'm fairly new to Java and am stuck on a particular homework question where a String gets passes and from there I have to split it into parts equal to an Integer that was passed.
For example: String "HelloWorld" is input and it has to be divided by 2 and those parts then have to be put into an array that has two parts like: array[hello, world].
Is there anyway to do this using a FOR loop?
My code so far enters the whole String into each array element. Here is my code:
String[] splitIntoParts(String word, int size) {
String[] array = new String[size];
for (int i = 0; i < array.length; i++) {
array[i] = word;
println(array[i]);;
}
return array;
}
There are many ways:
Here's the regex version:
public void splitEqual(String s){
int length = s.length();//Get string length
int whereToSplit;//store where will split
if(length%2==0) whereToSplit = length/2;//if length number is pair then it'll split equal
else whereToSplit = (length+1)/2;//else the first value will have one char more than the other
System.out.println(Arrays.toString(s.split("(?<=\\G.{"+whereToSplit+"})")));//split the string
}
\G is a zero-width assertion that matches the position where the previous match ended. If there was no previous match, it matches the beginning of the input, the same as \A. The enclosing lookbehind matches the position that's four characters along from the end of the last match.
Both lookbehind and \G are advanced regex features, not supported by all flavors. Furthermore, \G is not implemented consistently across the flavors that do support it. This trick will work (for example) in Java, Perl, .NET and JGSoft, but not in PHP (PCRE), Ruby 1.9+ or TextMate (both Oniguruma).
Using Substring:
/**
* Split String using substring, you'll have to tell where to split
* #param src String to split
* #param len where to split
* #return
*/
public static String[] split(String src, int len) {
String[] result = new String[(int)Math.ceil((double)src.length()/(double)len)];
for (int i=0; i<result.length; i++)
result[i] = src.substring(i*len, Math.min(src.length(), (i+1)*len));
return result;
}
You should also check this answer: Google Guava split
First check if the length of the string is a multiple of the divisor:
if(str.length() % divisor == 0)
Then you know that you can grab equal chunks of it. So you use substring to pull them out, in a loop.
while(str.length() > 0) {
String nextChunk = str.substring(0,divisor);
// store the chunk.
str = str.substring(divisor,str.length());
}
Will cycle through and grab a chunk that is divisor long each time.
Try the following application.It is dividing the provided word into equal parts based on the provided size per part
public class WordSpliter {
public static void main(String[] args) {
String[] words = new WordSpliter().splitter("abcdefghij", 4);
for(String s : words) System.out.println(s);
}
private String[] splitter(String word, int size) {
// Decide the size of the String array
int rest = word.length() % size;
int arrSize = ((word.length() - rest) / size) + 1;
// Declare the array and the start point of the word
String[] words = new String[arrSize];
int startPoint = 0;
for (int i = 0; i < words.length; i++) {
if (i + 1 == words.length) {
words[i] = word.substring(startPoint, startPoint + rest);
} else {
words[i] = word.substring(startPoint, startPoint + 4);
startPoint += 4;
}
}
return words;
}
}
Good Luck !!!!
You can use Brute force
public static List<String> splitStringEqually(String text, int size)
{
List<String> result = new ArrayList<String>((text.length() + size - 1) / size);
for (int i = 0; i < text.length(); i += size) {
result.add(text.substring(i, Math.min(text.length(), i + size)));
}
return result;
}
String s = "HelloWorld";
String firts_part=(String) s.subSequence(0, s.length() / 2);
String second_part=(String) s.subSequence((s.length() / 2)+1,s.length()-1 );
Try subSequence();
This is not plagarism, formatted the answer mentioned here - https://stackoverflow.com/a/3761521 as per the question.
public static void main(String[] args){
String str = "HelloWorld";
int parts = str.length()/3;
System.out.println(Arrays.toString(
str.split("(?<=\\G.{"+parts+"})")
));
}
Since length of a string is dived by 2
Code:
String st ="HelloWorld";
String firstPart = "";
String secondPart = "";
for (int j = 0; j < st.length(); j++) {
if ( j < st.length() /2) {
firstPart += st.charAt(j);
}else
secondPart += st.charAt(j);
}
System.out.println(firstPart);
System.out.println(secondPart);
Output:
Hello
World
Explanation: you add to firstPart String as long as your index has not met the middle index of the String. When it passed the middle index of String, you make the secondPart
Just looking at your input HelloWorld, You are trying to substring your input by Upper case letter.
You should go with that.
String str = "HelloWorldUser";
List<Integer> indexList = new ArrayList<>();
for (int i = 0; i < str.length(); i++) {
String temp = (str.charAt(i) + "").toUpperCase();
if (temp.equals(str.charAt(i) + "")) { // check for upper case letters
indexList.add(i);
}
}
List<String> subStrings = new LinkedList<>(); // to keep the insertion order
for (int i = indexList.size() - 1; i > -1; i--) { // substring reverse order
subStrings.add(str.substring(indexList.get(i)));
str=str.substring(0,indexList.get(i));
}
Collections.reverse(subStrings); // reverse to get original order
System.out.println(subStrings);
Out put:
[Hello, World, User]
If you want to get final result in to an array you can use
String[] arr= subStrings.toArray(new String[subStrings.size()]);
I figured it out. Here is my code:
String[] array = new String[size];
char[] charArray = new char[length(word)];
char[] temp = new char[length(word) / size];
int place = 0;
// turn the string into an array of chars
for (int i = 0; i < charArray.length; i++) {
charArray[i] = getChar(word, i);
}
// loop for each element of the desired string array
for (int i = 0; i < array.length; i++) {
// fill a temp array with the correct characters and the corect amount of characters
for (int j = 0; j < charArray.length / size; j++) {
temp[j] = charArray[place];
++place;
}
// insert the temp array into each element of the string array
array[i] = new String(temp);
}
return array;
A Simple solution is like
static void split(String str, int n) {
int partSize = str.length() / n;
while (str.length() - partSize > 0) {
String s = str.substring(0, partSize-1);
System.out.print(s + " ");
str = str.substring(partSize-1);
}
if (str.length() > 0) {
System.out.print(str);
}
}
You can do it using regex as follows:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
// Tests
System.out.println(Arrays.toString(splitIntoParts("HelloWorld", 5)));
System.out.println(Arrays.toString(splitIntoParts("HelloWorld", 4)));
System.out.println(Arrays.toString(splitIntoParts("HelloWorld", 2)));
}
static String[] splitIntoParts(String word, int size) {
return word.replaceAll("(.{" + size + "})", "$1\n").split("\n");
}
}
Output:
[Hello, World]
[Hell, oWor, ld]
[He, ll, oW, or, ld]

How do I find out the position of a char

I've got an String ("Dinosaur") and I don't exactly know how, but how do I get the position of the char "o" and is it in all possible to get two positions like if my String was ("Pool")
As for your first question, you can use String#indexOf(int) to get the index of every 'o' in your string.
int oPos = yourString.indexOf('o');
As for your second question, it is possible to get all positions of a given char by making a method which uses String.indexOf(int, int), tracking the previous index so that you don't repeat searched portions of the string. You could store the positions in an array or list.
Use indexOf with a loop:
String s = "Pool";
int idx = s.indexOf('o');
while (idx > -1) {
System.out.println(idx);
idx = s.indexOf('o', idx + 1);
}
Simply:
public static int[] getPositions(String word, char letter)
{
List<Integer> positions = new ArrayList<Integer>();
for(int i = 0; i < word.length(); i++) if(word.charAt(i) == letter) positions.add(i);
int[] result = new int[positions.size()];
for(int i = 0; i < positions.size(); i++) result[i] = positions.get(i);
return result;
}
This is probably going a little over board, but hey ;)
String master = "Pool";
String find = "o";
Pattern pattern = Pattern.compile(find);
Matcher matcher = pattern.matcher(master);
String match = null;
List<Integer[]> lstMatches = new ArrayList<Integer[]>(5);
while (matcher.find()) {
int startIndex = matcher.start();
int endIndex = matcher.end();
lstMatches.add(new Integer[] {startIndex, endIndex});
}
for (Integer[] indicies : lstMatches) {
System.out.println("Found " + find + " # " + indicies[0]);
}
Gives me
Found o # 1
Found o # 2
The great thing is, you could also find "oo" as well
Have you tried converting the String to a char array?
int counter = 0;
String input = "Pool";
for(char ch : input.toCharArray()) {
if(ch == 'o') {
System.out.println(counter);
}
counter += 1;
}
Try this
String s= "aloooha";
char array[] = s.toCharArray();
Stack stack = new Stack();
for (int i = 0; i < array.length; i++) {
if(array[i] == 'o'){
stack.push(i);
}
}
for (int i = 0; i < stack.size(); i++) {
System.out.println(stack.get(i));
}

Swapping elements in ArrayList

I want to write a method, which takes a String and swaps each pair of characters in it and then concatenates them into a new String. Please let me know how to fix this code (or write a new better one):
static String s;
public static void proc(String w) {
ArrayList k = new ArrayList();
ArrayList m = new ArrayList();
System.out.println(w.length());
int j = 0;
//test arraylist to check if string is written into arraylist
for (int i = 0; i < w.length(); i++){
k.add(w.charAt(i));
}
String p = k.get(2).toString();
System.out.println(p);
//here starts the logic of my app
for (int n = 0; n < w.length(); n++){
String v = k.get(n).toString();
if (n == 0){
m.add(1, v);
}
else if (n == 1){
m.add(0, v);
}
else if ((n % 2) == 0){
m.add(n+1, v);
}
else {
m.add(n, v);
}
}
}
public static void main(String[] args){
s = "tests";
proc(s);
}
Hi this is not a homework, but am doing exercises from a book. Anyway using code provided by Jon managed to work on my own - it may be not as much elegant but is doing the job using dynamic sizing as well:
public static void proc(String w) {
ArrayList k = new ArrayList();
ArrayList g = new ArrayList();
String h = "";
for (int i = 0; i < w.length(); i++){
char temp = w.charAt(i);
k.add(i, temp);
}
for (int i = 0; i < w.length(); i++){
if (i == 0){
h = k.get(1).toString();
g.add(h);
}
else if (i == 1){
h = k.get(0).toString();
g.add(h);
}
else if ((i % 2) == 0){
h = k.get(i+1).toString();
g.add(h);
}
else if ((i % 2) == 1){
h = k.get(i-1).toString();
g.add(h);
}
}
System.out.println(g.toString());
}
public static void main(String[] args){
s = "test";
proc(s);
}
I haven't tried to go through exactly how your code is trying to work, but it looks unnecessarily complicated to me. Given that you don't need dynamic sizing, you can do this more easily with an array:
public static String swapPairs(String input) {
char[] chars = input.toCharArray();
for (int i = 0; i < chars.length - 1; i += 2) {
char tmp = chars[i];
chars[i] = chars[i + 1];
chars[i + 1] = tmp;
}
return new String(chars);
}
Note that while this will work for "simple" characters (where each element of the array is independent of the rest), it doesn't try to take any form of "composite" characters into consideration, such as characters formed from two UTF-16 code units (surrogate pairs) or combined characters such as "e + acute accent". Doing this sort of contextually-aware swapping would take a lot more effort.
This looks like homework, so I'll limit my answer to a couple of hints.
I would accumulate the result in a StringBuilder (called sb in what follows).
I would have a loop (for i = 0; i < w.length(); i += 2). In this loop I would do two things:
if i + 1 is within the bounds of the string, I'd append the i + 1-th character to sb;
append the i-th character to sb.
At the end, call sb.toString().

Categories