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.
Related
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.
I'm trying to get the lowest integer out of a vector only containing numbers. I know how to do it with lists. You compare the first two values of the list and depending on which is larger you either save your value to output it later or call the function again with the rest of the list (all elements except the first) using the cdr procedure.
But with vectors I'm completely lost. My guess would be that the way of thinking about the solution would be the same for lists and vectors. I've been reading on the racket-lang website but haven't been able to come up with a solution to the problem. The procedures I've been experimenting most with are vector-ref and vector-length as they seem to be the most useful in this problem (but this is my first time working with vectors so what do I know).
So my two questions are:
How can we get all values except the first from a vector? Is there a procedure like cdr but for vectors?
If you were working with lists you would use cons to save the values you would want to output. But is there a similar way of doing it when working with vectors?
Thanks!
The simplest solution is to use a variant of for called for/fold.
I thought there were an for/min but alas.
#lang racket
(define v (vector 11 12 13 4 15 16))
(for/fold ([m +inf.0]) ([x (in-vector v)])
(min m x))
If you like a more explicit approach:
(define (vector-min xs)
(define n (vector-length xs))
(let loop ([i 0] ; running index
[m +inf.0]) ; minimum value so far
(cond
[(= i n) ; if the end is reached
m] ; return the minimum
[else ; else
(define x (vector-ref v i)) ; get new element in vector
(loop (+ i 1) ; increment index
(min m x))]))) ; new minimum
UPDATE
(let loop ([x 1] [y 10])
(loop (+ x 1) (- y 1))
is the same as:
(let ()
(define (loop (x y)
(loop (+ x 1) (- y 1)))
(loop 1 10))
Vectors are O(1) access and indexed so it is a completely different data structure, however you have SEFI-43 which is like the SRFI-1 List library, but for vectors.
#lang racket
(require srfi/43)
(define (min-element lst)
(vector-fold min (vector-ref lst 0) lst))
(max-element #(7 8 1 2 3 4 5 12))
; ==> 1
The racket/vector module has vector-argmin for finding the minimum element of a vector (Well, the minimum after feeding the elements through a transformation function). Combine that with a function like identity from racket/function and it's trivial:
(vector-argmin identity '#(5 4 3 2 1 6))
Iam another Clojure-newbi!
How can i assign a vector containing some values to another one?
I want to do:
[a b] >>> [b (+ a b)]
so that afterwards b has the value of (a+b) and a that of b.
It looks like you're trying to do a fibonacci sequence.
user=> (def fibseq (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1])))
#'user/fibseq
user=> (take 10 fibseq)
(1 1 2 3 5 8 13 21 34 55)
What you've got to remember in clojure is immutability, so you don't change a and b to be the new values. So something like:
user=> (defn next-fib [[a b]]
(let [na b
nb (+ a b)]
[na nb]))
user=> (next-fib [1 2])
[2 3]
would produce a function next-fib that would return the next 2 values from your input. During the function, a and b cannot be changed, they are immutable, hence assignment to new values.
Here, i'm using destructuring to immediately break the elements of the input vector into values a and b, which are then used to calculate the next element, and is the same as how the 1 liner at the top of my answer works.
Or if you're doing looping, you can recur with values that get substitute over their previous iteration, this is not changing a and b (during any iteration their values are fixed and still immutable), but redoing the entire stack with new values in their place, subtle difference. See articles on tail recursion.
user=> (loop [a 1 b 1]
(if (< a 20)
(recur b (+ a b))
[a b]))
[21 34]
Here's a simple version of the Fibonacci Sequence using recur, it returns the first n numbers.
(defn fib-recur [n]
(loop [fib [] x n a 0 b 1]
(if (zero? x)
fib
(recur (conj fib b) (dec x) b (+ a b)))))
It works by starting with an empty array of numbers it's building, then recurs by decrementing the counter (x) from n to 0, each iteration changes a and b to be new values as part of the recursion, and it adds the latest number to the array fib returning that when the counter gets to zero.
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)
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)