Posted in:

I’ve got another LINQ Challenge for you (The first one is here with C# answers here, and F# answers here). The idea with these challenges is to see if you can solve them using LINQ. It is in fact possible to solve them all in a single LINQ statement, but of course that may not always make for the most readable code, so feel free to break your answer up into multiple statements if you prefer.

So here’s problems for this challenge…

Problem 1 – Motor Sport Scores

In a motor sport competition, a player's points total for the season is the sum of all the points earned in each race, but the three worst results are not counted towards the total. Calculate the following player's score based on the points earned in each round:

"10,5,0,8,10,1,4,0,10,1"

Problem 2 – Bishop Moves

A chess board is an 8x8 grid, from a1 in the bottom left to h8 in the top right. A bishop can travel diagonally any number of squares. So for example a bishop on c5 can go to b4 or to a3 in one move. Create an enumerable sequence of board positions that includes every square a bishop can move to in one move on an empty chess board, if its starting position is c6. e.g. output would include b7, a8, b5, a4

Problem 3 – Sampling

The following sequence has 100 entries. Sample it by taking every 5th value and discarding the rest. The output should begin with 24,53,77,...

"0,6,12,18,24,30,36,42,48,53,58,63,68,72,77,80,84,87,90,92,95,96,98,99,99,100,99,99,98,96,95,92,90,87,84,80,77,72,68,63,58,53,48,42,36,30,24,18,12,6,0,-6,-12,-18,-24,-30,-36,-42,-48,-53,-58,-63,-68,-72,-77,-80,-84,-87,-90,-92,-95,-96,-98,-99,-99,-100,-99,-99,-98,-96,-95,-92,-90,-87,-84,-80,-77,-72,-68,-63,-58,-53,-48,-42,-36,-30,-24,-18,-12,-6"

Problem 4 – Vote Winning Margin

Yes won the vote, but how many more Yes votes were there than No votes?

"Yes,Yes,No,Yes,No,Yes,No,No,No,Yes,Yes,Yes,Yes,No,Yes,No,No,Yes,Yes"

Problem 5 – Counting Pets

Count how many have dogs, how many have cats, and how many have other pets. e.g. output would be a structure or sequence containing: Dog:5 Cat:3 Other:4

"Dog,Cat,Rabbit,Dog,Dog,Lizard,Cat,Cat,Dog,Rabbit,Guinea Pig,Dog"

Problem 6 – Run Length Decoding

Expand strings in this form: A5B10CD3 to AAAAABBBBBBBBBBCDDD. Note that a letter may have 0 digits after it (C in the example), which means just repeat it once. It may also have more than one digit after it, such as B in this example, which is repeated 10 times. This one is a bit tricky, but there is a handy method in the .NET framework (not part of LINQ) which can help you get started.

"A5B10CD3"

Over to You

Hope you have fun solving these. If you want to participate in the challenge, put your answers into a GitHub Gist and leave a link to it in the comments below.

I recommend LINQPad as a great tool for working on your answers, and you’ll find some additional .NET framework methods like string.Split and string.Join helpful in places.

I’ll give people a week to get their answers in, and then I’ll post what I consider to be the best solutions in both C# and F#. Of course, feel free to solve these in whatever language you like – Python, PowerShell, Perl…

Want to learn more about LINQ? Be sure to check out my Pluralsight course LINQ Best Practices.

Comments

Comment by Mark Heath

good stuff, the vote difference one is nice. One simple approach to bishop moves is enumerate through every square on a chessboard and decide if bishop can move there. But it is quite painful to make it a single linq statement that isn't quite ugly.

Mark Heath
Comment by Mark Jones

Added a solution for the bishop's moves; I'm looking forward to seeing other solutions
https://gist.github.com/ora...

Mark Jones
Comment by Mark Heath

Good job, I'll share some answers at the end of the week. I've had about 10 people attempt this, and it's always interesting to see the variety of different approaches

Mark Heath
Comment by Sehnsucht

Done it in F# : https://gist.github.com/Seh...
Done a small edit for problem 5. I've misread it and just counted by pet without seeing that all but dog and cat are one group (That's why I found it so easy)

Sehnsucht
Comment by Mark Heath

awesome, thanks for sharing. Have picked up a few more handy F# tips from your answers ;)

Mark Heath
Comment by Yossu Bonkers

I realise this is several years too late, but since I first had a go at these, #4 has always bothered me. It seemed that there should be a way of finding out how many votes each side got, as well as the overall majority.
Well, I just realised that it's pretty simple. Your answer uses Sum to aggregate the results, but that loses the individual scores. You can aggregate the scores in a way that you keep the information, so you can see how much each team/side/whatever got...
"Yes,Yes,No,Yes,No,Yes,No,No,No,Yes,Yes,Yes,Yes,No,Yes,No,No,Yes,Yes"
.Split(",")
.Select(yn => yn[0])
.Aggregate((0, 0, 0), (t, c) => c == 'Y'
? (t.Item1 + 1, t.Item2, t.Item1 + 1 - t.Item2)
: (t.Item1, t.Item2 + 1, t.Item1 - t.Item2 + 1))

In the resulting tuple, Item1 is the total Yes score, Item2 is the total No score, and Item3 is the majority that Yes had over No.
Not the most efficient way to do this, but a good exercise in thinking! Thanks for doing these, please can we have more?

Yossu Bonkers