-- File: send_more_money.sql -- Version: 1.2 -- Last Changed: 2016-12-30 -- by: Damir; https://www.damirsystems.com -- Project: Send More Money Puzzle -- DB: PostgreSQL -- Return True if there are no duplicates in the input array. -- CREATE OR REPLACE FUNCTION all_different(arr Integer[]) RETURNS Boolean AS $BODY$ DECLARE crd Integer ; cnt Integer ; rslt Boolean ; BEGIN crd := cardinality(arr); select count(distinct a) into cnt from unnest(arr) as a; -- expose edge cases [], [x] CASE WHEN crd = 0 THEN rslt := FALSE; -- [] empty array WHEN crd = 1 THEN rslt := TRUE; -- [x] one element only WHEN cnt = crd THEN rslt := TRUE ; ELSE rslt := FALSE; END CASE ; RETURN rslt; END; $BODY$ LANGUAGE plpgsql; -- The final query packaged into a view. -- CREATE OR REPLACE VIEW Send_MM AS with Digit as ( -- {0, 1, ... 9} select generate_series(0,9)::Integer as z ), Srch as ( -- Cartesian product and constraints select St.z as S , Et.z as E , Nt.z as N , Dt.z as D , Mt.z as M , Ot.z as O , Rt.z as R , Yt.z as Y from Digit as St cross join Digit as Et cross join Digit as Nt cross join Digit as Dt cross join Digit as Mt cross join Digit as Ot cross join Digit as Rt cross join Digit as Yt where Mt.z = 1 and St.z >= 8 and (Dt.z + Et.z) % 10 = Yt.z and Dt.z * 1 + Nt.z * 10 + Et.z * 100 + St.z * 1000 + Et.z * 1 + Rt.z * 10 + Ot.z * 100 + Mt.z * 1000 = Yt.z * 1 + Et.z * 10 + Nt.z * 100 + Ot.z * 1000 + Mt.z * 10000 ) -- check for all different select S,E,N,D,M,O,R,Y from Srch where all_different(ARRAY[S,E,N,D,M,O,R,Y]) ;