I'm doing a homework task that is:
Find a unique vowel in the string that is preceded by a consonant, and this consonant is preceded by a vowel.
Example: "eeaaAOEacafu"
Result is: u
What i already did:
Main.class
public class Principal {
public static void main(String[] args) {
// TODO Auto-generated method stub
Stream str = new Stream();
str.setText("eeaaAOEacafu");
System.out.println(str.returnChar(str.getVowel()));
}
Stream.class
public class Stream {
String text;
char vowel;
public String getText() {
return texto;
}
public void setText(String text) {
this.text = text;
}
public char getVowel() {
return vowel;
}
public void setVowel(char vowel) {
this.vowel = vowel;
}
public boolean isVowel(String str) {
str = str.toLowerCase();
for(int i=0; i<str.length(); i++) {
char c = str.charAt(i);
if(c=='a' || c=='e' || c=='i' || c=='o'|| c=='u') {
return true;
} else {
return false;
}
}
return false;
}
public char returnChar(String str) {
char last;
char next;
char result = '0';
int j=1;
for(int i=0; i<str.length(); i++) {
last = str.charAt(i-1);
next = str.charAt(i+1);
j++;
if(!vogal(str.charAt(i))) {
if(vogal(last) && vogal(next)) {
result = next;
}
}
}
this.setVowel(result);
return result;
} }
This returns: String index out of range: -1
This j=1, was to fix this -1 out of range. It fix but i got new one: out of range 11 because of the next.
The thing is: I have to use pure java and no API.
Can you guys help me?
use regular expressions for the test and locating the character
[aeiouAEIOU][bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ]([aeiouAEIOU])
Use a String as a cheap map to keep track of which vowels you've already seen. Also, keep a count of how many consecutive consonants you've encountered. Then, when you hit a vowel that you haven't seen before preceded by a single consonant you've found your answer.
public static void main(String[] args)
{
String s = "eeaaAOEacafu".toLowerCase();
int consCount = 0;
String seenVowels = "";
for(int i=0; i<s.length(); i++)
{
char c = s.charAt(i);
if("aeiou".indexOf(c) >= 0)
{
if(seenVowels.indexOf(c) == -1)
{
if(consCount == 1)
{
System.out.println("Result: " + c);
break;
}
seenVowels += c;
}
consCount = 0;
}
else consCount++;
}
}
Output:
Result: u
The above works if we take 'unique' to mean that we haven't seen the vowel before. If the vowel has to be unique within the input string then things are a little more complicated. Now we have to keep track of each vowel that meets the original criteria, but remove the solution if we subsequently encounter another instance of the same vowel.
Here's some code to illustrate:
public static void main(String[] args)
{
String s = "afuxekozue".toLowerCase();
int consCount = 0;
String seenVowels = "";
String answer = "";
for(int i=0; i<s.length(); i++)
{
char c = s.charAt(i);
if("aeiou".indexOf(c) >= 0)
{
if(seenVowels.indexOf(c) == -1)
{
if(consCount == 1)
{
answer += c;
}
seenVowels += c;
}
else if(answer.indexOf(c) >= 0)
{
answer = answer.replaceAll(String.valueOf(c), "");;
}
consCount = 0;
}
else consCount++;
}
if(answer.length() > 0)
System.out.println("Result: " + answer.charAt(0));
}
Output:
Result: o
Related
I solved a task concerning finding the first non-repeating character. For example, given the input "apple" the answer would be "a", the first character that isn't repeated. Even though "e" is not repeated it's not the first character. Another example: "lalas" answer is "s".
public static char firstNonRepeatingCharacter(String input) {
boolean unique;
int count = input.length();
char[] chars = input.toCharArray();
for (int i = 0; i < input.length(); i++) {
unique = true;
for (int j = 0; j < input.length(); j++) {
count--;
char c = chars[i];
if (i != j && c == chars[j]) {
unique = false;
break;
}
}
if (unique) {
return input.charAt(i);
}
}
return (0);
}
I want to simplify this code due to the nested loop having O(n2) complexity. I have been looking at the code trying to figure out if i could make it any faster but nothing comes to mind.
Another way is to find the first and last indexOf the character. If both are same then it is unique.
public static char firstNonRepeatingCharacter(String input) {
for(char c:input.toCharArray())
if(input.indexOf(c) == input.lastIndexOf(c))
return c;
return (0);
}
EDIT:
Or with Java 8+
return (char) input.chars()
.filter(c -> input.indexOf(c) == input.lastIndexOf(c))
.findFirst().orElse(0);
O(n) is better.
Use an intermedian structure to handle the number of repetitions.
public static char firstNonRepeatingCharacter(String input) {
boolean unique;
int count = input.length();
char[] chars = input.toCharArray();
for (int i = 0; i < input.length(); i++) {
unique = true;
for (int j = 0; j < input.length(); j++) {
count--;
char c = chars[i];
if (i != j && c == chars[j]) {
unique = false;
break;
}
}
if (unique) {
return input.charAt(i);
}
}
return (0);
}
public static char firstNonRepeatingCharacterMyVersion(String input) {
Map<String,Integer> map = new HashMap();
// first iteration put in a map the number of times a char appears. Linear O(n)=n
for (char c : input.toCharArray()) {
String character = String.valueOf(c);
if(map.containsKey(character)){
map.put(character,map.get(character) + 1);
} else {
map.put(character,1);
}
}
// Second iteration look for first element with one element.
for (char c : input.toCharArray()) {
String character = String.valueOf(c);
if(map.get(character) == 1){
return c;
}
}
return (0);
}
public static void main(String... args){
System.out.println(firstNonRepeatingCharacter("potatoaonionp"));
System.out.println(firstNonRepeatingCharacterMyVersion("potatoaonionp"));
}
See this solution. Similar to the above #Lucbel. Basically, using a LinkedList. We store all non repeating. However, we will use more space. But running time is O(n).
import java.util.LinkedList;
import java.util.List;
public class FirstNone {
public static void main(String[] args) {
System.out.println(firstNonRepeatingCharacter("apple"));
System.out.println(firstNonRepeatingCharacter("potatoaonionp"));
System.out.println(firstNonRepeatingCharacter("tksilicon"));
}
public static char firstNonRepeatingCharacter(String input) {
List<Character> charsInput = new LinkedList<>();
char[] chars = input.toCharArray();
for (int i = 0; i < input.length(); i++) {
if (charsInput.size() == 0) {
charsInput.add(chars[i]);
} else {
if (!charsInput.contains(chars[i])) {
charsInput.add(chars[i]);
} else if (charsInput.contains(chars[i])) {
charsInput.remove(Character.valueOf(chars[i]));
}
}
}
if (charsInput.size() > 0) {
return charsInput.get(0);
}
return (0);
}
}
private static int Solution(String s) {
// to check is values has been considered once
Set<String> set=new HashSet<String>();
// main loop
for (int i = 0; i < s.length(); i++) {
String temp = String.valueOf(s.charAt(i));
//rest of the values
String sub=s.substring(i+1);
if (set.add(temp) && !sub.contains(temp)) {
return i;
}
}
return -1;
}
I'm trying to count the number of times a letter appears in a string (aabcccccaaa) and placing the number of times that it does into a new string along with the corresponding letter. The problem's that I get a StringIndexOutOfBoundsException.
I kind of have a clue why but I think it's mainly because my logic is flawed with this problem.
Am I on the right track? What am I doing wrong and how can I fix it?
For example, the output should be a2b1c5a3
Here's my code:
public class Problem {
public static void main(String []args) {
String str = "aabcccccaaa";
System.out.println(compressBad(str));
}
public static String compressBad(String str) {
int countConsecutive = 0;
String compressedString = "";
for(int i = 0; i < str.length(); i++) {
if(str.charAt(i) != str.charAt(i + 1)) {
countConsecutive++;
compressedString += "" + str.charAt(i) + countConsecutive;
countConsecutive = 0;
}
}
return compressedString;
}
}
This line str.charAt(i + 1) will read out of bounds when i is the last index, i+1 is now out of bounds.
For what it's worth, here's what I would do :
public static String compressBad(final String str) {
if (str == null || str.length() < 0) {
return "";
}
int countConsecutive = 0;
StringBuilder sb = new StringBuilder();
char previousLetter = str.charAt(0);
for (char c : str.toCharArray()) {
if (c == previousLetter) {
countConsecutive++;
} else {
sb.append(previousLetter).append(countConsecutive);
previousLetter = c;
countConsecutive = 1;
}
}
sb.append(previousLetter).append(countConsecutive);
return sb.toString();
}
What am I doing wrong? When I run my program it only prints some of my string, and it does not capitalize the first letter..
public class StringTraining extends ConsoleProgram {
public void run() {
String str = "halOOlOO";
capitalize(str);
}
private String capitalize(String str){
String s = "";
char ch;
for(int i = 0;i<str.length();i++) {
ch = str.charAt(i);
if(i==0 && Character.isLowerCase(ch)) {
Character.toUpperCase(ch);
s += ch;
i++;
} else {
Character.toLowerCase(ch);
s += ch;
i++;
}
}
println(s);
return s;
}
}
You should not increment i again in the loop since it will be done automatically in the signature of the loop.
You have to assign Character.toUpperCase(ch) to the String or append it.
I'd suggest you use a StringBuilder when looping to build a String object
Correction
private static String capitalize(String str){
StringBuilder s = new StringBuilder();
char ch;
for(int i = 0;i<str.length();i++) {
ch = str.charAt(i);
if(i==0 && Character.isLowerCase(ch)) {
s.append(Character.toUpperCase(ch));
} else {
s.append(Character.toLowerCase(ch));
}
}
return s.toString();
}
Output
Halooloo
You need to assign the variable ch to the upper or lower case value:
for(int i = 0;i<str.length();i++) {
ch = str.charAt(i);
if(i==0 && Character.isLowerCase(ch)) {
ch = Character.toUpperCase(ch);
s += ch;
} else {
ch = Character.toLowerCase(ch);
s += ch;
}
}
Remove some unnecessary codes from your capitalize(String) method such as i++ and use
s += String.valueOf(Character.toUpperCase(ch)); code instead of
Character.toUpperCase(ch);
s += ch;
Complete capitalize(String) method
private static String capitalize(String str) {
String s = "";
char ch;
for (int i = 0; i < str.length(); i++) {
ch = str.charAt(i);
if (i == 0 && Character.isLowerCase(ch)) {
s += String.valueOf(Character.toUpperCase(ch));
} else {
s += String.valueOf(Character.toLowerCase(ch));
}
}
println(s);
return s;
}
toLowerCase() return a string, you need to assign it to ch.
You also need to increment your i only one time (in the for, and not in the if)
Change your capitalize(String str) method like this -
private static String capitalize(String str) {
char[] chars = str.toCharArray();
String caps = chars[0]+"";
caps = caps.toUpperCase();
String output = caps;
for(int i=1;i<chars.length;i++) {
output = output + chars[i];
}
return output;
}
Output :
HalOOlOO
import java.util.Scanner;
public class StringWithoutDuplicate {
public static void stringWithoutDuplicate(String s1)
{
int n = s1.length();
int i = 0;
while(i<n)
{
if(s1.charAt(i) == s1.charAt(i+1))
{
if(s1.charAt(i) == s1.charAt(n-1))
{
System.out.println(s1.charAt(i));
}
i++;
}
else if(s1.charAt(i) != s1.charAt(i+1))
{
if(s1.charAt(i) == s1.charAt(n-1))
{
System.out.println(s1.charAt(i));
}
System.out.println(s1.charAt(i));;
i++;
}
}
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
s.useDelimiter(",");
String s1 = s.next();
System.out.println(s1);
stringWithoutDuplicate(s1);
}
}
The code is giving the output but with an exception
please tell me the error in my code and ways to correct it.
I don't want to change the logic of my code so kindly solve it using this logic only.
ERROR:
Range of your i is from 0 to (n-1) which is same as the range of index of characters in your string s1. This is correct.
But during the last iteration of your while loop, i = n-1
At this point, s1.charAt(i+1) becomes same as s1.charAt(n). This should be giving an error.
public static void stringWithoutDuplicate(String s1) {
int prev = -1;
for (int i = 0, size = s1.length(); i < size; ++i) {
char c = s1.charAt(i);
if (c != prev) {
System.out.println(c);
prev = c;
}
}
}
I have to tokenize a boolean expression into an array list called tokens while considering primes. (apostrophes)
My code works for inputs such as
A'+B: [A', B]
B'+A: [B', A]
A'B'C+A: [A'B'C, A]
AB+C'D: [AB,C'D]
A'B'C: [A', B', C]
but will not work whenever the last character of the input string is an apostrophe such as:
A'+B'
AB+C'
A'B'C'
public static void tokenize(String expression)
{
String current = "";
String temp = "";
int counter=0;
for(int i = 0; i < expression.length(); i++)
{
char c = expression.charAt(i);
if(counter==0 && (c=='+' || c=='*'))
{
tokens.add(current);
limit++;
current = "";
if(tempUsed)
{
tokens.add(temp);
limit++;
tempUsed=false;
}
continue;
}
else if(c=='(')
{
counter++;
}
else if(c==')')
{
if(i+1<expression.length())
{
if(expression.charAt(i+1)=='\'')
{
temp = "("+current+")\'";
tempUsed = true;
}
}
counter--;
}
if(c!='(' && c!=')')
{
if(!(tempUsed && c=='\''))
current += c;
}
}
tokens.add(current);
limit++;
}
Any thoughts? Any help will greatly be appreciated. Thank you!