I'm continue learning Racket (well, in this case functional programming).
I have to implement this loop in a functional programming way:
At this moment I have this code:
#lang racket
(define EGS0
(lambda (PSET NSET CSET HSET)
(map (lambda (h)
(cond
[(not (andmap (lambda (p) (my-function h p)) PSET)) h]
[(not (ormap (lambda (n) (my-function h n)) NSET)) h]
) HSET))))
Instead of removing elements from HSET list, I'm creating a new one with the elements that I don't have to remove. This code is only a first approximation: in some cases this will add twice h but this is not my problem now.
CSET is an empty list and my-function returns #t or #f.
My problem comes with the last statement:
Then remove H from HSET and add H to CSET.
With map and I can get one list, but I don't know how to get two list. the only way I can think of is using set!, but if I use it, it is not going to be functional program.
Instead of map, I've thought to use a for loop, or maybe do two loops.
How can I get the two lists (the new list with the elements of HSET and the CSET list)?
UPDATE:
I'm adding some data to test the algorithm (someone needs extra help to understand the pseudocode).
(define my-function (lambda (x y) (and x y)))
(define hset '(1))
(define pset '(0))
(define nset '(1))
(egs pset nset '() hset)
It must returns: '(() (1)).
Notice that this problem is procedural in nature and is not as straightforward to write in a functional style; in this case writing an explicit loop is more natural than using map or filter.
Returning two values is easy, it can be managed by passing two accumulator parameters in the recursion and returning them at the end inside a list. Here's my implementation:
(define (egs pset nset cset hset)
(let loop ((input hset) (output '()) (cset cset))
(if (null? input)
; return modified cset and hset
(list cset output)
(let ((pset-match
(andmap (lambda (p) (my-function (car input) p)) pset))
(nset-match
(ormap (lambda (n) (my-function (car input) n)) nset)))
(cond ((not nset-match)
; if h does not match any members from nset
; remove h from hset, add h to cset
(loop (cdr input) output (cons (car input) cset)))
((not pset-match)
; if h does not match all members of pset
; remove h from hset, leave cset unmodified
(loop (cdr input) output cset))
(else
; otherwise don't remove h from hset, leave cset unmodified
(loop (cdr input) (cons (car input) output) cset)))))))
It works with the sample input:
(define my-function (lambda (x y) (and x y)))
(define hset '(1))
(define pset '(0))
(define nset '(1))
(egs pset nset '() hset)
=> '(() (1))
Related
I've been trying to tinker with this code to rewrite a "repeat" function using tail-end recursion but have gotten a bit stuck in my attempts.
(define (repeat n x)
(if (= n 0)
'()
(cons x (repeat (- n 1) x))))
This is the original "repeat" function. It traverses through 'n - 1' levels of recursion then appends 'x' into a list in 'n' additional recursive calls. Instead of that, the recursive call should be made and the 'x' should be appended to a list at the same time.
(define (repeat-tco n x)
(trace-let rec ([i 0]
[acc '()])
(if (= i n)
acc
(rec (+ i 1) (cons x acc)))))
This is the closest rewritten version that I've come up with which I believe follows tail-call recursion but I'm not completely sure.
Your repeat-tco function is indeed tail recursive: it is so because the recursive call to rec is in 'tail position': at the point where it's called, the function that is calling it has nothing left to do but return the value of that call.
[The following is just some perhaps useful things: the answer is above, but an answer which was essentially 'yes' seemed too short.]
This trick of taking a procedure p which accumulates some result via, say (cons ... (p ...)) and turning it into a procedure with an extra 'accumulator' argument which is then tail recursive is very common. A result of using this technique is that the results come out backwards: this doesn't matter for you because all the elements of your list are the same, but imagine this:
(define (evens/backwards l)
(let loop ([lt l]
[es '()])
(if (null? lt)
es
(loop (rest lt)
(if (even? (first lt))
(cons (first lt) es)
es)))))
This will return the even elements of its arguments, but backwards. If you want them the right way around, a terrible answer is
(define (evens/terrible l)
(let loop ([lt l]
[es '()])
(if (null? lt)
es
(loop (rest lt)
(if (even? (first lt))
(append es (list (first lt)))
es)))))
(Why is it a terrible answer?) The proper answer is
(define (evens l)
(let loop ([lt l]
[es '()])
(if (null? lt)
(reverse es)
(loop (rest lt)
(if (even? (first lt))
(cons (first lt) es)
es)))))
I'm using the beginning language with list abbreviations for DrRacket and want to make a powerset recursively but cannot figure out how to do it. I currently have this much
(define
(powerset aL)
(cond
[(empty? aL) (list)]
any help would be good.
What's in a powerset? A set's subsets!
An empty set is any set's subset,
so powerset of empty set's not empty.
Its (only) element it is an empty set:
(define
(powerset aL)
(cond
[(empty? aL) (list empty)]
[else
As for non-empty sets, there is a choice,
for each set's element, whether to be
or not to be included in subset
which is a member of a powerset.
We thus include both choices when combining
first element with smaller powerset,
that, which we get recursively applying
the same procedure to the rest of input:
(combine (first aL)
(powerset (rest aL)))]))
(define
(combine a r) ; `r` for Recursive Result
(cond
[(empty? r) empty] ; nothing to combine `a` with
[else
(cons (cons a (first r)) ; Both add `a` and
(cons (first r) ; don't add, to first subset in `r`
(combine ; and do the same
a ; with
(rest r))))])) ; the rest of `r`
"There are no answers, only choices". Rather,
the choices made, are what the answer's made of.
In Racket,
#lang racket
(define (power-set xs)
(cond
[(empty? xs) (list empty)] ; the empty set has only empty as subset
[(cons? xs) (define x (first xs)) ; a constructed list has a first element
(define ys (rest xs)) ; and a list of the remaining elements
;; There are two types of subsets of xs, thouse that
;; contain x and those without x.
(define with-out-x ; the power sets without x
(power-set ys))
(define with-x ; to get the power sets with x we
(cons-all x with-out-x)) ; we add x to the power sets without x
(append with-out-x with-x)])) ; Now both kind of subsets are returned.
(define (cons-all x xss)
; xss is a list of lists
; cons x onto all the lists in xss
(cond
[(empty? xss) empty]
[(cons? xss) (cons (cons x (first xss)) ; cons x to the first sublist
(cons-all x (rest xss)))])) ; and to the rest of the sublists
To test:
(power-set '(a b c))
Here's yet another implementation, after a couple of tests it appears to be faster than Chris' answer for larger lists. It was tested using standard Racket:
(define (powerset aL)
(if (empty? aL)
'(())
(let ((rst (powerset (rest aL))))
(append (map (lambda (x) (cons (first aL) x))
rst)
rst))))
Here's my implementation of power set (though I only tested it using standard Racket language, not Beginning Student):
(define (powerset lst)
(if (null? lst)
'(())
(append-map (lambda (x)
(list x (cons (car lst) x)))
(powerset (cdr lst)))))
(Thanks to samth for reminding me that flatmap is called append-map in Racket!)
You can just use side effect:
(define res '())
(define
(pow raw leaf)
(cond
[(empty? raw) (set! res (cons leaf res))
res]
[else (pow (cdr raw) leaf)
(pow (cdr raw) (cons (car raw) leaf))]))
(pow '(1 2 3) '())
(define-struct pizza (size toppings))
;; Constants for testing
(define (meat item)
(symbol=? 'meat item))
(define (tomatoes item)
(symbol=? 'tomatoes item))
(define (cheese item)
(symbol=? 'cheese item))
(define (pepperoni item)
(symbol=? 'pepperoni item))
(define (hot-peppers item)
(symbol=? 'hot-peppers item))
(define (count-toppings order topping)
(cond [(empty? order) 0]
[else
(local
[(define (single-pizza-tops pizza top)
(length (filter top (pizza-toppings pizza))))
(define (list-of-nums lop tops)
(list (single-pizza-tops (first lop) tops)
(single-pizza-tops (first (rest lop)) tops)
(single-pizza-tops (first (rest (rest lop))) tops)))]
(foldr + 0 (list-of-nums order topping)))]))
Turns out my code works fine with the defined constants, but count-toppings wont work with a symbol for 'topping?
Does anyone know a way to modify my filter function so that if I input a symbol for toppings, this code will work the same way?
Map and filter can be implemented in terms of foldr and cons. Since you aren't building a list you can disregard filter and map. In general though to map recursion to higher-order function you can look at type signatures. The more difficult way is to manually match your code to that of the functions.
Map takes a list, a function or arity one, and returns a list of the function mapped to each element of the list or (a -> b) -> [a] -> [b] in Haskell notaion.
(define (map f L) ;niave implementation pared down for simplicity
(if (null? L)
'()
(cons (f (car L)) (map f (cdr L)))))
Filter takes a predicate of arity one, and a list, and returns a list that safisfies that predicate. or (a -> bool) -> [a] -> [a] in Haskell.
(define (filter pred L) ;dirro
(cond ((null? L) '())
((pred (car L))
(cons (car L)
(filter pred (cdr L))))
(else (filter pred (cdr L)))))
Foldr takes an a function that that has arity two, an accumulator value, and a list and returns the accumulator. or (a -> b -> b) -> b -> [a] -> b in haskell.
(define (foldr kons knil L) ;ditto
(if (null? L)
knil
(kons (car L) (foldr kons knil (cdr L)))))
So the trick of it at first is assuaging the argument from your function to fit. In both your funcitons you have a cond clause [(empty? topping-list) 0], which suggests knil should be 0.
In count-topping's else statement you call +, which at first glance suggests kons should be a +, however your list isn't numbers directly, meaning youll have to wrap in in a lambda statement, or create a helper function. (lambda (x acc) (+ (single-pizza-toppings (pizza-toppings x) atop) acc))
To put it together
(define (count-topping alop atop)
(foldr (lambda (x acc)
(+ (single-pizza-toppings (pizza-toppings x) atop)
acc))
0
alop))
Now the interesting one, single-pizza-toppings will look very similar. Execpt that the lambda statement will contain an if statment that returns 1 if x is a symbol equal to topping and 0 otherwise. Or you can do something even simpler.
(define (single-pizza-toppings topping-list topping)
(foldr (lambda (x acc)
(+ 1 acc))
0
(filter (lammba (x) (symbol=? x topping))
topping-list)))
That filter filter insures every x going to the foldr is a topping so you can just ignore it and add to the accumulator.
Assuming that we have the first, we can define the second by
Count the occurrences of the topping in each pizza using the first function, by way of map
Compute the sum of the resulting list
That is,
(define (count-toppings pizzas topping)
(sum (map (lambda (p) (single-pizza-toppings (pizza-toppings p) topping)) pizzas)))
For the first function, we can use filter to get a list of all occurrences of the given topping.
The number of occurrences is the length of the result:
(define (single-pizza-toppings toppings topping)
(length (filter (lambda (t) (symbol=? t topping)) toppings)))
Both functions consist of a transformation of the input into the data we're interested in, map and filter, followed by a "reduction", sum and length.
This is a very common pattern.
And if you don't have sum:
(define (sum ts)
(foldr (lambda (x acc) (+ x acc)) 0 ts))
Looks like your first step will be to put together a complete set of test cases. If you're using DrRacket, you might want to enable "Syntactic Test Suite Coverage" in the "Choose Language..." menu to make sure you have a good set of tests. That's the first step....
I'm totally new to Scheme and I am trying to implement my own map function. I've tried to find it online, however all the questions I encountered were about some complex versions of map function (such as mapping functions that take two lists as an input).
The best answer I've managed to find is here: (For-each and map in Scheme). Here is the code from this question:
(define (map func lst)
(let recur ((rest lst))
(if (null? rest)
'()
(cons (func (car rest)) (recur (cdr rest))))))
It doesn't solve my problem though because of the usage of an obscure function recur. It doesn't make sense to me.
My code looks like this:
(define (mymap f L)
(cond ((null? L) '())
(f (car L))
(else (mymap (f (cdr L))))))
I do understand the logic behind the functional approach when programming in this language, however I've been having great difficulties with coding it.
The first code snippet you posted is indeed one way to implement the map function. It uses a named let. See my comment on an URL on how it works. It basically is an abstraction over a recursive function. If you were to write a function that prints all numbers from 10 to 0 you could write it liks this
(define (printer x)
(display x)
(if (> x 0)
(printer (- x 1))))
and then call it:
(printer 10)
But, since its just a loop you could write it using a named let:
(let loop ((x 10))
(display x)
(if (> x 0)
(loop (- x 1))))
This named let is, as Alexis King pointed out, syntactic sugar for a lambda that is immediately called. The above construct is equivalent to the snippet shown below.
(letrec ((loop (lambda (x)
(display x)
(if (> x 0)
(loop (- x 1))))))
(loop 10))
In spite of being a letrec it's not really special. It allows for the expression (the lambda, in this case) to call itself. This way you can do recursion. More on letrec and let here.
Now for the map function you wrote, you are almost there. There is an issue with your two last cases. If the list is not empty you want to take the first element, apply your function to it and then apply the function to the rest of the list. I think you misunderstand what you actually have written down. Ill elaborate.
Recall that a conditional clause is formed like this:
(cond (test1? consequence)
(test2? consequence2)
(else elsebody))
You have any number of tests with an obligatory consequence. Your evaluator will execute test1? and if that evaluated to #t it will execute the consequence as the result of the entire conditional. If test1? and test2? fail it will execute elsebody.
Sidenote
Everything in Scheme is truthy except for #f (false). For example:
(if (lambda (x) x)
1
2)
This if test will evaluate to 1 because the if test will check if (lambda (x) x) is truthy, which it is. It is a lambda. Truthy values are values that will evaluate to true in an expression where truth values are expected (e.g., if and cond).
Now for your cond. The first case of your cond will test if L is null. If that is evaluated to #t, you return the empty list. That is indeed correct. Mapping something over the empty list is just the empty list.
The second case ((f (car L))) literally states "if f is true, then return the car of L".
The else case states "otherwise, return the result mymap on the rest of my list L".
What I think you really want to do is use an if test. If the list is empty, return the empty list. If it is not empty, apply the function to the first element of the list. Map the function over the rest of the list, and then add the result of applying the function the first element of the list to that result.
(define (mymap f L)
(cond ((null? L) '())
(f (car L))
(else (mymap (f (cdr L))))))
So what you want might look look this:
(define (mymap f L)
(cond ((null? L) '())
(else
(cons (f (car L))
(mymap f (cdr L))))))
Using an if:
(define (mymap f L)
(if (null? L) '()
(cons (f (car L))
(mymap f (cdr L)))))
Since you are new to Scheme this function will do just fine. Try and understand it. However, there are better and faster ways to implement this kind of functions. Read this page to understand things like accumulator functions and tail recursion. I will not go in to detail about everything here since its 1) not the question and 2) might be information overload.
If you're taking on implementing your own list procedures, you should probably make sure they're using a proper tail call, when possible
(define (map f xs)
(define (loop xs ys)
(if (empty? xs)
ys
(loop (cdr xs) (cons (f (car xs)) ys))))
(loop (reverse xs) empty))
(map (λ (x) (* x 10)) '(1 2 3 4 5))
; => '(10 20 30 40 50)
Or you can make this a little sweeter with the named let expression, as seen in your original code. This one, however, uses a proper tail call
(define (map f xs)
(let loop ([xs (reverse xs)] [ys empty])
(if (empty? xs)
ys
(loop (cdr xs) (cons (f (car xs)) ys)))))
(map (λ (x) (* x 10)) '(1 2 3 4 5))
; => '(10 20 30 40 50)
I am trying to use recursion to stack a basic block I created (y), x amount of times high.
(define stack-copies-of
(lambda (x y)
(cond
((= x 0) 0)
((> x 0) (stack y y)
I didn't go any further because well... I'm stumped. I want the stack of blocks to appear on the screen. Thank you!
First of all, you are not using recursion. stack-copies-of is not stack.
You need to look at basic list operations. Heres some that makes a list:
;; easiest version, looks most like the one you started with
(define (make-list num-elements)
(if (zero? num-elements)
'() ; the tail of the list is the empty list
(cons '* (make-list (- num-elements 1)))))
;; tail recursive version using auxillary procedure
(define (make-list num-elements)
;; we define a local auxillary procedure to do the work
(define (make-list-aux num-elements acc)
(if (zero? n)
acc ; return the produced list
(make-list-aux (- n 1)
(cons '* acc))))
;; fire it off
(make-list-aux num-elements '()))
;; exactly the same as the previous, but with a named let
(define (make-list num-elements)
;; a named let can be called by name as a procedure, creating a loop
(let make-list-aux ((num-elements num-elements)
(acc '()))
(if (zero? n)
acc
(make-list-aux (- n 1)
(cons '* acc)))))
(display (make-list 10)) ; print the result
I expect what you're after could be based on one of these except instead of '* you use your extra argument.
If your data structure is a stack you can define it and the related operations push, pop and one to display the stack.
(define stack '())
(define (push e)
(set! stack (cons e stack)))
(define (pop)
(let ((e (car stack)))
(set! stack (cdr stack))
e))
(define (display-stack)
(for-each
(lambda (e) (display e) (newline))
stack))
the following is the recursive function to stack n times an element
(define (stack-ntimes n e)
(when (> n 0)
(push e)
(stack-ntimes (- n 1) e)))