A local variable cannot be declared in this scope[Linq/Lambda expression] - c#

I have following code snippet in c#
static void Main()
{
var numbers = new[] { 1, 2, 3, 4, 5, 6 };
var ngt5 = numbers.Where(n => n > 5);
var n = ngt5.First().ToString();
Console.WriteLine(n, numbers);
}
When I am compiling the above code I am getting following error
A local variable named 'n' cannot be declared in this scope

Your problem is here:
// Within your lambda you have an 'n'.
var ngt5 = numbers.Where(n => n > 5);
// And within the outer scope you also have an 'n'.
var n = ngt5.First().ToString();
To understand why this is a problem, consider the following code:
int n = 1000;
var evens = Enumerable.Range(1, 1000).Where(n => n % 2 == 0);
The expression n % 2 == 0 above is ambiguous: which n are we talking about? If we're talking about the outer n, then n % 2 == 0 is always true since n is just 1000 (and therefore evens will comprise all numbers from 1 to 1000). On the other hand, if we're talking about the inner n, then n % 2 == 0 will only hold true for even values of n (and evens will be 2, 4, 6, ... 1000).
The important point to realize is that variables declared outside the lambda are accessible from within the lambda's scope.
int n = 0;
Action incrementN = () => n++; // accessing an outer variable
incrementN();
Console.WriteLine(n); // outputs '1'
This is why the ambiguity exists, and why it is therefore not allowed.
The solution is simply to pick a different variable name for your lambda; e.g.:
var ngt5 = numbers.Where(x => x > 5);

Your problem is that you assume that closures are first class functions in C#, which is not the case and I wish it was the case.
You can't treat scope of C# closure as isolated function scope.
You can't return complicated Linq expression outside of current scope.
JavaScript allows this ambiguity, which allows to write closures without any limit, which makes closures first class functions of JavaScript.

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.

multiplicative persistence - recursion?

I'm working on this:
Write a function, persistence, that takes in a positive parameter num
and returns its multiplicative persistence, which is the number of
times you must multiply the digits in num until you reach a single
digit.
For example:
persistence(39) == 3 // because 3*9 = 27, 2*7 = 14, 1*4=4
// and 4 has only one digit
persistence(999) == 4 // because 9*9*9 = 729, 7*2*9 = 126,
// 1*2*6 = 12, and finally 1*2 = 2
persistence(4) == 0 // because 4 is already a one-digit number
This is what I tried:
public static int Persistence(long n)
{
List<long> listofints = new List<long>();
while (n > 0)
{
listofints.Add(n % 10);
n /= 10;
}
listofints.Reverse();
// list of a splited number
int[] arr = new int[listofints.Count];
for (int i = 0; i < listofints.Count; i++)
{
arr[i] = (int)listofints[i];
}
//list to array
int pro = 1;
for (int i = 0; i < arr.Length; i++)
{
pro *= arr[i];
}
// multiply each number
return pro;
}
I have a problem with understanding recursion - probably there is a place to use it. Can some1 give me advice not a solution, how to deal with that?
It looks like you've got the complete function to process one iteration. Now all you need to do is add the recursion. At the end of the function call Persistence again with the result of the first iteration as the parameter.
Persistence(pro);
This will recursively call your function passing the result of each iteration as the parameter to the next iteration.
Finally, you need to add some code to determine when you should stop the recursion, so you only want to call Persistence(pro) if your condition is true. This way, when your condition becomes false you'll stop the recursion.
if (some stop condition is true)
{
Persistence(pro);
}
Let me take a stab at explaining when you should consider using a recursive method.
Example of Factorial: Factorial of n is found by multiplying 1*2*3*4*..*n.
Suppose you want to find out what the factorial of a number is. For finding the answer, you can write a foreach loop that keeys multiplying a number with the next number and the next number until it reaches 0. Once you reach 0, you are done, you'll return your result.
Instead of using loops, you can use Recursion because the process at "each" step is the same. Multiply the first number with the result of the next, result of the next is found by multiplying that next number with the result of the next and so on.
5 * (result of rest)
4 * (result of rest )
3 * (result of rest)
...
1 (factorial of 0 is 1).---> Last Statement.
In this case, if we are doing recursion, we have a terminator of the sequence, the last statement where we know for a fact that factorial of 0 = 1. So, we can write this like,
FactorialOf(5) = return 5 * FactorialOf(4) = 120 (5 * 24)
FactorialOf(4) = return 4 * FactorialOf(3) = 24 (4 * 6)
FactorialOf(3) = return 3 * FactorialOf(2) = 6 (3 * 2)
FactorialOf(2) = return 2 * FactorialOf(1) = 2 (2 * 1)
FactorialOf(1) = return 1 * FactorialOf(0) = 1 (1 * 1)
FactorialOf(0) = Known -> 1.
So, it would make sense to use the same method over and over and once we get to our terminator, we stop and start going back up the tree. Each statement that called the FactorialOf would start returning numbers until it reaches all the way to the top. At the top, we will have our answer.
Your case of Persistence
It calls for recursive method as well as you are taking the result and doing the same process on it each time.
Persistence(39) (not single) = return 1 + Persistence(3 * 9 = 27) = 3
Persistence(27) (not single) = return 1 + Persistence(2 * 7 = 14) = 2
Persistence(14) (not single) = return 1 + Persistence(1 * 4 = 4) = 1
Persistence(4) (single digit) = Known -> 0 // Terminator.
At the end of the day, if you have same process performed after each calculation / processing with a termination, you can most likely find a way to use recursion for that process.
You definitely can invoke your multiplication call recursively.
You will need initial sate (0 multiplications) and keep calling your method until you reach your stop condition. Then you return the last iteration you've got up to as your result and pass it through all the way up:
int persistence(int input, int count = 0) {} // this is how I would define the method
// and this is how I see the control flowing
var result = persistence(input: 39, count: 0) {
//write a code that derives 27 out of 39
//then keep calling persistence() again, incrementing the iteration count with each invocation
return persistence(input: 27, count: 1) {
return persistence(input: 14, count: 2) {
return persistence(input: 4, count: 3) {
return 3
}
}
}
}
the above is obviously not a real code, but I'm hoping that illustrates the point well enough for you to explore it further
Designing a simple recursive solution usually involves two steps:
- Identify the trivial base case to which you can calculate the answer easily.
- Figure out how to turn a complex case to a simpler one, in a way that quickly approaches the base case.
In your problem:
- Any single-digit number has a simple solution, which is persistence = 1.
- Multiplying all digits of a number produces a smaller number, and we know that the persistence of the bigger number is greater than the persistence of the smaller number by exactly one.
That should bring you to your solution. All you need to do is understand the above and write that in C#. There are only a few modifications that you need to make in your existing code. I won't give you a ready solution as that kinda defeats the purpose of the exercise, doesn't it. If you encounter technical problems with codifying your solution into C#, you're welcome to ask another question.
public int PerRec(int n)
{
string numS = n.ToString();
if(numS.Length == 1)
return 0;
var number = numS.ToArray().Select(x => int.Parse(x.ToString())).Aggregate((a,b) => a*b);
return PerRec(number) + 1;
}
For every recursion, you should have a stop condition(a single digit in this case).
The idea here is taking your input and convert it to string to calculate that length. If it is 1 then you return 0
Then you need to do your transformation. Take all the digits from the string representation(in this case from the char array, parse all of them, after getting the IEnumerable<int>, multiply each digit to calculate the next parameter for your recursion call.
The final result is the new recursion call + 1 (which represents the previous transformation)
You can do this step in different ways:
var number = numS.ToArray().Select(x => int.Parse(x.ToString())).Aggregate((a,b) => a*b);
convert numS into an array of char calling ToArray()
iterate over the collection and convert each char into its integer representation and save it into an array or a list
iterate over the int list multiplying all the digits to have the next number for your recursion
Hope this helps
public static int Persistence(long n)
{
if (n < 10) // handle the trivial cases - stop condition
{
return 0;
}
long pro = 1; // int may not be big enough, use long instead
while (n > 0) // simplify the problem by one level
{
pro *= n % 10;
n /= 10;
}
return 1 + Persistence(pro); // 1 = one level solved, call the same function for the rest
}
It is the classic recursion usage. You handle the basic cases, simplify the problem by one level and then use the same function again - that is the recursion.
You can rewrite the recursion into loops if you wish, you always can.

TakeWhile, at least n elements

There seems to be no e.TakeWhile(predicate, atLeastNElements) overload. Is there a convenient way to express TakeWhile, however, take at least N elements if there are >= N elements available.?
Edit: the best I came up with in my head is to capture an int in TakeWhile's predicate and reduce it by one each call while returning true. The actual predicate is used only after the counter is down to zero.
You can use an overload to TakeWhile with the index of the current element:
var e = new [] { 1, 2, 3, 4, 5 };
var n = 3; // at least n
e.TakeWhile((element, index) => index < n || predicate(element));

What is the difference between these two pieces of code?

int[] div = new int[] {2,3,5};
IEnumerable<int> seq = new int[] {10,15,20,25,30};
int x;
for (int i=0; i<div.Length; i++){
x = div[i];
seq = seq.Where( s=> s%x ==0);
}
seq = seq.ToList();
AND
int[] div = new int[] {2,3,5};
IEnumerable<int> seq = new int[] {10,15,20,25,30};
for (int i=0; i<div.Length; i++){
int y = div[i];
seq = seq.Where( s=> s%y ==0);
}
seq = seq.ToList();
The first seq's final value is 10,15,20,25,30 and the second one's is 30.
I'm a little confused about the difference between int x;
and int y = div[i]; . Can someone explain this to me?
Thanks!
Invoking seq = seq.Where( s=> s%x ==0); does not iterate over elements. It only creates an IEnumarable encapsulating the iteration, that can be iterated in fututre.
So if you declare your x variable before the loop, the lambda, that you passed in Where() uses the same variable. Since you are changing its value in a loop, eventually only the last one will be actually used.
Instead of expression like:
seq.Where( s=> s % 2 == 0).Where( s=> s % 3 == 0).Where( s=> s % 5 == 0);
you get:
seq.Where( s=> s % 5 == 0).Where( s=> s % 5 == 0).Where( s=> s % 5 == 0);
The result is different because you are using lambda expression in the LINQ's Where() parameter. The actual execution of the all lambdas in Where()'s is performed on the very last row of both examples - the line where you perform .ToList(). Have a look at the Variable Scope in Lambda Expressions
The difference in the examples is how you initialize x/y.
In the first example there is only one memory slot for the variable x regardless of number of iterations of the foreach. The x always points to the same spot in the memory. Therefore there is only one value of the x on the last row and it is equal to the div[2].
In the second example there is separate memory slot created for y in each iteration of the loop. As the program evaluates, the address where y points to is changed in every iteration of the foreach. You might imagine it as there are multiple y variables like y_1, y_2,... Hence when evaluating the actual lambdas in Where()s the value of the y is different in every one of them.

C# Similarities of two arrays

There must be an better way to do this, I'm sure...
// Simplified code
var a = new List<int>() { 1, 2, 3, 4, 5, 6 };
var b = new List<int>() { 2, 3, 5, 7, 11 };
var z = new List<int>();
for (int i = 0; i < a.Count; i++)
if (b.Contains(a[i]))
z.Add(a[i]);
// (z) contains all of the numbers that are in BOTH (a) and (b), i.e. { 2, 3, 5 }
I don't mind using the above technique, but I want something fast and efficient (I need to compare very large Lists<> multiple times), and this appears to be neither! Any thoughts?
Edit: As it makes a difference - I'm using .NET 4.0, the initial arrays are already sorted and don't contain duplicates.
You could use IEnumerable.Intersect.
var z = a.Intersect(b);
which will probably be more efficient than your current solution.
note you left out one important piece of information - whether the lists happen to be ordered or not. If they are then a couple of nested loops that pass over each input array exactly once each may be faster - and a little more fun to write.
Edit
In response to your comment on ordering:
first stab at looping - it will need a little tweaking on your behalf but works for your initial data.
int j = 0;
foreach (var i in a)
{
int x = b[j];
while (x < i)
{
if (x == i)
{
z.Add(b[j]);
}
j++;
x = b[j];
}
}
this is where you need to add some unit tests ;)
Edit
final point - it may well be that Linq can use SortedList to perform this intersection very efficiently, if performance is a concern it is worth testing the various solutions. Dont forget to take the sorting into account if you load your data in an un-ordered manner.
One Final Edit because there has been some to and fro on this and people may be using the above without properly debugging it I am posting a later version here:
int j = 0;
int b1 = b[j];
foreach (var a1 in a)
{
while (b1 <= a1)
{
if (b1 == a1)
z1.Add(b[j]);
j++;
if (j >= b.Count)
break;
b1 = b[j];
}
}
There's IEnumerable.Intersect, but since this is an extension method, I doubt it will be very efficient.
If you want efficiency, take one list and turn it into a Set, then go over the second list and see which elements are in the set. Note that I preallocate z, just to make sure you don't suffer from any reallocations.
var set = new HashSet<int>(a);
var z = new List<int>(Math.Min(set.Count, b.Count));
foreach(int i in b)
{
if(set.Contains(i))
a.Add(i);
}
This is guaranteed to run in O(N+M) (N and M being the sizes of the two lists).
Now, you could use set.IntersectWith(b), and I believe it will be just as efficient, but I'm not 100% sure.
The Intersect() method does just that. From MSDN:
Produces the set intersection of two sequences by using the default
equality comparer to compare values.
So in your case:
var z = a.Intersect(b);
Use SortedSet<T> in System.Collections.Generic namespace:
SortedSet<int> a = new SortedSet<int>() { 1, 2, 3, 4, 5, 6 };
SortedSet<int> b = new SortedSet<int>() { 2, 3, 5, 7, 11 };
b.IntersectWith(s2);
But surely you have no duplicates!
Although your second list needs not to be a SortedSet. It can be any collection (IEnumerable<T>), but internally the method act in a way that if the second list also is SortedSet<T>, the operation is an O(n) operation.
If you can use LINQ, you could use the Enumerable.Intersect() extension method.

Categories