Java find second-leading digit in int - java

I am working on a Java problem in which I need to check if the second-leading digit of an int (ex: the '2' in 123, or the '8' in 58347) of any size is a particular digit (such as a '2' or a '5'), and then assign true to a Boolean, if it is that digit. I am trying to do the modulo/divisor method, but I am not able to extract the second-leading digit if the number is large.
I searched Stack Overflow, and found a very similar question. However, the solution for that question works if the number is hard-coded as being two digits. I know there is a way by converting int to String, and I tried that method successfully, but I need to use int/modulo/division method. I tried doing (n%100)/10; but it got me second-to-last digit (ex: the '7' in 4562374), not second-after-first digit.
// n is a number such as 123, or 25, or 52856.
while (n > 0) {
int i=((n%10)/10);
if( (i==2)||(i==3) || (i==5)|| (i==7) )
{ secondDigit=true; }
else { secondDigit= false; } }
System.out.println(secondDigit);

Just keep dividing by 10 until the number is < 100 then do modulo 10, example:
class Main {
public static void main(String[] args) {
int n = 58347;
while (n >= 100) {
n /= 10;
}
System.out.println(n % 10); // prints 8
}
}

Not certain about the efficiency of this method, however its easy to read.
Integer.parseInt(String.valueOf(Math.abs(initial_value)).charAt(1)+"")
However, you have to ensure that the number has more than 1 digit.

Instead of repeatedly dividing the number you have until it's small enough for you to handle, how about finding out how big the number is so you only need to do a single division?
What I mean is that you should consider using logarithms to find out the magnitude of your number. Finding the base 10 logarithm of your number gets you its magnitude. For 100 the log_10 is 2, so you can do the following:
long magnitude = Math.log10(number);
long divisor = Math.pow(10, magnitude - 1);
long smallNumber = number / divisor;
int digit = smallNumber % 10;

Related

Program isn't terminating for a specific input

I am trying to write a program that will let me know if a number has the odd divisor greater than one. Let's n be the number, and x be the divisor. x%2!=0 and x>1;
Code:
import java.util.Scanner;
public class Simple1{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
long n;
for(int i=0; i<t; i++) {
n=sc.nextLong();
if(n<3)System.out.println("NO");
else {
if(n%2!=0)System.out.println("YES");
else {
int ans=0;
for(long j=3; j<=n/2; j+=2) {
if(n%j==0) {
ans=1;
break;
}
}
if(ans==1)System.out.println("YES");
else System.out.println("NO");
}
}
}
}
}
This java code works fine. But it's not working for a specific input.. and that is n = 1099511627776. If I change the last digit to any int other than 6, then it works fine and gives output. Even numbers greater than that works. But only this number n=1099511627776, when I input this to my program, no terminating happens and no output. Help me to figure out what happens here.
The number 1099511627776 is two to the power 40. That means it has to check through the whole big for-loop to find no odd factors. You would get the same problem, to different extents, with 2199023255552 (2 to the 41) and 549755813888 (2 to the 39). You have to wait longer if you want to do it this way.
A much faster way is to divide n by 2 until you get an odd number.
E.g.
long n = sc.nextLong();
while (n > 1 && n % 2 == 0) {
n /= 2;
}
if (n > 1) {
System.out.println("Yes.");
} else {
System.out.println("No.");
}
An even faster way to tell if a number is a power of two is a bit-twiddling hack:
// Powers of 2 have the property that n & (n-1) is zero
if ((n & (n - 1)) != 0) {
System.out.println("Yes."); // Not a power of two, so has an odd factor
} else {
System.out.println("No."); // Is a power of two, so does not have an odd factor
}
Can you get rid of the powers of two another way?
long number = 1099511627776l;
long r = number >> Long.numberOfTrailingZeros​(number);
Then r is an odd divisor, which might be greater than one.
If you think in base 10, then you know a number is divisible by ten if has a trailing zero. You can remove all of the powers of 10 by removing all of the zeros. It is the same for base 2, you can remove all of the factors of 2 by removing all of the trailing zeros (in binary representation).

Improve performance of string to binary number conversion

This is one of the questions that I faced in competitive programming.
Ques) You have an input String which is in binary format 11100 and you need to count number of steps in which number will be zero. If number is odd -> subtract it by 1, if even -> divide it by 2.
For example
28 -> 28/2
14 -> 14/2
7 -> 7-1
6 -> 6/2
3 -> 3-1
2 -> 2/2
1-> 1-1
0 -> STOP
Number of steps =7
I came up with the following solutions
public int solution(String S) {
// write your code in Java SE 8
String parsableString = cleanString(S);
int integer = Integer.parseInt(S, 2);
return stepCounter(integer);
}
private static String cleanString(String S){
int i = 0;
while (i < S.length() && S.charAt(i) == '0')
i++;
StringBuffer sb = new StringBuffer(S);
sb.replace(0,i,"");
return sb.toString();
}
private static int stepCounter(int integer) {
int counter = 0;
while (integer > 0) {
if (integer == 0)
break;
else {
counter++;
if (integer % 2 == 0)
integer = integer / 2;
else
integer--;
}
}
return counter;
}
The solution to this question looks quite simple and straightforward, however the performance evaluation of this code got me a big ZERO. My initial impressions were that converting the string to int was a bottleneck but failed to find a better solution for this. Can anybody please point out to me the bottlenecks of this code and where it can be significantly improved ?
If a binary number is odd, the last (least significant) digit must be 1, so subtracting 1 is just changing the last digit from 1 to 0 (which, importantly, makes the number even).
If a binary number is even, the last digit must be 0, and dividing by zero can be accomplished by simply removing that last 0 entirely. (Just like in base ten, the number 10 can be divided by ten by taking away the last 0, leaving 1.)
So the number of steps is two steps for every 1 digit, and one step for every 0 digit -- minus 1, because when you get to the last 0, you don't divide by 2 any more, you just stop.
Here's a simple JavaScript (instead of Java) solution:
let n = '11100';
n.length + n.replace(/0/g, '').length - 1;
With just a little more work, this can deal with leading zeros '0011100' properly too, if that were needed.
Number of times you need to subtract is the number of one bits which is Integer.bitCount(). Number of times you need to divide is the position of most-significant bit which is Integer.SIZE (32, total number of bits in integer) minus Integer.numberOfLeadingZeros() minus one (you don't need to divide 1). For zero input I assume, the result should be zero. So we have
int numberOfOperations = integer == 0 ? 0 : Integer.bitCount(integer) +
Integer.SIZE - Integer.numberOfLeadingZeros(integer) - 1;
As per the given condition, we are dividing the number by 2 if it is even which is equivalent to remove the LSB, again if number is odd we are subtracting 1 and making it an even which is equivalent to unset the set bit (changing 1 to 0). Analyzing the above process we can say that the total number of steps required will be the sum of (number of bits i.e. (log2(n) +1)) and number of set bits - 1(last 0 need not to be removed).
C++ code:
result = __builtin_popcount(n) + log2(n) + 1 - 1;
result = __builtin_popcount(n) + log2(n);

sum of first and last digit in the integer

The method written in the below code needs to take integer and result sum of 1st digit and last digit in the integer.
NOTE: The reason i am asking this question though i got to know the correct solution is i need to understand why my code is not working also as that makes me a better programmer please help.
public class FirstLastDigitSum {
public static int sumFirstAndLastDigit(int number)//to add first and last
//digits of a given interger
{
int firstdigit=0;
int lastdigit=0;
if(number>=0 && number<=9)
{
return number+number;
}
else if(number>9)
{
lastdigit=number%10;
while(number>0)
{
number/=10;
if(number<=9 & number>=0){
firstdigit=number;
}
}
return firstdigit+lastdigit;
}
else
return -1;
}
public static void main(String[] args)
{
System.out.println(sumFirstAndLastDigit(121));
}
}
In the above code if i keep number/=10 after if block like below
if(number<=9 & number>=0){
firstdigit=number;
}
number/=10;
then my code is giving proper results. like if i input 121 to the method as first digit is 1 and second digit is 1 it is summing both and giving me result 2. which is absolutely correct
But if keep number/=10 above the if block like below
number/=10;
if(number<=9 & number>=0){
firstdigit=number;
}
Then my code is not giving proper result it is giving only last number which is 1.
I am not at all understanding why this is happening can any one explain please.
Lets break this up into two parts. Get the last digit of the number, and getting the first digit of the number.
The first part of the problem is easy. Its exactly what you already have; just take modulo 10 of the number.
int lastdigit = number % 10;
The second part is a little trickier, but not too much. While the number is greater than 10 divide it by 10 (using integers you will have truncation for the remainder). One problem I see in your solution is that you keep checking the value even after a digit is discovered. That means if the value was 1234, you correctly find 1, but then overwrite it to 0 with an extra loop iteration
int firstdigit = number;
while (firstdigit >= 10) {
firstdigit /= 10;
}
And that's it, you are done. Just return the value.
return firstdigit + lastdigit;
If the number is less than 0 then return -1. Otherwise the last number can be found by modulus 10, and the first number found by dividing by 10 until that number is less than 10.
public static int sumFirstAndLastDigit(int number) {
if (number < 0) {
return -1;
}
int last = number % 10;
int first = number;
while (first >= 10) {
first = first / 10;
}
return first + last;
}
In this case:
while(number>0)
{
number/=10;
if(number<=9 & number>=0){
firstdigit=number;
}
}
Note that you change number after you check number > 0. That means that number can be 0 when reaches the if statement and if it is 0 it will be accepted as first digit because it satisfies the condition number<=9 & number>=0. As an example, when you test it with 121 you have this values for number 121, 12, 1 and 0. The last one satisfies the if statement and set first digit to 0.
In this case:
while(number>0)
{
if(number<=9 & number>=0){
firstdigit=number;
}
number/=10;
}
You change number before you check number > 0. That means that the if statement will never have a number = 0 and firstdigit will never be 0. As an example, when you test it with 121 you have this values for number 121, 12, and 1. The last one satisfies the if statement and set first digit to 1. After that you divide number by zero and it becomes 0 and it stop the while loop.
This is not a direct solution to your problem, but we can fairly easily handle this using regex and the base methods:
int number = 12345678;
String val = String.valueOf(number);
val = val.replaceAll("(?<=\\d)\\d+(?=\\d)", "");
number = Integer.parseInt(val);
int sum = number % 10 + number / 10;
System.out.println(sum);

How to know the lowest value that is not in a group of numbers

I have a group of numbers 0 to 9 => {0 .. 9}, but another group that represent each amount of {0 .. 9} we have, for example:
0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
5 => 6
6 => 7
7 => 8
8 => 9
9 => 1
The lowest value that we cannot represent with those groups is 99. They are digits to represent a number, for example if we only have:
2 => 2
7 => 1
The lowest value should be 0 or 1, and the possibilities are, 2, 7, 22, 27, 72, 227, 272, 722.
I am doing an algorithym in java to calculate the lowest value that we cannot represent, but I even do not very well how to do it, and I need a little or big help.
Thanks.
You should decompose your problem.
Global algorithm
IMO, you should start at n = 0, and go up. For each value of n, check if the sequence of digits needed to represent it is allowed. As soon as you can't, n is your answer.
Smaller part
The new problem is to verify if the sequence of digits for a given number is allowed. That does not seem very difficult. You seem to deal with base 10 numbers only I guess:
decompose your number in base 10 digits
count the number of occurrences of each digit in your number
compare with the quantity available of that digit
if there are not enough, you're done, the number can't be represented
if there are enough, keep going with the other digits
Example implementation of the main algo. The argument nbAllowed would be a 10-sized array containing the quantity available of each digit. Ex: nbAllowed[2] is the number of times that the digit '2' is allowed to be used.
public static int smallestNonRepresentable(int[] nbAllowed) {
int n=0;
while (isRepresentable(n, nbAllowed)) {
n++;
}
return n;
}
Example implementation of the subroutine. This methods returns whether n is representable depending on the quantity available for each digit.
private static boolean isRepresentable(int n, int[] nbAllowed) {
int[] digitCount = getDigitCount(n);
// check if each digit is available enough times
for (int d = 0; d < nbAllowed.length; d++) {
if (nbAllowed[d] < digitCount[d]) {
return false; // not enough d digits to represent n
}
}
return true; // enough of all digits
}
Example implementation of how to count the number of occurrences of each digit in a number n. This method returns a 10-sized array containing the number of occurrences of each digit in n. Ex: digitCount[2] is the number of times that the digit '2' appears in the decimal representation of n.
private static int[] getDigitCount(int n) {
int[] digitCount = new int[10]; // 10 distinct digits
Arrays.fill(digitCount, 0); // start at 0 occurrence for each digit
// special case 0
if (n == 0) {
digitCount[0] = 1; // 1 occurrence for digit '0'
return digitCount;
}
// fill digitCount with the number of occurrences of each digit in n
int digit;
while(n > 0) {
digit = n % 10; // current last digit of n
digitCount[digit]++; // increments the number of occurrences for that digit
n /= 10; // shifts the decimal number n to the right (last digit disappears)
}
return digitCount;
}
The problem can be solved by not applying brute-force. There are four cases to distinguish in the given order, which means if we evaluate case 3, case 1 and 2 did not apply:
There is at least one digit with an amount of zero: then the smallest of those digits is not representable.
The set of digits with the smallest available amount does not contain the digit zero: now we know the amount is greater than zero and hence repeating the smallest of those digits one more time than available digits is the smallest non representable number.
The set of digits with the smallest available amount has a size of one: now we know it has to be the digit zero having an amount greater than zero. And we know the next greater digit, the one is available, due to passed through case 1. Hence the number composed of a leading 1 followed by amount many zeros is the smallest non representable number.
We know the set of digits with the smallest available amount contains the digit zero and at least one more digit: hence repeating the second smallest digit of this set one more time than available digits is the smallest non representable number.
Expressed in terms of a Java program the main algorithm looks like this:
private static final List<Integer> DIGIT_POOL =
Arrays.asList(2, 1, 3, 4, 5, 6, 7, 8, 9, 1);
public static void main(String[] args) {
Map<Integer, List<Integer>> amountToDigits = mapToDigits(DIGIT_POOL);
String number;
int amount = amountToDigits.keySet().iterator().next();
List<Integer> digits = amountToDigits.get(amount);
if (amount == 0) {
number = number(digits.get(0), 1);
} else if (!digits.contains(0)) {
number = number(digits.get(0), amount + 1);
} else if (digits.size() == 1) {
number = paddedWithZero(1, amount + 2);
} else {
number = number(digits.get(1), amount + 1);
}
System.out.println(number);
}
private static SortedMap<Integer, List<Integer>> mapToDigits(List<Integer> digitAmounts) {
SortedMap<Integer, List<Integer>> amountToDigits = new TreeMap<>();
for (int digit = 0; digit <= 9; digit++) {
int amount = digitAmounts.get(digit);
List<Integer> digits = amountToDigits.get(amount);
if (digits == null) {
digits = new ArrayList<>();
amountToDigits.put(amount, digits);
}
digits.add(digit);
}
return amountToDigits;
}
Constructing the resulting non representable number requires the following helper methods:
private static String paddedWithZero(Integer digit, int length) {
char[] letters = letters(0, length);
letters[0] = digit.toString().charAt(0);
return new String(letters);
}
private static String number(Integer digit, int length) {
return new String(letters(digit, length));
}
private static char[] letters(Integer digit, int length) {
char[] letters = new char[length];
Arrays.fill(letters, digit.toString().charAt(0));
return letters;
}
The total complexity of the algorithms is the sum of:
mapping n digits to their amounts: O(n)
distinguishing between four cases: O(1)
constructing a number of lenght m + 1, where m is the smallest amount of available digits: O(m)
Hence the total complexity is O(max(n, m)) which is linear. This solution works pretty fast for very large amounts (1k and greater) of given digits.
When you're going from the lowest point, it's usually prudent to start at 0. So we'll need some sort of loop, and because we don't know how many times we'll look, we'll implement a while loop.
boolean numberFound = false;
while(!numberFound) {
// Loops while a number has not been found.
}
We also need to keep track of our current number, so we'll declare a pointer p.
int p = 0;
boolean numberFound = false;
while(!numberFound) {
}
Now, let's assume you've got all these values in an array. So 1 is in position 0, 2 is in position 1 etc. You need to get the first value of p. Now, for any value of p between 9 and 0 inclusively, we can just grab the number of occurrences, so we do something like:
if(p <= 9 && p >= 0) {
// Get the number of occurrences.
int numberOfDigits = digits[p] // Digits is your array as described above.
if(numberOfDigits == 0) {
// You only need one digit to represent this number.
// If you don't have one digit, you've just found a number that works.
numberFound = true;
}
}
Next, you'll need to deal with numbers larger than 9. Because this has more than one digit, you'll need to do this in stages:
First, convert the Integer into a String.
Next, cycle through each character in that String.
Parse that character back to an integer, and grab the value from the array.
Get the number of times that character occurs in a string.
If the value in the array is less than the number of times that value occurs..
You've found a number.
Else, keep looping.
Good luck with the last part of the solution. As a general rule, when it looks like someone hasn't made much of an effort with a problem, I don't provide the entire solution.
My understanding is the same as Joffrey's algo.
Write a method like:
public boolean checkIfInGroup(int value) {
...
}
then you can create a loop in your outer method:
int n=0;
while (checkIfInGroup(n)) {
n++;
}
return n;
The challenge would be how to optimize the checkIfInGroup() method.
If I understood you correctly, you have one Array with numbers from 0 - 9 and another one with the same numbers in a different order. You want to know, which number is the one below the smallest displayable. So, if I understood you correctly, it should always be -1, because, if you have numbers from 0 - 9, 0 is the lowest displayable number, so -1 is the one beneath that. Could I help?

Last nth digit of an integer

I am having my final exam tomorrow so i am practicing some questions.But i am stuck at this question.
Write a method named getNthDigit that returns the n-th digit of an integer.It should work for negative numbers as well.
Eg.
CALL VALUE RETURNED
getNthDigit(123,1) 3
getNthDigit(123,2) 2
getNthDigit(123,3) 1
getNthDigit(-123,1) 3
My code:
public static void getNthDigit(int x,int y){
x=Math.abs(x);
x%10;
}
My thought process is everytime i modulo it by 10,it gives me the last digit.But it is still wrong.Like if i call for getNthDigit(123,2) ,i no longer need the last digit value.
Instead of strings, you could do:
(Math.abs(x) / Math.pow(10, y - 1)) % 10
abs(n) takes care of the negative case.
n / 10^(y - 1) truncates n to the first (counting from the left) y digits.
% 10 gets the last digit of that resulting number.
Modular arithmetic can be used to accomplish what you want. For example, if you divide 123 by 10, and take the remainder, you'd get the first digit 3. If you do integer division of 123 by 100 and then divide the result by 10, you'd get the second digit 2. More generally, the n-th digit of a number can be obtained by the formula (number / base^(n-1)) % base:
public int getNthDigit(int number, int base, int n) {
return (int) ((number / Math.pow(base, n - 1)) % base);
}
System.out.println(getNthDigit(123, 10, 1)); // 3
System.out.println(getNthDigit(123, 10, 2)); // 2
System.out.println(getNthDigit(123, 10, 3)); // 1
Hope it helps.
Why not simply convert the number to string and then get the character at the required position ?
public static void getNthDigit(int x,int y){
String str = String.valueOf(x);
if(str.charAt(0) == '-')
y++;
System.out.println(str.charAt(y-1));
}
I'd write it into a string, strip off any leading -ve and then just index into the string (handling the fact you want 1 based indexes where Java uses 0 based).
Try this:
String s = String.valueOf(x);
int index = s.length()- y;
char result = s.charAt(index);

Categories

Resources