Java reverse string method - java

I'm tying to learn Java. I need to make a method called reverse that gets a string and return a string (but in reverse order). Here is what i tried. Can you fix the code and explain what I'm doing wrong? Please also give me some advice about a good start in Java. Thank you!
public class Test{
public static String reverse(String a){
int j = a.length();
char[] newWord = new char[j];
for(int i=0;i<a.length();i++)
{
newWord[j] = a.charAt(i);
j--;
}
return new String(newWord);
}
public static void main(String a[]){
String word = "abcdefgh";
System.out.println(reverse(word));
}
}

You can use this to reverse the string, you don't need to use your own method
new StringBuilder(word).reverse().toString()
If you want to use your solution you must change int j = a.length() to int j = a.length() -1;

The fixed code is
public class Test {
public static String reverse(String a) {
int j = a.length();
char[] newWord = new char[j];
for (int i = 0; i < a.length(); i++) {
newWord[--j] = a.charAt(i);
}
return new String(newWord);
}
public static void main(String a[]) {
String word = "abcdefgh";
System.out.println(reverse(word));
}
}
Like others have mentioned, arrays indexes start at 0. So if an array has size 5 for example it has indices 0,1,2,3,4. It does not have an index 5.
For an example of a string with length 5, the code change that I did newWord[--j] = a.charAt(i); will assign to the indices 4,3,2,1,0 in that order.
Regarding getting a good start in Java, I think you could try https://softwareengineering.stackexchange.com/. This site is not meant for that kind of thing.

This is a common difficulty with new Java developers.
The point you are missing is that the last entry in an array is at position a.length-1. Similarly for Strings
Here's an improved version to demonstrate.
public static String reverse(String a) {
char[] newWord = new char[a.length()];
for (int i = 0, j = a.length() - 1; i < a.length(); i++, j--) {
newWord[j] = a.charAt(i);
}
return new String(newWord);
}

You're already on the right track with your method. The one thing I will say to you is that you don't need to use an array of characters and then use something like return new String(newWord);. That's overly complicated for beginner Java in my view.
Instead, you can create an empty String and just keep appending the characters onto it as you loop through all the characters in the String you want to reverse.
So your for loop, because you're reversing the word, should begin at the end of the word being reversed (a in this case) and work backwards to index position 0 (ie. the start of the word being reversed).
Try this and see if this makes sense to you:
public static String reverse(String a) {
String reversedWord = "";
for (int index = a.length() - 1; index >= 0; index --) {
reversedWord += a.charAt(index);
}
return reversedWord;
}
This is, then, starting at the end of a, working backwards one character at a time (hence the use of index --) until we reach a point where index has gone beyond the character at index position 0 (the middle condition of index >= 0).
At each index position, we are simply taking the character from the a String and appending it onto the reversedWord String.
Hope this helps! Feel free to ask any other questions if you are stuck on this.

In your for loop, body must be as that
newWord[--j] = a.charAt(i);. It's because if the lenght of array is 8, its indexes are 0-7. So we first decrement j and then use it as array pointer.

public class Test {
public static String reverse(String a) {
int size= a.length();//size of string
char[] newWord = new char[size];//intialize
for (int i = size-1,j=0; i >=0 ; i--,j++) {//loop start from 7 to 0
newWord[j] = a.charAt(i);// and reverse string goes from 0 to 7
}
return new String(newWord);
}
public static void main(String a[]) {
String word = "abcdefgh";
System.out.println(reverse(word));
}
}

static void reverse {
String word = "Hello World";
StringBuilder str = new StringBuilder(word);
str.reverse();
System.out.println(str);
}
or you could do
new StringBuilder(word).reverse().toString()

public static void main(String[] args) {
String input = "hello world";
String output = new String();
for (int i = input.length() - 1; i >= 0; i--) {
output = output + input.charAt(i);
}
System.out.println(output);
}

package Reverse;
import java.util.*;
public class StringReverse {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter a String: ");
String original = input.nextLine();
String rev = "";// Initialize as Empty String
for(int i = original.length() - 1 ; i>=0 ; i--){
rev += original.charAt(i);
}
System.out.println("Reverse form: "+rev);
}
}

Related

I'm stuck. I need to adjust my loops so they continue to compare my two arrays but not print out all the extra characters

I have to compare two string arrays. If the any of the characters in myArray match a character in argArray then I need to swap the case of the character in myArray. I'm almost there but am getting extra output.
This is what I have so far -
public class Main {
public static void main(String[] args) {
Main ob = new Main();
ob.reverse("bcdxyz#3210.");
}
public String reverse(String arg) {
String reverseCap = "";
String myStr = "abc, XYZ; 123.";
char[] argArray = arg.toCharArray();
char[] myArray = myStr.toCharArray();
for (int i =0; i < myArray.length; i++) {
for (int j =0; j < argArray.length; j++){
if (myArray[i] == argArray[j] && Character.isLowerCase(myArray[i])){
reverseCap += Character.toUpperCase(myArray[i]);
} else if (myArray[i] == argArray[j] && Character.isUpperCase(myArray[i])){
reverseCap += Character.toLowerCase(myArray[i]);
} else {
reverseCap += myArray[i];
}
}
}
System.out.println(reverseCap);
return null;
}
I want reverseCap to be "aBC, xyz, 123." but am getting the following -
"aaaaaaaaaaaaBbbbbbbbbbbbcCcccccccccc,,,,,,,,,,,, XXXXXXXXXXXXYYYYYYYYYYYYZZZZZZZZZZZZ;;;;;;;;;;;; 111111111111222222222222333333333333............
".
I've been staring at this for hours so I figured it was time to ask for help before I pluck my eyes out.
Marce noted the problem of adding characters to reverseCap on every iteration. Here is a solution that solves that problem and performs the case changes in place. Checking for a match first and then changing the case simplifies the logic a bit. Note myArray[i] needs to be lowercased before checking against arg[i] because the former may be an uppercase character; this is not needed for argArray[j] because those characters are assumed to be all lowercase. Finally, once the inner loop has matched, further iterations of it are no longer needed.
public class Main {
public static void main(String[] args) {
Main ob = new Main();
String testStr = "abc, XYZ; 123.";
String testArg = "bcdxyz#3210.";
System.out.println(testStr + " using " + testArg + " =>");
System.out.println(ob.reverse(testStr, testArg));
}
public String reverse(String myStr, String myArg) {
char[] myArray = myStr.toCharArray();
char[] argArray = myArg.toCharArray();
for (int i =0; i < myArray.length; i++) {
for (int j =0; j < argArray.length; j++) {
if (Character.toLowerCase(myArray[i]) == argArray[j]) {
if (Character.isLowerCase(myArray[i])) {
myArray[i] = Character.toUpperCase(myArray[i]);
} else if (Character.isUpperCase(myArray[i])) {
myArray[i] = Character.toLowerCase(myArray[i]);
}
break;
}
}
}
return String.valueOf(myArray);
}
}
With this part
} else {
reverseCap += myArray[i];
}
you're adding a character to reverseCap with every iteration, regardless if the characters match or not.
In your specific example, you could just leave that out, since every character in myStr also appears in arg, but if you want to add characters to reverseCap, even if they don't appear in arg, you'll need a way of checking if you already added a character to reverseCap.
Change
String reverseCap = "";
to
char[] reverseCap = new char[myStr.length()];
and then for each occurrence of
reverseCap +=
change that to read
reverseCap[i] =
Finally, convert reverseCap to a String:
String result = String.valueOf(reverseCap);
You are currently returning null. Consider returning result, and moving the System.out.println(...) into the main() method.
Update:
I think a better way to approach this is to use a lookup map containing upper/lower case pairs and their inverse to get the replacement character. The nested for loops are a bit gnarly.
/**
* Example: for the string "bcdxyz#3210."
* the lookup map is
* {B=b, b=B, C=c, c=C, D=d, d=D, X=x, x=X, Y=y, y=Y, Z=z, z=Z}
* <p>
* Using a map to get the inverse of a character is faster than repetitively
* looping through the string.
* </p>
* #param arg
* #return
*/
public String reverse2(String arg) {
Map<Character, Character> inverseLookup = createInverseLookupMap(arg);
String myStr = "abc, XYZ; 123.";
String result = myStr.chars()
.mapToObj(ch -> Character.toString(inverseLookup.getOrDefault(ch, (char) ch)))
.collect(Collectors.joining());
return result;
}
private Map<Character, Character> createInverseLookupMap(String arg) {
Map<Character, Character> lookupMap = arg.chars()
.filter(ch -> Character.isLetter(ch))
.mapToObj(this::getPairs)
.flatMap(List::stream)
.collect(Collectors.toMap(Pair::key, Pair::value));
System.out.println(lookupMap);
return lookupMap;
}
private List<Pair> getPairs(int ch) {
char upperVariant = (char) Character.toUpperCase(ch);
return List.of(
new Pair(upperVariant, Character.toLowerCase(upperVariant)),
new Pair(Character.toLowerCase(upperVariant), upperVariant));
}
static record Pair(Character key, Character value) {
}
But if one is not used to the Java streaming API, this might look a bit gnarly too.

Counting the number of specific occurrences in a java String

I am attempting to solve a problem where I create a method that counts the number of occurrences of capital and lowercase ("A" or "a") in a certain string. I have been working on this problem for a week now, and the main error that I am receiving is that "char cannot be dereferenced". Can anyone point me in the correct direction on this Java problem? Thank you.
class Main{
public static int countA (String s)
{
String s1 = "a";
String s2 = "A";
int count = 0;
for (int i = 0; i < s.length; i++){
String s3 = s.charAt(i);
if (s3.equals(s1) || s3.equals(s2)){
count += 1;
}
else{
System.out.print("");
}
}
}
//test case below (dont change):
public static void main(String[] args){
System.out.println(countA("aaA")); //3
System.out.println(countA("aaBBdf8k3AAadnklA")); //6
}
}
try a simpler solution
String in = "aaBBdf8k3AAadnklA";
String out = in.replace ("A", "").replace ("a", "");
int lenDiff = in.length () - out.length ();
Also as #chris mentions in his answer, the String could be converted to lowercase first and then only do a single check
the main error that I am receiving is that "char cannot be
dereferenced"
change this:
s.length // this syntax is incorrect
to this:
s.length() // this is how you invoke the length method on a string
also, change this:
String s3 = s.charAt(i); // you cannot assign a char type to string type
to this:
String s3 = Character.toString(s.charAt(i)); // convert the char to string
another solution to accomplishing your task in a simpler manner is by using the Stream#filter method. Then convert each String within the Stream to lowercase prior to comparison, if any Strings match "a" we keep it, if not we ignore it and at the end, we simply return the count.
public static int countA(String input)
{
return (int)Arrays.stream(input.split("")).filter(s -> s.toLowerCase().equals("a")).count();
}
For counting the number of time 'a' or 'A' appears in a String:
public int numberOfA(String s) {
s = s.toLowerCase();
int sum = 0;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == 'a')
sum++;
}
return sum;
}
Or just replace everything else and see how long your string is:
int numberOfA = string.replaceAll("[^aA]", "").length();
To find the number of times character a and A appear in string.
int numA = string.replaceAll("[^aA]","").length();

trouble with CharAt

I am suppose to make a simple program that would take a users input, and put spaces between each single letter. So for example, user enters mall, and it returns M A L L(on same line).
I am trying to make a loop with a if statement in it.But I think I would need CharAt for it, so if the string is greater value then 1, I would declare a variable to everysingle character in the string(that the userinput). Then I would say put spaces between each letter. I am in AP computer science A, and we are practicing loops.Everything underthis, is what I have done so far. And the directions are in the comment above code.And im useing eclipse,java.
/**
* Splits the string str into individual characters: Small becomes S m a l l
*/
public static String split(String str) {
for (int i = 0; str.length() > i; i++) {
if (str.length() > 0) {
char space = str.charAt();
}
}
return str;
}
My solution uses concat to build the str2, and trim to remove last white space.
public static String split(String str) {
String str2 = "";
for(int i=0; i<str.length(); i++) {
str2 = str2.concat(str.charAt(i)+" ");
}
return str2.trim();
}
You don't modify method parameters, you make copies of them.
You don't null-check/empty-check inside the loop, you do it first thing in the method.
The standard in a for loop is i < size, not size > i... meh
/**
* Splits the string str into individual characters: Small becomes S m a l l
*/
public static String split(final String str)
{
String result = "";
// If parameter is null or empty, return an empty string
if (str == null || str.isEmpty())
return result;
// Go through the parameter's characters, and modify the result
for (int i = 0; i < str.length(); i++)
{
// The new result will be the previous result,
// plus the current character at position i,
// plus a white space.
result = result + str.charAt(i) + " ";
}
return result;
}
4. Go pro, use StringBuilder for the result, and static final constants for empty string and space character.
Peace!
Ask yourself a question, where is s coming from?
char space = s.charAt(); ??? s ???
A second question, character at?
public static String split(String str){
for(int i = 0; i < str.length(); i++) {
if (str.length() > 0) {
char space = str.charAt(i)
}
}
return str;
}
#Babanfaraj, this a answer from a newbie like you!!
The code is very easy. The corrected program is-
class fopl
{
public static void main(String str)
{
int n=str.length();
for (int i = 0;i<n; i++)
{
if (n>=0)
{
String space = str.charAt(i)+" ";
System.out.print(space);
}
}
}
}
Happy to help you!

Shifting characters within a string

String newStr;
public RandomCuriosity(String input){
newStr = input;
}
public void shiftChars(){
char[] oldChar = newStr.toCharArray();
char[] newChar = new char[oldChar.length];
newChar[0] = oldChar[oldChar.length-1];
for(int i = 1; i < oldChar.length; i++){
newChar[i] = oldChar[i-1];
}
newStr = String.valueOf(newChar);
}
I created a method that shifts characters forward by one. For example, the input could be:
The input: Stackoverflow
The output: wStackoverflo
How I did it is I mutated an instance of a string. Convert that string to a char array (calling it oldChar), assigned the last index of of oldChar as the first index of newChar, and made a for-loop that took the first index of oldChar as the second index of my new Char array and so forth. Lastly, I converted the char array back to a string.
I feel like I did way too much to do something very simple. Is there a more efficient way to do something like this?
EDIT Thanks for the great answers!
newStr = newStr.charAt(newStr.length() - 1) + newStr.substring(0, newStr.length() - 1);
You can made your life simpler :
public static void main (String[] args) throws java.lang.Exception {
String input = "Stackoverflow";
for(int i = 0; i < s.length(); i++){
input = shift(input);
System.out.println(input);
}
}
public static String shift(String s) {
return s.charAt(s.length()-1)+s.substring(0, s.length()-1);
}
Output :
wStackoverflo
owStackoverfl
lowStackoverf
flowStackover
rflowStackove
erflowStackov
verflowStacko
overflowStack
koverflowStac
ckoverflowSta
ackoverflowSt
tackoverflowS
Stackoverflow
You could use System.arrayCopy:
char[] oldChar = newStr.toCharArray();
char[] newChar = new char[oldChar.length];
newChar[0] = oldChar[oldChar.length - 1];
System.arrayCopy(oldChar, 0, newChar, 1, oldChar.length - 1);
You can use StringBuilders.
StringBuilder strb = new StringBuilder();
strb.append(oldChar[oldChar.length-1]).append(oldchar.substring(0, oldChar.length-1));
newStr = strb.toString();
try this..
String old = "String";
char first = old.charAt(old.length()-1);
String newString = first+old.substring(0,old.length()-1);
System.out.println(newString);
Another solution, but without using loops, for left and right shift:
public static String cyclicLeftShift(String s, int n){ //'n' is the number of characters to shift left
n = n%s.length();
return s.substring(n) + s.substring(0, n);
}
public static String cyclicRightShift(String s, int n){ //'n' is the number of characters to shift right
n = n%s.length();
return s.substring(s.length() - n , s.length()) + s.substring(0, s.length() - n);
}
By Java, u can shift it to forward by O(n) where n is how many times to go forward by character which space o(1)
public static String shiftChars(String s , int times) {
String temp = s;
for (int i = 0; i < times ; i++) {
temp = temp.charAt(temp.length()-1)+temp.substring(0, temp.length()-1);
}
return temp;
}

Unable to convert to Int from String

I am working on a solution to the TSP problem. I have generated all the permutations of the String "123456", however, I need to convert this into an ArrayList of Integer like this [1,2,3,4,5,6]...[6,5,4,3,2,1]. I then store this into an ArrayList of ArrayLists. Once there I will be able to compare all of the cities that need to be traveled to.
When I run my code, I have a method to generate the permutation, then a method to change that permutation into an ArrayList of Integer. When I convert them, I get the exception java.lang.NumberFormatException: For input string: "". I don't know of any other way to get the String to Integer
Here is my code.
public static String permute(String begin, String string){
if(string.length() == 0){
stringToIntArray(begin+string);
return begin + string + " ";
}
else{
String result = "";
for(int i = 0; i < string.length(); ++i){
String newString = string.substring(0, i) + string.substring(i+1, string.length());;
result += permute(begin + string.charAt(i), newString);
}
stringToIntArray(result);
return result;
}
}
public static void stringToIntArray(String s){
ArrayList<Integer> perm = new ArrayList<Integer>();
String [] change = s.split("");
for(int i = 0; i < 7; ++i){
int integer = Integer.parseInt(change[i]);
System.out.println(integer);
}
}
public static void main(String[] args) {
permute("", "123456");
}
These lines
String [] change = s.split("");
for(int i = 0; i < 7; ++i){
int integer = Integer.parseInt(change[i]);
System.out.println(integer);
}
Given a String like "12345", when you split it on nothing, it will separate every character. Giving you an array with ["","1","2","3","4","5"]. Since the empty String "" is not a Number, you will get the NumberFormatException. You could change your index i to start at 1 so as to ignore that first empty String.
The split method, when splitting on "", produces an empty string as the first element of the array, so you need to start iterating from i = 1.
Also, it would be safer to stop the iteration at change.length to make sure you process all characters when there are more than 6, and don't go out of bounds if there are fewer.
String [] change = s.split("");
for(int i = 1; i < change.length; ++i){ // ignore first element
int integer = Integer.parseInt(change[i]);
System.out.println(integer);
}

Categories

Resources