My Question would be how can replace every 3rd ';' from a String a put a ',' at this position ?
for eg.:
String s = "RED;34;34;BLUE;44;44;GREEN;8;8;BLUE;53;53"
so that the String looks like:
RED;34;34,BLUE;44;44,GREEN;8;8,BLUE;53;53
I tried to solve it like this but i can't take a charAt(i) and replace it with an other char.
int counter =0;
for (int i=0;i<s.length();i++){
if(s.charAt(i) == ';'){
counter++;
}
if(counter ==3){
s.charAt(i)=',';
counter =0;
}
}
Normally some own effort is demanded from the question, but regex is hard.
s = s.replaceAll("([^;]*;[^;]*;[^;]*);", "$1,");
A sequence of 0 or more of not-semicolon followed by semicolon and such.
[^ ...characters... ] is some char not listed.
...* is zero or more of the immediately preceding match.
The match of the 1st group (...) is given in $1, so actually only the last semicolon is replaced by a comma.
You can use the modulo % operator to know the 3rd time something occurs. And a simple conversion between string and char array to do the rest:
class Main {
public static void main(String[] args) {
String s1 = "RED;34;34;BLUE;44;44;GREEN;8;8;BLUE;53;53";
char [] s = s1.toCharArray();
int j=0;
for(int i=0;i<s.length;i++){
if (s[i]==';') {
j++;
if(j % 3 == 0) {
s[i] = ',';
}
}
}
System.out.println(s);
}
}
There are many ways to do it, as I suggested in a comment. Here are implementations of the ones I suggested, but there are of course more ways than this.
The first is the simplest, from a code point of view, if you know regex. See answer by Joop Eggen for an explanation.
The second is likely the fastest, especially if you eliminate the % modulo operator by resetting j to 0 instead.
private static String usingRegex(String s) {
return s.replaceAll("([^;]*;[^;]*;[^;]*);", "$1,");
}
private static String usingCharArray(String s) {
char[] arr = s.toCharArray();
for (int i = 0, j = 0; i < arr.length; i++)
if (arr[i] == ';' && ++j % 3 == 0)
arr[i] = ',';
return new String(arr);
}
private static String usingStringBuilder(String s) {
StringBuilder sb = new StringBuilder(s);
for (int i = 0, j = 0; i < sb.length(); i++)
if (sb.charAt(i) == ';' && ++j % 3 == 0)
sb.setCharAt(i, ',');
return sb.toString();
}
private static String usingSubstring(String s) {
int i = -1, j = 0;
while ((i = s.indexOf(';', i + 1)) != -1)
if (++j % 3 == 0)
s = s.substring(0, i) + ',' + s.substring(i + 1);
return s;
}
Test
String s = "RED;34;34;BLUE;44;44;GREEN;8;8;BLUE;53;53";
System.out.println(usingRegex(s));
System.out.println(usingCharArray(s));
System.out.println(usingStringBuilder(s));
System.out.println(usingSubstring(s));
Output
RED;34;34,BLUE;44;44,GREEN;8;8,BLUE;53;53
RED;34;34,BLUE;44;44,GREEN;8;8,BLUE;53;53
RED;34;34,BLUE;44;44,GREEN;8;8,BLUE;53;53
RED;34;34,BLUE;44;44,GREEN;8;8,BLUE;53;53
Not that elegant like by #Joop, but probably simplier to understand:
String s = "RED;34;34;BLUE;44;44;GREEN;8;8;BLUE;53;53";
char[] chars = s.toCharArray();
int counter = 1;
for (int i = 0; i < chars.length; i++){
if (chars[i] == ';'){
if (counter == 3){
chars[i] = ','; // replace ';' with ','
counter = 1; // set counter to 1
}else {
counter++;
}
}
}
String output = String.valueOf(chars);
System.out.println(output); // RED;34;34,BLUE;44;44,GREEN;8;8,BLUE;53;53
Related
This question already has answers here:
Continue at first loop , inside the second loop
(7 answers)
Closed 1 year ago.
For this code kata I need to continue 2 for loops at the same time. How can I do that?
public class StringMerger {
public static boolean isMerge(String s, String part1, String part2) {
StringBuilder MergedWord = new StringBuilder("");
String Whole = part1+part2;
for(int j = 0; j < Whole.length(); j++){
for(int I = 0; I < part1.length(); I++){
if((Character.compare(s.charAt(j), part1.charAt(I)) == 0) && (j == I)){
MergedWord.append(s.charAt(I)+"");
continue;
}
else
break;
}
for(int i = 0; i < part2.length(); i++){
if((Character.compare(s.charAt(j), part2.charAt(i)) == 0) && (j == i)){
MergedWord.append(part2.charAt(i) + "");
continue;
}
else
break;
}
}
return s.equals(MergedWord.toString())? true : false;
}
}
I noticed when one of the for loops continue it only continues the internal loop, but labels would continue the upper loop and would be inefficient. Could I continue 2 for loops at the same time a.k.a continue the inner and upper loop in this nested for loop?
The task is to match each character in the target string, so you only need one loop, which iterates over the characters in the string. You do need two other loop variables to track how much of the two source strings have been used up.
My solution below is looping over three things at once: the target string and the two 'part' strings. The rate it moves over the 'part' strings isn't constant, but it does progress over them monotonically.
It wasn't clear to me whether the source strings could include extra characters not used in the target string. As the example didn't show any, I assumed not.
public class MergedStringChecker {
public static void main(String[] args) {
String target = "codewars";
String part1 = "cdw";
String part2 = "oears";
for (int i = 0, p1 = 0, p2 = 0; i < target.length(); ++i) {
if (p1 < part1.length() && target.charAt(i) == part1.charAt(p1)) {
++p1;
} else if (p2 < part2.length() && target.charAt(i) == part2.charAt(p2)) {
++p2;
} else {
throw new RuntimeException("No matching characters at index " + i);
}
}
}
}
The above solution is not Unicode safe if the string contains > 16 bit code points.
Try this.
public static boolean isMerge(String s, String part1, String part2) {
int length = s.length();
int length1 = part1.length();
int length2 = part2.length();
int i1 = 0, i2 = 0;
for (int i = 0; i < length; ++i)
if (i1 < length1 && s.charAt(i) == part1.charAt(i1))
++i1;
else if (i2 < length2 && s.charAt(i) == part2.charAt(i2))
++i2;
else
return false;
return i1 == length1 && i2 == length2;
}
public static void main(String[] args) throws IOException {
System.out.println(isMerge("codewars", "cdw", "oears"));
System.out.println(isMerge("codewars", "codewars", ""));
System.out.println(isMerge("codewars", "cdw", "oearsEXTRA"));
}
output:
true
true
false
you have an error on the first part loop you must append from the part not the s char
you don't need to chek the id of the part with the inital word (remove this check (j == I) and this one (j == i)
Use counter to avoid looping many times
Try this code :
public static boolean isMerge(String s, String part1, String part2) {
StringBuilder MergedWord = new StringBuilder("");
String Whole = part1+part2;
int counter1=0;
int counter2=0;
for(int w = 0; w < Whole.length(); w++){
for(int c1 = counter1; c1 < part1.length(); c1++){
if((s.charAt(w) == part1.charAt(c1)) ){
MergedWord.append(part1.charAt(c1)+"");
counter1++;
continue;
}
else
break;
}
for(int c2 = counter2; c2 < part2.length(); c2++){
if((s.charAt(w) == part2.charAt(c2)) ){
MergedWord.append(part2.charAt(c2) + "");
counter2++;
continue;
}
else
break;
}
}
return s.equals(MergedWord.toString())? true : false;
}
I'm trying to write a non-recursive Java method called showStar, which takes a string, and generates ALL possible combinations of that string without the mask “*” characters.
receiving this as an input "1011*00*10",
the method `showStar` will display output like:
1011000010
1011000110
1011100010
1011100110
I tried this way, however, as soon as the number of possible cases is more than the String length, the output is not exact.
Here is my code.
public static void showStar(String s){
String save;
int count = 0;
int poss;
save = s.replace('*','0');
StringBuilder myString = new StringBuilder(save);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '*' && myString.charAt(i) == '0') {
myString.setCharAt(i, '1');
System.out.println(myString);
}
}
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '*' && myString.charAt(i) == '1') {
myString.setCharAt(i, '0');
System.out.println(myString);
}
}
}
Say there are k *s. Then there are 2^k solutions. You can generate these by copying the bits from the integers 0 - 2^k-1 in order. (adding sufficient leading zeroes)
E.g. 1**1:
0 = 00 => 1001
1 = 01 => 1011
2 = 10 => 1101
3 = 11 => 1111
Here a recursive algoritm works just perfectly:
You check if an input string contains an asterisk '*' by using an x = str.indexOf('*');
If no asterisk is present (x == -1), you just print the string and return
Otherwise, you replace the asterisk at the position to '0' and '1' and call showStar() recursively for both replacements
public static void showStar(String str) {
int x = str.indexOf('*');
if(x == -1) {
System.out.println(str);
return;
}
String prefix = str.substring(0, x);
String suffix = str.substring(x + 1);
for (char i = '0'; i <= '1'; i++) {
showStar(prefix + i + suffix);
}
}
Update
In non-recursive implementation we need to collect the asterisk positions, then prepare a binary representation and set appropriate bits at the known positions:
public static void showStar(String str) {
int[] xs = IntStream.range(0, str.length())
.filter(i -> str.charAt(i) == '*')
.toArray();
int num = (int) Math.pow(2, xs.length); // 2^n variants for n asterisks
String format = xs.length > 0 ? "%" + xs.length + "s" : "%s"; // fix if no '*'
for (int i = 0; i < num; i++) {
String bin = String.format(format, Integer.toBinaryString(i))
.replace(' ', '0'); // pad leading zeros
StringBuilder sb = new StringBuilder(str);
// set 0 or 1 in place of asterisk(s)
for (int j = 0; j < xs.length; j++) {
sb.setCharAt(xs[j], bin.charAt(j));
}
System.out.println(sb);
}
}
I have a String of a length of more than 1000 character. In this string i have to print 1st character after that every 5th character.
I tried writing a program to iterate from 0th character to last character and have a count variable.
If count is equal to 5. I am printing the character and count is initializing with 0.
private static String getMaskedToken(String token) {
if (token == null)
return null;
char[] charArray = token.toCharArray();
int length = token.length();
StringBuilder sb = new StringBuilder();
int count = 0;
for (int i = 0; i < length; i++) {
count++;
if (i == 0 || i == length - 1) {
sb.append(charArray[i]);
} else if (count == 5) {
sb.append(charArray[i]);
count=0;
} else if(count < 5 && i == length-1){
sb.append(charArray[i]);
}else {
sb.append('*');
}
}
return sb.toString();
}
Need to print last character if count is less than 5 of last
iteration.
If String of length 9, "12345678" then actual output will be like
1***5**8
If String of length 9, "123456789abcd" then actual output will be
like 1***5****a**d
String output = "";
for (int i = 0; i < str.length(); i++) {
if (i == 0) {
output += str.charAt(i);
output += "***";
output += str.charAt(4);
i = 4;
} else if ((i - 4) % 5 == 0) {
output += str.charAt(i);
} else if (i == str.length()-1) {
output += str.charAt(i);
} else {
output += "*";
}
}
System.out.println(output);
}
This will print 1***5****a**d for string "123456789abcd".
try this code:
public void printFirstAndEveryFifthCharecter(String str)
{
for (int i = 0 ; i < str.length() ; i++)
{
if ((i+1) == 1 | (i+1) % 5 == 0) {
System.out.print(str.charAt(i) + "***");
}
}
if (str.length() % 5 > 0) {
System.out.print(str.charAt(str.length() - 1));
}
}
Your code should work fine. Here's an alternative without using StringBuilder and with fewer checks.
private static String getFirstFifthLast(String str) {
String[] strArray = str.split(""); //returns an array of strings with length 1
int arrayLength = strArray.length;
String result = strArray[0]; //append the first element
//append element if it is in 5th position, append "*" otherwise
for (int i = 0; i < arrayLength; i++) {
if ((i + 1) % 5 == 0) {
result += strArray[i];
} else {
result += "*";
}
}
result += strArray[arrayLength - 1]; //append the last element
return result;
}
Try this code,
private void printEvery5thCharacter(String str) {
for (int i = 1; i < str.length() - 1; i += 5) {
System.out.print(str.charAt(i - 1) + "***");
if (i == 1) {
i = 0;
}
}
if (str.length() % 5 > 0) {
System.out.print(str.charAt(str.length() - 1));
}
}
Take as input S, a string. Write a function that replaces every odd character with the character having just higher ASCII code and every even character with the character having just lower ASCII code. Print the value returned.
package assignments;
import java.util.Scanner;
public class strings_odd_even_char {
static Scanner scn = new Scanner(System.in);
public static void main(String[] args) {
String str = scn.nextLine();
for (int i = 0; i < str.length(); i = i + 2) {
char ch = str.charAt(i);
ch = (char)((ch + 1));
System.out.println(ch);
}
for (int j = 1; j < str.length(); j = j + 2) {
char ch = str.charAt(j);
ch = (char)((ch - 1));
System.out.print(ch);
}
}
}
The problem with my code is that it is first printing the values for all the odd characters and then for even characters but what I want is that they get printed in proper sequence like for input --> abcg , the output should be --> badf .
I'd hold the "incremenet" value in a variable and alternate it between +1 and -1 as I go voer the characters:
private static String change(String s) {
StringBuilder sb = new StringBuilder(s.length());
int increment = 1;
for (int i = 0; i < s.length(); ++i) {
sb.append((char)(s.charAt(i) + increment));
increment *= -1;
}
return sb.toString();
}
Just use one loop that handles both characters:
for (int i = 0; i < str.length(); i = i + 2) {
char ch = str.charAt(i);
ch = (char) (ch + 1);
System.out.print(ch);
if (i + 1 < str.length()) {
ch = str.charAt(i + 1);
ch = (char) (ch - 1);
System.out.print(ch);
}
}
You only need to iterate one time but do different operation (char+1) or (char-1) depending on the i:
public static void main(String[] args) {
String str = scn.nextLine();
for(int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(i % 2 == 0) { // even
ch += 1;
} else { // odd
ch -= 1;
}
System.out.print(ch);
}
}
You are using two loops, but you only need one. You can use the % operator to tell if i is even or odd, and then either subtract or add accordingly:
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(i % 2 == 0) {
ch = (char)((ch + 1));
System.out.println(ch);
} else {
ch = (char)((ch - 1));
System.out.print(ch);
}
}
You can do it in one for loop, to do that you will need to check whether the current index is even or odd. if current index is even you will increment char and print, if it is odd you will decrement char and print. to check if even or odd using % operator
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(i%2 == 0) {
ch = ch + 1;
System.out.println(ch);
continue;
}
ch = ch - 1;
System.out.println(ch);
}
I want to distinguish Unicode characters and ASCII characters from the below string:
abc\u263A\uD83D\uDE0A\uD83D\uDE22123
How can I distinguish characters? Can anyone help me with this issue? I have tried some code, but it crashes in some cases. What is wrong with my code?
The first three characters are abc, and the last three characters are 123. The rest of the string is Unicode characters. I want to make a string array like this:
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '\u263A\uD83D';
str[4] = '\uDE0A\uD83D';
str[5] = '\uDE22';
str[6] = '1';
str[7] = '2';
str[8] = '3';
Code:
private String[] getCharArray(String unicodeStr) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < unicodeStr.length(); i++) {
if (unicodeStr.charAt(i) == '\\') {
list.add(unicodeStr.substring(i, i + 11));
i = i + 11;
} else {
list.add(String.valueOf(unicodeStr.charAt(i)));
}
}
return list.toArray(new String[list.size()]);
}
ASCII characters exist in Unicode, they are Unicode codepoints U+0000 - U+007F, inclusive.
Java strings are represented in UTF-16, which is a 16-bit byte encoding of Unicode. Each Java char is a UTF-16 code unit. Unicode codepoints U+0000 - U+FFFF use 1 UTF-16 code unit and thus fit in a single char, whereas Unicode codepoints U+10000 and higher require a UTF-16 surrogate pair and thus need two chars.
If the string has UTF-16 code units represented as actual char values, then you can use Java's string methods that work with codepoints, eg:
private String[] getCharArray(String unicodeStr) {
ArrayList<String> list = new ArrayList<>();
int i = 0, j;
while (i < unicodeStr.length()) {
j = unicodeStr.offsetByCodePoints(i, 1);
list.add(unicodeStr.substring(i, j));
i = j;
}
return list.toArray(new String[list.size()]);
}
On the other hand, if the string has UTF-16 code units represented in an encoded "\uXXXX" format (ie, as 6 distinct characters - '\', 'u', ...), then things get a little more complicated as you have to parse the encoded sequences manually.
If you want to preserve the "\uXXXX" strings in your array, you could do something like this:
private boolean isUnicodeEncoded(string s, int index)
{
return (
(s.charAt(index) == '\\') &&
((index+5) < s.length()) &&
(s.charAt(index+1) == 'u')
);
}
private String[] getCharArray(String unicodeStr) {
ArrayList<String> list = new ArrayList<>();
int i = 0, j, start;
char ch;
while (i < unicodeStr.length()) {
start = i;
if (isUnicodeEncoded(unicodeStr, i)) {
ch = (char) Integer.parseInt(unicodeStr.substring(i+2, i+6), 16);
j = 6;
}
else {
ch = unicodeStr.charAt(i);
j = 1;
}
i += j;
if (Character.isHighSurrogate(ch) && (i < unicodeStr.length())) {
if (isUnicodeEncoded(unicodeStr, i)) {
ch = (char) Integer.parseInt(unicodeStr.substring(i+2, i+6), 16);
j = 6;
}
else {
ch = unicodeStr.charAt(i);
j = 1;
}
if (Character.isLowSurrogate(ch)) {
i += j;
}
}
list.add(unicodeStr.substring(start, i));
}
return list.toArray(new String[list.size()]);
}
If you want to decode the "\uXXXX" strings into actual chars in your array, you could do something like this instead:
private boolean isUnicodeEncoded(string s, int index)
{
return (
(s.charAt(index) == '\\') &&
((index+5) < s.length()) &&
(s.charAt(index+1) == 'u')
);
}
private String[] getCharArray(String unicodeStr) {
ArrayList<String> list = new ArrayList<>();
int i = 0, j;
char ch1, ch2;
while (i < unicodeStr.length()) {
if (isUnicodeEncoded(unicodeStr, i)) {
ch1 = (char) Integer.parseInt(unicodeStr.substring(i+2, i+6), 16);
j = 6;
}
else {
ch1 = unicodeStr.charAt(i);
j = 1;
}
i += j;
if (Character.isHighSurrogate(ch1) && (i < unicodeStr.length())) {
if (isUnicodeEncoded(unicodeStr, i)) {
ch2 = (char) Integer.parseInt(unicodeStr.substring(i+2, i+6), 16);
j = 6;
}
else {
ch2 = unicodeStr.charAt(i);
j = 1;
}
if (Character.isLowSurrogate(ch2)) {
list.add(String.valueOf(new char[]{ch1, ch2}));
i += j;
continue;
}
}
list.add(String.valueOf(ch1));
}
return list.toArray(new String[list.size()]);
}
Or, something like this (per https://stackoverflow.com/a/24046962/65863):
private String[] getCharArray(String unicodeStr) {
Properties p = new Properties();
p.load(new StringReader("key="+unicodeStr));
unicodeStr = p.getProperty("key");
ArrayList<String> list = new ArrayList<>();
int i = 0;
while (i < unicodeStr.length()) {
if (Character.isHighSurrogate(unicodeStr.charAt(i)) &&
((i+1) < unicodeStr.length()) &&
Character.isLowSurrogate(unicodeStr.charAt(i+1)))
{
list.add(unicodeStr.substring(i, i+2));
i += 2;
}
else {
list.add(unicodeStr.substring(i, i+1));
++i;
}
}
return list.toArray(new String[list.size()]);
}
It's not entirely clear what you're asking for, but if you want to tell if a specific character is ASCII, you can use Guava's ChatMatcher.ascii().
if ( CharMatcher.ascii().matches('a') ) {
System.out.println("'a' is ascii");
}
if ( CharMatcher.ascii().matches('\u263A\uD83D') ) {
// this shouldn't be printed
System.out.println("'\u263A\uD83D' is ascii");
}