Here's another suggestion:
data;
set isbn;
s=0;
do j=1 to 9;
s+j*input(char(isbn,j),1.);
end;
m=mod(s,11);
c=put(ifn(m=j,.X,m),1.)=char(isbn,j);
put isbn c;
run;
The report is only suitable for internal purposes as it contains just the ISBNs and a "correctness flag" c, i.e., c=0 indicates fake ISBNs, c=1 correct ones:
0434488665 0
2018166516 0
9405643837 0
6032522768 1
4394205952 0
2353276079 0
6493135591 1
6776994355 0
2227835451 1
8018735913 1
0841779538 1
8730652341 0
1594122350 1
224320418X 0
6857923406 0
3967006111 0
9537581977 1
1283514257 1
566485052X 0
6994588902 0
9236137644 1
7649918275 0
458574645X 0
7601111520 1
1911465988 1
266671036X 1
4287030303 1
2561407012 1
6933010252 1
4278675463 0
351049735X 1
0566910450 0
9802436077 0
195432331X 1
8421179217 1
0979272564 1
3584795834 1
0713565068 0
9074601407 0
0168786583 1
I used a bit of algebra to simplify the formulas.
Of course, the code could be shortened further. For example:
At the cost of an even uglier report (but now including the book titles) one could replace "isbn c" by "_all_" in the final PUT statement.
An ugly log could be achieved by omitting the INPUT function in the sum statement.
The name of the input dataset could also be omitted if the code is submitted directly after the DATA step creating dataset ISBN (risky!).
Sacrificing code readability, one could write all statements on the same line, without separating blanks, where possible.
However, the resulting DATA step (containing 108 characters) violates so many coding standards that it must be hidden behind a spoiler.
data;set;s=0;do j=1to 9;s+j*char(isbn,j);end;m=mod(s,11);c=put(ifn(m=j,.X,m),1.)=char(isbn,j);put _all_;run;
... View more