create or replace package body Plch_MM is
c_Digits constant pls_integer := 7;
c_Pclue constant varchar2(1) := 'P';
c_Nclue constant varchar2(1) := 'N';
cursor c_Nums(b_Digits pls_integer) is
with dig_set as (select to_char(level) dig from dual connect by level <= b_Digits)
select d1.dig||d2.dig||d3.dig||d4.dig num
from dig_set d1, dig_set d2, dig_set d3, dig_set d4
where d1.dig != d2.dig and d1.dig != d3.dig and d1.dig != d4.dig
and d2.dig != d3.dig and d2.dig!=d4.dig
and d3.dig != d4.dig;
function Get_Hint(i_Candid varchar2, i_Gues varchar2) return varchar2 is
v_Pos pls_integer;
v_Ret varchar2(20);
begin
for ii in 1 .. 4 loop
v_Pos := instr(i_Candid, substr(i_Gues, ii, 1));
if v_Pos = ii then
v_Ret := v_Ret || c_Pclue;
elsif v_Pos > 0 then
v_Ret := c_Nclue || v_Ret;
end if;
end loop;
return (v_Ret);
end;
function Is_Solution(i_Candid varchar2, i_Guesses Str_Tab_T, i_Hints Str_Tab_T) return boolean is
v_Ret boolean;
v_Ndx pls_integer := i_Guesses.first;
begin
v_Ret := v_Ndx is not null;
while v_Ret and v_Ndx is not null loop
v_Ret := Get_Hint(i_Candid, i_Guesses(v_Ndx)) = i_Hints(v_Ndx);
v_Ndx := i_Guesses.next(v_Ndx);
end loop;
return (v_Ret);
end;
-- Main function
function Get_Solutions(i_Turn_List varchar2) return Str_Tab_T pipelined is
v_Guesses Str_Tab_T := Str_Tab_T();
v_Hints Str_Tab_T := Str_Tab_T();
-- Make from the turn list two tables of guesses and hints
-- '2461NP, 2734NP, 2153NP' => {2461, 2734, 2153} and {NP, NP, NP}
procedure Make_Turns_Tab is
v_Str varchar2(2000);
v_Turn varchar2(20);
v_Pos pls_integer;
begin
v_Str := upper(replace(i_Turn_List, ' '));
while nvl(length(v_Str), 0) > 0 loop
v_Pos := instr(v_Str, ',');
if v_Pos > 0 then
v_Turn := substr(v_Str, 1, v_Pos-1);
v_Str := substr(v_Str, v_Pos +1);
else
v_Turn := v_Str;
v_Str := '';
end if;
v_Guesses.extend;
v_Hints.extend;
v_Guesses(v_Guesses.count) := substr(v_Turn, 1, 4);
v_Hints(v_Hints.count) := substr(v_Turn, 5);
end loop;
end;
begin
Make_Turns_Tab();
for r_Row in c_Nums(c_Digits) loop
if Is_Solution(r_Row.Num, v_Guesses, v_Hints) then
pipe row(r_Row.Num);
end if;
end loop;
return;
end;
end Plch_MM;