Basic recursion with bacteria - java

Just starting to learn recursion and I am confused on this bacteria problem. Basically, I must create a method that multiplies the bacteria over a certain amount of hours. The pattern/ equation for this is bacteriaLastHour + bacteriaLastHour * 2. As an example, after one hour there will be 10 + 10 * 2 = 30 bacteria, and after 2 hours there will be 30 + 30 * 2 = 90 bacteria.
Here is my code:
public static int numBacteriaAlive(int hour)
{
int bacteriaLastHour = 10;
int total = 0;
// Write a base case
if(hour == 0){
return 10;
}
// Write a recursive call
total += (bacteriaLastHour * 2) + numBacteriaAlive(hour-1);
bacteriaLastHour *= 3;
return total;
}
For hours 1 & 2, the method works perfectly, returning 10 & 30. Yet for the other hours, the variable bacteriaLastHour doesn't change and therefore the number it return is off. My code returns 50 for 2hours (should be 90), 70 for 3hours (should be 270), etc. Any advice helps, thank you!
Edit: Cannot change parameter values

It's a lot simpler than you're imagining:
public static int numBacteriaAlive(int hour) {
if (hour == 0) { // base case
return 10;
}
int bacteriaLastHour = numBacteriaAlive(hour-1); // recursive case
return bacteriaLastHour*3;
}
Note: bacteriaLastHour + 2*bacteriaLastHour is the same as bacteriaLastHour*3
Once you've written the base case (for hour==0) then you must trust that numBacteriaAlive(hour-1) will return the correct value. Once you know that, returning the answer for the current hour value is easy.

Related

Minimum number of powers of 2 to get an Integer?

I was asked below question in an interview:
Every number can be described via the addition and subtraction of powers of 2. For example, 29 = 2^0 + 2^2 + 2^3 + 2^4.
Given an int n, return minimum number of additions
and subtractions of 2^i to get n.
Example 1:
Input: 15
Output: 2
Explanation: 2^4 - 2^0 = 16 - 1 = 15
Example 2:
Input: 8
Output: 1
Example 3:
Input: 0
Output: 0
Below is what I got but is there any way to improve this or is there any better way to solve above problem?
public static int minPowerTwo(int n) {
if (n == 0) {
return 0;
}
if (Integer.bitCount(n) == 1) {
return 1;
}
String binary = Integer.toBinaryString(n);
StringBuilder sb = new StringBuilder();
sb.append(binary.charAt(0));
for (int i = 0; i < binary.length() - 1; i++) {
sb.append('0');
}
int min = Integer.parseInt(sb.toString(), 2);
sb.append('0');
int max = Integer.parseInt(sb.toString(), 2);
return 1 + Math.min(minPowerTwo(n - min), minPowerTwo(max - n));
}
Well... we can deduce that each power of two should be used only once, because otherwise you can get the same result a shorter way, since 2x + 2x = 2x+1, -2x - 2x = -2x+1, and 2x - 2x = 0.
Considering the powers used in order, each one has to change the corresponding bit from an incorrect value to the correct value, because there will be no further opportunities to fix that bit, since each power is used only once.
When you need to add or subtract, the difference is what happens to the higher bits:
000000 000000 111100 111100
+ 100 - 100 + 100 - 100
------ ------ ------ ------
000100 111100 000000 111000
One way, all the higher bits are flipped. The other way they are not.
Since each decision can independently determine the state of all the higher bits, the consequences of choosing between + or - are only relevant in determining the next power of 2.
When you have to choose + or -, one choice will correct 1 bit, but the other choice will correct 2 bits or more, meaning that the next bit that requires correction will be higher.
So, this problem has a very straightforward solution with no dynamic programming or searching or anything like that:
Find the smallest power of 2 that needs correction.
Either add it or subtract it. Pick the option that corrects 2 bits.
Repeat until all the bits are correct
in java, that would look like this. Instead of finding the operations required to make the value, I'll find the operations required to change the value to zero, which is the same thing with opposite signs:
int minPowersToFix(int val) {
int result = 0;
while(val!=0) {
++result;
int firstbit = val&-val; //smallest bit that needs fixed
int pluscase = val+firstbit;
if ((pluscase & (firstbit<<1)) == 0) {
val+=firstbit;
} else {
val-=firstbit;
}
}
return result;
}
And, here is a test case to check whether a solution is correct, written in Java.
(It was written for my solution, which is proven not correct in some case, so I removed that answer, but the test case is still relevant.)
Matt Timmermans's answer passes all the test cases, including negative numbers.
And, Integer.bitCount(val ^ (3 * val)) passes most of them, except when input is Integer.MAX_VALUE.
Code
MinCountOf2PowerTest.java
import org.testng.Assert;
import org.testng.annotations.Test;
public class MinCountOf2PowerTest {
#Test
public void testPositive() {
// no flip,
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01010001", 2)), 3);
// flip,
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("011", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("0111", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01111", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.MAX_VALUE), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01101", 2)), 3);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("011011", 2)), 3);
// flip, there are multiple flippable location,
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("0100000111", 2)), 3);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("010010000000111", 2)), 4);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("0100100000001111111", 2)), 4);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("010011000000001111111", 2)), 5);
}
#Test
public void testZero() {
Assert.assertEquals(MinCountOf2Power.minCount(0), 0);
}
#Test
public void testNegative() {
Assert.assertEquals(MinCountOf2Power.minCount(-1), 1);
Assert.assertEquals(MinCountOf2Power.minCount(-9), 2);
Assert.assertEquals(MinCountOf2Power.minCount(-100), 3);
}
// a positive number has the same result as its negative number,
#Test
public void testPositiveVsNegative() {
for (int i = 1; i <= 1000; i++) {
Assert.assertEquals(MinCountOf2Power.minCount(i), MinCountOf2Power.minCount(-i));
}
Assert.assertEquals(MinCountOf2Power.minCount(Integer.MAX_VALUE), MinCountOf2Power.minCount(-Integer.MAX_VALUE));
}
// corner case - ending 0,
#Test
public void testCornerEnding0() {
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01110", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("011110", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("011100", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("0111000", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01110000", 2)), 2);
}
// input from OP's question, refer: https://stackoverflow.com/questions/57797157
#Test
public void testOpInput() {
Assert.assertEquals(MinCountOf2Power.minCount(15), 2);
Assert.assertEquals(MinCountOf2Power.minCount(8), 1);
Assert.assertEquals(MinCountOf2Power.minCount(0), 0);
}
}
Tips:
It's written in Java, and use TestNG.
But you can use JUnit instead simply by replacing the import statement, I guess.
Or translate to other languages by coping the input / output value pairs with specific syntax.
I also found that a positive integer always has the same result as its negative number.
And there is a test case included to proved that.
I wrote this algorithm to solve the problem.
Given N a positive integer:
Find the highest power of 2 A and the lowest power of 2 B, such that A ≤ N ≤ B and A≠B. In other words find in what interval of
consecutive powers of 2 N belongs;
Find if N is closer to A or B, for example by comparing N with the mid value between A and B (It is their average, and since B=2×A the average is 3×A/2 or 1.5×A)
If N is closer to the lower bound (A) than N = A + δ: Append "subtract B" to the explanation message;
If N is closer to the higher bound (B) than N = B - δ: Append "add A" to the explanation message;
Replace N with δ and repeat
The number of iterations minus 1 is the solution you are looking for.
To solve step 1 I wrote this support method that returns the closest power of 2 that is smaller than input, that is A (and we can get B because it is just the double of A)
public int getClosestLowerboundPowerof2 (int n)
{
int i = 1;
while (i<=n/2){
i*=2;
}
return i;
}
The rest is done here:
int operations;
String explanation = "";
if (input>0){
operations = -1;
int n = input, a;
while (n >= 1) {
operations++;
a = getClosestLowerboundPowerof2(n);
if (n > a*1.5) {
explanation += " - "+ a * 2;
n = a * 2 - n;
} else {
explanation += " + " + a;
n -= a;
}
}
System.out.println(input + " = " + explanation.substring(3,explanation.length()) + ", that " + ((operations==1)?"is":"are") + " "+ operations + " operation" + ((operations==1)?"":"s"));
}
else{
System.out.println("Input must be positive");
}
As an example with input = 403 it would print:
403 = 512 - 128 + 16 + 2 + 1, that are 4 operations
Hope I helped!
NOTE: I first misinterpreted the question so I put effort in writing a detailed answer to the wrong problem...
I'm keeping here the original answer because it may be interesting for somebody.
The problem is actually a mathematical argument: how to convert a
number from base 10 to base 2, and they just asked you to implement
an algorithm for that.
Here some theory about this concept and here a method for
reference.
Programmatically I'm interpreting the problem as "Given an integer
print a string of its representation in base 2". For instance given
100 print 2^6 + 2^5 + 2^2. As the linked wiki on radixes explains,
that there is no need for subtractions, so there will only be
additions.
The shortest way to do is to start from n, halve it at each iteration
(i), and write 2^i only if this number (m) is odd. This is tested
with modulo operator (% in java). So the method will be just
this:
public String from10to2(int n){
String str = "";
for (int m = n, i=0; m>=1; m/=2, i++){
str = ((m%2==1)?"+ 2^"+i+" ":"")+str; //"adds '+ 2^i' on top of the string when m is odd, keep str the same otherwise
}
return str.substring(2,str.length()); //debug to remove " + " at the start of the string
}
The content of the for may look inintuitive because I put effort to
make the code as short as possible.
With little effort my method can be generalized to convert a number in
base 10 to any base:
public String baseConverter(int targetBase, int decimalNumber){
String str = "";
for (int m = decimalNumber, i=0; m>=1; m/=targetBase, i++){
str = ((m%targetBase==1)?"+ "+targetBase+"^"+i+" ":"")+str; //"adds '+ x^i' on top of the string when m is odd, keep str the same
otherwise
}
return str.substring(2,str.length()); //debug to remove " + " at the start of the string
}
PS: I didn't use StringBuilder because it's not conceived to append a string on the start. The use of the String concatenation as I
did is argument of debate (someone approve it, other don't).
I guess
For example, 29 = 2^0 + 2^2 + 2^3 + 2^4
is not a correct example in the context of this question. As far as I understand, I should be able to do like
29 = 2^5 - 2^2 + 2^0
Alright, basically this is a math problem. So if math isn't your best suit like me then i would advise you to consider logarithm in the first place whenever you see exponentials in a question. Sometimes it is very useful like in this case since it reduces this problem to a sort of coin change problem with dynamical denominators and also subtraction is allowed.
First I need to find the biggest n that's close to the target.
Lets find the exact n value in 2^n = 29 which is basically log
(2^n) = log 29, which is n log 2 = log 29 so n = log 29 / log
2. Which happens to be 4.857980995127573 and now i know that i
will start with by rounding it to 5.
2^5 is an overshoot. Now i need to reach 32-29 = 3 and also since 32 > 29 the result, 2^2 will be subtracted.
Now we have 2^5 - 2^2 which is 28 and less than 29. Now we need to add the next result and our target is 1.
Ok here is a simple recursive code in JS. I haven't fully tested but seemingly applies the logic just fine.
function pot(t, pr = 0){ // target and previous result
var d = Math.abs(t - pr), // difference
n = Math.round(Math.log(d)/Math.log(2)), // the n figure
cr = t > pr ? pr + 2**n // current result
: pr - 2**n;
return t > cr ? `2^${n} + ` + pot(t, cr) // compose the string result
: t < cr ? `2^${n} - ` + pot(t, cr)
: `2^${n}`;
}
console.log(pot(29));
console.log(pot(1453));
console.log(pot(8565368));
This seems pretty trivial to solve for the cases presented in the examples, like:
0111...1
You can replace any of this pattern with just two powers; i.e.: 7 = 8 - 1 or 15 = 16 - 1 and so on.
You can also deduce that if there are less then 3 consecutive ones, you don't gain much, for example:
0110 (4 + 2)
0110 (8 - 2)
But at the same time, you don't lose anything by doing that operation; in contrast for some cases this is even beneficial:
0110110 - // 54, this has 4 powers
we can take the "last" 0110 and replace it with 1000 - 0010 (8-2) or:
0111000 - 000010 (56 - 2)
but now we can replace 0111 with just two powers : 1000 - 0001.
As such a simple "replace" algorithm can be made:
static int count(int x) {
String s = new StringBuffer(Integer.toBinaryString(x)).reverse().toString() + "0";
Pattern p = Pattern.compile("1+10");
Matcher m = p.matcher(s);
int count = 0;
while (m.find()) {
++count;
s = m.replaceFirst("1");
m = p.matcher(s);
}
return Integer.bitCount(Integer.parseInt(s, 2)) + count;
}

Project Euler #3 - Solution runs forever

First time I've ever encountered this problem. It feels like it will never end.
My approach:
import java.util.TreeSet;
public class Euler3 {
public static void main(String[] args) {
long result = 0;
long startTime = System.nanoTime();
long numberGiven = 600851475143L;
TreeSet<Long> nums = new TreeSet<>();
for (long i = 2L; i < numberGiven; i++) {
if (numberGiven % i == 0 && isPrime(i)) {
nums.add(i);
}
}
result = nums.last();
System.out.print("Result: " + result +
".\nTime used for calculation in nanoseconds: " +
(System.nanoTime() - startTime) + ".");
}
public static boolean isPrime(long n) {
if (n <= 3) {
return n == 1 ? false : true;
} else if (n % 2 == 0 || n % 3 == 0) {
return false;
} else {
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
}
}
Of course this works on smaller numbers, but as is probably intended doesn't seem effective on over 600 billion.
I'm wondering, without giving the answer away:
Is there some obvious alteration I could employ to reduce the
running time/checks necessary?
Although it clearly doesn't work effectively here, is this approach
otherwise acceptable or would someone who posted this challenge,
even with a smaller number, be looking for something different?
I tried with integers the first time and got an overflow related error, is anything similar happening under the hood that would actually prevent this from terminating?
For every number you're checking that's a factor, you're doing an internal loop to figure out if it's a prime. That means your algorithm is effectively performing n * m operations.
You can instead use the following mathematical "trick", which I think is the same used by the UNIX factor program.
Since every number over one is either prime or a unique product of a set of primes (with potential duplicates in the set), we can just start dividing the number by the first prime two (actually reducing the number in the process) until that's no longer possible (i.e., it becomes odd). At that point, the reduced number will not have two or any multiples of two as a factor.
Then we do the same by continuously dividing by three until that's no longer possible.
Now you'd think that may be onerous but, because you've stripped out all the 'two' factors, the number cannot possibly be a multiple of four (or any other even number for that matter). So we detect that and move up to the next divisor of five and start dividing by that.
So the division operation are only done for prime divisors, speeding things up considerably. In addition, once the divisor gets above the square root of the (reduced) number, no more factors are possible, so we exit. In that case, the reduced number gives us the final (hence highest) prime factor.
For example, consider the number 924:
Number Divisor Result
------ ------- ------
924 2* 462
462 2* 231
231 2 not divisible, go to 3
231 3* 77
77 3 not divisible, go to 4
77 4 not divisible, go to 5
77 5 not divisible, go to 6
77 6 not divisible, go to 7
77 7* 11
11* 7 stop since 7 * 7 > 11
So the prime factors of 924 are {2, 2, 3, 7, 11}.
Now I urge you to try that algorithm on your own before looking below since the entire point of Euler is to test your own abilities. I simply provide the solution for completeness:
public class Test
{
public static void main(String[] args) {
long startTime = System.nanoTime();
long number = 600851475143L;
// Start with a divisor of two,
// continue until over sqrt(number).
long divisor = 2L;
while (divisor * divisor <= number) {
if ((number % divisor) == 0) {
// If factor, output then reduce number.
System.out.println(divisor);
number = number / divisor;
} else {
// Otherwise, move to next divisor.
divisor++;
}
}
// Final number is final divisor.
System.out.println(number);
System.out.print("Time used for calculation in nanoseconds: " +
(System.nanoTime() - startTime) + ".");
}
}
That gives you the four prime factors in about five thousandths of a second (on my box, anyway):
71
839
1471
6857
Time used for calculation in nanoseconds: 458826.
The program can be simple like this, which runs under a second:
long val = 600851475143L;
long ans = 0;
for(long i = 2; i*i <= val; i++){
if(val % i == 0){
ans = i;
while(val % i == 0)//This step will make sure that i is prime
val /= i;
}
}
if(val != 1){//If val is not 1, so val is a prime
ans = val > ans ? val : ans;
}
System.out.println(ans);
Answer is 6857, and it is correct answer :)
Notice that we only check for all i values which i*i smaller than val.

Euler Challenge 1 in Java - I'm doing something wrong?

http://projecteuler.net/problem=1
Hey. I'm a high schooler trying to get a good grasp on programming problems, so I visited Project Euler. For Problem 1, I wrote up some code in Java that would of solved it, but something is evidently going wrong. Can I get some insight as to what?
Explanation:
I stop everything at the index value of 332 because Java counts from 0, and 333 * 3 is 999 which is below 1,000. Apples is a seperate class with pretty much the same code, although it counts for 5. At the end, I manually add together the two answers, but it wasn't right. What am I doing wrong?
The two final sums are:
Three: 164838
Five: 97515
public class Learning {
public static void main(String[] args){
int three[] = new int[333];
int counter = 0;
three[332] = 0;
int totalthree = 0;
int threeincrementer = 1;
int grandtotal;
boolean run = true;
boolean runagain = true;
for (counter = 1; counter<=332; counter++){
three[counter] = 3 * counter;
if (!(three[332] == 0)){
System.out.println("Finished three.");
while (run == true){
totalthree = totalthree + three[threeincrementer];
threeincrementer++;
if (threeincrementer >= 332){
run = false;
System.out.println("Three final is: " + totalthree);
}
}
}
if (runagain == true){
apples ApplesObject = new apples();
ApplesObject.rerun(0);
runagain = false;
}
}
}
}
Some numbers are at the same time multiplication of 3 AND 5 like 15 so you shouldn't separately calculate sum of all multiplications of 3 and multiplications of 5 and than add them because you will end up doing something like
sum3 = 3,6,9,12,15,...
sum5 = 5,10,15,...
so first sum3 will include 15, and sum5 will also include it which means you will add 15 two times. Now to balance your calculations you will need to subtract from your sum3+sum5 sum which will add all multiplications of 15
sum15 = 15,30,45,...
So using your approach your final formula should look like sum3+sum5-sum15.
But simpler solution for this problem can look like
sum = 0
for each X in 1...999
if (X is multiplication of 3) OR (X is multiplication of 5)
add X to sum
To check if some number X is multiplication of number Y you can use modulo operator % (example reminder = X % Y) which finds the remainder of division of one number by another.
You can find more Java operators here

Given a stock of integers 0-9, what is the last number I can write before I run out of some integer?

As the title says, given a stock of integers 0-9, what is the last number I can write before I run out of some integer?
So if I'm given a stock of, say 10 for every number from 0 to 9, what is the last number I can write before I run out of some number. For example, with a stock of 2 I can write numbers 1 ... 10:
1 2 3 4 5 6 7 8 9 10
at this point my stock for ones is 0, and I cannot write 11.
Also note that if I was given a stock of 3, I could still write only numbers 1 ... 10, because 11 would cost me 2 ones, which would leave my stock for ones at -1.
What I have come up so far:
public class Numbers {
public static int numbers(int stock) {
int[] t = new int[10];
for (int k = 1; ; k++) {
int x = k;
while (x > 0) {
if (t[x % 10] == stock) return k-1;
t[x % 10]++;
x /= 10;
}
}
}
public static void main(String[] args) {
System.out.println(numbers(4));
}
}
With this I can get the correct answer for fairly big stock sizes. With a stock size of 10^6 the code completes in ~2 seconds, and with a stock of 10^7 numbers it takes a whole 27 seconds. This is not good enough, since I'm looking for a solution that can handle stock sizes of as big as 10^16, so I probably need a O(log(n)) solution.
This is a homework like assignment, so I didn't come here without wrestling with this pickle for quite some time. I have failed to come up with anything similiar by googling, and wolfram alpha doesn't recognize any kind of pattern this gives.
What I have concluded so far is that ones will allways run out first. I have no proof, but it is so.
Can anyone come up with any piece of advice? Thanks a lot.
EDIT:
I have come up with and implemented an efficient way of finding the cost of numbers 1...n thanks to btilly's pointers (see his post and comments below. also marked as a solution). I will elaborate this further after I have implemented the binary search for finding the last number you can write with the given stock later today.
EDIT 2: The Solution
I had completely forgotten about this post, so my apologies for not editing in my solution earlier. I won't copy the actual implementation, though.
My code for finding the cost of a number does the following:
First, let us choose a number, e.g. 9999. Now we will get the cost by summing the cost of each tens of digits like so:
9 9 9 9
^ ^ ^ ^
^ ^ ^ roof(9999 / 10^1) * 10^0 = 1000
^ ^ roof(9999 / 10^2) * 10^1 = 1000
^ roof(9999 / 10^3) * 10^2 = 1000
roof(9999 / 10^4) * 10^3 = 1000
Thus the cost for 9999 is 4000.
the same for 256:
2 5 6
^ ^ ^
^ ^ roof(256 / 10^1) * 10^0 = 26
^ roof(256 / 10^2) * 10^1 = 30
roof(256 / 10^3) * 10^2 = 100
Thus the cost for 256 is 156.
Implementing with this idea would make the program work only with numbers that have no digits 1 or 0, which is why further logic is needed. Let's call the method explained above C(n, d), where n is the number for which we are getting the cost for, and d is the d'th digit from n that we are currently working with. Let's also define a method D(n, d) that will return the d'th digit from n. Then we will apply the following logic:
sum = C(n, d)
if D(n, d) is 1:
for each k < d, k >= 0 :
sum -= ( 9 - D(n, k) ) * 10^(k-1);
else if D(n, d) is 0:
sum -= 10^(d-1)
With this the program will calculate the correct cost for a number efficiently. After this we simply apply a binary search for finding the number with the correct cost.
Step 1. Write an efficient function to calculate how much stock needs to be used to write all of the numbers up to N. (Hint: calculate everything that was used to write out the numbers in the last digit with a formula, and then use recursion to calculate everything that was used in the other digits.)
Step 2. Do a binary search to find the last number you can write with your amount of stock.
We can calculate the answer directly. A recursive formula can determine how much stock is needed to get from 1 to numbers that are powers of ten minus 1:
f(n, power, target){
if (power == target)
return 10 * n + power;
else
return f(10 * n + power, power * 10, target);
}
f(0,1,1) = 1 // a stock of 1 is needed for the numbers from 1 to 9
f(0,1,10) = 20 // a stock of 20 is needed for the numbers from 1 to 99
f(0,1,100) = 300 // a stock of 300 is needed for the numbers from 1 to 999
f(0,1,1000) = 4000 // a stock of 4000 is needed for the numbers from 1 to 9999
Where it gets complicated is accounting for the extra 1's needed when our calculation lands after the first multiple of any of the above coefficients; for example, on the second multiple of 10 (11-19) we need an extra 1 for each number.
JavaScript code:
function f(stock){
var cs = [0];
var p = 1;
function makeCoefficients(n,i){
n = 10*n + p;
if (n > stock){
return;
} else {
cs.push(n);
p *= 10;
makeCoefficients(n,i*10);
}
}
makeCoefficients(0,1);
var result = -1;
var numSndMul = 0;
var c;
while (stock > 0){
if (cs.length == 0){
return result;
}
c = cs.pop();
var mul = c + p * numSndMul;
if (stock >= mul){
stock -= mul;
result += p;
numSndMul++;
if (stock == 0){
return result;
}
}
var sndMul = c + p * numSndMul;
if (stock >= sndMul){
stock -= sndMul;
result += p;
numSndMul--;
if (stock == 0){
return result;
}
var numMul = Math.floor(stock / mul);
stock -= numMul * mul;
result += numMul * p;
}
p = Math.floor(p/10);
}
return result;
}
Output:
console.log(f(600));
1180
console.log(f(17654321));
16031415
console.log(f(2147483647));
1633388154

Method to find a factor of a number

I am trying to write a simple program that takes a non-prime number and returns the first factor of it. I have to use a method to do this. I think that I am really close to the correct code, but I keep running into variable definition issues in my method. Here is my (currently incorrect) code:
public class testing {
public static void main(String[] args) {
int a;
a = 42;
System.out.println(factor(a));
}
//This method finds a factor of the non-prime number
public static int factor(int m) {
for(int y=2 ; y <= m/2 ; y++) {
if(m%y==0) {
return y;
continue;
}
}
return y;
}
}
Please let me know what's incorrect!
Regarding your code:
public static int factor(int m) {
for(int y=2 ; y <= m/2 ; y++) {
if(m%y==0) {
return y;
continue;
}
}
return y;
}
At the point of that final return y, y does not exist. Its scope is limited to the inside of the for statement since that is where you create it. That's why you're getting undefined variables.
In any case, returning y when you can't find a factor is exactly the wrong thing to do since, if you pass in (for example) 47, it will give you back 24 (47 / 2 + 1) despite the fact it's not a factor.
There's also little point in attempting to continue the loop after you return :-) And, for efficiency, you only need to go up to the square root of m rather than half of it.
Hence I'd be looking at this for a starting point:
public static int factor (int num) {
for (int tst = 2 ; tst * tst <= num ; tst++)
if (num % tst == 0)
return tst;
return num;
}
This has the advantage of working with prime numbers as well since the first factor of a prime is the prime itself. And, if you foolishly pass in a negative number (or something less than two, you'll also get back the number you passed in. You may want to add some extra checks to the code if you want different behaviour.
And you can make it even faster, with something like:
public static int factor (int num) {
if (num % 2 == 0) return 2;
for (int tst = 3 ; tst * tst <= num ; tst += 2)
if (num % tst == 0)
return tst;
return num;
}
This runs a check against 2 up front then simply uses the odd numbers for remainder checking. Because you've already checked 2 you know it cannot be a multiple of any even number so you can roughly double the speed by only checking odd numbers.
If you want to make it even faster (potentially, though you should check it and keep in mind the code may be harder to understand), you can use a clever scheme pointed out by Will in a comment.
If you think about the odd numbers used by my loop above with some annotation, you can see that you periodically get a multiple of three:
5
7
9 = 3 x 3
11
13
15 = 3 x 5
17
19
21 = 3 x 7
23
25
27 = 3 x 9
That's mathematically evident when you realise that each annotated number is six (3 x 2) more than the previous annotated number.
Hence, if you start at five and alternately add two and four, you will skip the multiples of three as well as those of two:
5, +2=7, +4=11, +2=13, +4=17, +2=19, +4=23, ...
That can be done with the following code:
public static long factor (long num) {
if (num % 2 == 0) return 2;
if (num % 3 == 0) return 3;
for (int tst = 5, add = 2 ; tst * tst <= num ; tst += add, add = 6 - add)
if (num % tst == 0)
return tst;
return num;
}
You have to add testing against 3 up front since it violates the 2, 4, 2 rule (the sequence 3, 5, 7 has two consecutive gaps of two) but that may be a small price to pay for getting roughly another 25% reduction from the original search space (over and above the 50% already achieved by skipping all even numbers).
Setting add to 2 and then updating it with add = 6 - add is a way to have it alternate between 2 and 4:
6 - 2 -> 4
6 - 4 -> 2
As I said, this may increase the speed, especially in an environment where modulus is more expensive than simple subtraction, but you would want to actually benchmark it to be certain. I just provide it as another possible optimisation.
This is what you probably want to do:
public static void main(String[] args) {
int a;
a = 42;
System.out.println(factor(a));
}
public static int factor(int m) {
int y = 0;
for (y = 2; y <= m / 2; y++) {
if (m % y == 0) {
return y;
}
}
return y;
}
And the output will be 2.
we need just a simple for loop like,
public static void finfFactor(int z) {
for(int x=1; x <= z; x++) {
if(z % x == 0) {
System.out.println(x);
}
}

Categories

Resources