Can you replace ints in int Arrays? - c#

I'm looking for a way to replace every int that is greater than 9 in an array with the sum of the digits. I'm gonna demonstrate an example below.
I have this array:
int[] ints2 = new int[] { ints[0] * 2, ints[1], ints[2] * 2, ints[3], ints[4] * 2, ints[5], ints[6] * 2, ints[7], ints[8] * 2, ints[9]};
And I want to replace the first int to whatever the sum is of the two digits.
Lets say ints[0] = 9. And ints[0]*2 = 18. The sum should be 1+8 = 9.
Can I use some kind of replace method for ints? Or do you guys have any better ideas of how to deal with this issue?
I tried it like this, but obviously I'm wrong:
foreach (int number in ints)
{
int newNumberInt;
if (number > 9)
{
string newNum = number.ToString();
char[] charNum = newNum.ToCharArray();
int[] intNum = Array.ConvertAll(charNum, n => (int)Char.GetNumericValue(n));
newNumberInt = intNum[0] + intNum[1];
}
newNumberInt = number;
}

You are close. Your mistakes are an incorrect addition of digits, and failure to replace the values in the array. Here is a one line method that adds all the digits in an integer (using System.Linq):
//Adds up all the digits in a number
private static int AddDigits(int number) => number.ToString().Sum(digitCharacter => int.Parse(digitCharacter.ToString()));
For replacing the values, a foreach loop directly on the array won't work, due to changing the contents of the array during enumeration. A simple solution is to use a for loop.
for (int i = 0; i < ints.Length; i++)
{
var value = ints[i];
ints[i] = value > 9 ? AddDigits(value) : value;
}
Note: the AddDigits function I wrote only works for positive integers

Related

Creating a C# program that calculates sum of the individual digits of a given number

So for practice, I decided to attempt to create a C# program, that calculates the sum of the individual digits of a given (e.g. If I were to input the number 123, the sum should be 6, because 1 + 2 + 3..)
My thought process is that I would use a for loop to iterate through a specific number (I'd have to convert the number first to a string though), add each individual number into a list, and then find the sum of that list, in order to get my answer. However, when I do so, as demonstrated by the code below:
static void Main(string[] args)
{
int num;
int sumOfNum = 0;
List<int> numbersToAdd = new List<int>();
Console.WriteLine("insert number: ");
num = Convert.ToInt32(Console.ReadLine());
string myNum = num.ToString();
for (int i = 0; i < myNum.Length; i++)
{
numbersToAdd.Add(myNum[i]);
}
foreach (int n in numbersToAdd)
{
sumOfNum = numbersToAdd.Sum();
}
Console.WriteLine("the sum is " + sumOfNum);
}
Instead of the output is 6, my output instead is 150. I thought it was weird, so when I decided to iterate through my list, so I can see my values, as shown below:
foreach (int n in numbersToAdd)
{
Console.WriteLine(n);
}
Instead of getting the values 1, 2, and 3, I instead get 49, 50, 51.
Why is that? Is it because of the fact that I'm sending in an index of a string, instead of an actual int? And if so, how can I fix it?
myNum is a string, this means that myNum[i] will return a character and not an int. However, the char is implicitly converted to an int in your case, but you still get the ASCII-value of the character.
In your case, these characters happen to be '1', '2' and '3', which have an ASCII-value of 49, 50 and 51 respectively. To see other ASCII values, search the Internet for 'ASCII table'.
To fix your code, you must convert those ASCII-values back to their decimal value by subtracting the value of the '0'-character:
numbersToAdd.Add(myNum[i] - '0');
Apart from that, you don't have to convert the number to a string, you can use modulus 10 to get the right-most digit: num % 10 and then divide num with 10 to advance to the next digit: num /= 10;. Do this in a loop for as long num differs from zero.
while (num > 0)
{
sumOfNum += num % 10;
num /= 10;
}

Access digits from integer value

I have an int variable (value1).
Int value1 =95478;
I want to take each digit of value1 and insert them into an array (array1). Like this,
int[] array1 = { 9, 5, 4, 7, 8 };
No idea how this can be done. Any idea?
int[] array1 = 95478.ToString()
.Select(x => int.Parse(x.ToString()))
.ToArray();
try this
Int value1 =95478;
List<int> listInts = new List<int>();
while(value1 > 0)
{
listInts.Add(value1 % 10);
value1 = value1 / 10;
}
listInts.Reverse();
var result= listInts .ToArray();
this doesn't use strings
The most optimal solution I could come up with:
public static class Extensions {
public static int[] SplitByDigits(this int value) {
value = Math.Abs(value); // undefined behaviour for negative values, lets just skip them
// Initialize array of correct length
var intArr = new int[(int)Math.Log10(value) + 1];
for (int p = intArr.Length - 1; p >= 0; p--)
{
// Fill the array backwards with "last" digit
intArr[p] = value % 10;
// Go to "next" digit
value /= 10;
}
return intArr;
}
}
Is roughly double the speed of using a List<int> and reversing, roughly ten times faster and a tonne more memory efficient than using strings.
Just because you have a powerful computer you are not allowed to write bad code :)

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

C# : Split a sequence of numbers after given parameter length

I have a number something like this :
12345668788451223356456898941220036696897894
Now, the question is how can I split the number after each 8 digits.That is,
I need the output as :
12345668
78845122 and so on up to the end of the number.
If I convert it to string, I don't have a method so that I could split it only with length parameter.
Thanks in advance for answering.
String approach
If I convert it to string, I don't have a method so that I could split it only with length parameter.
Well you have Substring, don't you? You could use LINQ:
var numbers = Enumerable.Range(0, bigNumber.Length / 8)
.Select(x => bigNumber.Substring(x * 8, 8)
.ToList();
or a straight loop:
var numbers = new List<string>();
for (int i = 0; i < bigNumber.Length / 8; i++)
{
numbers.Add(bigNumber.Substring(i * 8, 8);
}
If you need to end up with a List<int> instead, just add a call to int.Parse in there.
(You should check that the input string length is a multiple of 8 first.)
BigInteger approach
It's not clear what form you have this number in to start with. If it's a BigInteger, you could keep using DivRem:
BigInteger value = ...;
List<BigInteger> results = new List<BigInteger>();
BigInteger divisor = 100000000L;
for (int i = 0; i < count; i++)
{
BigInteger tmp;
value = BigInteger.DivRem(value, divisor, out tmp);
results.Add(tmp);
}
Note that I'm using count here rather than just looping until value is 0, in case you have lots of leading 0s. You need to know how many numbers you're trying to extract :)
Use this regex to split after each 8 digits,
\d{1,8}
OR
(\d{1,8})
Output:
12345668
78845122
33564568
98941220
03669689
7894
Have you tried using
string string.substring(int startIndex,int length)
In you case, you can write a loop to extract the 8 digits from the string till all the numbers are extracted
string sDigits = "12345668788451223356456898941220036696897894";
int iArrLen = sDigits.length / 8;
string[] sArrDigitList = new string[iArrLen];
for(int i=0; i < sDigits.length; i++)
{
sArrDigitList[i] = sDigits.substring(0, 8);
sDigits = sDigits.substring(sDigits.length-8);
}

Random occurrences

I am not quite sure how to go about this.
I need to generate 14,296 random numbers with different levels of probability.
so for example I need an array containing the numbers 18, 1, and 17. Each number has a different percent probability of occuring. So:
55% = 18
(7,862.8 times)
30% = 1
(4,288.8 times)
15% = 17
(2,144.4 times)
the result would be something like new Array () { 18, 18, 1, 17, 1, 18...}
If you'll always have the values as integer percentages, I'd fill a 100-element array with values according to the probability, so in this case your array would have 55 occurrences of 18, 30 occurrences of 1, and 15 occurrences of 17. Then you just need to pick 14,296 random values from that array. (i.e. pick an integer in the range [0, 100) and take that element.)
For different ways of expressing the probabilities, there are different approaches, of course. But if you're given integer percentages, this is an easily-understood option. (Another way is to scale all of the probabilities by the total, i.e. into a range of [0, 1), and then take a random double in that range.)
Divide the range of random generator into proportional segments, and, judging to which segment the next random number has fallen into, select the corresponding number from your set.
Something like (simplified):
const int numbers[3] = { 1, 17, 18 };
const int borders[2] = { 0.30*MAX_RANDOM, (0.30 + 0.15) * MAX_RANDOM };
int i = random.next(), num;
if (i < borders[0]) num = number[0];
else if (i < borders[0]) num = number[1];
else num = number[2];
Of course, if there's more numbers than three, it's better to use a loop.
Note: unlike Jon Skeet's solution, this one can provide any desired granularity up to 1/(MAX_RANDOM+1) (which is often up to 2^32 on 32-bit machines), rather than strictly 1%.
Random r = new Random();
// for each number to generate
int nextNumber;
double probability = r.NextDouble();
if (probability < 55.0 / 100.0)
nextNumber = 18;
else if (probability < (55.0 + 30.0) / 100.0)
nextNumber = 1;
else
nextNumber = 17;
How about something like this (untested):
struct np
{
int n;
int p;
}
Create a List<np> and will it with value/percentage pairs (e.g. n = 18, p = 55).
Then just do the following to pick a number:
List<np> npl = new List<np>();
// (fill the list here)
int r = rnd.next(total_of_all_p_values); // get random number
int res = 0; // result
for(int i = 0; i < npl.Length(); r -= npl[i++].n)
{
if(r < npl[i].p) // remaining vlaue is smaller than current percentage
{
res = npl[i].n;
break;
}
}
You could populate a List<T> with the appropriate number of each of the 3 numbers, and then randomize the List.

Categories

Resources