问题
Is it possible to make a racket function to return powerset of a given list?
Constraints-
- without explicit recursion
- use abstract list functions
- code contained in 2 lines (actual requirement)
For eg:
(powerset '(1 2))
'((1 2) (1) (2) ())
in any order.
The other question I found still uses explicit recursion.
My workflow:
- Taking
(powerset '(a b c))
as an example, - First get a list of whole numbers up to
(expt 2 (length list)) ;'(0 1 2 3 4 5 6 7)
- Convert them into their respective binary form
2->(0,1,0)
. So we get'((0,0,0), (0,0,1), (0,1,0), (0,1,1), (1,0,0), (1,0,1), (1,1,0), (1,1,1))
- map '(1 2 3) to the list of binaries. For eg:
2->'(0,1,0)->'((0,a) (1,b) (0,c))
- filter the resulting list with a lambda such that we keep elements with 1, like
'((1,b))
. - Extract the powerset
Problem with my approach
It does not follow constraint of the question being in 1 line (additional to function header).
(define (powerset list)
( ... )) ;; ie the code is contained in 2 lines of 80 characters
I had this question in my assignment as a bonus question but I wasn't able to do it.
- What are abstract list functions?
- Functions like
foldl
,foldr
andmap
- My bonus included 3 subparts
- Part 1 asked to simply make this function in any way I wanted. So I used recursion to do so
- Part 2 is the part I asked the question about. This one was particularly tough because there was an added constraint of the code to be within 2 lines
- Part 3 was supposed to be the toughest.
Do not write any helper functions, and do not use any explicit recursion (i.e., your function cannot call itself by name). Do not use any abstract list functions. In fact, use only the following list of Racket functions, constants and special forms:
cons
,first
,rest
,empty?
,empty
,lambda
, andcond
.
However, funny thing, I studied Y-combinator
and was able to solve this one (after 6 hrs of coding).
回答1:
To answer your bonus part 2:
(define (pws l)
(foldr (lambda (e a) (append (map (lambda (x) (cons e x)) a) a)) '(()) l))
Two lines, less than 80 chars each, first line reserved for the define
(so, one line).
If append
isn't allowed, then we turn the append ... map
combination into a foldr
as well:
(define (pws-fr l)
(foldr (lambda (e a)
(foldr (lambda (x r)
(cons (cons e x) r))
a a))
'(()) l))
or, shortened,
(define (pws-fr-1 l)
(foldr (lambda (e a) (foldr (lambda (x r) (cons (cons e x) r)) a a)) '(()) l))
(with precisely 80 chars in its second line).
Another way to code this is the append-map
-based code (the second snippet) from this answer which, when re-coded with foldr
only, becomes
(define (pws-am-fr l)
(foldr (lambda (e a)
(foldr (lambda (x r)
(cons x (cons (cons e x) r)))
'() a))
'(()) l))
or shortened,
(define (pws-am-fr1 l) (foldr (lambda (e a)
(foldr (lambda (x r) (cons x (cons (cons e x) r))) '() a)) '(()) l))
which might or might not fulfill your requirements exactly.
来源:https://stackoverflow.com/questions/64984096/powerset-of-a-list-using-abstract-list-functions