Why is my forloop not working? - java

This is my first question on this site so I'm not sure how to do this, but my question is as follows:
This is just a small piece of a code with multiple methods.
I need to print the ASCII codes of all the characters in a String (input from the user). Now I am trying to use a for-loop which scans the first character prints the ASCII code of it, then scans the next one etc. But at the moment its just printing the first character's ASCII code a few times. Obviously there's something wrong with my for-loop but I've been trying to figure it out and I really can't find it.
static String zin(String zin) {
int length = zin.length();
char letter = zin.charAt(0);
int ascii = (int) letter;
for (int i = 0; i < zin.length(); i++ ) {
System.out.println((int) ascii);
}
return zin;
}

The reason is because you don't re-assign ascii. Try this:
static String zin(String zin) {
int i = 0;
int length = zin.length();
for ( i = 0; i < zin.length(); i++ ) {
int ascii = (int)zin.charAt(i);
System.out.println(ascii);
}
return zin;
}

The problem in your code is though you have a for loop you are not iterating through the strung using that for loop. You only get the 1st char of that string. Instead of that use
static String zin(String zin) {
for (int i = 0; i < zin.length(); i++) {
System.out.println((int) zin.charAt(i));
}
return zin;
}

Related

Unsure how to implement for loop

Hello I am having trouble implementing this function
Function:
Decompress the String s. Character in the string is preceded by a number. The number tells you how many times to repeat the letter. return a new string.
"3d1v0m" becomes "dddv"
I realize my code is incorrect thus far. I am unsure on how to fix it.
My code thus far is :
int start = 0;
for(int j = 0; j < s.length(); j++){
if (s.isDigit(charAt(s.indexOf(j)) == true){
Integer.parseInt(s.substring(0, s.index(j))
Assuming the input is in correct format, the following can be a simple code using for loop. Of course this is not a stylish code and you may write more concise and functional style code using Commons Lang or Guava.
StringBuilder builder = new StringBuilder();
for (int i = 0; i < s.length(); i += 2) {
final int n = Character.getNumericValue(s.charAt(i));
for (int j = 0; j < n; j++) {
builder.append(s.charAt(i + 1));
}
}
System.out.println(builder.toString());
Here is a solution you may like to use that uses Regex:
String query = "3d1v0m";
StringBuilder result = new StringBuilder();
String[] digitsA = query.split("\\D+");
String[] letterA = query.split("[0-9]+");
for (int arrIndex = 0; arrIndex < digitsA.length; arrIndex++)
{
for (int count = 0; count < Integer.parseInt(digitsA[arrIndex]); count++)
{
result.append(letterA[arrIndex + 1]);
}
}
System.out.println(result);
Output
dddv
This solution is scalable to support more than 1 digit numbers and more than 1 letter patterns.
i.e.
Input
3vs1a10m
Output
vsvsvsammmmmmmmmm
Though Nami's answer is terse and good. I'm still adding my solution for variety, built as a static method, which does not use a nested For loop, instead, it uses a While loop. And, it requires that the input string has even number of characters and every odd positioned character in the compressed string is a number.
public static String decompress_string(String compressed_string)
{
String decompressed_string = "";
for(int i=0; i<compressed_string.length(); i = i+2) //Skip by 2 characters in the compressed string
{
if(compressed_string.substring(i, i+1).matches("\\d")) //Check for a number at odd positions
{
int reps = Integer.parseInt(compressed_string.substring(i, i+1)); //Take the first number
String character = compressed_string.substring(i+1, i+2); //Take the next character in sequence
int count = 1;
while(count<=reps)//check if at least one repetition is required
{
decompressed_string = decompressed_string + character; //append the character to end of string
count++;
};
}
else
{
//In case the first character of the code pair is not a number
//Or when the string has uneven number of characters
return("Incorrect compressed string!!");
}
}
return decompressed_string;
}

StringBuilder#appendCodePoint(int) behaves unexpectedly

java.lang.StringBuilder's appendCodePoint(...) method, to me, behaves in an unexpected manner.
For unicode code points above Character.MAX_VALUE (which will need 3 or 4 bytes to encode in UTF-8, which is my Eclipse workspace setting), it behaves strangely.
I append a String's Unicode code points one by one to a StringBuilder, but its output looks different in the end.
I suspect that a call to Character.toSurrogates(codePoint, value, count) in AbstractStringBuilder#appendCodePoint(...) causes this, but I don't know how to work around it.
My code:
// returns random string in range of unicode code points 0x2F800 to 0x2FA1F
// e.g. 槪𥥼報悔𦖨嘆汧犕尢𦔣洴真硎尢趼犀㠯弢卿𢛔芋玥峀䔫䩶莭型築𡷦𩐊
String s = getRandomChineseJapaneseKoreanStringCompatibilitySupplementOfMaxLength(length);
System.out.println(s);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < getCodePointCount(s); i++) {
sb.appendCodePoint(s.codePointAt(i));
}
// prints some of the CJK characters, but between them there is a '?'
// e.g. 槪?𥥼?報?悔?𦖨?嘆?汧?犕?尢?𦔣?洴?真?硎?尢?趼?
System.out.println(sb.toString());
// returns random string in range of unicode code points 0x20000 to 0x2A6DF
// e.g. 𤸥𤈍𪉷𪉔𤑺𡹋𠋴𨸁𦧖𣯠𨚾𣥷𪂶𦄃𧊈𤧘𢙕𪚋𤧒𥩛𧆞𨕌𣸑𡚊𥽚𡛳𣐸𩆟𩣞𥑡
s = getRandomChineseJapaneseKoreanStringExtensionBOfMaxLength(length);
// prints the CJK characters correctly
System.out.println(s);
sb = new StringBuilder();
for (int i = 0; i < getCodePointCount(s); i++) {
sb.appendCodePoint(s.codePointAt(i));
}
// prints some of the CJK characters, but between them there is a '?'
// e.g. 𤸥?𤈍?𪉷?𪉔?𤑺?𡹋?𠋴?𨸁?𦧖?𣯠?𨚾?𣥷?𪂶?𦄃?𧊈?
System.out.println(sb.toString());
With:
public static int getCodePointCount(String s) {
return s.codePointCount(0, s.length());
}
public static String getRandomChineseJapaneseKoreanStringExtensionBOfMaxLength(int length) {
return getRandomStringOfMaxLengthInRange(length, 0x20000, 0x2A6DF);
}
public static String getRandomChineseJapaneseKoreanStringCompatibilitySupplementOfMaxLength(int length) {
return getRandomStringOfMaxLengthInRange(length, 0x2F800, 0x2FA1F);
}
private static String getRandomStringOfMaxLengthInRange(int length, int from, int to) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
// try to find a valid character MAX_TRIES times
for (int j = 0; j < MAX_TRIES; j++) {
int unicodeInt = from + random.nextInt(to - from);
if (Character.isValidCodePoint(unicodeInt) &&
(Character.isLetter(unicodeInt) || Character.isDigit(unicodeInt) ||
Character.isWhitespace(unicodeInt))) {
sb.appendCodePoint(unicodeInt);
break;
}
}
}
return new String(sb.toString().getBytes(), "UTF-8");
}
You're iterating over the code points incorrectly. You should use the strategy presented by Jonathan Feinberg here
final int length = s.length();
for (int offset = 0; offset < length; ) {
final int codepoint = s.codePointAt(offset);
// do something with the codepoint
offset += Character.charCount(codepoint);
}
or since Java 8
s.codePoints().forEach(/* do something */);
Note the Javadoc of String#codePointAt(int)
Returns the character (Unicode code point) at the specified index. The
index refers to char values (Unicode code units) and ranges from 0 to
length()- 1.
You were iterating from 0 to codePointCount. If the character is not a high-low surrogate pair, it's returned alone. In that case, your index should only increase by 1. Otherwise, it should be increased by 2 (Character#charCount(int) deals with this) as you're getting the codepoint corresponding to the pair.
Change your loops from this:
for (int i = 0; i < getCodePointCount(s); i++) {
to this:
for (int i = 0; i < getCodePointCount(s); i = s.offsetByCodePoints(i, 1)) {
In Java, a char is a single UTF-16 value. Supplemental codepoints take up two chars in a String.
But you are looping every single char in your String. This means that you are reading each supplemental codepoint twice: The first time, you are reading both of its UTF-16 surrogate chars; the second time, you are reading and appending just the low surrogate char.
Consider a string which contains only one codepoint, 0x2f8eb. A Java String representing that codepoint would actually contain this:
"\ud87e\udceb"
If you loop through each individual char index, then your loop would effectively do this:
sb.appendCodePoint(0x2f8eb); // codepoint found at index 0
sb.appendCodePoint(0xdceb); // codepoint found at index 1

Writing a word backwards using only 1 string converted to an array, a character, and an integer

I'm trying to create a code that writes an array backwards and can only use an array, character, and an integer. So far I have this, but it isn't doing anything. I'm a beginner at java.
import javax.swing.JOptionPane;
public class TestingArraysUsingOneArray
{
public static void main(String args[])
{
{
String str = JOptionPane.showInputDialog("Enter any text that you want to reverse.");
char[] charArray = str.toCharArray();
char current;
int a = 0;
for (int i = 0; i>=str.length()%2; i++) {
current = str.charAt(a);
charArray[a] = str.charAt(str.length()-a);
charArray[str.length()-a] = current;
a++;
}
System.out.println(charArray);
}
}
}
The output I'm getting is hello when I enter in hello. What do I need to change to get this program to work?
Your don't need half the code. I would try to make it as simple as possible. Try this
String str = ...
for(int i = str.length() - 1; i >= 0; i--)
System.out.print(str.chatAt(i));
System.out.println();
If the assignment says you have to reverse an array of chars you can do this.
String str = ...
char[] chars = str.toCharArray();
for(int i = 0; i < chars.length/2; i++) {
char ch = chars[i];
chars[i] = chars[chars.length - i - 1];
chars[chars.length - i - 1] = ch;
}
System.out.println(new String(chars));
As you can see this is needlessly complicated, so you would not do this. Another way you can do this if you don't want to use a loop is
String str = ...
System.out.println(new StringBuilder(str).reverse());
Well, for one thing, I think you want i<str.length()/2 - this will give you half the length. If you say i>=str.length()%2, you're getting the remainder when its length is divided by 2 - which is always either 1 or 0, and the loop continues as long as i is more than either 1 or 0. This should result in an infinite loop. Also, you don't need the variable a, as it is always equivalent to i. This, however, results in the string index being out of bounds sometimes, but I'll let you figure out how to solve that.
Your for loop is never entering because it should be i < str.length(), because at the moment when i is 0, the current check will immediately fail.
With that condition set, you need to change the two instances of str.length()-a to str.length()-a-1, because str.length-a when a is 0 will cause an StringIndexOutOfBoundException because the maximum index you can access is str.length-1.
Those are just corrections to the existing code. There's a better, more concise way of reversing the string suggested in another answer, which is the one you should accept.
What you want to do is replace the first character with the last and so on..
char[] charArray = str.toCharArray();
char current;
for (int i = 0; i < charArray.length / 2; i++) {
current = charArray[i];
charArray[i] = charArray[charArray.length - i - 1];
charArray[charArray.length - i - 1] = current;
}
The a int is completely redundant, and it would be a second int in your code - don't forget the variable in the for loop.

Doubling each letter in a String

I'm doing a project for Java 1, and I'm completely stuck on this question.
Basically I need to double each letter in a string.
"abc" -> "aabbcc"
"uk" -> "uukk"
"t" -> "tt"
I need to do it in a while loop in what is considered "Java 1" worthy. So i'm guessing that this means more of a problematic approach.
I know that the easiest way for me to do this, from my knowledge, would be using the charAt method in a while loop, but for some reason my mind can't figure out how to return the characters to another method as a string.
Thanks
[EDIT] My Code (wrong, but maybe this will help)
int index = 0;
int length = str.length();
while (index < length) {
return str.charAt(index) + str.charAt(index);
index++;
}
String s="mystring".replaceAll(".", "$0$0");
The method String.replaceAll uses the regular expression syntax which is described in the documentation of the Pattern class, where we can learn that . matches “any character”. Within the replacement, $number refers to numbered “capturing group” whereas $0 is predefined as the entire match. So $0$0 refers to the matching character two times. As the name of the method suggests, it is performed for all matches, i.e. all characters.
Yeah, a for loop would really make more sense here, but if you need to use a while loop then it would look like this:
String s = "abc";
String result = "";
int i = 0;
while (i < s.length()){
char c = s.charAt(i);
result = result + c + c;
i++;
}
You can do:
public void doubleString(String input) {
String output = "";
for (char c : input.toCharArray()) {
output += c + c;
}
System.out.println(output);
}
Your intuition is very good. charAt(i) will return the character in the string at location i, yes?
You also said you wanted to use a loop. A for loop, traversing the length of the list, string.length(), will allow you to do this. At every single node in the string, what do you need to do? Double the character.
Let's take a look at your code:
int index = 0;
int length = str.length();
while (index < length) {
return str.charAt(index) + str.charAt(index); //return ends the method
index++;
}
Problematically for your code, you are returning two characters immediately upon entering the loop. So for a string abc, you are returning aa. Let's store the aa in memory instead, and then return the completed string like so:
int index = 0;
int length = str.length();
String newString = "";
while (index < length) {
newString += str.charAt(index) + str.charAt(index);
index++;
}
return newString;
This will add the character to newString, allowing you to return the entire completed string, as opposed to a single set of doubled characters.
By the way, this may be easier to do as a for loop, condensing and clarifying your code. My personal solution (for a Java 1 class) would look something like this:
String newString = "";
for (int i = 0; i < str.length(); i++){
newString += str.charAt(i) + str.charAt(i);
}
return newString;
Hope this helps.
try this
String a = "abcd";
char[] aa = new char[a.length() * 2];
for(int i = 0, j = 0; j< a.length(); i+=2, j++){
aa[i] = a.charAt(j);
aa[i+1]= a.charAt(j);
}
System.out.println(aa);
public static char[] doubleChars(final char[] input) {
final char[] output = new char[input.length * 2];
for (int i = 0; i < input.length; i++) {
output[i] = input[i];
output[i + 1] = input[i];
}
return output;
}
Assuming this is inside a method, you should understand that you can only return once from a method. After encountering a return statement, the control goes back to the calling method. Thus your approach of returning char every time in a loop is faulty.
int index = 0;
int length = str.length();
while (index < length) {
return str.charAt(index) + str.charAt(index); // only the first return is reachable,other are not executed
index++;
}
Change your method to build a String and return it
public String modify(String str)
{
int index = 0;
int length = str.length();
String result="";
while (index < length) {
result += str.charAt[index]+str.charAt[index];
index++;
}
return result;
}

Using for loop to get the Hamming distance between 2 strings

In this task i need to get the Hamming distance (the Hamming distance between two strings of equal length is the number of positions at which the corresponding symbols are different - from Wikipedia) between the two strings sequence1 and sequence2.
First i made 2 new strings which is the 2 original strings but both with lowered case to make comparing easier. Then i resorted to using the for loop and if to compare the 2 strings. For any differences in characters in these 2 pair of string, the loop would add 1 to an int x = 0. The returns of the method will be the value of this x.
public static int getHammingDistance(String sequence1, String sequence2) {
int a = 0;
String sequenceX = sequence1.toLowerCase();
String sequenceY = sequence2.toLowerCase();
for (int x = 0; x < sequenceX.length(); x++) {
for (int y = 0; y < sequenceY.length(); y++) {
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else if (sequenceX.charAt(x) != sequenceY.charAt(y)) {
a += 1;
}
}
}
return a;
}
So does the code looks good and functional enough? Anything i could to fix or to optimize the code? Thanks in advance. I'm a huge noob so pardon me if i asked anything silly
From my point the following implementation would be ok:
public static int getHammingDistance(String sequence1, String sequence2) {
char[] s1 = sequence1.toCharArray();
char[] s2 = sequence2.toCharArray();
int shorter = Math.min(s1.length, s2.length);
int longest = Math.max(s1.length, s2.length);
int result = 0;
for (int i=0; i<shorter; i++) {
if (s1[i] != s2[i]) result++;
}
result += longest - shorter;
return result;
}
uses array, what avoids the invocation of two method (charAt) for each single char that needs to be compared;
avoid exception when one string is longer than the other.
your code is completely off.
as you said yourself, the distance is the number of places where the strings differ - so you should only have 1 loop, going over both strings at once. instead you have 2 nested loops that compare every index in string a to every index in string b.
also, writing an if condition that results in a+=0 is a waste of time.
try this instead:
for (int x = 0; x < sequenceX.length(); x++) { //both are of the same length
if (sequenceX.charAt(x) != sequenceY.charAt(x)) {
a += 1;
}
}
also, this is still a naive approach which will probbaly not work with complex unicode characters (where 2 characters can be logically equal yet not have the same character code)
public static int getHammingDistance(String sequenceX, String sequenceY) {
int a = 0;
// String sequenceX = sequence1.toLowerCase();
//String sequenceY = sequence2.toLowerCase();
if (sequenceX.length() != sequenceY.length()) {
return -1; //input strings should be of equal length
}
for (int i = 0; i < sequenceX.length(); i++) {
if (sequenceX.charAt(i) != sequenceY.charAt(i)) {
a++;
}
}
return a;
}
Your code is OK, however I'd suggest you the following improvements.
do not use charAt() of string. Get char array from string using toCharArray() before loop and then work with this array. This is more readable and more effective.
The structure
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else if (sequenceX.charAt(x) != sequenceY.charAt(y)) {
a += 1;
}
looks redundant. Fix it to:
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else {
a += 1;
}
Moreover taking into account that I recommended you to work with array change it to something like:
a += seqx[x] == seqY[x] ? 0 : 1
less code less bugs...
EDIT: as mentionded by #radai you do not need if/else structure at all: adding 0 to a is redundant.

Categories