Build-list within build-list Scheme/DrRacket - list

Trying to make a list that has n elements with each of those lists having r elements. i.e.
(function 2 3) would be (list (list 0 0 0)(list 0 1 2)). And those elements are made by multiplying the nth element by the rth element starting at 0. This is my code:
(define (nr nc)
(build-list nr (lambda (x)
(build-list nc (lambda (x) (* x 1))))))
so I have (function 2 3) coming out to (list (list 0 1 2)(list 0 1 2)) and I can't figure out how to multiply the first list by 0, the second by 1, third by 2, and so on.

You were close:
(define (build nr nc)
(build-list nr (lambda (r)
(build-list nc (lambda (c) (* r c))))))
> (build 2 3)
'((0 0 0) (0 1 2))
> (build 3 3)
'((0 0 0) (0 1 2) (0 2 4))
An alternative:
(define (build2 nr nc)
(for/list ([r nr])
(for/list ([c nc])
(* r c))))

(define (range n)
(define (range-iter i accum)
(if (= i 0) (cons 0 accum)
(range-iter (- i 1) (cons i accum))))
(range-iter (- n 1) `()))
(define (nested-list n r)
(map
(lambda (multiplier)
(map
(lambda (cell) (* cell multiplier))
(range r)))
(range n)))

Related

Insert a new element at the N-th position of a list

Is it possible to insert a new element at the N-th position of a list without conj?
defn insert-at [x xs n]
(let [[before after] (my-drop xs (dec n))]
(if (empty? after)
(if (= (count before) (dec n))
(concat before (replicate 1 x))
before)
(concat before (conj after x)))))
Use split-at and insert new element between two halves of list:
(defn list-insert [lst elem index]
(let [[l r] (split-at index lst)]
(concat l [elem] r)))
Examples:
(list-insert '(1 2 3 4 5) 0 0)
=> (0 1 2 3 4 5)
(list-insert '(1 2 3 4 5) 1 1)
=> (1 1 2 3 4 5)

Duplicate n times an element from a list in Racket

for example:
(duplicate 3 (list 1 2 3)) = (list 1 1 1 2 2 2 3 3 3)
i tried this:
(define (duplicate n l)
(cond [(zero? n) empty]
[else (cons l (duplicate (sub1 n) l))]))
but it gives me:
(duplicate 2 (list 1 2)) = (list (list 1 2) (list 1 2))
You are actually half way. What you have created is something that takes one element and a count and makes a list of that many elements.
(duplicate 3 'e) ; ==> (3 3 3)
That means that you can use that:
(duplicate-list 3 l)
; ==> (append (duplicate 3 (car l))
; (duplicate-list 3 (cdr l)))
(define (duplicate n x)
"Repeat x n times."
(cond [(zero? n) empty]
[else (cons x (duplicate (sub1 n) x))]))
(define (mappend fn . lists)
"map but appending the results."
(apply append (apply map fn lists)))
(define (duplicate-list n l)
"duplicate each element in l."
(mappend (lambda (x) (duplicate n x)) l))
Then
(duplicate-list 3 (list 1 2 3))
;; '(1 1 1 2 2 2 3 3 3)

Adding a single element onto a list until a certain point

I want to make a function that given a list and a natural number, adds zeros onto the list so the length of the list equals the natural number. What is an efficient way of doing this so instead of making every element zero, it does what it's supposed to do
(define (zero-list loz alon)
(cond
[(empty? loz) empty]
[(= (-(length loz) 1) alon) (cons 0 loz)]
[else (cons 0 (zero-list (rest loz)))]))
Example:
(zero-list (list 1 2 3) 5)) -> (list 0 0) so (length (list 1 2 3)) + (length (list 0 0)) = 5
Use make-list to generate a list that has the appropriate number of 0s (i.e. difference between the number and the length of the input list):
(define (zero-list l n)
(make-list (- n (length l)) 0))
(zero-list (list 1 2 3) 5) ; -> (list 0 0)

Adding values to a list in a sort of "overlapped" way

I'll explain in math, here's the transformation I'm struggling to write Scheme code for:
(f '(a b c) '(d e f)) = '(ad (+ bd ae) (+ cd be af) (+ ce bf) cf)
Where two letters together like ad means (* a d).
I'm trying to write it in a purely functional manner, but I'm struggling to see how. Any suggestions would be greatly appreciated.
Here are some examples:
(1mul '(0 1) '(0 1)) = '(0 0 1)
(1mul '(1 2 3) '(1 1)) = '(1 3 5 3)
(1mul '(1 2 3) '(1 2)) = '(1 4 7 6)
(1mul '(1 2 3) '(2 1)) = '(2 5 8 3)
(1mul '(1 2 3) '(2 2)) = '(2 6 10 6)
(1mul '(5 5 5) '(1 1)) = '(5 10 10 5)
(1mul '(0 0 1) '(2 5)) = '(0 0 2 5)
(1mul '(1 1 2 3) '(2 5)) = '(2 7 9 16 15)
So, the pattern is like what I posted at the beginning:
Multiply the first number in the list by every number in the second list (ad, ae, af) and then continue along, (bd, be, bf, cd, ce, cf) and arrange the numbers "somehow" to add the corresponding values. The reason I call it overlapping is because you can sort of visualize it like this:
(list
aa'
(+ ba' ab')
(+ ca' bb' ac')
(+ cb' bc')
cc')
Again,
(f '(a b c) '(d e f)) = '(ad (+ bd ae) (+ cd be af) (+ ce bf) cf)
However, not just for 3x3 lists, for any sized lists.
Here's my code. It's in racket
#lang racket
(define (drop n xs)
(cond [(<= n 0) xs]
[(empty? xs) '()]
[else (drop (sub1 n) (rest xs))]))
(define (take n xs)
(cond [(<= n 0) '()]
[(empty? xs) '()]
[else (cons (first xs) (take (sub1 n) (rest xs)))]))
(define (mult as bs)
(define (*- a b)
(list '* a b))
(define degree (length as))
(append
(for/list ([i (in-range 1 (+ 1 degree))])
(cons '+ (map *- (take i as) (reverse (take i bs)))))
(for/list ([i (in-range 1 degree)])
(cons '+ (map *- (drop i as) (reverse (drop i bs)))))))
The for/lists are just ways of mapping over a list of numbers and collecting the result in a list. If you need, I can reformulate it just maps.
Is this a good candidate for recursion? Not sure, but here's a
a direct translation of what you asked for.
(define (f abc def)
(let ((a (car abc)) (b (cadr abc)) (c (caddr abc))
(d (car def)) (e (cadr def)) (f (caddr def)))
(list (* a d)
(+ (* b d) (* a e))
(+ (* c d) (* b e) (* a f))
(+ (* c e) (* b f))
(* c f))))
Is it correct to assume, that you want to do this computation?
(a+b+c)*(d+e+f) = a(d+e+f) + b(d+e+f) + c(d+e+f)
= ad+ae+af + bd+be+bf + cd+ce+cf
If so, this is simple:
(define (f xs ys)
(* (apply + xs) (apply + ys))
If you are interested in the symbolic version:
#lang racket
(define (f xs ys)
(define (fx x)
(define (fxy y)
(list '* x y))
(cons '+ (map fxy ys)))
(cons '+ (map fx xs)))
And here is a test:
> (f '(a b c) '(d e f))
'(+ (+ (* a d) (* a e) (* a f))
(+ (* b d) (* b e) (* b f))
(+ (* c d) (* c e) (* c f)))

Building a 2D List

Looking for a function that would do something akin to the following:
(foo 3 2) => '( ( (1 1) (1 2) (1 3) )
( (2 1) (2 2) (2 3) ) )
Would there be any built-in function in DrRacket that accomplishes that?
The main tool that you want to use to get such things in Racket is the various for loops. Assuming that you want to create a list-based matrix structure, then this is one way to get it:
#lang racket
(define (foo x y)
(for/list ([i y])
(for/list ([j x])
(list (add1 i) (add1 j)))))
And since people raised the more general question of how to make foo create a matrix of any dimension, here's a generalized version that works with any number of arguments, and still returns the same result when called as (foo 3 2):
#lang racket
(define (foo . xs)
(let loop ([xs (reverse xs)] [r '()])
(if (null? xs)
(reverse r)
(for/list ([i (car xs)])
(loop (cdr xs) (cons (add1 i) r))))))
(Note BTW that in both cases I went with a simple 0-based iteration, and used add1 to get the numbers you want. An alternative way would be to replace
(for/list ([i x]) ... (add1 i) ...)
with
(for/list ([i (in-range 1 (add1 x)]) ... i ...)
)
Code:
(define (foo-makey const max data)
(let* ((i (length data))
(newy (- max i))
(newpair (cons const newy)))
(if (= max i)
data
(foo-makey const max
(cons newpair data)))))
(define (foo-makex xmax ymax data)
(let* ((i (length data))
(newx (- xmax i)))
(if (= xmax i)
data
(foo-makex xmax ymax
(cons (foo-makey newx ymax '()) data)))))
(define (foo x y)
(foo-makex y x '()))
Output:
> (foo 3 2)
'(((1 . 1) (1 . 2) (1 . 3)) ((2 . 1) (2 . 2) (2 . 3)))
I can't answer your question as-is because I don't understand how the nested lists should work for >2 arguments. AFAIK there is no built-in function to do what you want.
To start you off, here is some code that generates output without nested lists. As an exercise try adjusting the code to do the nested listing. And see if there's a way you can make the code more efficient.
;;can take in any number of arguments
(define (permutations . nums)
(foldl
(lambda (current-num acc)
(append-map
(lambda (list-in-acc)
(for/list ((i (build-list current-num (curry + 1))))
(append list-in-acc (list i))))
acc))
(list (list))
(reverse nums)))
Example 1:
> (permutations 3 2)
'((1 1) (1 2) (1 3) (2 1) (2 2) (2 3))
Example 2:
> (permutations 10)
'((1) (2) (3) (4) (5) (6) (7) (8) (9) (10))
Example 3:
> (permutations 2 3 4)
'((1 1 1)
(1 1 2)
(1 2 1)
(1 2 2)
(1 3 1)
(1 3 2)
(2 1 1)
(2 1 2)
(2 2 1)
(2 2 2)
(2 3 1)
(2 3 2)
(3 1 1)
(3 1 2)
(3 2 1)
(3 2 2)
(3 3 1)
(3 3 2)
(4 1 1)
(4 1 2)
(4 2 1)
(4 2 2)
(4 3 1)
(4 3 2))
(define (build-2d row col)
(build-list row (lambda(x) (build-list col (lambda(y) (list (+ x 1) (+ y 1))))))