CREATE OR REPLACE PACKAGE ackermann IS /* File: ackermann-memo.pls Explicit memo-fn version of ackermann's function Without memorization: Ackermann(3,10) = 8189 44698325 calls With memorization: Ackermann(3,10) = 8189 20481 calls, 4103 cache hits (functional languages can do this transparently by currying with the memo() function, eg "let ackermann = memofn(ackermann);" ) */ TYPE param2 IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER; TYPE memo2d IS TABLE of param2 INDEX BY PLS_INTEGER; FUNCTION memofn(x IN PLS_INTEGER, y IN PLS_INTEGER) RETURN PLS_INTEGER; END ackermann;
CREATE OR REPLACE PACKAGE BODY ackermann IS cache memo2d; FUNCTION memofn(x IN PLS_INTEGER, y IN PLS_INTEGER) RETURN PLS_INTEGER IS r PLS_INTEGER; BEGIN -- previous computation already memorized? IF cache.EXISTS(x) AND cache(x).EXISTS(y) THEN RETURN cache(x)(y); END IF; IF x = 0 THEN r := (y+1); ELSIF y = 0 THEN r := (ackermann.memofn(x-1,1)); ELSE r := (ackermann.memofn(x-1,ackermann.memofn(x,y-1))); END IF; cache(x)(y) := r; -- memorize new result RETURN r; END; END;
set serveroutput on BEGIN DBMS_Output.put_line('Ackermann(3, 10) = ' || ackermann.memofn(3, 10)); END;