How to subtract x from every number in a listbox - c#

So I have a list box of numbers and I want to subtract an integer from every single number of a list box. Here is an example:
1
2
3
4
5
I want to get the absolute value of the difference
Math.Abs(2 - 1)
Math.Abs(2 - 2)
Math.Abs(2 - 3)
Math.Abs(2 - 4)
Math.Abs(2 - 5)
And put them in a list box.
I've tried:
while (i < listBox1.Items.Count)
{
result -= Convert.ToInt32(listBox1.Items[i++]);
int result1 = Convert.ToInt32(result)
int sub = Math.abs(result1)
}

Would this work :
I am using Select(x => {return x;}) notation of linq to do an operation on the array element, and return a value. In this case, the operation is Math.abs of each element of the array and a given number. _absDiffs will be an IEnumerable<int>, which you could call .ToArray() on to turn it into int[].
int[] _nums = {1,2,3,4,5};
int _number = 2;
var _absDiffs = _nums.Select(num=> { return Math.abs(_number - num);});

Related

Why multiply Random.Next() by a Constant?

I recently read an article explaining how to generate a weighted random number, and there's a piece of the code that I don't understand:
int r = ((int)(rand.Next() * (323567)) % prefix[n - 1]) + 1;
Why is rand.Next being multiplied by a constant 323567? Would the code work without this constant?
Below is the full code for reference, and you can find the full article here: https://www.geeksforgeeks.org/random-number-generator-in-arbitrary-probability-distribution-fashion/
Any help is appreciated, thank you!!
// C# program to generate random numbers
// according to given frequency distribution
using System;
class GFG{
// Utility function to find ceiling
// of r in arr[l..h]
static int findCeil(int[] arr, int r,
int l, int h)
{
int mid;
while (l < h)
{
// Same as mid = (l+h)/2
mid = l + ((h - l) >> 1);
if (r > arr[mid])
l = mid + 1;
else
h = mid;
}
return (arr[l] >= r) ? l : -1;
}
// The main function that returns a random number
// from arr[] according to distribution array
// defined by freq[]. n is size of arrays.
static int myRand(int[] arr, int[] freq, int n)
{
// Create and fill prefix array
int[] prefix = new int[n];
int i;
prefix[0] = freq[0];
for(i = 1; i < n; ++i)
prefix[i] = prefix[i - 1] + freq[i];
// prefix[n-1] is sum of all frequencies.
// Generate a random number with
// value from 1 to this sum
Random rand = new Random();
int r = ((int)(rand.Next() * (323567)) % prefix[n - 1]) + 1; // <--- RNG * Constant
// Find index of ceiling of r in prefix array
int indexc = findCeil(prefix, r, 0, n - 1);
return arr[indexc];
}
// Driver Code
static void Main()
{
int[] arr = { 1, 2, 3, 4 };
int[] freq = { 10, 5, 20, 100 };
int i, n = arr.Length;
// Let us generate 10 random numbers
// according to given distribution
for(i = 0; i < 5; i++)
Console.WriteLine(myRand(arr, freq, n));
}
}
UPDATE:
I ran this code to check it:
int[] intArray = new int[] { 1, 2, 3, 4, 5 };
int[] weights = new int[] { 5, 20, 20, 40, 15 };
List<int> results = new List<int>();
for (int i = 0; i < 100000; i++)
{
results.Add(WeightedRNG.GetRand(intArray, weights, intArray.Length));
}
for (int i = 0; i < intArray.Length; i++)
{
int itemsFound = results.Where(x => x == intArray[i]).Count();
Console.WriteLine($"{intArray[i]} was returned {itemsFound} times.");
}
And here are the results with the constant:
1 was returned 5096 times.
2 was returned 19902 times.
3 was returned 20086 times.
4 was returned 40012 times.
5 was returned 14904 times.
And without the constant...
1 was returned 100000 times.
2 was returned 0 times.
3 was returned 0 times.
4 was returned 0 times.
5 was returned 0 times.
It completely breaks without it.
The constant does serve a purpose in some environments, but I don't believe this code is correct for C#.
To explain, let's look at the arguments to the function. The first sign something is off is passing n as an argument instead of inferring it from the arrays. The second sign is it's poor practice in C# to deal with paired arrays rather than something like a 2D array or sequence of single objects (such as a Tuple). But those are just indicators something is odd, and not evidence of any bugs.
So let's put that on hold for a moment and explain why a constant might matter by looking a small example.
Say you have three numbers (1, 2, and 3) with weights 3, 2, and 2. This function first builds up a prefix array, where each item includes the chances of finding the number for that index and all previous numbers.
We end up with a result like this: (3, 5, 7). Now we can use the last value and take a random number from 1 to 7. Values 1-3 result in 1, values 4 and 5 result in 2, and values 6 and 7 result in 3.
To find this random number the code now calls rand.Next(), and this is where I think the error comes in. In many platforms, the Next() function returns a double between 0 and 1. That's too small to use to lookup your weighted value, so you then multiply by a prime constant related the platform's epsilon value to ensure you have a reasonably large result that will cover the entire possible range of desired weights (in this case, 1-7) and then some. Now you take the remainder (%) vs your max weight (7), and map it via the prefix array to get the final result.
So the first error is, in C#, .Next() does not return a double. It is documented to return a non-negative random integer between 0 and int.MaxValue. Multiply that by 323567 and you're asking for integer overflow exceptions. Another sign of this mistake is the cast to int: the result of this function is already an int. And let's not even talk the meaningless extra parentheses around (323567).
There is also another, more subtle, error.
Let's the say the result of the (int)(rand.Next() * 323567) expression is 10. Now we take this value and get the remainder when dividing by our max value (%7). The problem here is we have two chances to roll a 1, 2, or 3 (the extra chance is if the original was 8, 9, or 10), and only once chance for the remaining weights (4-7). So we have introduced unintended bias into the system, completely throwing off the expected weights. (This is a simplification. The actual number space is not 1-10; it's 0 * 323567 - 0.999999 * 323567. But the potential for bias still exists as long that max value is not evenly divisible by the max weight value).
It's possible the constant was chosen because it has properties to minimize this effect, but again: it was based on a completely different kind of .Next() function.
Therefore the rand.Next() line should probably be changed to look like this:
int r = rand.Next(prefix[n - 1]) +1;
or this:
int r = ((int)(rand.NextDouble() * (323567 * prefix[n - 1])) % prefix[n - 1]) + 1;
But, given the other errors, I'd be wary of using this code at all.
For fun, here's an example running several different options:
https://dotnetfiddle.net/Y5qhRm
The original random method (using NextDouble() and a bare constant) doesn't fare as badly as I'd expect.

Get maximum closest number from int list

I have number list like below and I should check a condition to get most suitable match.
List<int> numbers= new List<int>();
numbers.Add(1000);
numbers.Add(3000);
numbers.Add(5500);
numbers.Add(7000);
If I send a value to check it should check like below examples
Scenario 1:
If I send a value less than or equal 1000 to check, it should return 1000
Scenario 2:
If I send a value between 1001 - 3000 to check, it should return 3000
Scenario 3:
If I send a value between 3001 - 5500 to check, it should return 5500
Scenario 4:
If I send a value between 5501 - 7000 to check, it should return 7000
Scenario 5:
If I send a value above 7000 to check, it should return nothing.
Can I do this with Linq? or what is the most efficient way to do this?
Update: the numbers in maxCheckPoint is dynamic and it can be any values. So we cannot hard coded and check
You can do this with LINQ:
int input = 1000;
int? result = numbers
.OrderBy(n => n) // get the numbers in ascending order
.SkipWhile(n => n < input) // skip until the remaining set >= input
.Cast<int?>() // cast to nullable int
.FirstOrDefault(); // take the first or default entry (if no items remain, it will be null)
Well, it's too late and my solution is far away from perfect, but:
int number = 400; //imput number
int closest = numbers.Aggregate((x, y) => Math.Abs(x - number) < Math.Abs(y - number) ? x : y); // searching the closer one
int compare;
try{
if (numbers.IndexOf(closest) != 0)
{
compare = Math.Max(closest, numbers[numbers.IndexOf(closest) + 1]); // if it's not 0th and last
}
else
{ compare = closest; // if closest with index 0}
}// check which closest number is bigger
catch{
compare = closest; // if closest is last
}
Console.WriteLine(compare);

Given an array of integers, how can I find all common multiples up to a maximum number?

This is my first question on this site. I am practicing on a problem on Hackerrank that asks to find numbers "Between two Sets". Given two arrays of integers, I must find the number(s) that fit the following two criteria:
1) The elements in the first array must all be factors of the number(s)
2) The number(s) must factor into all elements of the second array
I know that I need to find all common multiples of every element in the first array, but those multiples need to be less than or equal to the minimum value of the second array. I first sort the first array then find all the multiples of ONLY the largest number in the first array (again, up to a max of the second array's minimum) and store those multiples in a list. Then, I move on to the second largest element in the first array and test it against the array of existing multiples. All elements in the list of existing multiples that isn't also a multiple of the second largest element of the first array is removed. I then test the third largest value of the first array, all the way to the minimum value. The list of existing multiples should be getting trimmed as I iterate through the first array in descending order. I've written a solution which passes only 5 out of the 9 test cases on the site, see code below. My task was to edit the getTotalX function and I created the getCommonMultiples function myself as a helper. I did not create nor edit the main function. I am not sure why I am not passing the other 4 test cases as I can't see what any of the test cases are.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution {
/*
* Complete the getTotalX function below.
*/
static int getTotalX(int[] a, int[] b) {
//get minimum value of second array
int b_min = b.Min();
//create List to hold multiples
List<int> multiples = getCommonMultiples(a, b_min);
//create List to hold number of ints which are in solution
List<int> solutions = new List<int>();
foreach(int x in multiples)
{
foreach(int y in b)
{
if (y % x == 0 && !solutions.Contains(x))
{
solutions.Add(x);
}
else
{
break;
}
}
}
return solutions.Count;
}
static List<int> getCommonMultiples(int[] array, int max)
{
//make sure array is sorted
Array.Sort(array);
int x = array.Length - 1; //x will be the last # in array -- the max
int y = 1;
//find all multiples of largest number first and store in a list
int z = array[x] * y;
List<int> commonMultiples = new List<int>();
while(z <= max)
{
commonMultiples.Add(z);
y++;
z = array[x] * y;
}
//all multiples of largest number are now added to the list
//go through the smaller numbers in query array
//only keep elements in list if they are also multiples of smaller
//numbers
int xx = array.Length - 2;
for(int a = array[xx]; xx >= 0; xx--)
{
foreach(int b in commonMultiples.ToList())
{
if (b % a != 0)
{
commonMultiples.Remove(b);
}
else
{
continue;
}
}
}
return commonMultiples;
}
static void Main(string[] args) {
TextWriter tw = new StreamWriter(#System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
string[] nm = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nm[0]);
int m = Convert.ToInt32(nm[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] b = Array.ConvertAll(Console.ReadLine().Split(' '), bTemp => Convert.ToInt32(bTemp))
;
int total = getTotalX(a, b);
tw.WriteLine(total);
tw.Flush();
tw.Close();
}
}
Again, I can't see the test cases so I do not know what exactly the issue is. I went through the code line by line and can't find any OutOfBoundExceptions or things of that sort so it has to be a logic issue. Thanks for the help!
A typical sample involves 3 lines of input. The first line has 2 integers which gives the length of the first array and the second array, respectively. The second line will give the integers in the first array. The third line will give the integers in the second array. The output needs to be the total number of integers "in between" the two arrays. It will looks like this:
Sample Input
2 3
2 4
16 32 96
Sample Output
3
Explanation: 2 and 4 divide evenly into 4, 8, 12 and 16.
4, 8 and 16 divide evenly into 16, 32, 96.
4, 8 and 16 are the only three numbers for which each element of the first array is a factor and each is a factor of all elements of the second array.
I see two issues with the code you posted.
Firstly, as #Hans Kesting pointed out, a = array[xx] is not being updated each time in the for loop. Since the variable a is only used in one spot, I recommend just replacing that use with array[xx] and be done with it as follows:
for(int xx = array.Length - 2; xx >= 0; xx--)
{
foreach(int b in commonMultiples.ToList())
{
if (b % array[xx] != 0)
{
commonMultiples.Remove(b);
For your understanding of for loops: to properly increment a each time you'd write the for loop like this:
for(int xx = array.Length - 2, a = array[xx]; xx >= 0; xx--, a = array[xx])
The first part of the for loop (up until ;) is the initialization stage which is only called before the entering the loop the first time. The second part is the while condition that is checked before each time through loop (including the first) and if at any time it evaluates to false, the loop is broken (stopped). The third part is the increment stage that is called only after each successful loop.
Because of that in order to keep a up to date in the for loop head, it must appear twice.
Secondly, your solutions in getTotalX is additive, meaning that each multiple that works for each value in array b is added as a solution even if it doesn't fit the other values in b. To get it to work the way that you want, we have to use a Remove loop, rather than an Add loop.
List<int> multiples = getCommonMultiples(a, b_min);
//create List to hold number of ints which are in solution
List<int> solutions = multiples.ToList();
foreach(int x in multiples)
{
foreach(int y in b)
{
if (y % x != 0)
{
solutions.Remove(x);
break;
}
}
}
You could also use LINQ to perform an additive solution where it takes into account All members of b:
//create List to hold number of ints which are in solution
List<int> solutions = multiples.Where((x) => b.All((y) => y % x == 0)).ToList();

Calculate Greatest Common Divisor (GCD) of more than two values [duplicate]

This question already has answers here:
Greatest Common Divisor from a set of more than 2 integers
(12 answers)
Closed 4 years ago.
In VB.NET or C#, I would like to be able calculate the Greatest Common Divisor (GCD) of one or more values, dynamically, and without using recursive methodology.
I took as a guideline this solution in C# to calculate the GCD of two values. Now, I would like to adapt that solution to be able calculate an undetermined amount of values (one or more values that are contained in a array of values passed to the function below)...
This is what I did by the moment:
VB.NET (original code):
<DebuggerStepperBoundary>
Private Shared Function InternalGetGreatestCommonDivisor(ParamArray values As Integer()) As Integer
' Calculate GCD for 2 or more values...
If (values.Length > 1) Then
Do While Not values.Contains(0)
For Each value As Integer In values
Dim firstMaxValue As Integer = values.Max()
Dim secondMaxValue As Integer = values.OrderByDescending(Function(int As Integer) int)(1)
values(values.ToList.IndexOf(firstMaxValue)) = (firstMaxValue Mod secondMaxValue)
Next value
Loop
Return If(values.Contains(0), values.Max(), values.Min())
Else ' Calculate GCD for a single value...
Return ...
End If
End Function
C# (online code conversion, I didn't tested it at all):
[DebuggerStepperBoundary]
private static int InternalGetGreatestCommonDivisor(params int[] values)
{
// Calculate GCD for 2 or more values...
if (values.Length > 1)
{
while (!values.Contains(0))
{
foreach (int value in values)
{
int firstMaxValue = values.Max();
int secondMaxValue = values.OrderByDescending((int #int) => #int).ElementAtOrDefault(1);
values[values.ToList().IndexOf(firstMaxValue)] = (firstMaxValue % secondMaxValue);
}
}
return (values.Contains(0) ? values.Max() : values.Min());
}
else // Calculate GCD for a single value...
{
return ...;
}
I'm aware that the type conversion to List would affect overall performance for a large amount of values, but the most priority thing is to make this algorithm work as expected, and finally optimize/refactorize it.
My adaptation works as expected for some combinations of values, but it does not work for anothers. For example in this online GCD calculator, if we put these values: {1920, 1080, 5000, 1000, 6800, 5555} in theory the GCD is 5, or at least that is the GCD calculated by that online service, but my algorithm returns 15.
// pass all the values in array and call findGCD function
int findGCD(int arr[], int n)
{
int gcd = arr[0];
for (int i = 1; i < n; i++) {
gcd = getGcd(arr[i], gcd);
}
return gcd;
}
// check for gcd
int getGcd(int x, int y)
{
if (x == 0)
return y;
return gcd(y % x, x);
}
The issue you are facing is caused by the fact that you are leaving the inner loop too early. Checking if any value is 0 is not enough, as you actually have to check if all but one value is 0.
The C# code could look like this:
private static int InternalGetGreatestCommonDivisor(params int[] values)
{
// Calculate GCD for 2 or more values...
if (values.Length > 1)
{
while (values.Count(value => value > 0) != 1)
{
int firstMaxValue = values.Max();
int secondMaxValue = values.OrderByDescending((int #int) => #int).ElementAtOrDefault(1);
values[values.ToList().IndexOf(firstMaxValue)] = (firstMaxValue % secondMaxValue);
}
return values.Max();
}
else
{
// Calculate GCD for a single value...
}
}
The code returns 5 for your example. I'm afraid I can't give you the exact representation for the VB.NET code.
You can do this using Linq:
static int GCD2(int a, int b){
return b == 0 ? Math.Abs(a) : GCD2(b, a % b);
}
static int GCD(int[] numbers){
return numbers.Aggregate(GCD2);
}

How to work out the median C# [duplicate]

This question already has answers here:
Calculate median in c#
(12 answers)
Closed 5 years ago.
So I'm struggling to get this piece to output a median value with 4 values.
The output produces a value one above the actual middle value and I cannot seem to get it to output a decimal even when I change 2 to 2.0. I can get it to output a value with 3 numbers just haven't achieved it with 4.
Console.Write("Median Value: ");
var items = new[]{num1, num2, num3, num4 };
Array.Sort(items);
Console.WriteLine(items[items.Length/2]);
This work is an extension task in my computing class so I may have very well taken a completely wrong approach to this task.
Thanks in advance
If you look at the explanations in Wikipedia, it's quite simple:
Easy explanation of the sample median
In individual series (if number of observation is very low) first one must arrange all the observations in order.
Then count(n) is the total number of observation in given data.
If n is odd then Median (M) = value of ((n + 1)/2)th item term.
If n is even then Median (M) = value of [(n/2)th item term + (n/2 + 1)th item term]/2.
How does that translate to code ?
using System;
namespace ConsoleApp1
{
internal static class Program
{
private static void Main(string[] args)
{
var array = new[] {1, 2, 3, 4};
Array.Sort(array);
var n = array.Length;
double median;
var isOdd = n % 2 != 0;
if (isOdd)
{
median = array[(n + 1) / 2 - 1];
}
else
{
median = (array[n / 2 - 1] + array[n / 2]) / 2.0d;
}
Console.WriteLine(median);
}
}
}
Note that you have to subtract one when getting the value of an element in the array since array indices are zero-based.
public decimal GetMedian(int[] array)
{
int[] tempArray = array;
int count = tempArray.Length;
Array.Sort(tempArray);
decimal medianValue = 0;
if (count % 2 == 0)
{
// count is even, need to get the middle two elements, add them together, then divide by 2
int middleElement1 = tempArray[(count / 2) - 1];
int middleElement2 = tempArray[(count / 2)];
medianValue = (middleElement1 + middleElement2) / 2;
}
else
{
// count is odd, simply get the middle element.
medianValue = tempArray[(count / 2)];
}
return medianValue;
}
Your implementation works for odd sized collections. But when dealing with even sized collections, you find the middle pair of numbers, and then find the value that is half way (simple arithmetical average) between them. This is easily done by adding them together and dividing by two.
The method call based on your code:
Console.Write("Median Value: ");
int[] items = new int[] {num1, num2, num3, num4};
var median = GetMedian(items);
Console.WriteLine(median);
See it running on Ideone.
How to find the median value
Add a median method to a list (source)

Categories