I am making a simple calculator, however before I can do that, I need to make an algorithm to convert a user input into a consistent format. The user can input numbers and operators as well as parenthesis. The program has no problem dealing with numbers and operators, but for some unknown reason it throws an error whenever the loop encounters a parenthesis.
I have been attempting to debug the code for the past few hours, but I can't seem to figure out why this is happening?
/** These are the possible operators */
private static final String OPERATORS = "+-/*%^()[]{}";
/** This is an ArrayList of all the discrete
things (operators/operands) making up an input.
This is really just getting rid of the spaces,
and dividing up the "stuff" into manageable pieces.
*/
static ArrayList<String> input = new ArrayList<String>();
public static ArrayList inputCleaner(String postfix) {
StringBuilder poop = new StringBuilder();
String doody = postfix.replace(" ", "");
try {
for (int i = 0; i < doody.length(); i++) {
char c = doody.charAt(i);
boolean isNum = (c >= '0' && c <= '9');
if (isNum) {
poop.append(c);
if (i == doody.length() - 1) {
input.add(poop.toString());
poop.delete(0, poop.length());
}
}
else if (c == '.') {
for (int j = 0; j < poop.length(); j++) {
if (poop.charAt(j) == '.') {
throw new SyntaxErrorException("You can't have two decimals in a number.");
}
else if (j == poop.length() - 1) {
poop.append(c);
}
}
if (i == doody.length() - 1) {
throw new SyntaxErrorException("You can't end your equation with a decimal!");
}
}
else if (OPERATORS.indexOf(c) != -1 && poop.length() != 0) {
input.add(poop.toString());
poop.delete(0, poop.length());
poop.append(c);
input.add(poop.toString());
poop.delete(0, poop.length());
}
else {
throw new SyntaxErrorException("Make sure your input only contains numbers, operators, or parantheses/brackets/braces.");
}
}
return input;
}
catch (SyntaxErrorException exc) {
System.out.println("That didn't work, something was wrong with the syntax.");
return input;
}
}
public static void main(String[] args) {
ArrayList test = new ArrayList();
Scanner f = new Scanner(System.in);
System.out.println("Please insert an argument: \n");
String g = f.nextLine();
test = inputCleaner(g);
for (int z = 0; z < test.size(); z++) {
System.out.println(test.get(z));
}
}
I know my answer is not very good coz I have no good explanation for it(due to brain overheat at work) but this change doesn't throw exception as in your case(might be an answer for you ;) )
Instead of using poop.length() != 0 in the condition I have simply changed it to poop != null and voila... there are no Exceptions now. Comment if you can explain me this.
Related
Method validatePW:
Does not take any parameters and does not return any.
PW policy: must be at least 4 characters long
contain at least one two upper case letters
at least one number.
Throws an exception if PW does not conform to policy.
You should consider reading The Java™ Tutorials, specifically Defining Methods and the chapter on Exceptions as these are basics you should be familiar to complete this assignment.
There are many ways to complete this task, this is only one example:
import java.util.Scanner;
import java.lang.IllegalArgumentException;
public class Q53733706 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Password: ");
String password = input.nextLine();
validatePW(password);
}
// Method validatePW:
static void validatePW(String p){
int upperCase = 0;
int isDigit = 0;
for (int k = 0; k < p.length(); k++) {
if (Character.isDigit(p.charAt(k))) isDigit++;
if (Character.isUpperCase(p.charAt(k))) upperCase++;
}
if ((p.length() < 4) || (upperCase < 1) || (isDigit < 1)){
throw new IllegalArgumentException("Invalid password.");
}
else{
System.out.println("Valid password.");
}
}
}
Adjust the conditional checks to meet your particular "PW policy" as they are unclear as currently stated in the question.
This validatePW method would probably live in a User class that would roughly look something like this:
class User {
private int Id;
private String Password;
// ... other class variables, constructor, getters/setters
public void validatePW() {
int pwLength = this.Password.length();
if (pwLength < 4) {
throw new InvalidArgumentException("Password is too short.");
}
int upperCase = 0;
int lowerCase = 0;
int number = 0;
for (int i = 0; i < pwLength; i++) {
Character c = this.Password.charAt(i);
if (c.isUpperCase()) upperCase++;
if (c.isLowerCase()) lowerCase++;
if (c.isDigit()) number++;
}
if (upperCase == 0) {
throw new InvalidArgumentException("Password requires at least 1 upper case letter.");
}
if (lowerCase == 0) {
throw new InvalidArgumentException("Password requires at least 1 lower case letter.");
}
if (number == 0) {
throw new InvalidArgumentException("Password requires at least 1 number.");
}
}
}
public class Solution {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int tc = Integer.parseInt(br.readLine());//I get Numberformat Exception here
for(int i=0;i<tc;i++) // Even if my inputs are on separate lines
{
String original = br.readLine();
palindrome(original);
}
}
public static void palindrome(String original)
{
String reverse="";
int length = original.length();
for ( int i = length - 1 ; i >= 0 ; i-- )
reverse = reverse + original.charAt(i);
if (original.equals(reverse))
{
System.out.println(0);
}
else
{
char[] org = original.toCharArray();
int len = org.length;
int mid = len / 2;
if(len % 2 == 0)
{
char[] front = new char[mid];
char[] back = new char[mid];
for(int i=0;i<mid;i++)
{
front[i] = org[i];
}
int j=0;
for(int i=len-1;i>=mid;i--)
{
back[j] = org[i];
j++;
while(j > mid)
{
break;
}
}
change(front,back,mid);
}
else
{
char[] front = new char[mid];
char[] back = new char[mid];
for(int i=0;i<mid;i++)
{
front[i] = org[i];
}
int j=0;
for(int i=len-1;i>mid;i--)
{
back[j] = org[i];
j++;
while(j > mid)
{
break;
}
}
change(front,back,mid);
}
}
}
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
count += (back[i] - front[i]);
}
}
System.out.println(count)
}
}
What i try to do here is get an input from the number of test cases say 3 in my first line followed by the test-cases themselves.
sample input :
3
abc
abcba
abcd
Now it has to check if the string is a palindrome if its so it ll print 0
else it breaks the string into two halves front and back and finds the minimum number of changes to make it a palidrome.
here i have also checked if its a odd or even length string if odd i have omitted the middle char.
By changes we can only change 'd' to 'b' not 'b' to 'd'
Once a letter has been changed to 'a', it can no longer be changed.
My code works fine for the above input but it doesnt for some other inputs i dont quiet understand why..
for instance if i give a custom test case as
5
assfsdgrgregedhthtjh
efasfhnethiaoesdfgv
ehadfghsdfhmkfpg
wsertete
agdsjgtukgtulhgfd
I get a Number Format Exception.
Your code works fine here, whithout NumberFormatException: http://ideone.com/QJqjmG
This may not solve your problem, but improves your code...
As first user input you are expecting an integer. You are parsing the String returned by br.readLine() and do not take care of the NumberFormatException parseInt(...) may throw.
Just imagine someone hits space or return key as first input.
So I propose to put a try-catch-block around the parseInt(...). Here is an example how this may look like.
Guys thank you for all your suggestion i just found out why my other test cases weren't working
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
count += (back[i] - front[i]);
}
}
System.out.println(count)
}
This part of my code has to be changed to
public static void change(char[] front,char[] back,int len)
{
int count =0;
for(int i =0;i<len;i++)
{
if(front[i] != back[i] )
{
char great = findGreatest(front[i],back[i]);
if(great == back[i])
{
count += (back[i] - front[i]);
}
else
{
count += (front[i] - back[i]);
}
}
}
System.out.println(count);
}
public static char findGreatest(char first,char second)
{
int great = first;
if(first < second)
{
great = second;
}
return (char)great;
}
Because i get negative values coz of subtracting ascii's which are greater than them and as i have already mentioned i can only do 'd' to 'a' not the other way round.
Thank you for your time guys!
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 8 years ago.
I made a program to search for a certain string in another string and print Word found if the condition is true or print word not found if condition is false
The logic is as follows
enter word
length of word
for searching for letter [1]
if true
then for till length of word match with string to be searched
else continue loop
But I always get word not found no matter what the input, please help me over here!!!
The code is as follows :-
import java.util.Scanner;
class Search_i_String
{
public static void main(String args[])
{
int flag=0;
Scanner Prakhar=new Scanner(System.in);
System.out.println("Enter a String");
String ori=Prakhar.nextLine();
System.out.println("Enter the String to be Searched");
String x=Prakhar.nextLine();
char a[]=new char[ori.length()];
char b[]=new char[x.length()];
for(int i=0;i<ori.length();i++)
{
a[i]=ori.charAt(i);
}
for(int i=0;i<x.length();i++)
{
b[i]=x.charAt(i);
}
for(int i=0;i<a.length;i++)
{
if (a[i]==b[0])
{
for(int j=0;j<b.length;j++)
{
while(flag==0)
{
if(b[j]==a[i])
{
flag=0;
}
else if(b[j] != a[i])
{
flag=1;
}
i++;
}
}
}
}
if (flag==0)
{
System.out.println("Word Found !!!");
}
else
System.out.println("Word not Found");
}
}
P.S. : I know I can use the contains() function but I can as my professor suggests against it and could someone please correct the program I have written, because I could have scavenged off a program from the internet too if I had to, I just wanted to use my own logic
Thank You(again)
while(flag==0)
{
if(b[j]==a[i])
{
flag=0;
}
else if(b[j] != a[i])
{
flag=1;
}
i++;
j++; //add this and try once
}
If you are comparing strings in Java, you have to use equals();
So, stringA.equals(stringB);
Cheers!
Let me get this straight. You're looking for b array inside of a array? "Enter the string to be searched" means that you are searching the other way around, but I'll go with the logic your code seems to follow... Here's a naive way to do it:
if (a[i]==b[0])
{
flag = 0;
for(int j=0;j<b.length;j++)
{
if(b[j] != a[i+j]) // will array index out of bounds when its not foud
{
flag++; // you should probably break out of a named loop here
}
}
if(flag == 0){/*win*/}
}
You're modifying your first search loop with variable i when you don't have to. You can just add i to j. Also, you don't need the while loop inside if i'm understanding your problem. Like others have said, functions exist to do this already. This algorithm isn't even as efficient as it could be.
I know of an algorithm where you check starting in the last character in b instead of the first character in b to begin with. Then you can use that information to move your search along faster. Without resorting to full pseudo code, anyone know what that's called?
The simple way(but not the fastest way) is use double loop to check the chars in strings one by one, pls ref to my code and comments:
public class SearchString {
public static void main(String[] args) {
String a = "1234567890";
String b = "456";
// Use toCharArray() instead of loop to get chars.
search(a.toCharArray(), b.toCharArray());
}
public static void search(char[] a, char[] b) {
if (a == null || b == null || a.length == 0 || b.length == 0) {
System.out.println("Error: Empty Input!");
return;
}
int lenA = a.length, lenB = b.length;
if (lenA < lenB) {
System.out
.println("Error: search key word is larger than source string!");
return;
}
// Begin to use double loop to search key word in source string
for (int i = 0; i < lenA; i++) {
if (lenA - i < lenB) { // If the remaining source string is shorter than key word.
// Means the key word is impossible to be found.
System.out.println("Not found!");
return;
}
// Check the char one by one.
for (int j = 0; j < lenB; j++) {
if (a[i + j] == b[j]) {
if (j == lenB - 1) { // If this char is the last one of key word, means it's found!
System.out.println("Found!");
return;
}
} else {
// If any char mismatch, then right shift 1 char in the source string and restart the search
break;
}
}
}
}
}
You can just use String.contains();
If you really want to implement a method, try this one:
public static void main(String[] args) {
// Initialize values searchedWord and original by user
String original = [get original word from user] ;
String searchedWord = [get searched for word from user];
boolean containsWord = false;
int comparePosition = 0;
for(int i = 0; i < original.length() - searchedWord.length(); i++) {
if(original.charAt(i) == searchedWord.charAt(comparePosition)) {
comparePosition += 1;
} else {
comparePosition = 0;
}
if(comparePosition == searchedWord.length()) {
containsWord = true;
break;
}
}
return containsWord? "Word found!!" : "Word not found.";
}
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();
Hi I need to fix this code to delete characters that repeat immediately in the string. For example: If I type aaabbbcccdeeff, it has to return abcdef at the end. However on the computer in class it returns something of a, "out of range (number)", the number being dependent on how many characters I used. On my mac however it just returns a number like 3 as an output and gives no error message. I am on Eclipse.
Please help, I didn't understand what the professor said and he rarely helps. The code is (somewhat helped by professor):
package firstProgramSimple;
import java.awt.Toolkit;
import java.util.Scanner;
public class SimpleVersion {
public static void main(String[] args) {
Scanner kb = new Scanner(System. in );
System.out.println("Entre String");
String string = kb.nextLine();
//System.out.println(string);
int length = string.length();
for (int i = 1; i < length; i++) {
if (string.charAt(i) != string.charAt(i - 1)) {
System.out.print(i);
} else if (string.charAt(i) != string.charAt(i)) {
System.out.print(i);
}
}
}
}
You need to print string.charAt(i) and not i.
Also, this piece of code is unnecessary since it will always return false:
//string.charAt(i) is always equal to itself
else if ( string.charAt(i) != string.charAt( i )) {
System.out.print(i);
Since you start at i = 1, the char at index 0 will never be printed. Before the for-loop, you should add this line:
System.out.print(string.charAt(0));
You are printing your loop counter and not the value of the char at the position of the counter:
System.out.print(i);
Should be:
System.out.print(string.charAt(i));
You will get an arrayOutOfBoundsException for inputs of size < 2. You might want to add this line once you have the string initialised:
if(string == null || string.length() < 2){
System.out.println(string);
return;
}
Something like this:
public static void main(String[] args) {
Scanner kb = new Scanner(System. in );
System.out.println("Entre String");
String string = kb.nextLine();
//System.out.println(string);
int length = string.length();
if(length < 2) {
System.out.println(string);
return;
}
System.out.print(string.charAt(0));
for (int i = 1; i < length; i++) {
if (string.charAt(i) != string.charAt(i - 1)) {
System.out.print(string.charAt(i));
}
}
}
Just replace your for loop like bellow:
System.out.print(string.charAt(0));
for (int i = 1; i < length; i++) {
if (string.charAt(i) != string.charAt(i - 1)) {
System.out.print(string.charAt(i));
}
}
The idea is, print the beginning character first, then print the character at i th position, only if its different then its previous character. Simple!