Android Java Check Length of String - Multiple of 30 - java

My situation: I have a string (called str). The length of the string must be a multiple of 30 (e.g 30, 60, 90). If the length of the str is not a multiple of 30, add spaces " " to the end of it.
Something like this:
if (str.length() / 30 != ????) {
//add spaces to the end
}
Of course, the code above is not correct. It would be very appreciated if you could help me with this.
Thanks in advance!

You can quite simply do:
if(str.length()%30!=0)
str = String.format("%1$-"+(((str.length()/30)*30)+30)+"s", str);
str.length()%30 gives the remainder on dividing the length by 30. If it is not 0, then you have to add spaces.
String.format("%1$-"+(((str.length()/30)*30)+30)+"s", str) adds the spaces to the right of the String.
Or even simply, you can do:
while(str.length()%30 !=0)
str+= ' ';

this code is not tested but i guess it will work:
int a = str.length()%30;
for(int i=0; i<=a; i++)
str = str + " ";

What would you do to check if a number is a multiple of 30 in simple Maths?
Yes, you would divide and check if the remainder is 0 or not, right?
That's how you'll do it in Java. To get the remainder in Java, Modulus(%) operator is used. So, you can do it like this :
if (str.length() % 30 != 0) {
//add spaces to the end
str += " ";
}
or if you want to add spaces to make the length a multiple of 30, then do this:
int remainder = str.length() % 30;
if (remainder != 0) {
//add spaces to the end
int numSpacesRequired = 30-remainder; //no. of spaces reuired to make the length a multiple of 30
for(int i = 0; i < numSpacesRequired; i++)
str += " ";
}
Read more about the basic operators in Java here.

You can use Modulo to achieve that:
if (str.length() % 30 != 0) {
//add spaces to the end
str += ' ';
}

Simply: (Tested and worked)
public static void main(String[] args) {
String str = "AYOA"; //Length is only 4
//If the remainder of the str's length is not 0 (Not a multiple)
if (str.length() % 30 != 0){
str += ' ';
}
System.out.println("[" + str + "]"); //A space is added at the back
}
If you want to add the space continuously until the length is a multiple of 30:
public static void main(String[] args) {
String str = "AYOA"; //Length is only 4
//If the remainder of the str's length is not 0 (Not a multiple)
//Repeat until is multiple of 30
while(str.length % 30 != 0){
str += ' ';
}
System.out.println("[" + str + "]"); //A space is added at the back
}

use StringBuilder to build whitespaces
String str="multiple of 30";
int spacesNum=str.length()%30; //get the remainder
StringBuilder spaces=new StringBuilder(); //build white spaces
for(int j=0;j<spacesNum;j++){
spaces.append(' ');
}
System.out.println(str+spaces.toString());

Related

Take in String that contains number characters and add commas to each thousands place WITHOUT converting string into int or long

I want to take in a string for example "1234567890" and add commas to each thousands place in the number. However, I don't want to parse this string into an int or long. I think I might need to use recursion but I dont know how.
String number1 = "1234567890";
System.out.println(stringNumberAddCommas(number1));
//output == 1,234,567,890
public static String stringNumberAddCommas(String number1){ }
we can achieve this as below as well-
public static String stringNumberAddCommas(String number) {
for (int i = number.length() - 1; i >= 0; ) {
if (i >= 3) {
number = number.substring(0, i - 2) + "," + number.substring(i - 2);
}
i = i - 3;
}
System.out.println("number=" + number);
return number;
}
There's no need to mess with recursion; all you need is to realize that you need to either work backwards or do some very basic math based on length.
Given a pile o digits that is, say, 8 characters long, that's all the information you need to know that the first comma is after 2 digits, and then every further comma at +3 digits from that position until you reach the end.
Tools needed:
"12345678".length() (= 8)
"12345678".substring(2, 5) (= "345")
a for (int i = ...; i < in.length(); i+= 3) loop.
a new StringBuilder() along with its .append() method, both for appending the comma as well as those substrings.
Some exceedingly basic math on that length, involving in particular the % operator. a % b divides a by b, tosses the result in the garbage, and returns the leftovers. In other words, 5 % 3 returns 2 (because 5 divides into 3 one time, and that leaves a remainder of 2).
String test = "1234567890";
String reversed = new StringBuffer(test).reverse().toString();
int i = 0;
StringBuilder ans = new StringBuilder();
while(i+3<reversed.length()){
ans.append(reversed, i, i + 3).append(",");
i+=3;
}
ans.append(reversed, i, reversed.length());
String solution = ans.reverse().toString();
I'd define an offset to find the length of the first substring, then iterate over the string in 3 character substrings.
StringJoiner would also be helpful in adding the needed commas.
public static String stringNumberAddCommas(String str){
int offset = str.length() % 3 != 0 ? str.length() % 3 : 3;
StringJoiner sj = new StringJoiner(",");
for (int s = 0, i = offset; i <= str.length(); s = i, i += 3) {
sj.add(str.substring(s, i));
}
return sj.toString();
}

restore original word after Caesar Cipher shifting

I write a func of Caesar Cipher.
So after I shift a sentence, I want also shift back to the original sentence.
For now it works only for one direction, when I shift with natural positive number, but when I try to do this with negative number, it goes on to value less than 97 of ascii lowercase letters.
I give an example:
word: java
key = 10
output: tkfk
Now I want to shift back, to restore my word from tkfk to java.
key = -10
output: ja\a
Instead of v it put \
I know its happens couse from f to minus 10 from ascii table is the letter '\' and I want the letter v.
I think I need to manipulate this line, but I dont know how, I'm a little bit stuck and I don't have an idea what to do.
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97)
My method: (little bit long)
public static void MakeCipherText(String[] text, int key) {
int index =0;
if (key > 0) {
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in every itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
} else { // key is negetive number
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in evry itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
}
}
Any suggestion?
As the comments suggest you should really check your code again this will also help you to be a better programmer. But anyway you think too complicated.
If you check your else part that is the exact copy of the if part. And that is no wonder. To decode Caesar cipher you encode it basically again with the right key to encode.
For example:
If you encode it with A => B or in this example with 1:
test--> uftu
so how can we decode uftu back?
When we shift it with B=>A or in this case with 25.
uftu --> test
So in your requirement you want if you put -1 that you decode text that was encoded with 1 before.
So basically we have to find a method to map -1 to 25, -2 to 24 and so on.
And the key function is: modulo
-2 % 26 => 24
-1 % 26 => 25
...
In addition you can even now put numbers bigger than 26 because:
500 % 26 => 6
-500 % 26 => 20
and because 2 % 26 => 2 you don't even need that if clause. Your code looks like this in the end:
public static void MakeCipherText(String[] text, int key) {
int index =0;
key = (((key % 26) + 26) % 26); // See below for explanation of this weird modulo
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in every itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
}
Never forget to use functions and don't use duplicate code. Bad style and error prone. The solution is quite easy if you think it through.
Information weird modulo function
You see I use a weird modulo function. Because in Java % don't calculate the modulo but the remainder. (Different then in Python).
So to get the "true" modulo in Java we have to use this weird trick:
Reference: What's the difference between “mod” and “remainder”?
key = (((key % 26) + 26) % 26);

Remove every 8th char from a string

I have a string, which I want to iterate through and remove every 8th char. I have been trying with an modulo operation which check if i % 8 == 0. However, since I remove every 8th char the length of the string decreases, and I am therefore unable to perform that operation.
StringBuilder str = "1100110001011011000000000000000000000000000000000000000000000000";
System.out.println(str + " " + str.length());
for (int i = 0; i < str.length(); i++) {
// Every 8th element should be discarded
if (i > 7 && i % 8 == 0) {
str.deleteCharAt(i);
}
}
System.out.println(str + " " + str.length());
The length of the string is in the beginning 64, and after the for loop 57, which should be 56.
The main problem with your code is that you don't adjust i when removing characters.
Let's visualize that. You want to remove the following marked characters ("every 8th element"):
1100110001011011000000000000000000000000000000000000000000000000
^ ^ ^ ^ ^ ^ ^ ^
Now we're at i = 7 and remove that character, but because you don't adjust i accordingly the markers keep the same:
110011001011011000000000000000000000000000000000000000000000000
^ ^ ^ ^ ^ ^ ^ ^
Let's do that for 1 = 15 to i = 55:
11001100101101100000000000000000000000000000000000000000000000 //i = 15
1100110010110110000000000000000000000000000000000000000000000 //i = 23
110011001011011000000000000000000000000000000000000000000000 //i = 31
11001100101101100000000000000000000000000000000000000000000 //i = 39
1100110010110110000000000000000000000000000000000000000000 //i = 47
110011001011011000000000000000000000000000000000000000000 //i = 55
^ ^ ^ ^ ^ ^ ^ ^
As you can see, all but the last marker point to a valid character but you won't reach i = 63 because after the first time you remove a character there only are 63 left in the string and thus a max index of 62.
That's why your resulting string has 57 instead of 56 characters, the last "remove" operation doesn't run (and the others except the first remove the wrong elements).
To fix that iterate backwards, i.e. from i = str.length() - 1 to i = 0. Then you can remove every element where (i + 1) % 8 == 0.
Alternatively, as I said in my comment, use a regex: String shortened = str.replaceAll( "(.{7}).", "$1" );
This will match any sequence of 7 characters followed by another (8th) character and replaces that with the first group of 7 (thus skipping the 8th).
There is not deleteCharAt method in String, so I suppose you meant StringBuilder?
You can just reverse the direction of the for loop, so that it starts from the end of the string:
String str = "11111111811111118";
StringBuilder builder = new StringBuilder(str);
System.out.println(str + " " + str.length());
for (int i = str.length() - 1; i >= 0; i--) {
// Every 8th element should be discarded
if (i > 7 && i % 8 == 0) {
builder.deleteCharAt(i);
}
}
System.out.println(builder+ " " + builder.length());
By deleting chars from the end of the string, the indices of the chars to be removed no longer changes as you move along the string.
Why don't you use regex and achieve it in two lines of code like this,
public static void main(String[] args) {
String str = "1100110001011011000000000000000000000000000000000000000000000000";
String replacedStr = str.replaceAll("([01]{7})[01]", "$1");
System.out.println(str.toString() + " " + str.length());
System.out.println(replacedStr.toString() + " " + replacedStr.length());
}
This gives perfectly correct output,
1100110001011011000000000000000000000000000000000000000000000000 64
11001100101101000000000000000000000000000000000000000000 56
Alternatively, you can follow this traditional solution like you attempted.
Strings in java are immutable. So instead you should create a StringBuilder object and keep copying every character, except 8th character.
For correctly counting every 8th character, initialize your for loop index run from 1 rather than 0, like in this code, which will eradicate every 8th character effectively where you wanted to do if (i%8==0)
public static void main(String[] args) {
String str = "1100110001011011000000000000000000000000000000000000000000000000";
StringBuilder sb = new StringBuilder();
System.out.println(str + " " + str.length());
for (int i = 1; i <= str.length(); i++) {
// Every 8th element should be discarded
if (i % 8 == 0) {
// str.deleteCharAt(i);
} else {
sb.append(str.charAt(i-1));
}
}
System.out.println(sb.toString() + " " + sb.length());
}
And this gives following output,
1100110001011011000000000000000000000000000000000000000000000000 64
11001100101101000000000000000000000000000000000000000000 56
You can verify here where only every 8th character is gone in this output.
The problem is that Strings are starting with 0. Therefore the 8th element has the index 7 and has to be removed as well, which you don't do in your loop. I'd write it like that (but noting that this might not be the most elegant solution):
public static void main(String[] args)
{
String str = "1100110001011011000000000000000000000000000000000000000000000000";
System.out.println(str + " " + str.length());
int idx = 0;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
idx++;
if (idx == 8) {
idx = 0;
continue;
}
sb.append(str.charAt(i));
}
System.out.println(sb.toString() + " " + sb.length());
}
Outputs:
1100110001011011000000000000000000000000000000000000000000000000 64
11001100101101000000000000000000000000000000000000000000 56
Assuming that the string does not contain the char with ASCII value 0, convert the string to a char array and change every 8th char with the char with ASCII value 0, then reconstruct the string and replace all chars with ASCII value 0 with "":
String str = "0123456701234567012345670123456701234567012345670123456701234567";
System.out.println("initial = " + str);
char[] array = str.toCharArray();
for (int i = 7; i < array.length; i = i + 8) {
array[i] = 0;
}
str = String.valueOf(array).replace(String.valueOf(Character.toChars(0)), "");
System.out.println("final = " + str);
will print:
initial = 0123456701234567012345670123456701234567012345670123456701234567
final = 01234560123456012345601234560123456012345601234560123456
An alternative way is using substring() method.
substring(int beginIndex, int endIndex) Returns a new string that is a
substring of this string.
In every turn add 7 chars of the string to the new string and skip the 8th element of the string: sb.append(str.substring(start, start+7));
In first turn:
str.substring(0, 7) -> "1100110"
start += 8; -> start = 8;
In second turn:
str.substring(8, 15) -> "0101101"
start += 8; -> start = 23;
...
So the 8th element/the element has the index 7 ("0") has been skipped.
String str = "1100110001011011000000000000000000000000000000000000000000000000";
int length = str.length();
int start = 0;
StringBuilder sb = new StringBuilder();
while((start+7)<length) {
sb.append(str.substring(start, start+7));
start += 8;
}
if(start<length) {
sb.append(str.substring(start, length));
}
System.out.println(sb + " " + sb.length());
System.out.println(str + " " + str.length());
Output:
11001100101101000000000000000000000000000000000000000000 56
1100110001011011000000000000000000000000000000000000000000000000 64
String doesn't have a deleteCharAt() method. If it did, it would return the update string, since String is immutablem so code would have had to be str = str.deleteCharAt(i);.
You could use StringBuilder instead, since it does have a deleteCharAt() method.
To delete every 8th character, start at the end. That way index values are unaffected by already deleted characters, which is your current problem.
String str = "1100110001011011000000000000000000000000000000000000000000000000";
System.out.println(str + " " + str.length());
StringBuilder buf = new StringBuilder(str);
for (int i = (buf.length() - 1) / 8 * 8; i >= 0; i -= 8)
buf.deleteCharAt(i);
str = buf.toString();
System.out.println(str + " " + str.length());
Output
1100110001011011000000000000000000000000000000000000000000000000 64
10011001011011000000000000000000000000000000000000000000 56
UPDATE
The above code deletes the 1st, 9th, 17th, ... character, i.e. characters at index 0, 8, 16, ..., which is in accordance with "remove every 8th char" and "check if i % 8 == 0" mentioned in the question.
If code should delete the 8th, 16th, 24th, ... character, i.e. characters at index 7, 15, 23, ..., then change initialization of i as follows:
for (int i = (buf.length() - 8) & ~7 | 7; i >= 0; i -= 8)
buf.deleteCharAt(i);
Output
1100110001011011000000000000000000000000000000000000000000000000 64
11001100101101000000000000000000000000000000000000000000 56
Since StringBuilder::deleteCharAt changes the size of the underlying sequence, you need to process the target string in reverse order.
This solution is based on streams.
// create target string
String s = Stream.generate(() -> IntStream.range(0, 10))
.limit(10)
.map(stream -> stream.mapToObj(Objects::toString).collect(Collectors.joining()))
.collect(Collectors.joining());
StringBuilder sb = new StringBuilder(s);
// delete first element or not?
boolean removeFirst = false;
IntStream.range(removeFirst ? 0 : 1, s.length())
.boxed()
.sorted(Collections.reverseOrder()) // reverse number stream
.filter(i -> i % 8 == 0) // only keep multiples of 8
.forEach(sb::deleteCharAt);
System.out.println(s);
System.out.println(sb.toString());
This is the output it produces
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456790123457890123567890134567891234567901234578901235678901345678912345679012345789
The first element missing is the 8, then 6 (16), then the 4 (24), etc.

Split text from Right to left based on the input passed

i have string and im trying to split the text and format it
Input is 67.9200 2 3
Ouput will be 6 7.9 200
Rules
1) split from the right to left based on the digits passed.
2) when split contains "." then add 1 to it .
3) if anything is remaining will just show in the front.
Example
67.9200 2 3
1. 3 (digits) -> will take the last 200
2. 2 (digits) -> will take 7.9 (since it has ".")
3. 6 -> Remaining will show (6)
Any suggestion or solutions will be greatly appreciated
You can start scanning the string from right and keep storing them in a StringBuilder till you have captured n1(3) characters and whenever you encounter a dot, skip the count and once n1 becomes zero, append a space and move on. Apply same strategy for n2(2) and after you have the final string in StringBuilder, just reverse the string and you get your output. Here is a sample program.
public static void main(String[] args) {
String str = "67.9200";
int n1 = 2;
int n2 = 3;
StringBuilder sb = new StringBuilder();
for (int i = str.length() - 1; i >= 0; i--) {
if (n2 > 0) {
char c = str.charAt(i);
sb.append(c);
if (c != '.') {
n2--;
if (n2 == 0) {
sb.append(" ");
}
}
} else if (n1 > 0) {
char c = str.charAt(i);
sb.append(c);
if (c != '.') {
n1--;
if (n1 == 0) {
sb.append(" ");
}
}
} else {
sb.append(str.charAt(i));
}
}
System.out.println(sb.reverse().toString());
}
This gives following output,
6 7.9 200

Java text wrap issue, caused by input width

I am trying to wrap text based on a width of 10 characters. After looking at other questions, I have the following:
StringBuilder sb = new StringBuilder(s);
int i = 0;
while (i + 10 < sb.length() && (i = sb.lastIndexOf(" ", i + 10)) != -1) {
sb.replace(i, i + 1, "\n");
}
System.out.println(sb.toString());
This works until a word in my string is longer than the specified width. When this occurs, the rest of the string is printed on line line instead of still following the line width rule. Any ideas? I tried an "else" with a separate condition but I couldn't get it to work. Apologies if this seems rather trivial.
There is a ready solution for that.
https://mvnrepository.com/artifact/org.apache.commons/commons-text
WordUtils.wrap(s, 10);
When you have a word that's longer than 9 characters, sb.lastIndexOf("", i + 10) gives you -1. That's because index of the next space is greater than i + 10 and sb.lastIndexOf("", i + 10) starts from index i + 10 and looks for a space until the beginning of the string and cannot find any spaces (they have all been replaced with new lines). You can fix your code like below to make it work.
StringBuilder sb = new StringBuilder(s);
int i = 0;
while (i + 10 < sb.length() &&
(i = Math.max( sb.indexOf(" ", i), sb.lastIndexOf(" ", i + 10))) != -1) {
sb.replace(i, i + 1, "\n");
}
System.out.println(sb.toString());
You could convert your string to an array of characters and visit them and ask if the variable iterator % 10 (in this case in 9 because i = 0), if so You enter a line break plus the character, all this will be added to a StringBuilder ... might be a solution
char[] a="ABCDFGHIKLMNOPQRSTUVWXYZ".toCharArray(); //String convert to charArray
StringBuilder sb = new StringBuilder(a.length);
for (int i = 0; i < a.length; i++) {
if(i%9==0) sb.append("\n" + a[i]); //
sb.append(a[i]);
}
System.out.println(sb.toString());

Categories