String modifications assistance - java

I've spend the day working on these two classes. I've come further than I was expecting to yet needless to say I'm running into issues.
Basically I have to take an inputted String and return only the uppercase letters, every second letter, the entire string but with all vowels exchanged with an underscore, number of vowels in the string, and lastly positions of all vowels in the string.
I specifically designed my tester class, I believe correctly, to have a menu to try each command separately so I'm able to test each one.
This is the tester class..
//******************************************
// LetterTest.java
// Written by Sanchez
// 2013
//*******************************************
//===========================================
// This program tests the CharAPI class.
//===========================================
import java.util.Scanner;
public class LetterTest {
public static void main(String[] args){
//create Scanner for user input
Scanner in = new Scanner(System.in);
//get user input
System.out.println("Please enter a string of letters");
String input = in.nextLine();
System.out.println("\nChoose an option: "
+"\n1 - Uppercase, "
+"\n2 - Every Second Letter, "
+"\n3 - Replace vowels "
+"\n4 - Number of vowels "
+"\n5 - Positions of vowels");
int choice = in.nextInt();
//Call the method based on user choice
if (choice == 1) {
//each method returns a String
System.out.println(LetterAPI.bigLetters(input) );
}
else if (choice ==2) {
System.out.println(LetterAPI.secondLetter(input) );
}
else if (choice ==3) {
System.out.println(LetterAPI.vowelsGone(input) );
}
else if (choice ==4) {
System.out.println(LetterAPI.vowelNumber(input) );
}
else {
System.out.println(LetterAPI.vowelPositions(input) );
}
}
}
That seems to be working pretty well and I'm happy with it.
The issue I'm having is in my class with the objects that do the manipulation
I've used the // on a couple things just so I could get it to compile. The 1st, 2nd, and 4th, straight up don't return anything. The third one only exchanges the last letter for an underscore even if it's not a vowel, and the fifth one works pretty well except I'd like to add 1 to all the numbers so the results start at 1 and not 0. I understand that there's a lot going on here but I've spent the day on it and am finally submitting that I am in dire need of help.
This is the code for the objects...
//******************************************
// LetterAPI.java
// Written by Sanchez
// 2013
//*******************************************
//===========================================
// Objects of this class manipulate an inputted string.
//===========================================
import java.util.Scanner;
//contains a set of methods for maniuplaing the string
public class LetterAPI {
//print only uppercase letters
public static String bigLetters(String input) {
String result = "";
for (int i = 0; i <input.length(); i++) {
char currentLetter=input.charAt(i);
if (Character.isUpperCase(currentLetter))
result = result;
}
return result;
}
//print every second letter
public static String secondLetter(String input) {
String result = "";
for (int i = 0; i <input.length(); i++) {
//result = input.charAt(input);
}
return result;
}
//all vowels replaced by underscores
public static String vowelsGone(String input) {
String result ="aeiouAEIOU";
for (int i = 0; i<result.length();i++) {
result=input.replace(result.charAt(i), '_');
}
return result;
}
//the numbers of vowels
public static String vowelNumber(String input) {
String result = "";
for (int i = 0; i <input.length(); i++) {
if (Character.toLowerCase(input.charAt(i)) == 'a' || Character.toLowerCase(input.charAt(i)) == 'e' || Character.toLowerCase(input.charAt(i)) == 'i' || Character.toLowerCase(input.charAt(i)) == 'o' || Character.toLowerCase(input.charAt(i)) == 'u') {
i++;
}
}
return result;
}
//the positions of all vowels
public static String vowelPositions(String input) {
String result = "";
for (int i = 0; i <input.length(); i++) {
if (Character.toLowerCase(input.charAt(i)) == 'a' || Character.toLowerCase(input.charAt(i)) == 'e' || Character.toLowerCase(input.charAt(i)) == 'i' || Character.toLowerCase(input.charAt(i)) == 'o' || Character.toLowerCase(input.charAt(i)) == 'u') {
result = result + i + " ";
}
}
return result;
}
}
===UPDATE===
Thank you everyone! I've made some progress thank god. I've gotten the 3rd and 4th to work great. The first one was giving only the last uppercase but now is repeating my input. The second one is just giving me back the 1st letter. As for the last one I tried parenthesis but I seemed to have broke it so I put it back for now. That's not as critical..at least it works! If I can't figure that out I'll have to put a note that the count starts at 0. But the first two are killing me..at least it compiles. Here's where I'm at so far...
//******************************************
// LetterAPI.java
// Written by Sanchez
// 2013
//*******************************************
//===========================================
// Objects of this class manipulate an inputted string.
//===========================================
import java.util.Scanner;
//contains a set of methods for maniuplaing the string
public class LetterAPI {
//print only uppercase letters
public static String bigLetters(String input) {
String result = "";
char cl;
for (int i = 0; i <input.length(); i++) {
cl=input.charAt(i);
if (Character.isUpperCase(cl))
input = input + cl;
}
return input;
}
//print every second letter
public static String secondLetter(String input) {
String result = "";
for (int i=0; i<input.length(); i+=2) {
input = input + input.charAt(i) + " ";
}
return input;
}
//all vowels replaced by underscores
public static String vowelsGone(String input) {
String vowels ="aeiouAEIOU";
for (int i = 0; i<vowels.length();i++) {
input=input.replace(vowels.charAt(i), '_');
}
return input;
}
//the numbers of vowels
public static String vowelNumber(String input) {
String result = "";
int count = 0;
for (int i = 0; i <input.length(); i++) {
if (Character.toLowerCase(input.charAt(i)) == 'a' || Character.toLowerCase(input.charAt(i)) == 'e' || Character.toLowerCase( input.charAt(i)) == 'i' || Character.toLowerCase(input.charAt(i)) == 'o' || Character.toLowerCase(input.charAt(i)) == 'u') {
count++;
result = count + " ";
}
}
return result;
}
//the positions of all vowels
public static String vowelPositions(String input) {
String result = "";
for (int i = 0; i <input.length(); i++) {
if (Character.toLowerCase(input.charAt(i)) == 'a' || Character.toLowerCase(input.charAt(i)) == 'e' || Character.toLowerCase(input.charAt(i)) == 'i' || Character.toLowerCase(input.charAt(i)) == 'o' || Character.toLowerCase(input.charAt(i)) == 'u') {
result = result + i + " ";
}
}
return result;
}
}

Hints:
In part 1, you do this: result = result; That is nonsensical. It does nothing.
In part 2, the compilation error is because you are trying to assign a char to a String. That's not legal. But it is also not what you should be trying to do. (Think "append", not "assign" ...)
In part 3, the first mistake is this: String result = "aeiouAEIOU";. In fact, it should be String result = input;.
In part 4, you are counting all vowels, not each different vowel. You also need to turn the count (or counts) into a String (in result).
About part 5 you say: "works pretty well except I'd like to add 1 to all the numbers". So do it!

Related

How can I trim the last letter of a String while looping (until what's left is a single letter)?

I'm creating a program that will count the number of letters, vowels and consonants from what user put into using Scanner.
Here's my code:
'''
static String phrase;
static int vowel = 0;
static int consonant = 0;
static String reverse = "";
public static void countChar() {
System.out.println("\nNumber of characters: " + phrase.length());
}
public static void countVowelCons() {
phrase = phrase.toLowerCase();
for (int i = 0; i < phrase.length(); i++) {
if (phrase.charAt(i) == 'a' || phrase.charAt(i) == 'e' || phrase.charAt(i) == 'i' || phrase.charAt(i) == 'o'
|| phrase.charAt(i) == 'u') {
vowel++;
} else if (phrase.charAt(i) >= 'a' && phrase.charAt(i) <= 'z') {
consonant++;
}
}
System.out.println("Number of vowels: " + vowel);
System.out.println("Number of consonants: " + consonant);
}
public static void reverseString() {
for (int i = phrase.length() - 1; i >= 0; i--) {
reverse += phrase.charAt(i);
}
System.out.println(reverse);
}
'''
In the reverseString() method, how can I make the reversed String get trimmed or make the last letter deleted in a loop until all what's left is a single letter.
For example:
User inputs "qwertyuiop".
What should be the output is something like this:
poiuytrewq poiuytrew poiuytre poiuytr poiuyt poiuy poiu poi po p
How can I make it done like that? Please help thanks alot!
'''
public static void reverseString() {
for (int i = phrase.length() - 1; i >= 0; i--) {
reverse += phrase.charAt(i);
}
System.out.println(reverse);
'''
public static void reverseString() {
StringBuilder reverseStr = new StringBuilder();
for (int i = phrase.length() - 1; i >= 0; i--) {
reverseStr.append(phrase.charAt(i));
}
reverse = reverseStr.toString();
System.out.println(reverse);
}
// OR You can use inbuild method reverse() of StringBuilder
public static void reverseString() {
StringBuilder reverseStr = new StringBuilder(phrase);
reverse = reverseStr.reverse().toString();
System.out.println(reverse);
}
Sometimes rather than fixing code, you find an easier way:
vowel = phrase.replaceAll("(?i)[^aeiou]", "").length();
consonant = phrase.replaceAll("(?i)[^b-z&&[^eiou]]", "").length();
reverse = new StringBuilder(phrase).reverse().toString();
See live demo.
The character counts work by replacing with blank (ie "deleting") characters that aren't the type being counted and using the length of the resulting string.
Reversing uses functionality provided by the StringBuilder built-in class.

Java language conversion

this is code I am using to translate some text to English from pig Latin and vice versa. Except the fromPig method does not seem to be working correctly.
Expected output: "java is a wonderful programming language, and object oriented programming is the best thing after sliced bread."
Got output: "avajavajay isyisyay ayay onderfulwonderfulway ogrammingprogrammingpray..."
So you can see that the words are inside but I need to get rid of the other parts on the ends of the word. Please try to provide code if you can fixing my mistake.
public class PigLatin {
public String fromPig(String pigLatin) {
String res="";
String[] data=pigLatin.split(" ");
for(String word : data)
res += toEnglishWord(word) + " ";
return res;
}
private String toEnglishWord(String word) {
char punc=0;
for(int i=0;i<word.length();i++) {
if(word.charAt(i)=='.'||word.charAt(i)==','||word.charAt(i)==';'||word.charAt(i)=='!') {
punc=word.charAt(i);
break;
}
}
word=word.replace(punc + "","");
String[] data=word.split("-");
String firstPart=data[0];
String lastPart=data[0];
if(lastPart.equals("yay"))
return firstPart + punc ;
else {
lastPart=lastPart.replace("ay","");
return(lastPart+firstPart+punc);
}
}
}
This is the class that needs to execute the sentences.
public class Convert {
public static void main(String args []) {
PigLatin demo=new PigLatin();
String inEnglish="Now is the winter of our discontent " +
"Made glorious summer by this sun of York; " +
"And all the clouds that lour'd upon our house " +
"In the deep bosom of the ocean buried.";
String inPigLatin="avajay isyay ayay onderfulway ogrammingpray " +
"anguagelay, andyay objectyay orientedyay ogrammingpray " +
"isyay hetay estbay ingthay afteryay icedslay eadbray.";
System.out.println(demo.toPig(inEnglish));
System.out.println(demo.fromPig(inPigLatin));
}
}
Basically the english sentence needs to be converted to pig latin and the pig latin sentence needs to be converted to english.
English to piglatin is being done correctly. But piglatin to english is not.
Address the following problems:
Convert the text to a single case (e.g. lowercase) because you are comparing with only lowercase vowels.
The code inside your toEnglishWord is not correct. Change it as follows:
private String toEnglishWord(String word) {
char punc = 0;
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) == '.' || word.charAt(i) == ',' || word.charAt(i) == ';' || word.charAt(i) == '!') {
punc = word.charAt(i);
break;
}
}
// Trim the word, and remove all punctuation chars
word = word.trim().replaceAll("[\\.,;!]", "");
String english = "";
// If the word ends with 'yay', remove 'yay' from its end. Otherwise, if the
// word ends with 'ay', form the word as (3rd last letter + characters from
// beginning till the 4th last character). Also, add the punctuation at the end
if (word.length() > 2 && word.substring(word.length() - 3).equals("yay")) {
english = word.substring(0, word.length() - 3) + String.valueOf(punc);
} else if (word.length() > 3 && word.substring(word.length() - 2).equals("ay")) {
english = word.substring(word.length() - 3, word.length() - 2) + word.substring(0, word.length() - 3)
+ String.valueOf(punc);
}
return english;
}
Demo:
class PigLatin {
public String toPig(String english) {
String res = "";
String[] data = english.toLowerCase().split(" ");
for (String word : data)
res += toPigWord(word) + " ";
return res;
}
public String fromPig(String pigLatin) {
String res = "";
String[] data = pigLatin.toLowerCase().split(" ");
for (String word : data)
res += toEnglishWord(word) + " ";
return res;
}
private String toPigWord(String word) {
char punc = 0;
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) == '.' || word.charAt(i) == ',' || word.charAt(i) == ';' || word.charAt(i) == '!') {
punc = word.charAt(i);
break;
}
}
word = word.replace(punc + "", "");
if (isFirstLetterVowel(word))
return (word + "yay" + punc);
else {
int indexVowel = indexOfFirstVowel(word);
String after = word.substring(indexVowel);
String before = word.substring(0, indexVowel);
return (after + before + "ay" + punc);
}
}
private String toEnglishWord(String word) {
char punc = 0;
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) == '.' || word.charAt(i) == ',' || word.charAt(i) == ';' || word.charAt(i) == '!') {
punc = word.charAt(i);
break;
}
}
// Trim the word, and remove all punctuation chars
word = word.trim().replaceAll("[\\.,;!]", "");
String english = "";
// If the word ends with 'yay', remove 'yay' from its end. Otherwise, if the
// word ends with 'ay' and form the word as (3rd last letter + characters from
// beginning to the 4th last character). Also, add the punctuation at the end
if (word.length() > 2 && word.substring(word.length() - 3).equals("yay")) {
english = word.substring(0, word.length() - 3) + String.valueOf(punc);
} else if (word.length() > 3 && word.substring(word.length() - 2).equals("ay")) {
english = word.substring(word.length() - 3, word.length() - 2) + word.substring(0, word.length() - 3)
+ String.valueOf(punc);
}
return english;
}
private boolean isFirstLetterVowel(String word) {
String temp = word.toLowerCase();
return (temp.charAt(0) == 'a' || temp.charAt(0) == 'e' || temp.charAt(0) == 'i' || temp.charAt(0) == 'o'
|| temp.charAt(0) == 'u');
}
private int indexOfFirstVowel(String word) {
int index = 0;
String temp = word.toLowerCase();
for (int i = 0; i < temp.length(); i++) {
if (temp.charAt(i) == 'a' || temp.charAt(i) == 'e' || temp.charAt(i) == 'i' || temp.charAt(i) == 'o'
|| temp.charAt(i) == 'u') {
index = i;
break;
}
}
return index;
}
}
class Main {
public static void main(String[] args) {
PigLatin pigLatin = new PigLatin();
String str = "hello world! good morning! honesty is a good policy.";
String strToPigLatin = pigLatin.toPig(str);
System.out.println(strToPigLatin);
System.out.println(pigLatin.fromPig(strToPigLatin));
}
}
Output:
ellohay orldway! oodgay orningmay! onestyhay isyay ayay oodgay olicypay.
hello world! good morning! honesty is a good policy.
Note: With the current logic, there is no way to convert a word like ogrammingpray (which is the piglatin of programming) back to programming.
It's impossible to convert Pig Latin to English just like that - you need a human, a program with access to a database of words, or a neural net or something that's been trained on a database of words. Without that, you will only be convert words back to English if they originally started with a vowel or their first letter was a consonant and their second letter was a vowel. Otherwise, there is literally no way for a machine to tell where the word originally ended.
For that reason, you need to make a method that outputs a List<String> like this:
public static List<String> allPossibleSentences(String inPigLatin) {
List<String> pigWords = Arrays.asList(inPigLatin.split("\\s"));
//You can also use a method reference here
List<List<String>> possSentences = cartesianProduct(pigWords.stream().map(word -> possibleEnglishWords(word)).collect(Collectors.toList()));
return possSentences.stream().map(words -> String.join(" ", words)).collect(Collectors.toList());
}
But since you need a fromPig method in your code, you can write it like this:
public static String fromPig(String inPigLatin) {
return allPossibleSentences(inPigLatin).get(0);
}
This is overpowered, compared to the answer by Arvind Kumar Avinash, since it generates all permutations, but I feel it will be more useful if you have the most likely case and all possible sentences.
Example main method
public static void main(String[] args) {
String inPigLatin="avajay isyay ayay onderfulway ogrammingpray " +
"anguagelay andyay objectyay orientedyay ogrammingpray " +
"isyay hetay estbay ingthay afteryay icedslay eadbray";
System.out.println(fromPig(inPigLatin));
inPigLatin = "icedslay eadbray";
System.out.println("\nExpected = sliced bread, gotten = " + fromPig(inPigLatin));
System.out.println(String.join("\n", allPossibleSentences(inPigLatin)));
}
Example output
java is a wonderful rogrammingp language and object oriented rogrammingp is the best hingt after liceds readb
Expected = sliced bread, gotten = liceds readb
liceds readb
liceds bread
liceds dbrea
sliced readb
sliced bread //Here you have the right answer, but your method has no way to confirm that
sliced dbrea
dslice readb
dslice bread
dslice dbrea
Your PigLatin class now
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
class PigLatin {
//Put your toPig and toPigWord methods here (I couldn't find them)
public static String fromPig(String inPigLatin) {
return allPossibleSentences(inPigLatin).get(0);
}
/* Methods that above code relies on */
private static List<String> possibleEnglishWords(String word) {
List<String> possibilities = new ArrayList<>();
if (word.matches(".*yay$")) {
possibilities.add(word.substring(0, word.length() - 3));
return possibilities;
}
//Remove the pig latin part
word = word.substring(0, word.length() - 2);
for (int i = word.length() - 1; i >= 0; i --) {
if (isVowel(word.charAt(i))) break;
if (word == "anguagel") System.out.println("char = " + word.charAt(i));
possibilities.add(word.substring(i) + word.substring(0, i));
}
return possibilities;
}
//Put all the words together
public static List<List<String>> cartesianProduct(List<List<String>> possWordArr) {
if (possWordArr.size() == 1) {
List<List<String>> possSentencesAsWords = new ArrayList<>();
possSentencesAsWords.add(possWordArr.get(0));
return possSentencesAsWords;
}
return _cartesianProduct(0, possWordArr);
}
//Helper method
private static List<List<String>> _cartesianProduct(int index, List<List<String>> possWordArr) {
List<List<String>> ret = new ArrayList<>();
if (index == possWordArr.size()) {
ret.add(new ArrayList<>());
} else {
for (String word : possWordArr.get(index)) {
for (List<String> words : _cartesianProduct(index + 1, possWordArr)) {
words.add(0, word);
ret.add(words);
}
}
}
return ret;
}
private static boolean isVowel(char c) {
c = toUppercase(c);
switch (c) {
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
return true;
default:
return false;
}
}
private static char toUppercase(char c) {
if (c >= 'a') return (char) (((char) (c - 'a')) + 'A');
else return c;
}
}

Shortening the representation of a string by adding the number of consecutive characters

Given a random character string not including (0-9), I need to shorten the representation of that string by adding the number of consecutive characters. For e.g: ggee will result in g2e2 being displayed.
I managed to implement the program and tested it (works correctly) through various inputs. I have run into the issue where I cannot seem to understand how the character "e" is displayed given the input above.
I have traced my code multiple times but I don't see when/how "e" is displayed when "i" is 2/3.
String input = new String("ggee");
char position = input.charAt(0);
int accumulator = 1;
for (int i = 1; i < input.length(); i++)
{
// Correction. Was boolean lastIndexString = input.charAt(i) == (input.charAt(input.length() - 1));
boolean lastIndexString = i == (input.length() - 1);
if (position == input.charAt(i))
{
accumulator++;
if (lastIndexOfString)
System.out.print(accumulator); // In my mind, I should be printing
// (input.charAt(i) + "" + accumulator); here
}
else //(position != input.charAt(i))
{
if (accumulator > 1)
{
System.out.print(position + "" + accumulator);
}
else
{
System.out.print(position + "");
}
position = input.charAt(i);
accumulator = 1;
if (lastIndexOfString)
System.out.print(input.charAt(i)); // This is always printing when
// I am at the last index of my string,
// even ignoring my condition of
// (position == input.charAt(i))
}
}
In Java 9+, using regular expression to find consecutive characters, the following will do it:
static String shorten(String input) {
return Pattern.compile("(.)\\1+").matcher(input)
.replaceAll(r -> r.group(1) + r.group().length());
}
Test
System.out.println(shorten("ggggeecaaaaaaaaaaaa"));
System.out.println(shorten("ggggee😀😀😀😁😁😁😁"));
Output
g4e2ca12
g4e2😀6😁8
However, as you can see, that code doesn't work if input string contains Unicode characters from the supplemental planes, such as Emoji characters.
Small modification will fix that:
static String shorten(String input) {
return Pattern.compile("(.)\\1+").matcher(input)
.replaceAll(r -> r.group(1) + r.group().codePointCount(0, r.group().length()));
}
Or:
static String shorten(String input) {
return Pattern.compile("(.)\\1+").matcher(input)
.replaceAll(r -> r.group(1) + input.codePointCount(r.start(), r.end()));
}
Output
g4e2ca12
g4e2😀3😁4
Basically you want each char with no of repeats.
*******************************************************************************/
public class Main
{
public static void main(String[] args) {
String s="ggggggeee";
StringBuilder s1=new
StringBuilder("") ;
;
for(int i=0;i<s.length();i++)
{
int count=0,j;
for( j=i+1;j<s.length();j++)
{
if(s.charAt(i)==s.charAt(j))
count++;
else
{
break;}
}
i=j-1;
s1=s1.append(s.charAt(i)+""+(count+1));
}
System.out.print(s1);
}}
Output

Scanner.nextInt gives InputMismatchException: For input string: "222234411110000"

In my program I need to insert - between two odd numbers and * between even numbers and ignore if there is 0. For example:
Input = 99946 Output = 9-9-94*6
Input = 56647304 Output = 56*6*47-304
Method getDigits() places the digits of the entered number into array cells. Method insertDashesAsteriks() returns properly concatenated String.
But when I run my program with the following example:
Please enter the numbers so they could be rearranged:
222234411110000
Exception in thread "main" java.util.InputMismatchException: For input string: "222234411110000"
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at DashInsert2.main(DashInsert2.java:9)
then I'm getting InputMismatchException. Why am I getting the error?
import java.util.Scanner;
public class DashInsert2 {
public static void main(String[] args)
{
Scanner kbd = new Scanner(System.in);
System.out.println("Please enter the numbers so they could be rearranged: ");
int nums = kbd.nextInt();
int[] numArray = getDigits(nums);
System.out.println("The array representation of the numbers is \n");
System.out.println();
String result = insertDashesAsteriks(numArray);
System.out.println("The result is " + result);
}
public static int[] getDigits(int numbers)
{
int length = Integer.toString(numbers).length();
int[] temp = new int[length];
for(int i = 0; i < length; i++)
{
temp[i] = numbers % 10;
numbers = numbers / 10;
}
return temp;
}
public static String insertDashesAsteriks(int[] numArray)
{
String temp = "";
for(int i = 1; i < numArray.length; i++)
{
if(numArray[i] % 2 == 0 && numArray[i-1] % 2 ==0)
{
temp = numArray[i-1] + "*" + numArray[i] + "*";
}
else if(numArray[i] == 0 || numArray[i-1] == 0)
{
temp = numArray[i-1] + "" + numArray[i] + "";
}
else if(numArray[i] % 2 != 0 && numArray[i-1] % 2 != 0)
{
temp = numArray[i-1] + "-" + numArray[i] + "-";
}
}
return temp;
}
}
Maximum value for int is 2,147,483,647
You entered: 222,234,411,110,000
You'll need to treat the number as a string since the number you input is past the biggest possible 32 bit integer.
Try kbd.next().charAt(0); to parse it character by character instead.
First off, if you're reading in ints, you're limited to their range. That means numbers beyond about +/- two billion are out of the question. For handling larger number, you can move to larger data types (like long) or just handle strings, which have far less stringent limitations.
Once you are handling strings, there's a far simpler way (in terms of the code you have to write) to do this substitution using regular expressions:
public class Test {
static String morph(String s) {
String oldS;
do {
oldS = s;
s = s.replaceAll("([13579])([13579])", "$1-$2");
s = s.replaceAll("([2468])([2468])", "$1*$2");
} while (! s.equals(oldS));
return s;
}
public static void main(String args[]){
System.out.println(morph("99946"));
System.out.println(morph("56647304"));
System.out.println(morph("222234411110000"));
}
}
The morph function simply modifies the string with your substitution rules until it ceases to change. The output of the test harness (using the data you supplied) is:
9-9-94*6
56*6*47-304
2*2*2*234*41-1-1-10000
Now it may be that, if this is a classwork assignment, you're limited in the language facilities you can use. But, since you haven't mentioned that, and no coder in their right mind would (usually) choose a more difficult path, you should consider the use of the regular expression method. Code that is shorter is almost always less prone to bugs.
If you don't want to use regular expressions, you can still make your code relatively short and well structured, with something like:
// Helper functions for inserting characters.
static boolean is2468 (char ch) {
return (ch == '2' || ch == '4' || ch == '6' || ch == '8');
}
static boolean is13579 (char ch) {
return (ch == '1' || ch == '3' || ch == '5' || ch == '7' || ch == '9');
}
static String morph(String str) {
// Use efficient string builder for creating morphed string.
StringBuilder newStr = new StringBuilder();
// Last/current character, starting with '0' simplifies
// start condition.
char lastCh, ch = '0';
// Process every character in string.
for (int idx = 0; idx < str.length(); idx++) {
// Transfer previous current to last, get current.
lastCh = ch;
ch = str.charAt(idx);
// Put '-' between two odds, '*' between two non-zero evens.
if (is13579(lastCh) && is13579(ch))
newStr.append('-');
else if (is2468(lastCh) && is2468(ch))
newStr.append('*');
// Put character there regardless.
newStr.append(ch);
}
// Return string version of string builder.
return newStr.toString();
}

Java program that does simple string manipulation is not working correctly

I wrote this program for school and it almost works, but there is one problem. The goal of the program is to take an inputted string and create a new string out of each word in the input beginning with a vowel.
Example:
input: It is a hot and humid day.
output: Itisaand.
Here is the driver:
public class Driver {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("Input: ");
String input = console.nextLine();
Class strings = new Class(input);
int beg=0;
for(int j=0;j<input.length();j++)
{
if(strings.isVowel(j)&&(j==0||input.charAt(j-1)==' '))
beg=j;
else if(strings.endWord(j)&&(beg==0||input.charAt(beg-1)==' '))
{
strings.findWord(beg, j);
}
}
System.out.print("Output: ");
strings.printAnswer();
}
}
And here is the class:
public class Class {
String input="",answer="";
public Class(String input1)
{
input = input1;
}
public boolean isVowel(int loc)
{
return (input.charAt(loc)=='U'||input.charAt(loc)=='O'||input.charAt(loc)=='I'||input.charAt(loc)=='E'||input.charAt(loc)=='A'||input.charAt(loc)=='a'||input.charAt(loc)=='e'||input.charAt(loc)=='i'||input.charAt(loc)=='o'||input.charAt(loc)=='u');
}
public boolean endWord(int loc)
{
return (input.charAt(loc)==' '||input.charAt(loc)=='.'||input.charAt(loc)=='?'||input.charAt(loc)=='!');
}
public void findWord(int beg,int end)
{
answer = answer+(input.substring(beg,end));
}
public void printAnswer()
{
System.out.println(answer+".");
}
}
With this code, i get the output:
Itisaa hotandand humidand humid summerand humid summer day.
By removing this piece of code:
&& (j == 0 || input.charAt(j-1) == ' ')
I get the proper output, but it doesn't work if an inputted word has more than one vowel in it.
For example:
input: Apples and bananas.
output: and.
Can someone please explain:
a) why the code is printing out words beginning with consonants as it is and
b) how I could fix it.
Also, the methods in the class I've written can't be changed.
Here's a better algorithm:
split the input into an array of words
iterate over each word
if the word begins with a vowel, append it to the output
The easiest way to split the input would be to use String.split().
Here's a simple implementation:
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
String input = console.nextLine();
String[] words = input.split(" ");
StringBuilder output = new StringBuilder();
for (String s : words) {
if (startsWithVowel(s)) {
output.append(s);
}
else {
output.append(getPunc(s));
}
}
System.out.println(output.toString());
}
public static boolean startsWithVowel(String s) {
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
char firstChar = s.toLowerCase().charAt(0);
for (char v : vowels) {
if (v == firstChar) {
return true;
}
}
return false;
}
public static String getPunc(String s) {
if (s.matches(".*[.,:;!?]$")) {
int len = s.length();
return s.substring(len - 1, len);
}
return "";
}
The problem with your code was:
It was counting the same word multiple times, due to it finding vowels and starting the word search process over again.
Heres how I went about solving the problem, while still keeping your code looking relatively the same: All I changed was your loop
for(int i=0;i<input.length();i++)
{
if(strings.isVowel(i) &&(i==0 || strings.endWord(i-1))){
beg = i;
for(int j = i; j < input.length();j++) //look for end of word
{
if(strings.endWord(j)) //word has ended
{
i = j; //start from end of last word
strings.findWord(beg, j);
break; //word done, end word search
}
}
}
}
As mentioned above, there are better ways to go about this, and there are some pretty glaring flaws in the setup, but you wanted an answer, so here you go
Normally i would suggest you where to fix your code, but it's seems there is a lot of bad code practice in here.
Mass Concatenation should be apply be StringBuilder.
Never call a class Class
Conditions are too long and can be shorten by a static string of Vowels and apply .contains(Your-Char)
Spaces, Indentations required for readability purposes.
A different way of attacking this problem, may probably accelerate your efficiency.
Another approch will be Split the code by spaces and loop through the resulted array for starting vowels letters and then Append them to the result string.
A better readable and more maintainable version doing what you want:
public static String buildWeirdSentence(String input) {
Pattern vowels = Pattern.compile("A|E|I|O|U|a|e|i|o|u");
Pattern signs = Pattern.compile("!|\\.|,|:|;|\\?");
StringBuilder builder = new StringBuilder();
for (String word : input.split(" ")) {
String firstCharacter = word.substring(0, 1);
Matcher vowelMatcher = vowels.matcher(firstCharacter);
if (vowelMatcher.matches()) {
builder.append(word);
} else {
// we still might want the last character because it might be a sign
int wordLength = word.length();
String lastCharacter = word.substring(wordLength - 1, wordLength);
Matcher signMatcher = signs.matcher(lastCharacter);
if (signMatcher.matches()) {
builder.append(lastCharacter);
}
}
}
return builder.toString();
}
In use:
public static void main(String[] args) {
System.out.println(buildWeirdSentence("It is a hot and humid day.")); // Itisaand.
}
I think best approach is to split input and then check each word if it starts with vowel.
public static void main(String[] args)
{
Scanner console = new Scanner(System.in);
System.out.print("Input: ");
String str = console.next();
String[] input = str.split(" ");
StringBuilder s = new StringBuilder();
String test;
for (int i = 0; i < input.length; i++)
{
test = input[i];
if (test.charAt(0) == 'U' || test.charAt(0) == 'O'
|| test.charAt(0) == 'I' || test.charAt(0) == 'E'
|| test.charAt(0) == 'A' || test.charAt(0) == 'a'
|| test.charAt(0) == 'e' || test.charAt(0) == 'i'
|| test.charAt(0) == 'o' || test.charAt(0) == 'u')
{
s.append(input[i]);
}
}
System.out.println(s);
}
The problem with your code is that you override the first beg when a word has more that vowel. for example with Apples beg goes to 0 and before you could call findWord to catch it, it gets overridden with 4 which is the index of e. And this is what screws up your algorithm.
You need to note that you have already found a vowel until you have called finWord, for that you can add a boolean variable haveFirstVowel and set it the first time you have found one to true and only enter the branch for setting that variable to true if you haven't already set it. After you have called findWord set it back to false.
Next you need to detect the start of a word, otherwise for example the o of hot could wrongly signal a first vowel.
Class strings = new Class(input);
int beg = 0;
boolean haveFirstVowel = false;
for (int j = 0; j < input.length(); j++) {
boolean startOfWord = (beg == 0 || input.charAt(j - 1) == ' ');
if (startOfWord && ! haveFirstVowel && strings.isVowel(j)) {
beg = j;
haveFirstVowel = true;
}
else if (strings.endWord(j) && haveFirstVowel) {
strings.findWord(beg, j);
haveFirstVowel = false;
}
}
System.out.print("Output: ");
strings.printAnswer();
I think overall the algorithm is not bad. It's just that the implementation can definitely be better.
Regarding to the problem, you only need to call findWord() when:
You have found a vowel, and
You have reached the end of a word.
Your code forgot the rule (1), therefore the main() can be modified as followed:
Scanner console = new Scanner(System.in);
System.out.print("Input: ");
String input = console.nextLine();
Class strings = new Class(input);
int beg = 0;
boolean foundVowel = false; // added a flag indicating whether a vowel has been found or not
for (int j = 0; j < input.length(); j++) {
if (strings.isVowel(j) && (j == 0 || input.charAt(j - 1) == ' ')) {
beg = j;
foundVowel = true;
} else if (strings.endWord(j) && (beg == 0 || input.charAt(beg - 1) == ' ')) {
if (foundVowel) { // only call findWord() when you have found a vowel and reached the end of a word
strings.findWord(beg, j);
foundVowel = false; // remember to reset the flag
}
}
}
System.out.print("Output: ");
strings.printAnswer();

Categories

Resources