Is there any better way to find the digit multiplication and summation? - c#

int N = 2345;
var digitArray = N.ToString().ToCharArray();
int multiplicationSum = 1;
foreach (char digit in digitArray)
{
multiplicationSum = int.Parse(digit.ToString()) * multiplicationSum;
}
var sum = 0;
var sumArray = multiplicationSum.ToString().ToCharArray();
foreach (char digit in sumArray)
{
sum = int.Parse(digit.ToString()) + sum;
}
Thanks

Assuming you don't need to deal with negative numbers, it seems doing it mathematically would make a lot more sense
int N = 2345;
int multiplicationSum = 1;
while(N!=0)
{
multiplicationSum = multiplicationSum * (N%10);
N = N/10;
}
var sum = 0;
while(multiplicationSum!=0)
{
sum = sum + (multiplicationSum%10);
multiplicationSum = multiplicationSum/10;
}
References:
% operator
The % operator computes the remainder after dividing its first operand by its second
/ operator:
When you divide two integers, the result is always an integer. For example, the result of 7 / 3 is 2

Related

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));

Why aren't 10 and 100 considered Kaprekar numbers?

I'm trying to do the Modified Kaprekar Numbers problem (https://www.hackerrank.com/challenges/kaprekar-numbers) which describes a Kaprekar number by
Here's an explanation from Wikipedia about the ORIGINAL Kaprekar
Number (spot the difference!): In mathematics, a Kaprekar number for a
given base is a non-negative integer, the representation of whose
square in that base can be split into two parts that add up to the
original number again. For instance, 45 is a Kaprekar number, because
45² = 2025 and 20+25 = 45.
and what I don't understand is why 10 and 100 aren't Kaprekar numbers.
10^2 = 1000 and 10 + 00 = 10
Right?
So my solution
// Returns the number represented by the digits
// in the range arr[i], arr[i + 1], ..., arr[j - 1].
// If there are no elements in range, return 0.
static int NumberInRange(int[] arr, int i, int j)
{
int result = 0;
for(; i < j; ++i)
{
result *= 10;
result += arr[i];
}
return result;
}
// Returns true or false depending on whether k
// is a Kaprekar number.
// Example: IsKaprekar(45) = true because 45^2=2025 and 20+25=45
// Example: IsKaprekar(9) = false because the set of the split
// digits of 7^2=49 are {49,0},{4,9} and
// neither of 49+0 or 4+9 equal 7.
static bool IsKaprekar(int k)
{
int square = k * k;
int[] digits = square.ToString().Select(c => (int)Char.GetNumericValue(c)).ToArray();
for(int i = 0; i < digits.Length; ++i)
{
int right = NumberInRange(digits, 0, i);
int left = NumberInRange(digits, i, digits.Length);
if((right + left) == k)
return true;
}
return false;
}
is saying all the Kaprekar numbers between 1 and 100 are
1 9 10 45 55 99 100
whereas the "right" answer is
1 9 45 55 99
In 100+00 the right is 00, which is wrong because in a kaprekar number the right may start with zero (ex: 025) but cannot be entirely 0.
Therefore you can put a condition in the loop that
if(right==0)
return false;
The reason is because 10 x 10 = 100. Then you substring the right part with a length equals d = 2, that is digit count of original value (10), then the left part would be 1.
So l = 1 and r = 00, l + r = 1, that is not equals to 10.
The same for 100. 100 x 100 = 10000. l = 10, r = 000, so l + r = 10 not equal 100.
Here is my solution in JAVA.
static void kaprekarNumbers(int p, int q) {
long[] result = IntStream.rangeClosed(p, q).mapToLong(Long::valueOf)
.filter(v -> {
int d = String.valueOf(v).length();
Long sq = v * v;
String sqSt = sq.toString();
if (sqSt.length() > 1) {
long r = Long.parseLong(sqSt.substring(sqSt.length() - d));
long l = Long.parseLong(sqSt.substring(0, sqSt.length() - d));
return r + l == v;
} else return v == 1;
}).toArray();
if (result.length > 0) {
for (long l : result) {
System.out.print(l + " ");
}
} else {
System.out.println("INVALID RANGE");
}
}
How about something like this.
static bool IsKaprekar(int k)
{
int t;
for (int digits = new String(k).length(); digits > 0; digits--, t *= 10);
long sq = k * k;
long first = sq / t;
long second = sq % t;
return k == first + second;
}
find a number to divide and mod the square with in order to split it. This number should be a factor of 10 based on the number of digits in the original number.
calculate the square.
split the square.
compare the original to the sum of the splits.

median c# wrong calculate

I have problem with the calculation of the median when I put 1,2, 3 my median is = 44 i don't know why
double wynik = 0;
string x1 = textBox1.Text;
string[] tab = x1.Split(',');
int n = tab.Length;
Array.Sort(tab);
if (n % 2 == 0)
{
double c = x1[(n / 2) -1];
double v = x1[(n / 2)];
wynik = (c + v) / 2;
}
else
wynik = x1[n / 2];
textBox2.Text = wynik.ToString();
That is because 44 is the ASCII value of ,. And in your string, using your current method now, the median is the comma character , value = 44
To get the median, consider of splitting the string by , and then convert each value to numeric data (like int) and then sort it and simply get the middle value among the sorted data..
double wynik = 0;
string x1 = textBox1.Text;
int[] tab = x1.Split(',').Select(x => Convert.ToInt32(x)).ToArray(); //this is the trick
int n = tab.Length;
Array.Sort(tab);
int median = tab[n/2]; //here is your median
Your problem is that you are calculating with characters instead of number.
So let's say your textBox1.Text is "1,2,3". Then x1[(n/2)-1] would point at the character '1', which has the double value of 48 or something.
You need to parse the strings into int using int.Parse:
int[] tab = x1.Split(',').Select(s => int.Parse(s)).ToArray();
And then use these values instead the string again:
if (n % 2 == 0)
{
double c = tab[(n / 2) -1]; // tab instead of x1!
double v = tab[(n / 2)]; // tab instead of x1!
wynik = (c + v) / 2;
}
else
wynik = tab[n / 2]; // tab instead of x1
static void Main(string[] args)
{
Console.WriteLine("Define Array Size");
int size = Convert.ToInt32(Console.ReadLine());
float reference = 0;
int[] newArray = new int[size];
for (int i = 0; i < newArray.Length; i++)
{
newArray[i] = Convert.ToInt32(Console.ReadLine());
reference = reference + newArray[i];
}
float Median = reference / newArray.Length;
Console.WriteLine("The Median is ="+Median);
}

Split number into groups of 3 digits

I want to make a method that takes a variable of type int or long and returns an array of ints or longs, with each array item being a group of 3 digits. For example:
int[] i = splitNumber(100000);
// Outputs { 100, 000 }
int[] j = splitNumber(12345);
// Outputs { 12, 345 }
int[] k = splitNumber(12345678);
// Outputs { 12, 345, 678 }
// Et cetera
I know how to get the last n digits of a number using the modulo operator, but I have no idea how to get the first n digits, which is the only way to make this method that I can think of. Help please!
Without converting to string:
int[] splitNumber(int value)
{
Stack<int> q = new Stack<int>();
do
{
q.Push(value%1000);
value /= 1000;
} while (value>0);
return q.ToArray();
}
This is simple integer arithmetic; first take the modulo to get the right-most decimals, then divide to throw away the decimals you already added. I used the Stack to avoid reversing a list.
Edit: Using log to get the length was suggested in the comments. It could make for slightly shorter code, but in my opinion it is not better code, because the intent is less clear when reading it. Also, it might be less performant due to the extra Math function calls. Anyways; here it is:
int[] splitNumber(int value)
{
int length = (int) (1 + Math.Log(value, 1000));
var result = from n in Enumerable.Range(1,length)
select ((int)(value / Math.Pow(1000,length-n))) % 1000;
return result.ToArray();
}
By converting into a string and then into int array
int number = 1000000;
string parts = number.ToString("N0", new NumberFormatInfo()
{
NumberGroupSizes = new[] { 3 },
NumberGroupSeparator = "."
});
By using Maths,
public static int[] splitNumberIntoGroupOfDigits(int number)
{
var numberOfDigits = Math.Floor(Math.Log10(number) + 1); // compute number of digits
var intArray = new int[Convert.ToInt32(numberOfDigits / 3)]; // we know the size of array
var lastIndex = intArray.Length -1; // start filling array from the end
while (number != 0)
{
var lastSet = number % 1000;
number = number / 1000;
if (lastSet == 0)
{
intArray[lastIndex] = 0; // set of zeros
--lastIndex;
}
else if (number == 0)
{
intArray[lastIndex] = lastSet; // this could be your last set
--lastIndex;
}
else
{
intArray[lastIndex] = lastSet;
--lastIndex;
}
}
return intArray;
}
Try converting it to string first and do the parsing then convert it back to number again
Convert to string
Get length
If length modulus 3 == 0
String substring it into ints every 3
else if
Find remainder such as one or two left over
Substring remainder off of front of string
Then substring by 3 for the rest
You can first find out how large the number is, then use division to get the first digits, and modulo to keep the rest:
int number = 12345678;
int len = 1;
int div = 1;
while (number >= div * 1000) {
len++;
div *= 1000;
}
int[] result = new int[len];
for (int i = 0; i < result.Length; i++) {
result[i] = number / div;
number %= div;
div /= 1000;
}
You can use this with the System.Linq namespace from .NET 3.5 and above:
int[] splitNumber(long value)
{
LinkedList<int> results = new LinkedList<int>();
do
{
int current = (int) (value % 1000);
results.AddFirst(current);
value /= 1000;
} while (value > 0);
return results.ToArray();// Extension method
}
I use LinkedList<int> to avoid having to Reverse a list before returning. You could also use Stack<int> for the same purpose, which would only require .NET 2.0:
int[] splitNumber(long value)
{
Stack<int> results = new Stack<int>();
do
{
int current = (int) (value % 1000);
results.Push(current);
value /= 1000;
} while (value > 0);
return results.ToArray();
}

How to convert string into int array in C#

I am making a credit card validator program in which I am asking for a string which is going to be a 16 digit number (credit card #) and I want to convert that into an int array. How do I do that? I need to then multiply every other digit starting from the first digit by 2.
char[] creditNumbers = creditCardNumber.ToCharArray();
creditNumbers[0] = (char)((int)(creditNumbers[0] * 2));
creditNumbers[2] = (char)((int)(creditNumbers[2] * 2));
creditNumbers[4] = (char)((int)(creditNumbers[4] * 2));
creditNumbers[6] = (char)((int)(creditNumbers[6] * 2));
creditNumbers[8] = (char)((int)(creditNumbers[8] * 2));
This is what I made so far but my casting is not done properly. How do I fix the problem?
To just get the int array, I would do this:
creditCardNumber.Select(c => int.Parse(c.ToString())).ToArray()
To check the number using the Luhn algorithm, you could do this:
bool IsValid(string creditCardNumber)
{
var sum = creditCardNumber.Reverse()
.Select(TransformDigit)
.Sum();
return sum % 10 == 0;
}
int TransformDigit(char digitChar, int position)
{
int digit = int.Parse(digitChar.ToString());
if (position % 2 == 1)
digit *= 2;
return digit % 10 + digit / 10;
}
var intArray = creditCardNumber.ToCharArray().Select(o => int.Parse(o.ToString())).ToArray();
var result = new List<int>();
for(int i=0; i<intArray.Length; i++){
if((i % 2) == 0)
result.Add(intArray[i] * 2);
else
result.Add(intArray[i]);
}
Console.Write(string.Concat(result.Select(o => o.ToString())));

Categories

Resources