The logic of the bash power set function

Function (displays the power gain for this input)

p() { [ $# -eq 0 ] && echo || (shift; p " $@ ") | while read r ; do echo -e "$1 $r\n$r"; done } 

Test input

 p $(echo -e "1 2 3") 

Test output

 1 2 3 2 3 1 3 3 1 2 2 1 

I find it hard to understand recursion in the following code. I tried to figure this out by setting some variables inside the code to indicate the recursion level and execution order, but I'm still puzzled.

Here is what I can say so far:

  • The output of the final output will not be displayed on the final output, since it is redirected to the read command through the channel
  • The echo command adds a new line for all output

The execution order that I see is as follows:

  • p (1 2 3) β†’ 1 followed by the entire output combination below \ n the entire output combination below
  • p (2 3) β†’ 2 3 \ n3 \ n
  • p (3) β†’ 3
  • p () β†’

So, I think that to execute # 3, instead of p (3), there should be p (2), but how does this happen? Since shift goes only in one direction.

If I used "p (1 2 3 4)" as input, this is the part that shows "1 2 3" in the output, which bothers me.

+4
source share
1 answer

Using -e in the echo command seems to me pure obfuscation, since it could have been written:

 p() { [ $# -eq 0 ] && echo || (shift; p " $@ ") | while read r ; do echo $1 $r echo $r done } 

In other words, "for each set in the set of degrees of all but the first argument (shift; p " $@ ") , print both values ​​set with and without the first argument."

The bash function works by setting up a chain of subshells, each of which reads the next, something like this, where each box is a subshell and below it, I showed its output when it reads each line (I used "" to do "nothing" visible. => means "call"; <- means "read".)

 +---------+ +-------+ +-------+ +-------+ | p 1 2 3 | ==> | p 2 3 | ==> | p 3 | ==> | p | +---------+ +-------+ +-------+ +-------+ 1 2 3 "" <--+-- 2 3 "" <---+-- 3 "" <-----+-- "" 2 3 "" <-/ / / 1 3 "" <--+-- 3 "" <-/ / 3 "" <-/ / 1 2 "" <--+-- 2 "" <---+-- "" <-/ 2 "" <-/ / 1 "" <--+-- "" <-/ "" <-/ 
+3
source

All Articles