DOCOMB



#2

DOCOMB will evaluate <ob> for every combination of <n> elements from list <L>. Usage is similar to DOLIST and DOSUBS:

Input:
3: L list of objects
2: n number of elements to be taken each time
1: ob object to be evaluated
Output: ob evaluated for each of the COMB(s,n) combinations of n elements of L

@ DOCOMB 230.5_Bytes # 1997h (48G)
\<<
ROT DUP SIZE 1 + 0
\-> ob L s DoC
\<<
{}
{ OVER 1 -
\-> t n
\<<
s 1 -
IF n
THEN FOR s n L s GET 1 \->LIST t + DoC EVAL NEXT
ELSE FOR s L s GET t LIST\-> DROP ob EVAL NEXT
END
\>>
} DUP 'DoC' STO EVAL
\>>
\>>

examples:

{ 11 22 33 44 }
3
\<< 3 \->LIST \>>
DOCOMB
results in
{ 11 22 33 }
{ 11 22 44 }
{ 11 33 44 }
{ 22 33 44 }

0
{ (0,3) (0,0) (4,0) (3,4) (4,3) }
2
\<< - ABS MAX \>>
DOCOMB

results in 5

Cheers, Werner

Edited: 6 Oct 2012, 1:38 p.m. after one or more responses were posted


#3

Hi Werner,

Well done ! The problem is that recursivity is very slow in User RPL.
Perhaps is there a way to avoid recursivity ?

It would be great to have such a thing in SysRPL (why not in the Gofer List Library) but a will prefer an output in _one_ list of list.
I think it s not a good idea to have program wich return a variable number of items on the stack

Ex :

{ 11 22 33 44 }
3 << >>
DOCOMB
results in
{{ 11 22 33 }
{ 11 22 44 }
{ 11 33 44 }
{ 22 33 44 }}

PS : I never understood why RPL creators did not DOSUBS with n parameters to work like this :

{ 1 2 3 4 } 2 << R->C >> DOSUBS

{ (1 2) (3 4)}


Edited: 5 Oct 2012, 5:42 p.m.


#4

RE: P.S.

Or at least propose a multidimentional version of DOSUB as done with DUP or DROP :

{ 1 2 3 4 5 6 } « SQ »  DOSUB            returns  { 1 4 9 16 25 36 }

{ 1 2 3 4 5 6 } « R->C » DOSUB2 returns { (1 2) (3 4) (5 6) }

{ 1 2 3 4 5 6 } « 3 ->ARRY » 3 DOSUBN returns { [ 1 2 3 ] [ 4 5 6 ] }


Edited: 6 Oct 2012, 2:28 a.m.

#5

Hello Gilles,
you are right that, to correspond to how DOSUBS works, the result should be wrapped up in a list.
The inputs to the object being evaluated however, should not, just like DOSUBS does.
So,
{ 11 22 33 44 }
3
\<< 3 \->LIST \>>
DOCOMB
should return
{ { 11 22 33 } { 11 22 44 } { 11 33 44 } { 22 33 44 } }

My other example remains the same, as it doesn't add a stack level.
BTW this version is not my first, and the fastest I've been able to come up with.
I too, tried to circumvent recursion (and failed) and the creation of the temporary environment
at each recursive call - that is possible, but turned out to be much slower.
My SysRPL is very rusty I'm afraid, that will take me a lot of time to get in to again.
There's some nice tricks to be played with recursion though.
So the RPL version of DOCOMB becomes:
265.5 bytes
\<<
ROT DUP SIZE 1 + 0
\-> ob L s DoC
\<<
DEPTH DEPTH ROLLD
{}
{ OVER 1 -
\-> t n
\<<
s 1 -
IF n
THEN FOR s n L s GET 1 \->LIST t + DoC EVAL NEXT
ELSE FOR s L s GET t LIST\-> DROP ob EVAL NEXT
END
\>>
} DUP 'DoC' STO EVAL
DEPTH DEPTH ROLL -
IF DUP THEN \->LIST ELSE DROP END
\>>
\>>

Cheers, Werner

Forum Jump: