Combinação de números sem repetição em PL/SQL

Galera, boa tarde!
Essa semana estava com um amigo numa árdua tarefa, de desenvolver uma funcionalidade que faça a combinação de números N, P a P, passando os valores por parâmetros e sem a limitação do cálculo do fatorial. Abaixo segue a procedure que faz tal combinação utilizando um algoritmo de substituição binária.
create or replace package ALG_COMBINA is
  FUNCTION COMBINA RETURN EXEM_TABLE;
end ALG_COMBINA;
/
CREATE OR REPLACE PACKAGE BODY ALG_COMBINA IS
TYPE VX IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
VETOR     VX;
VETOS     EXEM_TABLE := EXEM_TABLE();
QTD       NUMBER;
N         NUMBER;
P         NUMBER;
W_MSG     VARCHAR2(500);
W_MSG_TMP VARCHAR2(100);
W_LIM_ELE NUMBER;
PROCEDURE GERA_COMBINACAO(W_N   IN NUMBER, — TOTAL DE EMENTOS NO VETOR
W_P   IN NUMBER, — TOTAL DE ELEMENTOS A SEREM COMBINADOS
W_I   IN NUMBER, — ELEMENTO ATUAL
NUM   IN NUMBER, — PRÓXIMO ELEMENTO
W_SAI IN VARCHAR2) IS
— STRING DE SAIDA COM A COMBINAÇÃO
RC NUMBER;
BEGIN
RC := 0;
W_LIM_ELE := W_N – W_P + W_I;
FOR I IN NUM .. W_LIM_ELE LOOP
W_MSG_TMP := W_SAI || TO_CHAR(VETOR(I), ‘FM00’);
IF W_I < W_P THEN
GERA_COMBINACAO(W_N, W_P, W_I + 1, I + 1, W_MSG_TMP || ‘,’);
ELSE
RC:= 0;
IF RC = 0 THEN
QTD := QTD + 1;
VETOS.EXTEND;
VETOS(QTD) := QTD || ‘:’ || W_MSG_TMP;
END IF;
END IF;
END LOOP;
END;
FUNCTION COMBINA RETURN EXEM_TABLE IS
BEGIN
QTD := 0;
N   := 15;
P   := 5;
FOR I IN 1 .. N LOOP
VETOR(I) := I;
END LOOP;
GERA_COMBINACAO(N, — TOTAL DE EMENTOS NO VETOR
P, — TOTAL DE ELEMENTOS A SEREM COMBINADOS
1, — ELEMENTO ATUAL
1, — PRÓXIMO ELEMENTO
W_MSG); — STRING DE SAIDA COM A COMBINAÇÃO
RETURN(VETOS);
END;
END LHM_COMBINA;
/
Após criar o pacote, iremos criar o tipo para a criação da tabela, e assim gerar uma tabela com as informações que estão em memória, usando o CAST.
CREATE OR REPLACE TYPE “EXEM_TABLE”  IS TABLE OF VARCHAR2(500);
SELECT *
FROM THE (SELECT CAST(ALG_COMBINA.COMBINA AS EXEM_TABLE) FROM DUAL) A
Espero que gostem e ajudem nas suas combinações!
Abraços.
 

    Deixe uma resposta

    O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

    © 2019 All Rights Reserved. Cooperati.