# Mastermind Solver by Hamid Talebian

• Script Name Mastermind Solver by Hamid Talebian
• Description Hamid created this script to verify a particular combination of digits as a solution the weekly PL/SQL Challenge logic quiz (modeled after the classic Mastermind game).
• Category PL/SQL General
• Contributor Steven Feuerstein (Oracle)
• Created Thursday May 11, 2017
• Statement 1
``````create or replace package Plch_MM
/*
Automatic Solution Generator for
PL/SQL Challenge's version of Mastermind

Author: Hamid Talebian

Permission granted by author to make it available to others to
use and modify to their own purposes.

*/
is
type Str_Tab_T is table of varchar2(100);

function Get_Solutions(i_Turn_List varchar2) return Str_Tab_T pipelined;

-- i_Turn_List: A comma separated list of guesses and hints.
--    The hints must begin with N clues (if any) and then P clues, thus PN and NPN are not allowed
-- Sample of usage:
-- v_Sol := Plch_MM.Get_Solutions('2461NP, 2734NP, 2153NP');
-- select * from table (Plch_MM.Get_Solutions('4 5 6 7 n n p,4 3 5 6 n n,7 5 4 2 n p'))
end Plch_MM; ``````
Package created.
• Statement 2
``````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; ``````
Package Body created.
• Statement 3
``````SELECT *
FROM TABLE (plch_mm.get_solutions ('4 3 2 1 n n,6 4 3 7 n n')) ``````
COLUMN_VALUE
1276
1546
1563
1564
1573
1574
1645
1653
1654
1672
1745
1753
1754
1762
2176
2546
2563
2564
2573
2574
2645
2653
2654
2716
2745
2753
2754
3156
3165
3175
3256
3265
3275
3516
3562
3572
3615
3652
3715
3752
5146
5163
5164
5173
5174
5246
5263
5264
5273
5274
5613
5614
5642
5713
5714
5742
7145
7153
7154
7162
7216
7245
7253
7254
7513
7514
7542
7612

68 rows selected.

# Additional Information

• Database on OTN