Basically I want to recursively get this:
“ pErHaPs I hAVe wRitten a Sentence LiKE this one “
To look like this:
“perhapsIHaveWrittenASentenceLikeThisOne”
n>0 of spaces before, between, and after each word
any assortment of upper-case and lower-case letters
ex: " lIkE ThIs"
What I think I understand:
Using string.charAt(i) to compare the specific character to a space
Using Character.isUpperCase() for case checking
What I don't understand:
How recursion will work to change the string since strings are immutable
What the base case will be
how to only uppercase the first letter of every word after the first word
EDIT:
This is what I have come up with after a few helpful hints:
`public static String toCamelCase(String str) {
if(str.length() == 1) {
if(str.charAt(0) == ' ') {
return "";
} else {
return str;
}
} else if(str.charAt(0) == ' ' && str.length() != 1) {
if(str.charAt(1) != ' ') {
return str.substring(1, 2).toUpperCase() + toCamelCase(str.substring(2, str.length()));
} else {
return toCamelCase(str.substring(1, str.length()));
}
} else if(str.charAt(0) != ' ' && str.length() != 1) {
if(str.charAt(1) != ' ') {
return str.substring(0,2).toLowerCase() + toCamelCase(str.substring(2, str.length()));
} else {
return str.substring(0,1).toLowerCase() + toCamelCase(str.substring(1, str.length()));
}
}
return str;
}`
Everything works except the first letter of the first word is also capitalized. How would I make the code exclude the first word when uppercasing first letters of words? Is this possible recursively?
There you go with your recursive implementation:
public String camelCase(String inputStr) {
String s = inputStr.toLowerCase();
String[] arr = s.split(" ");
s = arr[0];
return getCamelCased(s,1,arr);
}
private String getCamelCased(String s, int index, String[] arr) {
if(index >= arr.length)
return s;
String curr = arr[index++];
s += curr.length()==1?curr.toUpperCase():
(curr.toUpperCase.charAt(0)+curr.substring(1,curr.length()));
return getCamelCased(s,index,arr);
}
Related
The rest of the code is working perfectly but I cannot figure out how to prevent punctuation from being translated.
public class PigLatintranslator
{
public static String translateWord (String word)
{
String lowerCaseWord = word.toLowerCase ();
int pos = -1;
char ch;
for (int i = 0 ; i < lowerCaseWord.length () ; i++)
{
ch = lowerCaseWord.charAt (i);
if (isVowel (ch))
{
pos = i;
break;
}
}
if (pos == 0 && lowerCaseWord.length () != 1) //translates if word starts with vowel
{
return lowerCaseWord + "way"; // Adding "way" to the end of string
}
else if (lowerCaseWord.length () == 1) //Ignores words that are only 1 character
{
return lowerCaseWord;
}
else if (lowerCaseWord.charAt(0) == 'q' && lowerCaseWord.charAt(1) == 'u')//words that start with qu
{
String a = lowerCaseWord.substring (2);
return a + "qu" + "ay";
}
else
{
String a = lowerCaseWord.substring (1);
String b = lowerCaseWord.substring (0,1);
return a + b + "ay"; // Adding "ay" at the end of the extracted words after joining them.
}
}
public static boolean isVowel (char ch) checks for vowel
{
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'y')
{
return true;
}
return false;
}
}
I need the translation to ignore punctuation. For example "Question?" should be translated to "estionquay?" (question mark still in the same position and not translated)
As Andreas said, if the function is expecting only one word, it should be the responsibility of the calling function to ensure there's no full sentence or punctuation being passed to it. With that said, if you require the translator to handle this, you need to find the index of the string where the punctuation or non-letter character occurs. I added in a main method to test the function:
public static void main(String[] args) {
System.out.println(translateWord("QUESTION?"));
}
I added a loop into the qu case to find the punctuation being input, the two checks are to see if the character at position i is inside the range of a - z. The sub-string then only goes to the point where the punctuation is found.
int i;
for (i = 0; i < lowerCaseWord.length(); i++) {
if(lowerCaseWord.charAt(i) > 'z' || lowerCaseWord.charAt(i) < 'a') {
break;
}
}
String a = lowerCaseWord.substring (2, i);
String b = lowerCaseWord.substring(i);
return a + "qu" + "ay" + b;
This may need some tweaking if you're worried about words with hyphens and whatnot but this should put across the basic idea.
Here's the output I received:
$javac PigLatintranslator.java
$java -Xmx128M -Xms16M PigLatintranslator
estionquay?
I am trying to remove the letter x if it is present as the first or last character of any given string. Why does my code not check strings with length 0 even though I have accounted for it in my code?
I have already tried using an if statement to check if the length is 0 and, if so, to return the original string. I have also tried returning an empty string with the same value.
public String withoutX(String str) {
if (((str.charAt(0)=='x') || str.charAt(str.length()-1) == 'x') && str.length()>=2){
if (str.charAt(0)=='x'){
str = str.substring(1,str.length());
} if (str.charAt(str.length()-1) == 'x'){
str = str.substring(0,str.length()-1);
}
} if (str.length()==1 && str == "x"){
return "";
} if (str.length()==0){
return str;
// the above if statement (length = 0) does not work
} else{
return str;
}
}
The expected result is for it to return the string without the letter x. This has been achieved for all strings, except an empty one, where it says that the index is out of range.
if (str.length() == 0) {
return str;
}
It should be at the top of the method body. Or, at least, it should go prior to getting str.charAt(0).
There's String#isEmpty.
The way you compared Strings is wrong. Use equals instead of ==.
Always validate the length before accessing a letter by index. Make sure that index in a string exists.
In this line:
if (((str.charAt(0)=='x') || str.charAt(str.length()-1) == 'x') && str.length()>=2)
you do check for the length of the string but after you check the indexes.
Change to:
if (str.length()>=2 && (str.charAt(0)=='x' || str.charAt(str.length()-1) == 'x'))
if str.length()>=2 is false the other conditions will not be checked because of Short Circuit Evaluation.
Also use equals() to compare strings and not ==.
I vwould write your method like this:
public String withoutX(String str) {
if (str.length() == 0 || (str.length() == 1 && str.equals("x")))
return "";
if (str.charAt(0) == 'x') {
str = str.substring(1, str.length());
}
if (str.charAt(str.length() - 1) == 'x') {
str = str.substring(0, str.length() - 1);
}
return str;
}
I kept your logic and removed unnecessary code.
I think this is a better implementation of what you are trying to do
public String withoutX(String str) {
if (str.startsWith("x")){
str = str.replaceFirst("x", "");
}
if (str.endsWith("x")){
str = str.substring(0,str.lastIndexOf("x"));
}
return str;
}
A simpler approach without making many corner-cases checking is to use regex to remove the leading and trail x - if it exists. Here's the code:
public String withoutX(String str){
return "".equals(str)? str: str.replaceAll("(^x|x$)", "");
}
Your code is checking for a x before you check if the string is empty. You should move
if (str.length()==0){
return str;
// the above if statement (length = 0) does not work
}
to the first line of the method. Besides that your code is great.
public String withoutX(String str) {
if (!str.isEmpty() && str.charAt(0)=='x'){
str = str.substring(1, str.length());
}
if (!str.isEmpty() && str.charAt(str.length()-1) == 'x'){
str = str.substring(0,str.length()-1);
}
return str;
}
You can first check, if the str is empty and remove the first x. Then check the size for greater than 1 and remove the last x. This leads to less and more readable code.
I want to write a method to check a string for consonants using either .contains or .indexOf.
I guess I could do it the long way and check for every consonant in the alphabet but I know there is a better way. This is what I have so far but like I said this is sort of the long way, I think.
public boolean containsConsonant(String searchString) {
if(searchString.contains("b") || searchString.contains("c")){
return true;
}
I think a simple for loop is most readable here, you can test that a character is within the desired range with a boolean and. And you can use an or test to skip vowels. Something like,
public boolean containsConsonant(String searchString) {
if (searchString == null) {
return false;
}
for (char ch : searchString.toCharArray()) {
char lower = Character.toLowerCase(ch);
if (lower >= 'a' && lower <= 'z') {
if (lower == 'a' || lower == 'e' || lower == 'i' ||
lower == 'o' || lower == 'u') continue;
return true;
}
}
return false;
}
Optimization
You could then optimize the above (and directly to your question) by using contains on an extracted constant String of vowels. Something like,
private static final String vowels = "aeiou";
public static boolean containsConsonant(final String searchString) {
if (searchString == null) {
return false;
}
for (char ch : searchString.toCharArray()) {
char lower = Character.toLowerCase(ch);
if (lower >= 'a' && lower <= 'z' && !vowels.contains(String.valueOf(lower))) {
return true;
}
}
return false;
}
I see that you explicitly ask using contains or indexOf
in case - if you can use matches - it would be very easy to implement.
public boolean containsConsonant(String searchString){
String consonants = ".*[bcdfghj].*"; //list the characters to be checked
return searchString.matches(consonants);
}
you can create say an array containing all consonants and then run it using a loop
e.g.
String[] consonants{"b", "c",....}
boolean containsConsonants(String searchString, String[]arr){
for (String consonant: arr){
if(searchString.contains(str)){ return true} return False
I have to create a recursive method to display all substrings of a given string before the letter 'A' or 'a', and ignore that letter in the process. The termination condition works fine. However, in the continue condition I am thrown a indexoutofbounds error and I'm not entirely sure why. As far as I can tell I stop the loop before the index reaches the string's length. but I will post it here in case I missed something.
class Tree
{
void subStrings(String s)
{
if(s.length() == 1)
{
if(s.charAt(0) == 'A' || s.charAt(0) == 'a')
{
System.out.println("Cannot shorten substring.");
}
else
{
System.out.println(s);
}
}
else
{
String subString = "";
int i = 0;
while(s.charAt(i) != 'A' && i < s.length())//bad line
{
subString += s.charAt(i);
i++;
}
if(subString.equals(""))
subStrings(s.substring(i));
else
{
System.out.println(subString);
subStrings(s.substring(i));
}
}
}
int treeHeight(String tree)
{
return 0;
}
}
Even Robby's refactoring won't get you where you won't on account of some other issues. For what concerns your exception you must iterate to i < s.length() - 1 since you're incrementing the index in the loop, and charAt method you use inside the loop starts at index 0.
Checked further and you should change your substring(i) to subStrings(s.substring(0, i)) otherwise you would end up with the same string in recursion. The following should work for you
void subStrings(String s)
{
if(s == null || s.length() == 0 || s.charAt(0) == 'A' || s.charAt(0) == 'a')
{
System.out.println("Cannot shorten substring.");
return;
}
if(s.length() != 1)
{
String subString = "";
int i = 0;
while(s.charAt(i) != 'A' && s.charAt(i) != 'a' && i < s.length() - 1)//bad line
{
subString += s.charAt(i);
i++;
}
if(subString.equals(""))
subStrings(s.substring(i));
else
{
System.out.println(subString);
subStrings(s.substring(0, i));
}
}
}
You need to reverse these two conditions:
while(s.charAt(i) != 'A' && i < s.length()) { /*...*/ }
So, it should be:
while(i < s.length() && s.charAt(i) != 'A') { /*...*/ }
Otherwise you get an out of bounds exception when the string is empty and you try to access the first character (at position 0).
If you just want to split a string using a or A as a delimiter, you might as well do:
String[] substrings = str.split("[aA]");
If it absolutely has to be implemented using a recursive method, instead of processing the string character by character, you could use indexOf to find the position of the next a or A. It could look something like this:
public static void subStrings(String s) {
int i = s.toLowerCase().indexOf('a');
if (i >= 0) {
System.out.println(s.substring(0, i));
if (i + 1 < s.length()) {
subStrings(s.substring(i + 1));
}
}
}
Method should take in a word, recursively go thru the string and find letters that are the same distance from either end of the alphabet and remove them. If it removes a match, those letters cannot be used again. If every letter is removed, then it is a match.
for (int i = 1; i < word.length()-1; i++)
{
if (word.charAt(0) + word.charAt(i) == 155)
{
StringBuilder sb = new StringBuilder(word);
sb.deleteCharAt(0);
sb.deleteCharAt(i);
String strNew = sb.toString();
System.out.println(strNew);
return isAlphaOpp(strNew);
}
}
return false;
}
I have modified your method a bit, have a look at it. You need compare with 155 if your string is all capitals, if all lower case letters you need compare with 219. As #Raghu suggested, this doesnt required recursion (that is making things complicated), but I am assuming you want to try this with recursion.
public static boolean isAlphaOpp (String word)
{
//if word has odd number of characters, it cannot be an alpha opp
if (word.length() % 2 != 0)
{
return false;
}
//if string makes it to 0, then word must be an alpha opp
if (word.length() == 0)
{
return true;
}
/*if (word.charAt(0) + word.charAt(word.length()-1) == 155)
{
System.out.println(word.substring(1, word.length()-1));
return isAlphaOpp(word.substring(1, word.length()-1));
}
*/
//Should go thru each letter and compare the values with char(0). If char(0) + //char(i) == 155 (a match) then it should remove them and call the method again.
int length = word.length()-1;
int start = 0;
String newStr = null;
while(start < length) {
if(word.charAt(start) + word.charAt(length) == 219) {
StringBuilder sb = new StringBuilder(word);
sb.deleteCharAt(length);
sb.deleteCharAt(start);
newStr = sb.toString();
System.out.println(newStr);
start++;
length--;
break;
} else {
start++;
}
}
if(newStr != null) {
return isAlphaOpp(newStr);
}
return false;
}