Hello I have a problem with understanding the following code.
public static void main(String[] args) {
String vstup = "DEN DOBRY";
String vystup = "";
int i = 2;
do {
vystup = vystup + vstup.charAt(i);
i++;
} while (vystup.charAt(0)>=vstup.charAt(i));
System.out.println(vystup);
}
Why does this one print out "N D"?
And the second one:
public static void main(String[] args) {
String vstup = "Mama má emu.";
String vystup = "";
for (int i = 0;i<vstup.length();i++)
if ((i % 3) == 1) vystup = vystup.concat(vstup.substring(i, i+2));
System.out.println(vystup);
}
Why does this one print out "am m eu."?
Issues
The first part of the code can throw index out of bounds exception(or similar)
The second part of the code can also throw similar exception
Example Input for 1st case: ZYXWV
do {
vystup = vystup + vstup.charAt(i);
i++;
} while (vystup.charAt(0) >= vstup.charAt(i)); // i can get invalid
Example Input for 2nd case: ab
if ((i % 3) == 1) vystup = vystup.concat(vstup.substring(i, i+2)); // i + 2 can be invalid index
What 1st does?
Starts from 2nd index i = 2
concatenates character at index to output and increments index by 1
repeat step 2 if character at current (incremented) index is lesser than or equal to the first character(0th index) of the string
By >=, it compares the code points (numeric values of the character)
What 2nd does?
Starting from 2nd character(1 index), selects 2 adjacent characters(2 and 3rd character)
repeat by moving 3 character (from 2nd character exclusive) to right
str: M a m a m á e m u .
index: 0 1 2 3 4 5 6 7 8 9 10 11
i%3==1 i i+1 i i+1 i i+1 i i+1
I hope this helps you.
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);
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.
I am new to Java and currently learning it in a 4 week course. I am working on on an assignment to find all of the Cs and Gs in a string named dna, and then divide the number of Cs and Gs by dna. I have written a small program, and it compiles with no syntax errors, but when I run it, all that is printed out is the length of dna and then 1(The output of the dividing part).
My code:
public static void cgRatio (String dna) {
int counter = 0; // counts how many Cs and Gs
int index = 0; // start looking from index 0
while (dna.indexOf("C") != -1 && counter != dna.length()) { // while dna is not finished and you can find C in dna
index = dna.indexOf("C", index); // Start looking from last index
if (index != -1) {
counter++;
}
else {
break;
}
}
System.out.println("Number of C in dna: " + counter);
System.out.println("Gene cg ratio: " + (counter / dna.length()));
}
If anyone can help that would be great and appreciated, thanks!
The problem is that the second argument to indexOf is the first index in the string that it searches.
Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index.
Once it finds the first "C", it will then continue to always find that same "C" in the first index it looks in. You need to change your code to this:
index = dna.indexOf("C", index + 1);
To start from the first character after the "C" that you already found. You should also change the initial index to -1 so that it starts from the first character.
There are a few problems with your code:
It uses counter as the number of cs in your dna string when it is really equal to dna.length(). This causes the ratio to be 1 if there are any cs at all, or 0 if there are none.
There should be a variable that keeps track of how many cs there are in the string and how many gs there are (as seen in the above bullet, counter cannot be used for this.)
As resueman said, this line:
index = dna.indexOf("C", index); should be changed to: index = dna.indexOf("C", index + 1);, or else the index will remain the same (it will always be equal to the index of the first c in the string.)
A while loop really is not all that well suited to this kind of thing; instead, a for loop should be used.
The ratio should be a double, not an int since doubles have more precision (they can be decimals.)
Here's code I came up with that works:
public static void cratio(String dna) {
int c = 0;
int g = 0;
for(int i =0; i < dna.length(); i++) {
if((dna.charAt(i) == 'c') || (dna.charAt(i) == 'C')) c++;
if((dna.charAt(i) == 'g') || (dna.charAt(i) == 'G')) g++;
}
System.out.println("Number of 'C's in DNA: " + c + " and number of 'G's in DNA: " + g);
int length = dna.length();
double ratio = (double) (c+g)/length * 100;
System.out.println("The ratio of 'C's and 'G's to the length of the DNA chain is: " + ratio + "%.");
}
If you have any questions, just let me know!
I'm using java. I'm trying pull out the last letter of a word of 8 characters or less. Then pulling out each character after
lengthOfWord = word.length();
lc = word.charAt(lengthOfWord -1);
if (lengthOfWord == 1)
System.out.println(lc);
When I try to use a word with one character, it says "String index out of range: -1" and when I try using a word of two characters, it says build successfully, but doesn't print anything.
lengthOfWord is past the bounds of word. Use:
lc = word.charAt(lengthOfWord - 1);
Remember that .length() returns the number of characters of an object, but the index of an object starts at 0 and ends at length()-1.
UPDATE
Try this to check all characters in the word:
for (int i = 0; i < word.length(); i++) {
System.out.println("Char " + i + ": " + word.charAt(i));
}
lengthOfWord is 0 based, so you might wanna try lc = word.charAt(lengthOfWord - 1);