I would like to find all positive integer solutions to the equation
a^3 + b^3 = c^3 + d^3 where a,b,c,d are integers between 1 to 1000;
for (int a = 1; a <= 1000; ++a)
{
for (int b = 1; b <= 1000; ++b)
{
for (int c = 1; c <= 1000; ++c)
{
for (int d = 1; d <= 1000; ++d)
{
if (Math.Pow(a, 3) + Math.Pow(b, 3) == Math.Pow(c, 3) + Math.Pow(d, 3))
{
Console.WriteLine("{0} {1} {2} {3}", a,b,c,d);
}
}
}
}
I know that d = Math.Pow(a^3 + b^3 - c^3, 1/3), so
for (int a = 1; a <= 1000; ++a)
{
for (int b = 1; b <= 1000; ++b)
{
for (int c = 1; c <= 1000; ++c)
{
int d = (int)Math.Pow(Math.Pow(a, 3) + Math.Pow(b, 3) - Math.Pow(c, 3), 1/3);
if (Math.Pow(a, 3) + Math.Pow(b, 3) == Math.Pow(c, 3) + Math.Pow(d, 3))
{
Console.WriteLine("{0} {1} {2} {3}", a,b,c,d);
}
}
}
}
But the second algorithm produce much smaller number of results. Where is the bug in my code?
I try (double)1/3 but the second algorithm still gives me smaller number of results then first one
Pretty much none of these answers are right.
Your question is:
Where is the bug in my code?
If you are using double-precision arithmetic to solve a problem in the integers, you are doing something wrong. Do not use Math.Pow at all, and particularly do not use it to extract cube roots and expect that you will get an exact integer answer.
So how should you actually solve this problem?
Let's be smarter about not doing unnecessary work. Your program discovers that 13 + 123 = 93 + 103, but also that 123 + 13 = 103 + 93, and so on. If you know the first one then you can know the second one pretty easily.
So what should we do to make this more efficient?
First, b must be larger than a. That way we never waste any time figuring out that 13 + 123 = 123 + 13.
Similarly, d must be larger than c.
Now, we can also say that c and d must be between a and b. Do you see why?
Once we put these restrictions in place:
for (int a = 1; a <= 1000; ++a)
for (int b = a + 1; b <= 1000; ++b)
for (int c = a + 1; c < b; ++c)
for (int d = c + 1; d < b; ++d)
if (a * a * a + b * b * b == c * c * c + d * d * d)
Console.WriteLine($"{a} {b} {c} {d}");
Your program becomes a lot faster.
Now, there are ways to make it faster still, if you're willing to trade more memory for less time. Can you think of some ways that this program is wasting time? How many times are the same computations done over and over again? How can we improve this situation?
We might notice for example that a * a * a is computed every time through the three inner loops!
for (int a = 1; a <= 1000; ++a)
{
int a3 = a * a * a;
for (int b = a + 1; b <= 1000; ++b)
{
int b3 = b * b * b;
int sum = a3 + b3;
for (int c = a + 1; c < b; ++c)
{
int c3 = c * c * c;
int d3 = sum - c3;
for (int d = c + 1; d < b; ++d)
if (d3 == d * d * d)
Console.WriteLine($"{a} {b} {c} {d}");
}
}
}
But we could be even smarter than that. For example: what if we created a Dictionary<int, int> that maps cubes to their cube roots? There are only 1000 of them! Then we could say:
for (int a = 1; a <= 1000; ++a)
{
int a3 = a * a * a;
for (int b = a + 1; b <= 1000; ++b)
{
int b3 = b * b * b;
int sum = a3 + b3;
for (int c = a + 1; c < b; ++c)
{
int c3 = c * c * c;
int d3 = sum - c3;
if (dict.HasKey(d3))
{
d = dict[d3];
Console.WriteLine($"{a} {b} {c} {d}");
}
}
}
}
Now you don't have to compute cubes or cube roots of d; you just look up whether it is a cube, and if it is, what its cube root is.
Even as a double, 1/3 cannot be represented exactly with any IEEE floating point types.
So, you aren't actually computing the cube root of a value, but rather raising the value to the power of 0.333333333333333333333333333334 or some slightly off version. This introduces rounding errors that result in increasing error factors.
Consider the case with a = 995, b = 990, c = 990: your first loop would generate a match with d = 995, but your computation produces d = 994 due to rounding errors, which fails to match your condition. This will rarely match, which explains the results you are seeing.
To fix the problem, you could work entirely with floating point, but that would get messy since you have to check ranges due to representational problems even then, and only after you find a possibly suitable range, you would then have to check the integer versions. Another solution is to approach this from the mathematics standpoint rather than brute-force, although that will likely require kernel methods and get very messy.
Replace
int d = (int)Math.Pow(Math.Pow(a, 3) + Math.Pow(b, 3) - Math.Pow(c, 3), 1/3);
with
int d = (int)Math.Round(Math.Pow(Math.Pow(a, 3) + Math.Pow(b, 3) - Math.Pow(c, 3), 1.0/3), 0);
if(d > 1000) continue; // Restrict solutions as in brute force algorithm
The two errors fixed are,
1/3 is computed as an integer division resulting in 0. Using 1.0/3 forces a floating point division.
Because of floating point errors the calculation may return say 3.999999994 instead of 4. When cast to an integer this is truncated to 3, effectively removing a solution. Using Math.Round(3.999999994, 0) rounds this up to 4.0 which is cast to 4 as an integer.
Your problem is, that the result from this line: int d = (int)Math.Pow(Math.Pow(a, 3) + Math.Pow(b, 3) - Math.Pow(c, 3), 1/3); can be a non Integer value, which would not fullfill your requirement. But by casting it to int you get a larger amount of solutions.
You should change d to a double and then just check if d is an integer value between 1 and 1000:
double d = Math.Pow(Math.Pow(a, 3) + Math.Pow(b, 3) - Math.Pow(c, 3), 1.0/3.0);
double epsilon = 0.000000001;
double dint = Math.Round(d, 0);
if (dint<=d+epsilon && dint>=d-epsilon && dint>=1-epsilon && dint<=1000+epsilon)
{
Console.WriteLine("{0} {1} {2} {3}", a,b,c,d);
}
Edit: I added an epsilon to make sure your double comparison will work
Related
Example a: √12 =2√3
Example b: √16 = 4
I am trying to get both.
Whilst I can of course use Math.Sqrt(4) to achieve outcome b, I've no idea how to achieve a, or further how to get both to work simultaneously which is the goal. How do I achieve this type of simplification in C#?
I have tried several libraries including MathNet, Symbolics and NCalc with no success.
This post may have solved it in c++, although I do not know for sure. My attempts at converting that solution to even see if it worked were very much a failure:
var outside_root = 1;
var inside_root = 800;
var d = 2;
while (d * d <= inside_root)
if (inside_root % (d * d) == 0) //# inside_root evenly divisible by d * d
{
inside_root = inside_root / (d * d);
outside_root = (outside_root * d);
}
while (d * d > inside_root) {
d = (d + 1);}
Thank you for any help
The given C++ can be translated into C# without a lot of changes. Also a couple of modifications can be made to the original algorithm to reduce number of multiplications and increase overall performance:
static (int, int) Sqrt2(int n)
{
int m = 1, d = 2;
int dSquared;
while ((dSquared = d * d) <= n)
{
while ((n % dSquared) == 0)
{
n /= dSquared;
m *= d;
}
d++;
}
return (m, n);
}
static void Main(string[] args)
{
Console.WriteLine(Sqrt2(12)); // prints (2, 3)
Console.WriteLine(Sqrt2(16)); // prints (4, 1)
Console.WriteLine(Sqrt2(13)); // prints (1, 13)
}
This could be one of the solution
I think this is efficient. I used it in my calculator app
I did that using java. Hope this will help
static void surd_form(long a) {
long i = 2;
long sq = 1;
long k = 4;
long p = 1;
while (k <= a) {
if (a % i == 0) {
if (a % k == 0) {
a /= k;
sq *= i;
} else {
a /= i;
p *= i;
}
} else {
i += 1;
}
k = i * i;
}
System.out.println(sq + "" + "√" + (a * p));
}
So I have to make a program that prints how many times it has to make a certain calculation. However, when I print the result, I seem to be getting 16000 numbers that just add +1 every new time. My question is how to fix this. I have no idea...
Thank you for your help!
My code:
class Program
{
static void Main(string[] args)
{
double a = 0;
double b = 0;
double distance = 0;
int i = 1;
for (double x = -2; x < 2; x = x+0.01)
{
for (double y = -2; y < 2; y = y+ 0.01)
{
while(distance <= 2 || i < 100)
{
a = a * a - b * b + x;
b = 2 * a * b + y;
double a2b2 = Math.Pow(a, 2) + Math.Pow(b, 2);
distance = Math.Sqrt(a2b2);
i++;
}
Console.WriteLine(i);
}
}
Console.ReadKey();
}
}
I assume you're trying to plot a fractal of some description - I haven't checked the maths, but it reminds me of code I've used to generate Mandelbrot set images before now.
The problem is that you should be creating an independent calculation for each point - but you're maintaining the state of a, b, i and distance between points. That means once distance has become greater than 2 and i is greater than 100, you'll never get into the inside of the while loop. Just move the declaration and initialization of those variables to inside your inner for loop.
Additionally, the conditions for your while loop should be ANDed together rather than ORed together, assuming that the idea is to effectively limit it to 100 iterations per point.
for (double x = -2; x < 2; x += 0.01)
{
for (double y = -2; y < 2; y += 0.01)
{
// Initialize the local variables here, as they're meant to be independent for each point.
double a = 0;
double b = 0;
double distance = 0;
int i = 1;
while (distance <= 2 && i < 100)
{
a = a * a - b * b + x;
b = 2 * a * b + y;
double a2b2 = Math.Pow(a, 2) + Math.Pow(b, 2);
distance = Math.Sqrt(a2b2);
i++;
}
Console.WriteLine(i);
}
}
The double type means floating point type. See wiki. This type is not the right numeric type for precise addition like you use. Instead of that use decimal type.
So I want to output Pi with arbitrary precision digit by digit. I found some code here https://rosettacode.org/wiki/Pi#C.23
public IEnumerable<long> PiDigits(long b = 10)
{
BigInteger
k = 1,
l = 3,
n = 3,
q = 1,
r = 0,
t = 1
;
// skip integer part
var nr = b * (r - t * n);
n = b * (3 * q + r) / t - b * n;
q *= b;
r = nr;
for (; ; )
{
var tn = t * n;
if (4 * q + r - t < tn)
{
yield return (long)n;
nr = b * (r - tn);
n = b * (3 * q + r) / t - b * n;
q *= b;
}
else
{
t *= l;
nr = (2 * q + r) * l;
var nn = (q * (7 * k) + 2 + r * l) / t;
q *= k;
l += 2;
++k;
n = nn;
}
r = nr;
}
}
And it's working correctly but there's no explanation to it. I want to understand this algorithm but it looks too complicated. And variables' name don't give me anything. So could you please tell me what algorithm is that co I could continue my research. Thank you!
This is an implementation of the spigot algorithm translated from an implementation by Jeremy Gibbons.
His paper explains the inner workings of the algorithm. You should find the information you need at pages 5 and 6.
Two (2 digit) numbers are written together, so they form one 4 digit number. This 4 digit number can be divided by the multiplication of this two numbers. The problem is that I have to find this numbers.
I wrote an algorithm and get 2 pair of these numbers.
1) 13 and 52, so 1352 can be divided by 13 * 52.
2) 17 and 34, so 1734 can be divided by 17 * 34.
My algorithm looks like this:
for (int i = 1010; i <= 9999; i++)
{
int mult = (i / 100) * (i % 100);
if ((i % 100) > 9 && i % mult == 0)
{
Console.WriteLine(i / 100 + " <--> " + i % 100);
}
}
Edit: with this algorithm (based on mentallurg answer) I find this numbers a bit faster
for (int i = 10; i < 99; i++)
{
for (int j = 10; j < 99; j++)
{
int mult = i * j;
int num = i * 100 + j;
if (num % mult == 0)
{
Console.WriteLine(i + " <--> " + j);
}
}
}
I am interested in how I can make this algorithm more efficient.
This is very efficient:
var query =
from x in Enumerable.Range(10, 90)
from n in Enumerable.Range(1, 10).TakeWhile(w => w * x < 100)
let v = x * (100 + n)
where v % (n * x * x) == 0
select new { x, y = n * x };
It computes all possible first digits. It then computes all of the possible second digits that are multiples of the first digit that are greater than zero and less than 100. It then produces the a candidate value at checks if it is divisible by the product of both digits.
It gives both of the possible answers.
Here's the equivalent using for loops:
for (int x = 10; x <= 99; x++)
{
for (int n = 1; x * n < 100; n++)
{
var j = x * n;
int v = x * 100 + j;
int d = x * j;
if (v % d == 0)
{
Console.WriteLine(x + " <--> " + j);
}
}
}
Supposed one of the pairs are a and b, and so the four digits number can be expressed as 100a + b. Do a little math
100a + b = m * a * b
Divided by a on both sides, we have
100 + b / a = m * b
We can conclude that
b can be divided by a, let's say (b == n * a);
b must be greater than a, since 101 is a prime. And it cannot be 3/7/9 times of a, since 103/107/109 are also primes, but let’s neglect this to make the for loop simpler. This can be easily handled in the inner loop of the following code.
So the for loop can be written like this
for (int a = 10; a < 50; a++)
{
for (int n = 2; n * a < 100; n++)
{
if ((100 + n) % (n * a) == 0)
Console.WriteLine(a + " " + n * a);
}
}
The number of iteration of the loop is reduced to a few dozens, from almost 10 thousand.
Use 2 nested cycles from 1 to 99 and you will avoid two division operations on each step.
I am working on my app using Unity3D, and I am trying to get the user input string from the input filed then use that string to calculate the total sum by applying values from variables, but just cannot get to work. I have this
int B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U;
int characterLength = 0;
int numberLength = 0;
List<int> fomulaList = new List<int>();
List<int> numberList = new List<int>();
foreach (char c in charactersField.text)
{
characterLength++;
fomulaList.Add(c);
Debug.Log(c);
}
formulaArray = fomulaList.ToArray();
Debug.Log("Formula Length: " + formulaArray.Length + " " + formulaArray[0].ToString("D1") + " " + formulaArray[1].ToString("D1"));
Let's say: I typed in BC, and when I print out the DebugLog I got
Formula Length: 2 66 67
which is fine
foreach (char c in numbersField.text)
{
numberLength++;
Debug.Log(c);
}
for (int i = 0; i < winningNumberArray.Length; i++)
{
B = winningNumberArray[i] / 100000; //100000
C = (winningNumberArray[i] % 100000) / 10000; //10000
D = (winningNumberArray[i] % 10000) / 1000; //1000
E = (winningNumberArray[i] % 1000) / 100; //100
F = (winningNumberArray[i] % 100) / 10; //10
G = winningNumberArray[i] % 10; //1
H = twoNumberArray[i] / 10; //10
I = twoNumberArray[i] % 10; //1
J = firstThreeNumberArray[i] / 100; //100
K = (firstThreeNumberArray[i] % 100) / 10; //10
L = firstThreeNumberArray[i] % 10; //1
M = secondThreeNumberArray[i] / 100; //100
N = (secondThreeNumberArray[i] % 100) / 10; //10
O = secondThreeNumberArray[i] % 10; //1
P = thirdThreeNumberArray[i] / 100; //100
Q = (thirdThreeNumberArray[i] % 100) / 10; //10
R = thirdThreeNumberArray[i] % 10; //1
S = fourthThreeNumberArray[i] / 100; //100
T = (fourthThreeNumberArray[i] % 100) / 10; //10
U = fourthThreeNumberArray[i] % 10; //1
int sum = formulaArray.Sum();
Debug.Log("Sum: " + sum.ToString());
But when I print out the to I got
Sum: 133
It seems to me that the values for B and C are not from
B = winningNumberArray[i] / 100000;
C = (winningNumberArray[i] % 100000) / 10000;
How can I solve this?
The issue is likely that you are confusing the char 'B' with the variable B. Despite the similarities, they are completely unrelated.
It sounds like what you are trying to do is take user input, and get a particular value based on that user input. The right data structure for that, generally, in C# is a Dictionary.
In your case you would want:
Dictionary<char,int>
where char is the key (e.g. 'A' or 'B') and int is the value you are currently adding to your A or B variables).