Split number into groups of 3 digits - c#

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

Related

function to returns the nearest element of array to an integer

I want to make a function that gives an array returns the nearest element to a number.
here is some examples:
int[] arr = new int[] {12, 48, 50, 100};
my_function(1, arr); // returns 12.
my_function(40, arr); // returns 48.
my_function(49, arr); // returns 50; in two element with equal distance, returns greater number
my_function(70, arr); // returns 50.
my_function(10005, arr); // returns 100.
Sorry, I have no idea about how to write this function.
private int GetNearest(int[] array,int number)
{
return array.OrderBy(x => Math.Abs((long)x - number)).FirstOrDefault();
}
If you want to be sure that the larger number is before smaller number when the absolute difference is the same, add .ThenByDescending(a => a) after OrderBy(x => Math.Abs((long)x - number))
private int GetNearest(int[] array,int number)
{
return array.OrderBy(x => Math.Abs((long)x - number)).ThenByDescending(a => a).FirstOrDefault();
}
A different way to get the result expected is to calculate the distance between the value passed and the array elements. Then get the element with the lowest 'distance' and find the matching index in the input array. You need Linq as well here.
int Nearest(int value, int[] arr)
{
var distances = arr.Select(x => Math.Abs(x - value)).ToList();
int min = distances.Min();
// Using LastIndexOf is important
// if you get two equal distances (I.E. 48/50 and passing 49)
return arr[distances.LastIndexOf(min)];
}
This is a solution without using System.Linq and with O(n) complexity. You just go through array in loop and find a number with minimal difference, abs <= diff condition allows you to return the latest number (50 for 49 instead of 48) in sorted array. If difference equals 0, it means that you find the exact number
var arr = new[] { 12, 48, 50, 100 };
int nearest = GetNearest(1, arr);
nearest = GetNearest(40, arr);
nearest = GetNearest(49, arr);
nearest = GetNearest(70, arr);
nearest = GetNearest(1005, arr);
int GetNearest(int number, int[] array)
{
int diff = int.MaxValue;
int result = 0;
foreach (var item in array)
{
var abs = Math.Abs(item - number);
if (abs == 0)
{
result = item;
break;
}
if (abs <= diff)
{
diff = abs;
result = item;
}
}
return result;
}
This works:
public static int my_function(int num, int[] arr)
{
var minDiff = Math.Abs(arr[0] - num);
var nearest = arr[0];
for (int i = 1; i < arr.Length; i++)
{
var diff = Math.Abs(arr[i] - num);
if (diff <= minDiff)
{
minDiff = diff;
nearest = arr[i];
}
}
return nearest;
}
If you know that the array is sorted then you can find the closest value like this in O(log n) time.
public int GetNearest(int value, int[] sortedArray)
{
var index = Array.BinarySearch(sortedArray, value);
// If we found a match then the closest is equal to the value.
if(index >= 0) return value;
// Otherwise it's the bitwise compliment to the index of the value just larger.
var largerIndex = ~index;
// If the index is the length of the array then all numbers are smaller,
//so take the last.
if(largerIndex == sortedArray.Length) return sortedArray[arr.Length - 1];
// If the index is 0 then all numbers are greater so take the first.
if(largerIndex == 0) return sortedArray[0];
// Now get the number that is just larger and just smaller and calculate the
// difference to each.
var larger = sortedArray[largerIndex];
var smaller = sortedArray[largerIndex - 1];
var largerDiff = larger - value;
var smallerDiff = value - smaller;
// If the diff to the smaller number is less then we take the smaller number
// otherwise the larger number is closer or the difference is the same in which
// case we take the larger number.
return smallerDiff < largerDiff ? smaller : larger;
}
I have approached it this way.
private static int nearest(int number, int[] numbers)
{
int min = numbers[0];
int max = numbers.OrderByDescending(a => a).FirstOrDefault();
if (number> max)
{
return max;
}
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i]<number && numbers[i+1]>number)
{
int lower = Math.Abs(numbers[i])-Math.Abs(number);
int upper = Math.Abs(numbers[i+1]) - Math.Abs(number);
if (Math.Abs(upper)>Math.Abs(lower))
{
return numbers[i];
}
else
{
return numbers[i+1];
}
}
}
return min;
}

count odd and even digits in a number

I try to write program that check the ratio between odd and even
digits in a given number. I've had some problems with this code:
static void Main(string[] args)
{
int countEven = 0 ;
int countOdd = 0 ;
Console.WriteLine("insert a number");
int num = int.Parse(Console.ReadLine());
int length = num.GetLength;
for (int i = 0;i<length ; i++)
{
if((num/10)%2) == 0)
int countEven++;
}
}
any ideas?
The problem is that int does not have a length, only the string representation of it has one.As an alternative to m.rogalski answer, you can treat the input as a string to get all the digits one by one. Once you have a digit, then parsing it to int and checking if it is even or odd is trivial.Would be something like this:
int countEven = 0;
int countOdd = 0;
Console.WriteLine("insert a number");
string inputString = Console.ReadLine();
for (int i = 0; i < inputString.Length; i++)
{
if ((int.Parse(inputString[i].ToString()) % 2) == 0)
countEven++;
else
countOdd++;
}
Linq approach
Console.WriteLine("insert a number");
string num = Console.ReadLine(); // check for valid number here?
int countEven = num.Select(x => x - '0').Count(x => x % 2 == 0);
int countOdd = num.Select(x => x - '0').Count(x => x % 2 != 0);
Let's assume your input is : 123456
Now all you have to do is to get the modulo from the division by ten : int m = num % 10;
After that just check if bool isEven = m % 2 == 0;
On the end you have to just divide your input number by 10 and repeat the whole process till the end of numbers.
int a = 123456, oddCounter = 0, evenCounter = 0;
do
{
int m = a % 10;
switch(m % 2)
{
case 0:
evenCounter++;
break;
default: // case 1:
oddCounter++;
break;
}
//bool isEven = m % 2 == 0;
}while( ( a /= 10 ) != 0 );
Online example
Made a small change to your code and it works perfectly
int countEven = 0;
int countOdd = 0;
Console.WriteLine( "insert a number" );
char[] nums = Console.ReadLine().ToCharArray();
for ( int i = 0; i < nums.Length; i++ )
{
if ( int.Parse( nums[i].ToString() ) % 2 == 0 )
{
countEven++;
}
else
{
countOdd++;
}
}
Console.WriteLine($"{countEven} even numbers \n{countOdd} odd numbers");
Console.ReadKey();
What I do is get each number as a a character in an array char[] and I loop through this array and check if its even or not.
If the Input number is a 32-bit integer (user pick the length of the number)
if asked:
The number of even digits in the input number
Product of odd digits in the input number
The sum of all digits of the input number
private void button1_Click(object sender, EventArgs e) {
int num = ConvertToInt32(textBox1.Text);
int len_num = textBox1.Text.Length;
int[] arn = new int[len_num];
int cEv = 0; pOd = 0; s = 0;
for (int i = len_num-1; i >= 0; i--) { // loop until integer length is got down to 1
arn[i] = broj % 10; //using the mod we put the last digit into a declared array
if (arn[i] % 2 == 0) { // then check, is current digit even or odd
cEv++; // count even digits
} else { // or odd
if (pOd == 0) pOd++; // avoid product with zero
pOd *= arn [i]; // and multiply odd digits
}
num /= 10; // we divide by 10 until it's length is get to 1(len_num-1)
s += arn [i]; // sum of all digits
}
// and at last showing it in labels...
label2.Text = "a) The even digits count is: " + Convert.ToString(cEv);
label3.Text = "b) The product of odd digits is: " + Convert.ToString(pOd);
label4.Text = "c) The sum of all digits in this number is: " + Convert.ToString(s);
}
All we need in the interface is the textbox for entering the number, the button for the tasks, and labels to show obtained results. Of course, we have the same result if we use a classic form for the for loop like for (int i = 0; and <= len_num-1; i++) - because the essence is to count the even or odd digits rather than the sequence of the digits entry into the array
static void Main(string args[]) {
WriteLine("Please enter a number...");
var num = ReadLine();
// Check if input is a number
if (!long.TryParse(num, out _)) {
WriteLine("NaN!");
return;
}
var evenChars = 0;
var oddChars = 0;
// Convert string to char array, rid of any non-numeric characters (e.g.: -)
num.ToCharArray().Where(c => char.IsDigit(c)).ToList().ForEach(c => {
byte.TryParse(c.ToString(), out var b);
if (b % 2 == 0)
evenChars++;
else
oddChars++;
});
// Continue with code
}
EDIT:
You could also do this with a helper (local) function within the method body:
static void Main(string args[]) {
WriteLine("Please enter a number...");
var num = ReadLine();
// Check if input is a number
if (!long.TryParse(num, out _)) {
WriteLine("NaN!");
return;
}
var evenChars = 0;
var oddChars = 0;
// Convert string to char array, rid of any non-numeric characters (e.g.: -)
num.ToCharArray().Where(c => char.IsDigit(c)).ToList().ForEach(c => {
byte.TryParse(c.ToString(), out var b);
if (b % 2 == 0)
evenChars++;
else
oddChars++;
// Alternative method:
IsEven(b) ? evenChars++ : oddChars++;
});
// Continue with code
bool IsEven(byte b) => b % 2 == 0;
}
Why am I using a byte?
Dealing with numbers, it is ideal to use datatypes that don't take up as much RAM.
Granted, not as much an issue nowadays with multiple 100s of gigabytes possible, however, it is something not to be neglected.
An integer takes up 32 bits (4 bytes) of RAM, whereas a byte takes up a single byte (8 bits).
Imagine you're processing 1 mio. single-digit numbers, and assigning them each to integers. You're using 4 MiB of RAM, whereas the byte would only use up 1 MiB for 1 mio. numbers.
And seeming as a single-digit number (as is used in this case) can only go up to 9 (0-9), you're wasting a potential of 28 bits of memory (2^28) - whereas a byte can only go up to 255 (0-255), you're only wasting a measly four bits (2^4) of memory.

Pass in a long number and return an array of all the digits and the count of each digit

For instance, if the input is set to 1234, the program will return 11213141 because digit 1 occurs once, digit 2 occurs once ... so on and so forth.
Another example: 142225 => 11234151
My program works fine with small input but if the input has 10 digits or more, the result would make no sense. Please help.
class Example
{
// Get sorted(ascending) list for each digit in num
public static List<int> GetList(long num)
{
List<int> listOfInts = new List<int>();
while (num > 0)
{
int remainder = (int) num % 10;
listOfInts.Add(remainder);
num = num / 10;
}
listOfInts.Sort();
return listOfInts;
}
// Get minimum digit in the list
public static int getMinimumInt(List<int> l)
{
int min = 10;
foreach (int s in l)
{
if (s <= min)
{
min = s;
}
}
return min;
}
// Get count of the minimum digit specified
public static int getCount(int i,List<int> l)
{
int count = 0;
foreach (int s in l)
{
if (s == i)
{
count++;
}
}
return count;
}
public static void Main()
{
long input = 1234567891020; // Arbituary input
// initialize
List<int> outputList=new List<int>(); // List that would be eventually outputted
List<int> listOfInt = new List<int>();
listOfInt = GetList(input);
//Loop end till no element left in listOfInt
while ((listOfInt.ToArray()).Length!=0)
{
int item = getMinimumInt(listOfInt);
int count = getCount(item, listOfInt);
outputList.Add(item); // Add the item to be counted
outputList.Add(count); // Add count of the item
listOfInt.RemoveRange(0, count); // Remove digits that have been counted
}
// Output the list
foreach (int i in outputList)
{
Console.Write(i);
}
Console.WriteLine();
Console.ReadLine();
}
}
}
In your GetList() function, you are casting your 10+ digit long to an integer:
int remainder = (int) num % 10;
Attempting to place a 10+ digit number into an int means you are running up against the highest value of 32-bit integers, which is 2,147,483,647. That would explain why your results seem strange.
Use a long instead. If that isn't enough you can try System.Numerics.BigInteger, which will allow you to add more digits to it until you run out of memory.
You can use this LINQ approach, it doesn't care about numbers, just chars:
string output = String.Concat(input
.GroupBy(c => c)
.Select(g => String.Format("{0}{1}", g.Key, g.Count())));
If you want the result as long use long.TryParse(output, out longvariable).
int sourceVal = 12341231;
string sourceStr = sourceVal.ToString();
List<char> uniqueChars = null;
#if LINQ
uniqueChars = sourceStr.ToCharArray().Distinct().ToList();
#else
uniqueChars = new List<char>();
foreach (char c in sourceStr)
if (!uniqueChars.Contains(c))
uniqueChars.Add(c);
#endif
string result = "";
foreach (var wantedChar in uniqueChars)
#if LINQ
result += wantedChar.ToString() + (sourceStr.Count(f => f == wantedChar)).ToString();
#else
result += wantedChar.ToString() + (sourceStr.Split(wantedChar).Length - 1).ToString();
#endif
Console.WriteLine("Result = " + result);
This was my code to keep it as similar to yours. If you want to limit the count, use a modulus on the end (% 10) to keep the count to a single digit.
Having now seen the other Linq answer, I think that is a lot neater. Given that your maximum answer would be something like 192,939,495,969,798,999 if sorted in character order ascending, you would need a long not an int to store that.
Just change
int remainder = (int) num % 10;
to
int remainder = (int)(num % 10);
The first one is casting num to int then doing the mod 10. This will result in overflow when num is larger than int.MaxValue, typically a negative number. The second does the mod 10 first then the cast, which is safe as the mod will result in a value that can easily fit into an int.

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

need a better way add leading digits to int and return array of digits

I need to create a modulus check which adds leading digits, lets say 0, to a seed int. I then need to return an array of digits in the array as I need to do a calculation on each digit to return a new whole number.
my code is as follows,
var seed = 1234;
var seedString = seed.ToString();
var test = new List<int>();
for(int i = 0; i < 10 - seedString.Length; i++)
{
test.Add(0);
}
var value = seed;
for(int i = 0; i < seedString.Length; i ++)
{
test.Insert(10 - seedString.Length, value % 10);
value = value / 10;
}
is there an easier way of doing this?
If you want to convert your number to a 10-digit string, you can format the number using a Custom Numeric Format String as follows:
string result = seed.ToString("0000000000");
// result == "0000001234"
See: The "0" Custom Specifier
If you need a 10-element array consisting of the individual digits, try this:
int[] result = new int[10];
for (int value = seed, i = result.Length; value != 0; value /= 10)
{
result[--i] = value % 10;
}
// result == new int[] { 0, 0, 0, 0, 0, 0, 1, 2, 3, 4 }
See also: Fastest way to separate the digits of an int into an array in .NET?
Try this:
int myNumber = 1234;
string myStringNumber = myNumber.ToString().PadLeft(10, '0');
HTH
Another shorthand way of getting the string representation would be
int num = 1234;
num.ToString("D10");

Categories

Resources