Solving modulo equations programmatically - c#

My goal is to implement a (simple) check digit alglorithm as described Here
My implemantion is the following but I am not sure if it is optimal:
private int CheckDigit(string SevenDecimal)
{
///Get UPC check digit of a 7-digit URI
///Add odd and multiply by 3 =Odds
///Add even =Evens
///Add Odds+Evens=sum
///Check digit is the number that makes Sum divisble by 10
int Odds = 0;
int Evens = 0;
int sum = 0;
int index = 0;
foreach (char digit in SevenDecimal)
{
index++;
int Digit = int.Parse(digit.ToString());
if (index % 2 == 0)
{
Evens +=Digit;
}
else
{
Odds +=Digit;
}
}
Odds = Odds * 3;
sum = Odds + Evens;
for (int i = 0; i < 10; i++) ///Brute force way check for better implementation
{
int Localsum;
Localsum = sum + i;
if (Localsum % 10 == 0)
{
return i;
}
}
return -1;//error;
}
My main concern is in the final for loop which as I describe is totallly brute.
Is there a better way to obtaining the check digit?
More precisely which is the best way to solve programmatically, the equation:
(sum+x)%10=0 //solve for x

To find "how much i you have to add to make the last digit of a number a 0", you can subtract from 10:
int checkDigit = (10 - (sum % 10)) % 10;
The second modulo is used for the special case when sum % 10 == 0, because 10 - 0 = 10

You are asking the wrong question. The expression is not one of equivalence thus x is not a value. The solution is that x is an infinite number of values each of which correctly solve the equation. As such you don't really want to solve for x but just check if x is in this solution space. You can check this simply with:
remainder = base - (sum % base)
You can then test if x sums up to the remainder with:
if (x % base === base - (sum % base))
{
// (sum + x) % base = 0 is true
}
Replace base with 10and you'll have it.

Related

Correct ICCID algo

I need to validate ICCID, I found only one algo:
int numberStringLength = 18;
int cs = 0;
int dodd;
for (int i = 0; i < numberStringLength; i += 2)
{
dodd = Convert.ToInt32(iccid.Substring(i + 1, 1)) << 1;
cs += Convert.ToInt32(iccid.Substring(i, 1)) + (int)(dodd / 10) + (dodd % 10);
}
cs = (10-(cs % 10)) % 10;
if (cs == Convert.ToInt32(iccid.Substring(numberStringLength, 1)))
{
return true;
}
else
{
return false;
}
but it returns false for 100% right ICCID (89148000005339755555). Where can I get real ICCID algo?
Thanks
According to Wikipedia, ICCIDs use the Luhn algorithm.
Your code that you found is a bit broken, as it assumes that the value has an odd number of digits (an even number of normal digits, plus 1 check digit). It starts parsing the value from the left-most digit, and assumes that this left-most digit ("8" in your example) is not doubled and the next one ("9") is doubled. But this is not correct if the value has an even number of digits. The "8" should be the one that's doubled in your case.
Thankfully, it's very easy to implement the Luhn algorithm ourselves, properly, using that Wikipedia page as reference:
string input = "89148000005339755555";
int sum = 0;
// We'll use index i = 0 means the right-most digit, i = 1 is second-right, etc
for (int i = 0; i < input.Length; i++)
{
// Get the digit at the i'th position from the right
int digit = int.Parse(input[input.Length - i - 1].ToString());
// If it's in an odd position (starting from the right), then double it.
if (i % 2 == 1)
{
digit *= 2;
// If it's now >= 10, subtract 9
if (digit >= 10)
{
digit -= 9;
}
}
sum += digit;
}
// It's a pass if the result is a multiple of 10
bool pass = sum % 10 == 0;
Console.WriteLine(pass ? "Pass" : "Fail");
See it on dotnetfiddle.net.

Get all n-digit numbers whose sum of digits equals to given sum

How can I get all n-digit numbers whose sum of digits equals to given sum? I need the fastest solution because n can be equal with 9 and sum can be equal with 1000.
I have implemented the solution below but it's too slow...
List<int> l = new List<int>();
void findNDigitNumsUtil(int n, int sum, char[] ou, int index)
{
if (index > n || sum < 0)
return;
if (index == n)
{
if (sum == 0)
{
ou[index] = '\0';
string s = new string(ou);
l.Add(Int32.Parse(s));
}
return;
}
for (int i = 0; i <= 9; i++)
{
ou[index] = (char)(i + '0');
findNDigitNumsUtil(n, sum - i, ou,
index + 1);
}
}
void findNDigitNums(int n, int sum)
{
char[] ou = new char[n + 1];
for (int i = 1; i <= 9; i++)
{
ou[0] = (char)(i + '0');
findNDigitNumsUtil(n, sum - i, ou, 1);
}
}
I need the fastest solution
No, you need a fast-enough solution. You are probably unwilling to spend even a million dollars on custom hardware to get the fastest possible solution.
How can I get all n-digit numbers whose sum of digits equals to given sum?
Here, I'll give you the solution for a slightly different problem:
What are all the sequences of n digits drawn from 0-9 that sum to sum?
This is different because this counts 01 and 10 as sequences of length two that sum to 1, but 01 is not a two-digit number.
I'll give you a hint for how to solve this easier problem. You then take that solution and adapt it to your harder problem.
First, can you solve the problem for one-digit numbers? That's pretty easy. The one-digit numbers whose digits sum to n are the digit n if n is 0 through 9, and there is no solution otherwise.
Second: Suppose n > 1. Then the n-digit numbers that sum to sum are:
0 followed by all the n-1 digit numbers that sum to sum
1 followed by all the n-1 digit numbers that sum to sum-1
2 followed by all the n-1 digit numbers that sum to sum-2
...
9 followed by all the n-1 digit numbers that sum to sum-9
Write an implementation that solves that problem, and then adapt it to solve your problem.
You can treat n-digit number as an array of n digits. Then you can increment a particular number to the next number that also adds up to the sum. Stepping through all the next answers, you have generated all possible combinations.
Using a generator to yield each n-digit combination as an IEnumerable<int> (in fact, an int[]), you start with the "smallest" n-digit combination that yields the sum, and go through each one.
IEnumerable<IEnumerable<int>> DigitsToSum(int n, int sum) {
if (sum > 9 * n)
yield return Enumerable.Empty<int>();
else {
var ans = new int[n];
void distribute(int wsum, int downto) {
for (var j1 = n - 1; j1 > downto; --j1) {
if (wsum > 9) {
ans[j1] = 9;
wsum -= 9;
}
else {
ans[j1] = wsum;
wsum = 0;
}
}
}
ans[0] = Math.Max(1, sum-9*(n-1));
distribute(sum-ans[0], 0);
bool nextAns() {
var wsum = ans[n-1];
for (var j1 = n - 2; j1 >= 0; --j1) {
wsum += ans[j1];
if (ans[j1] < Math.Min(9, wsum)) {
++ans[j1];
distribute(wsum - ans[j1], j1);
return true;
}
}
return false;
}
do {
yield return ans;
} while (nextAns());
}
}
This is tremendously faster than my recursive double generator solution (somewhat like #EricLippert's suggestion) to iterate over all possibilities (e.g. using Count()).
You can put the digits back together to get a final numeric string for each number:
var ans = DigitsToSum(n, sum).Select(p => String.Join("", p));

Efficient way to count the number of appearances of a digit in a number

I need to count the number of times a single digit (not 0) appears in a number (positive integer) of varying length.
The obvious solution is to convert the number to a string, the digit to a character and iterate over the string to count the number of times the character appears in the string.
static int CountDigitInString(string searchString, char digit)
{
int sum = 0;
for (int i = 0; i < searchString.Length; i++)
{
if (searchString[i] == digit)
sum++;
}
return sum;
}
The problem with this method, however, is that it is too slow for my purposes as I am running it many times.
public static void Run()
{
for (int i = 0; i < 1000000; i++)
{
CountDigitInString(i.ToString(), (char)j);
}
}
After I noted that the process took too much time, the CPU sampling profiler showed me that the problem was with the conversion to string.
So, how do I efficiently count the number of times a digit (single digit only, not a number) appears in a number (of any length)?
Here is more optimized version of #shaitibber solution. It replaces one division with multiplying and returns 1 for 0,0. It is about 20% faster.
static int CountDigitsInString2(int number, int digit)
{
int sum = 0;
do
{
int n2 = number / 10;
if (number - n2 * 10 == digit)
sum++;
number = n2;
} while (number != 0);
return sum;
}
And here is solution about three times faster than that (but does not work for 0 digit, which is not required). It precalculates results for numbers 0..9999.
private static int[][] cache = new int[10][];
private const int cacheSize = 10000;//or 100000
private static int[] initCache(int digit)
{
var ca = cache[digit] = new int[cacheSize];
for (int i = 0; i < ca.Length; ++i)
{
ca[i] = CountDigitsInString2(i, digit);
}
return ca;
}
static int CountDigitsInString3(int number, int digit)
{
var ca = cache[digit] ?? initCache(digit);
int sum = 0;
while (number != 0)
{
int n2 = number / cacheSize;
sum += ca[number - n2 * cacheSize];
number = n2;
};
return sum;
}
I found a way which turned out to be about 3 times as fast on average (checked using a Stopwatch):
static int CountDigitsInString(int number, int digit)
{
int sum = 0;
while (number != 0)
{
if (number % 10 == digit)
sum++;
number /= 10;
}
return sum;
}
EDIT:
I found a way which is over 4 times as fast as the one above. Before I start, note that this solution is valid only for cases in which you are counting appearances of a digit in consecutive numbers.
It occurred to me that if you counted the number of times the digit "d" appeared in a number "A", then you don't neccessarily have to recount the number of times "d" appears in "A + 1" to know what it is.
For example, if I know that the digit 3 appears 4 times in the number 35312336, I can know for a fact that it will still appear 4 times in the next consecutive number 35312337, without actually counting.
The reason I can do this is that the count would only change in one of three cases:
1) When the last digit of "A - 1" was a 9, "A" can change entirely due to numbers being carried over. This is the only case in which we actually have to count (although you could, theoretically, optimize this further by checking the numbers carried over to see if they affect the total but this strikes me as overly complicated).
2) When the last digit of "A - 1" was "d - 1", we know that the number of times "d" appears in "A" has increased by one.
3) When the last digit of "A - 1" was "d", we know that the number of times "d" appears in "A" has decreased by one.
This means that you only have to count the appearances of "d" in "A" using arithmetical operations in one out of 10 cases!
public static void Run()
{
int digit = 1;
int count = 0;
for (int i = 0; i < 100000; i++)
{
int previousLastDigit = (i - 1) % 10;
if (previousLastDigit == (digit - 1))
count++;
else if (previousLastDigit == 9)
count = CountDigitsInString(i, digit);
else if (previousLastDigit == digit)
count--;
Console.WriteLine(digit + " appears " + count + " times in the number " + i);
}
}
The CountDigitsInString function is the one above.
Here is a little snip with LINQ to give you another way to do it (didn't ran a stopwatch)
var number = 11334511;
var digit = 1;
var digitAsChar = Convert.ToChar(digit.ToString().ToLower());
// Occurence will be 4
var occurence = number.ToString().ToLower().Count(s => s == digitAsChar);
I suggest you use LINQ on string.
Source: https://msdn.microsoft.com/en-us/library/mt693025.aspx
static int CountDigitInString(string number, char digit)
{
int count = number.Count(ns => ns == digit);
return count;
}

What number is a specified digit and how many of them are there in a number?

Ok, so at first, I'm very beginner in programming. It's my school homework and I cannot use conversion to string. Just if,else,for,while.
On input there is the number and the digit.
I know how to get information what number is a specified digit in a number but I have no idea how to find out how many of these numbers are there.
Let's say I have number 123 467 (it has to be less than 999 999) and I want the third number. I know it's bigger than 100 000, so I do the math - (int) 123 467 / 100 = 123 and then 123%10 = 3. Now I need to know if there are any more 3's in the number - but here is the point - I'm not sure what cycle should I use.
And I also have to create some code which determines how large is the number (bigger than 100/1000/10000/...).
I'm not asking for a full solution but little help would be appreciated. Even in a pseudolanguage.
Current code (almost nothing):
double digit, number;
try
{
digit = Convert.ToInt32(poledigit.Text);
number = Convert.ToInt32(polenumber.Text);
}
catch
{
MessageBox.Show("Zadejte číslo ve správném formátu");
return;
}
if (digit > 6 & number > 999999)
{
MessageBox.Show("Číslo musí být menší než 999 999 a digit musí být menší než 6.");
return;
}
while(number >= 100000)
{
number /= Math.Pow(10, digit);
number %= 10;
}
I would create an int array counting the number of digits
int[] digitCount = new int[10]; // Range: digitCount[0..9]
Then determine the digits one by one by eliminating the last one, until the number is zero. The loop would repeat the following code:
int digit = number % 10;
number /= 10;
digitCount[digit]++;
Now digitCount contains the count of each digit
int countOfDigit3 = digitCount[3];
If you cannot use arrays, count only the occurences of the desired digit
int digit = ...;
int digitCount = 0;
while (number != 0) {
int d = number % 10;
number /= 10;
if (d == digit) {
digitCount++;
}
}
You can iterate through the digits as follows:
int digitToSearch = 3;
int count = 0;
while (number != 0)
{
int digit = number % 10;
if (digit == digitToSearch)
count++;
number /= 10;
}

Get the seventh digit from an integer

I have a integer of 10 digits. I need to get the 7th digit of that integer.
I have found a mathematical solution to get the first digit of an integer.
var myDigit = 2345346792;
var firstDigit = Math.Abs(myDigit);
while (firstDigit >= 10)
{
firstDigit /= 10;
}
How can I get the seventh digit from myDigit? I am trying to avoid casting to string and doing a substring. I would like to see the mathemathical version of getting the seventh digit.
Anyone?
var seventh_digit = ( myDigit/1000000 ) % 10;
int getSeventhDigit(int number)
{
while(number >= 10000000)
number /= 10;
return number % 10;
}
This will take the last digit of numbers with 7 or less digits.
For numbers with 8 or more digits, it will divide by 10 until the number is 7 digits long, then take the last digit.
Mathematical solution without while loops:
int myDigit = 2345346792;
var seventh = (myDigit / 1000000) % 10;
//result should be 5, your seventh digit from the right
More generally, you can create a (zero-based) array from the digits:
uint myDigit = 2345346792;
int[] digits = new int[10];
for (int i = 9; i >= 0; i--)
{
digits[i] = (int)(myDigit % 10);
myDigit /= 10;
}
That should be useful for whatever manipulation you wish to do.
var nthDigit = (int)((number / Math.Pow(10, nth - 1)) % 10);
Where nth is n-th digit of the number.
Assuming that the "zeroth digit" is the least significant digit, this should do you:
public static int nthDigit( int value , int n )
{
if ( n < 0 ) throw new ArgumentException();
if ( value < 0 ) throw new ArgumentException() ;
while ( n-- > 0 )
{
value /= 10 ;
}
int digit = value % 10 ;
return digit ;
}
Something like this (C code, but should be readily portable):
if (n < 1000000)
return 0; // no 7th digit
while (n > 9999999)
n /= 10; // now in the range [1,000,000..9,999,999]
return n % 10;
This may seem outdated, but I wanted to get specific digits from a string of numbers and most of these solutions (and others I found) were lacking. So...I decided a workaround and converted the number to a string and then pulled the characters of the string, converting them back to an int. I know this isn't very efficient, but for small projects I don't concern myself with efficiency.
For my task, I was specifically working with phone numbers, so here is my code:
long number = 5559876543;
string s = "" + number;
int areaCode = int.Parse(s.Substring(0, 3));
int prefix = int.Parse(s.Substring(3, 3));
int suffix = int.Parse(s.Substring(6, 4));
I hope this helps anyone looking for a similar solution.
public static int GetNthDigit(this int value, int digits)
{
double mult = Math.Pow(10.0, digits);
if (value >= mult)
{
while(value >= mult)
value /= 10;
return value % 10;
}
else
{
throw new ArgumentOutOfRangeException("Digits greater than value");
}
}

Categories

Resources