I can't understand how to solve the problem that the teacher gave me.
Given a number N (0 <= N <= 100), find its first digit.
For example:
input: 100
result: 1
input: 46
result: 4
input: 3
result: 3
It seemed easy at first, but (as the teacher said) it should be done using ONLY integer data types (in other words, using +, -, *, / and % operators). Is it even possible to do it this way?
I just can't realize how to extract the first digit from a variable-length number without using things like log10, conditions, "while" loop or string conversion.
Without any conditionals:
int H= N / 100; // Hundreds digit
int T= (N / 10) % 10; // Tens digit
int U= N % 10; // Units digit
int h= H; // Hundreds flag
int t= (T + 9) / 10 * (1 - h); // Tens flag
int u= (1 - t) * (1 - h); // Units flag
int Answer= u * U + t * T + h * H; // Combination
Edit: Now tested for 0 and 100:
var result = n / 10 * (1 - n / 100) + n / 100 + (109 - n) / 100 * n;
How it works:
n | n / 10 * (1 - n / 100) | n / 100 | (109 - n) / 100 * n
-----------------------------------------------------------------
10 - 99 | 1 - 9 | 0 | 0
-----------------------------------------------------------------
100 | 0 | 1 | 0
-----------------------------------------------------------------
0 - 9 | 0 | 0 | 0 - 9
Use a while loop, and keep dividing the input number by 10, so long as we are starting with a value which is greater than or equal to 10. When the modified input is less than ten, then it means we have stripped off all digits to the right, except for the "first" digit.
int input = 100;
while (input >= 10)
{
input /= 10;
}
Console.WriteLine("First digit is: {0}", input);
Demo
This is a non-generic response, and only works because the domain is limited. The idea is to return all the digits (hundred's, ten's, and one's) smooshed together." Some thoughts on specific ranges of numbers:
100 is easy because the ten's and one's units are both zero. There are no other three digit numbers, which is good, because anything with a non-zero one's or ten's place will cause problems below.
All numbers less than 100 can include the hundred's digit in the response because it will always be zero.
Any multiple of 10 is easy, just include the each hundred's ten's and one's value, because the other digits are zero.
The tricky part is the one's place. There needs to be a way to "cancel out" this value if a larger digit is supposed to be returned. For example, 87, we want the 8 but want to cancel out the 7.
This leads to the idea
(ten - 9)*(ten - 8)*(ten - 7)*(ten - 6)*(ten - 5)*(ten - 4)*(ten - 3)*(ten - 2)*(ten - 1)
What happens is that any time the ten's place is non-zero, the above will evaluate to zero. So we can multiply the one's place by this to zero out the one's place when the ten's place is non-zero. However, there's a problem when the ten's place is zero. In that case, we're off by a factor of 9! (nine factorial = 362880) and the wrong sign. This is why an extra minus sign is included, and divide out by 362880 to get the right answer when ten's place is zero.
public int GetFirstDigit(int n)
{
var hundred = (n % 1000) / 100;
var ten = (n % 100) / 10;
var one = n % 10;
return hundred + ten + one*
(
-(ten - 9)*(ten - 8)*(ten - 7)*(ten - 6)*(ten - 5)*(ten - 4)*(ten - 3)*(ten - 2)*(ten - 1)
) / 362880
;
}
check with
Enumerable.Range(0, 101).ToList().ForEach(x => Console.WriteLine(x + ": " + GetFirstDigit(x)));
I tried to solve the case but without success,
I can only achieve finding the first digit if the N is 1 - 100.
Here is my source code for it. Hope it helps
https://dotnetfiddle.net/6XyOfd
static int Result(int input)
{
return input/100 + (input%100/input)*input/10 + (input%10/input)*input;
}
input/100 will return 1 if and only if input equals 100, else 0
(input%100/input) will return 1 if and only if input < 100, else 0
if input is lower than 10, input/10 will be 0
(input%10/input) will return 1 if and only if input < 10, else 0
Caution
This would break if input == 0, see #quanik's answer to handle 0.
However, it will work for 1-999.
if (N < 10)
Output(N)
else if (N < 100)
Output(N / 10)
else
Output(1)
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm just beginning to learn C# and I can't figure out why this example problem is laid out this way. Maybe I'm not understanding the basics of how the order of operations works. Can someone explain how the "while" portion of this program works? I don't understand what "num = num / 10" does when num is not referenced after this line. Does it affect the previous line? Thanks for any insight.
/*
* C# Program to Get a Number and Display the Sum of the Digits
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Program
{
class Program
{
static void Main(string[] args)
{
int num, sum = 0, r;
Console.WriteLine("Enter a Number : ");
num = int.Parse(Console.ReadLine());
while (num != 0)
{
r = num % 10;
num = num / 10;
sum = sum + r;
}
Console.WriteLine("Sum of Digits of the Number : "+sum);
Console.ReadLine();
}
}
}
Does it affect the previous line?
If by previous you mean the while condition, then yes, and just affect the check by next check in the loop.
the code just do a summary of all the digital numbers
like if your input is
1235
then the output will be
1+2+3+5 = 11
The while loop will forever be executed if the condition is true by
num != 0
And in the loop, you just modify the num so that it will be compared to 0 again in the next condition check.
If it's always true ie always
num != 0
Then you will get an infinite loop, which is possible in some condition.
And welcome to the coding world :D
Example We Input a Number "123"
When it goes to the condition While Number(123) != (is not equal to) 0 Then it will perform the code.
First get the remainder by using modulus %.
Second get the Whole number by using division.
Third Get the sum.
1.) r = num % 10 | The value of r now is 3
2.) num = num / 10 | The value of num now is 12.
3.) sum = sum + r | The value of sum here is 0 + the remainder 3.
It will go the the while statement again. Is the number(12) != (is not equal to) 0 then it will perform the code.
Take note the value now of Num is 12 ok.
Perform again the code.
1.) r = num % 10 | The value of r now is 2
2.) num = num / 10 | The value of num now is 1.
3.) sum = sum + r | The value of sum here now is 3 + the remainder now is 2.
So the sum now is 5. Then it will loop again because Num now is equal to 1. Then
Perform the code again.
I think this explains the best for you.
class Program
{
static void Main(string[] args)
{
int num, sum = 0, r;
Console.WriteLine("Enter a Number : ");
num = int.Parse(Console.ReadLine());
while (num != 0)
{
/* Important: The logic behind is to add the numbers from the last one
* to the first one.
*
* For example, 123 will be added in this way: 3 + 2 + 1
* We will use number 123 as example.*/
/* Comment:
*
* 1st run: 123 % 10, remainder will be 3. Anything modulus 10 will
* always get the final digit. Now, we have r = 3, which will be used
* in the final sum below.
*
* 2nd run: 12 % 10, remainder will be 2. Now, we have r = 2, which
* will be used in the final sum below.
*
* 3rd run: 1 % 10, remainder will be 1. Now, we have r = 1, which will
* be used in the final sum below.
*/
r = num % 10;
/* Comment:
*
* 1st run: 123 / 10, answer will be 12. If you are wondering why it
* isn't 12.3, then it is because the datatype in used is "int", so the
* answer will always be a round number, so 12.3 in round number will
* be 12, which is the 2 numbers that have not been added, so now,
* num = 12, and we have managed to discard 3 because we no longer need
* it because it will be added in the final sum below.
*
* 2nd run: 12 / 10, again answer is not 1.2, but num = 1.
* We have managed to discard 2 because we no longer need it because it
* will be added in the final sum below.
*
* 3rd run: 1 / 10, again answer is not 0.1, but num = 0.
* We have managed to discard 1 because we no longer need it because it
* will be added in the final sum below. This will be the final run.
*/
num = num / 10;
/* Comment:
* 1st run: 0 + 3 (1st run remainder)
* 2nd run: 3 + 2 (2nd run remainder)
* 3rd run: 5 + 1 (3rd run remainder)
*/
sum = sum + r;
}
Console.WriteLine("Sum of Digits of the Number : " + sum);
Console.ReadLine();
}
}
And yes, the "num" variable is used by the "while" loop to check on the current condition. If the "num" is not "0", then the logic will continue to run. Hope this helps.
I think you will end up in an endless loop in that Code. Using while loop it always execute the code inside the while loop as long as your num variable has a value.
And inside your while loop code your sum value has no connection with the formula.
r = num % 10;
num = num / 10;
sum = sum + r;
Instead change it to this where sum is set to value of num / 10
r = num % 10;
sum = num / 10;
sum = sum + r;
And use if statement instead. Because every time the user input number it is guaranteed that it is only executed once. so no need for while loop.
This is what I have so far:
int num = 12345;
int length = Math.Floor(Math.Log10(num)+1);
Console.WriteLine(length);
Console.ReadKey();
The output should be 5.
This is obviously giving me errors, but I really don't know another way of how to do it since the instructions are so clear to not use ToString.
Any help or guidance would be appriciated. Thanks.
There are two ways to go about this: The really lazy easy way, and a slightly less lazy but simpler-to-understand way.
Here's the easy way. It's almost what you did, but with a few tweaks to handle the zero corner-case, and the requisite cast:
int length = number > 0 ? (int)Math.Floor(Math.Log10(number)) + 1 : 1;
The slightly less lazy solution is repeated division by ten; to know how many digits there are, you just keep dividing by ten until you run out of them:
int length = 0;
while (number > 0) {
length++;
number /= 10;
}
if (length < 1) length = 1;
The last "less than one" check is because you obviously can't have a number with no digits at all in it.
As one of the commenters noted, this only works for nonnegative integers. (But then the "length" of a negative integer is an interesting meta-question in and of itself; should you include the sign as part of the length, or is it merely the number of digits?) If you want it to work for negative values (or fractions), you'll have to convert them to positive values first, and then potentially add one more position for the sign, depending on what you're trying to compute.
Anyway, there ya go. Nice and easy.
The length is 1+⌊log10max(1,|x|)⌋. So you can implement it like:
int length = 1+Math.Floor(Math.Log10(Math.Max(1,Math.Abs(num))));
Examples in the csharp console:
csharp> for(int i = 0; i < 15; i++) {
> Console.WriteLine("{0}: {1}",i,1+Math.Floor(Math.Log10(Math.Max(1,Math.Abs(i)))));
> }
0: 1
1: 1
2: 1
3: 1
4: 1
5: 1
6: 1
7: 1
8: 1
9: 1
10: 2
11: 2
12: 2
13: 2
14: 2
csharp> for(int i = 0; i > -15; i--) {
> Console.WriteLine("{0}: {1}",i,1+Math.Floor(Math.Log10(Math.Max(1,Math.Abs(i)))));
> }
0: 1
-1: 1
-2: 1
-3: 1
-4: 1
-5: 1
-6: 1
-7: 1
-8: 1
-9: 1
-10: 2
-11: 2
-12: 2
-13: 2
-14: 2
You can divide the number by 10 (i.e. shift the decimal separator) until all the digits are on the right side of the decimal separator:
public static int GetNumDigitsWithoutToString(int forInput)
{
if (forInput == 0) return 1; // guard clause to prevent divide by zero error.
int numDigits = 0;
var x = (decimal) forInput;
while (x >= 1)
{
numDigits++;
x = x / 10;
}
return numDigits;
}
IMO the easiest one to understand would be :
int num = 12345;
int counter = 1; // start counter with one because you'll automatically "remove" one sign
while ( ( num /= 10 ) != 0 ) counter++;
//Console.WriteLine(counter) >> 5;
This will work with negatives as well.
online example
I created LINQ implementation of mod10 algorithm.
The source code:
string number = "7992739871";
int mod10sum = number.Reverse()
.Select((c, i) => (c - '0') << ((i + 1) & 1)) // Double every other digit and sum the digits of the products (e.g., 10: 1 + 0 = 1, 14: 1 + 4 = 5)
.Sum(c => c - '0') % 10; // together with the undoubled digits from the original number
string checkDigit = (mod10sum == 0 ? 0 : 10 - mod10sum).ToString("0");
Console.WriteLine(checkDigit);
As per the example, 7992739871 number should have check digit as 3; however, what I am getting is 15.
What I am doing wrong? I am sure the mistake is very small but can't find it.
The problem is with the Select method. In order to sum up all the digits (as described in the algorithm) you would need to return 1 and 0 instead of 10, 1 and 4 instead of 14 (as in your example).
The easiest (but it does not have to be the most optimal) way to do that is to conert number from Select to string (14 -> "14") and then split the string characters using SelectMany.
So your code should look as follows:
int mod10sum = number.Reverse()
.SelectMany((c, i) => ((c - '0') << ((i + 1) & 1)).ToString())
.Sum(c => c - '0') % 10;
checkDigit = (mod10sum == 0 ? 0 : 10 - mod10sum).ToString("0");
Console.WriteLine(checkDigit);
A bit of theory
LINQ SelectMany returns IEnumerable<>. When you return string (which is IEnumerable) then that's why SelectMany "splits" returned string into characters.
Microsoft has very nice page (101 LINQ Samples) with different LINQ samples which should help you out.
EDIT
I would also recommend working on that conversion from int to string. I was working on similar project literally yesterday and in my case that conversion is a bit problematic from performance point of view as we call that method millions of times. If you have to calculate lots of mod10's then it might be not the best solution.
I would change the Sum.
At this point, you don't have a sequence of characters, but the single-or-doubled-as-appropriate value for each original digit.
Thus, you don't need to be subtracting 0, you need to be calculating the digit sum of each of these integers, and (since you know they'll be small) you can do this as simply as
.Sum(i => (i % 10) + (i / 10))
giving
string number = "7992739871";
int mod10sum = number.Reverse()
.Select((c, i) => (c - '0') << ((i + 1) & 1))
.Sum(i => (i % 10) + (i / 10)) % 10;
This should be more effecient than calling ToString() and iterating over the result.
I'm trying to refactor this algorithm to make it faster. What would be the first refactoring here for speed?
public int GetHowManyFactors(int numberToCheck)
{
// we know 1 is a factor and the numberToCheck
int factorCount = 2;
// start from 2 as we know 1 is a factor, and less than as numberToCheck is a factor
for (int i = 2; i < numberToCheck; i++)
{
if (numberToCheck % i == 0)
factorCount++;
}
return factorCount;
}
The first optimization you could make is that you only need to check up to the square root of the number. This is because factors come in pairs where one is less than the square root and the other is greater.
One exception to this is if n is an exact square then its square root is a factor of n but not part of a pair.
For example if your number is 30 the factors are in these pairs:
1 x 30
2 x 15
3 x 10
5 x 6
So you don't need to check any numbers higher than 5 because all the other factors can already be deduced to exist once you find the corresponding small factor in the pair.
Here is one way to do it in C#:
public int GetFactorCount(int numberToCheck)
{
int factorCount = 0;
int sqrt = (int)Math.Ceiling(Math.Sqrt(numberToCheck));
// Start from 1 as we want our method to also work when numberToCheck is 0 or 1.
for (int i = 1; i < sqrt; i++)
{
if (numberToCheck % i == 0)
{
factorCount += 2; // We found a pair of factors.
}
}
// Check if our number is an exact square.
if (sqrt * sqrt == numberToCheck)
{
factorCount++;
}
return factorCount;
}
There are other approaches you could use that are faster but you might find that this is already fast enough for your needs, especially if you only need it to work with 32-bit integers.
Reducing the bound of how high you have to go as you could knowingly stop at the square root of the number, though this does carry the caution of picking out squares that would have the odd number of factors, but it does help reduce how often the loop has to be executed.
Looks like there is a lengthy discussion about this exact topic here: Algorithm to calculate the number of divisors of a given number
Hope this helps
The first thing to notice is that it suffices to find all of the prime factors. Once you have these it's easy to find the number of total divisors: for each prime, add 1 to the number of times it appears and multiply these together. So for 12 = 2 * 2 * 3 you have (2 + 1) * (1 + 1) = 3 * 2 = 6 factors.
The next thing follows from the first: when you find a factor, divide it out so that the resulting number is smaller. When you combine this with the fact that you need only check to the square root of the current number this is a huge improvement. For example, consider N = 10714293844487412. Naively it would take N steps. Checking up to its square root takes sqrt(N) or about 100 million steps. But since the factors 2, 2, 3, and 953 are discovered early on you actually only need to check to one million -- a 100x improvement!
Another improvement: you don't need to check every number to see if it divides your number, just the primes. If it's more convenient you can use 2 and the odd numbers, or 2, 3, and the numbers 6n-1 and 6n+1 (a basic wheel sieve).
Here's another nice improvement. If you can quickly determine whether a number is prime, you can reduce the need for division even further. Suppose, after removing small factors, you have 120528291333090808192969. Even checking up to its square root will take a long time -- 300 billion steps. But a Miller-Rabin test (very fast -- maybe 10 to 20 nanoseconds) will show that this number is composite. How does this help? It means that if you check up to its cube root and find no factors, then there are exactly two primes left. If the number is a square, its factors are prime; if the number is not a square, the numbers are distinct primes. This means you can multiply your 'running total' by 3 or 4, respectively, to get the final answer -- even without knowing the factors! This can make more of a difference than you'd guess: the number of steps needed drops from 300 billion to just 50 million, a 6000-fold improvement!
The only trouble with the above is that Miller-Rabin can only prove that numbers are composite; if it's given a prime it can't prove that the number is prime. In that case you may wish to write a primality-proving function to spare yourself the effort of factoring to the square root of the number. (Alternately, you could just do a few more Miller-Rabin tests, if you would be satisfied with high confidence that your answer is correct rather than a proof that it is. If a number passes 15 tests then it's composite with probability less than 1 in a billion.)
You can limit the upper limit of your FOR loop to numberToCheck / 2
Start your loop counter at 2 (if your number is even) or 3 (for odd values). This should allow you to check every other number dropping your loop count by another 50%.
public int GetHowManyFactors(int numberToCheck)
{
// we know 1 is a factor and the numberToCheck
int factorCount = 2;
int i = 2 + ( numberToCheck % 2 ); //start at 2 (or 3 if numberToCheck is odd)
for( ; i < numberToCheck / 2; i+=2)
{
if (numberToCheck % i == 0)
factorCount++;
}
return factorCount;
}
Well if you are going to use this function a lot you can use modified algorithm of Eratosthenes http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes and store answars for a interval 1 to Max in array. It will run IntializeArray() once and after it will return answers in 0(1).
const int Max =1000000;
int arr [] = new int [Max+1];
public void InitializeArray()
{
for(int i=1;i<=Max;++i)
arr[i]=1;//1 is factor for everyone
for(int i=2;i<=Max;++i)
for(int j=i;i<=Max;i+=j)
++arr[j];
}
public int GetHowManyFactors(int numberToCheck)
{
return arr[numberToCheck];
}
But if you are not going to use this function a lot I think best solution is to check unitll square root.
Note: I have corrected my code!
An easy to implement algorithm that will bring you much farther than trial division is Pollard Rho
Here is a Java implementation, that should be easy to adapt to C#: http://www.cs.princeton.edu/introcs/78crypto/PollardRho.java.html
https://codility.com/demo/results/demoAAW2WH-MGF/
public int solution(int n) {
var counter = 0;
if (n == 1) return 1;
counter = 2; //1 and itself
int sqrtPoint = (Int32)(Math.Truncate(Math.Sqrt(n)));
for (int i = 2; i <= sqrtPoint; i++)
{
if (n % i == 0)
{
counter += 2; // We found a pair of factors.
}
}
// Check if our number is an exact square.
if (sqrtPoint * sqrtPoint == n)
{
counter -=1;
}
return counter;
}
Codility Python 100 %
Here is solution in python with little explanation-
def solution(N):
"""
Problem Statement can be found here-
https://app.codility.com/demo/results/trainingJNNRF6-VG4/
Codility 100%
Idea is count decedent factor in single travers. ie. if 24 is divisible by 4 then it is also divisible by 8
Traverse only up to square root of number ie. in case of 24, 4*4 < 24 but 5*5!<24 so loop through only i*i<N
"""
print(N)
count = 0
i = 1
while i * i <= N:
if N % i == 0:
print()
print("Divisible by " + str(i))
if i * i == N:
count += 1
print("Count increase by one " + str(count))
else:
count += 2
print("Also divisible by " + str(int(N / i)))
print("Count increase by two count " + str(count))
i += 1
return count
Example by run-
if __name__ == '__main__':
# result = solution(24)
# result = solution(35)
result = solution(1)
print("")
print("Solution " + str(result))
"""
Example1-
24
Divisible by 1
Also divisible by 24
Count increase by two count 2
Divisible by 2
Also divisible by 12
Count increase by two count 4
Divisible by 3
Also divisible by 8
Count increase by two count 6
Divisible by 4
Also divisible by 6
Count increase by two count 8
Solution 8
Example2-
35
Divisible by 1
Also divisible by 35
Count increase by two count 2
Divisible by 5
Also divisible by 7
Count increase by two count 4
Solution 4
Example3-
1
Divisible by 1
Count increase by one 1
Solution 1
"""
Github link
I got pretty good results with complexity of O(sqrt(N)).
if (N == 1) return 1;
int divisors = 0;
int max = N;
for (int div = 1; div < max; div++) {
if (N % div == 0) {
divisors++;
if (div != N/div) {
divisors++;
}
}
if (N/div < max) {
max = N/div;
}
}
return divisors;
Python Implementation
Score 100% https://app.codility.com/demo/results/trainingJ78AK2-DZ5/
import math;
def solution(N):
# write your code in Python 3.6
NumberFactor=2; #one and the number itself
if(N==1):
return 1;
if(N==2):
return 2;
squareN=int(math.sqrt(N)) +1;
#print(squareN)
for elem in range (2,squareN):
if(N%elem==0):
NumberFactor+=2;
if( (squareN-1) * (squareN-1) ==N):
NumberFactor-=1;
return NumberFactor
What is the algorithm in c# to do this?
Example 1:
Given n = 972, function will then append 3 to make 9723, because 9 + 7 + 2 + 3 = 21 (ends with 1). Function should return 3.
Example 2:
Given n = 33, function will then append 5 to make 335, because 3 + 3 + 5 = 11 (ends with 1). Function should return 5.
Algorithms are language independent. Asking for "an algorithm in C#" doesn't make much sense.
Asking for the algorithm (as though there is only one) is similarly misguided.
So, let's do this step by step.
First, we note that only the last digit of the result is meaningful. So, we'll sum up our existing digits, and then ignore all but the last one. A good way to do this is to take the sum modulo 10.
So, we have the sum of the existing digits, and we want to add another digit to that, so that the sum of the two ends in 1.
For the vast majority of cases, that will mean sum + newDigit = 11. Rearranging gives newDigit = 11 - sum
We can then take this modulo 10 (again) in order to reduce it to a single digit.
Finally, we multiply the original number by 10, and add our new digit to it.
The algorithm in general:
(10 - (sum of digits mod 10) + 1) mod 10
The answer of the above expression is your needed digit.
sum of digits mod 10 gives you the current remainder, when you subtract this from 10 you get the needed value for a remainder of 0. When you add 1 you get the needed value to get a remainder of 1. The last mod 10 gives you the answer as a 1 digit number.
So in C# something like this:
static int getNewValue(string s)
{
int sum = 0;
foreach (char c in s)
{
sum += Convert.ToInt32(c.ToString());
}
int newDigit = (10 - (sum % 10) + 1) % 10;
return newDigit;
}
Another alternative using mod once only
int sum = 0;
foreach (char c in s)
sum += Convert.ToInt32(c.ToString());
int diff = 0;
while (sum % 10 != 1)
{
sum++;
diff++;
}
if (diff > 0)
s += diff.ToString();
Well, it's easier in C++.
std::string s = boost::lexical_cast<string>( i );
i = i * 10 + 9 - std::accumulate( s.begin(), s.end(), 8 - '0' * s.size() ) % 10;
Addicted to code golf…