Stack Class seperating elements - java

Hello everyone im trying to make a code to remove
vowels and consonants when a user types a string
but i seem to fail at the code and i need to use a stack class to do it
Sample Output should be like this and will ignore non alphabet characters
Enter a String : hello1234!##$
Vowels : eo
Consonant : hll
Final contents : 1234!##$
can someone fix my code
this is the error I get
enter image description here
import java.util.Scanner;
import java.util.Stack;
public class PushPop
{
//I used the push and pop methods
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
System.out.print("Enter a String: ");
String str = sc.nextLine();
Stack<String> String = new Stack();
String.push(str);
String vowels = String.pop();
vowels = vowels.replace("[aeiou]", "");
String consonants = String.pop();
consonants = consonants.replace("[qbcdfghjklmnpqrstvwxyz]", "");
System.out.println("Vowels: "+ vowels);
System.out.print("Consonant: "+ consonants);
//this will print what is left after popping the elements
System.out.print("Final contents: "+ str);
}
}

If you just want to remove all vowels and consonants form the user's input, a Stack is not needed (at least if you use the ready made Java's Pattern in some way). In fact, you get the Exception because you try to pop from the Stack twice, while having only pushed once. In particular you first push the user's input str, then pop it to the variable vowels (so the Stack is now empty) and then you pop from it again, this time into the variable consonants.
vowels = vowels.replace("[aeiou]", "");
According to documentation of replace it will replace all literals with the second argument. This means that it will replace all Strings matching the literal "[aeiou]" (if it exists as is in the user's input) with the empty String. Instead you should use replaceAll method which takes a regex (ie Regular Expression) as the first argument:
str = str.replaceAll("[aeiou]", "");
The regular expressions you are using seem correct for your problem, although you want to first remove the vowels from the user's input and then from that String (which is the result of the user's input by removing all vowels) remove also the consonants. So the logic should instead be:
String str = sc.nextLine(); //Get user input.
str = str.replaceAll("[aeiou]", ""); //Remove vowels.
str = str.replaceAll("[qbcdfghjklmnpqrstvwxyz]", ""); //Remove consonants.
System.out.println(str); //Print result.
which, if you combine the two regexes toghether in a single operation, can be shortened to:
String str = sc.nextLine();
str = str.replaceAll("[aeiouqbcdfghjklmnpqrstvwxyz]", "");
System.out.println(str);
which, if you realize that these are all alphabet letters, can be shortened even further with:
str = str.replaceAll("[a-z]", "");
and if you also want both upper and lower case letters, then you can do:
str = str.replaceAll("[a-zA-Z]", "");
which is equivalent to:
str = str.replaceAll("\\p{Alpha}", "");
All those examples can be made clear for someone if they read the documentation on how a Java Pattern is constructed, so it may help to take a look there, if you didn't already know it.
i need to use a stack class to do it
Can you please explain what is the desired behaviour, and how a Stack needs to be used? Because it seems like you just want to remove all alphabet letters. Are you required to not use regexes for this?

Related

I want to split a string with multiple whitespaces using split() method?

This program is to return the readable string for the given morse code.
class MorseCode{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String morseCode = scanner.nextLine();
System.out.println(getMorse(morseCode));
}
private static String getMorse(String morseCode){
StringBuilder res = new StringBuilder();
String characters = new String(morseCode);
String[] charactersArray = characters.split(" "); /*this method isn't
working for
splitting what
should I do*/
for(String charac : charactersArray)
res.append(get(charac)); /*this will return a string for the
corresponding string and it will
appended*/
return res.toString();
}
Can you people suggest a way to split up the string with multiple whitespaces. And can you give me some example for some other split operations.
Could you please share here the example of source string and the result?
Sharing this will help to understand the root cause.
By the way this code just works fine
String source = "a b c d";
String[] result = source.split(" ");
for (String s : result) {
System.out.println(s);
}
The code above prints out:
a
b
c
d
First, that method will only work if you have a specific number of spaces that you want to split by. You must also make sure that the argument on the split method is equal to the number of spaces you want to split by.
If, however, you want to split by any number of spaces, a smart way to do that would be trimming the string first (that removes all trailing whitespace), and then splitting by a single space:
charactersArray = characters.trim().split(" ");
Also, I don't understand the point of creating the characters string. Strings are immutable so there's nothing wrong with doing String characters = morseCode. Even then, I don't see the point of the new string. Why not just name your parameter characters and be done with it?

Why all the test cases are not getting passed for the below question?

The Coding Question which I am trying to solve is this. I tried to solve but not all the test cases passed I am not able to find what could be the reason?
Identify possible words: Detective Bakshi while solving a case stumbled upon a letter which had many words whose one character was missing i.e. one character in the word was replaced by an underscore. For e.g.“Fi_er”. He also found thin strips of paper which had a group of words separated by colons, for e.g. “Fever:filer:Filter:Fixer:fiber:fibre:tailor:offer”. He could figure out that the word whose one character was missing was one of the possible words from the thin strips of paper. Detective Bakshi has approached you (a computer programmer) asking for help in identifying the possible words for each incomplete word.
You are expected to write a function to identify the set of possible words.
The function identifyPossibleWords takes two strings as input
where,
input1 contains the incomplete word, and
input2 is the string containing a set of words separated by colons.
The function is expected to find all the possible words from input2 that can replace the incomplete word input1, and return the result in the format suggested below.
Example1 -
input1 = “Fi_er”
input2 = “Fever:filer:Filter:Fixer:fiber:fibre:tailor:offer”
output string should be returned as “FILER:FIXER:FIBER”
Note that –
The output string should contain the set of all possible words that can replace the incomplete word in input1
all words in the output string should be stored in UPPER-CASE
all words in the output string should appear in the order in which they appeared in input2, i.e. in the above example we have FILER followed by FIXER followed by FIBER.
While searching for input1 in input2, the case of the letters are ignored, i.e “Fi_er” matches with “filer” as well as “Fixer” as well as “fiber”.
IMPORTANT: If none of the words in input2 are possible candidates to replace input1, the output string should contain the string “ERROR-009”
Assumption(s):
Input1 will contain only a single word with only 1 character replaced by an underscore “_”
Input2 will contain a series of words separated by colons and NO space character in between
Input2 will NOT contain any other special character other than underscore and alphabetic characters.
My solution for the question is:
import java.io.*;
import java.util.*;
class UserMaincode
{
public String indentifyPossibleWords(String input1, String input2)
{
input1=input1.toUpperCase();
input2=input2.toUpperCase();
String arr1[]=input1.split("_");
String arr2[]=input2.split(":");
StringBuilder sb=new StringBuilder("");
for(int i=0;i<arr2.length;i++){
if(arr2[i].matches(arr1[0]+"."+arr1[1])){
sb.append(arr2[i]+":");
}
}
if(sb.length()!=0){
sb.deleteCharAt(sb.length()-1);
}
String s=sb.toString();
if(s==""){
return "ERROR-009";
}
return s;
}
}
But some of hidden testcases did not pass. Where could be the problem.
I found one code from web which passes all the test case. Please refer this link for that.
https://www.csinfo360.com/2020/01/cracking-coding-interview-step-11.html
There are many ways to achieve the result as expected in the mentioned problem. Since; you've mentioned regex in the tag; therefore I'll try to provide a possible solution using regex. Although; this can be achieved without them too.
Proposed Procedure:
1. Create a regex from the given input1 i.e. replace the _ present anywhere inside input1 with regex dot (.) meta-character.
2. Split the string based on :.
3. Keep a count of length of spliced array of input2.
4. for each item in input2:
5. match using the regex formed in step 1
If successful
append to upper-cased result.
else:
increment the counter.
6. if counter == length of spliced array i.e. no match found
return "ERROR-009"
else
return the appended result.
Implementation of the above procedure in java:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Main
{
public static void main(String[] args) {
System.out.println(identifyPossibleWords("Fi_er", "Fever:filer:Filter:Fixer:fiber:fibre:tailor:offer"));
// Fever:fiqqer:Filter:Fixxer:fibber:fibre:tailor:offer return ERROR-009
}
public static String identifyPossibleWords(String input1, String input2){
input1 = input1.replace("_", ".");
StringBuilder sb = new StringBuilder();
int counter = 0;
int lengthOfInput2 = input2.split(":").length;
final Pattern pattern = Pattern.compile(input1, Pattern.CASE_INSENSITIVE);
for(String str: input2.split(":")){
Matcher matcher = pattern.matcher(str);
if(matcher.matches())sb.append(matcher.group(0).toUpperCase() + "\n"); // \n to print in new line. You can edit the code accordingly.
else counter++;
}
if(counter == lengthOfInput2)return "ERROR-009";
return sb.toString();
}
}
You can find the sample run of the above implementation in here.
easy fix--->
input1=input1.toUpperCase();
input2=input2.toUpperCase();
String arr1[]=input1.split("_");
String arr2[]=input2.split(":");
StringBuilder sb=new StringBuilder("");
for(int i=0;i<arr2.length;i++){
if(arr2[i].matches(arr1[0]+"."+arr1[1])){
sb.append(arr2[i]+":");
}
}
if(sb.length()!=0){
sb.deleteCharAt(sb.length()-1);
}
String x = "ERROR-009";
String s=sb.toString();
if(sb.length()==0){ // this
return x.toString();
}
return s;
}
}

Use Scanner class to replace all occurrence of string with another

i want to scan a string with a Scanner class and i want to replace each "is" word by "is not" expect embedded "is " like "this" for example
good morning this is my name became good morning this is not my name
i write the snippet of code
public static void main(String[] args) {
String chaine="good morning this is my name";
Scanner sc=new Scanner(chaine);
while(sc.hasNext()) {
String word=sc.next();
if(word.equals("is"))
chaine=chaine.replace(word, "is not");
}
System.out.println(chaine);
}
when i execute this program it print:
good morning this not is not my name but i want to print good morning this is not my name
Sorry for before I did not see what you exactly want. I modify a little your code. I use StringBuilder to store the parts of the words and I close the Scanner.
public static void main(String[] args) {
String chaine="good morning this is my name";
Scanner sc=new Scanner(chaine);
StringBuilder sb = new StringBuilder();
while(sc.hasNext()) {
String word=sc.next();
if(word.equals("is"))
{
sb.append("is not");
}
else
{
sb.append(word);
}
//Add space after every added word.
sb.append(" ");
}
sc.close();
String result = sb.toString();
//Call trim to remove the space after the last word
System.out.println(result.trim());
}
Good Luck to all!
I have attached a solution to your problem. It's a similar approach with the correction from the solution already been submitted. Consider the use case where the user will type "Good morning this is not my name". In this situation also the code will replace "is" with "is not". And the output will be "Good morning this is not not my name". You can consider this solution where we can check whether it's already "is not" or not.
(I am assuming here that you just want to correct "is" to "is not" and if you user types "is not" then you will not change anything. If this what you want then here is the correct code.)
StringBuilder sb=new StringBuilder();
Scanner sc=new Scanner(System.in);
while(sc.hasNext()) {
String word=sc.nextLine();
if(!word.contains("is not"))
sb.append(word.replace("is","is not"));
else sb.append(word);
sb.append("\n"); //new line to get same string as
// user's input
}
sc.close();
System.out.println(sb.toString());
If you want to use the earlier solution then you have to put a condition to check whether the user has already given a correct input or not.
You can use replace method for replace substrings.
But anyway if you don't need to replace parts of other words, you just should write " is " in brackets with spaces.
this worked
if(word.equals("is")) {
chaine=chaine.replaceFirst(" "+word+" ", " is not ");
}
replace function replaces all the occurences of the word you give, and you are giving it "is" which is included in "this", just put some spaces to prevent this. Using replace first will replace the first occurence, instead of replace which replaces everything.
even if using Scanner it self seems not to be a right practice
Since you are using Java's Scanner class and utilizing the Scanner#next() method in conjunction with the Scanner#hasNext() method you can expect to retrieve each word within the string as a token for each iteration of your while loop.
This is a better mechanism for what you are trying to do (with Scanner) when specifically utilizing the String#replace() method because the Scanner#next() method retrieves each word on its own based on the default White-Space delimiter (since you have not specified a delimiter using the Scanner#useDelimiter() method - Note this: more later).
As you may already know the String#replace() method will replace all occurrences of a substring within a string whether it's inside a word or the word itself so you don't want to play that card in this particular case.
Your problem is that you are using the String#replace() method against the entire string rather than just the found word itself:
if(word.equals("is")) {
chaine = chaine.replace(word, "is not");
}
This will of course replace all occurrences of the substring is throughout the entire String (including in the word "this" which is obviously not desired. It should be:
if(word.equals("is")) {
word = word.replace(word, "is not");
}
and then append the contents of the word variable to a particular string build. You will need to rebuild the string as you are finished processing each word retrieved by the Scanner#next() method upon each iteration of the while loop.
For this small use case, to rebuild the string you can use the String Concatenation Operator (+):
String finalString = ""; // Will hold the string build
while (sc.hasNext()) {
String word = sc.next();
if (word.equals("is")) {
word = word.replace(word, "is not");
}
// Rebuild the string upon each iteration
finalString+= (!finalString.equals("") ? " " + word : word);
}
In the code line above: finalString+= (finalString.equals("") ? word : " " + word); you can see the use of the String Concatenation Operator (+): finalString+= but there is also an equals character after it. This is basically telling the compiler that finalyString is to hold and maintain the string data that is already contained within it, in other words: finalyString = finallyString +.
In the above code line you can also see the use of a Ternary Operator so as to apply white-spaces where needed:
(finalString+= (!finalString.equals("") ? " " + word : word);
A ternary operator works in the very same fashion as an if/else scenario. Using if/else it would look like:
// If finalString is NOT empty
if (!finalString.equals("") {
// Append a white-space and then the word
finalString+= " " + word;
}
// otherwise if finalString is empty
else {
// Just append the word
finalString+= word;
}
You can quickly see why using a Ternary Operator is a good way to go.
Another way you can rebuild the string is by utilizing the StringBuilder class. It is good to use this class for building lots of strings through lots of iterations. It's good to get into the habit of using this class even for small situations like this:
String chaine = "good morning this is my name";
Scanner sc = new Scanner(chaine);
StringBuilder sb = new StringBuilder();
while (sc.hasNext()) {
String word = sc.next();
if (word.equals("is")) {
word = word.replace(word, "is not");
}
/* If the 'string build' is not empty then add
a white-space in preperation for next word. */
if (!sb.toString().equals("")) {
sb.append(" ");
}
// Append next word (modified or not)
sb.append(word);
}
chaine = sb.toString();
This is all fine and good but there is one little problem with all of this. What if the main string supplied has padded or additional white-spaces in specific locations along that String we want to remain? The above build examples remove them.
The Scanner#hasNext() with the Scanner#next() ignores all white-spaces when each token (word) is retrieved. This can actually be a major problem in a lot of situations but not all is lost since there is a simple fix.
Remember that Scanner#useDelimiter() method we touched on earlier? Well, use it:
Scanner sc = new Scanner(chaine).useDelimiter(" ");
Now white-spaces will not be ignored and are retrieved as Null Strings ("") and processed within our code with:
// In the String Concatenation Operator code
finalString+= (!finalString.equals("") ? " " + word : word);
O R
// In the StringBuilder code
if (!sb.toString().equals("")) {
sb.append(" ");
}
But this does not take care of Leading white-spaces in the main string. To take care of Leading white-spaces we need to add a wee bit more code:
// In the String Concatenation Operator code
finalString+= (!finalString.equals("") || word.equals("") ? " " + word : word);
O R
// In the StringBuilder code
if (!sb.toString().equals("") || word.equals("")) {
sb.append(" ");
}
There, done....but you know, you can accomplish the same thing with a single line of code using the String#replaceAll() method:
String chaine = "good morning this is my name";
// A Single line of code (all whitespaces remain intact).
chaine = chaine.replaceAll("\\bis\\b", "is not");
The String#replaceAll() method allows for Regular Expressions (RegEx) to be utilized arguably making life soooo much easier in a lot of cases.
The regular expression ("\\bis\\b") passed to the replaceAll() method above contains the Word Boundary meta character \b which checks if a string or substring pattern begins and ends on a word boundary and the word within the expression is of course "is". You can read about Boundary Matchers here. If you want to play around with Regular Expressions and test them then you can do it at RegEx101.com.

Looped If statements confusion - using scanners to find palindroms, cannot use .reverse for assignment

When I input any sentence, my output returns that any string is a palindrome, and I think that my replaceAll calls aren't working in some cases. This is likely due to error my part, because using the Scanner class in Java is new for me (more used to input from C++ and Python3). I added comments to make it clearer what my intentions were when writing the program.
import java.util.Scanner;
public class PalindromeTest
{
public static void main (String[] args)
{
Scanner stringScan = new Scanner(System.in); //Scanner for strings, avoids reading ints as strings
Scanner intScan = new Scanner(System.in); //Scanner for ints, avoids reading strings as ints
String forwardPal = ""; //Variables for the rest of the program
String reversePal = "";
String trimForward = "";
char tempChar;
int revCount;
int revPalLength;
int quit;
while (true) //Loop to keep the program running, problem is in here
{
System.out.println("Please enter a word or a sentence."); //Prompts user to enter a word or sentence, I assume that the program is counting
forwardPal = stringScan.nextLine();
trimForward = forwardPal.replaceAll(" " , ""); //Trims the forwardPal string of characters that are not letters
trimForward = trimForward.replaceAll("," , "");
trimForward = trimForward.replaceAll("." , "");
trimForward = trimForward.replaceAll("!", "");
trimForward = trimForward.replaceAll(":", "");
trimForward = trimForward.replaceAll(";", "");
revPalLength = trimForward.length() ; //Makes the reverse palindrome length equal to the length of the new trimmed string entered
for (revCount = revPalLength - 1; revCount >= 0; revCount--) //Loop to count the reverse palindrome and add each character to the string reversePal iteratively
{
tempChar = trimForward.charAt(revCount);
reversePal += tempChar;
System.out.println(reversePal);
}
if (trimForward.equalsIgnoreCase(reversePal)) //Makes sure that the palindrome forward is the same as the palindrome backwards
{
System.out.println("Congrats, you have a palindrome"); //Output if the sentence is a palindrome
}
else
{
System.out.println("Sorry, that's not a palindrome"); //Output if the sentence isn't a palindrome
}
System.out.println("Press -1 to quit, any other number to enter another sentence."); //Loops to ask if the user wants to continue
quit = intScan.nextInt(); //Checks if the user input a number
if (quit == -1) //If the user inputs -1, quit the program and close the strings
{
stringScan.close();
intScan.close();
break;
}
}
}
}
Your problem is this line
trimForward = trimForward.replaceAll("." , "");
That function takes the first argument as a regex, and the dot means that it is replacing all characters as a "".
Instead, use
trimForward = trimForward.replace("." , "");
In fact, all your lines should be using #replace instead of #replaceAll as none of them take advantage of regex. Only use those if you plan to take advantage of it.
Or in fact, if you do want to use a regex, this is a nice one which does all of that in one neat line.
trimForward = forwardPal.replaceAll("[ .!;:]" , "");
I hope this was of some help.
The simplest fix is to use replace() instead of replaceAll().
replace() replaces all occurences of the given plain text.
replaceAll() replaces all occurences of the given regex.
Since some of your replacements have special meaning in regex (specifically the dot ., which means any character), you cant use replaceAll() as you are currently (you'd have to escape the dot).
It's common, and quite reasonable, to assume that replace() replaces one occurrence and replaceAll() replaces all occurrences. They are poorly named methods, because they interpret their parameters differently, yet both replace all matches.
As an aside, you may find this briefer solution of interest:
forwardPal = forwardPal.replaceAll("\\W", ""); // remove non-word chars
boolean isPalindrome = new StringBuilder(forwardPal).reverse().toString().equals(forwardPal);

.replace to replace input letters with symbols

I want to make everything the user enters capitalized and certain letters to be replaced with numbers or symbols. Im trying to utilize .replace but something is not going right. Im not sure what im doing wrong?
public class Qbert
{
public static void main(String[] args)
{
//variables
String str;
//get input
Scanner kb = new Scanner(System.in);
System.out.print(" Please Enter a Word:");
//accept input
str = kb.nextLine();
System.out.print("" );
System.out.println(str.toUpperCase()//make all letters entered uppercase
//sort specific letters to make them corresponding number, letter, or symbol
+ str.replace("A,#")+ str.replaceChar("E","3")+ str.replaceChar ("G","6")
+ str.replaceChar("I","!")+ str.replaceChar("S","$")+ str.replaceChar ("T","7"));
}
}
In Java, Strings are immutable. This means that modifying a string will result in a new string. E.g.
str.replace("a", "b");
this will replace all the occurrences of 'a' to 'b' in a new string. Original string will remain unaffected. So, to apply the formatting on the actual string, we will have to write:
str = str.replace("a", "b");
Similarly, if we want to do multiple replacements then, we need to append replace calls together, e.g.
str = str.replace("a","b").replace("c", "d");
Going by this, if you want to perform the substitution, the last system.out in your code will be:
System.out.println(str.toUpperCase().replace("A","#").replace("E","3")
.replace("G","6").replace("I","!").replace("S","$").replace("T","7"));
String doesn't have a replaceChar method. You probably wanted to use method replace.
And String.replace() takes 2 arguments:
public String replace(CharSequence target, CharSequence replacement)
Replaces each substring of this string that matches the literal target
sequence with the specified literal replacement sequence. The
replacement proceeds from the beginning of the string to the end, for
example, replacing "aa" with "b" in the string "aaa" will result in
"ba" rather than "ab".
You have written str.replace("A,#")+... instead of str.replace("A","#")+..., and so on
One more thing - use a good IDE like Eclipse or Intellij IDEA, they will highlight the parts of your code where you have errors.
public static void main(String... args) {
// variables
String str;
// get input
Scanner kb = new Scanner(System.in);
System.out.print(" Please Enter a Word:");
// accept input
str = kb.nextLine();
System.out.print("");
System.out.println(str.toUpperCase()); // Upper Case
System.out.println(str.toUpperCase().replace("A", "#").replace("E", "3")
.replace("E", "3").replace("G", "6").replace("I", "!").replace("S", "$").replace("T", "7") );
}
This should work like you want it to. Hope you find this helpful.
As you want to make multiple changes to the same string, you just use
str.toUpperCase().replace().replace().... This means you are giving
the output of str.toUpperCase() to the first replace function and so
on...
System.out.println(str.toUpperCase()
.replace("A","#")
.replace("E","3")
.replace("G","6")
.replace("I","!")
.replace("S","$")
.replace("T","7"));

Categories