Pascal's Triangle with a Twist - scheme

Say we want to generate Pascal's Triangle within Scheme, but with a twist. For the function (pascal left right depth), where left is the number on the left side of the triangle and right is the number on the right. For example a call of (pascal 1 1 5) would return
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
and a call to (pascal 1 2 5) would return
1
1 2
1 3 2
1 4 5 2
1 5 9 7 2
1 6 14 16 9 2
How would you print the triangle out so that it is spaced like the examples?
My code so far is as follows but all this does is return which number should be at which location within the standard triangle.
(define (pascal x y)
(cond ((or (<= x 0) (<= y 0) (< x y)) 0)
((or (= 1 y) (= x y)) 1)
(else (+ (pascal (- x 1) y) (pascal (- x 1) (- y 1))))))

Add a decreasing number of spaces to the start of each line. Determine the number from the length of the last line and the length of the current line to be printed.

Related

Is there a way of summing two vectors with different lengths in Scheme?

Am a beginner to Scheme a dialect of Lisp, am trying to implement a function sum-vector that takes two vectors of numbers as arguments and returns a vector with the sum of the corresponding elements of the input vectors.
I have tried the following code but i can't figure out how to sum two vectors with different lengths.
Here is my current code
#lang scheme
(define sum-vector
(lambda (vec-1 vec-2)
(let* ((len (vector-length vec-1))
(result (make-vector len)))
(do ((index 0 (+ index 1)))
((= index len) result)
(vector-set! result index
(+ (vector-ref vec-1 index)
(vector-ref vec-2 index)))))))
(sum-vector (vector 4 6 8 3) (vector 5 6 7))
When i run the above code it works perfectly for vectors with same lengths e.g (sum-vector (vector 4 6 8) (vector 5 6 7)) returns #(9 12 15) I want it to work similarly for different lengths e.g (sum-vector (vector 4 6 8 3) (vector 5 6 7)) should return #(9 11 15 3) but i can't figure out the logic for doing that.
One possible solution is to append zeros to each vector to make their lengths equal and then use vector-map:
(define (zero-vector len)
(make-vector len 0))
(define (append-zeros vec max-len)
(vector-append vec (zero-vector (- max-len (vector-length vec)))))
(define (sum-vector v1 v2)
(let ((max-len (max (vector-length v1)
(vector-length v2))))
(vector-map +
(append-zeros v1 max-len)
(append-zeros v2 max-len))))
Tests:
> (sum-vector (vector 1 2 3) (vector 1 2 3 4 5 6))
'#(2 4 6 4 5 6)
> (sum-vector (vector) (vector 1 2 3 4 5 6 7 8))
'#(1 2 3 4 5 6 7 8)
Another, Racket-specific way.
Racket has something called comprehensions, which allow for easy iteration over containers. In particular, for/vector returns a vector of the results:
> (define v1 (vector 4 6 8 3))
> (define v2 (vector 5 6 7))
> (for/vector ([e1 v1] [e2 v2]) (+ e1 e2))
'#(9 12 15)
Note that the resulting vector is the length of the shortest container being iterated over. You can tell it to produce a vector of a given length, though:
> (for/vector #:length (vector-length v1) ([e1 v1] [e2 v2]) (+ e1 e2))
'#(9 12 15 0)
It fills in the extra elements with 0. Combine that with vector-copy!, which copies a range of elements from one vector to another at given offsets to copy the extra elements from the larger vector to the smaller (Or do nothing if they're the same length), and you get:
(define (sum-vector v1 v2)
(let ([sum-helper
(lambda (short long)
(let ([result (for/vector #:length (vector-length long)
([e1 short] [e2 long])
(+ e1 e2))])
(vector-copy! result (vector-length short)
long (vector-length short) (vector-length long))
result))])
(if (< (vector-length v1) (vector-length v2))
(sum-helper v1 v2)
(sum-helper v2 v1))))
Examples:
> (sum-vector (vector 4 6 8 3) (vector 5 6 7))
'#(9 12 15 3)
> (sum-vector (vector 1 2 3) (vector 1 2 3 4 5 6))
'#(2 4 6 4 5 6)
> (sum-vector (vector) (vector 1 2 3 4 5 6 7 8))
'#(1 2 3 4 5 6 7 8)

Is there a way to make this print without a list inside a list?

I am writing a scheme program in dr racket that takes a list of numbers representing a matrix sets an item in the list to the number given. So far it works for case row 1 column 1 and knows where to place the number but any other case it makes lists of lists. I have attempted to make a function to help but still receive the same error. Any help would be greatly appreciated.
The error I'm getting:
(setCell Matrix 2 2 9)
((2 4 6 8) (1 (9 5 7)) (2 9 0 1))
I need
(setCell Matrix 2 2 9)
((2 4 6 8) (1 9 5 7) (2 9 0 1))
Any help would be greatly appreciated.
(define Matrix '(( 2 4 6 8 )( 1 3 5 7)( 2 9 0 1)))
;getCell Matrix Row Column
;if i want row 2 col 2
(define (getCell Matrix Row Column)
(if (= Row 1)
(if (= Column 1)
(car (car Matrix))
(getCell (cons (cdr (car Matrix)) ()) Row (- Column 1))
)
(getCell (cdr Matrix) (- Row 1) Column)
)
)
;> (getCell Matrix 1 1)
;2
;(define Matrix '(( 2 4 6 8 )( 1 3 5 7)( 2 9 0 1)))
;setCell Matrix Row Column Item
(define (setCell Matrix Row Column Item)
(if (= Row 1)
(if (= Column 1)
(helpMe Matrix Item)
(cons
(cons (car (car Matrix))
(setCell (cons (cdr (car Matrix)) ()) Row (- Column 1) Item))
(cdr Matrix))
)
(cons (car Matrix) (setCell (cdr Matrix) (- Row 1) Column Item))
)
)
(define (helpMe Matrix Item)
(cons (cons Item (cdr (car Matrix))) (cdr Matrix)))
;ERROR:
;>(setCell Matrix 2 2 9)
;((2 4 6 8) (1 (9 5 7)) (2 9 0 1))
;> (setCell Matrix 1 1 9)
;((9 4 6 8) (1 3 5 7) (2 9 0 1))
This is a common problem.
The basic idea is coordinate, data structure shape, make a good abstraction, visting all element, given coordinate get corresponding value.
In here we define upper left element is (1,1) (so we have to minus 1)
First we want build a same matrix. Second each value determine by function f. And f input is coordinate (i,j) so f is a function call upgrade function. You can set any rule. Like a common question is ask you build diagonal matrix the rule will be i=j. (It a beautiful abstraction)
It's means we must make this coordinate
(0,0) (0,1) (0,2) ... (0,(length (first m))
(1,0) (1,1) (1,2) ... (1,(length (first m))
(2,0 ...
...
(length of matrix),0) ... ((length of matrix),(length (first m)))
Then we send coordinate to f. So we can let f return original value in input matrix but when i = row and j = column we return new value (item). The same idea you can build vector or orthers not just list. The same idea can use to build triangle circle or something else not just rectangle.
#lang racket
(define (setCell m row column item)
(local ((define index-i (- row 1))
(define index-j (- column 1))
(define (f i j)
(if (and (= i index-i) (= j index-j))
item
(list-ref (list-ref m i) j))))
(build-list (length m) (lambda (i) (build-list (length (first m)) (lambda (j) (f i j)))))))
;;; TEST
(define k
'((1 2 3)
(1 2 3)
(1 2 3)))
(setCell k 1 1 100)
(setCell k 2 3 100)
(define k2
'((1 2 3)
(1 2 3)))
(setCell k2 1 3 100)
(setCell k2 2 3 100)
I am writing a scheme program in dr racket that takes a list of numbers representing a matrix sets an item in the list to the number given.
#lang racket
(define matrix-id (build-list 4 (λ (x) (build-list 4 (λ (y) (if (= x y) 1 2))))))
;; => '((1 0 0 0) (0 1 0 0) (0 0 1 0) (0 0 0 1))
;; [X] Number Number X [List-of [Lis-of X]] -> [List-of [Lis-of X]]
(define (set-mat row col item mat)
(for/list ([l mat] [i (length mat)])
(for/list ([e l] [j (length l)])
(if (and (= i row) (= j col))
item
e))))
(set-mat 1 1 'fef matrix-id)
;; => '((1 0 0 0) (0 fef 0 0) (0 0 1 0) (0 0 0 1))

Recursive Pascal in Scheme - Unable to find the correct algorithm

(define (pascal x y)
(cond ((or (<= x 0) (<= y 0) (< x y )) 0)
((or (= 1 y) (= x y) ) 1)
(else (+ (pascal (- x 1) y) (pascal (- x 1) (- y 1))))))
This is the function I have for a recursive pascal call that should return the number given the x and y of the triangle.
1
11
121
1331
14641
If I enter pascal 0 0, it should return 1, however it returns 0;
If I enter pascal 4 2, it should return 6, but it returns 3;
Seems like my base is off but I'm not sure how I can change it without ruining the calculation for pascals algorithm. Could someone point me to the right direction
You are very close, but your conditions aren't quite doing what you think they are. You have something like an off-by-1 error, and you haven't properly split apart your cond cases.
#lang racket/base
(for ((x (in-range 1 6)))
(for ((y (in-range (add1 x))))
(printf "~a " (pascal x y)))
(newline))
0 1
0 1 1
0 1 2 1
0 1 3 3 1
0 1 4 6 4 1
I make some small changes to your conditions and get this output:
(for ((x (in-range 6)))
(for ((y (in-range (add1 x))))
(printf "~a " (pascal x y)))
(newline))
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
If this doesn't help I can edit later and put the solution in, but this smells like homework and I don't want to just post a solution.

how to divide a vector by 4 in scheme

I have a vector list (3 6 8 2 ) and want to divide each element of the vector by 4 and return the vector
ex:- (div4 #(3 6 8 2))
'#(3/4 6/4 8/4 2/4)
You can use vector-map to apply a procedure to every element of a vector, as:
(define (div4 vec)
(vector-map (lambda (x) (/ x 4)) vec))
For example,
> (div4 #(4 8 12 16))
'#(1 2 3 4)

Turn list of list into image

Okay, so I am trying to turn a list of a list of numbers into an image where each number represents a block with a color assigned to that number. For example:
(define allig
'((1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
(1 1 1 1 1 1 1 2 2 2 2 1 1 1 1 1 1 1 1)
(1 1 1 1 1 1 2 4 5 5 5 2 1 1 1 2 2 1 1)
(1 1 1 1 2 2 2 5 5 3 2 5 2 2 2 5 5 2 1)
(1 1 2 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 2)
(2 2 5 5 2 5 4 5 5 2 3 2 3 2 3 2 3 2 1)
(5 5 5 5 5 5 5 5 2 1 2 1 2 1 2 1 2 1 1)
(4 5 2 5 4 5 2 5 2 1 1 1 1 1 1 1 1 1 1)
(5 5 5 5 5 5 5 5 2 1 1 1 1 1 1 1 1 1 1)
(2 5 4 5 2 5 4 5 5 2 1 2 1 2 1 2 1 2 1)
(5 5 5 5 5 5 5 5 5 5 2 3 2 3 2 3 2 3 2)
(5 5 2 2 2 2 2 2 5 5 5 5 5 5 5 5 5 5 2)
(5 5 2 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1)
(5 5 5 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
(2 5 5 5 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
(1 2 5 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
(1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
))
I want to turn it into this:
(paint-picture allig palette 10)
where 10 is the size of the squares that make up the image, palette is the color assigned to each number (ie 1 is "blue" in this picture), and allig is the list of list of numbers.
So far I have a way to get the colors, make the first column, and repeat the column over and over to make a picture Col x Row big. My problem is that I don't know how to get each consecutive column, only the first.
I'm pretty much done with this, I'm just stuck on this last part so any help would be great.
Here's what I have:
(define (make-column painting)
(cond
[(zero? (length painting)) (square 0 "solid" "red")]
[else (above (square 30 "solid"
(get-color (first (first painting)) pal))
(make-column (rest painting)))]))
;puts images side by side to make a row
(define (make-row n img1 img2)
(cond
[(zero? n ) (square 0 "solid" "red")]
[else (beside img1 (make-row (sub1 n) img2 img1))]))
;makes a row of columns, I'm stuck as to how to make it recursive
; to get the next column since it is a list of a list
(define (paint-picture painting)
(cond
[(zero? (length painting) ) (square 0 "solid" "red")]
[else (make-row (length (first painting))
(make-column painting)
; this should be the recursive next col part (paint-picture painting))]))
(define pal (list "blue" "dark gray" "white" "green" "dark green"))
(define (get-color n colors) (list-ref colors (- n 1)))
Here is a set of functions that implement what you're looking for in plain ISL with no global state whatsoever.
; (a b -> c) a -> (b -> c)
(define (partial f x)
(let ([g (lambda (y) (f x y))])
g))
; (listof string?) integer? -> image?
(define (pixel palette c)
(let ([color (list-ref palette (sub1 c))])
(square 1 "solid" color)))
; (listof string?) (listof integer?) -> image?
(define (row->image palette lst)
(let* ([pixel/palette (partial pixel palette)]
[pixels (map pixel/palette lst)])
(apply beside pixels)))
; (listof string?) (listof (listof integer?)) -> image?
(define (matrix->image palette lst)
(let* ([row/palette->image (partial row->image palette)]
[rows (map row/palette->image lst)])
(apply above rows)))
; (listof (listof integer?)) (listof string?) integer? -> image?
(define (paint-picture matrix palette size)
(scale size (matrix->image palette matrix)))
The tricky bit is the partial function, which implements partial function application for binary functions (i.e. functions with arity 2) in plain ISL. I'm not sure if this is supposed to work in ISL, but it does. Maybe it's a bug, haha?
A straight-forward version without any higher order functions or any bells and whistles at all - very beginner-level, I hope:
It's most common to recurse on the lists' structure, not their size, so we'll do that.
This can seem uncomfortable at first if you're used to writing for-loops, but most of the time the exact length of a list is irrelevant in Racket - you only care about whether it's empty or not.
First, a readability helper:
(define nothing (square 0 "solid" "red"))
Going through the "picture" row by row, we either have the empty list or we don't.
If it's empty, paint nothing.
Otherwise, paint the first row above the rest of the picture:
(define (paint-picture painting)
(if (empty? painting)
nothing
(above (paint-row (first painting))
(paint-picture (rest painting)))))
Next, we need to paint a row.
This also has two cases:
If it's the empty list, paint nothing.
Otherwise, paint the first pixel beside the rest of the row:
(define (paint-row row)
(if (empty? row)
nothing
(beside (square 30 "solid" (get-color (first row) pal))
(paint-row (rest row)))))
And that's it.
This works in #lang racket.
(define pal '(Transparent Blue DarkGray White Green DarkGreen))
(apply above (map (lambda (row)
(apply beside (map (lambda (col)
(square 4 'solid (list-ref pal col)))
row)))
allig))
(Notice that I added Transparent to the front of pal so that I don't have to shift the index by 1.)
It also works for #lang htdp/isl+ (but for some reason, it shows the struct instead of displaying the image directly). Of course, the reason why Alexis King was asking whether you were using ISL+ vs plain ISL is that the lambda expressions I used above are forbidden in plain ISL.
Here's a version that works in plain ISL:
(define pal '(Transparent Blue DarkGray White Green DarkGreen))
(define (make-pixel col)
(square 4 'solid (list-ref pal col)))
(define (make-row row)
(apply beside (map make-pixel row)))
(apply above (map make-row allig))

Resources