usingSystem.Linq;usingSystem;publicclassKata{publicstaticint[]CountPositivesSumNegatives(int[]a){// guard clause for edge casesif(a==null||a.Length==0)returnnewint[0];intcount=0;intsum=0;// ".ToList()" is required to iterate the sequencea.Select(n=>n>0?count++:sum+=n).ToList();returnnew[]{count,sum};}}
I'm Jake Cahill: Lifetime Pythonista, web scraping, cloud computing, and automation expert. Enjoy books. Love my wife, dog, and cat, and think AI and Rust are pretty nifty
Location
Massachusetts, USA
Education
A Master's patient mentorship and insatiable curiosity
letupdate(count,sum)value=ifvalue>0then(count+1),sumelsecount,(sum+value)// usage, start with 0 count/sum, update them for each valuelet(count,sum)=Array.foldupdate(0,0)inputArr
This returns a tuple instead of an array, which I believe is an improvement.
Note: Aggregate is equivalent to reduce in JavaScript or other languages
and seed value is the first argument unlike in JavaScript, in which it's the last argument.
Oh holy shit! I was looking at it for several minutes and it started making sense! Maybe because I thought through problem with @aspittel
, or maybe this APL is more sensible (the last one I saw, someone had spilled a bag of unicode across its source).
I'm using Ruby's comment syntax because IDK how to do it in APL
# Haskell uses arrows for assignment in `do` blocks.
# Whitespace delimited numbers are a thing in lisp.
# The high bar looks a lot like a minus sign, so:
A← # set into the variable A
A←1 2 3 ¯4 ¯5 ¯6 # the list of numbers: [1, 2, 3, -4, -5, -6]
# Haskell iplements + as a function that you can pass around
# The slash looks like and is used like a shell pipeline.
# Tilde is logical negation in many syntaxes.
# `A` in `A<0` is like SQL, which uses the
# table name to refer to that table's current row.
X← # set into the variable X
X←+/ # the sum of
X←+/(~ # the numbers which aren't
X←+/(~A<0)/ # negative
X←+/(~A<0)/A # from the list A
Y← # set into the variable Y
Y←+/ # the sum of
Y←+/(~ # the variables that aren't
Y←+/(~A>0)/ # positive
Y←+/(~A>0)/A # from the list A
O←X Y # set X and Y as the output
A certain bathroom has N + 2 stalls in a single row; the stalls on the left and right ends are permanently occupied by the bathroom guards. The other N stalls are for users.
When picking a stall, instead of considering two pieces, Rs, Ls, of state, all you need to know is the size of groups of free stalls. You always pick the middle stall of the largest group of sequential free stalls (in case of ties, you pick the leftmost group, in case the size is even, you pick the half-left stall).
Order doesn't matter - the problem doesn't ask for which stall the Kth person is going to pick, it asks indirectly for the size of the group (given the size of the group you can easily compute max(Ls, Rs) and min(Ls, Rs).
You can group stall groups by size - so this is a little trickier, but you can consider the choices of stalls as a binary tree (the solution above seemed to be going in that direction). Each choice corresponds to a group of stalls. At each level of the binary tree, you'll have a lot of repeated group sizes. In particular, each level of the binary tree has at most 2 different group sizes (I'll leave this as an exercise for you to prove). So, instead of splitting each group one at a time, since order doesn't matter, we can split all groups of the same time in one step, and just add groups for the next level.
At the end you get a nice concise O(log(K)) runtime and O(1) space solution.
Here's an example of how this works by manually solving N=1000 and K=100:
You start with a group of size 1000 for free stalls, so your group size -> number of groups maps looks like this:
Step 1:
1000 -> 1
k = 100
You split 1000 into two groups, one of 499, and one of size 500, and this represents the choice of 1 person, since there is 1 group of size 1000. So now our state looks like:
Step 2:
500 -> 1
499 -> 1
k = 99
Now you split 500 into 249 and 250:
Step 3:
499 -> 1
249 -> 1
250 -> 1
k = 98
Now I'll just draw the next steps, without explaining:
Now things get special, because there are 41 groups of 15 free stalls, but only 36 people left to choose a stall. Therefore, the last person will choose the middle stall of a group of 15 free stalls, and thus Ls = 7 and Rs = 7!
Ah -- I must have introduced an issue while refactoring -- it passed the tests during the competition. But then I refactored, should have checked again!
I think you should add the problems to the post itself. Otherwise, the later problems will get lost in the comment thread. It will be even better to create a separate post per problem and embed them in the weekly post. That way, discussion will be more focused.
You've got me on a go kick, and now I'm going back and doing previous exercises you've posted! (Sorry for the large volume of comments on your posts today.
Monday
Count of positives / sum of negatives (8 KYU):
Return an array, where the first element is the count of positives numbers and the second element is sum of negative numbers.
link
Solved it awhile ago (forgot about it).
Here is a C# answer.
And just re-solved it using JavaScript
Python 3 solution update. Posted to the wrong part of the discussion :P
Refactored to the code-golfiest thing ever with help of @joshcheek !
F#
This returns a tuple instead of an array, which I believe is an improvement.
Tuesday
Ones and Zeros (7 KYU):
Given an array of one's and zero's convert the equivalent binary value to an integer.
link
Q/kdb+ solution (let l be the input list):
with list multiplication:
with adverb over:
F#
Edit: shortened
Here is a C# version
Note:
Aggregateis equivalent toreducein JavaScript or other languagesand
seedvalue is the first argument unlike in JavaScript, in which it's the last argument.My Python solution:
Wednesday
Write a program to reverse the digits of a positive integer but without converting it to a string.
My Python solution:
And now this is... 😮
F#
whileloop on compile)i % 10gets the right-most digit ofirev * 10shifts the numbers left, with right-most zeroi / 10shifts the numbers right, dropping right-most digitI happened to remember these little number tricks from a previous challenge. This is basically using integers as digit stacks.
Thank you, Ali.
This has been one of the most fun challenges.
Took me awhile but here is the C# version.
The gist is that, remainder is calculated for each digit, stored in a stack (LIFO - last in first out) to reverse the remainder.
Lastly the
totalis reconstructed from the stack.Runnable code on .NET Fiddle
Oh that's a really cool approach!
Thursday
Calculating with Functions:
This time we want to write calculations using functions and get the results. For example:
seven(times(five())); // must return 35
link
thanks, it's fun :)
Ugly but worked :p
JavaScript
Python solution:
Though I prefer this one from the CodeWars solutions!
Apparently I've done this kata before...but I don't know if that even helped me this time. It's so hard to wrap my brain around.
Thanks for the suggestion there, @asparallel.
Here is the updated C# code (with the same logic as JavaScript one) using
.Aggregate.Oh holy shit! I was looking at it for several minutes and it started making sense! Maybe because I thought through problem with @aspittel , or maybe this APL is more sensible (the last one I saw, someone had spilled a bag of unicode across its source).
I'm using Ruby's comment syntax because IDK how to do it in APL
I will one day be able to look at APL without my brain leaking out of my ears.
Today is not that day.
Friday
Bathroom Stalls (Code Jam):
A certain bathroom has N + 2 stalls in a single row; the stalls on the left and right ends are permanently occupied by the bathroom guards. The other N stalls are for users.
link
Python solution!
So I was curious since this solution didn't seem correct, and tried to run this through the codejam grader, and it seems like it isn't correct.
I had some fun with this problem, though (it entertained some part of a plane ride), and came up with a nice concise solution:
A few insights here:
At the end you get a nice concise O(log(K)) runtime and O(1) space solution.
Here's an example of how this works by manually solving N=1000 and K=100:
You start with a group of size 1000 for free stalls, so your group size -> number of groups maps looks like this:
You split 1000 into two groups, one of 499, and one of size 500, and this represents the choice of 1 person, since there is 1 group of size 1000. So now our state looks like:
Now you split 500 into 249 and 250:
Now I'll just draw the next steps, without explaining:
Now things get special, because there are 41 groups of 15 free stalls, but only 36 people left to choose a stall. Therefore, the last person will choose the middle stall of a group of 15 free stalls, and thus Ls = 7 and Rs = 7!
Ah -- I must have introduced an issue while refactoring -- it passed the tests during the competition. But then I refactored, should have checked again!
Meta
Discussion on how I should format this post!
I think you should add the problems to the post itself. Otherwise, the later problems will get lost in the comment thread. It will be even better to create a separate post per problem and embed them in the weekly post. That way, discussion will be more focused.
yeah -- the only thing that makes me nervous about that is it seeming spammy to post one every day?
Ah ha. Tuple being a value type, it is better optimized.
Thanks for the tips there 👊
987654321is how I expect it to work though without the 0 in the beginning as you should return apositive integer.Common Lisp FTW!
the positive integer shouldn't have a leading zero I don't think. It's at least up to interpretation.
Haha there are worse problems out there
You've got me on a go kick, and now I'm going back and doing previous exercises you've posted! (Sorry for the large volume of comments on your posts today.
true -- I'm on Python 3 though and the test cases are all small