A Python solution
@Absinthe Here is my #toyprogrammingchallenge no-division solution:
```
#!/usr/bin/env python
from collections import deque
from functools import reduce
from random import randint
def get_product_and_rotate(d):
"""Gets product of all but the first items in the queue"""
prod = reduce(lambda a, b: a * b, list(d)[1:])
d.rotate(-1) # Rotates left so that the next
return prod
if __name__ == "__main__":
n_items = randint(2, 10)
input_list = [randint(0, 9) for _ in range(n_items)]
print(input_list)
product_queue = deque(input_list)
print([get_product_and_rotate(product_queue) for _ in input_list])
```
Uses `reduce` for the multiplication, and uses a `deque` (double-ended queue) to rotate the list. I've read that using a deque is actually more efficient than just taking slices out of the list.
@Absinthe https://book.pythontips.com/en/latest/map_filter.html
I think that gives a good breakdown of map, filter, and reduce, which are common in functional programming.
@Absinthe The lambda is basically an anonymous function. It's passed in to the reduce call. Reduce calls that repeatedly until you're left with only one value.
@zingbretsen yeah, I looked it up. Works nice, perhaps I will try it with the list comprehension that I suggested.
@zingbretsen sounds like the big data functions. :)
@Absinthe Yeah, MapReduce is (well, was) pretty widely used for "big data" processing
A Python solution
@zingbretsen Okay, this is less of a criticism as it is a question of understanding:
You used the deque to rotate and slice the list for the multiplication, Could you have also used list comprehension something like this:
current_index = the one we are working on
[ value for idx, value in enumerate(list) if idx != current_idx]
I know you wanted to use the deque
A Python solution
@Absinthe Yes, you could do it that way. And that would also probably be better with the functional approach.
A Python solution
@Absinthe Rather than maintaining state with the deque, it would probably be better to pass the index in to the product function.
A Python solution
@zingbretsen right... bbiab, errand time
A Python solution
@zingbretsen The only problem I have with all of these no-division solutions is that you have to do the multiplication in all cases. I wonder if there is a mathematical trick to somehow solve without having to calculate the whole product each time, like the division solution. @freemo ... any ideas?
A Python solution
@Absinthe @freemo there's probably a dynamic programming approach where you cache the results of sub problems.
Maybe a recursive solution where you split the filtered list in half and return the product of the result of calling the function on both halves. Python has a decorator you can use called lru_cache which can cache the results of calling a function with specific inputs. This way, when it hits a problem that it's already seen before, it can just serve the result up from the cache instead of recomputing.
A Python solution
@zingbretsen What about this... as a one liner:
[reduce(lambda a, b: a *b, [ y for x, y in enumerate(list) if x != idx]) for idx, _ in enumerate(list)]
A Python solution
@Absinthe looks right to me
A Python solution
@zingbretsen This works...
print("One Liner no division")
print([reduce(lambda a, b: a *b,
[ y for x, y in enumerate(random_list) if x != idx])
for idx, _ in enumerate(random_list)])
It's a one liner, except I am sticking to 80 columns so I split it a few times.. still calling it a one liner :)
A Python solution
@Absinthe looks good.
I'll try to do something with the dynamic programming approach tomorrow or Monday.
For something like multiplication, I don't think it will make much of a difference in the execution time, but for a more expensive operation it would
re: A Python solution
I can’t think of any way to avoid the multiplications.
Here’s the lisp solution using rotate
. Destructive, so ugly, but actually leaves the input list the same as it came in. Conses only the result list.
(defun rotate (list)
(prog1 (nconc (cdr list) list)
(setf (cdr list) nil)))
(defun excluded-product-with-rotation (list)
(loop with l = list
collect (reduce #'* (cdr l) :initial-value 1)
do
(setf l (rotate l))
(when (eq l list) (loop-finish))))
re: A Python solution
@billstclair @zingbretsen Hey bill please remember to include #toyprogrammingchallenge hashtag in your responses so people can find them by searching for it.
Can I run this in gcl or emacs or do I need more code to have the list and output?
re: A Python solution
re: A Python solution
@billstclair @zingbretsen I have access to gcl but it looks like I need more to make this function
re: A Python solution
Works for me:
wws@Xossbow:~/lisp/toy-programming-challenge$ git remote -v
origin https://github.com/billstclair/toy-programming-challenge.git (fetch)
origin https://github.com/billstclair/toy-programming-challenge.git (push)
wws@Xossbow:~/lisp/toy-programming-challenge$ ls
beer.lisp excluded-product.lisp LICENSE README.md zero-to-nine.lisp
wws@Xossbow:~/lisp/toy-programming-challenge$ gcl
GCL (GNU Common Lisp) 2.6.12 CLtL1 Oct 29 2015 23:21:28
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License: GPL due to GPL'ed components: (XGCL READLINE UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter
Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files:
/tmp/
>(load "excluded-product.lisp")
Loading excluded-product.lisp
Finished loading excluded-product.lisp
T
>(apropos "excluded" *package*)
EXCLUDED-PRODUCT Function
EXCLUDED-PRODUCT-WITH-ROTATION Function
EXCLUDED-PRODUCT-WITHOUT-DIVISION Function
>(excluded-product '(1 2 3 4))
(24 12 8 ...)
>*print-length*
3
>(setf *print-length* nil)
NIL
>***
(24 12 8 6)
>(excluded-product-with-rotation '(1 2 3 4))
(24 12 8 6)
>
re: A Python solution
@billstclair @zingbretsen right, so I had to do more than just run it :) It just gave me some funtions to call. I got it now.
re: A Python solution
re: A Python solution
@billstclair @zingbretsen got it
re: A Python solution
re: A Python solution
@billstclair @zingbretsen excellent! I can't wait.
A Python solution
@zingbretsen am pretty sure there is no technical reason not to use division, just to make the problem more complicated. I am getting ready to put up a new one. But feel free to keep playing with this one. I got a new one today, but it seems a little "specific" because they give a python code starting point, and want you to serialize and deserialize a binary tree. I will likely not put that one up as a freebie. Especially since I want to get the new real on up.
A Python solution
@zingbretsen now you are stretching me. I have never seen rotate() but I can intuit what it does. I also have not used lamda's. But what is happening in the reduce() call? I assume the lamda takes 2 values how is that acting on the list? Or is the lamda being passed into the reduce call ... time to read about reduce :)