Idiomatic way to sum multiple vectors in Clojure - vector

Problem: I've got a collection of vectors or lists which I would like to find an idiomatic way to sum onto an existing vector possibly with uneven sized vectors.
Contrived example showing the setup:
=>(def collated-list [2 3 4 5 6 7 8])
=>(def lists-to-add (partition-all 3 collatedlist))
=>(def base-list [1 1 1])
I'd like the result to sum the broken down collated lists onto the base-list, for example, the first item would be 1 + 2 + 5 + 8 and so on.
What I've tried: I've tried a map and a for loop in couple of different ways but I seem to encounter either problems with Lazy Sequencing or problems of trying to add an Integer to a Vector.
These are my first experiments with Clojure so it's almost certainly me mis-understanding functional iteration here.
Thanks

First of all, it'll be much easier if lists-to-add contains lists of even length, so use partition instead of partition-all:
(def lists-to-add (partition 3 3 '(0 0) collated-list))
And then you can do the summing with map and recursion:
(defn sum-lists [base-lists lists-to-add]
(reduce #(map + %1 %2) base-list lists-to-add))

; List of list
(def lst (partition 5 (range 200)))
; Base list
(def base [1 1 1 1 1])
; Sum operation
(apply map (fn [& args] (apply + args) ) base lst)

Related

How does scramble function works? (Chapter 1 of The Seasoned Schemer)

According to the book, this is what the function definition is,
The function scramble takes a non-empty tuple in which no argument is greater than its own index and returns a tuple of same length. Each number in the argument is treated as a backward index from its own position to a point earlier in tuple. The result at each position is obtained by counting backward from the current position according to this index.
And these are some examples,
; Examples of scramble
(scramble '(1 1 1 3 4 2 1 1 9 2)) ; '(1 1 1 1 1 4 1 1 1 9)
(scramble '(1 2 3 4 5 6 7 8 9)) ; '(1 1 1 1 1 1 1 1 1)
(scramble '(1 2 3 1 2 3 4 1 8 2 10)) ; '(1 1 1 1 1 1 1 1 2 8 2)
Here is the implementation,
(define pick
(λ (i lat)
(cond
((eq? i 1) (car lat))
(else (pick (sub1 i)
(cdr lat))))))
(define scramble-b
(lambda (tup rev-pre)
(cond
((null? tup) '())
(else
(cons (pick (car tup) (cons (car tup) rev-pre))
(scramble-b (cdr tup)
(cons (car tup) rev-pre)))))))
(define scramble
(lambda (tup)
(scramble-b tup '())))
This is a case where using a very minimal version of the language means that the code is verbose enough that understanding the algorithm is not perhaps easy.
One way of dealing with this problem is to write the program in a much richer language, and then work out how the algorithm, which is now obvious, is implemented in the minimal version. Let's pick Racket as the rich language.
Racket has a function (as does Scheme) called list-ref: (list-ref l i) returns the ith element of l, zero-based.
It also has a nice notion of 'sequences' which are pretty much 'things you can iterate over' and a bunch of constructs whose names begin with for for iterating over sequences. There are two functions which make sequences we care about:
in-naturals makes an infinite sequence of the natural numbers, which by default starts from 0, but (in-naturals n) starts from n.
in-list makes a sequence from a list (a list is already a sequence in fact, but in-list makes things clearer and there are rumours also faster).
And the iteration construct we care about is for/list which iterates over some sequences and collects the result from its body into a list.
Given these, then the algorithm is almost trivial: we want to iterate along the list, keeping track of the current index and then do the appropriate subtraction to pick a value further back along the list. The only non-trivial bit is dealing with zero- vs one-based indexing.
(define (scramble l)
(for/list ([index (in-naturals)]
[element (in-list l)])
(list-ref l (+ (- index element) 1))))
And in fact if we cause in-naturals to count from 1 we can avoid the awkward adding-1:
(define (scramble l)
(for/list ([index (in-naturals 1)]
(element (in-list l)))
(list-ref l (- index element))))
Now looking at this code, even if you don't know Racket, the algorithm is very clear, and you can check it gives the answers in the book:
> (scramble '(1 1 1 3 4 2 1 1 9 2))
'(1 1 1 1 1 4 1 1 1 9)
Now it remains to work out how the code in the book implements the same algorithm. That's fiddly, but once you know what the algorithm is it should be straightforward.
If the verbal description looks vague and hard to follow, we can try following the code itself, turning it into a more visual pseudocode as we go:
pick i [x, ...ys] =
case i {
1 --> x ;
pick (i-1) ys }
==>
pick i xs = nth1 i xs
(* 1 <= i <= |xs| *)
scramble xs =
scramble2 xs []
scramble2 xs revPre =
case xs {
[] --> [] ;
[x, ...ys] -->
[ pick x [x, ...revPre],
...scramble2 ys
[x, ...revPre]] }
Thus,
scramble [x,y,z,w, ...]
=
[ nth1 x [x] (*x=1..1*)
, nth1 y [y,x] (*y=1..2*)
, nth1 z [z,y,x] (*z=1..3*)
, nth1 w [w,z,y,x] (*w=1..4*)
, ... ]
Thus each element in the input list is used as an index into the reversed prefix of that list, up to and including that element. In other words, an index into the prefix while counting backwards, i.e. from the element to the left, i.e. towards the list's start.
So we have now visualized what the code is doing, and have also discovered requirements for its input list's elements.

Scheme - Iterating Over Two Lists

Hi all I am new at learning Scheme and often have issues with making parallels between an imperative language and a functional language.
For example if I had had two arrays.
A = [1 2 3]
B = [4 5 6]
If I wanted to create a new array with the elements of A multiplied by each element in B I could simply do something like (pseudo-code):
for(int i = 0; i < A.length; i++)
for(int j = 0; j < B.length, j++)
arr.push(A[i]*B[j])
Which would give back:
arr = [4 5 6 8 10 12 12 15 18]
What would be some ways to approach this problem in a functional language?
In Scheme, the most common data structure is the linked list. Unless you have to access elements by index, it's always preferred to use lists, as there are countless built-in procedures for handling lists, that make easy to implement most algorithms without ever using an index. Just remember that for efficient access by index, using a vector would be a better idea.
Having said that, and depending on the Scheme dialect that you're using, the solution can be as simple as this (in Racket, see the documentation):
(define a '(1 2 3))
(define b '(4 5 6))
(for*/list ([x a] [y b])
(* x y))
=> '(4 5 6 8 10 12 12 15 18)
Alternatively, using only standard Scheme:
(apply append
(map (lambda (x)
(map (lambda (y) (* x y))
b))
a))
In Scheme and Racket arrays (array: a data structure indexed by a natural number) is represented using vectors.
(define as (vector 1 2 3))
(define bs (vector 4 5 6))
To make a loop-inside-a-loop we will use a variant of for*.
Plain for* works like this:
(for* ([a as] [b bs])
(displayln (* a b))))
Here a runs through the elements of the vector as and b runs through the elements in bs. Since for* is used, the b-loop runs inside the a-loop.
If for is used instead the loops run in parallel (try it).
Now since we want to collect the element, we can use for*/vector which stores the generated elements in a vector:
(for*/vector ([a as] [b bs])
(* a b)))
For efficiency reason, one can write:
(for*/vector ([a (in-vector as)] [b (in-vector bs)])
(* a b)))
This will generate sligthly more efficient code.
However
(for*/vector ([a as] [b bs])
(* a b)))
will also work if as and bs are lists.

Count elements in a vector of vectors in clojure

If I have a matrix defined as:
(def m1 [[1 2 3][4 5 6][7 8 9]])
How do I go about counting the vectors within the vector in clojure. I know that (count m1) will return 3 which is the number of vectors I have in the initial vector but I can't remember how to count the inner vectors (its been a very very long time since I've had to deal with any lisp dialect). Also I do not want to flatten the vector and then count it because I need to count the values separately (ie. I want to return 3, 3, 3 because each of the inner vectors have 3 elements. One last restriction I guess is that I want to do this without using map right away because I realized I can simply do (map count m1).
That's actually very simple, just call:
(map count m1)
Or if you want to have your result also in vector:
(mapv count m1)
You'll want to use map. It will apply count to each element in the vector and return a list of counts.
(def m1 [[1 2 3][4 5 6][7 8 9]])
(map count m1)
=> (3 3 3)
Your edit: "I want to do this without using map."
(defn counts [vs]
(loop [vs vs, cs []]
(if (empty? vs)
cs
(recur (rest vs), (conj cs (count (first vs)))))))
One answer quite good but use count. Assume not using count and also not use map
((fn [lst]
(loop [l lst, n 0]
(if (empty? l)
n
(recur (rest l) (inc n)))))'(1 2 3))

clojure - delete an element from a ref vector

I'm using a vector of maps which defined as a referece.
i want to delete a single map from the vector and i know that in order to delete an element from a vector i should use subvec.
my problem is that i couldn't find a way to implement the subvec over a reference vector.
i tried to do it using:
(dosync (commute v assoc 0 (vec (concat (subvec #v 0 1) (subvec #v 2 5))))), so that the seq returned from the vec function will be located on index 0 of the vector but it didn't work.
does anyone have an idea how to implement this?
thanks
commute (just like alter) needs a function that will be applied to the value of the reference.
So you will want something like:
;; define your ref containing a vector
(def v (ref [1 2 3 4 5 6 7]))
;; define a function to delete from a vector at a specified position
(defn delete-element [vc pos]
(vec (concat
(subvec vc 0 pos)
(subvec vc (inc pos)))))
;; delete element at position 1 from the ref v
;; note that communte passes the old value of the reference
;; as the first parameter to delete-element
(dosync
(commute v delete-element 1))
#v
=> [1 3 4 5 6 7]
Note the that separating out the code to delete an element from the vector is a generally good idea for several reasons:
This function is potentially re-usable elsewhere
It makes your transaction code shorter and more self-desciptive

getting an interval of a vector

I want to take an interval of a vector in Scheme. I know there is a procedure named vector->values, but seems like it returns each element separately, while I want to get the result as a vector. How can I achieve this?
> (vector->values (vector 1 2 3 4 5) 0 3)
1
2
3
while I need:
#(1 2 3)
If you're using PLT, you have a few easy ways to get this:
(define (subvector v start end)
(list->vector (for/list ([i (in-vector v start end)]) i)))
(define (subvector v start end)
(build-vector (- end start) (lambda (i) (vector-ref v (+ i start)))))
(define (subvector v start end)
(define new (make-vector (- end start)))
(vector-copy! new 0 v start end)
new)
The last one is probably going to be the fastest. The reason that there is no such operation that is built-in is that people usually don't do that. When you're dealing with vectors in Scheme, you're usually doing so because you want to optimize something so returning a vector and a range instead of allocating a new one is more common.
(And if you think that this is useful, please suggest it on the PLT mailing list.)
The Scheme R6RS standard has make-vector, vector-ref, vector-set! and vector-length. With that you can write your own function subvector, which does not seem to be part of R6RS (!). Some Scheme implementation have something like subvector already.
You can also switch to Common Lisp, which provides the function SUBSEQ in the standard.
Here is a portable R6RS version using SRFI 43:
#!r6rs
(import (rnrs base)
(prefix (srfi :43) srfi/43:))
(srfi/43:vector-copy (vector 1 2 3 4 5) 0 3)
#lang scheme
(define (my-vector-value v l h c)
(if (and (>= c l) (< c h))
(cons (first v) (my-vector-value (rest v) l h (add1 c)))
empty))
(list->vector (my-vector-value (vector->list (vector 1 2 3 4 5)) 0 3 0))
Ghetto? Yes, very. But it only took two minutes to write and gets the job done.
(I find it's generally easier to play with lists in Scheme)
you want subvector:
(subvector (vector 1 2 3 4 5) 0 3)

Resources