Friday programming quiz
-
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
-
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
Your sample solution has at least two issues I can see:
- It may explode if inputs is empty. Then again, the expected behavior for that case isn't defined, so that may be fine.
- The variable "avg" seems to have been created out of thin air.
-
Your sample solution has at least two issues I can see:
- It may explode if inputs is empty. Then again, the expected behavior for that case isn't defined, so that may be fine.
- The variable "avg" seems to have been created out of thin air.
-
Fixed issue number 2 by copy-pasting the correct code this time. Didn't think too much about issue number 1, and seeing as this is my first posted programming quiz, I should get a little slack.
jesarg wrote:
I should get a little slack.
Here ya go[^].
Henry Minute Girl: (staring) "Why do you need an icy cucumber?" “I want to report a fraud. The government is lying to us all.” I wouldn't let CG touch my Abacus! When you're wrestling a gorilla, you don't stop when you're tired, you stop when the gorilla is. Cogito ergo thumb - Sucking my thumb helps me to think.
-
Your sample solution has at least two issues I can see:
- It may explode if inputs is empty. Then again, the expected behavior for that case isn't defined, so that may be fine.
- The variable "avg" seems to have been created out of thin air.
In order to get rid of the avg variable so that it doesn't look like created out of thin air, you can replace it with inputs.Average(). As for the unexpected behaviour when the inputs array is empty, you can substitute First() with FirstOrDefault(). This prevents the code from exploding but, as you mentioned, since the expected behaviour is not defined, the result might not be the desired. I must say though, the proposed solution has a nested Lambda expression which contradicts the quiz requirement to use a "Single LINQ Lambda statement" Cheers!
-
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
jesarg wrote:
inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
You seem to like
O^42
complexity :) -
In order to get rid of the avg variable so that it doesn't look like created out of thin air, you can replace it with inputs.Average(). As for the unexpected behaviour when the inputs array is empty, you can substitute First() with FirstOrDefault(). This prevents the code from exploding but, as you mentioned, since the expected behaviour is not defined, the result might not be the desired. I must say though, the proposed solution has a nested Lambda expression which contradicts the quiz requirement to use a "Single LINQ Lambda statement" Cheers!
Already replaced the avg with inputs.Average() before you posted. :) I triple-checked the post before posting it the first time, but still made that mistake; hopefully, nobody else sees it. As for the nested Lambda expression, it only has one semi-colon in it, so to me it counts as a single LINQ lambda statement. Maybe I should say "LINQ lambda statement with only one semi-colon at the end", but that would be confusing, and I'd get a ton of people asking for clarification. In any case, thank you for the feedback, and I'll be sure to refine my quiz-posting skills from all this. In the meantime, somebody should try and post their own solution; it's not much of a programming quiz without a few more solutions.
-
In order to get rid of the avg variable so that it doesn't look like created out of thin air, you can replace it with inputs.Average(). As for the unexpected behaviour when the inputs array is empty, you can substitute First() with FirstOrDefault(). This prevents the code from exploding but, as you mentioned, since the expected behaviour is not defined, the result might not be the desired. I must say though, the proposed solution has a nested Lambda expression which contradicts the quiz requirement to use a "Single LINQ Lambda statement" Cheers!
Andres Orozco Correa wrote:
FirstOrDefault()
I think
DefaultOrEmpty()
is preferred. -
jesarg wrote:
inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
You seem to like
O^42
complexity :)Although I don't know how the LINQ is resolved, it looks like it can't be worse than O(N^3). The Average() function costs N, the Min() costs N, the Where equals costs N, and the Select Average costs N * N. The worst nesting is N * N * N. Edited: it's at worst O(N^3).
-
Although I don't know how the LINQ is resolved, it looks like it can't be worse than O(N^3). The Average() function costs N, the Min() costs N, the Where equals costs N, and the Select Average costs N * N. The worst nesting is N * N * N. Edited: it's at worst O(N^3).
jesarg wrote:
it's at worst O(N^3).
See you in a few years when a billion iterations finish ;p
-
jesarg wrote:
it's at worst O(N^3).
See you in a few years when a billion iterations finish ;p
-
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
+5 Interesting challenge, even though far beyond my linquidity. Would like to take a course in Linq from you, because I feel "stymied" in my attempts to advance beyond kindergarten-level using it, assuming I am constitutionally linquidable, that is. best, Bill
"It is the mark of an educated mind to be able to entertain a thought without accepting it." Aristotle
-
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
"We don't do homework!" AND "No programming questions in the Lounge..." ;P
Why can't I be applicable like John? - Me, April 2011
-----
Beidh ceol, caint agus craic againn - Seán Bán Breathnach
-----
Da mihi sis crustum Etruscum cum omnibus in eo!
-----
Just because a thing is new don’t mean that it’s better - Will Rogers, September 4, 1932 -
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
Not a very efficient approach (and hope I'm not cheating, there is only one semi-colon!) but here goes:
int closest = (from t in
from i in inputs
let avg = inputs.Average()
select new { Number = i, Delta = Math.Abs(i - avg) }
orderby t.Delta
select t.Number).FirstOrDefault(); -
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
Won't work when
inputs
is of zero length. :) /raviMy new year resolution: 2048 x 1536 Home | Articles | My .NET bits | Freeware ravib(at)ravib(dot)com
-
+5 Interesting challenge, even though far beyond my linquidity. Would like to take a course in Linq from you, because I feel "stymied" in my attempts to advance beyond kindergarten-level using it, assuming I am constitutionally linquidable, that is. best, Bill
"It is the mark of an educated mind to be able to entertain a thought without accepting it." Aristotle
BillWoodruff wrote:
linquidity
Interesting term... I think I'll adopt that! :-D
Why can't I be applicable like John? - Me, April 2011
-----
Beidh ceol, caint agus craic againn - Seán Bán Breathnach
-----
Da mihi sis crustum Etruscum cum omnibus in eo!
-----
Just because a thing is new don’t mean that it’s better - Will Rogers, September 4, 1932 -
Won't work when
inputs
is of zero length. :) /raviMy new year resolution: 2048 x 1536 Home | Articles | My .NET bits | Freeware ravib(at)ravib(dot)com
-
:thumbsup: /ravi
My new year resolution: 2048 x 1536 Home | Articles | My .NET bits | Freeware ravib(at)ravib(dot)com
-
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
jesarg wrote:
you must use nothing but a single LINQ lambda statement
Frack that; I thought you said this was a programming quiz.
-
I promised a programming quiz a couple weeks ago, so here's one: Given an array of integers, select the integer in the array that is the closest to the average of all integers in the array; you must use nothing but a single LINQ lambda statement. If more than one integer is the closest, then any of the closest integers will do. For example, the following code should assign "14" to the int "closest":
int[] inputs = {1, 2, 3, 5, -1, 7, 145, -33, 22, 14};
int closest = // put a LINQ lambda expression hereIf you're up for actually figuring out your own solution, ignore the rest of this post. OR If you're lazy and unethical, feel free to copy-paste the sample solution in the small text below and claim it as your own. inputs.Where(x => Math.Abs(x - inputs.Average()) == inputs.Select(y => Math.Abs(y - inputs.Average())).Min()).First();
int closest = inputs.OrderBy(i => Math.Abs(i - inputs.Average())).FirstOrDefault();
This is O(N²) as Average() gets called for every sort key that gets calculated. We can do better by storing the average in a variable. And we can use LINQ to introduce variables within an expression:
int closest = (from avg in new[] { inputs.Average() }
from i in inputs
orderby Math.Abs(i - avg)
select i).FirstOrDefault();This is O(N log N), but note that instead of sorting, we just need to find the minimum. Sadly, all the Min() methods compare the element itself, not just a key. However, we can build a suitable implementation using Aggregate():
int closest = (from avg in new[] { inputs.Average() }
select inputs.Aggregate((a, b) => Math.Abs(a - avg) < Math.Abs(b - avg) ? a : b)
).Single();This runs in linear time, and does pretty much the same as an implementation using a loop would do.