Parsing user input to correlating array values - java

I am trying to assign a number to a letter grade that a user inputs. The user will input a letter such as A, B, or C and then based on what they enter a value is stored in an integer.
I figured the easiest way to do this was setup an array such as:
char[] grade = char[] grade = {'A','B','C','D','F'};
grade[0] = 4;
grade[1] = 3;
// ... as so on
So, whenever a user inputs 'A' for their grade, I use the 4 when I need to.
I am trying to figure out how to read an input (JOptionPane) and read the letter they enter to the corresponding value I have assigned it. How do I go about parsing the letter input based on my array?

I'm not sure, whether I understood you right:
int grade (char input)
{
return 5 - (input - 'A');
}
Think of it as a graph. In computer encoding, Ascii or UTF8, the characters A-F are sequentially encoded, with A being the lowest, but not 0 or 1, but 65 or something, which we don't remember exactly.
5 | *
4 | *
3 | *
2 | *
1 | *
0 +-- ... ------------------*----->
A B C D E F
65 6 7 8 9 70
Drawing this graph, I mentioned that you jump form D to F - is that intentionally? If not:
If we subtract from 5 the difference from input and 'A', we get 5 - 0 for 'A', and 5 - 1 for 'B' and so on. Since we don't want to look up the number for 'A', we use 'A' directly, which is fine, since we can perform arithmetics on characters.
We could as well write
return 70 - input;
or
return 'F' - input;
The standard form of a linear equation is y = mx + n, where n is the cut through the y-axis (70), and m = -1, the gradient, negative in our case.

It might be easier to just cast the character to an int. A char basically has an int value. Doing this:
int i = (char)'A';
will yield 65. For a lower case a it would be 97. You could cast the char to int, then use that value to do bounds checking and some arithmetic. Sequential letters will yield sequential integers. This is safe since you're running on a JVM and don't have to take bizarro character set orders for different platforms into account.
Apart from that, seeing how you have limited allowed inputs, a map could work well too:
Map<Character, Integer> grades = new HashMap<Character, Integer>();
grades.put('A', 4); //optionally also: grades.put('a' 4);
...
Type params and auto-boxing and unboxing makes this a lot more convenient these days.

Related

How do I create a method to generate all possible boolean functions?

I have used JAVA to create a linked list of 30 nodes. Each node is assigned a random Boolean value when instantiated.
I want each node assigned its own random boolean method/function/rule that takes three Boolean arguments and returns the result:
boolean assignedBolMethod(boolean a, boolean b, boolean c) {
boolean answer = conduct assigned ruled
return answer;
}
I understand there are 256 such rules to chose from (2^2^3); how could I generate all 256 possible rules without typing them out manually?
Let's say '0' when we mean false and '1' when we mean true, because that makes this a lot easier to read:
There are 8 different possible inputs (000, 001, 010, 011, 100, 101, 110, and 111), and for each input, there are 2 possible answers: 0 or 1.
Let's define a 'rule' as follows: We always list all the inputs in that exact order, and then we list the rule's answer to each input in terms of a 1 or a 0. Thus, 00001111 is the rule that says '000 = 0', '001 = 0, 010 = 0, 011 = 0, 100 = 1, ', etcetera - in other words, the rule is: return a;, if you were to put it in code.
It is then obvious that there are indeed 256 rules (2 ^ 8), and you can represent each rule as a single byte, as bytes consist of 8 bits. Every existing byte represents one rule. Thus 'a rule' and 'a byte' are completely interchangeable, thus, this boils down to: How do I generate an arbitrary byte.
And that's easy:
Random r = new Random(); // do this once someplace
byte rule = r.nextByte();
Alternatively if you want an ordered list of every possible rule:
byte[] rules = new byte[256];
for (int i = 0; i < rules.length; i++) rules[i] = (byte) i;
But this array is mostly meaningless; it effectively maps '100' to '100' - not very useful. There is no actual need to have a 'list' of all possible rules: Java already ships with it: byte - that is a data type that exactly matches. Thus, if you have some code and you want 'rule 100' to be applied, all you need to write is byte rule = 100; - no need for a list.
Given a byte that represents a rule, plus those 3 inputs, how do you determine the answer the rule indicates is correct?
Well, first you need to collapse those 3 booleans you have into which one of the 8 bits in your byte represents the answer.
int bitPos = (a ? 1 : 0) + (b ? 2 : 0) + (c ? 4 : 0);
This gives you the position of the bit (a number between 0 and 7) that determines the answer.
Then, given a bit position and a byte:
boolean answer = ((rule >> bitpos) & 1) != 0;
Breaking that down:
a >> b will take the bitstring of a (let's say it's rule 00110111), and shift it to the right by b spots. So if we want the bit at bitpos=2 (so, the third bit), 0b00110111 >> 2 is 0b00001101. This means the bit we are interested in is now at the very end.
a & b will take the bitstring of a, and the bitstring of b, and checks for all positions where both a and b have a 1. Then, it returns a new number represented by setting each bit to 1 where both a and b have a one. Therefore, a & 1 has the effect of zeroing out all bits, except the lowest bit (1 = 00000001 - all bits unset except the lowest bit). It gets rid of all bits, except the bit we care about.
!= 0 then just checks if that bit was set or not.

Java Hexadecimal to Decimal conversion: Custom Logic

I am trying to figure out how to convert hex into a string and integer so I can manipulate an RGB light on my arduino micro-controller through it's serialport. I found a good example on the java website, but I'm having a difficult time understanding some of the methods and I am getting hung up. I could easily just copy-paste this code and have it work but I want to fully understand it. I will add comments to my understandings and hopefully someone can provide some feedback.
public class HexToDecimalExample3{
public static int getDecimal(String hex){ //this is the function which we will call later and they are declaring string hex here. Can we declare string hex inside the scope..?
String digits = "0123456789ABCDEF"; //declaring string "digits" with all possible inputs in linear order for later indexing
hex = hex.toUpperCase(); //converting string to uppercase, just "in case"
int val = 0; //declaring int val. I don't get this part.
for (int i = 0; i < hex.length(); i++) //hex.length is how long the string is I think, so we don't finish the loop until all letters in string is done. pls validate this
{
char c = hex.charAt(i); //char is completely new to me. Are we taking the characters from the string 'hex' and making an indexed array of a sort? It seems similar to indexOf but non-linear? help me understand this..
int d = digits.indexOf(c); //indexing linearly where 0=1 and A=11 and storing to an integer variable
val = 16*val + d; //How do we multiply 16(bits) by val=0 to get a converted value? I do not get this..
}
return val;
}
public static void main(String args[]){
System.out.println("Decimal of a is: "+getDecimal("a")); //printing the conversions out.
System.out.println("Decimal of f is: "+getDecimal("f"));
System.out.println("Decimal of 121 is: "+getDecimal("121"));
}}
To summerize the comments, it's primarily the char c = hex.charAt(i); AND the val = 16*val + d; parts I don't understand.
Ok, let's go line for line
public static int getDecimal(String hex)
hex is the parameter, it needs to be declared there, so you can pass a String when you call the function.
String digits = "0123456789ABCDEF";
Yes, this declares a string with all characters which can occur in a hexadecimal number.
hex = hex.toUpperCase();
It converts the letters in the hex-String to upper case, so that it is consistent, i.e. you always have F and never f, no matter which is being input.
int val = 0;
This is the variable where the corresponding decimal value will later be in. We will do our calculations with this variable.
for (int i = 0; i < hex.length(); i++)
hex.length() is the number of characters in the hex-String provided. We execute the code inside this for loop once per character.
char c = hex.charAt(i);
Yes, char represents a single character. We retrieve the character from the hex-String at index i, so in the first iteration it is the first character, in the second iteration the second character and so on.
int d = digits.indexOf(c);
We look which index the character has in the digit-String. In that way we determine the decimal representation of this specific digit. Like 0-9 stay 0-9 and F becomes a 15.
val = 16*val + d;
Let's think about what we have to do. We have the decimal value of the digit. But in hexadecimal we have this digit at a specific position with which it gets multiplied. Like the '1' in '100' is actually not a 1, but 100 * 1 because it is at this position.
10 in hexadecimal is 16 in decimal, because we have 1 * 16. Now the approach here is a little bit complicated. val is not uninitialized. val is 0 at the beginning and then contains the cumulated values from the previous iterations. Since the first character in the String is the highest position we don't know directly with what we have to multiply, because we don't know how many digits the number has (actually we do, but this approach doesn't use this). So we just add the digit value to it. In the consecutive iterations it will get multiplied by 16 to scale it up to the corresponding digit base value. Let me show you an example:
Take 25F as hex number. Now the first iteration takes the 2 and converts it to a 2 and adds it to val. The 16 * val resolves to 0 so is not effective in the first time.
The next iteration multiplies the 2 with 16 and takes the 5 (converted to 5) and adds it to val. So now we have (I split it mathematically so you understand it):
2 * 16 + 5
Next we get the F which is decimal 15. We multiply val by 16 and add the 15.
We get 2 * 256 + 5 * 16 + 16 (* 1), which is actually how you calculate the decimal value of this hex value mathematically.
Another possibility to compute val is:
val += Math.pow(16, hex.length() - i - 1) * d;

Why does charAt work differently depending on the data type it is printed as

public class MyClass
{
public static void main(String args[])
{
String a = "(4 + 4i)";
String b = "(2 + 3i)";
int g = 1;
int c = a.charAt( g ); // sets c to 52
System.out.println( c ); // prints 52
System.out.println( (double) a.charAt( g ) ); // prints 52.0
System.out.println( a.charAt( g ) ); // prints 4
System.out.println( 2 * a.charAt( g ) ); // prints 104
}
}
I was trying to write code to multiply imaginary numbers which is why I have "i" in the strings. So I thought take first and and convert to int or double. This gave me 52 which baffled me. However when I printed directly to console, it worked but only without the double. This is useless because I need to use it elsewhere. So what is going on here? Would it better to try to parse parts of strings a and to int or double and are there alternatives to manipulating numbers within strings without using parse? And are there methods that can deal with imaginary numbers i.e. "e^pi * i = 1"?
A String is a sequence of symbols, such as letters, punctuation, and digits, called characters. Each character is associated with a number. One common way to do this is with what is called the ASCII characters. In this case, you see that the character '4' is represented by the number 52.
With this in mind, let's look at some of your code:
int c = a.charAt( g );
This line silently converts the character to its numerical value. By "numerical value" I mean the number that represents the character, not the value of the digit itself. In this case, the character '4' has the numerical value 52.
System.out.println( a.charAt( g ) ); // prints 4
This prints out the character '4', not the int 4. It is extremely important that you learn the difference between the digit characters and their integer values.
In order to get the number 4 so that you can perform arithmetic operations, you must parse the String. The function Integer.valueOf() will help a lot with this.
You should also learn about classes and objects. For example, you can create a Complex class which will allow you to use complex numbers as a single entity with its own operations.
To get the numerical values that you want, you need to use Integer.valueOf() or Double.valueOf() depending on whether you want an int or a double:
int c = Integer.valueOf(a.charAt(g))
You will need to use more sophisticated parsing methods if you want to allow numbers with multiple digits or decimal points.
You get 52 because the ascii value of '4' is 52.
System.out.println("(4 + 4i)".charAt(1) == '4'); // '4' == '4'
System.out.println((int) '4'); // <-- 52
If you want to convert a char to its' int value, you need to check that it is in the expected range and then parse it. You can subtract '0' from the value, or use Character.digit - like
char c = '4';
if (c >= '0' && c <= '9') {
System.out.println((int) (c - '0'));
System.out.println(Character.digit(c, 10));
}
And, finally, System#out is a PrintStream, that is what provides the overloaded methods to write int (or char, or String, or double, etc).

What is the use of hypen(-) in java

Can some one explain what runner.children[c-'a']
means in the following code.
public boolean search(String word) {
TrieNode runner = root;
for(char c : word.toCharArray()) {
if(runner.children[c-'a'] == null) {
return false;
} else {
runner = runner.children[c-'a'];
}
}
return runner.isEndOfWord;
}
Every char has a numeric value, check out the ASCII table for more information.
So assume that the variable c contains character b, and subtract character a from that, you will get 1 for your answer.
That's just subtraction. You can subtract characters as though they were numbers. You end up with the result of subtracting their character codes. 'c' - 'a' (for example) equals 2, since 'a' is 2 less than 'c'.
- is the subtraction operator.
§15.18.2 The type of each of the operands of the binary - operator must be a type that is convertible to a primitive numeric type
§5.6.2 Widening primitive conversion is applied to convert either or both operands … both operands are converted to type int.
Binary numeric promotion is performed on the operands of certain operators: … addition and subtraction operators for numeric types + and - …
In other words, both c and 'a' are of type char (a UTF-16 code unit, which has a range from Character.MIN_VALUE to Character.MAX_VALUE). Due to subtraction, they are widened to type int, subtracted, resulting in a value of type int.
Think of characters on a number line. Subtraction is the distance from one character to the other. With a constant reference to 'a', the distances for 'a', 'b', … 'z' are 0, 1, … 25. This makes sense only over certain short segments of the UTF-16 number line.
Arrays are 0-based so shifting the scale like this allows characters to be used to index an array without having a large used portion with elements corresponding to unused characters.
(Note: Some people are saying ASCII because they think it's easier to understand a simpler, wrong thing on the way to learning the right thing. 🤷)
In this case children[] is probably the size of the amount of letters from a-z.
What is going on above is that they take the ascii value of the char c, and subtracting the ascii code of 'a'. Effectively resulting in getting the index of the char c in the alphabet (0-Index assumed)
Let c = 'b'
[c-'a'] = 98 - 97 = 1 (Ascii of b - Ascii of a)
With c = 'd'
[c-'a'] = 100 - 97 = 3
It is minus sign and not hyphen. In java char takes 2 bytes of space. char is representation of bits ranging from 00000000 to 11111111, most significant bit is read as signed bit. You can easily read it as a number also by assiging a char to an int variable ( as int can accept 4 bytes so 2 bytes of char can easily fit ).
char charA = ''A'; // represents 65
char charB = `B`; // represents 66
int diff = charB - charA; // this will represent 66-65 i.e. 1
Index of the array is positve int and hence it can also accept values like
anyTypeArray[charB - charA] //represents the 2nd element (index starts from 0 for arrays in java).
anyTypeArray['C' - charA] // represents the 3rd element of the array
Also I liked answer above https://stackoverflow.com/a/47106997/504133 and would like to add its link to extend my answer.

The most efficient way to decipher some text

I am developing a small application where I am given some string "MRUGDQ" and a shift value 3 for example. Then I shift each letter to left by 3 and the result would be "JORDAN". For instance M would be replaced by J and R would be replaced by O and so on.
So now this is the approach I was thinking of using, but I was wondering if this is efficient and can I improve my solution?
Assumptions I make:
I am assuming my string will be either capital A to Z letter or small a to z letter and therefore the ascii range is from 65 to 90 and 97 to 122 respectively.
Pesudo Code
get ascii value of char
(assume char happens to be between the capital letter range)
add the shift value to the char ascii value
if new ascii value <= 90
replace old letter by new letter
else
int diff = new ascii value - 90
while (new ascii value <= 90) {
decrement diff value by 1
increment new ascii value by 1
}
add remaining diff to 65 and set that as new ascii value
replace old letter by new letter
Do that for each letter in the string.
Please let me know if my approach is correct or if I can be more efficient.
I don't see much to improve, except your handling of the new char is out of range.
If you like to "roll" the overlapping amount back to the beginning of your range, than just calculate: (x % 90) + 64(*) (with x being the ascii value after adding the shift value).
Example:
'Y' (89) + 3 = '\' 92
92 % 90 = 2
2 + 64 = 'B' (66)
You need to start from 64, to avoid skipping over 'A', which has the value 65.
(*) The general formula is: (value % upper bound) + (lower bound - 1).
You could also use (value % upper bound + 1) + lower bound.

Categories

Resources