partitioning integer into almost equal elements - java

Is there a function somewhere that divides integer or decimal numbers into parts that are as equal as possible and sum up to the input value?
I'm looking for something that would work like that:
devide(4,2) -> {2,2} (2+2=4, 2 and 2 are equal)
devide(6,4) -> {2,2,1,1} (2+2+1+1=6, no way to make these numbers closer to each other)
I know I can do it myself but I'm looking for some library function.

I've never heard of a library that does that, but it'es quite easy. Just put the quotient in each cells of an array the size of the divisor, then put the remainder in each cell.
Example:
public static int[] divide(int n, int d){ //d for divisor
int[] res = new int[d];
int qu = n/d; //quotient
int rm = n%d; //remainder
for(int i=0; i<d; i++){
res[i] = qu;
if(i < rm){
res[i]++;
}
}
return res;
}

Related

saving many intgers into 1 integer

I am trying to save many natural numbers that are smaller than m into 1 natural number n.
I need a function to read i'th number from n.
In python I can do it like:
def read(n,m,i):#reads a number on index i from n.
return n//m**i%m
def save(numbers_to_save, m=None):#saves natural numbers, that are smaller than m to n.
if m is None:
m=max(numbers_to_save)+1
n=0
for i_number in range(len(numbers_to_save)):
n+=m**i_number*numbers_to_save[i_number]
return n
numbers_to_save=[12,54,3,7,23,8,9,3,72,3]
i_max=len(numbers_to_save)
m=max(numbers_to_save)+1
n=save(numbers_to_save,m)
del numbers_to_save
for i in range(i_max):
print(read(n,m,i),end=",")
But how to do it effectively in java reading n only byte per byte? n is bigger than maximum value of long, so I can not use long to save n.
To translate this code to Java, you would need to use BigInteger class.
It works similarly to Python's "infinite" size integers, but with two key differences:
It is immutable, which means every time you change it, the result is a new object you must store in place of the old one.
You can't use regular operators (+, -, *, +) on it directly, but instead you must use the instance methods such as add or pow.
Here is an example of how your read function will look in Java:
int read(BigInteger n, BigInteger m, int i) {
return n.divide(m.pow(i)).mod(m).intValue();
}
Note, that for simplicity, this code assumes that both i and m will be smaller than MAX_INT.
It is possible to make both of them BigInteger as well to allow them to be of any size.
A long can be used for that specific given numbers (since m**count < Long.MAX_VALUE).
import static java.lang.Math.*;
public static long save(int m, int... numbers) {
long result = 0;
long mult = 1;
for (var num : numbers) {
if (num <0 || num >= m) throw new IllegalArgumentException("invalid: " + num);
result = addExact(result, multiplyExact(mult, num));
mult = multiplyExact(mult, m);
}
return result;
}
public static int read(long compressed, int m, int i) {
return (int) (compressed / (long)pow(m, i) % m);
}
private static void test() {
int[] numbers = { 12, 54, 3, 7, 23, 8, 9, 3, 72, 3};
int m = Arrays.stream(numbers).max().orElseThrow() + 1;
long compressed = save(m, numbers);
for (var i = 0; i < numbers.length; i++) {
int val = read(compressed, m, i);
if (val == numbers[i])
System.out.println(val);
else
System.err.printf("%d != %d # %d%n", val, numbers[i], i);
}
}
I am a bit lazy, so I used the Math methods addExactly and multiplyExact that throw an Exception in case of overflow. Alternative: check if long can save that count of numbers given m at start of method and use
result += mult * num;
mult *= m;
instead in the loop.
Use BigInteger as posted in this answer), if more space is needed.
this code also works with int to compress less, smaller values

Return prime factors from int as input as an array

I need to code an algorithm which takes an int, gets its prime factors, puts them into an array and returns them.
My code is the following.
public static int[] primfaktorzerlegung(int zahl) {
int d=1; //this is the length of the array
int[] result = new int[d]; //array has to be returned
List<Integer> factors = new ArrayList<Integer>();
for(int factor = 2; factor <= zahl; factor++) {
while(zahl % factor == 0) {
factors.add(factor);
zahl = zahl / factor;
}
}
for(int i : factors){ //trying to get every number of the arraylist
int z = i;
result[d] = z; //trying to put the numbers of the arraylist into the array result
d++; //makes the array dimension one higher
}
return result; //returns the array
}
I get the following error:
Error: java.lang.ArrayIndexOutOfBoundsException:
Index 1 out of bounds for length 1
at: result[d] = z;
What could be the cause?
You are not actually increasing the size of the array by incrementing d. Once you have allocated the array, its size is fixed.
You can do this instead:
public static int[] primes(int number) {
List<Integer> factors = new ArrayList<>();
for(int factor = 2; factor <= number; factor++) {
while (number % factor == 0) {
factors.add(factor);
number = number / factor;
}
}
return factors.stream().mapToInt(n -> n.intValue()).toArray();
}
The stream() method exposes the ArrayList as a Stream, which allows you do use nice methods to manipulate collections. One of them is mapToInt, which allows you do apply a function to each element in the stream. You apply the function that takes an n and returns whatever comes in the body (the part after the ->). In particular, since you are putting together a collection of boxed Integers, you have to unbox them into ints (more on boxing here). The intValue() method does exactly that. Finally, you return an int[] by calling toArray() on it. In practice, you are saying: apply intValue() to each item in the list and return the resulting array.
Note that I took your main logic as is, I didn't go into the correctness of how you are computing prime factors.

Java Compute C(n,k) and factorial with biginteger

I want to compute the answer of C(n,k),such as C(10,2)=10*9/2*1 = 45
If I test my code by small numbers like 10, the code works.
However, when I try to compute C(1000,900), it compiles
Exception in thread "main" java.lang.ArithmeticException: / by zero
I've seen someone says it should use BigInteger,But after I tried, it still has errors.
For example: I change int factorial into BigInteger factorial,
while the for loop in cSelect, I can not change int i into BigInteger type,
As result, the answer up/factorial(y) has errors.
Please help me to fix this problem. Thanks!!
public class Test {
// Write a factorial function
static int factorial(int m) {
int result =1;
for (int i=2; i<=m; i++) {
result = result*i;
}
return result;
}
// Caculate C(x,y)
static int cSelect(int x, int y) {
int up=1;
for(int i=x; i>=(x-y+1); i--) {
up = up*i;
}
return up/factorial(y);
}
public static void main(String[] args) {
System.out.println(cSelect(1000,900));
}
}
Your code is fairly easy to translate in factorial. Start with ONE, multiply by the BigInteger.valueOf(long) for each i in your loop. Like,
// Write a factorial function
static BigInteger factorial(int m) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= m; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
Your other function does exactly the same, plus a division by the result of factorial(y). Like,
// Caculate C(x,y)
static BigInteger cSelect(int x, int y) {
BigInteger up = BigInteger.ONE;
for (int i = x; i >= (x - y + 1); i--) {
up = up.multiply(BigInteger.valueOf(i));
}
return up.divide(factorial(y));
}
With no other changes I get
63850511926305130236698511142022274281262900693853331776286816221524376994750901948920974351797699894319420811933446197797592213357065053890
Which I assume is correct.
First, return value must be BigInteger, because result of C(1000,900) far exceeds the range on an int.
Second, you don't need separate factorial() method. Doing the division as you iterate will improve memory footprint by not creating excessively large intermediate values (at cost of doing multiple divisions, but even so it might actually be faster).
Like this:
static BigInteger cSelect(int x, int y) {
BigInteger v = BigInteger.ONE;
for (int i = x, j = 1; j <= y; i--, j++)
v = v.multiply(BigInteger.valueOf(i)).divide(BigInteger.valueOf(j));
return v;
}
By counting i down and j up, there will never be a fraction from the division.
Test
System.out.println(cSelect(10, 2));
System.out.println(cSelect(1000, 900));
Output
45
63850511926305130236698511142022274281262900693853331776286816221524376994750901948920974351797699894319420811933446197797592213357065053890
You have to use BigInteger to do the calculation.
The value you are trying to compute is approximately 6.385051192630516e+139 and it is not representable as a Java primitive integer value.
Even if the result was representable, the reason you are getting divide by zero errors is that the divisor expression 900! ∗ 100! is overflowing to zero. You then divide by that zero.
The reason that it overflows to zero is that it is divisible by 2^32 and 2^64. That can be proven by using some simple algebra to compute the number of factors of 2 there are in 900! and 100!

Decimal to binary convertor

I've been trying to write a small and simple program that converts dec numbers to bin.The idea is that when the user enters a positive integer a for- cycle have to go through all the rounds of deviding the number /2 but it also have to get the tail (idk the math term really the actuall bin numbers) and write them in an array, thats the part Im having trouble with.I have predefined the array size of 30 (cant find a way to make a working array without specifying it's length) my idea was that then I could make a reversed array with length = index(i from the first for cycle) from the previous array with another for cycle etc. but when I tested the first array all I get is empty brackets printed: [] or nothing at all, eclipse doesnt find any errors in the code and I cant figure out whats wrong.I could use some help.Anyways here's the code:
public static void decToBin(){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
if (n <= 0) {System.out.println("ERROR:n<=0");return;}
else if (n > 0){
int[] ostataci = new int[30];
for (int i = 0;n <= 0;i++){
ostataci[i] = n % 2;
n = n / 2;
// System.out.printf("%d %n", ostataci[i]); - even this one doesnt print at all
}
// System.out.println(Arrays.toString(ostataci)); - nor this one
}
}
Thanks for the replies Ive learnt a few new things.But since Im a newbie I wanted to do it with the metod I described thx for pointing me the error in the for cycle, that was my biggest problem, anyway heres the last code I wrote( working correctly) thats what I was trying to do from the beggining.
public static void decToBin2(){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
int i = 0;
int[] ostataci = new int[32];
if (n <= 0) {System.out.println("ERROR:n<=0");return;}
else if (n > 0){
while (n > 0){
i++;
ostataci[i] = n % 2;
n = n / 2;
}
}
int reverse = i;
int[] reversed = new int[reverse];
for (int i2 = 0;i2 != reverse;i--,i2++){
reversed[i2] = ostataci[i];
System.out.print(reversed[i2]);
}
}
The immediate error is in the for loop:
else if (n > 0) {
// Since n > 0 it'll never run
for (int i = 0;n <= 0;i++)
The implementation itself could be something like that (keep it simpler!):
...
if (n <= 0)
System.out.println("ERROR:n<=0");
else {
// Why do we need array/ArrayList etc.? We are supposed to build a string!
StringBuilder Sb = new StringBuilder();
// while we have something to do...
// (are we supposed to compute exact number of steps? No)
while (n > 0) {
Sb.insert(0, n % 2);
n /= 2;
}
System.out.println(Sb.toString());
}
Your loop for (int i = 0;n <= 0;i++){ } won't execute because you know that n is positive (by your if condition), but the for condition demands that n be negative (n <= 0). I suspect you mean n>0 instead.
As for variable length arrays you can use Lists, although that might be better to add in later
your for loop is wrong for (int i = 0;n <= 0;i++){ this just wont run change it to something like this while (n > 0) { and your code will works fine. also int is 32 bit so change int[] ostataci = new int[30]; to int[] ostataci = new int[32]; although it is better to uselist instead of array.
Decimals are already converted to binary on the computer, why don't you use bit wise operations to check the saved integer? Eg to check if bit n of an int is set, evaluate the boolean (number >> n) & 1. Just put that in a loop and you're done. Everyone else is making it too complicated.
Here is an alternative approach, using the shift operator and bit-masking:
public static int[] dec2bin(int n) {
int[] result = new int[32];
for (int i = 0; i < 32; i++) {
result[31-i] = n & 0x1;
n >>= 1;
}
return result;
}
This will also work just fine for negative numbers.
Example usage:
public static void main(String[] args) {
int[] result = dec2bin(5);
for (int i : result)
System.out.print(i);
System.out.flush();
}
Ouput:
00000000000000000000000000000101
Explaination
The code n & 0x1 from above is bit-masking. The 0x1 is hex notation for the number 1. In binary, that number looks like this:
00000001
In the first iteration of the for loop, n looks like:
00000101
The & operator does a bit-by-bit (bitwise) comparison of the bits in the two numbers, 'anding' them together, producing a new number based on those comparisons. If either or both of the corresponding bits are 0, the resulting bit is 0. If both of them are 1, the resulting bit is 1. So, for the two numbers listed above, the result of 'anding' them together is:
00000001
Or, in decimal, 1. You'll note that that also happens to be the bit value of the rightmost bit in n. Which we save into the result array at the rightmost index.
Next, we shift (>>) n right by 1. This moves every bit along by one (the rightmost bit is lost), and the resulting n is now:
00000010
We repeat that process 32 times (for each of the 32 bits of an int) and at the end we get a result array containing the correct answer.
Try this:
package mypackage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.Arrays;
public class Converter{
final static int ARRAY_SIZE = 30;
public static void main(String[] args){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
if (n <= 0){
System.out.println("ERROR:n<=0");
return;
}else if (n > 0){
int[] ostataci = new int[ARRAY_SIZE];
int i = 0;
while (n>0){
ostataci[i] = n % 2;
i++;
n = n / 2;
System.out.printf("%d %n", ostataci[i]);
}
System.out.println("All done!");
System.out.println(Arrays.toString(ostataci));
}
}
}

Decimal-to-binary conversion

I want to convert decimal numbers to binary numbers. I want to store them in an array.
First I need to create an array that has a certain length so that I can store the binary numbers. After that I perform the conversion, here is how I do it:
public class Aufg3 {
public static void main(String[] args) {
int[] test = decToBin(12, getBinArray(12));
for(int i = 0; i < test.length; i++){
System.out.println(test[i]);
}
}
public static int[] getBinArray(int number){
int res = number, length = 0;
while(res != 0){
res /= 2;
length++;
}
return new int[length];
}
public static int[] decToBin(int number, int[] array){
int res = number, k = array.length-1;
while(res != 0){
if(res%2 == 0){
array[k] = 0;
}else{
array[k] = 1;
}
k--;
res /= 2;
}
return array;
}
}
Is there anything to improve? It should print 1100 for input of 12.
Why not just use the toBinaryString method of the Integer class:
System.out.println(Integer.toBinaryString(12))
I assume you want to write your own code -- otherwise this is straightforward to do using methods from the standard Java library.
Some quick comments:
You can get rid of the res temp vars. Work directly on number (remember that Java passes parameters by value).
Shift is more efficient than division (number >>>= 1 instead of number /= 2), although the compiler should be able to optimize this anyway
You can avoid the modulus in decToBin if you just do array[k] = number & 1;
While you are at it, why not call getBinArray from decToBin directly? Then you can call decToBin with only one arg -- the value to convert.
Here is a slightly optimized version of your code:
public static int[] getBinArray(int number) {
int length = 0;
while (number != 0) {
number >>>= 1;
length++;
}
return new int[length];
}
public static int[] decToBin(int number) {
int[] array = getBinArray(number);
int k = array.length-1;
while (number != 0)
{
array[k--] = number & 1;
number >>>= 1;
}
return array;
}
If this isn't homework, no need to do it yourself. The following code should work:
BigInteger bigInt = new BigInteger(number);
String asString = bigInt.toString(2);
There might be more efficient ways, but this is certainly very readable and maintainable.
There are some small things that you can improve:
You should define a "high-level" method that converts an int to an int[]. In the current code you have to mention the 12 two times, which is bad.
You should use a do { ... } while (number != 0) loop. Otherwise the number 0 will be represented by an empty array.
You should use x >>> 1 instead of x / 2, since that handles negative numbers correctly.
If you want to check that your code is correct, write another method that converts back from binary to int. Then you can check that binToDec(decToBin(12, ...)) == 12.
The method getBinArray should not be public, since it is only a helper method. You can either replace the public with private or just remove the public.

Categories

Resources