Scheme: Making a list of sublist maxes - list

Given a list, each item of which is an (r g b) color, return a list consisting of the
maximum component in each color.
Example: given ((123 200 6) (10 30 20) (212 255 10) (0 0 39) (37 34 34)),
code should return (200 30 255 39 37)

(define (sublist-max list-of-lists)
(map (lambda (sublist) (apply max sublist)) list-of-lists))

Related

LISP - sequence of integers

Does exist a function in LISP for making a sequence of integers like (0 1 2 3)?
I found make-sequence, but I didn't find out how to make a sequence of integers.
I tried make-list and nothing.
I know that in Scheme exists (build-list 5 (lambda (x) x)). I tried to change the build-list with make-list, but it didn't work.
Some ideas? Thanks
Edit: I need something like make-list 5 ==> (0 1 2 3 4)
Simply done with loop:
(loop :for n :below 10 :collect n)
; ==> (0 1 2 3 4 5 6 7 8 9)
The Alexandria library, which is intended to work on any conforming implementation of Common Lisp, defines iota:
(iota 5)
=> (0 1 2 3 4)
You can also customize start and step:
(iota 3 :start 1 :step 1.0)
=> (1.0 2.0 3.0)
But often you do not need to actually produce the list, you just want to iterate over the given range. That's why there is also map-iota:
(map-iota #'print 3 :start 1 :step 1.0)
=> 3
In such cases you can of course use LOOP:
(loop for i from 1.0 below 22 by 1.5 do (print i))
Instead of do, you can also collect and obtain a list; this is a bit more verbose than iota, but easier to customize.
Lets see if can still write mac lisp of the top of my head:
(defun foo (num acc)
(if (eq num 0)
acc
(foo (- num 1) (cons num acc))))
(foo 5 nil)
should be
(1 2 3 4 5)

Appending list in lisp

In lisp, I am appending lists as:
(setq newlist (append (side a b)(this a b) (that a b) ))
This appends all the required list as: (1 0 0 0 2 0 4 0 6 0)
but what I want is something like this: ((1 0)(0 0)(2 0)(4 0)(6 0))
What should I do to get the required format. Please post code examples in lisp.
So in fact you just need to restructure the elements after you have appended it:
(loop :for (e1 e2)
:on '(1 0 0 0 2 0 4 0 6 0)
:by #'cddr
:collect (list e1 e2))
; ==> ((1 0) (0 0) (2 0) (4 0) (6 0))
Suggested reading is LOOP for black belts, the section you should pay attention to which I've used here is "Looping Over Collections and Packages" and "Destructuring Variables". This is probably the chapter from Practical Common Lisp I read the most. The whole book is very good so every lisper should know about it.

Clojure reducers fold not calling combine function as expected

I'm experimenting with the clojure reducers library, and I'm a little confused as to when the combining function is called as part of the reducers/fold function. To see what was being called when, I created the below example:
(def input (range 1 100))
(defn combine-f
([]
(println "identity-combine")
0)
([left right]
(println (str "combine " left " " right))
(max (reduce max 0 left)
(reduce max 0 right))))
(defn reduce-f
([]
(println "identity-reduce")
0)
([result input]
(println (str "reduce " result " " input))
(max result input)))
(clojure.core.reducers/fold 10 combine-f reduce-f input)
;prints
identity-combine
reduce 0 1
reduce 1 2
reduce 2 3
reduce 3 4
.
.
.
reduce 98 99
I was expecting that when fold executes, the input would be partitioned into groups of approximately size 10, with each group reduced using reduce-f, and then combined using combine-f. However running the above code, it seems that the combine function is only called once as an identity, and the entire input reduced using reduce-f. Can anyone explain why I'm seeing this behaviour?
Thanks,
Matt.
Unfortunately, range cannot at the moment be realized in parallel. It seems there are foldable implementations around as an enhancement ticket, but I can't seem to find right now why they haven't been accepted. As is, folds over a range will always proceed like a straight reduce, except for the identity call to the combine operator. For comparison, a vector provides random access and so is foldable:
(def input (vec (range 1 50)))
(defn combine-f
([]
(println "identity-combine")
Long/MIN_VALUE)
([left right]
(println (str "combine " left " " right))
(max left right)))
(defn reduce-f
([]
(println "identity-reduce")
Long/MIN_VALUE)
([result input]
(println (str "reduce " result " " input))
(max result input)))
(clojure.core.reducers/fold 10 combine-f reduce-f input)
with output:
identity-combineidentity-combineidentity-combine
reduce -9223372036854775808 1
reduce -9223372036854775808 25reduce -9223372036854775808 19
reduce -9223372036854775808 13reduce 25 26
reduce 26 27
reduce 1 2
reduce 27 28
reduce 28 29
reduce 29 30
reduce 2 3
reduce 19 20
reduce 3 4
identity-combinereduce 4 5
reduce 5 6reduce 13 14
reduce 14 15
reduce 20 21identity-combine
reduce 21 22
reduce 15 16
reduce -9223372036854775808 31
reduce 22 23reduce 16 17reduce -9223372036854775808 7
reduce 7 8
reduce 8 9
reduce 23 24
reduce 31 32
reduce 17 18
reduce 9 10
reduce 10 11
reduce 11 12
identity-combine
reduce 32 33
combine 18 24
combine 6 12identity-combine
reduce -9223372036854775808 37
reduce 33 34
reduce 37 38reduce -9223372036854775808 43
combine 12 24
reduce 43 44reduce 34 35reduce 38 39
reduce 44 45
reduce 35 36
reduce 45 46
reduce 39 40
reduce 46 47
combine 30 36
reduce 47 48
reduce 48 49
reduce 40 41
reduce 41 42
combine 42 49
combine 36 49
combine 24 49
which you may notice is a lot more jumbled because of non-serialized accessing of *out*.
(I needed to alter combine-f a little because it was trying and failing to reduce over a single long. Switching to Long/MIN_VALUE doesn't affect this example much but is the identity element of max over longs, so I figured why not?).

How to make a cumulative sequence?

Say I have a lazy sequence like the following:
(def s (iterate inc 1))
(take 10 s)
=> (1 2 3 4 5 6 7 8 9 10)
Now, I want to generate a sequence of cumulative sum of s like the following:
=> (1 3 6 10 15 ...)
How can I do this?
What I tried is to use atom and accumulate the sum to it(mutating) Is this the only way to generate cumulative sequence or is there a better way to do this?
NOTE: the above cumulative sum is only an example. The source sequence can be other sequence. So I can't use formula: s(n) = n(n+1)/2
(take 10 (reductions + s))
=> (1 3 6 10 15 21 28 36 45 55)

Generate truth table for n operators

I've been tasked with writing a function that generates a table given n operators. The truth table must be in a list and each row of the table must be in separate lists (inside the main list).
I know the solution involves recursion but I just can't seem to think it through.
Can someone help me out? This is only a small part of the assignment.
Easiest way I can think of off the top of my head is to simply convert 2^n to binary and count down, then convert the output to a list.
ie for n=3:
Truth table:
a b c
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
2^3 = 8, 8 in binary = 1000, start from 1000-1 = 111 and work your way down to 0, record outputs, and voila!
If hkf's interpretation of your question is right, this should work in Racket:
#lang racket
(define (generate-table n)
(if (zero? n)
'(())
(for*/list ((y (in-list (generate-table (sub1 n))))
(x (in-list '(0 1))))
(cons x y))))
Use it like this:
(generate-table 3)
> ((0 0 0) (1 0 0) (0 1 0) (1 1 0) (0 0 1) (1 0 1) (0 1 1) (1 1 1))
Let's assume that all N operators are binary functions, like AND and OR.
;; Common Lisp
(defun truth-tables (ops)
(loop for op in ops
collecting
(loop for args in '((nil nil) (nil t) (t nil) (t t))
collecting (eval `(,op ,#args)))))
(truth-tables '(and or xor)) -> ((NIL NIL NIL T) (NIL T T T) (NIL T T NIL))
This gives you an idea. Well, here I don't have "each row of the truth table" as a sublist; I have the columns for the AND, OR and XOR truth tables, respectively. The input variable combinations are left implicit: you know that the third entry of every one corresponds to (<op> t nil). Your description of the problem is not very clear.
As you can also see, I cheated by using the Lisp operators through generated code which is dynamically evaluated.