How this bitshift to build the number works? - java

I saw this method which is used for faster reading of positive value of Long.
public static long readLong(InputStream in) throws IOException {
long n = 0;
int c = in.read();
while (c < 48 || c > 57) {
c = in.read();
}
while (c >= 48 && c <= 57) {
n = (n<<3) + (n<<1) + (c-'0');
c = in.read();
}
return n;
}
While I understand all of the part, what I'm not able to get is this:
bit shifting by odd number to
build the number n = (n<<3) + (n<<1) + (c-'0');
Why ignore the 3rd bit and how it's able to build it?
If anyone of you could explain me in simple way, it would be very much helpful.
Thanks!

n << i is n * 2^i. So,
(n<<3) + (n<<1) = (n * 2^3) + (n * 2^1) = n * (2^3 + 2^1) = n * 10
Basically, it means to shift the value of n one digit to the left.
Adding it with c + '0' means adding the last digit with the integer value of c.

Consider this code,
while (c >= 48 && c <= 57) {
n = (n<<3) + (n<<1) + (c-'0');
System.out.println(n);
c = System.in.read();
}
If I enter 123456, it prints
1
12 // 1 * 10 + 2
123 // 12 * 10 + 3
1234 // 123 * 10 + 4
12345 // 1234 * 10 + 5
123456 // 12345 * 10 + 6
So what it basically does is making space at the units place for the next number by just multiplying it by 10 and adding the int value of the character.

This is what happens:
(n<<3) means (n*8)
(n<<1) means (n*2)
(c-'0') gives you the character as int value
Together this means
n = n*10 + theNewDigit

Related

How to proceed to find the maximum sum of 2 integers with replacing only one digit?

example 1
a=1
b=90
answer will be 1+99 = 100
example 2
23
45
answer will be 93+45 =138
Note:there can be negative numbers also.
You are not allowed to add digits, just replace a single digit to get maximum sum
Use this
if(a>b || a==b){
a=10*((a/10)+1)
return a;
}
else{
b=10*((b/10)+1)
return b;
}
Let's assume that the first number has d1 digits, the second has d2 digits and for the sake of simplicity, let's assume further that
d1 >= d2
and
k = d1 - d2
so, k >= 0. If the first k digits of the larger number are modifiable (modifiable: if the number is positive, but the digit is not 9, or the number is negative), then modify that digit optimally, as described earlier.
Otherwise, in subsequent digits check whether any of the digits is modifiable and if so, compute the difference between the changes you would do on the two digits and choose the one where the change was larger.
When the first modification was done, then the work should stop.
Here is a straightforward recursion in JavaScript (easily translatable to Java or C++). The idea is to choose the best addition or subtraction (for negatives) possible for each number. The complexity is O(log10 n), where n is the larger number.
function improve(n){
if (n > -10 && n < 10)
return n < 0 ? -n : 9 - n;
return Math.max(
10 * improve(~~(n / 10)),
n < 10 ? -(n % 10) : 9 - (n % 10)
);
}
function f(a, b){
return a + b + Math.max(improve(a), improve(b));
}
var abs = [
[1, 90],
[23, 45],
[-94, 5]
];
for (let [a, b] of abs){
console.log(a, b);
console.log(f(a, b));
console.log('');
}
I had a rather simple idea. First convert two integers `n1`, `n2` into c-string `s1` , `s2`. Then if s1[0] = '-' (n1 is negative) change `s1[1] = 0`, else (n1>0) change `s1[0] = 9`. Similarly for c-string `s2`. Finally compare which sum is the larger: `n1 + stoi(s2)` or `n2 + stoi(s1)` to determine the set to be choose.
One extra care is that for a integer >0, and starting with digits`999...` To take this case into consideration, we use a for loop to change the first digit that is not equal to `9`. If all digits are `9`, we do nothing to the integer.
#include <iostream>
#include <fstream>
#include <cstring>
int main()
{
int n1, n2, a, b;
char s1[32], s2[32];
while (1)
{
std::cout << "\n input n1 & n2 = ";
std::cin >> n1 >> n2;
itoa(n1, s1, 10);
itoa(n2, s2, 10);
if (s1[0] == '-') s1[1] = '0';
else for (int i=0; i<strlen(s1); i++) {
if (s1[i] = '9') continue;
else {s1[i] = '9'; break;}
if (s2[0] == '-') s2[1] = '0';
else for (int i=0; i<strlen(s2); i++) {
if (s2[i] = '9') continue;
else {s2[i] = '9'; break;}
a = n1 + std::stoi(s2);
b = n2 + std::stoi(s1);
if (a > b) std::cout << "two integers: " << n1 << ", " << s2 <<std::endl;
else std::cout << "two integers: " << s1 << ", " << n2 <<std::endl;
}
return 0;
}
Some test sets:
$ ./a.exe
input n1 & n2 = 12 78
two integers: 92, 78
input n1 & n2 = -45 90
two integers: -05, 90
input n1 & n2 = -34 -78
two integers: -34, -08
input n1 & n2 = 23 9999
two integers: 93, 9999

Why does "col" variable return a wrong value

In a recent job interview, I had to solve a programmatic question. The question was to convert a given excel alphabet column name to a column number. My solution worked for the most part until they (interviewer) gave me "AUHS" as a column name. The solution broke. The expected answer "31999" but I got "18999". I want to learn where I went wrong and what I could do to improve the solution.
PS: I am new to Java
My solution,
public class test {
public static void main(String[] args) {
String argChar = "AUHS";
char a = 'A';
int asciiA = (int) a;
int col = 0;
col += Math.pow(26, 0) + (int)argChar.charAt(argChar.length()-1) - asciiA;
for(int i=1; i<argChar.length(); i++) {
col += (int)(Math.pow(26, i) + ((int)argChar.charAt(argChar.length()-(i+1)) - asciiA) * 26);
}
System.out.println(col);
}
}
The formula for spreadsheets's alphabetical column labels
The sequence of A-Z encoded (base-26) column-labels is:
A .. 1 (= 26^0*1)
B .. 2 (= 26^0*2)
H .. 2 (= 26^0*8)
S .. 2 (= 26^0*19)
U .. 2 (= 26^0*21)
Z .. 26 (= 26^0*26)
AA .. 27 (= 26^1*1 +1)
AZ .. 52 (= 26^1*1 +26)
BA .. 53 (= 26^1*2 +1)
ZZ .. 702 (= 26^1*26 +26)
AAA .. 703 (= 26^2*1 + 26^1*1 + 26^0*1)
UHS .. 14423 (= 26^2*21 + 26^1*8 + 26^0*19)
AUHS .. 31999 (= 26^3*1 + 26^2*21 + 26^1*8 + 26^0*19)
So we can deduct the formula (in pseudo-mathematical-notation) as:
sum-of ( 26^index * letterAsNumber ) over each letter
where index is the position of the letter from the end starting with 0
where letterAsNumber is the letter mapped to a number {1..26}
where letter must be in range {A..Z}
See also Positional notation.
The parts of this formula in Java
Given following inputs:
column-label String columnLabel
base int radix = 26
ASCII-code offset int asciiOffset = 65 - 1 (A has the decimal ASCII code 65)
We need to calculate the following working variables:
backwards-index int backwardsIndex, which is initially 0 and is incremented by 1 when iterating through each character; starting at the end of the column-label (hence: backwards!)
the running column-number long columnNumber, where a column-letters numerical-character-representation will be added during each iteration
The formula in Java
final int asciiOffset = (int) 'A' - 1; // 64 = 65 - 1, so that (int) 'B' - asciiOffset == 2
long columnNumber = 0;
for (int backwardsIndex=0; backwardsIndex < columnLabel.length(); backwardsIndex++) {
char letter = columnLabel.charAt(columnLabel.length() - backwardsIndex -1);
int letterAsNumber = (int) letter - asciiOffset;
columnNumber += Math.pow(26, backwardsIndex) * letterAsNumber;
}
return columnNumber;
}
See working demo on IDEone.
Issues in your code
What I did to show them:
split some statements of yours into meaningful and testable parts
commented the issues (actual values and expected)
added an assert below some lines (to verify expected values)
added a fixing statement below (with some explanation)
String argChar = "AUHS";
// int asciiA = (int) 'A'; // actual: 65; expected: 64
int asciiA = (int) 'A' - 1; // should be an offset to have: (int) `A` - offset == 1
assert asciiA == 64;
int col = 0;
char letter = argChar.charAt(argChar.length()-1); // actual == expected: 'S'
int letterAsNumber = (int) letter - asciiA; // actual: 83 - 65: expected: 83 - 64;
assert letterAsNumber == 19;
// col += Math.pow(26, 0) + letterAsNumber; // actual: 20 = 1 + 19; expected: 19 = 1 * 19
col = (int) Math.pow(26, 0) * letterAsNumber; // multiply instead add
assert col == 19;
for(int i=1; i<argChar.length(); i++) {
letter = argChar.charAt(argChar.length() - (i + 1));
// letterAsNumber = ((int) letter - asciiA) * 26;
letterAsNumber = ((int) letter - asciiA); // should not add 26 at the end
// col += Math.pow(26, i) + letterAsNumber;
col += Math.pow(26, i) * letterAsNumber; // multiply instead add
}
assert col == 31999;
As counting starts from 1, and columns are counted from A, a correction argChar.charAt(i) - 'A' + 1 is needed to properly convert chars to digits:
String argChar = "AUHS";
int pow = 1;
int n = 0;
for (int i = argChar.length() - 1; i >= 0; i--) {
n += (argChar.charAt(i) - 'A' + 1) * pow;
pow *= 26;
}
System.out.println("n = " + n);
Output:
n = 31999

Converting to base 10 in java?

I have a homework assignment where I have to covert any base to base 10. I have some given numbers, which are the "basen". I have to convert those bases to base 10. The only part that I am stuck in is this part of the code:
answer = ; // Not sure what I have to put in here
I have seen some other posts about converting to base ten, but I am just not sure how to how to incorporate them into my code.
public class BaseN {
public static final int BASEN_ERRNO = -1;
public static int digit = 0;
public static void main(String[] argv) {
basen(512, 6);
basen(314, 8);
basen(49, 5);
basen(10101, 2);
}
public static void basen(int n, int b) {
int ans = basen(n, b, 1, 0);
if (ans == BASEN_ERRNO)
System.out.println(n + " is not a valid base-" + b + " number");
else
System.out.println(n + " base-" + b + " = " + ans + " base-10");
}
public static int basen(int number, int base, int placevalue, int answer) {
if (number == 0) return answer;
digit = number % 10;
if (digit >= base) return BASEN_ERRNO;
answer = 1;// not sure what to put here
number = 0;
placevalue = 0;
return basen(number, base, placevalue, answer);
}
}
You could look at a k length number of base n like this:
x(0)*n^(k-1) + x(1)*n^(k-2) + ... + x(k-1)*n^1 + x(k)*n^0
Where x(0), x(1), ..., x(k) is the digit at position k from the left.
So, if you are trying to convert, say, 101 base 2 to base 10 you would do the following :
1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 4 + 0 + 1 = 5 base 10
say you want to convert the number 352 from base 6:
3 * 6^2 + 5 * 6^1 + 2 * 6^0 = 108 + 30 + 2 = 145 base 10
What you're looking for code wise is something like this :
int[] digits = {3, 5, 2};
int base = 6;
int answer = 0;
for(int i = digits.length - 1; i >= 0; i--)
{
answer += digits[i] * Math.pow(base,digits.length-i-1);
}
return answer;
which will return 145.
Hopefully even though my implementation is iterative you should be able to apply it to your recursive implementation as well.
You can implement the following algorithm. Lets say you are given String number which represents the number you want to convert to decimal form and int base which represents the base of given number. You can implement function int convertToNumber(char c); which accepts one character representing one digit from your number and will map characters to numbers like this:
0 -> 0,
1 -> 1,
... ,
A-> 10,
B -> 11,
... ,
F -> 15,
...
Then you just iterate through your given string and multiply this functions output with base to the power of iteration. For example, convert number A32(hexadecimal):
A32 = convertToNumber(A) * b ^ 2 + convertToNumber(3) * b ^ 1 + convertToNumber(2) * b ^ 0 = 10 * 16 ^ 2 + 3 * 16 ^ 1 + 2 * 16 ^ 0 = 10 * 16 * 16 + 3 * 16 + 2 = 2610 (decimal).
public class BaseConvert {
public static int convertDigitToNumber(char c) throws Exception {
if(c >= '0' && c <= '9') return c - '0';
if(c >= 'A' && c <= 'Z') return c - 55;
if(c >= 'a' && c <= 'z') return c - 97;
throw new Exception("Invalid digit!");
}
public static int convertToBase(String number, int base) throws Exception {
int result = 0;
for(int i = 0; i < number.length(); i++){
result += convertDigitToNumber(number.charAt(i)) * (int)Math.pow(base, number.length() - i - 1);
}
return result;
}
public static void main(String[] args) {
try{
System.out.println(convertToBase("732", 8));
System.out.println(convertToBase("A32", 16));
System.out.println(convertToBase("1010", 2));
}catch (Exception e) {
System.out.print(e);
}
}
}

Output of converting string into number does not come as expected

Given a string as input, convert it into the number it represents. You can assume that the string consists of only numeric digits. It will not consist of negative numbers. Do not use Integer.parseInt to solve this problem.
MyApproach
I converted string to char array and stored the original number but I am unable to convert it into a single number
I tried converting individual elements but the digits can be of any length.So,It was difficult to follow that approach.
Hint:I have a hint that the numbers can be added using place values
For e.g if the number is 2300.I stored each number in the form of arrays.Then it should be 2*1000+3*100+0*10+0=2300
But I am unable to convert it into code.
Can anyone guide me how to do that?
Note I cannot use any inbuilt functions.
public int toNumber(String str)
{
char ch1[]=str.toCharArray();
int c[]=new int[ch1.length];
int k=0;
for(int i=0;i<c.length;i++)
{
if(ch1[i]==48)
{
c[k++]=0;
}
else if(ch1[i]==49)
{
c[k++]=1;
}
else if(ch1[i]==50)
{
c[k++]=2;
}
else if(ch1[i]==51)
{
c[k++]=3;
}
else if(ch1[i]==52)
{
c[k++]=4;
}
else if(ch1[i]==53)
{
c[k++]=5;
}
else if(ch1[i]==54)
{
c[k++]=6;
}
else if(ch1[i]==55)
{
c[k++]=7;
}
else if(ch1[i]==56)
{
c[k++]=8;
}
else if(ch1[i]==57)
{
c[k++]=9;
}
}
}
You don't need to do powers or keep track of your multiplier. Just multiply your running total by 10 each time you add in a new digit. And use c - '0' to turn a character into a number:
int n = 0;
for (int i = 0; i < str.length(); i++) {
n = n * 10 + str.charAt(i) - '0';
}
So for example for 1234 it goes
0 * 10 + 1 = 1
1 * 10 + 2 = 12
12 * 10 + 3 = 123
123 * 10 + 4 = 1234
A digit character ('0'-'9') can be converted into an integer value (0-9) using:
ch - '0'
This is because the digit characters are all consecutive in ASCII/Unicode.
As for calculating the full number, for the input 2300, you don't want:
2 * 1000 + 3 * 100 + 0 * 10 + 0
Instead, you'll want a more incremental approach using a loop:
r = 0
r = r * 10 + 2 (2)
r = r * 10 + 3 (23)
r = r * 10 + 0 (230)
r = r * 10 + 0 (2300)
This is much better than trying to calculate 1000 (Math.pow(10,3)), which your formula would require.
This should be enough information for you to code it. If not, create a new question.
If you loop through the char array you have and take the last value, put it through an if statement and add to an to number integer whatever that number is (use 10 if statements). Next go to the second to last value, and do the same thing only this time multiply the resulting numbers by 10 before adding it to the total number. Repeat this using 1 * 10^(value away from end) being multiplied to the number gotten from the if statements.
Well what comes to my mind when seeing this problem is to multiply the numbers you are getting with your current code with the place they have in the charArray:
int desiredNumber = 0;
for(int k=1; k<=c.length; k++) {
desiredNumber += c[k] * (Math.pow(10, c.length - k));
}
If you are not allowed to use the Math.pow() function then simply write one yourself with aid of a loop.
Greetings Raven
You can do
int no = 0;
for(int i = 0; i < c.length; i++){
no += c[i] * Math.pow(10, c.length - 1 - i);
}

Reading integers and getting the answer + 10

I have written a readInt() method to read integers from System.in but for some reason every integer returned is off by 10. This is regardless of whether the number is one or several digits and it is confusing me to no end. My code is below, where have I gone wrong?
/**
* #return The next integer read from the Input Stream
*/
public static int readInt() throws IOException {
BufferedInputStream in = new BufferedInputStream(System.in);
char c = (char) in.read();
int num = 0, cNum = Character.getNumericValue(c);
//Checks that the current value of c is in fact a single digit number (as it must be to be a char and an int)
while (cNum > -1 && cNum < 10) {
num = num * 10 + cNum;
c = (char) in.read();
cNum = Character.getNumericValue(c);
}
//If no number has been read, keep reading until one is read
if (num == 0 && c != '0') {
return readInt();
}
System.out.print(num + '\n');
return num;
}
EXAMPLE I/O:
INPUT (I): 1 - OUTPUT (O): 11
I: 2 - O: 12
I: 3 - O: 13
I: 5 - O: 15
I: 10 - O: 20
I: 99 - O: 109
I: 100 - O: 110
When you add a character to an integer it does integer arithmetic.
So
x + '\n'
is the same as
x + 10
because (int) '\n' is 10
What you intended is
x + "\n"
which does strings arithmetic
But a simpler/more efficient solution is
System.out.println(x);
Collin,
I hope you are fine.
I took a look at your code and tested it.
Apparently, the '\n' is the cause of your problem, because when I deleted it the result was fine.
if you want to start a new line, replace '\n' with "\n" (double quotes not single quotes).
I hope my answer did help :)

Categories

Resources