Here is the actual basic code I use for both conversions. Note, this code was written
around 20 years ago. Pickt = the number of numbers within a set. Dat1$ is the string
variable that holds the number set, numbers are zero padded, single spaced.
LEX1$ is the index value of a set for converting a lex-index to a set, second sub
below. There are many variables within the subs that need to be dimed as double.
This is basic code but runs very fast, around 4000 conversions per second. It may
be hard to follow and someday I will modernize it. Most of the code in the first
sub is just setting up the number data and the conversion code starts with NEXTLEXF:
NCR is the number of sets in the matrix. I think this will handle up to a 13 digit
index value or 9,999,999,999,999 sets.
This code could be greatly condensed and was created to work in all my programs that
need it. I admit the code looks like crap and parts of it may not even be used as it's
underwent many changes over the years. At one time I had to use embedded lookup charts
to get the factorials as basic could not calculate nCr for anything above a 5-30 matrix.
SUB SETTOLEX
A=0:B=0:C=0:D=0:E=0:F=0
N1=0:N2=0:N3=0:N4=0:N5=0:N6=0:
N1$="":N2$="":N3$="":N4$="":N5$="":N6$="":N7$="":N8$=""
IF PICKT >=1 THEN N1$=MID$(DAT1$, 1, 2)
IF PICKT >=2 THEN N2$=MID$(DAT1$, 4, 2)
IF PICKT >=3 THEN N3$=MID$(DAT1$, 7, 2)
IF PICKT >=4 THEN N4$=MID$(DAT1$,10, 2)
IF PICKT >=5 THEN N5$=MID$(DAT1$,13, 2)
IF PICKT >=6 THEN N6$=MID$(DAT1$,16, 2)
IF PICKT >=1 THEN N1=VAL(N1$)
IF PICKT >=2 THEN N2=VAL(N2$)
IF PICKT >=3 THEN N3=VAL(N3$)
IF PICKT >=4 THEN N4=VAL(N4$)
IF PICKT >=5 THEN N5=VAL(N5$)
IF PICKT >=6 THEN N6=VAL(N6$)
LEX1$="":LEX1=NCR:LNUM=1:LX=PICKT
IF PICKT >= 1 THEN A=N1
IF PICKT >= 2 THEN B=N2
IF PICKT >= 3 THEN C=N3
IF PICKT >= 4 THEN D=N4
IF PICKT >= 5 THEN E=N5
IF PICKT >= 6 THEN F=N6
HNUM=NSET-VAL(RIGHT$(DAT1$,2))
NEXTLEXF:
IF PICKT >= 1 AND LNUM = 1 THEN LV = (NSET-A)
IF PICKT >= 2 AND LNUM = 2 THEN LV = (NSET-B)
IF PICKT >= 3 AND LNUM = 3 THEN LV = (NSET-C)
IF PICKT >= 4 AND LNUM = 4 THEN LV = (NSET-D)
IF PICKT >= 5 AND LNUM = 5 THEN LV = (NSET-E)
IF PICKT >= 6 AND LNUM = 6 THEN LV = (NSET-F)
LZ=(LV-LX):NC1=0:
IF LX < 1 THEN LX=1
IF LZ < 1 THEN LZ=1
IF LV < 1 THEN LV=1
NC1 = Factorial(LV) / (Factorial(LX)*Factorial(LZ))
NC1$ = LTRIM$(STR$(NC1)):DP1=0
IF INSTR(NC1$, ".") > 0 THEN DP1=CINT(VAL(MID$(NC1$,INSTR(NC1$, "."), 10)))
IF INSTR(NC1$, ".") > 0 THEN NC1$=MID$(NC1$,1,(INSTR(NC1$, ".")-1))
NC1=VAL(NC1$) + DP1
LEX1=LEX1-NC1
LX=LX-1
LNUM=LNUM+1:
IF LX >=1 THEN GOTO NEXTLEXF
IF HNUM = 0 THEN LEX1=LEX1+1
LEX1$ = "0000000000000" + LTRIM$(STR$(LEX1))
LEX1$ = RIGHT$(LEX1$, LNCR)
END SUB
SUB LEXTOSET
LEX1=VAL(LEX1$)
IF LEX1 > NCR THEN GOTO BYPASSCONVERT
SET1$="": LX1=NSET: LEXHI=(NCR-LEX1):PICK1 = PICKT
NEXTMINI:
NC1 = Factorial(LX1) / (Factorial(PICK1) * Factorial(LX1 - PICK1)):
NC1$ = LTRIM$(STR$(NC1))
DP1=0
IF INSTR(NC1$, ".") > 0 THEN DP1=CINT(VAL(MID$(NC1$,INSTR(NC1$, "."), 10)))
IF INSTR(NC1$, ".") > 0 THEN NC1$=MID$(NC1$,1,(INSTR(NC1$, ".")-1))
NC1=VAL(NC1$) + DP1
DO UNTIL NC1 <= LEXHI
LX1 = LX1 - 1: IF LX1 <= (PICK1-1) THEN EXIT DO
NC1 = Factorial(LX1) / (Factorial(PICK1) * Factorial(LX1 - PICK1)):
NC1$ = LTRIM$(STR$(NC1))
DP1=0
IF INSTR(NC1$, ".") > 0 THEN DP1=CINT(VAL(MID$(NC1$,INSTR(NC1$, "."), 10)))
IF INSTR(NC1$, ".") > 0 THEN NC1$=MID$(NC1$,1,(INSTR(NC1$, ".")-1))
NC1=VAL(NC1$) + DP1
LOOP
IF (NSET - LX1) < 10 THEN SET1$ = SET1$ + "0" + LTRIM$(STR$(NSET - LX1)) + " "
IF (NSET - LX1) > 9 THEN SET1$ = SET1$ + LTRIM$(STR$(NSET - LX1)) + " "
LEXHI = LEXHI - NC1: PICK1 = PICK1 - 1
IF PICK1 > 0 THEN GOTO NEXTMINI
SET1$=LTRIM$(RTRIM$(SET1$))
BYPASSCONVERT:
END SUB
This function expands basic to handle the large factorial calculations.
FUNCTION Factorial# (n AS DOUBLE)
CONST maxNToCache = 100
STATIC resultCache() AS DOUBLE
STATIC FIRSTCALL AS INTEGER
IF firstCall = 0 THEN
firstCall = -1
REDIM resultCache(maxNToCache) AS DOUBLE
resultCache(0) = 1
resultCache(1) = 1
resultCache(2) = 2
END IF
IF n <= maxNToCache THEN
IF resultCache(n) <> 0 THEN
Factorial = resultCache(n)
EXIT FUNCTION
END IF
END IF
resultCache(n) = INT(n) * Factorial(INT(n) - 1)
Factorial = resultCache(n)
END FUNCTION