Infix to postfix with real numbers (included negative ones) - java

I made an app that allows the transformation from infix to postfix expressions for real numbers (included negative ones). It works perfectly except for the case when I put a negative number on the first and then I put minus another number. For example -1 - 2 or -2 + 8 - 9. It shows -1-2 and -2 8-9 +. It should be -1 2 - and -2 8 + 9 -. It's certainly a problem when the sign is -. This is a part of my code when the input char is '-'.
for (int j = 0; j < input.length(); j++) {
char ch = input.charAt(j);
if (ch == '-') {
if ((ch == input.charAt(0)) || (input.charAt(j - 1) == '(')
|| (input.charAt(j - 1) == '-'))
temp = temp + ch;
else {
output = output + temp + " ";
temp = "";
gotOper(ch, 1);
}
}
else if ..
...
}
When the app find - and it's on the first of the input or after ( or after - so it's a negative number and I put it into a temporary variable. When it's between 0 and 9 or it's ., the same thing. else, when it's and operand, I put which is in temp in output and I do operations with the Stack. I can't show the whole code, it's very long! Can someone help me please?
EDIT: I did this input = input.replaceAll("\\s+", ""); to remove all whitespaces

This part (ch == input.charAt(0)) in the second if-statement should be replaced with (j == 0). Otherwise, it will return true whenever ch == '-' if the input also starts with a '-'.

Related

restore original word after Caesar Cipher shifting

I write a func of Caesar Cipher.
So after I shift a sentence, I want also shift back to the original sentence.
For now it works only for one direction, when I shift with natural positive number, but when I try to do this with negative number, it goes on to value less than 97 of ascii lowercase letters.
I give an example:
word: java
key = 10
output: tkfk
Now I want to shift back, to restore my word from tkfk to java.
key = -10
output: ja\a
Instead of v it put \
I know its happens couse from f to minus 10 from ascii table is the letter '\' and I want the letter v.
I think I need to manipulate this line, but I dont know how, I'm a little bit stuck and I don't have an idea what to do.
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97)
My method: (little bit long)
public static void MakeCipherText(String[] text, int key) {
int index =0;
if (key > 0) {
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in every itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
} else { // key is negetive number
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in evry itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
}
}
Any suggestion?
As the comments suggest you should really check your code again this will also help you to be a better programmer. But anyway you think too complicated.
If you check your else part that is the exact copy of the if part. And that is no wonder. To decode Caesar cipher you encode it basically again with the right key to encode.
For example:
If you encode it with A => B or in this example with 1:
test--> uftu
so how can we decode uftu back?
When we shift it with B=>A or in this case with 25.
uftu --> test
So in your requirement you want if you put -1 that you decode text that was encoded with 1 before.
So basically we have to find a method to map -1 to 25, -2 to 24 and so on.
And the key function is: modulo
-2 % 26 => 24
-1 % 26 => 25
...
In addition you can even now put numbers bigger than 26 because:
500 % 26 => 6
-500 % 26 => 20
and because 2 % 26 => 2 you don't even need that if clause. Your code looks like this in the end:
public static void MakeCipherText(String[] text, int key) {
int index =0;
key = (((key % 26) + 26) % 26); // See below for explanation of this weird modulo
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in every itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
}
Never forget to use functions and don't use duplicate code. Bad style and error prone. The solution is quite easy if you think it through.
Information weird modulo function
You see I use a weird modulo function. Because in Java % don't calculate the modulo but the remainder. (Different then in Python).
So to get the "true" modulo in Java we have to use this weird trick:
Reference: What's the difference between “mod” and “remainder”?
key = (((key % 26) + 26) % 26);

Split text from Right to left based on the input passed

i have string and im trying to split the text and format it
Input is 67.9200 2 3
Ouput will be 6 7.9 200
Rules
1) split from the right to left based on the digits passed.
2) when split contains "." then add 1 to it .
3) if anything is remaining will just show in the front.
Example
67.9200 2 3
1. 3 (digits) -> will take the last 200
2. 2 (digits) -> will take 7.9 (since it has ".")
3. 6 -> Remaining will show (6)
Any suggestion or solutions will be greatly appreciated
You can start scanning the string from right and keep storing them in a StringBuilder till you have captured n1(3) characters and whenever you encounter a dot, skip the count and once n1 becomes zero, append a space and move on. Apply same strategy for n2(2) and after you have the final string in StringBuilder, just reverse the string and you get your output. Here is a sample program.
public static void main(String[] args) {
String str = "67.9200";
int n1 = 2;
int n2 = 3;
StringBuilder sb = new StringBuilder();
for (int i = str.length() - 1; i >= 0; i--) {
if (n2 > 0) {
char c = str.charAt(i);
sb.append(c);
if (c != '.') {
n2--;
if (n2 == 0) {
sb.append(" ");
}
}
} else if (n1 > 0) {
char c = str.charAt(i);
sb.append(c);
if (c != '.') {
n1--;
if (n1 == 0) {
sb.append(" ");
}
}
} else {
sb.append(str.charAt(i));
}
}
System.out.println(sb.reverse().toString());
}
This gives following output,
6 7.9 200

Is there a better way to check string for any numbers in it?

basically, Ive been asked to write a program that checks how many times a number is apparent in a string and print it out. This is what i have
BufferedReader input = new BufferedReader (new InputStreamReader (System.in));
System.out.println("Please enter your string");
String s = input.readLine();
/*System.out.println("Please enter the chracter you are looking for");
char c = (char)input.read();*/
char one = '1';
char two = '2';
char three = '3';
char four = '4';
char five = '5';
char six = '6';
char seven = '7';
char eight = '8';
char nine = '9';
char zero= '0';
int counter = 0;
for( int i=0; i<s.length(); i++ ) {
if( s.charAt(i) == one || s.charAt(i) == two || s.charAt(i) == three || s.charAt(i) == four ||
s.charAt(i) == five || s.charAt(i) == six || s.charAt(i) == seven
|| s.charAt(i) == eight || s.charAt(i) == nine || s.charAt(i) == zero ) {
counter++;
}
}
is there a faster, better way to do this? I tried another way but for this error
Error: The operator || is undefined for the argument type(s) boolean, char
Instead of declaring digits by yourself in the code, you can take a look at Character.isDigit() method in Java. This will make the code much cleaner. There's no other faster way of doing this.
If you want to count occurrence of each digit, one simple way to do that would be to use Java Maps. You can read basic tutorial about Maps from here.
this works in c#
foreach (char c in str)
{
if (c >= '0' && c <= '9')
counter++;
}
You can use the decimal value of the character (as defined in the ASCII table)
String s = "abc123def456";
int cpt = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) >= '0' && s.charAt(i) <= '9') {
cpt++;
}
}
System.out.println(cpt); // 6
You can also use the Character::isDigit method
if (Character.isDigit(s.charAt(i))) {
cpt++;
}
EDIT :
If you are using Java 8+ you can turn the String in an stream of characters, apply a filter to keep the digits, and then count the number of elements in it.
long nbDigits = s.chars()
.filter(Character::isDigit) // If the character is a digit (= the isDigit() method returns true) it's kept in the stream
.count();
System.out.println(nbDigits); // 6
is there a faster, better way to do this
Your approach is absolute correct and almost maximum fast!. You could make it mo readable.
I think that general algorithm is the same for all languages with O(n):
Loop the array and increment counter when find a number character.
Your approach is absolute correct and almost maximum fast!. (note: I really think that speed between two comparisons and nine is very-very small and we should not care about it) All you can do is just write it with as less lines of code as possible. You can do following corrections:
char is integer in JVM and ASCII code for 0-9 is 0x30-0x39, so you can move from == to ch >= '0' && ch <= '9'.
Character class contains special method to check it: Character.isDigit(ch).
For java 8 you can use Streams instead of manual for...each.
Not using streams (plain old java) I think this approach provides maximum speed and lees memory objects
public int countDigits(String str) {
int count = 0;
for(int i = 0; i < str.length(); i++)
if(Character.isDigit(str.charAt(i)))
count++;
return count;
}
Using streams (from java 8). Looks good, works a little bit slower that previous example, and creates some additional objects in memory.
public int countDigits(String str) {
// could be a little bit slower, because additional objects are created inside
return (int)str.chars().filter(Character::isDigit).count();
}
P.S. If you want to show your skill, plain old java variant is more preferable. In working code, both variant are equal.
P.P.S. actually String.toCharArray() or str.chars() are look more elegant and even a little bit less performed that str.charAr(int), because they create additional objects in memory, but str.charAr(int) works directly with internal arrays. But I did not faced with problem with any approaches in real application.

(Java ) problems with myString.charAt(i) > "1" or myString.charAt(i) < "A"

I have a car Object which is supposed to have a characteristic. The characteristic is supposed to have the requirements: starts with two capital letter followed by a number from 1-9 followed by 4 numbers from 0-9.
public void writeCharacteristic(){
System.out.println("write down the characteristic for the car.");
String characteristic = kb.nextLine();
progress = false;
if (characteristic.length() != 7){
System.out.println("The string is not 7 letter/numbers long");
progress = false;
}
for(int i = 0; i < 2; ++i){
if (characteristic.charAt(i) < "A" || characteristic.charAt(i) > "Z"){
System.out.println(" character number " + i + " is invalid");
progress = false;
}
}
if (characteristic.charAt(3) < "1" || characteristic.charAt(3) > "9")
progress = false;
for (int j = 3; j < 7; ++j){
if (characteristic.charAt(j) < 0 || characteristic.charAt(j) > 9)
progress =false;
}
if (progress == false){
System.out.println("characteristic will have the value null.");
characteristic = null;
}
if (progress == true)
car.setCharacteristic(characteristic);
}
I'm having a problem at the lines "if (characteristic.charAt(i) < "A" || characteristic.charAt(i) > "Z"){"
The compiler is saying "The operator < is undefined for the argument type(s) char, String"
Any help is highly appreciated, thanks.
In Java, you can compare a character (char) to a character, but you can't compare a character to a String. charAt returns a character, so you must compare its result to a character.
These are String
"A" "Z" "1" "9"
And these are characters
'A' 'Z' '1' '9'
You can compare a character to an integer (int), but the result may not be what you want. So in the code below:
for (int j = 3; j < 7; ++j){
if (characteristic.charAt(j) < 0 || characteristic.charAt(j) > 9)
0 and 9 should be change to '0' and '9'.
Note: There is another unrelated logic error in your code:
String characteristic = kb.nextLine();
progress = false;
Shouldn't progress be set to true here?
I would certainly check out the other answers on this page re. character comparisons. However, I would perhaps suggest a different approach given:
starts with two capital letter followed by a number from 1-9 followed
by 4 numbers from 0-9
and investigate regular expressions. Something like:
[A-Z]{2}[1-9][0-9]{4}
would satisfy the above requirement.
Use single quotes for chars, double quotes for Strings.
characteristic.charAt(3) < '1'
there is meaning for single and double quotes in java
And for your situation best suits is a regex
Replace the double quotes with single quotes.
You'll also have to put single quotes around the numbers when comparing them with chars, even though the compiler doesn't complain.
Compare like this
characteristic.charAt(3) < '1'
First, you can achieve this goal with regexp:
[A-Z]{2}[1-9][0-9]{4}
(Read Pattern article to know how to use it).
If you want to do it as you started - use singleqoutes instead of doublequotes with characters. e.g. "a" -> 'a'.
If you want to assign value to char use single quote. If it is a String use double quote
char myChar='a';
String myString="a";
so
characteristic.charAt(3) < "1" should change as characteristic.charAt(3) < '1'

Java .charAt(i) comparison issue

Why when comparing a char against another it must be taken also from a string? For example;
This does not work
while(i < t.length() && zeroCount < 5) {
if(t.charAt(i) == 0){
zeroCount++;
}
i++;
}
Nor does this
char zero = 0;
while(i < t.length() && zeroCount < 5) {
if(t.charAt(i) == zero){
zeroCount++;
}
i++;
}
The only way I managed to get it working is like this...
String zeros = "0000000000";
while(i < t.length() && zeroCount < 5) {
if(t.charAt(i) == zeros.charAt(i)){
zeroCount++;
}
i++;
}
Can anyone explain if am doing something wrong, or if it is just not acceptable to do it like the top 2 examples. If so, why?
You're confusing
char zero = 0;
with
char zero = '0';
The former is the null-character (ASCII value of zero), whereas the latter is the character representing the digit zero.
This confusion is a rather unfortunate hang-over from C, with char variables being treated as numbers as well as characters.
You are looking for the character '0'? Then compare to '0', not 0.
You're comparing against Unicode value 0 (aka U+0000, the "null" character) - which is not the same as the Unicode character representing the digit 0.
Use '0' instead of 0:
while(i < t.length() && zeroCount < 5) {
if(t.charAt(i) == '0'){
zeroCount++;
}
i++;
}
Use '0' instead of 0.
The simple answer is that the value 0 is not the same as the character '0' which has an ASCII code of 48 (IIRC).
You should compare it with the char value charAt(i) == '0' or subtract the char before comparison charAt(i) - '0' == 0
These other answers have it right, but there’s one very important thing you should know. You should never use chatAt! You should only use codePointAt.
Similarly, you mustn’t blindly use i++ to bump through a string. You need to see whether s.codePointAt(i) > Character.MAX_VALUE to know whether to give an extra i++ kicker.
For example, to print out all the codepoints in a String s in standard "U+" notation:
private static void say_U_contents(String s) {
System.out.print("U+");
for (int i = 0; i < s.length(); i++) {
System.out.printf("%X", s.codePointAt(i));
if (s.codePointAt(i) > Character.MAX_VALUE) { i++; } // UG!
if (i+1 < s.length()) { System.out.printf("."); }
}
}
That way you can output like U+61.DF, U+3C3, and U+1F4A9.1F4A9 for the corresponding strings. That last one looks like "\uD83D\uDCA9\uD83D\uDCA9", which is simply insane.

Categories