I am currently coding a pig latin translator that breaks down strings into words and then translate them. If any of the first four letters of a word are consonsants, it will move those letters to the back and add an "ay." If the word begins with a vowel, add "way" to the end of the word.
Apparently my pig latin translator code does not output a translated string, but instead it gives me original english words broken down in several different parts. I am a little stuck on what to go next, if anyone can help me diagnose the problem then it will be great. Thanks!
public class WL10Driver {
public String convertToPig(String english){
String pigLatin = "";
int pigLatinWord = 0;
String vowel = "[aeiouAEIOU]";
for(int i = 0; i<english.length(); i++){
char let = english.charAt(i);
int ind = vowel.indexOf(let);
if(ind > -1){
if(i == 0){
return english+"yay";
}
else{
String start = english.substring(0,i);
String end = english.substring(i);
return end+start+"ay";
}
}
}
return english+"ay";
}
}
It seems like the problem is with the calling method. I made it show JOptionPane.showMessageDialog(null,english);.
What should I make JOptionPane show instead?
boolean isVowel(char ch) {
return "aeiouAEIOU".contains("" + ch);
}
public String convertToPig(String english) {
if (english == null) return null;
for (int i = 0; i < Math.min(english.length(), 4); i++) {
char ch = english.charAt(i);
if (i == 0 && isVowel(ch)) return english + "way";
if (!isVowel(ch)) {
String tmp = "";
if (i < english.length() - 1) tmp = english.substring(i + 1);
return english.substring(0, i) + tmp + ch + "ay";
}
}
return english;
}
Related
I am currently in a Intro to Computer Language class and everyone few lessons I have to develop some minimal programs (we are given 5 different prompts and have to pick three of them to complete). Due to time, I moved on and completed a different program, but I still want to understand what is going wrong with this one.
It is supposed to translate a given phrase into Pig Latin using for loops and different methods (as broken down in their template, which I cannot change, though I know there is a more efficient way). I can get the words in the phrases to translate, but when I print out the array (either by converting it to a string or running a for loop to print each element out separately) some of the elements only print the reference code. Could someone tell me what's going on? Below is the code and then a sample of a few print outs.
import java.util.Arrays;
import java.util.Scanner;
public class PigLatin {
public static void main (String[] args){
Scanner scnr = new Scanner(System.in);
String userWord;
userWord = scnr.nextLine();
userWord = userWord.toLowerCase();
String[] wordArry = userWord.split(" ");
print(wordArry);
}
public static String[] translate(String[] words){
String[] pigLatin = new String[words.length];
for (int i = 0; i < words.length; ++i) {
if (isVowel(words[i].charAt(0)) == true){
pigLatin[i] = words + "ay";
}
else if (words[i].charAt(0) == 'y') {
pigLatin[i] = words[i].substring(findFirstVowel(words[i]), words[i].length()) + words[i].substring(0, findFirstVowel(words[i])) + "ay";
}
else {
pigLatin[i] = words[i].substring(findFirstVowel(words[i]), words[i].length()) + words[i].substring(0, findFirstVowel(words[i])) + "ay";
}
}
return pigLatin;
}
public static int findFirstVowel(String s){
char[] vowList = {'a','e','i','o','u','y'};
for (int i = 1; i < s.length(); ++i) {
for (int j = 0; j < vowList.length; ++j) {
if (s.charAt(i) == vowList[j]) {
return i;
}
}
}
return -1;
}
public static boolean isVowel(char c){
boolean vowel = false;
char[] vowList = {'a','e','i','o','u'};
for (int i = 0; i < vowList.length; ++i) {
if (c == vowList[i]) {
vowel = true;
}
}
return vowel;
}
public static void print(String[] words){
String[] newArry = new String[words.length];
for (int i = 0; i < words.length; ++i) {
newArry[i] = words[i];
}
String finalPrint = Arrays.toString(translate(newArry));
finalPrint = finalPrint.replace("[", "");
finalPrint = finalPrint.replace(",", "");
finalPrint = finalPrint.replace("]", "");
System.out.println(finalPrint);
}
}
Here are some of the printed responses:
Input: the rain in spain stays mainly in the plain
Output: ethay ainray [Ljava.lang.String;#17c68925ay ainspay aysstay ainlymay [Ljava.lang.String;#17c68925ay ethay ainplay
Expected: ethay ainray inay ainspay aysstay ainlymay inay ethay ainplay
Input: you should have stayed with the soup question
OutPut: ouyay ouldshay avehay ayedstay ithway ethay oupsay uestionqay
This print's out correctly
Input: the stuff that dreams are made of
Output: ethay uffstay atthay eamsdray [Ljava.lang.String;#17c68925ay ademay [Ljava.lang.String;#17c68925ay
Expected: ethay uffstay atthay eamsdray areay ademay ofay
I cannot find an answer as to why this is happening. Please let me know if you need any additional information. Thanks!
You have a mistake (typo, likely) in this block:
if (isVowel(words[i].charAt(0)) == true){
pigLatin[i] = words + "ay";
}
It should be instead (note you don't need to compare boolean value with true):
if (isVowel(words[i].charAt(0))) {
pigLatin[i] = words[i] + "ay";
}
Also, you don't need to copy your array in print() method - translate() doesn't modify input array in any way.
Finally, instead of replacing the output of Arrays.toString, you could use String.join, so your print method would look like:
public static void print(String[] words){
System.out.println(String.join(" ", translate(words)));
}
pigLatin[i] = words + "ay";
This line. You are appending string to an array. Change it to:
pigLatin[i] = words[i] + "ay";
Side note 1:
for (int i = 0; i < words.length; ++i) {
newArry[i] = words[i];
}
This loop can be changed to:
System.arraycopy(words, 0, newArry, 0, words.length);
Side note 2:
Splitting on "\\s+" is better. It also takes care of multiple spaces.
Side note 3:
if (isVowel(words[i].charAt(0)) == true) {
This can be simplified as:
if (isVowel(words[i].charAt(0))) {
Side note 4:
for (char value : vowList) {
if (c == value) {
vowel = true;
break;
}
}
Using break for slightly better performance. Also, using foreach loop.
Final side note:
finalPrint = finalPrint.replace("[", "")
.replace(",", "")
.replace("]", "");
Chaining of replace calls.
I will ask this again. I have this problem which is to create a program that would read a string input from the user (sentence or word). And the Nth number (from the user) will turn into upper case and the rest will be in lowercase.
Example:
string = "good morning everyone"
n = 2
Output = gOod mOrning eVeryone
for (int x = 0; x < s.length(); x++)
if (x == n-1){
temp+=(""+s.charAt(x)).toUpperCase();
}else{
temp+=(""+s.charAt(x)).toLowerCase();
}
s=temp;
System.out.println(s);
}
Output: gOod morning everyone
I know what you want to happen - but you didn't phrase your question very well. The only part your missing is iterating through every word in the sentence. If you asked "how do I apply a function on every word in a String" you likely would have gotten a better response.
This is a bit sloppy since it adds a trailing " " to the end - but you could fix that easily.
public class Test {
static String test = "This is a test.";
public static void main(String[] args) {
String[] words = test.split(" ");
String result = "";
for (String word : words) {
result += nthToUpperCase(word, 2);
result += " ";
}
System.out.println(result);
}
public static String NthToUpperCase(String s, int n) {
String temp = "";
for (int i = 0; i < s.length(); i++) {
if (i == (n-1)) {
temp+=Character.toString(s.charAt(i)).toUpperCase();
} else {
temp+=Character.toString(s.charAt(i));
}
}
return temp;
}
}
You can do this with two for loops. Iterate over each word and within the iteration iterate over each character.
toUpperCase(2, "good morning everyone");
private static void toUpperCase(int nth, String sentence) {
StringBuilder result = new StringBuilder();
for(String word : sentence.split(" ")) {
for(int i = 0; i < word.length(); i++) {
if(i > 0 && i % nth - 1 == 0) {
result.append(Character.toString(word.charAt(i)).toUpperCase());
} else {
result.append(word.charAt(i));
}
}
result.append(" ");
}
System.out.println(result);
}
gOoD mOrNiNg eVeRyOnE
The purpose of this method is replace all but the first and last letters of each word with "_". I'm a complete novice when it comes to coding, so I'm certain my code is fairly incorrect. I think where my code starts functioning improperly is with the while loop.
EDIT: How do I make this method without using arrays or extra methods, like the split method?
public static String blankWords(String s1) {
StringBuilder sb = new StringBuilder();
if(s1.length() > 2) {
sb.append(s1.charAt(0));
for(int x = 1; x < s1.length() - 1; x = x + 1) {
char y = ' ';
while(y != s1.charAt(x)) {
sb.append("_");
x = x + 1;
}
}
sb.append(s1.charAt(s1.length() - 1));
return sb.toString();
}
return s1;
}
What my code is outputting:
HW2.blankWords("This is a Test.")
java.lang.StringIndexOutOfBoundsException: String index out of range: 15
at java.lang.String.charAt(Unknown Source)
at HW2.blankWords(HW2.java:73)
What my code should output:
HW2.blankWords("This is a Test.")
"T__s is a T__t."
Here is a pretty simple solution:
class Scratch {
public static void main(String[] args) {
System.out.println(blankWords("My name is sam orozco"));
}
public static String delim = "_";
public static String blankWords(String s1) {
// this split arg on one or more space
String[] words = s1.split("\\s+");
StringBuilder response = new StringBuilder();
for (String val : words) {
val = convertWord(val);
response.append(val).append(" ");
}
return response.toString().trim();
}
public static String convertWord(String val) {
int len = val.length();
StringBuilder bldr = new StringBuilder();
int index = 0;
for (char ch : val.toCharArray()) {
if (index == 0 || index == len - 1) {
bldr.append(ch);
} else {
bldr.append(delim);
}
index++;
}
return bldr.toString();
}
}
You can do this using a StringTokenizer that will extract words based on a list of delimiters. Since you want to keep those delimiters in the output, you'll instruct the tokenizer to return them as tokens:
String blankWords(String s) {
// build a tokenizer for your string, listing all special chars as delimiters. The last argument says that delimiters are going to be returned as tokens themselves (so we can include them in the output string)
StringTokenizer tokenizer = new StringTokenizer(s, " .,;:?!()[]{}", true);
// a helper class to build the output string; think of it as just a more efficient concat utility
StringBuilder sb = new StringBuilder();
while (tokenizer.hasMoreTokens()) {
String blankWord = blank(tokenizer.nextToken());
sb.append(blankWord);
}
return sb.toString();
}
/**
* Replaces all but the first and last characters in a string with '_'
*/
private String blank(String word) {
// strings of up to two chars will be returned as such
// delimiters will always fall into this category, as they are always single characters
if (word.length() <= 2) {
return word;
}
// no need to iterate through all chars, we'll just get the array
final char[] chars = word.toCharArray();
// fill the array of chars with '_', starting with position 1 (the second char) up to the last char (exclusive, i.e. last-but-one)
Arrays.fill(chars, 1, chars.length - 1, '_');
// build the resulting word based on the modified array of chars
return new String(chars);
}
Here is the contents of a test that validates this implementation, using TestNG:
#Test(dataProvider = "texts")
public void testBlankWords(String input, String expectedOutput) {
assertEquals(blankWords(input), expectedOutput);
}
#DataProvider
public Object[][] texts() {
return new Object[][] {
{"This is a test.", "T__s is a t__t."},
{"This one, again, is (yet another) test!", "T__s o_e, a___n, is (y_t a_____r) t__t!"}
};
}
The main drawback of this implementation is that StringTokenizer requires you to list all the delimiters by hand. With a more advanced implementation, you can consider a delimiter any character that returns false for Character.isAlphabetic(c) or however you decide to define your non-word chars.
P.S.
This could be a "more advanced implementation", as I mentioned above:
static String blankWords(String text) {
final char[] textChars = text.toCharArray();
int wordStart = -1; // keep track of the current word start position, -1 means no current word
for (int i = 0; i < textChars.length; i++) {
if (!Character.isAlphabetic(textChars[i])) {
if (wordStart >= 0) {
for (int j = wordStart + 1; j < i - 1; j++) {
textChars[j] = '_';
}
}
wordStart = -1; // reset the current word to none
} else if (wordStart == -1) {
wordStart = i; // alphabetic characters start a new word, when there's none started already
} else if (i == textChars.length - 1) { // if the last character is aplhabetic
for (int j = wordStart + 1; j < i; j++) {
textChars[j] = '_';
}
}
}
return new String(textChars);
}
No while loop necessary!
Look ahead by 1 character to see if it's a space, or if the current character is a space, in that case you append it. Otherwise you make sure to add the next character (skipNext false).
Always add the last character
public static String blankWords(String s1) {
StringBuilder sb = new StringBuilder();
if(s1.length() > 2) {
Boolean skipNext = false;
for(int x = 0; x < s1.length() - 1; x = x + 1) {
if(s1.charAt(x) == ' ' || s1.charAt(x + 1) == ' ') {
sb.append(s1.charAt(x));
skipNext = false;
}
else {
if(skipNext) {
sb.append('_');
}
else {
sb.append(s1.charAt(x));
skipNext = true;
}
}
}
sb.append(s1.charAt(s1.length() - 1));
return sb.toString();
}
return s1;
}
For the more advanced programmer, use regular expression.
public static String blankWords(String s1) {
return s1.replaceAll("\\B\\w\\B", "_");
}
This correctly keeps the final t, i.e. blankWords("This is a Test.") returns "T__s is a T__t.".
I'm trying to convert a sentence to pig latin but can't seem to get the correct output to work. For example the input
the rain in spain stays mainly in the plain yields an output of ethay ethay ethay with my current code whereas the expected output is ethay ainray inay ainspay aysstay ainlymay inay ethay ainplay
For those unfamiliar, the basic rules of pig latin are:
If the word begins with a consonant, take the beginning consonants up until the first vowel and move them to the end of the word. Then append ay at the very end. (so cricket would become icketcray)
If the word begins with a vowel, simply add ay to the end. (apple would become appleay)
If y is the first letter in the word, treat it as a consonant, otherwise it is used as a vowel. (young would become oungyay and system would become ystemsay)
My code is as follows:
import java.util.Scanner;
public class PigLatin{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String line = scan.next();
String piglatin = translateSentence(line);
System.out.println(piglatin);
}
public static String translateSentence(String line){
for (int i =0; i < line.length(); i++ ) {
char c = line.charAt(i);
//for loop to analyze each word
if (Character.isAlphabetic(c)) {
//if (i <='a' || i<='A' || i>='z' || i>='Z'){
String piglatin = translateword(line);
return piglatin;
}
}
return line;
}
public static String translateword(String line) {
Scanner scan = new Scanner(System.in);
int position = firstVowel(line);
String words = "";
String output = "";
for(int i = 0; i<line.length();i++){
words = "";
if (firstVowel(line) == 0) {
words = line + "-way";
} else if (firstVowel(line) == -1) {
words = line + "";
} else {
String first = line.substring(position);
String second = line.substring(0,position) + "ay";
words = first + second;
}
output = output + " " + words;
//words = "";
}
return output;
}
public static int firstVowel(String line) {
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == 'a' || line.charAt(i) == 'e'
|| line.charAt(i) == 'i' || line.charAt(i) == 'o'
|| line.charAt(i) == 'u') {
return i;
}
}
return -1;
}
}
Any help is greatly appreciated, thank you.
first write a separate function to get list of words from line
public String[] getWords(String line) {
String list[]=new String[100];
int j=0;
int end;
end=line.indexOf(' ');
while (end!=-1) {
list[j]=line.substring(0, end);
line=line.substring(end+1,line.length());
j++;
end=line.indexOf(' ');
}
list[j]=line.substring(0,line.length());
return list;
}
then modify your translate line to call translate word multiple times, each time pass a single word.
Assuming your translateWord() returns a single correctly translated word. translateLine change in the following way:
if (Character.isAlphabetic(c)) {
String wordList[]=getWords(line);
String piglatin="";
int i=0;
while(!line[i].equals("")) {
piglatin = piglatin+translateword(word[i]);
i++;
}
return piglatin;
}
Trying to write a code that makes a string become altcase (ie. "hello" becomes "HeLlO". I borrowed code from another question on this forum that asked for something similar (Java Case Switcher) However, the code only switched the casing of a letter instead of having a capital letter (first), then lowercase letter, etc. pattern.
What I have so far:
public String altCase(String text)
{
String str = "";
for (int i = 0; i <= text.length(); i++)
{
char cA = text.charAt(i);
if (text.charAt(0).isUppercase)
{
str += Character.toLowerCase(cA);
}
if (text.charAt(0).isLowercase)
{
str += Character.toUpperCase;
}
if(i != 0 && Character.isUpperCase(cA))
{
if (text.charAt(i)-1.isUpperCase || text.charAt(i)+1.isUpperCase)
{
str += Character.toLowerCase(cA);
}
else
{
str += cA;
}
}
if(i != 0 && Character.isLowerCase(cA))
{
if (text.charAt(i)-1.isLowerCase || text.charAt(i)+1.isLowerCase)
{
str += Character.toUpperCase(cA);
}
else
{
str += cA;
}
}
}
return str;
}
I'm still relatively new to coding in general so please excuse my inefficiencies, as well as any headaches I might induce from the lack of experience in my coding. I cannot tell where I am going wrong except maybe when I typed "text.charAt(i)-1.isLowerCase" as the statement seems a bit illogical, but I am lost in terms of trying to come up with something else that would accomplish the same thing. Or is my error completely elsewhere? Thanks for any help in advance.
The modulus operator could take you a long way here...
StringBuilder rslt = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
switch (i % 2) {
case 0:
rslt.append(Character.toUpperCase(c));
break;
case 1:
rslt.append(Character.toLowerCase(c));
break;
}
}
return rslt.toString();
If I truly understand what you want to get is that:
Get a string, change it in a format of AbCdEfG.... and so on.
There is more simple solution.
Get a string and with for loop, for every character, change character size depending on position in string, for i%2 == 0 upper case, and i%2 == 1 lower case.
public String altCase(String text)
{
String str = "";
for (int i = 0; i < text.length(); i++)
{
char cA = text.charAt(i);
if (i%2 == 0)
{
str += Character.toUpperCase(cA);
}
else
{
str += Character.toLowerCase(cA);
}
}
return str;
}
I would start with a StringBuilder (a mutable character sequence) of text.toLowerCase(); then set the characters at even indices to their capital equivalents (and your method doesn't appear to depend on instance state, so it might be static). Something like,
public static String altCase(String text) {
StringBuilder sb = new StringBuilder(text.toLowerCase());
for (int i = 0; i < text.length(); i += 2) {
sb.setCharAt(i, Character.toUpperCase(sb.charAt(i)));
}
return sb.toString();
}
IntStream.range(0, s.length()).mapToObj(i -> i % 2 == 0 ?
Character.toUpperCase(s.charAt(i)) :
Character.toLowerCase(s.charAt(i)))
.map(String::valueOf)
.collect(Collectors.joining());