How to print very big numbers to the screen - java

In an interview I had, I was asked to write a program that prints to the screen the numbers 1,2,3,4,5....until 99999999999999.....?(the last number to print is the digit 9 million times)
You are not allowed to use Big-Integer or any other similar object.
The hint I got is to use modulo and work with strings, I tried to think about it but haven't figured it out.
Thanks in advance

You need an array to store the number, and perform operations on the array.
Here's an example
public class BigNumberTest2 {
public static void main(String[] args) {
/*Array with the digits of the number. 0th index stores the most significant digit*/
//int[] num = new int[1000000];
//Can have a million digits, length is 1 + needed to avoid overflow
int[] num = {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int base = 10;
int step = 1;
String endNum = "100000000000000000000000000000000000000000000000000020";//Can have a million digits
while(true) {
//Increment by step
for(int carry = step, i = num.length - 1; carry != 0 && i >= 0; i--) {
int newDigit = num[i] + carry;
num[i] = newDigit % base;
carry = newDigit / base;
}
//Find the position of most significant digit
int mostSignificantDigitIndex = 0;
while(num[mostSignificantDigitIndex] == 0) {/*No need to check if firstNonZero < num.length, as start num >=0 */
mostSignificantDigitIndex++;
}
StringBuilder strNum = new StringBuilder();
//Concatenate to get actual string
for(int i = mostSignificantDigitIndex; i < num.length; i++) {
strNum.append(num[i]);
}
System.out.println(strNum);
//Check if number current number is greater or equal to endNum
if(strNum.length() > endNum.length() || (strNum.length() == endNum.length() && strNum.toString().compareTo(endNum) >= 0)) {
break;
}
}
}
}
Output
1000000000000000000000000000000000000000000000000000001
1000000000000000000000000000000000000000000000000000002
1000000000000000000000000000000000000000000000000000003
1000000000000000000000000000000000000000000000000000004
1000000000000000000000000000000000000000000000000000005
1000000000000000000000000000000000000000000000000000006
1000000000000000000000000000000000000000000000000000007
1000000000000000000000000000000000000000000000000000008
1000000000000000000000000000000000000000000000000000009
1000000000000000000000000000000000000000000000000000010
1000000000000000000000000000000000000000000000000000011
1000000000000000000000000000000000000000000000000000012
1000000000000000000000000000000000000000000000000000013
1000000000000000000000000000000000000000000000000000014
1000000000000000000000000000000000000000000000000000015
1000000000000000000000000000000000000000000000000000016
1000000000000000000000000000000000000000000000000000017
1000000000000000000000000000000000000000000000000000018
1000000000000000000000000000000000000000000000000000019
1000000000000000000000000000000000000000000000000000020

Something like this:
This is a PHP, but you could transform it to java easy...
Recursion with increasing number through string.
function nextNum($num="", $step=1, $end="999999999999999999") {
$string = "";
$saving = 0;
for($i=strlen($num)-1; $i>=0; $i--) {
$calc = intval(intval($num[$i]) + $saving);
if ($i==(strlen($num)-1)) $calc = $calc + $step;
if (strlen($calc)==2) {
$calc = $calc."";
$saving = intval($calc[0]);
$calc = intval($calc[1]);
}
else {
$calc = intval($calc);
$saving = 0;
}
$string = $calc . $string;
}
if ($saving!=0) $string = $saving.$string;
echo $string." ";
if ($end == $string || strlen($end)<strlen($string)) { return; }
else return nextNum($string, $step, $end);
}
nextNum("0", 1, "999999999999999999");
I didn't test it... but it should work..

Related

Multiplicative Sum Solver not functioning

In a class I am taking, we are supposed to solve equations that look like this ([] = digit):
[][]*[][][]=[][][][]
Where each digit 1-9 can only be used once.
The one the code I have made is solving is [][]*[][][]=4396
I have code that is free of errors, but will not do the intended action
Disclaimer: The code does not check if the digits 1-9 are only used once, that is up for the human to decide (for now, please do not add this function in any example code)
Here is the code:
public class MK1
{
public static void main(String[] args)
{
//the full sum
long sum = 4396;
long guess = 10000, guessCopy, otherSum = 0;
short count = 0;
//the digits used to guess the number
long[] digits = new long[5];
while(guess <= 99999)
{
//sets the different indexes of digits[] to the digits of guess
guessCopy = guess;
count = 0;
while(guessCopy > 0)
{
digits[count] = (guessCopy % 10);
guessCopy = guessCopy / 10;
count++;
}
//determining if the guess is correct
otherSum = ((digits[4]*10) + digits[3]) * ((digits[2]*100) + (digits[1]*10) + digits[0]);
if(otherSum == sum)
{
//Print out digits that work
for(int i = 0; i > digits.length; i++)
{
System.out.println(digits[i]);
//print out the separation between different solutions
if(i == digits.length -1)
{
System.out.println("next possible solution");
}
}
}
//iterating the guess
guess++;
}
}
}
For one, your digits are backwards in your otherSum calculation line. Also, your loop to print digits has the wrong comparison sign, it should be i < digits.length. Here is working code you should replace in:
//determining if the guess is correct
otherSum = ((digits[0]*10) + digits[1]) * ((digits[2]*100) + (digits[3]*10) + digits[4]);
if(otherSum == sum)
{
//Print out digits that work
for(int i = 0; i < digits.length; i++)
{
System.out.println(digits[i]);
//print out the separation between different solutions
if(i == digits.length -1)
{
System.out.println("next possible solution");
}
}
}
You might also want to consider switching your output to look better, right now its very vertical and tough to interpret.

Given a number n, list all n-digit numbers such that each number does not have repeating digits

I'm trying to solve the following problem. Given an integer, n, list all n-digits numbers such that each number does not have repeating digits.
For example, if n is 4, then the output is as follows:
0123
0124
0125
...
9875
9876
Total number of 4-digit numbers is 5040
My present approach is by brute-force. I can generate all n-digit numbers, then, using a Set, list all numbers with no repeating digits. However, I'm pretty sure there is a faster, better and more elegant way of doing this.
I'm programming in Java, but I can read source code in C.
Thanks
Mathematically, you have 10 options for the first number, 9 for the second, 8 for the 3rd, and 7 for the 4th. So, 10 * 9 * 8 * 7 = 5040.
Programmatically, you can generate these with some combinations logic. Using a functional approach usually keeps code cleaner; meaning build up a new string recursively as opposed to trying to use a StringBuilder or array to keep modifying your existing string.
Example Code
The following code will generate the permutations, without reusing digits, without any extra set or map/etc.
public class LockerNumberNoRepeats {
public static void main(String[] args) {
System.out.println("Total combinations = " + permutations(4));
}
public static int permutations(int targetLength) {
return permutations("", "0123456789", targetLength);
}
private static int permutations(String c, String r, int targetLength) {
if (c.length() == targetLength) {
System.out.println(c);
return 1;
}
int sum = 0;
for (int i = 0; i < r.length(); ++i) {
sum += permutations(c + r.charAt(i), r.substring(0,i) + r.substring(i + 1), targetLength);
}
return sum;
}
}
Output:
...
9875
9876
Total combinations = 5040
Explanation
Pulling this from a comment by #Rick as it was very well said and helps to clarify the solution.
So to explain what is happening here - it's recursing a function which takes three parameters: a list of digits we've already used (the string we're building - c), a list of digits we haven't used yet (the string r) and the target depth or length. Then when a digit is used, it is added to c and removed from r for subsequent recursive calls, so you don't need to check if it is already used, because you only pass in those which haven't already been used.
it's easy to find a formula. i.e.
if n=1 there are 10 variants.
if n=2 there are 9*10 variants.
if n=3 there are 8*9*10 variants.
if n=4 there are 7*8*9*10 variants.
Note the symmetry here:
0123
0124
...
9875
9876
9876 = 9999 - 123
9875 = 9999 - 124
So for starters you can chop the work in half.
It's possible that you might be able to find a regex which covers scenarios such that if a digit occurs twice in the same string then it matches/fails.
Whether the regex will be faster or not, who knows?
Specifically for four digits you could have nested For loops:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j != i) {
for (int k = 0; k < 10; k++) {
if ((k != j) && (k != i)) {
for (int m = 0; m < 10; m++) {
if ((m != k) && (m != j) && (m != i)) {
someStringCollection.add((((("" + i) + j) + k) + m));
(etc)
Alternatively, for a more generalised solution, this is a good example of the handy-dandy nature of recursion. E.g. you have a function which takes the list of previous digits, and required depth, and if the number of required digits is less than the depth just have a loop of ten iterations (through each value for the digit you're adding), if the digit doesn't exist in the list already then add it to the list and recurse. If you're at the correct depth just concatenate all the digits in the list and add it to the collection of valid strings you have.
Backtracking method is also a brute-force method.
private static int pickAndSet(byte[] used, int last) {
if (last >= 0) used[last] = 0;
int start = (last < 0) ? 0 : last + 1;
for (int i = start; i < used.length; i++) {
if (used[i] == 0) {
used[i] = 1;
return i;
}
}
return -1;
}
public static int get_series(int n) {
if (n < 1 || n > 10) return 0;
byte[] used = new byte[10];
int[] result = new int[n];
char[] output = new char[n];
int idx = 0;
boolean dirForward = true;
int count = 0;
while (true) {
result[idx] = pickAndSet(used, dirForward ? -1 : result[idx]);
if (result[idx] < 0) { //fail, should rewind.
if (idx == 0) break; //the zero index rewind failed, think all over.
dirForward = false;
idx --;
continue;
} else {//forward.
dirForward = true;
}
idx ++;
if (n == idx) {
for (int k = 0; k < result.length; k++) output[k] = (char)('0' + result[k]);
System.out.println(output);
count ++;
dirForward = false;
idx --;
}
}
return count;
}

All digits in int are divisible by certain int

I am trying to figure out how to count all numbers between two ints(a and b), where all of the digits are divisible with another int(k) and 0 counts as divisible.Here is what I've made so far, but it is looping forever.
for (int i = a; i<=b; i++){
while (i < 10) {
digit = i % 10;
if(digit % k == 0 || digit == 0){
count ++;
}
i = i / 10;
}
}
Also I was thinking about comparing if all of the digits were divisible by counting them and comparing with number of digits int length = (int)Math.Log10(Math.Abs(number)) + 1;
Any help would be appreciated. Thank you!
Once you get in to your while block you're never going to get out of it. The while condition is when i less than 10. You're dividing i by 10 at the end of the whole block. i will never have a chance of getting above 10.
Try this one
public class Calculator {
public static void main(String[] args) {
int a = 2;
int b = 150;
int k = 3;
int count = 0;
for (int i = a; i <= b; i++) {
boolean isDivisible = true;
int num = i;
while (num != 0) {
int digit = num % 10;
if (digit % k != 0) {
isDivisible = false;
break;
}
num /= 10;
}
if (isDivisible) {
count++;
System.out.println(i+" is one such number.");
}
}
System.out.println("Total " + count + " numbers are divisible by " + k);
}
}
Ok, so there are quite a few things going on here, so we'll take this a piece at a time.
for (int i = a; i <= b; i++){
// This line is part of the biggest problem. This will cause the
// loop to skip entirely when you start with a >= 10. I'm assuming
// this is not the case, as you are seeing an infinite loop - which
// will happen when a < 10, for reasons I'll show below.
while (i < 10) {
digit = i % 10;
if(digit % k == 0 || digit == 0){
count ++;
// A missing line here will cause you to get incorrect
// results. You don't terminate the loop, so what you are
// actually counting is every digit that is divisible by k
// in every number between a and b.
}
// This is the other part of the biggest problem. This line
// causes the infinite loop because you are modifying the
// variable you are using as the loop counter. Mutable state is
// tricky like that.
i = i / 10;
}
}
It's possible to re-write this with minimal changes, but there are some improvements you can make that will provide a more readable result. This code is untested, but does compile, and should get you most of the way there.
// Extracting this out into a function is often a good idea.
private int countOfNumbersWithAllDigitsDivisibleByN(final int modBy, final int start, final int end) {
int count = 0;
// I prefer += to ++, as each statement should do only one thing,
// it's easier to reason about
for (int i = start; i <= end; i += 1) {
// Pulling this into a separate function prevents leaking
// state, which was the bulk of the issue in the original.
// Ternary if adds 1 or 0, depending on the result of the
// method call. When the methods are named sensibly, I find
// this can be more readable than a regular if construct.
count += ifAllDigitsDivisibleByN(modBy, i) ? 1 : 0;
}
return count;
}
private boolean ifAllDigitsDivisibleByN(final int modBy, final int i) {
// For smaller numbers, this won't make much of a difference, but
// in principle, there's no real reason to check every instance of
// a particular digit.
for(Integer digit : uniqueDigitsInN(i)) {
if ( !isDigitDivisibleBy(modBy, digit) ) {
return false;
}
}
return true;
}
// The switch to Integer is to avoid Java's auto-boxing, which
// can get expensive inside of a tight loop.
private boolean isDigitDivisibleBy(final Integer modBy, final Integer digit) {
// Always include parens to group sub-expressions, forgetting the
// precedence rules between && and || is a good way to introduce
// bugs.
return digit == 0 || (digit % modBy == 0);
}
private Set<Integer> uniqueDigitsInN(final int number) {
// Sets are an easy and efficient way to cull duplicates.
Set<Integer> digitsInN = new HashSet<>();
for (int n = number; n != 0; n /= 10) {
digitsInN.add(n % 10);
}
return digitsInN;
}

How to add numbers(integers) that are stored inside a string

I have to create a program that uses Luhn's algorithm to check to see if a credit card is valid.
The algorithm is this:
Form a sum of every other digit, including the right-most digit; so
5490123456789128 sums to 8+1+8+6+4+2+0+4 = 33
Form double each remaining digit, then sum all the digits that creates it; the remaining digits in our example (5 9 1 3 5 7 9 2) double to 10 18 2 6 10 14 18 4, which sums to 1+0+1+8+2+6+1+0+1+4+1+8+4 = 37
Add the two sums above (33+37 = 70)
If the result is a multiple of 10 (i.e., its last digit is 0) then it was a valid credit card number.
I made a Scanner and saved the credit card number into String card number
Then I created a while loop to save every other character starting from the right into a string. So now, I have a string filled with every other digit of the credit card number, starting from the right. However, I need to add up all of the digits within that string, which I can't figure out.
For example, if the user entered 1234 as the card number, the string everyotherdigit = 42. How can I add up 4 and 2 within the string?
There are numerous ways to do that. You can actually find your own solution by doing a bit of googling.
Anyway, this is what you can do:
Get individual characters from your string, and convert them to int.
String cardNumber = "5490123456789128";
int value = cardNumber.charAt(0) - '0';
Using a for loop and changing 0 to x(loop counter) will solve everything.
Get single String and convert to int.
String cardNumber = "5490123456789128";
int value = Integer.parseInt(cardNumber.substring(0,1));
I'd treat the string as an array of chars, and use Character.digit(int, int) to convert each character to the corresponsing int:
public static boolean isValidCreditCard (String s);
char[] arr = s.toCharArray();
int everyOtherSum = 0;
for (int i = arr.length - 1; i >= 0; i -= 2) {
everyOtherSum += Character.digit(arr[i], 10);
}
int doubleSum = 0;
for (for (int i = arr.length - 2; i >= 0; i -= 2) {
int currDigit = Character.digit(arr[i], 10);
int doubleDigit = currDigit * 2;
while (doubleDigit > 0) {
doubleSum += (doubleDigit % 10);
doubleDigit /= 10;
}
}
int total = everyOtherSum + doubleSum;
return total % 10 == 0;
}
So something like this would work for you:
public static void main(String[] args)
{
String cardNum = "5490123456789128";
String others = null;
int evenDigitSum = 0;
int oddDigitTransformSum = 0;
for (int pos = 0; pos < cardNum.length(); pos++)
{
if ((pos%2) != 0)
{
evenDigitSum += (cardNum.charAt(pos) - '0');
}
else
{
others = Integer.toString((cardNum.charAt(pos)-'0')*2);
for (char c : others.toCharArray())
{
oddDigitTransformSum += (c-'0');
}
}
}
System.out.println("Odds: " + oddDigitTransformSum);
System.out.println("Evens: " + evenDigitSum);
System.out.println("Total: " + (evenDigitSum+oddDigitTransformSum));
System.out.println("Valid Card: " + ((evenDigitSum+oddDigitTransformSum)%10==0));
}
public int cardCount(String numbers){
Stack<Integer> stack = new Stack<>();
int count = 0;
for(char c : numbers.toCharArray()){
stack.push(Character.getNumericValue(c));
}
int size = stack.size();
for(int i=1;i <= size; i++){
if(i%2 != 0){
count = count + stack.pop();
}else{
stack.pop();
}
}
return count;
}
This just does what you asked, not the entire algorithm

Integer to binary array

I'm trying to convert an integer to a 7 bit Boolean binary array. So far the code doesn't work:
If i input say integer 8 to be converted, instead of 0001000 I get 1000000, or say 15 I should get 0001111 but I get 1111000. The char array is a different length to the binary array and the positions are wrong.
public static void main(String[] args){
String maxAmpStr = Integer.toBinaryString(8);
char[] arr = maxAmpStr.toCharArray();
boolean[] binaryarray = new boolean[7];
for (int i=0; i<maxAmpStr.length(); i++){
if (arr[i] == '1'){
binaryarray[i] = true;
}
else if (arr[i] == '0'){
binaryarray[i] = false;
}
}
System.out.println(maxAmpStr);
System.out.println(binaryarray[0]);
System.out.println(binaryarray[1]);
System.out.println(binaryarray[2]);
System.out.println(binaryarray[3]);
System.out.println(binaryarray[4]);
System.out.println(binaryarray[5]);
System.out.println(binaryarray[6]);
}
Any help is appreciated.
There's really no need to deal with strings for this, just do bitwise comparisons for the 7 bits you're interested in.
public static void main(String[] args) {
int input = 15;
boolean[] bits = new boolean[7];
for (int i = 6; i >= 0; i--) {
bits[i] = (input & (1 << i)) != 0;
}
System.out.println(input + " = " + Arrays.toString(bits));
}
I would use this:
private static boolean[] toBinary(int number, int base) {
final boolean[] ret = new boolean[base];
for (int i = 0; i < base; i++) {
ret[base - 1 - i] = (1 << i & number) != 0;
}
return ret;
}
number 15 with base 7 will produce {false, false, false, true, true, true, true} = 0001111b
number 8, base 7 {false, false, false, true, false, false, false} = 0001000b
Hints: Think about what happens when you get a character representation that's less than seven characters.
In particular, think about how the char[] and boolean[] arrays "line up"; there will be extra elements in one than the other, so how should the indices coincide?
Actual answer: At the moment you're using the first element of the character array as the first element of the boolean array, which is only correct when you're using a seven-character string. In fact, you want the last elements of the arrays to coincide (so that the zeros are padded at the front not at the end).
One way to approach this problem would be to play around with the indices within the loop (e.g. work out the size difference and modify binaryarray[i + offset] instead). But an even simpler solution is just to left pad the string with zeros after the first line, to ensure it's exactly seven characters before converting it to the char array.
(Extra marks: what do you do when there's more than 7 characters in the array, e.g. if someone passes in 200 as an argument? Based on both solutions above you should be able to detect this case easily and handle it specifically.)
What you get when you do System.out.println(maxAmpStr); is "1000" in case of the 8.
So, you only get the relevant part, the first "0000" that you expected is just ommitted.
It's not pretty but what you could do is:
for (int i=0; i<maxAmpStr.length(); i++)
{
if (arr[i] == '1')
{
binaryarray[i+maxAmpStr.length()-1] = true;
}
else if (arr[i] == '0')
{
binaryarray[i+maxAmpStr.length()-1] = false;
}
}
Since nobody here has a answer with a dynamic array length, here is my solution:
public static boolean[] convertToBinary(int number) {
int binExpo = 0;
int bin = 1;
while(bin < number) { //calculates the needed digits
bin = bin*2;
binExpo++;
}
bin = bin/2;
boolean[] binary = new boolean[binExpo]; //array with the right length
binExpo--;
while(binExpo>=0) {
if(bin<=number) {
binary[binExpo] = true;
number =number -bin;
bin = bin/2;
}else {
binary[binExpo] = false;
}
binExpo--;
}
return binary;
}
The char-array is only as long as needed, so your boolean-array might be longer and places the bits at the wrong position. So start from behind, and when your char-array is finished, fill your boolean-array with 0's until first position.
Integer.toBinaryString(int i) does not pad. For e.g. Integer.toBinaryString(7) prints 111 not 00000111 as you expect. You need to take this into account when deciding where to start populating your boolean array.
15.ToBinaryString will be '1111'
You are lopping through that from first to last character, so the first '1' which is bit(3) is going into binaryArray[0] which I'm assuming should be bit 0.
You ned to pad ToBinaryString with leading zeros to a length of 7 (8 ??)
and then reverse the string, (or your loop)
Or you could stop messing about with strings and simply use bit wise operators
BinaryArray[3] = (SomeInt && 2^3 != 0);
^ = power operator or if not (1 << 3) or whatever is left shift in Java.
public static boolean[] convertToBinary(int b){
boolean[] binArray = new boolean[7];
boolean bin;
for(int i = 6; i >= 0; i--) {
if (b%2 == 1) bin = true;
else bin = false;
binArray[i] = bin;
b/=2;
}
return binArray;
}
public static String intToBinary(int num) {
int copy = num;
String sb = "";
for(int i=30; i>=0; i--) {
sb = (copy&1) + sb;
copy = copy >>>=1;
}
return sb;
}
AND the number with 1
Append the vale to a string
do unsigned right shift
repeat steps 1-3 for i=30..0
String maxAmpStr = Integer.toBinaryString(255);
char[] arr = maxAmpStr.toCharArray();
boolean[] binaryarray = new boolean[20];
int pivot = binaryarray.length - arr.length;
int j = binaryarray.length - 1;
for (int i = arr.length - 1; i >= 0; i--) {
if (arr[i] == '1') {
binaryarray[j] = true;
} else if (arr[i] == '0') {
binaryarray[j] = false;
}
if (j >= pivot)
j--;
}
System.out.println(maxAmpStr);
for (int k = 0; k < binaryarray.length; k++)
System.out.println(binaryarray[k]);
}

Categories

Resources