How to read this lambda expression - c#

Can someone read me the following line lambda.
n => n % 2 == 1
Also if I have to write the same piece of code without lambda how would I write it. It might make me understand.
Another piece of code is below
List<int> numbers = new List<int>{11,37,52};
List<int> oddNumbers = numbers.where(n => n % 2 == 1).ToList();

Reading the expression out loud would be
n 'goes to' n modulus two equals one
n => n % 2 == 1
Essentially, you can think of this lambda as a function that returns true when the value provided to it (n) is odd and positive, false otherwise. You could also write this as a method
bool IsOddAndPositive(int n)
{
return n % 2 == 1;
}
Using it as in your snippet would be
List<int> numbers = new List<int>{11, 37, 52};
List<int> oddNumbers = numbers.Where(IsOddAndPositive).ToList();
And the result (of both what you've specified and the method example) is
11, 37

this function
n => n % 2 == 1
takes one argument (n) and return boolean value:
true, if n is odd: n % 2 == 1 (n is odd if and only if it has remainder 1 when divided by 2)
false otherwise (if n is even)
When re-written as ordinary function it would be equivalent to
Boolean IsOdd(int n) { -- <- I've named it "IsOdd" since lambda functions have no explict names while ordinary functions have
return n % 2 == 1;
}
Your code below
List<int> oddNumbers = numbers.where(n => n % 2 == 1).ToList();
i's a LINQ expression which selects odd values from the list

As for youer problem, how you would write it without lambda:
int[] digits = {1,2,3,4,5,6,7,8,9,10};
int[] OddDigits = new int[5];
for(int i = 0; i < digits.Length; i++)
{
if(digits[i] % 2 == 1)
{
int x = 0;
OddDigits[x] = digits[i];
x++;
}
}
I just replaced the list with arrays for simplicity. As I stated in my comment earlier, it is a simple modulo operation

Line 1 instantiates a list of 3 integers
The % operator, also called modulo operator, computes the remainder after dividing its first operand by its second
The results of the second line will be a list containing 11 and 37.
you could write this like this using a foreach:
List<int> numbers = new List<int> { 11, 37, 52 };
List<int> oddNumbers = new List<int>();
foreach (var num in numbers)
{
if (num % 2 == 1)
{
oddNumbers.Add(num);
}
}
you could also use Array.ForEach, like this:
numbers.ForEach(num =>
{
if (num % 2 == 1)
oddNumbers.Add(num);
});

Related

How to find all possible values of 100 dollar bill [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
banknotes provided = 10 Dollar, 50 Dollar, 100 Dollar
Expected Result for 100 dollar bill with above bank notes.
I want to show the denomination exactly like below
5 x 10 + 1x 50
2 x 50
1 x 100
10 x 10
As you can see all the banknotes denomination total to 100 above
Let's split the problem in two:
Solve the exchange problem of total given notes (in descending order), starting from nominal at index.
Provide the solution in required format
Code:
private static IEnumerable<int[]> Solutions(int total, int[] notes, int index) {
int value = notes[index];
if (index == notes.Length - 1) {
if (total % value == 0)
yield return new int[] { total / value };
}
else
for (int i = total / value; i >= 0; --i)
foreach (int[] rest in Solutions(total - value * i, notes, index + 1))
yield return rest.Prepend(i).ToArray();
}
private static IEnumerable<string> Solve(int total, int[] notes) {
var items = notes.OrderByDescending(item => item).ToArray();
foreach (int[] solution in Solutions(total, items, 0))
yield return string.Join(" + ", solution
.Zip(items, (count, note) => (count, note))
.Where(pair => pair.count > 0)
.Select(pair => $"{pair.count} x {pair.note}"));
}
Demo:
int total = 170;
int[] notes = new int[] {10, 50, 100};
Console.Write(string.Join(Environment.NewLine, Solve(total, notes)));
Output:
1 x 100 + 1 x 50 + 2 x 10
1 x 100 + 7 x 10
3 x 50 + 2 x 10
2 x 50 + 7 x 10
1 x 50 + 12 x 10
17 x 10
Fiddle
Here is another (way less compact and cool than Dmitry's) solution, that uses recursion as you said. Basically I create a tree for each possible sum of the available banknotes that starts with the given amount at the root. For example, for your given amount of 100, and the given notes 10, 50, 100, I create the following pictured trees (and more), where the leaf values represent the individual banknotes that make up the total amount.
The leaf values then get transformed to your output, and possible duplicates (since different trees can be created from the same bank notes) are not printed out.
The following input:
int[] availableBanknotes = { 10, 50, 100 };
int amount = 100;
SolveRecursive(amount, availableBanknotes);
prints out:
10 x 10
1 x 50 + 5 x 10
2 x 50
1 x 100
The following input:
int[] availableBanknotes = { 10, 50, 100 };
int amount = 170;
SolveRecursive(amount, availableBanknotes);
prints out:
17 x 10
1 x 50 + 12 x 10
2 x 50 + 7 x 10
1 x 100 + 7 x 10
3 x 50 + 2 x 10
1 x 100 + 1 x 50 + 2 x 10
Here is the code:
private static List<string> Solutions = new List<string>();
private static void SolveRecursive(int amount, int[] availableBanknotes)
{
List<int> denomination = new List<int>();
for (int i = 0; i < availableBanknotes.Length; i++)
{
if (amount >= availableBanknotes[i])
{
ProvidedBanknotes(amount, availableBanknotes[i], availableBanknotes, new List<int>(denomination));
}
}
Solutions = new List<string>();
}
private static void ProvidedBanknotes(int amount, int currentBankNote, int[] availableBanknotes, List<int> denomination)
{
amount = amount - currentBankNote;
denomination.Add(currentBankNote);
if (amount == 0)
{
PrintSolution(denomination, availableBanknotes);
return;
}
for (int i = 0; i < availableBanknotes.Length; i++)
{
if(amount >= availableBanknotes[i])
{
ProvidedBanknotes(amount, availableBanknotes[i], availableBanknotes, new List<int>(denomination));
}
}
}
private static void PrintSolution(List<int> denomination, int[] availableBanknotes)
{
string solution = "";
for(int i = availableBanknotes.Length - 1; i >= 0; i--)
{
int currentVal = availableBanknotes[i];
int count = denomination.Where(temp => temp.Equals(currentVal))
.Select(temp => temp)
.Count();
if (count != 0)
{
if(solution.Equals(""))
{
solution = $"{count} x {currentVal}";
}
else
{
solution = solution + $" + {count} x {currentVal}";
}
}
}
if(!Solutions.Contains(solution))
{
Solutions.Add(solution);
Console.WriteLine(solution);
}
}
Given
var notes = new[] { 10, 50, 100 };
var total = 100;
You can use a LINQ Extension Method to create all possible combinations of notes and filter them to just combinations that could be used to create the total. I sort the notes in the combination descending so that the final answer will be output in descending order:
var possibleCombos = notes.Where(n => n <= total)
.AllCombinations()
.Select(c => c.OrderByDescending(n => n).ToList())
.Where(c => c.Sum() <= total && c.Aggregate(total-c.Sum(), (r, n) => r % n) == 0)
.OrderBy(c => c.Last());
While it doesn't apply to the example, the Aggregate expression ensures that impossible combinations aren't selected, such as trying to make { 50, 20 } yield 100.
For each possible combination, you can start with the total and then take away one of each note to ensure at least one of each note is in the answer. It then computes the number of additional notes needed for each denomination, starting with the largest. For each combination it outputs the number of each note in the format requested:
foreach (var combo in possibleCombos) {
var numberOfNotes = Enumerable.Repeat(1, combo.Count).ToList(); // one of each denomination
var remainder = total - combo.Sum(); // start by taking away one of each denomination
for (int j1 = 0; j1 < combo.Count; ++j1) {
numberOfNotes[j1] += remainder / combo[j1]; // take away all possible of each denomination
remainder = remainder % combo[j1];
}
Console.WriteLine(String.Join(" + ", numberOfNotes.Select((numberOfNote, j1) => $"{numberOfNote} x {combo[j1]}")));
}
The extension method is defined as:
public static class IEnumerableExt {
public static IEnumerable<IEnumerable<T>> AllCombinations<T>(this IEnumerable<T> start) {
IEnumerable<IEnumerable<T>> HelperCombinations(IEnumerable<T> items) {
if (items.IsEmpty())
yield return items;
else {
var head = items.First();
var tail = items.Skip(1);
foreach (var sequence in HelperCombinations(tail)) {
yield return sequence; // Without first
yield return sequence.Prepend(head);
}
}
}
return HelperCombinations(start).Skip(1); // don't return the empty set
}
}
NOTE: This only produces one possible solution for each combination of bills, the one that uses the maximum possible number of the largest denomination.
Here's my take on this:
public IEnumerable<List<int>> GetDenominations(List<int> denominations, int value) =>
GetDenominations(new List<int>(), denominations, value);
private IEnumerable<List<int>> GetDenominations(List<int> bills, List<int> denominations, int value)
{
int sum = bills.Sum();
if (sum == value)
{
yield return bills;
}
else if (sum < value && denominations.Any())
{
for (int i = 0; i < denominations.Count; i++)
{
List<int> denominations2 = denominations.Skip(i).ToList();
List<int> bills2 = bills.Append(denominations2.First()).ToList();
foreach (var result in GetDenominations(bills2, denominations2, value))
{
yield return result;
}
}
}
}
That produces all valid combinations of the denominations that add up the value passed.
I get the results like this:
IEnumerable<List<int>> results = GetDenominations(new List<int>() { 10, 50, 100 }, 170);
And formatting is just a little LINQ work:
string output =
String
.Join(
Environment.NewLine,
results
.Reverse()
.Select(xs =>
String
.Join(
" + ",
xs
.OrderByDescending(x => x)
.GroupBy(x => x)
.Select(x => $"{x.Count()} x {x.Key}"))));
That gives me:
1 x 100 + 1 x 50 + 2 x 10
3 x 50 + 2 x 10
1 x 100 + 7 x 10
2 x 50 + 7 x 10
1 x 50 + 12 x 10
17 x 10

How to check if the sequence of ints has even and odd numbers alternating using LINQ, C#

Let's say I have a list of ints in c# like this:
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3 };
Is there a way of checking that it has alternating odd and even numbers in it (like in the example above: if one if them is even then the next must be odd or vice versa)?
I know it's simple to check it in a loop, but I'm trying to implement this using LINQ and extension methods only.
Let's analyze the problem. What does it mean alternating parity?
index : value : value + index
------------------------------
0 : 1 : 1 - note, all sums are odd
1 : 2 : 3
2 : 7 : 9
....
Or
index : value : value + index
------------------------------
0 : 2 : 2 - note, all sums are even
1 : 1 : 2
2 : 6 : 8
....
As you can see (and you can easily prove it) alternating parity means that
index + value sums are either all odd or all even. Let's check it with a help of Linq:
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3, 79 };
bool result = numbers
.DefaultIfEmpty()
.Select((item, index) => Math.Abs((long)item + (long)index))
.Aggregate((s, a) => s % 2 == a % 2 ? s % 2 : -1) >= 0;
Notes to the implementation:
DefaultIfEmpty() - empty sequence has all (all zero) values alternating; however, Aggregate has nothing to aggregate and throws exception. Let's turn empty sequence into one element sequence.
(long) in order to prevent integer overflow (int.MaxValue + index can well be out of int range)
Math.Abs: c# can return negative remainder (e.g. -1 % 2); we don't want an additional check for this, so let's work with absolute values
However, we can exploit this effect (-1 % 2 == -1) in the final Aggregate
Extension Method solution I hope is easier to understand:
public static bool IsAlternating(this IEnumerable<int> source) {
if (null == source)
throw new ArgumentNullException(nameof(source));
bool expectedZero = false;
bool first = true;
foreach (int item in source) {
int actual = item % 2;
if (first) {
first = false;
expectedZero = actual == 0;
}
else if (actual == 0 && !expectedZero || actual != 0 && expectedZero)
return false;
expectedZero = !expectedZero;
}
return true;
}
Note, that the loop solution (extension method) is more efficient: it returns false immediately when pattern doesn't meet.
You can do with LINQ in this way. you can check if there is atelast one even item at add place or an odd item at even place.
List<int> numbers = new List<int>() { 1, 2, 7, 20, 3 };
var temp = numbers.Where((x, i) => (i % 2 == 0 && x % 2 == 0) || (i % 2 == 1 && x % 2 == 1)).Take(1);
int count = temp.Count();
if(count == 0)
{
//true
}
else
{
//false
}
Note: Assuming that you are expecting even numbers at even place and odd numbers at an odd place.
You can use Aggregate to determine if a sequence is alternating.
Let's assume that if there's 0 or 1 elements then the result is true.
You can modify this logic however you see fit.
Based on this an extension method can be created:
public static bool IsAlternatingParitySequenceVerbose(this IEnumerable<int> col)
{
// state:
// -1 - sequence is not alternating
// 0 - even
// 1 - odd
if (!col.Any())
return true;
//check if first value is even
var firstState = Math.Abs(col.First() % 2);
var IsAlternating = col.Skip(1).Aggregate(firstState, (state, val) =>
{
if (state == -1)
return -1;
var current = Math.Abs(val % 2);
if (current == state)
return -1;
return current;
});
return IsAlternating != -1;
}
And then make a one-liner out of it:
public static bool IsAlternatingParitySequence(this IEnumerable<int> col) =>
!col.Any()
|| col.Skip(1).Aggregate(Math.Abs(col.First() % 2), (state, val) =>
state == -1
? -1
: Math.Abs(val % 2) is var current && current == state
? -1
: current
) != -1;

How to search for a number in a list of arrays of numbers based on the first index of each array using LINQ?

I have a list of arrays of numbers. I am searching for the two arrays where my search number falls between the numbers positioned in index 0. Then return the number positioned in index 1 from the second array. (Assume numbers in index 0 are sorted already and there are no duplicates)
My wrong solution for LINQPad:
The value of 'found' should be 3 because 9 falls between 4 & 10 in second and third array. Then I take the second found array and return 3 which is in index 1 of that array.
List<int[]> list = new List<int[]> { new[] { 1, 5 }, new[] { 4, 6 }, new[] { 10, 3} , new[] { 15, 8} };
int searchFor = 9;
int found = list.Where(n => searchFor >= n[0] && searchFor <= n[0]).Select(i => i[1]).FirstOrDefault();
found.Dump(); //should be 3 instead of 0.
Try this :
int found = list.Zip(list.Skip(1), (x, y) => x[0]<=searchFor&&y[0]>=searchFor?y[1]:0).FirstOrDefault(o=>o!=0);
Well my logic is a little different, but get the result you want. I would recommend just using a Dictionary if you are doing key-pair-value stuff like this. It makes things simpler in my opinion and if you have no repeating key's this should work fine.
// Use dictionary instead of array's if just using two int values
var dic = new Dictionary<int, int>();
dic.Add(1, 5);
dic.Add(4, 6);
dic.Add(10, 3);
dic.Add(15, 8);
int searchFor = 9;
// Don't need to find this really
int low = (from l in dic
where l.Key <= searchFor
select l.Key).Max();
// Just need this
int found = (from h in dic
where h.Key >= searchFor
select h.Value).Min();
Console.WriteLine("Low: " + low);
Console.WriteLine("Found: " + found);
How about
var found = list.First(l => l[0] > searchFor)[1];
It should do the trick as I can assume that list is ordered by each first element.
If not, then
var found = list.Orderby(l=>l[0]).First(l => l[0] > searchFor)[1];
should also work.
The expression in the where statement filters for arrays having the first element less or equal and greater or equal than 9. Since it can't be less and greater at the same time it actually filters for all arrays that have 9 as first element.
For the given data this results in an empty sequence. FirstOrDefault therefore returns the default (0 for integers).
You actually have to look for the first element greater or equal than 9:
int[] result = list.FirstOrDefault(arr => arr[0] >= searchFor);
if (result == null)
{
Console.WriteLine("Not found!");
}
else
{
Console.WriteLine(result[1]);
}

C# using LINQ to limit a recursive list

I'm trying to figure out how to use LINQ to limit a recursive call.
My intention with the following code is to run through a list of numbers (num) and for each number recursively count/print up to a set amount (6).
the sequence in newnum that I'm trying to get is : 3 4
5
1
2
3
4
5
5
2
3
4
5
but naturally I'm running into an infinite loop instead. The .Where predicate isn't stopping the loop as I had thought and it's probable my base case is off. Any insight as to the proper way to set this up? Thank you.
var num = new[] {3, 1, 8, 5, 2};
Func<int, int> writeString = delegate(int count)
{
Func<int, int> recursiveWrite = null;
recursiveWrite = n =>
{
Console.WriteLine("string " + n);
recursiveWrite(n+1);
return n;
};
return recursiveWrite(count);
};
var newnum = num.Where(n => writeString(n) < 6); // is this possible?
newnum.ToList().ForEach( w => Console.WriteLine(w));
I noticed that a similar stopping pattern occurs in the following sample code, the .Where will only include factorials less than 7, what am I missing?
var numbers = new[] { 5,1,3,7,2,6,4};
Func<int, int> factorial = delegate(int num) {
Func<int, int> locFactorial = null;
locFactorial = n => n == 1 ? 1 : n * locFactorial(n - 1);
return locFactorial(num);
};
var smallnums = numbers.Where(n => factorial(n) < 7);
The answer is that you don't have a base case. Once your recursive function is executed, there is nothing to stop it - LINQ doesn't perform any kind of magic that can modify the internal logic of another function.
In the example you are missing this key bit of code that will stop the recursion - the base case:
locFactorial = n => n == 1 ? 1 : n * locFactorial(n - 1);
The ternary operator checks to see if n==1 - if it is, it returns 1. This is the base case that your function lacks.
There is no way to provide a base-case to your function through LINQ alone. You need to build this into the recursive function.
Additionally, you are returning the wrong type from your recursive function if you want to return a list of numbers from a single number: this is fundamentally a different case from the Factorial function which returns a single number given a single number.
Here is a function that does what you require without using recursion:
void Main()
{
var numbers = new[] {3, 1, 8, 5, 2};
numbers.SelectMany(x => GetIncreasing(x).TakeWhile(y => y < 6));
}
IEnumerable<int> GetIncreasing(int x)
{
while (true)
yield return x++;
}
You could just stick with generating sequences that fits your requirements, something like:
var num = new[] { 3, 1, 8, 5, 2 };
var limit = 6;
var query = from n in num
where n < limit // sanity check
from pn in Enumerable.Range(n, limit - n)
select pn;
Decent performance and clean code
The difference with the factorial sample is the placing of the end condition. This is what you should do:
recursiveWrite = n =>
{
Console.WriteLine("string " + n);
if (n < 6)
recursiveWrite(n+1);
return n;
};
Not completely sure of what you are trying to achieve but I hope this willl help.
You need a stop condition in your recursive lambda (as n==1 in factorial).
With nested funcs, you can inject this limit "dynamically".
class Program
{
static void Main(string[] args)
{
var num = new[] { 3, 1, 8, 5, 2 };
Func<int, Func<int, IEnumerable<int>>> writeString =
delegate(int maxcount)
{
Func<int, IEnumerable<int>> recursiveWrite = null;
recursiveWrite = (n) =>
{
if (n < maxcount)
{
Console.WriteLine("string " + n);
var rec = recursiveWrite(n + 1);
return new List<int>(){n}.Concat(rec);
}
return new List<int>();
};
return recursiveWrite;
};
var newnum = num.SelectMany(n => writeString(6)(n)); // is this possible?
newnum.ToList().ForEach(w => Console.WriteLine(w));
Console.ReadLine();
}
}

getting repeated combinations using LINQ

i have two numbers 1,2 in one array.Now i want to generate all the possible combinations of arrays(of size=5) like
1,2,0,0,0 ||
2,1,0,0,0 ||
1,0,2,0,0
.
.
.
.
.
I tried to write a recursive function but its not working
Now I want to solve this using LINQ because the code will be considerably small.
Please help me
LINQ is excellent for searching; it's much worse at generating, so it is a wrong tool for the job. So is recursion (although it is a better choice than LINQ). What you need is two nested loops, like this:
var elements = new [] {1, 2};
for (var i = 0 ; i != 5 ; i++) {
for (int j = 0 ; j != 5 ; j++) {
if (i == j) continue;
var data = new int[5];
data[i] = elements[0];
data[j] = elements[1];
ProcessCombination(data);
}
}
Here is what the code does: at each iteration of the inner loop it places the first and the second element from the elements array at distinct positions i and j. Nested loops go from 0 to 5, making sure all position combinations are covered.
You could use something like this:
public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> list)
{
if (list.Count() == 1)
return new List<IEnumerable<T>> { list };
return list.Select((a, i1) => Permute(
list.Where((b, i2) => i2 != i1)).Select(
b => (new List<T> { a }).Union(b))
).SelectMany(c => c);
};
.....
var result = Permute(new int[]{1,2,0,0,0});

Categories

Resources