Is it possible to get substring from right hand hand(Reverse) direction using substring() in JAVA.
Example.
Suppose String S="abcdef",
Can I get Substring "fedc" using S.substring(S.length()-1,3) ?
If it is not correct, please suggest me how to get Substring from right hand end(Reverse direction)??
You could reverse the string and use substring. Unfortunately String does not have that, but StringBuilder has it e.g.
new StringBuilder("abcdef").reverse().toString().substring(0,4);
You can reverse the string and find the substring
// reverse
String s = "abcdef";
StringBuilder builder = new StringBuilder(s);
String substring = builder.reverse().substring(0,3);
Java doesn't support extension methods like C# does, so I would build a function for this. This way you can control how much of the reverse substring you want with a parameter.
public class StackOverflow {
public static void main(String[] args) {
String data = "abcdef";
for (int i = 0; i < data.length(); i++) {
System.out.println(reverseSubstring(data, i+1));
}
}
public static String reverseSubstring(String data, int length) {
return new StringBuilder(data).reverse().substring(0, length);
}
}
Result:
f
fe
fed
fedc
fedcb
fedcba
UPDATE
Another approach is to create a wrapper class to String. This way you can call a class method like how you're asking in your question with the example S.substring(S.length()-1,3). This will also allow you to still have all the String methods after using the wrapper's get() method.
String Wrapper
public class MyString {
private String theString;
public MyString(String s) {
theString = s;
}
public String get() {
return theString;
}
public String reverseSubstring(int length) {
return new StringBuilder(theString).reverse().substring(0, length);
}
}
Usage
public class StackOverflow {
public static void main(String[] args) {
MyString data = new MyString("abcdef");
for (int i = 0; i < data.get().length(); i++) {
System.out.println(data.reverseSubstring(i+1));
}
}
}
Results:
f
fe
fed
fedc
fedcb
fedcba
Related
I am trying to solve a question where I need to remove specific substring from string using recursion.
I was able to solve this using a do while loop but that is not the best approach.
For example,
Suppose I have a string named, DADDAUUPPA and if I am given set of substrings like "DD", "UU","PP", "AA" then the returned string should be DA because, DADDAUUPPA -> DAAUUPPA -> DUUPPA -> DPPA -> DA
Here is my solution doing it using while loop.
String s = "DADDAUUPPA";
do{
String original = s;
return original.replace("DD","").replace("UU","").replace("PP","").replace("AA","" );
} while(!original)
Other challenging task is what if we are given these substrings as an array, how would we do it then?
For example,
public soln (String[] sub) {
// sub contains all the substring to be removed
}
Here is a solution
import java.util.LinkedList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> subs = new LinkedList<>();
subs.add("DD");
subs.add("AA");
subs.add("UU");
subs.add("PP");
String result = getSubString(subs, "DADDAUUPPA ");
System.out.print(result);
}
private static String getSubString(List<String> subs, String myString) {
if(subs !=null && subs.size() != 0) {
String sub = subs.get(0);
subs.remove(0);
myString = getSubString(subs, myString.replace(sub, ""));
}
return myString;
}
}
Key thing to learn is
private static String getSubString(List<String> subs, String myString) {
if(subs !=null && subs.size() != 0) {
myString = myString.replace(subs.get(0), "");
subs.remove(0);
getSubString(subs, myString);
}
return myString;
}
This does not work, note the difference between first and second getSubString method. As the stack unwinds myString gets assigned to original value.
This question already has answers here:
Reverse a string in Java
(36 answers)
Closed 5 years ago.
Like to know how to reverse a string value (1 word) which is pre-declared in the program. I mean not using user input or scanner.
Like to reverse a word "TRAIN" which is pre-declared in the program.
Have tried the below program but no results and no error also.
// QUERY PROGRAM NOT RUNNING - NO RESULT, NO ERROR.
// STRING REVERSE PROGRAM USING ARRAY
package abnpackage;
class Play {
void REVERSE (){
String [] INPUT_WORD = {"T","R","A","I","N"};
int Q;
for(Q=INPUT_WORD.length-1; Q>=0; Q=Q--);
System.out.print ("REVERSE VALUE" + INPUT_WORD[Q]);
}
public static void main(String[]args){
Play PL = new Play();
PL.REVERSE();
}
}
Problem in Q=Q-- and ; symbol after for cylce. Try this:
class Play{
void REVERSE (){
String [] INPUT_WORD = {"T","R","A","I","N"};
int Q;
for(Q=INPUT_WORD.length-1; Q>=0; Q--) {
System.out.print(INPUT_WORD[Q]);
}
}
public static void main(String[]args){
Play PL = new Play();
PL.REVERSE();
}
}
I'd like to offer a few suggestions.
Indent your code. It not only makes it easier for you to follow, but makes it easier for others to read your code.
Naming conventions. Use Title case for classes, camelCase for both variables and methods, and UPPER_CASE for constants.
Strings and characters. A String can be decomposed into an array of characters with the built-in method, String.toCharArray(). A character array is mutable, so is often used as an intermediate structure when converting a String from one state to another for tasks like ciphers or interview problems.
Encapsulation. If you can make your methods use only what is submitted to them through their method signature, and only output their return value, it's usually best. Prefer passing values over referencing constants in your utility methods to make them easier to follow.
package abnpackage;
class Play {
private static final String INPUT_WORD = "TRAIN";
private String reverse(String word) {
char[] letters=word.toCharArray();
StringBuilder sb=new StringBuilder();
for (int q=letters.length-1; q>=0; q--) {
sb.append(letters[q]);
}
return sb.toString();
}
public static void main(String[]args) {
Play play = new Play();
System.out.println("REVERSE VALUE: " + play.reverse(INPUT_WORD));
}
}
class Play {
void REVERSE() {
String[] INPUT_WORD = {"T", "R", "A", "I", "N"};
String[] OUTPUT_WORD =new String[INPUT_WORD.length];
int length = INPUT_WORD.length;
int i = 0;
while(--length>=0){
OUTPUT_WORD[i++] = INPUT_WORD[length];
}
System.out.println(Arrays.toString(OUTPUT_WORD));
}
public static void main(String[] args) {
Play PL = new Play();
PL.REVERSE();
}
}
Your code is entering an endless loop because of the assignment "Q=Q--"
for(Q=INPUT_WORD.length-1; Q>=0; Q=Q--);
It should instead be
Q--
without a semicolon at the end.
If the code runs successfully, it will print the words "REVERSE VALUE" repeatedly prior to printing each character in reverse.
System.out.print ("REVERSE VALUE" + INPUT_WORD[Q]);
So you will want to keep the text in reverse prior to printing the whole statement at the end of the execution of the for loop.
What is the reason to use array of String instead of just String? Since it's not mentioned as a requirement, I'm suggesting the following as an alternative solution:
public class Play {
static void reverse(){
String inputWord = "TRAIN";
char[] toStrArray = inputWord.toCharArray();
char[] revisedInput = new char[inputWord.length()];
int i = 0;
for(int q=toStrArray.length-1; q>=0; q--){
revisedInput[i]=toStrArray[q];
i++;
}
System.out.print ("REVERSE VALUE: " + new String(revisedInput));
}
public static void main(String[]args){
//Play PL = new Play();
//PL.REVERSE();
reverse();
}
}
Note: You can declare the method reverse as a static method. By doing this you don't have to create an object before calling it. Hope this helps.
I have a program that takes letters for input and then sums the numeric value of each letter.
I have it so that if I input "abc", my output is "6".
I ignore uppercase letters, so if I input "abC", my output is "3".
What I want to do now, is in a separate class, make a method, which if set to true will run my main program as is, but when it is set to false, it will treat uppercase letters as lowercase, giving an input of "abC", an output of "6".
I hope this makes sense, I've tried a few different things but they all run the programm as is, ignoring uppercase.
Here is my code, I appreciate any constructive feedback.
Thanks
EDIT: I would also appreciate if you didn't downvote me for asking a question, if you don't want to help dont', seems every question I asked gets downvoted for no obvious or fair reason. I didn't want to ask for help since I knew this would happen. We all start have to somewhere!
Main method:
Scanner scan = new Scanner(System.in);
System.out.println("\nPlease enter the letters you would like to use:");
String s, t = "";
scan.next();
s = scan.next();
boolean b = Converter.caseSensitive(false, s);
scan.close();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (!t.isEmpty()) {
t += ",";
}
if (ch >= 'a' && ch <= 'z') {
int n = ch - 'a' + 1;
t += String.valueOf(n);
}
}
Second method in separate class:
public class Converter {
public static boolean caseSensitive(Boolean b, String s) {
for (char c : s.toCharArray()) {
if (Character.isLetter(c) && Character.isLowerCase(c)) {
b = s.equalsIgnoreCase(s);
return false;
}
}
s = s.toLowerCase();
return true;
}
}
I believe your question is "how do I record a static boolean value in a class and then request it from another class?"
public class Configuration {
private static boolean convertToUppercase = true;
public static void setConvertToUppercase(boolean convert) {
convertToUppercase = convert;
}
public static boolean getConvertToUppercase() {
return convertToUppercase;
}
}
This can be used as:
StringConverter.caseSensitive(Configuration.getConvertToUppercase(), input);
Note that most coders (me included) would consider this poor design but explaining why is outside the scope of your question.
There are a lot of other issues with your code. For example your method call above will leave the input string unchanged. But I suggest you ask another question with just the relevant code when you get stuck.
String is immutable in Java. Please read following stackoverflow question for more information about this topic:
String is immutable. What exactly is the meaning?
public static void main(String[] args) throws Exception
{
String test = "abc";
toUpperCase(test);
System.out.println(test);
}
private static void toUpperCase(String test)
{
test = test.toUpperCase();
}
Please note that above code will output:
abc
In order to have "ABC" as result you need to use following code:
public static void main(String[] args) throws Exception
{
String test = "abc";
test = toUpperCase(test);
System.out.println(test);
}
private static String toUpperCase(String test)
{
return test.toUpperCase();
}
This one outputs:
ABC
So your Converter.caseSensitive method should return String.
I don't think you really need the Converter class. You can delete class and replace the line:
boolean b = Converter.caseSensitive(false, s);
with this
boolean shouldCountUppercaseLetters = false;
if (shouldCountUppercaseLetters) {
s = s.toLowerCase();
}
My java program formats data from a string array into a string and can basically pull an inception and store these strings along other strings of the same format, in a way making a 2D array but in a string format. My issue is for a 1D array I roughly have the following methods in a class...
public static String parse(String data) {
return "#"+Integer.toString(data.length())+":"+data;
}
public static String parse(String[] data) {
String str="";
for (int i=1;i<=data.length;i++) {
str+=parse(data[i-1]);//parse() would receive a String
}
return str;
}
My problem is I want to make a singular method that can take in an array of ANY dimensions, but the closest I can get to doing this is declaring multiple methods with the same name but with higher array dimensions set for the input variable 'data' like so...
public static String parse(String[][] data) {//can take in a 2D array
String str="";
for (int i=1;i<=data.length;i++) {
str+=parse(data[i-1]);//parse() would receive a 1D array
}
return str;
}
public static String parse(String[][][] data) {//can take in a 3D array
String str="";
for (int i=1;i<=data.length;i++) {
str+=parse(data[i-1]);//parse() would receive a 2D array
}
return str;
}
//etc...
Is there a way to work arround this? Or is this the best way to program it?
PS:I'm new to this language and still dont know a lot of terminology, so keep it simple please.
The problem is the difference in types, 1 parse method takes a String[][][] and calls another parse method that takes a String[][]. That second call is different for each level, so you can't create 1 single method that works for all of them.
Something that you can do (but will be tricky to grasp for a beginner) is reduce some of the duplication. If you pass the next parse method to call as an argument to parse. You can then use lambdas to chain method calls together:
public static String parse0(String data) {
return "#" + Integer.toString(data.length()) + ":" + data;
}
// Method that contains the real logic
private static <T> String parseInternal(T[] data, Function<T, String> parser) {
String str = "";
for (int i = 0; i < data.length; i++) {
str += parser.apply(data[i]);
}
return str;
}
// Methods that provide the call chain:
public static String parse3(String[][][] data) {
return parseInternal(data, arr2 -> parse2(arr2));
}
public static String parse2(String[][] data) {
return parseInternal(data, arr -> parse1(arr));
}
public static String parse1(String[] data) {
return parseInternal(data, str -> parse0(str));
}
Note: I gave all the methods a different name to show better what is going on. But you could give all of them the same name as well.
For more information about lambda expressions see the Oracle tutorial.
The solution is called recursion: that a method sometimes calls itself for doing some of its task:
public static String parse(Object data) {
if (data instanceof String) {
return "#" + Integer.toString(((String) data).length()) + ":" + data;
}
if (data instanceof Object[]) {
String str = "";
for (Object obj : (Object[]) data) {
str += parse(obj);
}
return str;
}
throw new IllegalArgumentException("Cannot parse type " + data.getClass());
}
Now we may do for instance:
System.out.println(parse("str"));
System.out.println(parse(new String[] { "abc", "def" }));
System.out.println(parse(new String[][] { { "gh", "ij" }, { "kl" } }));
System.out.println(parse(new String[][][] { { { "mn" }, { "op", "qr", "st" }, { "uv" } } }));
This prints:
#3:str
#3:abc#3:def
#2:gh#2:ij#2:kl
#2:mn#2:op#2:qr#2:st#2:uv
In fact you can call it with a String array with any number of dimension.
public class Anagram {
public static void main(String[] args) {
String a = "Despera tion-".toLowerCase();
String b = "A Rope Ends It".toLowerCase();
String aSorted = sortStringAlphabetically(a);
String bSorted = sortStringAlphabetically(b);
if(aSorted.equals(bSorted)){
System.out.println("Anagram Found!");
}else{
System.out.println("No anagram was found");
}
}
public static String sortStringAlphabetically(String s) {
char[] ca = s.toCharArray();
int cnt = 0;
ArrayList al = new ArrayList();
for (int i = 0; i < ca.length; i++) {
if (Character.isLetter(ca[cnt]))
al.add(ca[cnt]);
cnt++;
}
Collections.sort(al);
return al.toString();
}
}
As a learner, I hacked up this boolean Anagram checker. My chosen solution was to create a sortStringAlphabetically method seems to do just too much type-juggling String -> chars[] -> ArrayList ->String - given that I do just want to compare 2 strings to test whether one phrase is an anagram of another - could I have done it with less type-juggling?
ps The tutors solution was a mile away from my attempt, and probably much better for a lot of reasons - but I am really trying to get a handle on all the different Collection types.
http://www.home.hs-karlsruhe.de/~pach0003/informatik_1/aufgaben/en/doc/src-html/de/hska/java/exercises/arrays/Anagram.html#line.18
EDIT
FTW here is the original challenge, I realise I wandered away from the solution.
http://www.home.hs-karlsruhe.de/~pach0003/informatik_1/aufgaben/en/arrays.html
My initial kneejerk reaction was to simply work though array a, knocking out those chars which matched with array b - but that seemingly required me to rebuild the array at every iteration - Many thanks for all your efforts to educate me.
There are different ways to improve this, if you go with this algorithm.
First, you don't necessarily need to create a character array. You can use String.charAt() to access a specific character of your string.
Second, you don't need a list. If you used a SortedMultiSet or a SortedBag, you could just add things in sorted order. If you write a function that creates the SortedMultiSet from your string, you could just compare the sets without rebuilding the string.
Note: I don't know what libraries you're allowed to use (Google and Apache have these types), but you can always 'brew your own'.
Also, make sure to use generics for your types. Just defining ArrayLists is pretty risky, IMHO.
You could just sort the string without using a list:
public static String sortStringAlphabetically(String s) {
String lettersOnly = s.replaceAll("\\W", "");
char[] chars = lettersOnly.toCharArray();
Arrays.sort(chars);
return new String(chars);
}
N.B. I haven't actually tried running the code.
Your algorithm, but shorter (and yet, slower). The "type-juggling" is done "implicitly" in Java's various library classes:
public static boolean isAnagram(String a, String b) {
List<String> listA = new ArrayList<String>(Arrays.asList(
a.toLowerCase().replaceAll("\\W", "").split("")));
List<String> listB = new ArrayList<String>(Arrays.asList(
b.toLowerCase().replaceAll("\\W", "").split("")));
Collections.sort(listA);
Collections.sort(listB);
return listA.equals(listB);
}
Optionally, replace the \W regular expression to exclude those letters that you don't want to consider for the anagram
public class Anagram {
public static void main(String[] args) throws Exception {
String s1 = "Despera tion-";
String s2 = "A Rope Ends It";
anagramCheck(s1, s2);
}
private static void anagramCheck(String s1, String s2) {
if (isAnagram(s1, s2)) {
System.out.println("Anagram Found!");
} else {
System.out.println("No anagram was found");
}
}
private static boolean isAnagram(String s1, String s2) {
return sort(s1).equals(sort(s2));
}
private static String sort(String s) {
char[] array = s.replaceAll("\\W", "").toLowerCase().toCharArray();
Arrays.sort(array);
return new String(array);
}
}