The original problem is located at Project Euler Largest palindrome product and is below.
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. Find the largest palindrome made from the product of two 3-digit numbers.
The question in context is found at
Dmitry Answering Largest palindrome product - C#. I got the correct answer but did it from min to max instead of max to min so I looked for a more efficient answer to study. I understand what all the code does, but I can't figure out where Dmitry started to get the formula to get the minimum multiplicand from the maximum multiplicand constant. I'm blitzing through several coding challenge websites in preparation for some technical interviews.
This line:
const int NMin = NMax - (NMax + 1) / 10 + 1;
OF
// Store the maximum palindrome number here:
long maxNumber = 0;
// The maximum multiplicand (typically: 9...9):
const int NMax = 999;
// The minimum multiplicand.
// Obviously, it couldn't be less than 90...0:
const int NMin = NMax - (NMax + 1) / 10 + 1;
for (int i = NMax; i > NMin; i--)
{
// Starting from i since i * j = j * i for any i, j:
for (int j = i; j > NMin; j--)
{
long number = Math.BigMul(i, j);
// The fastest condition should be the first in the `if` statement:
if (number > maxNumber && isPalindome(number))
{
maxNumber = number;
Console.WriteLine("{0} = {1} * {2}", number, i, j);
break; // Leave the `j` loop, because it's guaranteed that there is
// no numbers greater than `number` for the current `i`
}
}
}
The websites I've been going through include:
Advent Of Code
HackerEarth and HackerRank
Leetcode I've been attempting to finish the Comprehensive Study Plans
Project Euler Only on Problem #4 right now
As stated in problem 4 the largest palindrome for the product of two-digit numbers is 91*99. I believe Dmitry recognized that of all max palindromes for a given digit range (3, 4, or 5 as he calculated but realistically to infinity) must be 9x -> 9y (where x represents 0's and y represents 9's). The amount of x and y needed is digit - 1 if you always want the highest palindrome. The lower 90% here is simply not worth checking for palindromes because they won't produce the highest multiplication.
Thus he can calculate the minimum every time given the equation he provided:
NMin = NMax - (NMax + 1) / 10 + 1 // NMin = 900 if NMax = 999
In the case of 4-digit palindrome, this produces 9,000 -> 9,999 or 90,000 -> 99,999 for 5.
The important thing to note here is he could have hard-coded NMin or picked a larger minimum number.
Related
I know to change the value in nested for loop i=2 the program will not give result in prime numbers. But I want to know the reason and purpose of assigning only 2 to i. Also a Plus if someone explain this using pseudo code.
using System;
namespace Prime_number
{
class Program
{
static void Main(string[] args)
{
int num, i, count, start, end;
Console.Write("Enter Start of range: ");
start = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter End of range : ");
end = Convert.ToInt32(Console.ReadLine());
Console.Write("The prime numbers between {0} and {1} are : \n", start, end);
for (num = start; num <= end; num++)
{
count = 0;
for (i = 2; i <= num / 2; i++)
{
if (num % i == 0)
{
count++;
break;
}
}
if (count == 0 && num != 1)
Console.Write(num + "\n");
}
Console.Write("\n");
}
}
}
It is a self explanatory code:
Read the range_start value.
Read the range_end value.
For each value from range_start to range_end
Check if valueis divisible by any number in range 2 to the half of value
It will be prime if it is not divisible.
The divisors 0 and 1 are not tested for obvious reasons, all numbers are divisible by 1 and any number divided by 0 gives same result, infinity, in limits theory, or divide by zero exception, in a real CPU implementation. only numbers up to value / 2 are tested for an also obvious reason, value would not be divisible by any number in that range but itself.
EDIT: As you're working with integer values, one small optimization would be to use value >> 1 instead of value / 2, shift operations are way faster than div operations at CPU level, yet compilers often apply this optimization when the divisor is known at compile-time.
Homework alert! I am trying to build a console app to determine whether a given integer is an Armstrong number. I found a working solution online, but after spending far too much time analyzing it, I still don't understand the logic well enough to reproduce it on my own... The two pain points I've identified are 1) I do not understand exactly how the Parse method is acting upon the integer that the user inputs, and 2) the logic sequence of the for loop is not self-evident (see code and my logic description below):
int number, remainder, sum = 0;
Console.WriteLine("Enter a number: ");
number = int.Parse(Console.ReadLine());
for (int i = number; i > 0; i = i / 10)
{
remainder = i % 10;
sum = sum + remainder * remainder * remainder;
}
if (sum == number)
{
Console.Write("Entered Number is an Armstrong Number");
}
else
Console.Write("Entered Number is not an Armstrong Number");
Console.ReadLine();
This is how my understanding of the for loop logic breaks down:
The integer is passed into the for loop and assigned to int i
//e.g. i = 153//
If the value of i is greater than 0, then re-assign the value of i to i/10 //e.g. 153/10 == 15r3 //
Assign the remainder value of i/10 to int remainder //e.g. remainder = 3//
Compute the sum as sum + remainder * remainder * remainder //e.g. sum = 0 + 3 * 3 * 3//
if the sum is equal to the number, then print "Entered number is Armstrong number" //e.g. however, 27 !== 153//
What am I missing here?
Since this is self-admitted homework, I'm not going to give you a complete answer, but pointers instead.
Make number a string variable. You can then use your for loop to go through each character in the string and perform the math on them.
Use math.pow to create your sum, not sum = sum + remainder * remainder * remainder, since this makes the assumption that you are always using a 3-digit number. (hint: int N = number.Length()
Helper links:
math.pow
Armstrong Numbers
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
And my answer is:
bool IsRishoni;
int soap = 0;
for (int i = 3; i < 2000000; i++)
{
IsRishoni = true;
for (int a = 2; (a <= Math.Sqrt(i)) && (IsRishoni); a++)
{
if (i % a == 0)
IsRishoni = false;
}
if (IsRishoni)
{
soap = i + soap;
}
}
Console.WriteLine(soap + 2);
Console.ReadLine();
Why is this not working? the answer I got is 1179908154 ... help please.
Replace
soap = i + soap;
with
soap = checked(i + soap);
..and the problem should be exposed.
This question has more details: No overflow exception for int in C#?
Your answer (stored in soap) is a value greater than int.Maxvalue (2,147,483,647).
Your answer is ~ 150,000,000,000
In other words you need to use an data type which is bigger than that.
long.MaxValue = 9,223,372,036,854,775,807
int.Maxvalue = 2,147,483,647
The result you’re after might be too large to represent through a 32-bit signed integer (int).
Let’s first determine the result’s upper bound by assuming that all numbers are prime. Through summation, we know that the sum of all numbers up to N (inclusive) is N * (N + 1) / 2; thus, the upper bound for the sum of all primes up to 2,000,000 is 2,000,001,000,000. This is larger than the maximum value allowed by int, 2,147,483,647, so you’re probably getting a numeric overflow which is silently ignored.
If you wanted a more accurate estimate of your answer, you could use the prime number theorem, which states that the probability of a random integer between 0 and N being prime is approximately 1 / ln(N). Combining this with our previous formula, the approximate sum of all primes up to N is N * (N + 1) / (2 * ln(N)). For 2,000,000, this evaluates to around 138,000,000,000, which is still larger than the maximum value for int.
To resolve your problem, you could simply switch the integral data type you’re using for the soap variable to a 64-bit integer representation, such as long. Its maximum value is 9,223,372,036,854,775,807, so it would definitely be able to represent your number.
long soap = 0;
On a separate note: Since you’re working with sequences of primes, you could achieve a huge performance gain (at least 100×) if you change your implementation to a Sieve of Eratosthenes.
I already know when a fraction is repeating decimals. Here is the function.
public bool IsRepeatingDecimal
{
get
{
if (Numerator % Denominator == 0)
return false;
var primes = MathAlgorithms.Primes(Denominator);
foreach (int n in primes)
{
if (n != 2 && n != 5)
return true;
}
return false;
}
}
Now, I'm trying to get the repeated number. I'm checking this web site: http://en.wikipedia.org/wiki/Repeating_decimal
public decimal RepeatingDecimal()
{
if (!IsRepeatingDecimal) throw new InvalidOperationException("The fraction is not producing repeating decimals");
int digitsToTake;
switch (Denominator)
{
case 3:
case 9: digitsToTake = 1; break;
case 11: digitsToTake = 2; break;
case 13: digitsToTake = 6; break;
default: digitsToTake = Denominator - 1; break;
}
return MathExtensions.TruncateAt((decimal)Numerator / Denominator, digitsToTake);
}
But I really realized, that some numbers has a partial decimal finite and later infinite. For example: 1/28
Do you know a better way to do this? Or an Algorithm?
A very simple algorithm is this: implement long division. Record every intermediate division you do. As soon as you see a division identical to the one you've done before, you have what's being repeated.
Example: 7/13.
1. 13 goes into 7 0 times with remainder 7; bring down a 0.
2. 13 goes into 70 5 times with remainder 5; bring down a 0.
3. 13 goes into 50 3 times with remainder 11; bring down a 0.
4. 13 goes into 110 8 times with remainder 6; bring down a 0.
5. 13 goes into 60 4 times with remainder 8; bring down a 0.
6. 13 goes into 80 6 times with remainder 2; bring down a 0.
7. 13 goes into 20 1 time with remainder 7; bring down a 0.
8. We have already seen 13/70 on line 2; so lines 2-7 have the repeating part
The algorithm gives us 538461 as the repeating part. My calculator says 7/13 is 0.538461538. Looks right to me! All that remains are implementation details, or to find a better algorithm!
If you have a (positive) reduced fraction numerator / denominator, the decimal expansion of the fraction terminates if and only if denominator has no prime factor other than 2 or 5. If it has any other prime factor, the decimal expansion will be periodic. However, the cases where the denominator is divisible by at least one of 2 and 5 and where it isn't give rise to slightly different behaviour. We have three cases:
denominator = 2^a * 5^b, then the decimal expansion terminates max {a, b} digits after the decimal point.
denominator = 2^a * 5^b * m where m > 1 is not divisible by 2 or by 5, then the fractional part of the decimal expansions consists of two parts, the pre-period of length max {a, b} and the period, whose length is determined by m and independent of the numerator.
denominator > 1 is not divisible by 2 or by 5, then the decimal expansion is purely periodic, meaning the period starts immediately after the decimal point.
The treatment of cases 1. and 2. has a common part, let c = max {a, b}, then
numerator / denominator = (numerator * 2^(c-a) * 5^(c-b)) / (10^c * m)
where m = 1 for case 1. Note that one of the factors 2^(c-a) and 5^(c-b) with which we multiply the numerator is 1. Then you get the decimal expansion by expanding
(numerator * 2^(c-a) * 5^(c-b)) / m
and shifting the decimal point c places to the left. In the first case (m = 1) that part is trivial.
The treatment of cases 2. and 3. also has a common part, the calculation of a fraction
n / m
where n and m have no common prime factor (and m > 1). We can write n = q*m + r with 0 <= r < m (division with remainder, r = n % m), q is the integral part of the fraction and rather uninteresting.
Since the fraction was assumed reduced, we have r > 0, so we want to find the expansion of a fraction r / m where 0 < r < m and m is not divisible by 2 or by 5. As mentioned above, such an expansion is purely periodic, so finding the period means finding the complete expansion.
Let's go about finding the period heuristically. So let k be the length of the (shortest) period and p = d_1d1_2...d_k the period. So
r / m = 0.d_1d_2...d_kd_1d_2...d_kd_1...
= (d_1d_2...d_k)/(10^k) + (d_1d_2...d_k)/(10^(2k)) + (d_1d_2...d_k)/(10^(3k)) + ...
= p/(10^k) * (1 + 1/(10^k) + 1/(10^(2k)) + 1/(10^(3k)) + ...)
The last term is a geometric series, 1 + q + q^2 + q^3 + ... which, for |q| < 1 has the sum 1/(1-q).
In our case, 0 < q = 1/(10^k) < 1, so the sum is 1 / (1 - 1/(10^k)) = 10^k / (10^k-1). Thus we have seen that
r / m = p / (10^k-1)
Since r and m have no common factor, that means there is an s with 10^k - 1 = s*m and p = s*r. If we know k, the length of the period, we can simply find the digits of the period by calculating
p = ((10^k - 1)/m) * r
and padding with leading zeros until we have k digits. (Note: it is that simple only if k is sufficiently small or a big integer type is available. To calculate the period of for example 17/983 with standard fixed-width integer types, use long division as explained by #Patrick87.)
So it remains to find the length of the period. We can revert the reasoning above and find that if m divides 10^u - 1, then we can write
r / m = t/(10^u - 1) = t/(10^u) + t/(10^(2u)) + t/(10^(3u)) + ...
= 0.t_1t_2...t_ut_1t_2...t_ut_1...
and r/m has a period of length u. So the length of the shortest period is the minimal positive u such that m divides 10^u - 1, or, put another way, the smallest positive u such that 10^u % m == 1.
We can find it in O(m) time with
u = 0;
a = 1;
do {
++u;
a = (10*a) % m;
while(a != 1);
Now, finding the length of the period that way is not more efficient than finding the digits and length of the period together with long division, and for small enough m that is the most efficient method.
int[] long_division(int numerator, int denominator) {
if (numerator < 1 || numerator >= denominator) throw new IllegalArgumentException("Bad call");
// now we know 0 < numerator < denominator
if (denominator % 2 == 0 || denominator % 5 == 0) throw new IllegalArgumentException("Bad denominator");
// now we know we get a purely periodic expansion
int[] digits = new int[denominator];
int k = 0, n = numerator;
do {
n *= 10;
digits[k++] = n / denominator;
n = n % denominator;
}while(n != numerator);
int[] period = new int[k];
for(n = 0; n < k; ++n) {
period[n] = digits[n];
}
return period;
}
That works as long as 10*(denominator - 1) doesn't overflow, of course int could be a 32-bit or 64-bit integer as needed.
But for large denominators, that is inefficient, one can find the period length and also the period faster by considering the prime factorisation of the denominator. Regarding the period length,
If the denominator is a prime power, m = p^k, the period length of r/m is a divisor of (p-1) * p^(k-1)
If a and b are coprime and m = a * b, the period length of r/m is the least common multiple of the period lengths of 1/a and 1/b.
Taken together, the period length of r/m is a divisor of λ(m), where λ is the Carmichael function.
So to find the period length of r/m, find the prime factorisation of m and for all prime power factors p^k, find the period of 1/(p^k) - equivalently, the multiplicative order of 10 modulo p^k, which is known to be a divisor of (p-1) * p^(k-1). Since such numbers haven't many divisors, that is quickly done.
Then find the least common multiple of all these.
For the period itself (the digits), if a big integer type is available and the period isn't too long, the formula
p = (10^k - 1)/m * r
is a quick way to compute it. If the period is too long or no big integer type is available, efficiently computing the digits is messier, and off the top of my head I don't remember how exactly that is done.
One way would be to repeat the way that you do long division by hand, and keep note of the remainder at each stage. When the remainder repeats, the rest of the process must repeat as well. E.g. the digits of 1.0/7 are 0.1 remainder 3 then 0.14 remainder 2 then 0.142 remainder 6 then 0.1428 remainder 4 then 0.14285 remainder 5 then 0.142857 remainder 1 which is the 1 that starts it off again amd so you get 0.1428571 remainder 3 and it repeats again from there.
The long division algorithm is pretty good, so I have nothing to add there.
But note that your algorithm IsRepeatingDecimal may not work and is inneficient.
It will not work if your fraction is not irreductible, that is if there exists an integer larger than 1 that divides both your numerator and your denominator. For example, if you feed 7/14 then your algorithm will return true when it should return false.
To reduce your fraction, find the gcd between both numerator and denominator and divide both by this gcd.
If you assume that the fraction is irreducible, then your test
if (Numerator % Denominator == 0)
can simply be replaced with
if (Denominator == 1)
But that is still unnecessary since if Denominator is 1, then your list 'primes' is going to be empty and your algorithm will return false anyway.
Finally, calling MathAlgorithms.Primes(Denominator) is going to be expensive for large numbers and can be avoided. Indeed, all you need to do is divide your denominator by 5 (respectively 2) untill it is no longer divisible by 5 (resp. 2). If the end result is 1, then return false, otherwise return true.
I came here expecting to be able to copy & paste the code to do this, but it didn't exist. So after reading #Patrick87's answer, I went ahead and coded it up. I spent some time testing it thoroughly and giving things a nice name. I thought I would leave it here so others don't have to waste their time.
Features:
If the decimal terminates, it handles that. It calculates the period and puts that in a separate variable called period, in case you want to know the length of the reptend.
Limitations:
It will fail if the transient + reptend is longer than can be represented by a System.Decimal.
public static string FormatDecimalExpansion(RationalNumber value)
{
RationalNumber currentValue = value;
string decimalString = value.ToDecimal().ToString();
int currentIndex = decimalString.IndexOf('.');
Dictionary<RationalNumber, int> dict = new Dictionary<RationalNumber, int>();
while (!dict.ContainsKey(currentValue))
{
dict.Add(currentValue, currentIndex);
int rem = currentValue.Numerator % currentValue.Denominator;
int carry = rem * 10;
if (rem == 0) // Terminating decimal
{
return decimalString;
}
currentValue = new RationalNumber(carry, currentValue.Denominator);
currentIndex++;
}
int startIndex = dict[currentValue];
int endIndex = currentIndex;
int period = (endIndex - startIndex); // The period is the length of the reptend
if (endIndex >= decimalString.Length)
{
throw new ArgumentOutOfRangeException(nameof(value),
"The value supplied has a decimal expansion that is longer" +
$" than can be represented by value of type {nameof(System.Decimal)}.");
}
string transient = decimalString.Substring(0, startIndex);
string reptend = decimalString.Substring(startIndex, period);
return transient + $"({reptend})";
}
And for good measure, I will include my RationalNumber class.
Note: It inherits from IEquatable so that it works correctly with the dictionary:
public struct RationalNumber : IEquatable<RationalNumber>
{
public int Numerator;
public int Denominator;
public RationalNumber(int numerator, int denominator)
{
Numerator = numerator;
Denominator = denominator;
}
public decimal ToDecimal()
{
return Decimal.Divide(Numerator, Denominator);
}
public bool Equals(RationalNumber other)
{
return (Numerator == other.Numerator && Denominator == other.Denominator);
}
public override int GetHashCode()
{
return new Tuple<int, int>(Numerator, Denominator).GetHashCode();
}
public override string ToString()
{
return $"{Numerator}/{Denominator}";
}
}
Enjoy!
I am coding a program where a form opens for a certain period of time before closing. I am giving the users to specify the time in seconds. But i'd like this to be in mutliples of five. Or the number gets rounded off to the nearest multiple.
if they enter 1 - 4, then the value is automatically set to 5.
If they enter 6 - 10 then the value is automatically set to 10.
max value is 60, min is 0.
what i have, but i am not happy with this logic since it resets it to 10 seconds.
if (Convert.ToInt32(maskedTextBox1.Text) >= 60 || Convert.ToInt32(maskedTextBox1.Text) <= 0)
mySettings.ToastFormTimer = 10000;
else
mySettings.ToastFormTimer = Convert.ToInt32 (maskedTextBox1.Text) * 1000;
use the Modulus Operator
if(num % 5 == 0)
{
// the number is a multiple of 5.
}
what about this:
int x = int.Parse(maskedTextBox1.Text)/5;
int y = Math.Min(Math.Max(x,1),12)*5; // between [5,60]
// use y as the answer you need
5 * ((num - 1) / 5 + 1)
Should work if c# does integer division.
For the higher goal of rounding to the upper multiple of 5, you don't need to test whether a number is a multiple. Generally speaking, you can round-up or round-to-nearest by adding a constant, then rounding down. To round up, the constant is one less than n. Rounding an integer down to a multiple of n is simple: divide by n and multiply the result by n. Here's a case where rounding error works in your favor.
int ceil_n(int x, int n) {
return ((x+n-1) / n) * n;
}
In dynamic languages that cast the result of integer division to prevent rounding error (which doesn't include C#), you'd need to cast the quotient back to an integer.
Dividing by n can be viewed as a right-shift by 1 place in base n; similarly, multiplying by n is equivalent to a left-shift by 1. This is why the above approach works: it sets the least-significant digit of the number in base n to 0.
2410=445, 2510=505, 2610=515
((445+4 = 535) >>5 1) <<5 1 = 505 = 2510
((505+4 = 545) >>5 1) <<5 1 = 505 = 2510
((515+4 = 605) >>5 1) <<5 1 = 605 = 3010
Another way of zeroing the LSD is to subtract the remainder to set the least significant base n digit to 0, as Jeras does in his comment.
int ceil_n(int x, int n) {
x += n-1;
return x - x%n;
}