Foldr and Foldl in DrRacket - scheme

I can see how it does it on
(foldl * 1 '(1 2 3 4 5)) == 120
(foldr * 1 '(1 2 3 4 5)) == 120
but I can't figure out how it gets 2 for
(foldl - 1 '(1 2 3 4 5)) == 2
I would've thought (foldl - 1 '(1 2 3 4 5)) would be ((((1-1)-2)-3)-4)-5), a negative number. What did I miss?
I can tho see why
(foldl + 1 '(1 2 3 4 5)) == 16

(foldl - 1 '(1 2 3 4 5)) is actually equivalent to (- 5 (- 4 (- 3 (- 2 (- 1 1))))), or, in infix, 5 - (4 - (3 - (2 - (1 - 1)))).
Likewise, (foldr - 1 '(1 2 3 4 5)) is actually equivalent to (- 1 (- 2 (- 3 (- 4 (- 5 1))))), or, in infix, 1 - (2 - (3 - (4 - (5 - 1)))).

Related

how can i append to a list without creating a dotted pair

how do i append (1 2 3) to the end of () to make ((1 2 3))
how do i append (4 5 6) to the end of that to make ((1 2 3) (4 5 6))
how do i append "|" to the end of that to make ((1 2 3) (4 5 6) "|")
with NO dotted pairs.
I'm working with Chicken Scheme but I'll take an answer from any scheme at this point. Note that any of these lists could also be nested lists of who knows what... i'm just writing a trivial example.
note: #sjamaan shows a solution using append that involves wrapping everything in another list to compensate for append doing things OTHER than what the name says.
(append (list 1 2 3) "|" ) ;=> (1 2 3 . "|")
;^^ didn't actually append, created a dotted pair
(append '(1 2 3) (list 4 5 6)) ;=> (1 2 3 4 5 6) ; don't want unwrapped list
;^^ didn't actually append the list i gave it but appended the contents of the list.
Basically I'm hoping for an append method that actually appends what you give it, not appends the contents of it, or takes it and makes a dotted pair. Maybe i'm just a dreamer... I can write a "no really append" method that just takes whatever params you give it and wraps them in an outer list to compensate but that's just silly... Surely scheme has some way to append without this crazyness.
Here is how append is made:
(define (append2 lst1 lst2)
(if (null? lst1)
lst2 ; the second list is unaltered
(cons (car lst1)
(append2 (cdr lst1) lst2))))
makes a pair chain consisting of all the elements in lst1 and lst2. It does not make a pair where there is nont in lst2 so:
(append2 '(1 2 3) '(4 5)) ; ==> (1 2 3 4 5)
(append2 '(1 2 3) '()) ; ==> (1 2 3) and not (1 2 3 ())
(append2 '(1 2 3) '5) ; ==> (1 2 3 . 5)
Note that every list like (1 2 3) actually is (1 2 3 . ()) or even more correctly (1 . (2 . (3 . ())))
how do i append (1 2 3) to the end of () to make ((1 2 3))
(define (insert-last e lst)
(let helper ((lst lst))
(if (pair? lst)
(cons (car lst)
(helper (cdr lst)))
(cons e '()))))
(insert-last '(1 2 3) '())
; ==> ((1 2 3))
how do i append (4 5 6) to the end of that to make ((1 2 3) (4 5
6))
(insert-last '(4 5 6) '((1 2 3)))
; ==> ((1 2 3) (4 5 6))
how do i append "|" to the end of that to make ((1 2 3) (4 5 6)
"|")
(insert-last "|" '((1 2 3) (4 5 6)))
; ==> ((1 2 3) (4 5 6) "|")
Know that this is very much like append. These are the worst way to make that list since you are making a new list every time. It's O(n) for each insert and O(n^2) for n elements. If you could do this in reverse order you get something that do this O(1) instead of O(n) for each insert. Instead of insert-last you use cons:
(cons '"|" '()) ; ==> ("|")
(cons '(4 5 6) '("|")) ; ==> ((4 5 6) "|")
(cons '(1 2 3) '((4 5 6) "|") ; ==> ((1 2 3) (4 5 6) "|")
This is O(1), O(n) for n elements processed. If you need to do it in the original order you can accumulate, then reverse..
(cons '(1 2 3) '()) ; ==> ((1 2 3))
(cons '(4 5 6) '((1 2 3))) ; ==> ((4 5 6) (1 2 3))
(cons '"|" '((4 5 6) (1 2 3))) ; ==> ("|" (4 5 6) (1 2 3))
(reverse '("|" (4 5 6) (1 2 3)) ; ==> ((1 2 3) (4 5 6) "|")
This is O(1), then O(n) for the reverse but it still is O(1) amortized. O(n) for n elements you process.
append doesn't append atoms to lists. It concatenates lists. You have to lift the atom up to a list before concatenation makes sense.
(append xs (list y))
But it makes sense to point out (reverse (cons y (reverse xs))) which has the same result. reverse suggests that you might be building up your list backwards if you need to append atoms to the end.
The procedure you're looking for is unsurprisingly called append (from SRFI-1). It appends a list of things onto another list. This does mean that if you want to add just one item, you'll need to make a list out of it:
(append '() '((1 2 3))) => ((1 2 3))
(append '((1 2 3)) '((4 5 6))) => ((1 2 3) (4 5 6))
(append '((1 2 3) (4 5 6)) '("|") ) => ((1 2 3) (4 5 6) "|")
It accepts multiple arguments, which will all be appended to eachother in that order, so you can also do:
(append '() '((1 2 3)) '((4 5 6)) '("|")) => ((1 2 3) (4 5 6) "|")
Hope this helps!
Whether you want it or not, cons cells will be created, since lists consist of cons cells.
how do i append (1 2 3) to the end of () to make ((1 2 3))
CL-USER 24 > (list '(1 2 3))
((1 2 3))
how do i append (4 5 6) to the end of that to make ((1 2 3) (4 5 6))
CL-USER 25 > (append '((1 2 3)) (list '(4 5 6)))
((1 2 3) (4 5 6))
how do i append "|" to the end of that to make ((1 2 3) (4 5 6) "|")
CL-USER 26 > (append '((1 2 3) (4 5 6)) (list "|"))
((1 2 3) (4 5 6) "|")

Kadane's Algorithm in Scheme (Racket)

I understand the logic behind how Kadane's Algorithm (maximum sum of all sequential sub-arrays in an array) works in "pseudo-code," and I'm sure I could implement it as a function in C or C++. However, I'm trying to implement it using lists in Scheme (Racket; the file extension is .rkt), which I have no experience with.
The end result I'm looking for is...
Input: (maxsum `(1 4 -2 1))
Output: 5
So far I've developed two helper functions I may be able to use within the maxsum function.
(1) size: returns the number of elements in a list.
(define size
(lambda (list)
(cond
[(not (list? list)) 0]
[(null? list) 0]
[else (+ 1 (size (cdr list)))]
)
)
)
(2) sum: returns the sum of all elements in a list.
(define sum
(lambda (list)
(cond
[(not (list? list)) 0]
[(null? list) 0]
[else (+ (car list) (sum (cdr list)))]
)
)
)
How would I go about defining/designing the maxsum function?
Here is a version patterned after the Phyton code on wikipedia:
(define (maxsum lst)
(define (aux lst max-ending-here max-so-far)
(if (null? lst)
max-so-far
(let ((new-max-ending-here (max 0 (+ (car lst) max-ending-here))))
(aux (cdr lst) new-max-ending-here (max max-so-far new-max-ending-here)))))
(aux lst 0 0))
(maxsum '(1 4 -2 1)) ; => 5
(maxsum '(-2 1 -3 4 -1 2 1 -5 4)) ; => 6
It is tail recursive, so it will be compiled into an efficient iterative program.
Almost literal translation of [Python code][1] to Racket:
(define (max_subarray A)
(define-values (max_ending_here max_so_far) (values 0 0))
(for ((x (in-list A)))
(set! max_ending_here (max 0 (+ max_ending_here x)))
(set! max_so_far (max max_so_far max_ending_here)))
max_so_far)
Testing:
(max_subarray `(1 4 -2 1))
(max_subarray '(-2 1 -3 4 -1 2 1 -5 4))
Output:
5
6
Please note that recursive functions are generally preferred over iterative ones in Racket and use of "set!" is discouraged here.
Following uses higher functions like apply and map for different steps:
(define (maxsum lst)
(define subarrays
(for*/list ((start (length lst))
(len (range 1 (- (add1(length lst)) start))))
(take (drop lst start) len)))
(define sumlist (map (λ (x) (apply + x)) subarrays))
(apply max sumlist))
Following is more verbose form:
(define (maxsum lst)
(define subarrays
(for*/list ((start (length lst))
(len (range 1 (- (add1(length lst)) start))))
(take (drop lst start) len)))
(displayln "\n----- SUBARRAYS ---------")
(displayln subarrays)
(define sumlist (map (λ (x) (apply + x)) subarrays))
(displayln "----- SUMS OF SUBARRAYS ---------")
(displayln sumlist)
(display "MAX SUM:")
(apply max sumlist))
Testing:
(maxsum `(1 4 -2 1))
(maxsum '(-2 1 -3 4 -1 2 1 -5 4))
Output:
----- SUBARRAYS ---------
((1) (1 4) (1 4 -2) (1 4 -2 1) (4) (4 -2) (4 -2 1) (-2) (-2 1) (1))
----- SUMS OF SUBARRAYS ---------
(1 5 3 4 4 2 3 -2 -1 1)
MAX SUM:5
----- SUBARRAYS ---------
((-2) (-2 1) (-2 1 -3) (-2 1 -3 4) (-2 1 -3 4 -1) (-2 1 -3 4 -1 2) (-2 1 -3 4 -1 2 1) (-2 1 -3 4 -1 2 1 -5) (-2 1 -3 4 -1 2 1 -5 4) (1) (1 -3) (1 -3 4) (1 -3 4 -1) (1 -3 4 -1 2) (1 -3 4 -1 2 1) (1 -3 4 -1 2 1 -5) (1 -3 4 -1 2 1 -5 4) (-3) (-3 4) (-3 4 -1) (-3 4 -1 2) (-3 4 -1 2 1) (-3 4 -1 2 1 -5) (-3 4 -1 2 1 -5 4) (4) (4 -1) (4 -1 2) (4 -1 2 1) (4 -1 2 1 -5) (4 -1 2 1 -5 4) (-1) (-1 2) (-1 2 1) (-1 2 1 -5) (-1 2 1 -5 4) (2) (2 1) (2 1 -5) (2 1 -5 4) (1) (1 -5) (1 -5 4) (-5) (-5 4) (4))
----- SUMS OF SUBARRAYS ---------
(-2 -1 -4 0 -1 1 2 -3 1 1 -2 2 1 3 4 -1 3 -3 1 0 2 3 -2 2 4 3 5 6 1 5 -1 1 2 -3 1 2 3 -2 2 1 -4 0 -5 -1 4)
MAX SUM:6

in Scheme, is there syntactical sugar for an ordinary, unquoted list?

In Scheme, if I wanted a list, say (1 2 3), I would just write '(1 2 3). Usually, this is fine, but it is actually equivalent to (quote (1 2 3)), which is not exactly the same as (list 1 2 3). An example of when this would give different results:
'(1 2 (+ 0 3)) -> (1 2 (+ 0 3))
(list 1 2 (+ 0 3)) -> (1 2 3)
Is there a syntactical sugar for the second line here? For vectors there is. For example:
#(1 2 (+ 0 3)) -> #(1 2 3)
(vector 1 2 (+ 0 3)) -> #(1 2 3)
If there is no such sugar for list, that would be pretty ironic, because lists are used way more often than vectors in Scheme!
If you need to evaluate a part of the list, you can use quasiquoting and unquoting, like this:
`(1 2 ,(+ 0 3))
=> '(1 2 3)

Project for the game 'Oware'

I have a project about the game "Oware", we are supposed to write the game in the program Dr.Racket.
These are the rules for the game, they explain it pretty well, illustrating with pictures: http://www.awale.info/jugar-a-lawale/les-regles-de-lawale/?lang=en
Im kinda stuck on the first exercise, i have the method, but its not giving the numbers in the right order.
The first function we have to write is called "distribute" which should re-put x grains in the holes, giving the result in a form of a list consisting of the number of grains rest and the new numbers for the holes.
This is whats expected:
(distribute 5 '(2 3 1 5 5 2)) -> (0 (3 4 2 6 6 2))
(distribute 5 '(2 3 1)) -> (2 (3 4 2))
What I wrote:
(define distribue
(lambda (n l)
(if (or (= n 0) (null? l))
(list l n)
(cons (+ (car l) 1) (distribue (- n 1) (cdr l))))))
What it gives:
(distribue 5 '(2 3 1 5 5 2)) -> (3 4 2 6 6 (2) 0)
(distribue 5 '(2 3 1)) -> (3 4 2 () 2)
I was trying to change the list cons append, but never got the expected form of answer
How about
(define (distribue n l)
(define (iterator n p q)
(if (or (= n 0) (null? q))
(list n (append p q))
(iterator (- n 1) (append p (list (+ 1 (car q)))) (cdr q))))
(iterator n '() l))
where
(distribue 5 '(2 3 1 5 5 2))
(distribue 5 '(2 3 1))
returns
'(0 (3 4 2 6 6 2))
'(2 (3 4 2))
as required.

SICP Exercise 1.2

I'm having a hard time with exercise 1.2 in SICP.
Translate the following to prefix form:
5 + 4 + (2 - (3 - (6 + 4/5))) / 3(6 - 2)(2 - 7)
Here's what I have, and I can't figure out why it doesn't work. What am I missing?
(/
(+
(+ 4 5)
(- 2
(- 3
(+ 6
(/ 4 5)))))
(* 3
(*
(-6 2)
(- 2 7))))
(-6 2)
Here you're trying to call -6 with 2 as its argument, which doesn't work of course as -6 is not a function. You rather want to call the - function with 6 and 2 as its arguments.
tl;dr: You forgot a space between - and 6.
(/
(+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5)))))
(* 3 (- 6 2) (- 2 7)))

Resources