You're welcome. Only a few small changes (highlighted in bold below) to the previous code are needed to create a new function VCDVAL that returns 1 if the last digit of the argument is the correct Verhoeff check digit and 0 otherwise:
/* Validate a check digit from a digit string S according to the Verhoeff algorithm,
using tables and formulas from https://en.wikipedia.org/wiki/Verhoeff_algorithm (2024-05-17) */
proc fcmp outlib=work.funcs.test;
function vcdval(s $);
array d[10,10] /nosymbols (0 1 2 3 4 5 6 7 8 9
1 2 3 4 0 6 7 8 9 5
2 3 4 0 1 7 8 9 5 6
3 4 0 1 2 8 9 5 6 7
4 0 1 2 3 9 5 6 7 8
5 9 8 7 6 0 4 3 2 1
6 5 9 8 7 1 0 4 3 2
7 6 5 9 8 2 1 0 4 3
8 7 6 5 9 3 2 1 0 4
9 8 7 6 5 4 3 2 1 0);
array v[10] /nosymbols (0 4 3 2 1 5 6 7 8 9);
array p[8,10] /nosymbols (0 1 2 3 4 5 6 7 8 9
1 5 7 6 2 8 3 0 9 4
5 8 0 3 7 9 6 1 4 2
8 9 1 6 0 4 3 5 2 7
9 4 5 3 1 2 6 8 7 0
4 2 8 6 5 7 3 9 0 1
2 7 9 3 8 0 6 4 1 5
7 0 4 6 9 1 3 2 5 8);
array n[1] /nosymbols;
k=length(s);
call dynamic_array(n, k);
do i=1 to k;
n[i]=input(char(s,k-i+1),1.);
end;
c=0;
do i=1 to k;
c=d[c+1,p[mod(i-1,8)+1,n[i]+1]+1];
end;
val=(c=0);
return(val);
endsub;
run;
options cmplib=work.funcs;
/* Example */
data _null_;
if vcdval('2363') then put 'Check digit is correct.';
else put 'Check digit is wrong.';
run;
Having the two functions in place, it's easy to check their consistency on, say, one million random digit strings with lengths ranging from 1 to, e.g., 40:
358 data _null_;
359 call streaminit('MT64',27182818);
360 length s $40;
361 do i=1 to 1e6;
362 s=' ';
363 do j=1 to rand('integer',40);
364 substr(s,j,1)=put(rand('integer',0,9),1.);
365 end;
366 if vcdval(cats(s,vcd(s)))=0 then do;
367 put 'ER' 'ROR: Wrong check digit encountered for ' s=;
368 stop;
369 end;
370 end;
371 run;
NOTE: DATA statement used (Total process time):
real time 20.93 seconds
cpu time 20.79 seconds
... View more