2

Is it possible to make a racket function to return powerset of a given list?


Constraints-

  1. without explicit recursion
  2. use abstract list functions
  3. 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:

  1. Taking (powerset '(a b c)) as an example,
  2. First get a list of whole numbers up to (expt 2 (length list)) ;'(0 1 2 3 4 5 6 7)
  3. 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))
  4. map '(1 2 3) to the list of binaries. For eg: 2->'(0,1,0)->'((0,a) (1,b) (0,c))
  5. filter the resulting list with a lambda such that we keep elements with 1, like '((1,b)).
  6. 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.

  1. What are abstract list functions?
  • Functions like foldl, foldr and map
  1. 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, and cond.

However, funny thing, I studied Y-combinator and was able to solve this one (after 6 hrs of coding).

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Saksham
  • 21
  • 2
  • Your previous question was closed as a duplicate. Do not simply delete it and re-ask it identically. Instead, read the other question and its answers; probably they address your question. If they do not, edit the first question while making it clear what is different about your question - closed questions can be reopened when edited. – amalloy Nov 24 '20 at 10:24
  • 1
    @amalloy No! I made the edit in the previous question too! But it was still closed. The thing is it is easy to do it with recursion. I have done it for part 1. I added the constraints section, it clearly states- use of no explicit recursion (which is violated in the question you suggested). Thanks. – Saksham Nov 24 '20 at 10:35
  • 1
    @amalloy Is it clear now? – Saksham Nov 24 '20 at 10:37
  • 1
    @ÓscarLópez I know it contains an answer but it uses **recursion**. Check the comments above before pointing this out again. Yes, it was homework, I mentioned it in the post. The deadline passed so it doesn't even matter but I was curious how can it be done. Maybe my approach that I mentioned was correct? The 2 line requirement is not silly. In the post I have mentioned that I have a 80 character limit in a line. Please read the post carefully before pointing it out! I'll just ask my prof. Thank you for taking your time out for this. – Saksham Nov 24 '20 at 11:45
  • If you don't want explicit recursion, then Y combinator is a way to go. However, I don't think the type of question "how do I fit it in two lines" is appropriate for StackOverflow. You might want to ask this kind of question at https://codegolf.stackexchange.com/ instead. – Sorawee Porncharoenwase Nov 24 '20 at 12:51
  • It's kind of sad that apparently no-one read the question carefully enough to see that the referenced answers *don't* actually answer it. The answer isn't hard and you don't need Y. Oh well. –  Nov 24 '20 at 14:28
  • Nice question, and ideas! :) – Will Ness Nov 24 '20 at 18:45
  • 2
    answer: `(define (pws l)` `(foldr (lambda (e a) (append (map (lambda (x) (cons e x)) a) a)) '(()) l))` – Will Ness Nov 24 '20 at 20:07
  • Indeed it seems we were too quick to close this question, I'm sorry about that. Voting to reopen. – Óscar López Nov 24 '20 at 21:36
  • Anyway: you might want to check out the alleged [duplicate](https://stackoverflow.com/a/42875002/201359) again, thanks to Will's suggestions now it's closer to what you were looking for. – Óscar López Nov 24 '20 at 21:53
  • @Saksham your bonus part 3 was recently [asked about](https://stackoverflow.com/q/64904835/849891) too (with a code based on [this answer](https://stackoverflow.com/a/20623487/849891) of mine). kudos for solving it by yourself! :) – Will Ness Nov 24 '20 at 23:22
  • for your task 1, if `append` isn't allowed, it can itself be coded with foldr, in [this snippet](https://stackoverflow.com/questions/64984096/powerset-of-a-list-using-abstract-list-functions#comment114905414_64984096) – Will Ness Nov 24 '20 at 23:25
  • I voted to reopen. Sorry about that. I'm guilty of all charges. – Sorawee Porncharoenwase Nov 25 '20 at 01:18

1 Answers1

2

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.

Will Ness
  • 70,110
  • 9
  • 98
  • 181