[[https://www.revelation.com/|Sign up on the Revelation Software website to have access to the most current content, and to be able to ask questions and get answers from the Revelation community]]
==== Unique combinations of numbers in a set (AREV Specific) ====
=== At 06 AUG 2011 06:44:07AM William Titus wrote: ===
{{tag>"AREV Specific"}}
From a sorted list of numbers such as "10,20,30,40,50" I need to build an ordered list of all unique combinations without repeating elements.
In this case, the combinations would be:
10, 20, 30, 40, 50, 10*20, 10*30, 10*40, 10*50, 20*30, 20*40, 20*50, 30*40, 30*50, 40*50, 10*20*30, 10*20*40, 10*20*50, 10*30*40, 10*30*50, 10*40*50, 10*20*30*40, 10*20*30*50, 10*30*40*50, 10*20*30*40*50
The number of numbers is not fixed.
Can one of you math wizards set me on the right programmatic path (recursive or otherwise) to get me where I need to go?
Thanks!
----
=== At 06 AUG 2011 11:27AM Richard Hunt wrote: ===
Since I am not sure if you can delimit by using value marks and field marks rather than the commas ans asterisks, I used FOR/NEXT rather than REMOVE statements...
RESULT='
DELIMITER=*'
STRING=1:DELIMITER:2:DELIMITER:3:DELIMITER:4:DELIMITER:5
STRING=1:DELIMITER:2:DELIMITER:3:DELIMITER:4:DELIMITER:5
LAST_VALUE=COUNT(STRING,DELIMITER) + (STRING NE '')
FOR VALUE=1 TO LAST_VALUE
RESULT := @VM:FIELD(STRING,DELIMITER,VALUE)
NEXT VALUE
FOR VALUE=1 TO LAST_VALUE
PREFIX=FIELD(STRING,DELIMITER,1,VALUE)
SUFFIX=FIELD(STRING,DELIMITER,VALUE + 1,LAST_VALUE)
LAST_SUFFIX_VALUE=COUNT(SUFFIX,DELIMITER) + (SUFFIX NE '')
FOR SUFFIX_VALUE=1 TO LAST_SUFFIX_VALUE
RESULT := @VM:PREFIX:DELIMITER:FIELD(SUFFIX,DELIMITER,SUFFIX_VALUE)
NEXT SUFFIX_VALUE
NEXT VALUE
RESULT=RESULT2,LEN(RESULT)
----
=== At 06 AUG 2011 02:58PM William Titus wrote: ===
Thanks, Richard, for taking time to send me your code. It's a lot more compact than mine and took me as far as:
1²2²3²4²5²1*2²1*3²1*4²1*5²1*2*3²1*2*4²1*2*5²1*2*3*4²1*2*3*5²1*2*3*4*5
The code I've built to this point is this:
***********
DATUM="
RUN=1
NUMBERS=1,2,3,4,5"
CONVERT "," TO @VM IN NUMBERS
HOWMANY=COUNT(NUMBERS,@VM)+(NUMBERS NE "")
COMBOS=HOWMANY * HOWMANY
ARRAY="
FOR X=1 TO HOWMANY
FOR G=1 TO HOWMANY
ARRAY=NUMBERS
NEXT G
NEXT X
*
ALLCOMBOS="
FOR X=1 TO COMBOS
FOR G=1 TO HOWMANY
DATUM=ARRAY
LOCATE DATUM IN ALLCOMBOS USING @VM SETTING POS ELSE
IF DATUM NE "" THEN
IF ALLCOMBOS=" THEN ALLCOMBOS=DATUM ELSE ALLCOMBOS:=@VM:DATUM
END
END
NEXT G
NEXT X
*
FOR X=1 TO COMBOS
D=NUMBERS
FOR Y=X+1 TO COMBOS
E=NUMBERS
IF E NE "" THEN
DATUM=D:"*":E
LOCATE DATUM IN ALLCOMBOS USING @VM SETTING POS ELSE
IF DATUM NE "" THEN
IF ALLCOMBOS=" THEN ALLCOMBOS=DATUM ELSE ALLCOMBOS:=@VM:DATUM
END
END
END
NEXT Y
NEXT X
FOR X=1 TO COMBOS
D=NUMBERS
FOR Y=X+1 TO COMBOS
E=NUMBERS
FOR Z=Y+1 TO COMBOS
F=NUMBERS
IF E NE "" AND F NE "" THEN
DATUM=D:"*":E:"*":F
LOCATE DATUM IN ALLCOMBOS USING @VM SETTING POS ELSE
IF DATUM NE "" THEN
IF ALLCOMBOS=" THEN ALLCOMBOS=DATUM ELSE ALLCOMBOS:=@VM:DATUM
END
END
END
NEXT Z
NEXT Y
NEXT X
***********
And it gets me to:
1²2²3²4²5²1*2²1*3²1*4²1*5²2*3²2*4²2*5²3*4²3*5²4*5²1*2*3²1*2*4²1*2*5²1*3*4²1*3*5²1*4
*5²2*3*4²2*3*5²2*4*5²3*4*5
I realized that this is a kludge and only gets me to 3-digit groups, though it gets exactly what I want to that point.
I think I need a simple recursive way to minimize the code and maximize efficiency. I'm just not proficient enough as a coder at this point to know the way to get there except by adding more FOR-NEXT loops while also accounting for the maximum number of numbers the user will want to put into as many groups as possible.
Thanks again for your help.
----
=== At 08 AUG 2011 10:13AM Michael Slack wrote: ===
Just off the top of my head, I think you might find a FOR loop and a LOCATE BY to be simpler. I'll sketch out what I'm thinking in pseudo code.
* Start_Array is your array or row that you want to work with.
* End_Array is your resulting array or row.
CNT_START_ARRAY=COUNT(START_ARRAY, @VM) + (START_ARRAY # '')
IF CNT_START_ARRAY=0 THEN STOP PROCESS
FOR I=1 TO CNT_START_ARRAY
LOCATE START_ARRAY IN END_ARRAY BY "AL" USING @VM SETTING POS ELSE
END_ARRAY=START_ARRAY
END
NEXT I
What this does is any time it doesn't find a matching value in the END_ARRAY, it put it in, in sorted order. So, if it find a duplicate value already within the END_ARRAY, it won't add it. So, in the end you get only unique values within the END_ARRAY.
Of course if this is what you're looking for, you'll need to flesh it out to fit your particular needs.
I hope this helps.
Michael Slack
----
=== At 10 AUG 2011 02:37PM Mike Ruane wrote: ===
Mike-
I'd use the same code as you, except using a LOOP...REMOVE to remove the items from the array, instead of the FOR...NEXT loop.
Mike
----
=== At 11 AUG 2011 04:49PM Bill Titus wrote: ===
Thanks, all.
Your help is much appreciated by this old dog. Now it's off to implement what's been suggested!
[[https://www.revelation.com/revweb/oecgi4p.php/O4W_HANDOFF?DESTN=O4W_RUN_FORM&INQID=NONWORKS_READ&SUMMARY=1&KEY=1407169525032DFC852578E4003AF8D7|View this thread on the forum...]]