Changing or to our - java
I've been working on a program for school for some time now that is supposed to change every word that ends in "or" and does not have a vowel before the "or". However I am running into an issue where it replaces the letters for words such as paper and letter into papeur and letteur. Here's my code:
import java.util.Scanner;
public class main {
public static void main(String[] args){
//Initializing Variables
Scanner input = new Scanner(System.in);
char[] vowels = new char[] {'a','e','i','o','u'};
boolean hasVowel = false;
boolean running = true;
boolean oR = false;
while(running){
//Check for word
System.out.println("Enter a word more than 4 letters long or type quit to stop");
String word = input.nextLine();
if(word.equalsIgnoreCase("quit")){
System.exit(0);
}
while(word.length() <= 4){
System.out.println("That word is not more than 4 letters long");
word = input.next();
}
//Used to insert words
StringBuilder stringBuilder = new StringBuilder(word);
//Check for the letters
char x = word.charAt(word.length()-2);
if(word.endsWith("r")){
if(x == 'o') {
oR = true;
System.out.println("Has or");
for (char c : vowels) {
if (c == word.charAt(word.length() - 3)) {
hasVowel = true;
oR = false;
}
}
}
}
//output
if (hasVowel){
System.out.println(word);
}
else{
if(oR = true) {
stringBuilder.insert(word.length() - 1, "u");
System.out.println(stringBuilder.toString());
}
else if (oR = false) {
System.out.println(word);
}
}
System.out.println(hasVowel);
System.out.println(word.charAt(word.length()-3));
}
}
}
If someone could help me out that would be amazing!
Your problem is this line:
if(oR = true) {
This will always be true, because it is an assignment rather than an equality check. You want == here.
Also note that the else clause that goes with this:
else if (oR = false) {
can be just:
else {
since if a boolean value isn't true, it has to be false.
This way you can edit
public static void main(String[] args){
//Initializing Variables
Scanner input = new Scanner(System.in);
char[] vowels = new char[] {'a','e','i','o','u'};
boolean hasVowel = false;
boolean running = true;
boolean oR = false;
while(running){
//Check for word
System.out.println("Enter a word more than 4 letters long or type quit to stop");
String word = input.nextLine();
if(word.equalsIgnoreCase("quit")){
System.exit(0);
}
while(word.length() <= 4){
System.out.println("That word is not more than 4 letters long");
word = input.next();
}
//Used to insert words
StringBuilder stringBuilder = new StringBuilder(word);
//Check for the letters
char x = word.charAt(word.length()-2);
if(word.endsWith("r")){
if(x == 'o') {
oR = true;
System.out.println("Has or");
for (char c : vowels) {
if (c == word.charAt(word.length() - 3)) {
hasVowel = true;
oR = false;
}
}
}
}
//output
if (hasVowel){
System.out.println(word);
}
else{
if(oR) { //if(oR == true)
stringBuilder.insert(word.length() - 1, "u");
System.out.println(stringBuilder.toString());
}
else { //else if (!oR) //else if (oR == false)
System.out.println(word);
}
}
System.out.println(hasVowel);
System.out.println(word.charAt(word.length()-3));
}
}
As mentioned in the comments, this task could be resolved using regular expressions because it is a natural way of searching and replacing substrings in strings.
The basic regular expression to replace suffix -or with suffix -our on the condition that -or is not preceded by a vowel is as follows:
public String simpleOrToOur(String word) {
return word.replaceAll("(\\w+[^aeiou])or", "$1our");
}
However, the initial rule does not seem to be correct because the replacements should NOT occur in multiple cases when there is a consonant before or, and may occur for -ior prefix:
bor: no rubour
cor: no decour, mucour, only rancour/succour
dor: only ardour, candour, odour, splendor are valid, no replacement needed in dor, condor, corridor, vendor, etc.
for: is not replaced with four
gor: only clangour, rigour, vigour, and no replacement in: mortgagor, pledgor, turgor
hor: not replaceable at all: anchor, author, camphor, etc.
ior: vowel need to replace in behavior, pavior, savior
lor: no replacement needed in bachelor, chancellor, counsellor, jailor, sailor, tailor etc.
mor: actually it should be a[r]mor or umor as in armor, clamor, glamor, humor, no replacement in mor, tremor
nor: replacement needed only in honor, demeanor and their derivatives, no replacement in donor, manor, minor, signor, tenor, etc.
por: needed in sapor, vapor, not in stupor, torpor
vor: should be avor/ervor as in flavor, fervor, not in salvor, survivor
Other prefixes with remaining consonants [jkqstwxyz]or do not need replacement to -our either.
That being said, a better matching regexp consisting of prefix including the mentioned subparts joined with OR | and suffix -or may be implemented:
public static String changePrefixOrToOur(String word) {
return word.replaceAll("(((h?ar|[lt]a|neigh)b)|(ranc|succ)|((ar|can|o|splen)d)|((clan|[rv]i)g)|(vi)|(([cd]o|par|va)l)|((ar?|u)m)|((ho|demea)n)|([sv]ap)|((a|er)v))or",
"$1our"
);
}
Test:
String[] replaceableWords = {
"arbor", "harbor", "neighbor", "labor", "tabor",
"rancor", "succor",
"ardor", "candor", "odor", "splendor",
"clangor", "vigor", "rigor",
"misbehavior", "pavior", "savior",
"color", "dolor", "parlor", "valor",
"amor", "armor", "tumor", "humor", "clamor", "glamor",
"dishonor", "honor", "misdemeanor",
"vapor", "sapor",
"flavor", "endeavor", "favor", "savor", "disfavor"
};
int successCount = 0;
for (String word : replaceableWords) {
String replaced = changePrefixOrToOur(word);
successCount += replaced.endsWith("our") ? 1 : 0;
//System.out.printf("%s -> %s ? %s%n", word, replaced, replaced.endsWith("our") ? "OK" : "FAIL");
}
System.out.printf("Replaced `or` to `our`: %d of %d words%n---%n%n", successCount, replaceableWords.length);
String[] notReplaceableWords = {
"rubor",
"decor", "mucor",
"ambassador", "condor", "corridor", "conquistador", "dor", "matador", "picador", "vendor",
"meteor",
"for",
"mortgagor", "pledgor", "turgor", "tangor",
"abhor", "anaphor", "anchor", "author", "camphor", "metaphor",
"anterior", "prior", "superior", "warrior",
"Angkor",
"bachelor", "counselor", "chancellor", "squalor", "tailor", "sailor", "taylor",
"mor", "tremor",
"nor", "assignor", "donor", "governor", "signor", "minor", "manor", "tenor", "intervenor",
"door", "floor", "moor", "outdoor", "poor", "boor",
"por", "sopor", "torpor", "stupor",
"advisor", "censor", "professor", "processor", "sensor", "tensor",
"actor", "doctor", "director", "factor", "bettor",
"liquor", "languor", "fluor",
"survivor", "salvor",
"xor", "luxor", "taxor",
"mayor",
"razor", "seizor", "vizor"
};
for (String word : notReplaceableWords) {
String replaced = changePrefixOrToOur(word);
successCount += replaced.endsWith("or") ? 1 : 0;
//System.out.printf("%s -> %s ? %s%n", word, replaced, replaced.endsWith("or") ? "OK" : "FAIL");
}
System.out.printf("Not replaced `or` to `our`: %d of %d words%n", successCount - replaceableWords.length, notReplaceableWords.length);
Output:
Replaced `or` to `our`: 37 of 37 words
---
Not replaced `or` to `our`: 79 of 79 words
Related
The user must enter a string that contains at least one lowercase “a”
The user must do the question above or the question keeps repeating so I need a while loop. I need to do this using a subroutine too. My code below isn't working. public static boolean isAlpha(String name) { char[] chars = name.toCharArray(); for (char c : chars) { if (!Character.isLetter(c)) { return false; } else { for (int i = 0; i < name.length(); i++) { if (name.charAt(i) >= 'a') { return false; } else { return false; } } } } return false; } This is the second part: System. out.print ("Please enter a string that contains at least one lowercase a. "); String name = input.next (); if (isAlpha(name)) { System.out.println("That is a valid string onto stage 2."); } else { System.out.println("That is an invalid string. Try again."); }
You're passing a String to the isAlpha method, which iterates over the String and checks each letter to be 'a' or not. You're returning false for every char that isn't 'a', and returning false if you iterate through the entire String. An easier way to handle this would be to return true upon finding the first 'a', or returning false after iterating over the entire String. It will make scaling easier as well if you reduce the number of return statements in a single method.
Here are three different ways to check whether a string contains at least one lowercase a. The first way uses a for loop as you have tried to do in the code in your question. The second way uses regular expressions and the last way uses streams. The code also contains a main method which contains a while loop as requested in your question. do the question above or the question keeps repeating import java.util.Scanner; public class Solution { public static boolean isAlpha(String name) { /* Using a loop. */ char[] chars = name.toCharArray(); for (char ch : chars) { if (ch == 'a') { return true; } } return false; /* Using regular expression. */ // return name.matches("^.*a.*$"); /* Using stream API. */ // return name.chars() // .filter(c -> c == 'a') // .findFirst() // .isPresent(); } public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Please enter a string that contains at least one lowercase 'a': "); String str = input.nextLine(); while (!isAlpha(str)) { System.out.println("That is an invalid string. Try again."); str = input.nextLine(); } System.out.println("That is a valid string. On to stage 2."); } } Here is a sample run: Please enter a string that contains at least one lowercase 'a': 1 is the lonliest number. That is an invalid string. Try again. 2 can be as bad as 1 That is a valid string. On to stage 2.
A couple of mistakes were made. Firstly, your method only returns false, there is no way in which it could be true. Secondly, your code here loops through the entire array for every single character. public static Boolean isAlpha(String name) { char[] chars = name.toCharArray(); for (char c : chars) { if (!Character.isLetter(c)) { return false; } else { for (int i = 0; i < name.length(); i++) { if (name.charAt(i) >= 'a') { return false; } else { return false; } } } } return false; } Try this instead. public static Boolean isAlpha(String name) { char[] chars = name.toCharArray(); for(char c : chars) { if(c=='a') { return true; } } return false; }
Check whether String2 is substring of string1 with '*' and '\'
Given two strings s1 and s2, we have to check if s2 is a substring of s1. If it's true print "true" else print "false" But s1 and s2 can contain characters like '*' and '\'. In s2, '*' represents zero or more characters in between two alphabets and '\' represents an escape sequence for '*'. In s1, '*' and '\' are just other characters that are to be checked. Sample Input and Output: Input: abcd , a*c Output: true Input : spoon , sp*n Output : true Input : regex , re*g Output : true Input : search , *c Output : true Input : zoho , *o*o Output : true Input : zoho , *ogo Output : false Input : test , pest Output : false Input : st*r , t\*r Output : true Input : star , t\*r Output false Input : tree , tr\ Output false Input : tr\e , tr\ Output true I know this question can be solved easily by using regex, but I need a logical approach for solving this. Can anybody help me soon? Below is my code that I have tried, but couldn't solve entirely. public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s1 = sc.next(); String s2 = sc.next(); boolean flag = true; int i=0,j=0; for(;s2.charAt(j)<'a' || s2.charAt(j)>'z';j++); for(i=0;i<s1.length();i++) { char ch = s1.charAt(i); if(ch==s2.charAt(j)) { i++;j++; break; } } for(;j<s2.length();) { System.out.println(i+" "+j); while(s2.charAt(j)=='*' && j<s2.length()-1 && s2.charAt(j+1)!=s1.charAt(i) && i<s1.length()) { i++; } j++; if(i==s1.length()) { flag = false; break; } if(s1.charAt(i)!=s2.charAt(j) && s2.charAt(j)<97 && s2.charAt(j)>122) { flag = false; break; } } System.out.print(flag); }
You can strip the string of * and break it whenever you encounter the * character and check if substrings are in the actual string. Something like: public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s1 = sc.next(); String s2 = sc.next(); int begIndex = 0; int prevIndex = 0; boolean flag = true; s2 = stripLeadingAndTrailingCharacter(s2, '*'); for(int i = 0; i < s2.length(); ++i) { if ((( i == 0 || s2.charAt(i - 1) != '\\') && s2.charAt(i) == '*') || (i == s2.length() - 1)) { int endIndex = i == s2.length() - 1 ? i + 1 : i; String str = s2.substring(begIndex, endIndex).replace("\\*", "*"); if (s1.contains(str) && prevIndex <= s1.indexOf(str)) { prevIndex = s1.indexOf(str); } else { flag = false; break; } begIndex = i + 1; } } System.out.println(flag); } public static String stripLeadingAndTrailingCharacter(String s, char ch) { int index; for (index = 0; index < s.length(); index++) { if (s.charAt(index) != ch) { break; } } s = s.substring(index); for (index = s.length() - 1; index >= 0; index--) { if (s.charAt(index) != ch) { break; } } s = s.substring(0, index + 1); return s; }
I'm not sure what what you mean with the * and the /, but, one solution to know if a string is a substring for another one is using "contains" method, that extends from String class: public static void main(String[] args) { String str1 = "abcdefghi"; String str2 = "abcd"; if (str1.contains(str2)) { System.out.println("Exist the substring."); } else { System.out.println("Not exist."); } } I'm thinking that you also needs to replace if exist * or / as a valid value
Check if a sentence has the same words forward and backwards
I am trying to check if a sentence is the same forwards and backwards or a "sentence palindrome." The sentence "You can cage a swallow, can't you, but you can't swallow a cage, can you?" should return (True) as a palindrome. Ignore everything that is not a letter. My problem: Not sure how to compare words specifically. This currently works for words checking if they are palindromes, but I need to figure out what to change to compare each word. public static boolean isWordPalindrome(String input) { Deque<Character> q = new LinkedList<>( ); Deque<Character> q2 = new LinkedList<>( ); Character letter; // One character from the input string int mismatches = 0; // Number of spots that mismatched int i; // Index for the input string int x; for (i = 0; i < input.length( ); i++) { letter = input.charAt(i); // read next character in the string if (letter.toString().equals(',') || letter.toString().equals('"') || letter.toString().equals('?') || letter.toString().equals('!') || letter.toString().equals('.') || letter.toString().equals(' ')) { //throwaway.add(letter); //ignore above chars and put in throwaway stack } if (Character.isLetter(letter)) // if letter put into q's { q.add(letter); q2.addFirst(letter); } } // end of for loop System.out.println("q: " + q); System.out.println("q2:" + q2); while (!q.isEmpty( )) { if (!Objects.equals(q.remove(), q2.remove())) mismatches++; }
I'd remove all the special characters, split the string by whitespaces and check the list is "symmetrical": private static boolean isSentancePalindrom(String sentence) { String[] words = sentence.replaceAll("[^a-zA-Z ]", "").split("\\s+"); for (int i = 0; i < words.length / 2; ++i) { if (!words[i].equalsIgnoreCase(words[words.length - i - 1])) { return false; } } return true; }
I came up with this: public static boolean checkString(String str) { str = str.replaceAll("[,\\?\\.!]+", "").toUpperCase(); String[] split = str.split(" "); String[] reverse = new String[split.length]; System.arraycopy(split, 0, reverse, 0, split.length); List<String> listOfSring = Arrays.asList(split); List<String> reversListOfSring = Arrays.asList(reverse); Collections.reverse(reversListOfSring); return reversListOfSring.equals(listOfSring); } I hope it would help!
How to adjust the given string such that the first letter after the space becomes Upper case in java?
So I was solving problem from one competitive websites.And I have completed 75% of the constraint.But the condition where the first word in the given sentence after space must be uppercase.I tried but it does not give correct answer. For example if the sentence is "This is" is the sentence it must be changed to "ThIs Is".So help me. And my code is as follows import java.util.Scanner; public class DancingSentence { public String makeDancing(String sentence) { //sentence=sentence.replace("\\s+",""); //String sen = null; char[] sen = sentence.toCharArray(); int i = 0; System.out.println(sen.length); if(i==0) { sen[i]=sen[i]; } for(i=1;i<sen.length;i++) { // if() if (i%2==0) { sen[i] = (char)(sen[i]-32); } //if((int)sen[i]==32) if(Character.isWhitespace(sen[i])) { //System.out.print(" "); sen[i+1]=Character.toUpperCase(sen[i+1]); //i+=1; } } sentence = sen.toString().copyValueOf(sen); //sentence = sentence.replace("", "\\s+"); //System.out.println(sentence); return sentence; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); String sentence = sc.nextLine(); //sentence=sentence.replaceAll("\\s+",""); DancingSentence ds = new DancingSentence(); String result=ds.makeDancing(sentence); System.out.println(result); } }
Your logic is almost right. If the index is even (i % 2 == 0), you convert the character to uppercase. If you encounter a whitespace, you just skip it and don't increase your variable that you use for determining even positions. public String makeDancing(String sentence) { char[] sen = sentence.toCharArray(); int mod = 0; //counts just letters for(int i=0; i < sen.length; i++) { if(Character.isWhitespace(sen[i])) { //if character is a whitespace, skip it continue; } if (mod % 2 == 0) { //if it is an even position, make it uppercase sen[i] = Character.toUpperCase(sen[i]); } mod++; } sentence = new String(sen); return sentence; }
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();