Strange Java Behavior [closed] - java

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last year.
Improve this question
Firstly, this question came about because I was trying to make a hello world program (the first main method commented out) as convoluted as possible. I tried to rewrite some of it to make it more readable but maintain the strange behavior I am addressing.
Specifically, in the for loop I am trying to convert the strings to floats, then truncate the floats to ASCII values, and then lastly to chars that say "Hello, World!" The problem is that inside the conditional, in the for loop, if you have it simply be (i == 0) it will capitalize the h just fine but when you add
(i == 6) it acts really strange and ends up printing chars inconsistently such as "Hello,d!", "Hello,!" and "Hello,rld!" (among others). Can anyone explain this behavior to me? Thank you.
import java.util.Scanner;
class helloWorld {
// public static void main(String[] args) {
// System.out.println("Hello, World!");
// }
public static void main(String[] args) {
//This array is just soon to be truncated ASCII vals
String[] nums = {"104.367", "101.432", "108.43276", "108.1", "111.43", "44.231", "32.12", "119.32", "111.24", "114.37", "108.2", "100.52", "33.237", "10.4"};
//Empty "Hello, World!" string
String message = "";
//This is to store the converted ASCII values
char[] chars = new char[nums.length];
//this is just the difference in ASCII vals to go from lower to uppercase letters
int toUpperCase = 32;
for (int i = 0; i < nums.length; i++){
//i == 6 || i == 0 because I want the w and h to be capitalized
//i == 0 capitalizes the 'h' and prints as expected but adding "i == 6 ||" to the condition causes it to break and print chars inconsistently
if (i == 6 || i == 0) {
//converts from float to int (truncates decimals to the normal ASCII val) and then from the ASCII value to the char
chars[i] = (char)((int)((Float.parseFloat(nums[i])) - toUpperCase));
} else {
chars[i] = (char)((int)(Float.parseFloat(nums[i])));
}
System.out.print(chars[i]);
}
System.out.print(message);
}
}

tl;dr
The bug is actually a minor one, you used i == 6 but instead you should have used i == 7.
Index
Let's break down what happens and why. To start off, the source string you are reading from (even though you made it floats, but doesn't matter) is Hello, World!, the indices for your array are as follows:
// _ denotes the space
h e l l o , _ w o r l d !
0 1 2 3 4 5 6 7 8 9 10 11 12
Note that 6 is actually the index of the space and not the w, which you wanted to capitalize.
NUL character
Next up, you subtract 32 from the ASCII value of the space. Fun fact, the ASCII value of that is 32 as well:
System.out.println((int) ' '); // 32
So your subtraction results in 0. The char that has the ASCII value 0 is the so called null character (not to confuse with the Java keyword null), which is a special control character with no visual representation. It can also be written as '\0'.
System.out.println((char) 0);
So when you told your console to print the null char, it might start doing funny things. Although, the consoles I tested with, simply skip the character and print Hello,world! consistently.
If you want to try it out with a minimal example, use this one:
System.out.println("Hello,\0world!");
which is the string that your code produced.
ASCII table
While at it, here is the ASCII table with the null character and space highlighted (from Wikipedia):
You can also see that the first 32 characters are all control characters without a direct visual representation. In fact, try out this one:
System.out.print((char) 7);
depending on your console, you might hear a beep sound now.

Related

Rotating a string with ASCII in Java

I'm doing some practice on HackerRank and I'm stuck on a problem. The problem is:
Julius Caesar protected his confidential information by encrypting it using a cipher. Caesar's cipher shifts each letter by a number of letters. If the shift takes you past the end of the alphabet, just rotate back to the front of the alphabet. In the case of a rotation by 3, w, x, y and z would map to z, a, b and c.
Original alphabet: abcdefghijklmnopqrstuvwxyz
Alphabet rotated +3: defghijklmnopqrstuvwxyzabc
Example
input:
11
middle-Outz
2
output:
okffng-Qwvb
I pass this test case, but I don't pass the rest of the test cases and it won't tell me which ones. What am I missing in my logic?
public static String caesarCipher(String s, int k) {
String newString = "";
// Write your code here
for (int i=0; i<s.length(); i++) {
char currentChar = s.charAt(i);
int currentAscii = currentChar;
if (currentAscii <65|| currentAscii>122 || (currentAscii>90 && currentAscii < 97)) {
newString += currentChar;
} else {
currentAscii = currentChar+k;
if (currentAscii > 122) {
currentAscii = Math.abs(currentAscii-26);
}
newString += (char) currentAscii;
}
}
return newString;
}
.
Here is an ASCII chart.
Your rotate algorithm is:
If the value is below 65 (less than 'A' in that chart), or above 122 (more than 'z' in that chart), do nothing to the character and just copy it verbatim.
In all other cases, add k, e.g. 11. This goes wrong, immediately. Note how for example [ is in between 65 and 122. Adding 11 to [ is nonsensical. [ should obviously be treated the same as, say, < is treated (which is less than 65).
Of course, adding 11 isn't what 'rotating' is all about: If adding 11 pushes it 'beyond' the z or Z, you want to snap around back to the a or A. Your code does that, but only if the end result is above 'z'. You forgot about 'Z'.
For example, adding 1 to Z (Which is value 90) gets you [ (the character with value 91). Given that 91 is not above 122, you don't modify this at all.
Add more test cases, especially involving capitals, preferably Z. You'll see the problem immediately.
The solution involves getting rid of the 65/122 dichotomy; instead it's 2 ranges: 65-90 and 97-122. For what it is worth, int a = (int) 65; and int a = (int) 'a'; is exactly the same code, and the latter is far more readable, so you might want to use that. There is no need to write any actual number in this code anywhere, except possibly '26'.

Converting letters to alphabet position with two JLists

I'm trying to replace all words (alphabet letters) from JList1 to the number corresponding its place in the alphabet to JList2 with the press of the Run button. (ex. A to 01) And if it's not an English alphabet letter then leaving it as it is. Capitalization doesn't matter (a and A is still 01) and spaces should be kept.
For visual purposes:
"Apple!" should be converted to "0116161205!"
"stack Overflow" to "1920010311 1522051806121523"
"über" to "ü020518"
I have tried a few methods I found on here, but had zero clue how to add the extra 0 in front of the first 9 letters or keep the spaces. Any help is much appreciated.
Here is a solution :
//Create a Map of character and equivalent number
Map<Character, String> lettersToNumber = new HashMap<>();
int i = 1;
for(char c = 'a'; c <= 'z'; c++) {
lettersToNumber.put(c, String.format("%02d", i++));
}
//Loop over the characters of your input and the corresponding number
String result = "";
for(char c : "Apple!".toCharArray()) {
char x = Character.toLowerCase(c);
result+= lettersToNumber.containsKey(x) ? lettersToNumber.get(x) : c;
}
Input, Output
Apple! => 0116161205!
stack Overflow => 1920010311 1522051806121523
über => ü020518
So given...
(ex. A to 01) And if it's not an English alphabet letter then leaving it as it is. Capitalization doesn't matter (a and A is still 01) and spaces should be kept.
This raises some interesting points:
We don't care about non-english characters, so we can dispense with issues around UTF encoding
Capitalization doesn't matter
Spaces should be kept
The reason these points are interesting to me is it means we're only interested in a small subset of characters (1-26). This immediately screams "ASCII" to me!
This provides an immediate lookup table which doesn't require us to produce anything up front, it's immediately accessible.
A quick look at any ascii table provides us with all the information we need. A-Z is in the range of 65-90 (since we don't care about case, we don't need to worry about the lower case range.
But how does that help us!?
Well, this now means the primary question becomes, "How do we convert a char to an int?", which is amazingly simple! A char can be both a "character" and a "number" at the same time, because of the ASCII encoding support!
So if you were to print out (int)'A', it would print 65! And since all the characters are in order, we just need to subtract 64 from 65 to get 1!
That's basically your entire problem solved right there!
Oh, okay, you need to deal with the edge cases of characters not falling between A-Z, but that's just a simple if statement
A solution based on the above "might" look something like...
public static String convert(String text) {
int offset = 64;
StringBuilder sb = new StringBuilder(32);
for (char c : text.toCharArray()) {
char input = Character.toUpperCase(c);
int value = ((int) input) - offset;
if (value < 1 || value > 25) {
sb.append(c);
} else {
sb.append(String.format("%02d", value));
}
}
return sb.toString();
}
Now, there are a number of ways you might approach this, I've chosen a path based on my understanding of the problem and my experience.
And based on your example input...
String[] test = {"Apple!", "stack Overflow", "über"};
for (String value : test) {
System.out.println(value + " = " + convert(value));
}
would produce the following output...
Apple! = 0116161205!
stack Overflow = 1920010311 1522051806121523
über = ü020518

The output of this loop should be less than 1, but I get very large numbers [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
This program is supposed to count the number of characters "c" and "g" in genes in the DNA string and then take that number and divide it by the length of each gene. The number of cs and gs is always < gene.length(), therefore the output should be something like 0.65555, 0.35657 etc, but I get large numbers like 141, etc. Not sure what is wrong with this loop.
public void testfile(){
String dnaTest = "aaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaacccttaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctaaccctcacccttctaact";
int counter = 0;
for(String gene : s1.data()) {
for (char cORg : gene.toCharArray()) {
if ((cORg == 'c') || (cORg == 'g')) {
counter ++;
}
System.out.print(gene +" ");
}
float cgRatioGenes = counter/gene.length();
System.out.println("cgRatio: " + cgRatioGenes);
}
}
}
If you spot the error, let me know. Thanks!
EDIT
Even without the parentesis at the end of the DNA string and with the closing bracket, the loop was not producing the results I expected. Therefore, it is not off topic.
Two problems:
First, you never reinitialize counter when you start the loop again. Move that declaration inside the loop so that each repetition starts with a counter of zero.
If you make that change, all your results will be zero though, because you're diving two integers, which will truncate the results. Cast one to float, so that it keeps the decimal part. See this question for more information on the problem
for(String gene : s1.data()) {
int counter = 0; //Moved inside the for loop, so that it always starts at 0
for (char cORg : gene.toCharArray()) {
if ((cORg == 'c') || (cORg == 'g')) {
counter ++;
}
System.out.print(gene +" ");
}
//Floating point division, instead of integer division
float cgRatioGenes = ((float)counter)/gene.length();
System.out.println("cgRatio: " + cgRatioGenes);
}
One potential problem is here
float cgRatioGenes = counter/gene.length();
As gene.length() is an integer value the ratio is not computed correctly. Instead, you should cast one of them to float like this
float cgRatioGenes = ((float)counter)/gene.length();
In addition, the counter variable should probably be initialized to zero for each gene (unless you want to count the c/g values over all genes).
This probably does not explain the behavior you are observing, but it is not possible to figure it out unless a complete working example is given.
It's a little unclear what the exact intent of this code is, but my guess is that you're using one int counter for every gene in s1.data(). I assume you want to count the number of valid characters per gene, not in the entire pool.
If you do want to count for the entire pool, the problem is that you're peforming gene.length outside of the for, which should honestly throw a compiler error unless you have a gene defined somewhere else as well.
Additionally, you're dividing two ints for your answer, which will yield an int. Case one of your variables to float to get a decimal answer.

Java function to output every case possible in a string [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am trying to make a function that outputs every case possible of a string. The function must output each variation of a string and keep a counter for that variation. For example in no particular order:
C.d
C>d
C>D
C.D
c.d
c.D
c>D
c>d
So far I have this:
public int allCase(String data)
{
int count=0; // counter for the amount of case changes completed
int size= data.length();// length of incoming string
char c[]= data.toLowerCase().toCharArray();
double maxpos=Math.pow(2,size);
System.out.println("Maximum possibilities= "+maxpos);
for(int i=0;i<size;i++)
{
if (c[i]> 33 && c[i]<64) // if the character is special characters !##$%^&*()_<>?,./
{ // prints characters in front and behind of special character
System.out.println( data.substring(0,i)+((char)(c[i]+16))+data.substring(i+1));
}
else{
// output the string variation
}
count++;
}
return count;
}
You can handle the alphabetic characters as a group, adding or subtracting 32, but the rest of the mappings aren't regular enough to beat a table lookup.
Keep two parallel strings:
shifted = "ABCDEFGHIJKLMNOPQRSTUVWXYZ~!##$%^&*()_+|<>?:\"{}";
unshifted = "abcdefghijklmnopqrstuvwxyz`1234567890-=\,./;'[]";
Then, find each character in one or the other string with .indexOf(). Find the opposite shift at the same index in the other string. If a character isn't in either string, then it's a space or another character that isn't part of a shifted/unshifted pair. The total number of strings to generate is then 2^(number of chars found in one of those strings).
Speaking of powers of 2, using Math.pow() is a lousy way to compute small powers of 2. Use 1L<<n instead of Math.pow(n) for integers 0 <= n <= 62, or even 1<<n for 0<=n<=30 if you're able to live with only being able to print out a billion or so strings.
You can make an iterative version, looping from an index value of 0 to (2^n)-1, where n the length of the input string, and then loop for k=0 to (n-1) testing bit k of the outer loop index value to see whether to print upper or lowercase version of the character. I didn't see it before, but Hot Licks has a comment about using this approach. To perform that test, observe that index&(1<<k) is nonzero if and only if bit k is set in (index).
A recursive version is much simpler, but I suspect you'll learn about that later.

Comparing String Integers Issue

I have a scanner that reads a 7 character alphanumeric code (inputted by the user). the String variable is called "code".
The last character of the code (7th character, 6th index) MUST BE NUMERIC, while the rest may be either numeric or alphabetical.
So, I sought ought to make a catch, which would stop the rest of the method from executing if the last character in the code was anything but a number (from 0 - 9).
However, my code does not work as expected, seeing as even if my code ends in an integer between 0 and 9, the if statement will be met, and print out "last character in code is non-numerical).
example code: 45m4av7
CharacterAtEnd prints out as the string character 7, as it should.
however my program still tells me my code ends non-numerically.
I'm aware that my number values are string characters, but it shouldnt matter, should it?
also I apparently cannot compare actual integer values with an "|", which is mainly why im using String.valueOf, and taking the string characters of 0-9.
String characterAtEnd = String.valueOf(code.charAt(code.length()-1));
System.out.println(characterAtEnd);
if(!characterAtEnd.equals(String.valueOf(0|1|2|3|4|5|6|7|8|9))){
System.out.println("INVALID CRC CODE: last character in code in non-numerical.");
System.exit(0);
I cannot for the life of me, figure out why my program is telling me my code (that has a 7 at the end) ends non-numerically. It should skip the if statement and continue on. right?
The String contains method will work here:
String digits = "0123456789";
digits.contains(characterAtEnd); // true if ends with digit, false otherwise
String.valueOf(0|1|2|3|4|5|6|7|8|9) is actually "15", which of course can never be equal to the last character. This should make sense, because 0|1|2|3|4|5|6|7|8|9 evaluates to 15 using integer math, which then gets converted to a String.
Alternatively, try this:
String code = "45m4av7";
char characterAtEnd = code.charAt(code.length() - 1);
System.out.println(characterAtEnd);
if(characterAtEnd < '0' || characterAtEnd > '9'){
System.out.println("INVALID CRC CODE: last character in code in non-numerical.");
System.exit(0);
}
You are doing bitwise operations here: if(!characterAtEnd.equals(String.valueOf(0|1|2|3|4|5|6|7|8|9)))
Check out the difference between | and ||
This bit of code should accomplish your task using regular expressions:
String code = "45m4av7";
if (!code.matches("^.+?\\d$")){
System.out.println("INVALID CRC CODE");
}
Also, for reference, this method sometimes comes in handy in similar situations:
/* returns true if someString actually ends with the specified suffix */
someString.endsWith(suffix);
As .endswith(suffix) does not take regular expressions, if you wanted to go through all possible lower-case alphabet values, you'd need to do something like this:
/* ASCII approach */
String s = "hello";
boolean endsInLetter = false;
for (int i = 97; i <= 122; i++) {
if (s.endsWith(String.valueOf(Character.toChars(i)))) {
endsInLetter = true;
}
}
System.out.println(endsInLetter);
/* String approach */
String alphabet = "abcdefghijklmnopqrstuvwxyz";
boolean endsInLetter2 = false;
for (int i = 0; i < alphabet.length(); i++) {
if (s.endsWith(String.valueOf(alphabet.charAt(i)))) {
endsInLetter2 = true;
}
}
System.out.println(endsInLetter2);
Note that neither of the aforementioned approaches are a good idea - they are clunky and rather inefficient.
Going off of the ASCII approach, you could even do something like this:
ASCII reference : http://www.asciitable.com/
int i = (int)code.charAt(code.length() - 1);
/* Corresponding ASCII values to digits */
if(i <= 57 && i >= 48){
System.out.println("Last char is a digit!");
}
If you want a one-liner, stick to regular expressions, for example:
System.out.println((!code.matches("^.+?\\d$")? "Invalid CRC Code" : "Valid CRC Code"));
I hope this helps!

Categories