map reduce complexity - clojure

Lets suppose that i have this input: a list of list
(def list-of-list-3 (list (list 1 2 3) (list 4 5 6) (list 7 8 9)) )
(map #(reduce * %1) list-of-list3 )
The map-reduce has a O(n^2) complexity in this case?
is map-reduce translated as two nested for ?
So when i run the above example on the clojure REPL, the complexity time seems like O(n).
when i duplicate the input size ( list-of-list-6 (list (list 1 2 3) (list 4 5 6) ( list 7 8 9) (list 8 2 3) (list 9 8 1) (list 7 6 4)) ) the time increase in a linear way, not quadratic.
Can anyone say why ?
thanks in advance

It's not O(n^2), it's roughly O(n*m) where n is the no of lists and m is the length of them.
There will be other factors as well to do with the lengths of various numbers. Do it by hand and time yourself to see why!

The map-reduce has a O(n^2) complexity in this case?
Impossible to say, unless you tell us what n corresponds to in the list-of-list-3 expression.
By the way, O(n^2) or O(n*n) is quadratic complexity, not exponential complexity. Exponential complexity it O(e^n).
when i [double] the input size
( list-of-list-6 (list (list 1 2 3) (list 4 5 6) ( list 7 8 9)
(list 8 2 3) (list 9 8 1) (list 7 6 4)) )
the time increase in a linear way, not exponential.
From this, I surmise that the n is supposed to be the length of the outer list. If so, then the reduce is actually O(n) not O(n^2). To get quadratic growth, you would need to define list-of-list-6 as:
( list-of-list-6 (list (list 1 2 3 4 5 6) (list 4 5 6 1 3 2)
(list 7 8 9 1 2 3) (list 8 2 3 2 3 4)
(list 9 8 1 2 3 4) (list 7 6 4 5 6 7)) )

Related

How to create a list with n applications of a procedure

My question is related to this one but in my case I would like to obtain a list with the results of n applications of a function whose output is not computable again with the previous result (picking randomly an element from a list, for example).
That is, it is not the composition of a function n times with itself but the n results shown together into a list.
Something like this?
#!racket/base
(require srfi/1)
(define (times/list proc n)
(unfold-right zero? proc sub1 n))
(times/list (lambda (v) (abs (- v 5))) 10)
; ==> (4 3 2 1 0 1 2 3 4 5)
(times/list (lambda _ 5) 10)
; ==> (5 5 5 5 5 5 5 5 5 5)
(times/list (lambda _ (+ 1 (random 5))) 10)
; ==> (4 2 2 4 4 1 5 3 1 3) (varies)
You can use for/list like this:
(define (times/list proc n)
(for/list ([i n]) (proc)))
Using it:
> (times/list (λ () (random 5)) 10)
'(3 4 3 3 0 0 4 0 2 1)

Advice on how to tackle this lisp function.

I have written a function called my_rotate that takes a number from a user and creates a list up to five numbers. my_rotate then, pops off the first element of the list and adds it to the end of the list. Any advice on how I could write my_rotate to take in another number n and rotate the list based on the number n, in which the user entered.
Example:
> (my_rotate 1 2)
Outputs:
(3 4 5 1 2)
This is what I have so far:
(defun my_rotate (y)
(append (loop for i from (+ 1 y) to (+ 4 y) collect i)
(list y)))
Here the function.
I create two lists and then concatenate them.
(defun my-rotate (length shift)
"Return a list of given LENGTH, rotated by SHIFT."
(nconc
(loop for i from (1+ shift) to (- length shift -2) collect i)
(loop for i from 1 to shift collect i)))
(my-rotate 7 2)
==> (3 4 5 6 7 1 2)
Note that since both loops produce fresh lists, I use nconc instead of append.
If, however, you want to rotate an existing list, you will need to do something else:
(defun rotate-list (list shift)
"Rotate the given LIST by the specified SHIFT."
(let ((len (length list)))
(setq shift (mod shift len)) ; handle circular shifts
(append (nthcdr (- len shift) list)
(butlast list shift))))
(rotate-list '(1 2 3 4 5 6) 2)
==> (5 6 1 2 3 4)
(rotate-list '(1 2 3 4 5 6) 20)
==> (5 6 1 2 3 4) ; same because 20 = 2 mod 6
(rotate-list '(1 2 3 4 5 6) 0)
==> (1 2 3 4 5 6) ; unchanged
Note that nthcdr points inside the original list, so we have to use append to avoid modifying the argument.
Note also that we scan the list argument twice (once in nthcdr and once in butlast).
If your lists are huge, and profiling shows that this function is the bottleneck, you might want to re-write this using a loop (this is scenario is so unlikely, that I already regret having wasted my time writing this note).

opposite of list-ref? (Racket)

Is there anything which acts as the opposite of list-ref, where instead of selecting certain values to add to a list, it'll take values away from a list?
I basically want to do the following
(list 1 2 3 4 5 6 7) (list 3 6 7) -> (list 1 2 4 5)
Where the values in list two get deleted from list one. (preferred)
Since I will always start with a list that goes from 1 to n,
the second list could also represent the location/position where a number on list 1 should be deleted. (less preferred)
I'm trying to create a code which will manipulate other functions to come up with these lists, so please be clear where each list is 'mentioned' in the code, as I sometimes get confused if people use x y and z and so forth with multiple lambda, local definitions, etc.
I have something here which does the opposite of what I want and I've been trying to alter it so instead of outputting the elements of x that are on y, it gives the elements of x which are NOT on y.
(define (selection x y)
(filter (lambda (e2)
(ormap (lambda (e1) (equal? e1 e2))
y))
x))
example:
(list 1 2 3 4 5 6 7 8 9 10)
(list 2 4 6 8 10))
-> (list 2 4 6 8 10))
Anybody have any ideas on how to change the output to what I need?
It sounds like you're using lists as sets. You could instead use Racket sets, and use the set-subtract function:
#lang racket
(set-subtract (set 1 2 3 4 5 6 7)
(set 3 6 7))
;; => (set 1 2 4 5)
remove will do the trick I guess.
> (remove* (list 1 2) (list 1 2 3 2 4 5 2))
'(3 4 5)
You can read the doc here.
Here's a simple recursive function that achieves what you want:
(define remove-list-from-list (lambda (list remlist)
(cond
[(null? list) '()]
[(member (car list) remlist) (remove-list-from-list (cdr list) remlist)]
[else (cons (car list) (remove-list-from-list (cdr list) remlist))])))
Now you can use it like so:
> (remove-list-from-list (list 1 2 3 4 5 6 7) (list 3 6 7))
'(1 2 4 5)

Shuffle by merging lists in Clojure

How does one write a function to split a list and then merge it back together such that the resulting list represents the shuffle of a deck?
The list (1 2 3 4 5 6 7 8 9 10) should end up as (1 6 2 7 3 8 4 9 5 10)
Is there a way to use split-at or reduce or some other function to achieve this?
So far I'm here:
(defn shuffle [cards]
(split-at (/ (count cards) 2) cards)
)
(apply interleave (split-at 5 (range 1 11)))
(1 6 2 7 3 8 4 9 5 10)
Clojure has an excellent selection of sequence functions.
user> (range 1 11)
(1 2 3 4 5 6 7 8 9 10)
user> (apply mapcat list (split-at 5 (range 1 11)))
(1 6 2 7 3 8 4 9 5 10)
You can get an overview at the clojure cheatsheet, it's a little out of date but mostly still relevant, and gives a good overview of the Clojure basics.
Split like you already have, then zip the two halves together and flatten:
(defn shuffle [cards]
(->> cards
(split-at (/ (count cards) 2))
(apply map list)
(flatten)))
(shuffle '(1 2 3 4 5 6 7 8 9 10)) ;=> (1 6 2 7 3 8 4 9 5 10)
Of course if you want a “truly” random shuffle, use clojure.core/shuffle.
A general solution is
(defn riffle [s]
(let [v (vec s), c (quot (count v) 2)]
(interleave (subvec v 0 c) (subvec v c))))
In this case
(riffle '(1 2 3 4 5 6 7 8 9 10))
; (1 6 2 7 3 8 4 9 5 10)

Scheme remove a list

I found the contents of this thread quite useful!
How to delete an element from a list in scheme
I tested the code recommended, and it seems that it removes a single item at its first and only occurrence in the list.
Say instead I wanted to all occurrences of the item from the list. Or even further, if I wanted to specify a list of items instead of an item to remove.
For example if I had a function called removelist that took two lists as parameters
(define (removelist L M))
> (removelist '(1 2 2 3 4 5 2 2 5 6 7 8 9) '(1 2))
> '(3 4 5 5 6 7 8 9)
Hope this makes sense.
Here a simple function that uses filter and member to accomplish this:
(define (remove-list l m)
(filter (lambda (element)
(not (member element m)))
l))
Here the results:
> (remove-list '(1 2 2 3 4 5 2 2 5 6 7 8 9) '(1 2))
(3 4 5 5 6 7 8 9)
> (remove-list '(1 2 2 3 4 5 2 2 5 6 7 8 9) '(1 2 1))
(3 4 5 5 6 7 8 9)
This snippet requires srfi-1. Hope this helps.
Regards,
Matt
Using simple recursion and no built-in functions like filter or member:
(define (filter_out m l)
(cond ( (null? l) '() )
( (equal? (car l) m) (filter_out m (cdr l)) )
( else (cons (car l) (filter_out m (cdr l))) )
))
Test:
(filter_out 'jay (list 'jay 'z 'jay 'dilla 'jay 'electro))
(filter_out '(jay z) (list '(jay z) '(jay dilla) 'jay '(electro)))
If you're interested in learning this type of coding, check out "The Little Schemer." It takes only a few hours to read and you'll be a master at recursion after reading it.