Can't convert to char in ? : operator - java

I want to give user with 2 choices which are whether reading the node in alphabets or numbers. It will say something like "From node A to B" or "From node 1 to 2". So I wrote codes like the //2 code(I want to make it simple so I let the condition to be "true"). But the result is "66" instead of "B". However, the //1 code works fine. How can I wrote the code that allows me to change the letter and display correctly the way I want? Thanks.
System.out.println(true?(char)(65+1):65);//1
int a=65;
System.out.println(true?(char)(65+1):a);//2
Results
B
66
*Try to make it clearer: I want to make a loop to print out
From node A to node B
From node A to node C
From node A to node D
...
So I will write
for (int i=1;i<26;i++)System.out.println("From node A to node "+ (char)(65+i));
But I also want to make it able to print out this if user decide to:
From node 1 to node 2
From node 1 to node 3
From node 1 to node 4
...
So, I make a question about the format the user wants as a boolean format variable. And I edit the code to be
boolean format=true;//I simplify it
for (int i=1;i<26;i++)System.out.println("From node "+(format?"A":1)+ " to node "+ (format?(char)(65+i):i));
Here is there result
From node A to node 66
From node A to node 67
From node A to node 68
...
This is not what I want. It should be "From node A to node B", etc...
I changed the short type in //2 to int as recommended, but it(type) is not the point I'm asking. So please don't mind it.

I can't understand what you're trying to achieve (and why you're using short variables), but the behavior you're observing is explained in the Java Language Specification:
If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression (§15.28) of type int whose value is representable in type T, then the type of the conditional expression is T.
That explains what you see in the first example: 65 is a constant expression of type int, (char)(65+1) is a char, and the type of the ternary expression is thus char.
Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.
That explains what you see in the second example: one is of type short and the other is of type char: they're both promoted to int and the result is thus of type int.
To do what you want to achieve, I'd do something like:
private String formatNode(int node) {
return formatAsInteger ? Integer.toString(node + 1) : Character.toString((char) (node + 'A'));
}
// ...
for (int i = 1; i < 26; i++) {
System.out.println("From node " + formatNode(0) + " to node " + formatNode(i));
}

There are two problems in your code, different types for the second and third expressions in the ?:, and dead code due to the use of true. I fixed the first problem two different ways. The first println selects between two int expressions, and casts the result to char. The second cases each of the selected expressions. I fixed the second problem by using a boolean whose value the compiler does not know.
public class Test {
public static void main(String[] args) {
boolean test = args.length < 1;
System.out.println((char) (test ? (65 + 1) : 65));
System.out.println(test ? (char) (65 + 1) : (char) 65);
}
}

Try :
System.out.println(true?(char)(65+1):65);//1
char a=65;
System.out.println(true?(char)(65+1):a);//2

If I understand your question correctly, this is what you should write:
System.out.println((char)(false?(65+1):65));
You need to cast the result.

Related

Comparing two string using XOR return true but the strings are different

I'm testing some ways to identify anagrams and I found a situation that got me off guard. I found out that it's possible to do using XOR so I was testing it using the XOR operator. Here's my code:
public static void main(String[] args) {
// TODO code application logic here
String s1 = "pe";
String s2 = "ep";
System.out.println(isAnagram(s1, s2));
}
private static boolean isAnagram(String firstString, String secondString)
{
int control = 0;
System.out.println("Comparing: " + firstString + " and " + secondString);
for (int i = 0; i < firstString.length(); i++) {
control = control ^ firstString.charAt(i);
}
for (int i = 0; i < secondString.length(); i++) {
control = control ^ secondString.charAt(i);
}
System.out.println("Control: " + control);
return (control == 0);
}
When the 2 strings have the same sets of characters, even when they are not in the same order the control variable is 0 returning true to anagram. However, when the 2 strings are different the control has a value > 0 returning false to anagram.
I tried using many words and most of them worked, but for some reason it often has some strange situations where, for example, "v" and "ils" return true to anagram or "tat" and "atata" returns true as well.
I would like to understand why it happens and what should I do so this situations doesn't show up anymore.
Simply, the algorithm you are using is not going to work. Since XOR is associative and commutative (like, for example, addition), XORing together all the characters in a string produces the same value regardless of the order in which you do the XORs. Similarly, you get the same sum of the values in an array regardless of the order in which you do the additions.
But, also like addition, XOR throws away information. You cannot go backwards from the result to the original values: 1+3 = 2+2 = 0+4. And similarly with XOR: 1^3 = 6^4 = 0^2.
One particular feature of XOR is that a ^ a = 0 for any a; also a ^ 0 = a. (These statements are related.) So you can always just remove pairs of identical characters; the XOR combination of atata is the same as the combination of tat and also the same as a.
So you're going to continue running into these issues due to how the function of bitwise operators. v has an acsii of 01110110,i has an acsii of 01101001, l has an acsii of 01101100, and s has an acsii of 01110011.
Here's the line by line of the comparisons that lead to 00000000 being returned.
v - 01110110
i - 01101001
new:00011111
l - 01101100
new:01110011
s - 01110011
new:00000000
Each "new" is your control and the individual comparisons that lead to 00000000 or your true result.

Counting The Number of Valleys [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 3 years ago.
I'm doing a problem on hackerRank and the problem is:
Problem Statement
Here we have to count the number of valleys does XYZ person visits.
A valley is a sequence of consecutive steps below sea level, starting with a step down from sea level and ending with a step up to sea level.
For One step up it U, and one step down it is D. We will be given the number of steps does XYZ person traveled plus the ups and down in the form of string, i.e,
UUDDUDUDDUU
Sample Input
8
UDDDUDUU
Sample Output
1
Explanation
If we represent _ as sea level, a step up as /, and a step down as \, Gary's hike can be drawn as:
_/\ _
\ /
\/\/
He enters and leaves one valley.
The code I wrote doesn't work
static int countingValleys(int n, String s) {
int count = 0;
int level = 0;
String[] arr = s.split("");
for(int i = 0; i<n;i++){
if(arr[i] == "U"){
level++;
} else{
level--;
}
if(level==0 && arr[i]=="U"){
count++;
}
}
return count;
}
But another solution I found does, however no matter how I look at it the logic is the same as mine:
static int countingValleys(int n, String s) {
int v = 0; // # of valleys
int lvl = 0; // current level
for(char c : s.toCharArray()){
if(c == 'U') ++lvl;
if(c == 'D') --lvl;
// if we just came UP to sea level
if(lvl == 0 && c == 'U')
++v;
}
return v;
}
So what's the difference I'm missing here that causes mine to not work?
Thanks.
In java, you need to do this to compare String values:
if("U".equals (arr[i])) {
And not this:
if(arr[i] == "U") {
The former compares the value "U" to the contents of arr[i].
The latter checks whether the strings reference the same content or more precisely the same instance of an object. You could think of this as do they refer to the same block of memory? The answer, in this case, is they do not.
To address the other aspect of your question.
Why this works:
for(char c : s.toCharArray()){
if(c == 'U') ++lvl;
if(c == 'D') --lvl;
when this does not:
String[] arr = s.split("");
for(int i = 0; i<n;i++){
if(arr[i] == "U"){
You state that the logic is the same. Hmmmm, maybe, but the data types are not.
In the first version, the string s is split into an array of character values. These are primitive values (i.e. an array of values of a primitive data type) - just like numbers are (ignoring autoboxing for a moment). Since character values are primitive types, the value in arr[i] is compared by the == operator. Thus arr[i] == 'U' (or "is the primitive character value in arr[i] equal to the literal value 'U') results in true if arr[i] happens to contain the letter 'U'.
In the second version, the string s is split into an array of strings. This is an array of instances (or more precisely, an array of references to instances) of String objects. In this case the == operator compares the reference values (you might think of this as a pointer to the two strings). In this case, the value of arr[i] (i.e. the reference to the string) is compared to the reference to the string literal "U" (or "D"). Thus arr[i] == "U" (or "is the reference value in arr[i] equal to the reference value of where the String instance containing a "U" string" is located) is false because these two strings are in different locations in memory.
As mentioned above, since they are different instances of String objects the == test is false (the fact that they just happen to contain the same value is irrelevant in Java because the == operator doesn't look at the content). Hence the need for the various equals, equalsIgnoreCase and some other methods associated with the String class that define exactly how you wish to "compare" the two string values. At risk of confusing you further, you could consider a "reference" or "pointer" to be a primitive data type, and thus, the behaviour of == is entirely consistent.
If this doesn't make sense, then think about it in terms of other object types. For example, consider a Person class which maybe has name, date of birth and zip/postcode attributes. If two instances of Person happen to have the same name, DOB and zip/postcode, does that mean that they are the same Person? Maybe, but it could also mean that they are two different people that just happen to have the same name, same date of birth and just happen to live in the same suburb. While unlikely, it definitely does happen.
FWIW, the behaviour of == in Java is the same behaviour as == in 'C'. For better or worse, right or wrong, this is the behaviour that the Java designers chose for == in Java.
It is worthy to note that other languages, e.g. Scala, define the == operator for Strings (again rightly or wrongly, for better or worse) to perform a comparison of the values of the strings via the == operator. So, in theory, if you addressed other syntactic issues, your arr[i] == "U" test would work in Scala. It all boils down to understanding the rules that the various operators and methods implement.
Going back to the Person example, assume Person was defined as a case class in Scala. If we created two instances of Person with the same name, DOB and zip/postcode (e.g. p1 and p2), then p1 == p2 would be true (in Scala). To perform a reference comparison (i.e. are p1 and p2 instances of the same object), we would need to use p1.eq(p2) (which would result in false).
Hopefully the Scala reference, does not create additional confusion. If it does, then simply think of it as the function of an operator (or method) is defined by the designers of the language / library that you are using and you need to understand what their rules are.
At the time Java was designed, C was prevalent, so it can be argued that it makes sense the C like behaviour of == replicated in Java was a good choice at that time. As time has moved on, more people think that == should be a value comparison and thus some languages have implemented it that way.

Could someone please explain the algorithm of reverse string using tail recursion?

I am sorry for being stupid to ask this question. I able to understand the code until getting the last character of the given string and return, then I am not able to relate the recursion logic.
Before posting it here, debugger helped me partially. Unfortunately, not 100%
Could you please help me to understand this?
public static void main(String[] args) {
System.out.println(reverseRecursively("abcd"));
}
public static String reverseRecursively(String str) {
if (str.length() < 2) {
return str;
}
return reverseRecursively(str.substring(1)) + str.charAt(0);
}
Debugger Output:
0=abcd
1=bcd
2=cd
3=d
Final: dcba
Well, it's a pretty simple logic:
return reverseRecursively(str.substring(1)) + str.charAt(0);
If you put a System.out.println() before the return, you'll get the following output:
Recursing with substring: bcd and adding a
Recursing with substring: cd and adding b
Recursing with substring: d and adding c
Adding d as final char
If you reverse this, you get dcba.
Why is it reversed though?
Well, you have to think of the call trace:
return reverseRecursively("bcd") + a -> retruns "dcba"
-> return reverseRecursively("cd") + b -> returns "dcb"
-> return reverseRecursively("d") + c -> returns "dc"
-> return d -> returns "d"
I guess the key point is to understand that the recursion is always combined with the result of another recursion.
When the method runs, it will check first if the String is one or zero characters in length. This will tell it whether it is the final character in the string. If not, it will append the current character to the end of the string and run again, this time on the next character along. This means that the string gets a character shorter every time.
What may be confusing is that the str.charAt(0) is not passed into the next iteration of the method, rather just added as a part of the return statement. This means that once the method has completed the final character, it will return all characters in backwards order as each method completes one after the other starting with the one that returns the last character. This will happen until all methods return and returns your reversed string.
It's like layers of methods, one will invoke another and then they will all complete in backwards order to the order in which they were called.
Hope this helped your understanding!
No question is stupid question. If one doesn't ask a question, thinking that people will think he/she is stupid, then he/she is stupid for life. :)
Now the explanation:
I added a print statement to help you with it.
public static String reverseRecursively(String str) {
System.out.println("For debuging : "+str); // this is my print statement.
if (str.length() < 2) {
return str;
}
return reverseRecursively(str.substring(1)) + str.charAt(0);
}
It prints the below.
For debuging : abcd
For debuging : bcd
For debuging : cd
For debuging : d
dcba
The base criteria for the method to return the value is, str.length() < 2.
So when the "d" is returned by last method call(or we can say the fourth method call to reverseRecursively(String str)), because the length is less than 2. The third method call will return
"d" + "cd".charAt(0);
which is nothing but : dc.
Similary 2nd method will use the third method's return value (dc) and return the value
"dc" + "bcd".charAt(0);
which is dcb.
and so the first method call, where you passed the string "abcd" as input will return.
"dcb" + "abcd".charAt(0);
which is dcba.
Hope this helps. Cheers !!!
`public static String reverseRecursively(String str) {
if (str.length() < 2) {
return str;
}
return reverseRecursively(str.substring(1)) //take "bcd" : 1st Itration
//"cd" : 2nd
// "d" : 3rd (this makes str.length() < 2)
// 3rd returns first with "d" and pass control back to 2nd recursion
//2nd takes d and adds 0th char c and returns with "dc" and pass control to 1st
//1st takes dc and adds b returns with "dcb" and pass control to base call
// base call take "dcb" and adds 0th char a and returns to calling method
+ str.charAt(0);
}`.

Java String += Shorthand explanation needed

While I was creating a program to compress a string I ran into this strange problem, I will paste the code snippets with their outputs, I would like someone to clearly explain why this is happening.
The first code snippet: here if same letter appears consecutively, then the successive occurrences of the letter is replaced by the total count of same letters. Ex: aaabbb should be written as a3b3.
public static String compress(String str){
String compressed = "";
char prev = str.charAt(0);
int count = 1;
for (int i = 1; i < str.length(); i++) {
char curr = str.charAt(i);
if (curr == prev) { // in case curr is equal to prev
count++;
} else { // in case curr is not equal to prev
//compressed=compressed+prev+count;
compressed+=prev+count; // Shorthand used here
count=1;
prev=curr;
}
}
compressed=compressed+prev+count; // Shorthand not used
System.out.println(compressed);
return compressed;
}
the output for this above code when inputted with aabbccaabbccaabbccaabb is 99100101991001019910010199b2, observe the last two elements of the output, this is because outside the loop, shorthand is not used. If I write the expression as compressed = compressed +prev+count inside the loop, I'll get the intended output.
I thought this output is because the operation is messing with the address of the String. But the next code confused me again.
String prev= "abc";
String curr = "def";
String result="";
result+=prev+curr;
System.out.println(result);
I think this is because the right hand operation is performing an ASCII addition, I cannot come to a conclusion, can anyone clarify.
I am sleep deprived and hence I am not able to come to a conclusion, hence asking someone to clarify my trivial doubt.
It has nothing to do with the reference. When you did prev+count ascii value of the character in prev is added with the integer count. In this case :
ascii of "a" is 97, and it occurred twice... so 97 +2 = 99 ..
ascii of "b" is 98, and it occurred twice... so 98 +2 = 100 ..
ascii of "c" is 99, and it occurred twice... so 99 +2 = 101 ..
that's why the output is 99100101991001019910010199100
try this : compressed+=(""+prev)+count; // Shorthand used here
In this case, or in compressed+=""+prev+count case, since the operation happens from left to right, the + operator is applied on a string ("") and char(prev) and behaves like append and also returns a string. The resulting string is then appened with another int (prev)
A better way is using a StringBuilder
Take a look at this subject and at JLS 15.18.1 section :
You see this behavior as a result of the combination of operator
precedence and string conversion.
JLS 15.18.1 states:
If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a
string at run time.
Therefore the right hand operands in your first expression are
implicitly converted to string: string = string + ((char)65) + 5;
For the second expression however string += ((char)65) + 5; the +=
compound assignment operator has to be considered along with +.
Since += is weaker than +, the + operator is evaluated first.
There we have a char and an int which results in a binary numeric
promotion to int. Only then += is evaluated, but at this time
the result of the expression involving the + operator has already been evaluated.
Whenever you add a char to an int in java first it converts the character into its equivalent ASCII value and then adds it to the integer
eg suppose the following scenario ,
char c = 'a'; // ASCII value of 'a' is 97
int i = c + 5 ; // result will be 97 + 5 = 102
I think this answers your first half question
Now the Second part ,
Whenever you use the shorthand operator in Java the expression at right hand side is evaluated first.
Hence , for expresion
result += prev + curr it is evaluated as
result = result + (prev + curr);
Therefore ,
result+=prev+curr; // Here first it appends "abc" with "def" and then the resultant "abcdef" is appended to as result .
you can convert your charater value "prev" to string and than append count to it.
compressed += Character.toString(prev) + count;

Creating a Binary Expression Tree given prefix notation in java

How should we construct the binary tree of the following "prefix" order expression?
( - * / 8 + 5 1 4 + 3 - 5 / 18 6 )
4
Pseudocode is like this:
public ExpressionRootNode MakeBinaryTree(expr):
element = next element in expr
if element is a number:
return a leaf node of that number
else: // element is an operator
left = MakeBinaryTree(expr)
right = MakeBinaryTree(expr)
return a binary tree with subtrees left and right and with operator element
//^aka return root
However, I dont quite understand how to recursively call the function to create said tree.
I have tried looking at how to Create a binary tree from an algebraic expression, but can't figure out how to backtrack up to the other node.
Project files : http://pastebin.com/BJiPtDM5, its a mess.
More pseudocode:
abstract class Tree { .... }
class Leave extends Tree { int number; ... }
class Expr extends Tree { Tree left, right; String operation; .... }
public Tree makeBinaryTree(expr):
element = next element in expr
if element is a number:
return new Leave(element)
else: // element is an operator
left = makeBinaryTree(expr)
right = makeBinaryTree(expr)
return new Expr(left, right, element)
The constructors of Leave/Expr are expected to just set the fields from their arguments.
What is left to be done is some error handling, though. Ohh, and make sure that "next element in expr" also removes the part already dealt with.
Given a correct input, it will work like this:
if the input is just a number, it will return a Leave with that number
if the input is of the form OP L R, it will remember OP, make the left subtree from L and the right subtree from R and return that as expression.
no other inputs are possible/valid
Example:
* + 5 1 7
will result in:
Expr(Expr(Leave(5), Leave(1), "+"), Leave(7), "*")
Note that those prefix expressions cannot see if "-" is supposed to be unary negation or binary subtraction. Hence you can't use the same operator character for that.
See the last two answers here.
parsing math expression in c/c++
I think they are quite useful.
You need a formal grammar and then a recursive descent parser.
Not sure if you're fully familiar with these two concepts.
If not, you should read some more about them.

Categories