A man is keeping score of a football (soccer) game. He tracks partial results like this: 1-0, 1-1, 2-1, 2-2, 3-2. The sum of the goals in all of these partial results is 15, and the final result is 3-2, which is 5 goals. Given N which is sum of the goals of the partial results, you need to find number of goals of the final result. Here are some examples:
Input 15
Output 5
Input 6
Output 3
Input 55
Output 10
I can't use loops to solve the problem; I can only use if/else and arithmetical operations. Using just those operations, how can I find hte number of goals of the final result?
It is a summation problem. A record is created every time a goal is scored. The record is always one larger than the previous record. The total is the sum of all records.
Total = summation( number of goals scored )
So is the total is 1 then you know the number of goals is 1 as well.
If the total is three then there were two goals scored (1 and 1+1)
55 = 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 so there were 10 goals scored.
edit Calculating the actual answer is simpler than using the fractional math shown in other answers, but it requires solving a quadratic equation.
Note that the solution to ax**2 + bx + c == 0 is
x = (-b +/- SQRT( b**2 - 4*a*c) / 2*a
T = n(n+1)/2
2T = n**2 + n
n**2 + n - 2T = 0
n = (-1 +/- SQRT( 1 - 4*1*(-2T))) / (2 * 1), n > 0
n = (SQRT( 1 + 8T ) - 1) / 2
so if T = 10, n = (SQRT(81) - 1) / 2 == 4
r ="result"
s = "sum of goals"
n = "number of goals"
r s n
1-0 1 1
1-1 3 2
2-1 6 3
2-2 10 4
3-2 15 5
This tells us that s is just the sum of the first n integers, but we need n(s), not s(n).
Here's an example calculation.
Here's the code for making this happen in java:
class Example {
public static int n(int s) {
return (int) Math.round(-1.0 / 2.0 + Math.sqrt(1.0 / 4.0 + 2.0 * s));
}
public static int s(int n) {
return (n * (n + 1)) / 2;
}
public static void main(String[] args) {
for (int n = 0; n <= 10; n++) {
int s = s(n);
printResult(s);
}
}
private static void printResult(int s) {
int n = n(s);
System.out.println("If the sum of goals is " + s + ", then the number of goals is " + n);
}
}
Here's the output:
If the sum of goals is 0, then the number of goals is 0
If the sum of goals is 1, then the number of goals is 1
If the sum of goals is 3, then the number of goals is 2
If the sum of goals is 6, then the number of goals is 3
If the sum of goals is 10, then the number of goals is 4
If the sum of goals is 15, then the number of goals is 5
If the sum of goals is 21, then the number of goals is 6
If the sum of goals is 28, then the number of goals is 7
If the sum of goals is 36, then the number of goals is 8
The question is ambiguous as to whether square root is allowed, does it strictly count as an arithmetic operation?
If we assume its not allowed and we cannot use any looping we can use Newton's method to give a good approximation to the answer. Others have pointed out that we are basically trying the find the inverse of the triangular numbers T(n)=n(n+1)/2. If we are given a sum S let f(n)=n^2/2+n/2-S we want to solve f(n)=0. Newton's method is a fast iterative method, given an initial guess x0 we can find a better guess x1 using
x1 = x0 - f(x) / df(x)
where df(x)=x-1/2 is the derivative. If we do this 4 times we get a pretty good solution.
public class InverseSqrt {
static float f(float x,float S) {
return x*x/2+x/2-S;
}
static float df(float x,float S) {
return x+0.5f;
}
static float newton(float sum) {
float x = sum/2; // first initial guess
// Apply Newton's method four time
x = x - f(x,sum) / df(x,sum);
x = x - f(x,sum) / df(x,sum);
x = x - f(x,sum) / df(x,sum);
x = x - f(x,sum) / df(x,sum);
return x;
}
public static void main(String[] args) {
int i=0;
int ires=0;
do { // loop through possible number of goals
++i;
float s = i * (i+1) * 0.5f; // calculate the total
float res = newton(s);
ires = (int) (res+0.5); // round to nearest integer
System.out.print("T("+i+")="+(int)s);
System.out.println("\tres="+ires+"\t("+res+")");
} while(ires==i); // break first time it fails
}
}
This works pretty well up to an input of 351 giving an output of 26. But fails for the next input 378 giving 28 rather than 27 goal.
We can improve things a bit by using 5 steps of Newtons method working up to an input of 1176 with an output of 48. Tuning the initial guess improves things dramatically, using a starting guess of n/16 with 5 steps works upto input 42195 output 290.
A much better solution can be found using the Fast inverse squareroot. This can be implemented in Java following this answer.
static float Q_rsqrt( float x )
{
float xhalf = 0.5f*x;
int i = Float.floatToIntBits(x);
i = 0x5f3759df - (i>>1);
x = Float.intBitsToFloat(i);
x = x*(1.5f - xhalf*x*x);
return x;
}
Our Newton iteration method is then
static float newton(float sum) {
float x = Q_rsqrt(1/sum);
x = x - f(x,sum) / df(x,sum);
x = x - f(x,sum) / df(x,sum);
x = x - f(x,sum) / df(x,sum);
return x;
}
with only 3 iteration steps.
This works upto Input 1073720960 Output 46340. The next item after than gives an integer overflow in calculating the sum, so it can be said to work for all legal int values.
This might not be counted as a legal solution as it uses floatToIntBits(x) and intBitsToFloat(x) which don't really class as arithmetic operations.
It seems that sum of arithmetic progression S(n) is given, and you have to find n.
Use simple math and calculate n from equation:
S(n) = n * (n + 1) / 2
Related
Given an integer A representing the square blocks. The height of each square block is 1. The task is to create a staircase of max height using these blocks. The first stair would require only one block, the second stair would require two blocks and so on. Find and return the maximum height of the staircase.
Your submission failed for the following input: A : 92761
Your function returned the following : 65536
The expected returned value : 430
Approach:
We are interested in the number of steps and we know that each step Si uses exactly Bi number of bricks. We can represent this problem as an equation:
n * (n + 1) / 2 = T (For Natural number series starting from 1, 2, 3, 4, 5 …)
n * (n + 1) = 2 * T
n-1 will represent our final solution because our series in problem starts from 2, 3, 4, 5…
Now, we just have to solve this equation and for that we can exploit binary search to find the solution to this equation. Lower and Higher bounds of binary search are 1 and T.
CODE
public int solve(int A) {
int l=1,h=A,T=2*A;
while(l<=h)
{
int mid=l+(h-l)/2;
if((mid*(mid+1))==T)
return mid;
if((mid*(mid+1))>T && (mid!=0 && (mid*(mid-1))<=T) )
return mid-1;
if((mid*(mid+1))>T)
h=mid-1;
else
l=mid+1;
}
return 0;
}
To expand on the comment by Matt Timmermans:
You know that for n steps, you need (n * (n + 1))/2 blocks. You want know, if given B blocks, how many steps you can create.
So you have:
(n * (n + 1))/2 = B
(n^2 + n)/2 = B
n^2 + n = 2B
n^2 + n - 2B = 0
That looks suspiciously like something for which you'd use the quadratic formula.
In this case, a=1, b=1, and c=(-2B). Plugging the numbers into the formula:
n = ((-b) + sqrt(b^2 - 4*a*c))/(2*a)
= (-1 + sqrt(1 - 4*1*(-2B)))/(2*a)
= (-1 + sqrt(1 + 8B))/2
= (sqrt(1 + 8B) - 1)/2
So if you have 5050 blocks, you get:
n = (sqrt(1 + 40400) - 1)/2
= (sqrt(40401) - 1)/2
= (201 - 1)/2
= 100
Try it with the quadratic formula calculator. Use 1 for the value of a and b, and replace c with negative two times the number of blocks you're given. So in the example above, c would be -10100.
In your program, since you can't have a partial step, you'd want to truncate the result.
Why are you using all these formulas? A simple while() loop should do the trick, eventually, it's just a simple Gaussian Sum ..
public static int calculateStairs(int blocks) {
int lastHeight = 0;
int sum = 0;
int currentHeight = 0; //number of bricks / level
while (sum <= blocks) {
lastHeight = currentHeight;
currentHeight++;
sum += currentHeight;
}
return lastHeight;
}
So this should do the job as it also returns the expected value. Correct me if im wrong.
public int solve(int blocks) {
int current; //Create Variables
for (int x = 0; x < Integer.MAX_VALUE; x++) { //Increment until return
current = 0; //Set current to 0
//Implementation of the Gauss sum
for (int i = 1; i <= x; i++) { //Sum up [1,*current height*]
current += i;
} //Now we have the amount of blocks required for the current height
//Now we check if the amount of blocks is bigger than
// the wanted amount, and if so we return the last one
if (current > blocks) {
return x - 1;
}
}
return current;
}
I'm trying to write a program that can multiply all the digits of a number from 0 to 1000 exclusive using only math expressions in Java. My program works fine as long as the user types in a 3-digit number, but results in 0 if they type in anything less than 100.
I have tried getting the last digit of the input with '%10' and removing the last digit with '/10' but without a control statement to detect if the input has been reduced to zero, the program ends up multiplying by 0 when a 2-digit number has been reduced to zero, giving an incorrect result.
public class MultiplyDigits {
public static void main(String[] args){
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("Enter a number between 0 and 1000: ");
int number = input.nextInt();
int product = 1;
product*=number%10;
number/=10;
product*=number%10;
number/=10;
product*=number%10;
System.out.println(product);
}
}
An input of 55 should result in 25, but my program does 5 x 5 x 0 = 0
An input of 999 results in 729, which is correct. 9 x 9 x 9 = 729
Some more clarification, this is a problem out of the 2nd chapter of a textbook for complete novices. The author has not covered selection statements, loops, writing our own methods or classes, or anything more advanced than elementary programming, so the implication is that this is doable without those. The book has covered invoking methods in classes built into Java, although the author has only mentioned methods in the Math and System classes. For example, Math.max(), Math.min(), Math.pow(), System.currentTimeMillis();
What about this variant. To find the first number, you can decrease, first of all, the entered number by 100 and add 1 to avoid 0 during multipication. And , as recomended NVioli, the second number should be the same updated to have a possibility to enter number lower then 10. Thus, the final variant is:
int number = input.nextInt();
int t1 = 1 + (number-100) / 100;
int t2 = (1 + (number-10) / 10) % 10; \\By NVioli
int t3 = number % 10;
int product = t1 * t2 * t3;
System.out.println(product);
The first part is to extract the essential code into a separate Java method. I'm calling it dprod, which is short for "digit product".
static int dprod(int x) {
int hun = x / 100 % 10;
int ten = x / 10 % 10;
int one = x / 1 % 10;
return hun * ten * one;
}
The above code is the naive version that only works for numbers >= 100.
To treat numbers less than 100 as expected, you need to replace the hun or ten with 1 if it is 0.
static int dprod(int x) {
int hun = x < 100 ? 1 : x / 100 % 10;
int ten = x < 10 ? 1 : x / 10 % 10;
int one = x / 1 % 10;
return hun * ten * one;
}
The ?: operator is called a conditional operator, therefore it is probably not allowed under your rules. There is a possible workaround by using the ?: operator without writing it explicitly, by using the Math.max function.
static int dprod(int x) {
int hun = Math.max(100, x) / 100 % 10;
int ten = Math.max(10, x) / 10 % 10;
int one = x / 1 % 10;
return hun * ten * one;
}
The Math.max function uses the ?: operator internally, therefore it might be forbidden, too. This is subject to discussion though, since it depends on the exact wording of the rules and their intention.
If Math.max is forbidden, it is possible to implement it entirely without branches or conditions, see this C++ question, which can be translated to Java by replacing int32 with int and by replacing inline with static.
The complete code, including automatic tests, is:
package de.roland_illig.so;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
public class DprodTest {
static int dprod(int x) {
int hun = Math.max(x, 100) / 100 % 10;
int ten = Math.max(x, 10) / 10 % 10;
int one = x / 1 % 10;
return hun * ten * one;
}
#Test
public void testDprod() {
assertThat(dprod(999)).isEqualTo(729);
assertThat(dprod(123)).isEqualTo(6);
assertThat(dprod(99)).isEqualTo(81);
assertThat(dprod(9)).isEqualTo(9);
}
}
You could just initialize the program with a length 1000 array, initialize it with the value of each number, and then your real problem simplifies to:
System.out.println(calculatedArray[number]);
Your initialization could even take advantage of the fact that a leading 0 doesn't matter according to your rules (55 and 155 are the same result.)
calculatedArray[55] = calculcate(155);
there are some ways which can help you but all of them has a simple loop or if:
You can use digits = Logarithm of your number(10 base) and then you have number of digits, then you can use a loop to calculate the result. your loop will be repeated digit times so no matter how many digits your number has, it will always work.
You can check if your number is less than 100 and then just add 100 to that, then calculate the result, because of 1 * digit1 * digit2 there will be no error.
This question already has answers here:
Java Math.pow(a,b) time complexity
(2 answers)
Closed 4 years ago.
public class HelloWorld{
public static void main(String []args){
int orig=103, reverse=0, mod;
int numOfDigits=0;
int n = orig;
while (n>0){
n /= 10;
numOfDigits++;
}
n = orig;
while (n > 0){
mod = n % 10;
reverse = reverse + (int)(mod * java.lang.Math.pow(10, numOfDigits-1));
numOfDigits--;
n /= 10;
}
System.out.println("Reversed is : " + reverse);
}
}
I do know that reverse = reverse + (int)(mod * java.lang.Math.pow(10, numOfDigits-1)); can be replaced by reverse = mod + (reverse*10).
Was wondering if I had just increased the complexity of a simple program by calculating total number of digits and applying power?
P.S: Kindly assume that orig can be taken as an input from the user and could be a number of any number of digits. I have hard coded only for experiment.
You didn't increase the complexity ... but you did make it slower. The expression pow(10, numOfDigits - 1) will be substantially slower than reverse = mod + (reverse * 10)
It is also possible that a computation that uses Math.pow instead of integer multiplication is inaccurate due to floating point imprecision. A double has only 52 bits of precision, compared with 63 for a long. In this example, this probably doesn't apply, but it is something to be wary of, in general
Probably, this would be the best approach with less iteration & complexity:
public class NumReverse {
public long reverseNumber(long number){
long reverse = 0;
while(number != 0){
reverse = (reverse*10)+(number%10);
number = number/10;
}
return reverse;
}
public static void main(String a[]){
System.out.println("Reversed is: "+new NumReverse().reverseNumber(103));
}
}
compute the multiply times and add times:
suppose f(x) = an * x^n + an-1 * x^n-1 + ... + a1 * x + a0
1. If calculate f(x) by computing one item by one item,
it will take (n+1) + n + (n-1) + ... + 1 + 0 = (n+1)(n+2)/2 multiply times and n addition times.
2. If calculate f(x) by n = n*10 + mod,
it will take n multiply times and n addition times.
Of course, if pow() has some optimization such as "divide and conquer", the complexity of pow() should be O(logN).
I am trying to figure out a way in order to solve this particular problem faster and in a more optimized way. I do not know if it is possible to have this code run on multiple cores and threads or if somehow I could offload it to GPU's but the faster this is able to compute the better.
public class numberCounter
{
public static void main(String[] args)
{
//Used only to check speed of calculation
long start = System.currentTimeMillis();
//Initialized variables
double x, y, z;
//30 can be substituted out but i used it as a test.
//I am unable to calculate 31 and above.
long t = (long) Math.pow(2, 30);
//used later for counting
long counter = 0;
//starting number
System.out.println("Number - " + t);
for(int i = 1; i < t; i++)
{
x = i % 2;
y = i % 3;
z = i % 5;
if(x*y*z > 0)
counter++;
}
System.out.println();
//prints out number of numbers that follow the rule above
System.out.printf("Numbers: %.0f\n", counter);
long end = System.currentTimeMillis();
//prints out time taken
System.out.println((end - start) + " ms");
}
}
The biggest burden is the loop, so it is best to be addressed if we want to gain something for optimization.
You have to reverse the problem, instead of looking for numbers indivisible by 2 or 3 or 5, we were looking for numbers divisible by 2 or 3 or 5. The resulting number of such numbers subtract all the numbers will give us the number of indivisible numbers by 2 or 3 or 5. In this way, we obtain an algorithm with a constant execution time. Execution time does not depend on the input.
public static long indivisbleBy_2or3or5(long t) {
long x, y, z;
//amount of numbers divisible by 2, and several for 3 and 5.
x = t / 2;
//amount of numbers divisible by 3 - numbers divisible by 3 and 2 = amount of numbers divisible by 3, and several for 5.
y = t / 3;
y = y - y / 2;
//amount of numbers divisible by 5 - numbers divisible by 5 and 2 - (numbers divisible by 5 and 3 - numbers divisible by 5 and 3 and 2) = number only divisible by 5
z = t / 5;
z = z - z / 2 - (z / 3 - z / (2 * 3) );
//All numbers - (The amount of numbers divisible by 2, and several for 3 and 5
//+ The amount of numbers divisible by 3 and several for 5 + number only divisible by 5)
//= indivisible by 2 or 3 or 5
return t - (x + y + z);
}
I do not know whether the "pow" there is some optimization, but it is generally better to perform an action (2 ^ 15) ^ 2 which gives 15 operations than 2 ^ 30, which gives 29 operations. According to the principle of "divide et impera". :)
I'm creating a world generator for my 2D game, which uses the Diamond-Square Algorithm in Java, and I've heard that it only works (or at least, only works well) with numbers that are 2n+1 (power of two).
The method that generates the world is called with generateWorld(width, height), but that creates a problem. I want to be able to input a width, and the function will find the nearest number which is a power of two, if the input width isn't. I don't really know how I can do this, so all help is greatly appreciated!
Summarizing: If one number isn't power of two, I want to find the nearest number to that one, which is a power of two.
You can round up to a higher power of two (no change if it already was a power of two) like this:
x = x - 1;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
It will give 0 for inputs where the next higher power of two does not exist.
The other candidate is simply half that. Then take the nearest.
There are two candidates: 2^floor(log2(x)) and 2^ceil(log2(x)). Just check which of the two is closer.
For integers, you can use bit fiddling to find the most-significant set bit to get the exact value of floor(log2(x)). I've written about the idea before. Again this yields two candidates that you can check.
Mathematically speaking, the closest power of 2 would be 2round(log2(x)). Java, unfortunately, doesn't have a pre-made method for log2, but luckily, it's easily doable with the pre-existing java.lang.Math functions:
int width = ...;
double log = Math.log(width) / Math.log(2);
long roundLog = Math.round(log);
long powerOfTwo = Math.pow(2, roundLog);
Guava 20+
You have 3 useful methods:
IntMath.ceilingPowerOfTwo(x)
IntMath.floorPowerOfTwo(x)
IntMath.isPowerOfTwo(x)
and you can check which one of the floor power of 2 and the ceiling power of 2 is closer.
E.g.:
public static void main(String[] args) {
for ( int i = 1 ; i < 13 ; i++ ) {
nearestPowerOfTwo(i);
}
}
private static void nearestPowerOfTwo(int x) {
int ceil = IntMath.ceilingPowerOfTwo(x);
int floor = IntMath.floorPowerOfTwo(x);
System.out.print(x + " ---> ");
if ( IntMath.isPowerOfTwo(x) ) {
System.out.println(x + " (the number is power of 2)");
} else if ( ceil - x > x - floor ) {
System.out.println(floor);
} else if (ceil - x == x - floor) {
System.out.println(floor + " and " + ceil);
} else {
System.out.println(ceil);
}
}
Output:
1 ---> 1 (the number is power of 2)
2 ---> 2 (the number is power of 2)
3 ---> 2 and 4
4 ---> 4 (the number is power of 2)
5 ---> 4
6 ---> 4 and 8
7 ---> 8
8 ---> 8 (the number is power of 2)
9 ---> 8
10 ---> 8
11 ---> 8
12 ---> 8 and 16
There are also LongMath and DoubleMath if the IntMath is not enough.