ISBN13 check digit: Difference between revisions

m
m (→‎{{header|Haskell}}: Tidied variant expressed in terms of cycle.)
(70 intermediate revisions by 33 users not shown)
Line 1:
{{task}}
 
;Task:
Validate the check digit of an ISBN-13 code:
::*   Multiply every other digit by  '''3'''.
::*   Add these numbers and the digitsother togetherdigits.
::*   Take the remainder of this number after division by  '''10'''.
::*   If it is  '''0''',   the ISBN-13 check digit is correct.
 
 
UseYou might use the following codes for testing:
::::*   978-17343145020596528126       (good)
::::*   978-17343145090596528120         (bad)
::::*   978-1788399081       (good)
::::*   978-1788399083         (bad)
Line 26:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F is_isbn13(=n)
n = n.replace(‘-’, ‘’).replace(‘ ’, ‘’)
I n.len != 13
Line 34:
R product % 10 == 0
 
V tests = |‘978-0596528126
978-0596528120
978-1734314502
978-1788399081
978-1734314509
978-1788399083’.split("\n")
978-1788399081
978-1788399083’.trim("\n").split("\n")
 
L(t) tests
print(‘ISBN13 ’t‘ validates ’is_isbn13(t))</langsyntaxhighlight>
 
{{out}}
<pre>
ISBN13 978-17343145020596528126 validates 1B
ISBN13 978-17343145090596528120 validates 0B
ISBN13 978-1788399081 validates 1B
ISBN13 978-1788399083 validates 0B
Line 53 ⟶ 52:
=={{header|8080 Assembly}}==
 
<langsyntaxhighlight lang="8080asm"> org 100h
jmp demo
;;; ---------------------------------------------------------------
Line 119 ⟶ 118:
jmp 5
good: db 'good$'
bad: db 'bad$'</langsyntaxhighlight>
 
{{out}}
 
<pre>A>isbn13 978-17343145020596528126
good
A>isbn13 978-17343145090596528120
bad
A>isbn13 978-1788399081
Line 134 ⟶ 133:
=={{header|8086 Assembly}}==
 
<langsyntaxhighlight lang="asm"> cpu 8086
bits 16
org 100h
Line 187 ⟶ 186:
section .data
good: db 'good$'
bad: db 'bad$'</langsyntaxhighlight>
 
{{out}}
 
<pre>C:\>isbn13 978-17343145020596528126
good
C:\>isbn13 978-17343145090596528120
bad
C:\>isbn13 978-1788399081
Line 199 ⟶ 198:
C:\>isbn13 978-1788399083
bad</pre>
 
=={{header|ABC}}==
<syntaxhighlight lang="abc">HOW TO REPORT valid.isbn13 str:
PUT {} IN digits
FOR d IN {0..9}: PUT d IN digits["`d`"]
IF #str <> 14 OR str item 4 <> '-': FAIL
PUT 1, 0 IN mul, sum
FOR c IN str|3 ^ str@5:
IF c not.in keys digits: FAIL
PUT sum + digits[c] * mul IN sum
PUT 4 - mul IN mul
REPORT sum mod 10 = 0
 
PUT {} IN tests
PUT "978-0596528126" IN tests[1]
PUT "978-0596528120" IN tests[2]
PUT "978-1788399081" IN tests[3]
PUT "978-1788399083" IN tests[4]
 
FOR test IN tests:
SELECT:
valid.isbn13 test: WRITE test^": good"/
ELSE: WRITE test^": bad"/</syntaxhighlight>
{{out}}
<pre>978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang="action!">INCLUDE "D2:CHARTEST.ACT" ;from the Action! Tool Kit
 
BYTE FUNC CheckISBN13(CHAR ARRAY t)
BYTE i,index,sum,v
 
sum=0 index=0
FOR i=1 TO t(0)
DO
v=t(i)
IF IsDigit(v) THEN
v==-'0
IF index MOD 2=1 THEN
v==*3
FI
sum==+v
index==+1
ELSEIF v#' AND v#'- THEN
RETURN (0)
FI
OD
IF index#13 OR sum MOD 10#0 THEN
RETURN (0)
FI
RETURN (1)
 
PROC Test(CHAR ARRAY t)
BYTE correct
 
correct=CheckISBN13(t)
Print(t) Print(" is ")
IF correct THEN
PrintE("correct")
ELSE
PrintE("incorrect")
FI
RETURN
 
PROC Main()
Put(125) PutE() ;clear screen
 
Test("978-0596528126")
Test("978-0596528120")
Test("978-1788399081")
Test("978-1788399083")
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/ISBN13_check_digit.png Screenshot from Atari 8-bit computer]
<pre>
978-0596528126 is correct
978-0596528120 is incorrect
978-1788399081 is correct
978-1788399083 is incorrect
</pre>
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">with Ada.Text_IO;
 
procedure ISBN_Check is
 
function Is_Valid (ISBN : String) return Boolean is
Odd : Boolean := True;
Sum : Integer := 0;
Value : Integer;
begin
for I in ISBN'Range loop
if ISBN (I) in '0' .. '9' then
Value := Character'Pos (ISBN (I)) - Character'Pos ('0');
if Odd then
Sum := Sum + Value;
else
Sum := Sum + 3 * Value;
end if;
Odd := not Odd;
end if;
end loop;
return Sum mod 10 = 0;
end Is_Valid;
 
procedure Show (ISBN : String) is
use Ada.Text_IO;
Valid : constant Boolean := Is_Valid (ISBN);
begin
Put (ISBN); Put (" ");
Put ((if Valid then "Good" else "Bad"));
New_Line;
end Show;
begin
Show ("978-0596528126");
Show ("978-0596528120");
Show ("978-1788399081");
Show ("978-1788399083");
end ISBN_Check;</syntaxhighlight>
{{out}}
<pre>978-0596528126 Good
978-0596528120 Bad
978-1788399081 Good
978-1788399083 Bad</pre>
 
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
<langsyntaxhighlight lang="algol68">BEGIN # Check some IsBN13 check digits #
# returns TRUE if the alledged isbn13 has the correct check sum, #
# FALSE otherwise #
Line 224 ⟶ 350:
END; # check isbn13 #
# task test cases #
[]STRING tests = ( "978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083" );
[]BOOL expected = ( TRUE, FALSE, TRUE, FALSE );
FOR pos FROM LWB tests TO UPB tests DO
Line 236 ⟶ 362:
)
OD
END</langsyntaxhighlight>
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
Line 247 ⟶ 373:
=={{header|APL}}==
{{works with|Dyalog APL}}
<langsyntaxhighlight lang="apl">check_isbn13←{
13≠⍴n←(⍵∊⎕D)/⍵:0
0=10|(⍎¨n)+.×13⍴1 3
}</langsyntaxhighlight>
 
{{out}}
 
<pre> check_isbn13¨ '978-17343145020596528126' '978-17343145090596528120' '978-1788399081' '978-1788399083'
1 0 1 0</pre>
 
Line 260 ⟶ 386:
===Composition of pure functions===
 
<langsyntaxhighlight lang="applescript">-------------------- ISBN13 CHECK DIGIT --------------------
 
-- isISBN13 :: String -> Bool
Line 289 ⟶ 415:
end script
map(test, {"978-17343145020596528126", "978-17343145090596528120", ¬
"978-1788399081", "978-1788399083"})
end run
Line 464 ⟶ 590:
return lst
end tell
end zipWith</langsyntaxhighlight>
{{Out}}
<pre>{{"978-17343145020596528126", true}, {"978-17343145090596528120", false}, {"978-1788399081", true}, {"978-1788399083", false}}</pre>
 
===Straightforward===
Line 472 ⟶ 598:
This task ''can'' be tackled very simply by working through the numeric text two characters at a time:
 
<langsyntaxhighlight lang="applescript">on validateISBN13(ISBN13)
if (ISBN13's class is not text) then return false
Line 500 ⟶ 626:
set output to {}
set verdicts to {"bad", "good"}
repeat with thisISBN13 in {"978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"}
set isValid to validateISBN13(thisISBN13)
set end of output to thisISBN13 & ": " & item ((isValid as integer) + 1) of verdicts
Line 509 ⟶ 635:
set output to output as text
set AppleScript's text item delimiters to astid
return output</langsyntaxhighlight>
 
{{output}}
<pre>"978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad"</pre>
Line 519 ⟶ 645:
Or it can be handled purely numerically. Since the "weights" alternate and are palindromic, it makes no difference whether the last digit or the first is treated as the check digit. In fact, if preferred, the repeat below can go round 7 times with the <tt>return</tt> line as simply: <tt>return (sum mod 10 = 0)</tt>.
 
<langsyntaxhighlight lang="applescript">on validateISBN13(ISBN13)
if (ISBN13's class is not text) then return false
Line 543 ⟶ 669:
return ((sum + ISBN13) mod 10 = 0)
end validateISBN13</langsyntaxhighlight>
 
=={{header|Arturo}}==
 
<langsyntaxhighlight lang="rebol">validISBN?: function [isbn][
currentCheck: to :integer to :string last isbn
isbn: map split chop replace isbn "-" "" ='d -> [to :integer] d
 
s: 0
Line 561 ⟶ 687:
 
tests: [
"978-17343145020596528126" "978-17343145090596528120"
"978-1788399081" "978-1788399083"
]
Line 567 ⟶ 693:
loop tests 'test [
print [test "=>" validISBN? test]
]</langsyntaxhighlight>
 
{{out}}
 
<pre>978-17343145020596528126 => true
978-17343145090596528120 => false
978-1788399081 => true
978-1788399083 => false</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">ISBN13_check_digit(n){
for i, v in StrSplit(RegExReplace(n, "[^0-9]"))
sum += !Mod(i, 2) ? v*3 : v
return n "`t" (Mod(sum, 10) ? "(bad)" : "(good)")
}</langsyntaxhighlight>
Examples:<langsyntaxhighlight AutoHotkeylang="autohotkey">output := ""
nums := ["978-17343145020596528126","978-17343145090596528120","978-1788399081","978-1788399083"]
for i, n in nums
output .= ISBN13_check_digit(n) "`n"
MsgBox % output
return</langsyntaxhighlight>
{{out}}
<pre>978-17343145020596528126 (good)
978-17343145090596528120 (bad)
978-1788399081 (good)
978-1788399083 (bad)</pre>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f ISBN13_CHECK_DIGIT.AWK
BEGIN {
arr[++n] = "978-17343145020596528126"
arr[++n] = "978-17343145090596528120"
arr[++n] = "978-1788399081"
arr[++n] = "978-1788399083"
Line 618 ⟶ 744:
return(substr(isbn,13,1) == check_digit ? "OK" : sprintf("NG check digit S/B %d",check_digit))
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
978-17343145020596528126 OK
978-17343145090596528120 NG check digit S/B 2
978-1788399081 OK
978-1788399083 NG check digit S/B 1
Line 628 ⟶ 754:
0820424528 NG length
</pre>
 
=={{header|BASIC256}}==
{{trans|Ring}}
<syntaxhighlight lang="vb">arraybase 1
dim isbn = {"978-0596528126", "978-0596528120", "978-1788399081", "978-1788399083", "978-2-74839-908-0", "978-2-74839-908-5", "978 1 86197 876 9"}
 
for n = 1 to isbn[?]
sum = 0
isbnStr = isbn[n]
isbnStr = replace(isbnStr, "-", "")
isbnStr = replace(isbnStr, " ", "")
for m = 1 to length(isbnStr)
if m mod 2 = 0 then
num = 3 * int(mid(isbnStr, m, 1))
else
num = int(mid(isbnStr, m, 1))
end if
sum += num
next m
if sum mod 10 = 0 then
print isbn[n]; ": good"
else
print isbn[n]; ": bad"
end if
next n</syntaxhighlight>
 
=={{header|BCPL}}==
<syntaxhighlight lang="bcpl">get "libhdr"
 
let checkISBN(s) = valof
$( let tally = 0
unless s%0 = 14 resultis false
unless s%4 = '-' resultis false
for i=1 to 3
$( let digit = s%i-'0'
test i rem 2 = 0
do tally := tally + 3 * digit
or tally := tally + digit
$)
for i=5 to 14
$( let digit = s%i-'0'
test i rem 2 = 0
do tally := tally + digit
or tally := tally + 3 * digit
$)
resultis tally rem 10 = 0
$)
 
let show(s) be
writef("%S: %S*N", s, checkISBN(s) -> "good", "bad")
 
let start() be
$( show("978-0596528126")
show("978-0596528120")
show("978-1788399081")
show("978-1788399083")
$)</syntaxhighlight>
{{out}}
<pre>978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
 
int check_isbn13(const char *isbn) {
Line 656 ⟶ 847:
int main() {
int i;
const char* isbns[] = {"978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"};
for (i = 0; i < 4; ++i) {
printf("%s: %s\n", isbns[i], check_isbn13(isbns[i]) ? "good" : "bad");
}
return 0;
}</langsyntaxhighlight>
 
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
Line 673 ⟶ 864:
=={{header|C++}}==
{{trans|C}}
<langsyntaxhighlight lang="cpp">#include <iostream>
 
bool check_isbn13(std::string isbn) {
Line 702 ⟶ 893:
 
int main() {
auto isbns = { "978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083" };
for (auto isbn : isbns) {
std::cout << isbn << ": " << (check_isbn13(isbn) ? "good" : "bad") << '\n';
Line 708 ⟶ 899:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
 
=={{header|C sharp}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Linq;
 
Line 722 ⟶ 913:
{
public static void Main() {
Console.WriteLine(CheckISBN13("978-17343145020596528126"));
Console.WriteLine(CheckISBN13("978-17343145090596528120"));
Console.WriteLine(CheckISBN13("978-1788399081"));
Console.WriteLine(CheckISBN13("978-1788399083"));
Line 738 ⟶ 929:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 745 ⟶ 936:
True
False</pre>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">isbn13_check = proc (s: string) returns (bool)
if string$size(s) ~= 14 then return(false) end
if s[4] ~= '-' then return(false) end
begin
check: int := 0
for i: int in int$from_to(1, 14) do
if i=4 then continue end
d: int := int$parse(string$c2s(s[i]))
if i=2 cor (i>4 cand i//2=1) then d := d*3 end
check := check + d
end
return(check//10 = 0)
end except when bad_format:
return(false)
end
end isbn13_check
 
start_up = proc ()
po: stream := stream$primary_output()
tests: array[string] := array[string]$
["978-0596528126",
"978-0596528120",
"978-1788399081",
"978-1788399083"]
for test: string in array[string]$elements(tests) do
stream$puts(po, test)
stream$puts(po, ": ")
if isbn13_check(test)
then stream$putl(po, "good")
else stream$putl(po, "bad")
end
end
end start_up</syntaxhighlight>
{{out}}
<pre>978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
 
=={{header|COBOL}}==
{{works with|GnuCOBOL}}
<langsyntaxhighlight COBOLlang="cobol"> ******************************************************************
* Author: Jay Moseley
* Date: November 10, 2019
Line 775 ⟶ 1,007:
01 IX PIC S9(4) COMP.
01 TEST-ISBNS.
02 FILLER PIC X(14) VALUE '978-17343145020596528126'.
02 FILLER PIC X(14) VALUE '978-17343145090596528120'.
02 FILLER PIC X(14) VALUE '978-1788399081'.
02 FILLER PIC X(14) VALUE '978-1788399083'.
Line 887 ⟶ 1,119:
 
END FUNCTION validISBN13.
</syntaxhighlight>
</lang>
 
{{out}}
 
<pre>978-17343145020596528126 (good)
978-17343145090596528120 (bad)
978-1788399081 (good)
978-1788399083 (bad)
</pre>
 
=={{header|Cowgol}}==
<syntaxhighlight lang="cowgol">include "cowgol.coh";
sub check_isbn13(isbn: [uint8]): (r: uint8) is
Line 923 ⟶ 1,156:
var isbns: [uint8][] := {
"978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"
};
Line 933 ⟶ 1,166:
print(result[check_isbn13(isbns[n])]);
n := n + 1;
end loop;</syntaxhighlight>
{{out}}
<pre>978-1734314502: good
<pre>978-17343145090596528126: badgood
978-0596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
Line 941 ⟶ 1,175:
=={{header|D}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="d">import std.stdio;
 
bool isValidISBN13(string text) {
Line 961 ⟶ 1,195:
 
unittest {
assert(isValidISBN13("978-17343145020596528126"));
assert(!isValidISBN13("978-17343145090596528120"));
assert(isValidISBN13("978-1788399081"));
assert(!isValidISBN13("978-1788399083"));
}</langsyntaxhighlight>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
 
 
<syntaxhighlight lang="Delphi">
 
function ValidateISBN(ISBN: string): boolean;
{Validate an ISBN number}
var I,N,Sum: integer;
begin
Sum:=0;
{Go througha chars, ignoring non-digits}
for I:=1 to Length(ISBN) do
if ISBN[I] in ['0'..'9'] then
begin
N:=StrToInt(ISBN[I]);
{Every other digit multiplied by 3}
if (I and 1)=1 then N:=N*3;
{Sum digits}
Sum:=Sum+N;
end;
{The sum must be an even multiple of 10}
Result:=(Sum mod 10)=0;
end;
 
procedure ValidateAndShow(Memo: TMemo; ISBN: string);
{Validate ISBN number and show the result}
var S: string;
begin
S:=ISBN;
if ValidateISBN(ISBN) then S:=S+' (Good)'
else S:=S+' (Bad)';
Memo.Lines.Add(S);
end;
 
procedure TestISBNSet(Memo: TMemo);
{Test supplied set of ISBN numbers}
begin
ValidateAndShow(Memo,'978-0596528126'); //(good)
ValidateAndShow(Memo,'978-0596528120'); //(bad)
ValidateAndShow(Memo,'978-1788399081'); //(good)
ValidateAndShow(Memo,'978-1788399083'); //(bad)
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
978-0596528126 (Good)
978-0596528120 (Bad)
978-1788399081 (Good)
978-1788399083 (Bad)
 
</pre>
 
 
=={{header|Draco}}==
<syntaxhighlight lang="draco">proc nonrec isbn13_check(*char isbn) bool:
byte n, check, d;
char cur;
bool ok;
n := 0;
check := 0;
ok := true;
while
cur := isbn*;
isbn := isbn + 1;
ok and cur ~= '\e'
do
if n=3 then
if cur ~= '-' then ok := false fi
elif cur<'0' or cur>'9' then
ok := false
else
d := cur - '0';
if n=1 or (n>3 and n&1 = 0) then
d := d * 3;
fi;
check := check + d
fi;
n := n + 1
od;
ok and n = 14 and check%10 = 0
corp
 
proc nonrec test(*char isbn) void:
writeln(isbn, ": ",
if isbn13_check(isbn) then "good" else "bad" fi)
corp
 
proc nonrec main() void:
test("978-0596528126");
test("978-0596528120");
test("978-1788399081");
test("978-1788399083")
corp</syntaxhighlight>
{{out}}
<pre>978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
 
=={{header|EasyLang}}==
<syntaxhighlight lang="text">
func ISBN13check isbn$ .
for c$ in strchars isbn$
if c$ <> "-"
ndigs += 1
.
dig = number c$
if ndigs mod 2 = 0
dig *= 3
.
sum += dig
.
if sum mod 10 <> 0
return 0
.
return 1
.
codes$[] = [ "978-0596528126" "978-0596528120" "978-1788399081" "978-1788399083" ]
for code$ in codes$[]
if ISBN13check code$ = 1
print code$ & " is a valid ISBN"
else
print code$ & " is not a valid ISBN"
.
.
</syntaxhighlight>
{{out}}
<pre>
978-0596528126 is a valid ISBN
978-0596528120 is not a valid ISBN
978-1788399081 is a valid ISBN
978-1788399083 is not a valid ISBN
</pre>
 
=={{header|Excel}}==
===LAMBDA===
 
Binding the name '''ISBN13Check''' to the following lambda expression in the Name Manager of the Excel WorkBook:
 
(See [https://www.microsoft.com/en-us/research/blog/lambda-the-ultimatae-excel-worksheet-function/ LAMBDA: The ultimate Excel worksheet function])
 
{{Works with|Office 365 betas 2021}}
<syntaxhighlight lang="lisp">ISBN13Check
=LAMBDA(s,
LET(
ns, FILTERP(
LAMBDA(v,
NOT(ISERROR(v))
)
)(
VALUE(CHARSROW(s))
),
ixs, SEQUENCE(
1, COLUMNS(ns),
1, 1
),
 
0 = MOD(
SUM(
IF(0 <> MOD(ixs, 2),
INDEX(ns, ixs),
3 * INDEX(ns, ixs)
)
),
10
)
)
)</syntaxhighlight>
 
and also assuming the following generic bindings in the Name Manager for the WorkBook:
 
<syntaxhighlight lang="lisp">CHARSROW
=LAMBDA(s,
MID(s,
SEQUENCE(1, LEN(s), 1, 1),
1
)
)
 
 
FILTERP
=LAMBDA(p,
LAMBDA(xs,
FILTER(xs, p(xs))
)
)
 
 
ISDIGIT
=LAMBDA(c,
LET(
ic, CODE(c),
 
AND(47 < ic, 58 > ic)
)
)</syntaxhighlight>
 
{{Out}}
{| class="wikitable"
|-
|||style="text-align:right; font-family:serif; font-style:italic; font-size:120%;"|fx
! colspan="2" style="text-align:left; vertical-align: bottom; font-family:Arial, Helvetica, sans-serif !important;"|=ISBN13Check(A2)
|- style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff;"
|
| A
| B
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 1
| style="font-weight:bold" | Candidate string
| style="font-weight:bold" | ISBN13 checked
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 2
| 978-0596528126
| style="background-color:#cbcefb" | TRUE
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 3
| 978-0596528120
| FALSE
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 4
| 978-1788399081
| TRUE
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 5
| 978-1788399083
| FALSE
|}
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: combinators.short-circuit formatting kernel math
math.functions math.parser math.vectors qw sequences
sequences.extras sets unicode ;
Line 980 ⟶ 1,446:
{ [ length 13 = ] [ [ digit? ] all? ] [ (isbn13?) ] } 1&& ;
 
qw{ 978-17343145020596528126 978-17343145090596528120 978-1788399081 978-1788399083 }
[ dup isbn13? "good" "bad" ? "%s: %s\n" printf ] each</langsyntaxhighlight>
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
</pre>
 
=={{header|Forth}}==
The following word not only identifies correct 13 digit ISBN (and EAN) codes, but also 8 digit EAN and GTIN codes.
<syntaxhighlight lang="text">: is-digit [char] 0 - 10 u< ;
 
: isbn? ( a n -- f)
1- chars over + 2>r 0 1 2r> ?do
dup i c@ dup is-digit \ get length and factor, setup loop
if [char] 0 - * rot + swap 3 * 8 mod else drop drop then
-1 chars +loop drop 10 mod 0= \ now calculate checksum
;</syntaxhighlight>
{{out}}
In Forth, a "true" value is indicated by "-1".
<pre>
s" 978-0596528126" isbn? . -1 ok
s" 978-0596528120" isbn? . 0 ok
s" 978-1788399081" isbn? . -1 ok
s" 978-1788399083" isbn? . 0 ok
</pre>
 
=={{header|Fortran}}==
<langsyntaxhighlight lang="fortran">
program isbn13
implicit none
 
character(len=14), dimension(4), parameter :: isbns=["978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"]
integer :: i
 
Line 1,028 ⟶ 1,513:
end function check_isbn13
end program isbn13
</syntaxhighlight>
</lang>
 
{{out}}
<pre>
978-17343145020596528126 : good
978-17343145090596528120 : bad
978-1788399081 : good
978-1788399083 : bad
Line 1,039 ⟶ 1,524:
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">#define ZEROC asc("0")
 
function is_num( byval c as string ) as boolean
Line 1,067 ⟶ 1,552:
end function
 
dim as string isbns(0 to 3) = { "978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083" }
dim as uinteger i
for i = 0 to 3
Line 1,075 ⟶ 1,560:
print isbns(i)+": bad"
end if
next i</langsyntaxhighlight>
 
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
</pre>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">// ISBN13 Check Digit
open System
 
let parseInput (input: string) =
Seq.map(fun c -> c |> string) input |> Seq.toList |> List.map(fun x -> Int32.Parse x)
 
[<EntryPoint>]
let main argv =
let isbnnum = parseInput (String.filter (fun x -> x <> '-') argv.[0])
// Multiply every other digit by 3
let everyOther = List.mapi (fun i x -> if i % 2 = 0 then x * 3 else x) isbnnum
// Sum the *3 list with the original list
let sum = List.sum everyOther + List.sum isbnnum
// If the remainder of sum / 10 is 0 then it's a valid ISBN13
if sum % 10 = 0 then
printfn "%s Valid ISBN13" argv.[0]
else
printfn "%s Invalid ISBN13" argv.[0]
0</syntaxhighlight>
 
{{out}}
<pre>978-0596528126 Valid ISBN13
978-0596528120 Inalid ISBN13
978-1788399081 Valid ISBN13
978-1788399083 Inalid ISBN13</pre>
 
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/ISBN13_check_digit}}
 
'''Solution'''
 
[[File:Fōrmulæ - ISBN13 check digit 01.png]]
 
'''Test cases'''
 
[[File:Fōrmulæ - ISBN13 check digit 02.png]]
 
[[File:Fōrmulæ - ISBN13 check digit 03.png]]
 
=={{header|Gambas}}==
{{trans|BASIC256}}
<syntaxhighlight lang="vbnet">Public Sub Main()
Dim isbn As String[] = ["978-0596528126", "978-0596528120", "978-1788399081", "978-1788399083", "978-2-74839-908-0", "978-2-74839-908-5", "978 1 86197 876 9"]
For n As Integer = 1 To isbn.Count
Dim sum As Integer = 0, num As Integer
Dim isbnStr As String = isbn[n]
isbnStr = Replace(isbnStr, "-", "")
isbnStr = Replace(isbnStr, " ", "")
For m As Integer = 1 To Len(isbnStr)
If m Mod 2 = 0 Then
num = 3 * CInt(Mid(isbnStr, m, 1))
Else
num = CInt(Mid(isbnStr, m, 1))
End If
sum += num
Next
If sum Mod 10 = 0 Then
Print isbn[n]; ": good"
Else
Print isbn[n]; ": bad"
End If
Next
End</syntaxhighlight>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,118 ⟶ 1,672:
 
func main() {
isbns := []string{"978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"}
for _, isbn := range isbns {
res := "bad"
Line 1,126 ⟶ 1,680:
fmt.Printf("%s: %s\n", isbn, res)
}
}</langsyntaxhighlight>
 
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
Line 1,137 ⟶ 1,691:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Data.Char (isDigitdigitToInt, digitToIntisDigit)
import Control.Monad (forM_)
import Text.Printf (printf)
 
testISBNs :: [String]
testISBNs = ["978-1734314502", "978-1734314509", "978-1788399081", "978-1788399083"]
 
pair :: Num a => [a] -> [(a, a)]
pair [] = []
pair xs = p (take 2 xs) : pair (drop 2 xs)
where
where p ps = case ps of (x:y:zs) -> (x,y)
p ps = case ps of
(x:zs) -> (x,0)
(x : y : zs) -> (x, y)
(x : zs) -> (x, 0)
 
validIsbn13 :: String -> Bool
validIsbn13 isbn
| length (digits isbn) /= 13 = False
| otherwise = calc isbn `rem` 10 == 0
where
where digits = map digitToInt . filter isDigit
calc digits = sum . map (\(x, y) -> x + y * 3)digitToInt . pairfilter . digitsisDigit
calc = sum . map (\(x, y) -> x + y * 3) . pair . digits
 
main :: IO ()
main =
main = forM_ testISBNs (\isbn -> printf "%s: Valid: %s\n" isbn (show $ validIsbn13 isbn))</lang>
mapM_
(printf "%s: Valid: %s\n" <*> (show . validIsbn13))
[ "978-0596528126",
"978-0596528120",
"978-1788399081",
"978-1788399083"
]</syntaxhighlight>
{{out}}
<pre>978-17343145020596528126: Valid: True
978-17343145090596528120: Valid: False
978-1788399081: Valid: True
978-1788399083: Valid: False</pre>
Line 1,167 ⟶ 1,727:
Or, expressed in terms of ''cycle'':
 
<langsyntaxhighlight lang="haskell">import Data.Char (digitToInt, isDigit)
 
isISBN13 :: String -> Bool
Line 1,180 ⟶ 1,740:
main :: IO ()
main =
mapM_ print $
(print . ((,) <*> isISBN13))
fmap
[ "978-0596528126",
((,) <*> isISBN13)
[ "978-17343145020596528120",
"978-17343145091788399081",
"978-17883990811788399083",
]</syntaxhighlight>
"978-1788399083"
]</lang>
{{Out}}
<pre>("978-17343145020596528126",True)
("978-17343145090596528120",False)
("978-1788399081",True)
("978-1788399083",False)</pre>
 
=={{header|IS-BASIC}}==
<langsyntaxhighlight ISlang="is-BASICbasic">100 PROGRAM "ISBN13.bas"
110 DO
120 PRINT :INPUT PROMPT "ISBN-13 code: ":IS$
Line 1,220 ⟶ 1,779:
330 LET SUM=SUM+VAL(ISBN$(13))
340 IF MOD(SUM,10)=0 THEN LET ISBN=-1
350 END DEF</langsyntaxhighlight>
 
=={{header|J}}==
<syntaxhighlight lang="j"> D =: '0123456789'
isbn13c =: D&([ check@:i. clean)
check =: 0 = 10 | lc
lc =: [ +/@:* weight
weight =: 1 3 $~ #
clean =: ] -. a. -. [</syntaxhighlight>
{{out}}
 
<syntaxhighlight lang="j"> isbn13c;._1 ' 978-0596528126 978-0596528120 978-1788399081 978-1788399083'
1 0 1 0</syntaxhighlight>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
<lang java>public static void main(){
public static void main(String[] args) {
System.out.println(isISBN13("978-1734314502"));
String[] isbn13s = {
System.out.println(isISBN13("978-1734314509"));
"978-0596528126",
"978-0596528120",
"978-1788399081",
"978-1788399083"
};
for (String isbn13 : isbn13s)
System.out.printf("%s %b%n", isbn13, validateISBN13(isbn13));
}
 
static boolean validateISBN13(String string) {
int[] digits = digits(string.strip().replace("-", ""));
return digits[12] == checksum(digits);
}
 
static int[] digits(String string) {
int[] digits = new int[13];
int index = 0;
for (char character : string.toCharArray()) {
if (character < '0' || character > '9')
throw new IllegalArgumentException("Invalid ISBN-13");
/* convert ascii to integer */
digits[index++] = Character.digit(character, 10);
}
return digits;
}
 
static int checksum(int[] digits) {
int total = 0;
int index = 0;
for (int digit : digits) {
if (index == 12) break;
if (index++ % 2 == 1) digit *= 3;
total += digit;
}
return 10 - (total % 10);
}
</syntaxhighlight>
<pre>
978-0596528126 true
978-0596528120 false
978-1788399081 true
978-1788399083 false
</pre>
<br />
An alternate demonstration
<syntaxhighlight lang="java">public static void main(){
System.out.println(isISBN13("978-0596528126"));
System.out.println(isISBN13("978-0596528120"));
System.out.println(isISBN13("978-1788399081"));
System.out.println(isISBN13("978-1788399083"));
Line 1,241 ⟶ 1,861:
return false;
}
</langsyntaxhighlight>{{out}}
<pre>
true
Line 1,248 ⟶ 1,868:
false
</pre>
 
=={{header|jq}}==
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq">
def isbn_check:
def digits: tostring | explode | map( select(. >= 48 and . <= 57) | [.] | implode | tonumber);
def sum(s): reduce s as $x (null; . + $x);
digits
| . as $digits
| sum(range(0;length;2) | $digits[.]) as $one
| (3 * sum(range(1;length;2) | $digits[.])) as $two
| (($one+$two) % 10) == 0;
 
def testingcodes:
["978-0596528126", "978-0596528120",
"978-1788399081", "978-1788399083"];
testingcodes[]
| "\(.): \(if isbn_check then "good" else "bad" end)"
</syntaxhighlight>
{{out}}
<pre>
978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">function isbncheck(str)
return sum(iseven(i) ? 3 * parse(Int, ch) : parse(Int, ch)
for (i, ch) in enumerate(replace(str, r"\D" => ""))) % 10 == 0
end
 
const testingcodes = ["978-17343145020596528126", "978-17343145090596528120",
"978-1788399081", "978-1788399083"]
 
Line 1,260 ⟶ 1,909:
println(code, ": ", isbncheck(code) ? "good" : "bad")
end
</langsyntaxhighlight>{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
</pre>
 
=={{header|K}}==
{{works with|ngn/k}}
<syntaxhighlight lang=K>digits: {x[&(x>"/")&x<":"]-"0"}
isbn13c: 0=10!+/{x*(#x)#1 3} digits@
 
isbn13c "978-0596528126"
1
isbn13c "978-0596528120"
0
isbn13c " 978-1788399081"
1
isbn13c "978-1788399083"
0</syntaxhighlight>
 
=={{header|Kotlin}}==
<syntaxhighlight lang="kotlin">
<lang Kotlin>
fun isValidISBN13(text: String): Boolean {
val isbn = text.replace(Regex("[- ]"), "")
Line 1,276 ⟶ 1,939:
.sum() % 10 == 0
}
</syntaxhighlight>
</lang>
 
Tested using Spek
<syntaxhighlight lang="kotlin">
<lang Kotlin>
describe("ISBN Utilities") {
mapOf(
"978-17343145020596528126" to true,
"978-17343145090596528120" to false,
"978-1788399081" to true,
"978-1788399083" to false
Line 1,296 ⟶ 1,959:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
Line 1,306 ⟶ 1,969:
 
=={{header|langur}}==
{{works with|langur|0.8.11}}
In this example, we map to multiple functions (actually 1 no-op).
<langsyntaxhighlight lang="langur">val .isbn13checkdigit = ffn(var .s) {
.s = replace(.s, RE/[\- ]/)
matching(.s -> re/^[0-9]{13}$/, .s) and
fold(ffn{+}, map [_, ffn{x *3}], s2n .s) div 10
}
 
val .tests = h{
"978-17343145020596528126": true,
"978-17343145090596528120": false,
"978-1788399081": true,
"978-1788399083": false,
Line 1,325 ⟶ 1,987:
write .key, ": ", if(.pass: "good"; "bad")
writeln if(.pass == .tests[.key]: ""; " (ISBN-13 CHECK DIGIT TEST FAILED)")
}</langsyntaxhighlight>
 
{{works with|langur|0.9.0}}
In this example, we set a for loop value as it progresses.
<lang langur>val .isbn13checkdigit = f(var .s) {
.s = replace(.s, RE/[\- ]/)
var .alt = true
matching(re/^[0-9]{13}$/, .s) and
for[=0] .d in s2n(.s) { _for += if(not= .alt: .d x 3; .d) } div 10
}
 
val .tests = h{
"978-1734314502": true,
"978-1734314509": false,
"978-1788399081": true,
"978-1788399083": false,
}
 
for .key of .tests {
val .pass = .isbn13checkdigit(.key)
write .key, ": ", if(.pass: "good"; "bad")
writeln if(.pass == .tests[.key]: ""; " (ISBN-13 CHECK DIGIT TEST FAILED)")
}</lang>
 
{{out}}
<pre>978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
Line 1,357 ⟶ 1,997:
=={{header|Lua}}==
{{trans|C}}
<langsyntaxhighlight lang="lua">function checkIsbn13(isbn)
local count = 0
local sum = 0
Line 1,391 ⟶ 2,031:
 
function main()
test("978-17343145020596528126")
test("978-17343145090596528120")
test("978-1788399081")
test("978-1788399083")
end
 
main()</langsyntaxhighlight>
{{out}}
<pre>978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
 
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[ValidISBNQ]
ValidISBNQ[iban_String] := Module[{i},
i = StringReplace[iban, {" " -> "", "-" -> ""}];
If[StringMatchQ[i, Repeated[DigitCharacter]],
i = ToExpression /@ Characters[i];
i[[2 ;; ;; 2]] *= 3;
Mod[Total[i], 10] == 0
,
False
]
]
ValidISBNQ["978-0596528126"]
ValidISBNQ["978-0596528120"]
ValidISBNQ["978-1788399081"]
ValidISBNQ["978-1788399083"]</syntaxhighlight>
{{out}}
<pre>True
False
True
False</pre>
 
=={{header|MiniScript}}==
This GUI implementation is for use with [http://miniscript.org/MiniMicro Mini Micro].
<syntaxhighlight lang="miniscript">
isISBN13 = function(n)
n = n.replace("-","").replace(" ","")
s = 0
for i in range(0, n.len-1,2)
s += n[i].val
end for
for i in range(1, n.len-1,2)
s += n[i].val * 3
end for
return not (s % 10)
end function
 
testValues = "978-0596528126 978-0596528120 978-1788399081 978-1788399083".split(" ")
for val in testValues
print val + " " + ["bad", "good"][isISBN13(val)]
end for
</syntaxhighlight>
{{out}}
<pre>
978-0596528126 good
978-0596528120 bad
978-1788399081 good
978-1788399083 bad</pre>
 
=={{header|Miranda}}==
<syntaxhighlight lang="miranda">main :: [sys_message]
main = [Stdout (lay (map test tests))]
 
test :: [char]->[char]
test isbn = isbn ++ ": good", if isbn13 isbn
= isbn ++ ": bad", otherwise
 
tests :: [[char]]
tests = ["978-0596528126",
"978-0596528120",
"978-1788399081",
"978-1788399083"]
 
isbn13 :: [char]->bool
isbn13 str = False, if #isbn ~= 13 \/ ~and (map digit isbn)
= check mod 10 = 0, otherwise
where isbn = filter (~= '-') str
digits = map (numval.(:[])) isbn
check = sum (zipwith (*) digits (concat (repeat [1,3])))
 
uncurry :: (*->**->***)->(*,**)->***
uncurry f (a,b) = f a b
 
zipwith :: (*->**->***)->[*]->[**]->[***]
zipwith f a b = map (uncurry f) (zip2 a b)</syntaxhighlight>
{{out}}
<pre>978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
 
=={{header|Modula-2}}==
<syntaxhighlight lang="modula2">MODULE ISBN;
FROM InOut IMPORT WriteString, WriteLn;
FROM Strings IMPORT Length;
 
PROCEDURE validISBN(s: ARRAY OF CHAR): BOOLEAN;
VAR total, i, length: CARDINAL;
BEGIN
total := 0;
length := Length(s);
IF (length # 14) OR (s[3] # '-') THEN
RETURN FALSE;
END;
FOR i := 0 TO length-1 DO
IF i # 3 THEN
IF (s[i] < '0') OR (s[i] > '9') THEN
RETURN FALSE;
ELSIF (i < 3) AND (i MOD 2 = 1) OR (i > 3) AND (i MOD 2 = 0) THEN
total := total + 3 * (ORD(s[i]) - ORD('0'));
ELSE
total := total + ORD(s[i]) - ORD('0');
END;
END;
END;
RETURN total MOD 10 = 0;
END validISBN;
 
PROCEDURE check(s: ARRAY OF CHAR);
BEGIN
WriteString(s);
WriteString(': ');
IF validISBN(s) THEN
WriteString('good');
ELSE
WriteString('bad');
END;
WriteLn;
END check;
 
BEGIN
check('978-0596528126');
check('978-0596528120');
check('978-1788399081');
check('978-1788399083');
END ISBN.</syntaxhighlight>
{{out}}
<pre>978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
Line 1,406 ⟶ 2,179:
=={{header|Nanoquery}}==
{{trans|Go}}
<langsyntaxhighlight lang="nanoquery">def checkIsbn13(isbn)
// remove any hyphens or spaces
isbn = str(isbn).replace("-","").replace(" ","")
Line 1,433 ⟶ 2,206:
end
 
isbns = {"978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"}
for isbn in isbns
res = "bad"
Line 1,441 ⟶ 2,214:
 
print format("%s: %s\n", isbn, res)
end</langsyntaxhighlight>
{{out}}
<pre>978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import strutils, strformat
 
func is_isbn*(s: string): bool =
Line 1,462 ⟶ 2,235:
 
when is_main_module:
let isbns = [ "978-17343145020596528126", "978-17343145090596528120",
"978-1788399081", "978-1788399083" ]
for isbn in isbns:
var quality: string = if is_isbn(isbn): "good" else: "bad"
echo &"{isbn}: {quality}"</langsyntaxhighlight>
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
</pre>
 
=={{header|Pascal}}==
{{works with|Extended Pascal}}
<syntaxhighlight lang="pascal">program ISBNChecksum(output);
 
const
codeIndexMaximum = 17;
ISBNIndexMinimum = 1;
ISBNIndexMaximum = 13;
ISBNIndexRange = ISBNIndexMaximum - ISBNIndexMinimum + 1;
 
type
code = string(codeIndexMaximum);
codeIndex = 1..codeIndexMaximum value 1;
decimalDigit = '0'..'9';
decimalValue = 0..9;
ISBNIndex = ISBNIndexMinimum..ISBNIndexMaximum;
ISBN = array[ISBNIndex] of decimalDigit;
 
{ returns the integer value represented by a character }
function numericValue(protected c: decimalDigit): decimalValue;
begin
{ in Pascal result variable bears the same name as the function }
numericValue := ord(c) - ord('0')
end;
 
{ determines whether an ISBN is technically valid (checksum correct) }
function isValidISBN(protected n: ISBN): Boolean;
var
sum: 0..225 value 0;
i: ISBNIndex;
begin
{ NB: in Pascal for-loop-limits are _inclusive_ }
for i := ISBNIndexMinimum to ISBNIndexMaximum do
begin
{ alternating scale factor 3^0, 3^1 based on Boolean }
sum := sum + numericValue(n[i]) * 3 pow ord(not odd(i))
end;
isValidISBN := sum mod 10 = 0
end;
 
{ transform '978-0-387-97649-5' into '9780387976495' }
function digits(n: code): code;
var
sourceIndex, destinationIndex: codeIndex;
begin
for sourceIndex := 1 to length(n) do
begin
if n[sourceIndex] in ['0'..'9'] then
begin
n[destinationIndex] := n[sourceIndex];
destinationIndex := destinationIndex + 1
end
end;
{ to alter a string’s length you need overwrite it completely }
digits := subStr(n, 1, destinationIndex - 1)
end;
 
{ data type coercion }
function asISBN(protected n: code): ISBN;
var
result: ISBN;
begin
unpack(n[1..length(n)], result, 1);
asISBN := result
end;
 
{ tells whether a string value contains a proper ISBN representation }
function isValidISBNString(protected hyphenatedForm: code): Boolean;
var
digitOnlyForm: code;
begin
digitOnlyForm := digits(hyphenatedForm);
{ The Extended Pascal `and_then` Boolean operator allows us }
{ to first check the length before invoking `isValidISBN`. }
isValidISBNString := (length(digitOnlyForm) = ISBNIndexRange)
and_then isValidISBN(asISBN(digitOnlyForm))
end;
 
{ === MAIN ============================================================= }
begin
writeLn(isValidISBNString('978-0596528126'));
writeLn(isValidISBNString('978-0596528120'));
writeLn(isValidISBNString('978-1788399081'));
writeLn(isValidISBNString('978-1788399083'))
end.</syntaxhighlight>
{{out}}
<pre>True
False
True
False</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 1,486 ⟶ 2,352:
}
 
for (<978-17343145020596528126 978-17343145090596528120 978-1788399081 978-1788399083 978-2-74839-908-0 978-2-74839-908-5>) {
my($isbn,$check) = /(.*)(.)/;
my $check_d = check_digit($isbn);
say "$_ : " . ($check == $check_d ? 'Good' : "Bad check-digit $check; should be $check_d")
}</langsyntaxhighlight>
{{out}}
<pre>978-17343145020596528126 : Good
978-17343145090596528120 : Bad check-digit 9; should be 2
978-1788399081 : Good
978-1788399083 : Bad check-digit 3; should be 1
Line 1,500 ⟶ 2,366:
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>procedure check_isbn13(string isbn)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
integer digits = 0, checksum = 0, w = 1
<span style="color: #008080;">procedure</span> <span style="color: #000000;">check_isbn13</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">isbn</span><span style="color: #0000FF;">)</span>
for i=1 to length(isbn) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">digits</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">checksum</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
integer ch = isbn[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">isbn</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if ch!=' ' and ch!='-' then
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">isbn</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
ch -= '0'
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span>
if ch<0 or ch>9 then checksum = 9 exit end if
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">-=</span> <span style="color: #008000;">'0'</span>
checksum += ch*w
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #000000;">9</span> <span style="color: #008080;">then</span> <span style="color: #000000;">checksum</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">9</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
digits += 1
<span style="color: #000000;">checksum</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">*</span><span style="color: #000000;">w</span>
w = 4-w
<span style="color: #000000;">digits</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end if
<span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">-</span><span style="color: #000000;">w</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
checksum = remainder(checksum,10)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
string gb = iff(digits=13 and checksum=0 ? "good" : "bad")
<span style="color: #000000;">checksum</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">checksum</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
printf(1,"%s: %s\n",{isbn,gb})
<span style="color: #004080;">string</span> <span style="color: #000000;">gb</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digits</span><span style="color: #0000FF;">=</span><span style="color: #000000;">13</span> <span style="color: #008080;">and</span> <span style="color: #000000;">checksum</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #0000FF;">?</span> <span style="color: #008000;">"good"</span> <span style="color: #0000FF;">:</span> <span style="color: #008000;">"bad"</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">isbn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">gb</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
constant isbns = {"978-1734314502", "978-1734314509", "978-1788399081", "978-1788399083",
"978-2-74839-908-0","978-2-74839-908-5","978 1 86197 876 9"}
<span style="color: #008080;">constant</span> <span style="color: #000000;">isbns</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"978-0596528126"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"978-0596528120"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"978-1788399081"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"978-1788399083"</span><span style="color: #0000FF;">,</span>
for i=1 to length(isbns) do check_isbn13(isbns[i]) end for</lang>
<span style="color: #008000;">"978-2-74839-908-0"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"978-2-74839-908-5"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"978 1 86197 876 9"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">isbns</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000000;">check_isbn13</span><span style="color: #0000FF;">(</span><span style="color: #000000;">isbns</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
Line 1,532 ⟶ 2,401:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de isbn13? (S)
(let L
(make
Line 1,547 ⟶ 2,416:
(if (isbn13? A) 'ok 'fail) ) )
(quote
"978-17343145020596528126"
"978-17343145090596528120"
"978-1-86197-876-9"
"978-2-74839-908-5"
"978 1 86197 876 9" ) )</langsyntaxhighlight>
{{out}}
<pre>
978-17343145020596528126 ok
978-17343145090596528120 fail
978-1-86197-876-9 ok
978-2-74839-908-5 fail
978 1 86197 876 9 ok
</pre>
 
=={{header|PL/M}}==
<syntaxhighlight lang="plm">100H:
 
CHECK$ISBN13: PROCEDURE (PTR) BYTE;
DECLARE PTR ADDRESS, ISBN BASED PTR BYTE;
DECLARE (I, F, T) BYTE;
F = 1;
T = 0;
DO I = 0 TO 13;
IF I = 3 THEN DO;
/* THIRD CHAR SHOULD BE '-' */
IF ISBN(I) <> '-' THEN RETURN 0;
END;
ELSE DO;
/* DIGITS MUST BE VALID */
IF ISBN(I) < '0' OR ISBN(I) > '9' THEN RETURN 0;
T = T + (ISBN(I) - '0') * F;
F = 4 - F; /* MULTIPLY BY 1 AND 3 ALTERNATELY */
END;
END;
RETURN (T MOD 10) = 0;
END CHECK$ISBN13;
 
/* CP/M BDOS CALL */
BDOS: PROCEDURE (FUNC, ARG);
DECLARE FUNC BYTE, ARG ADDRESS;
GO TO 5;
END BDOS;
 
PRINT: PROCEDURE (STR);
DECLARE STR ADDRESS;
CALL BDOS(9, STR);
END PRINT;
 
/* TESTS */
DECLARE TEST (4) ADDRESS;
TEST(0) = .'978-0596528126$';
TEST(1) = .'978-0596528120$';
TEST(2) = .'978-1788399081$';
TEST(3) = .'978-1788399083$';
 
DECLARE I BYTE;
DO I = 0 TO LAST(TEST);
CALL PRINT(TEST(I));
CALL PRINT(.': $');
IF CHECK$ISBN13(TEST(I)) THEN
CALL PRINT(.'GOOD$');
ELSE
CALL PRINT(.'BAD$');
CALL PRINT(.(13,10,'$'));
END;
 
CALL BDOS(0,0);
EOF</syntaxhighlight>
{{out}}
<pre>978-0596528126: GOOD
978-0596528120: BAD
978-1788399081: GOOD
978-1788399083: BAD</pre>
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
function Get-ISBN13 {
$codes = (
"978-0596528126",
"978-0596528120",
"978-1788399081",
"978-1788399083"
)
 
foreach ($line in $codes) {
 
$sum = $null
$codeNoDash = $line.Replace("-","")
 
for ($i = 0; $i -lt $codeNoDash.length; $i++) {
 
if (($i % 2) -eq 1) {
 
$sum += [decimal]$codeNoDash[$i] * 3
}else {
 
$sum += [decimal]$codeNoDash[$i]
 
}
}
if (($sum % 10) -eq 0) {
 
Write-Host "$line Good"
}else {
 
Write-Host "$line Bad"
 
}
}
}
Get-ISBN13
</syntaxhighlight>
 
{{out}}
<pre>
978-0596528126 Good
978-0596528120 Bad
978-1788399081 Good
978-1788399083 Bad
</pre>
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Macro TestISBN13(X)
Print(X)
If IsISBN13(X) : PrintN(" good") : Else : PrintN(" bad") : EndIf
Line 1,577 ⟶ 2,556:
 
If OpenConsole()
TestISBN13("978-17343145020596528126")
TestISBN13("978-17343145090596528120")
TestISBN13("978-1788399081")
TestISBN13("978-1788399083")
Input()
EndIf</langsyntaxhighlight>
{{out}}
<pre>978-17343145020596528126 good
978-17343145090596528120 bad
978-1788399081 good
978-1788399083 bad
Line 1,591 ⟶ 2,570:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">def is_isbn13(n):
n = n.replace('-','').replace(' ', '')
if len(n) != 13:
Line 1,601 ⟶ 2,580:
if __name__ == '__main__':
tests = '''
978-17343145020596528126
978-17343145090596528120
978-1788399081
978-1788399083'''.strip().split()
for t in tests:
print(f"ISBN13 {t} validates {is_isbn13(t)}")</langsyntaxhighlight>
 
{{out}}
<pre>ISBN13 978-17343145020596528126 validates True
ISBN13 978-17343145090596528120 validates False
ISBN13 978-1788399081 validates True
ISBN13 978-1788399083 validates False</pre>
Line 1,616 ⟶ 2,595:
 
Or, expressed in terms of ''itertools.cycle''
<langsyntaxhighlight lang="python">'''ISBN13 check digit'''
 
 
from itertools import cycle
from operator import mul
 
 
# isISBN13 :: String -> Bool
def isISBN13(s):
'''True if thes digitsis ofa svalid ISBN13 formstring
a valid ISBN-13 code.
'''
digits = [int(c) for c in s if c.isdigit()]
return 13 == len(digits) and 0 == sum(
0 == sum(map(
mullambda f, x: f(x),
digits,cycle([
cycle([1, 3]) lambda x: x,
) lambda x: 3 * x
) % 10 ]),
digits
)) % 10
)
 
 
# --------------------------- TEST-- -------------------------
# main :: IO ()
def main():
'''ValidationTest ofstrings fourfor strings:ISBN-13 validity.'''
 
print('\n'.join(
for s in ['978-1734314502', '978-1734314509',
repr((s, isISBN13(s))) for s
'978-1788399081', '978-1788399083']:
print((s,in isISBN13(s)))["978-0596528126",
"978-0596528120",
"978-1788399081",
"978-1788399083"
]
))
 
 
# MAIN ---
if __name__ == '__main__':
main()</lang>
</syntaxhighlight>
{{Out}}
<pre>('978-17343145020596528126', True)
('978-17343145090596528120', False)
('978-1788399081', True)
('978-1788399083', False)</pre>
 
=={{header|Quackery}}==
<langsyntaxhighlight lang="quackery">[ char 0 char 9 1+ within ] is digit? ( c --> b )
 
[ 1 & ] is odd? ( n --> b )
Line 1,685 ⟶ 2,672:
else [ say "Bad" ] cr ] is isbn-test ( $ --> )
 
$ '978-17343145020596528126' isbn-test
$ '978-17343145090596528120' isbn-test
$ '978-1788399081' isbn-test
$ '978-1788399083' isbn-test</langsyntaxhighlight>
{{out}}
<pre>
978-17343145020596528126: Good
978-17343145090596528120: Bad
978-1788399081: Good
978-1788399083: Bad
Line 1,699 ⟶ 2,686:
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">#lang racket/base
 
(define (isbn13-check-digit-valid? s)
Line 1,710 ⟶ 2,697:
(module+ test
(require rackunit)
(check-true (isbn13-check-digit-valid? "978-17343145020596528126"))
(check-false (isbn13-check-digit-valid? "978-17343145090596528120"))
(check-true (isbn13-check-digit-valid? "978-1788399081"))
(check-false (isbn13-check-digit-valid? "978-1788399083")))</langsyntaxhighlight>
 
{{out}}
Line 1,723 ⟶ 2,710:
Also test a value that has a zero check digit.
 
<syntaxhighlight lang="raku" perl6line>sub check-digit ($isbn) {
(10 - (sum (|$isbn.comb(/<[0..9]>/)) »*» (1,3)) % 10).substr: *-1
}
Line 1,734 ⟶ 2,721:
"Bad check-digit $check; should be $check-digit"
} for words <
978-17343145020596528126
978-17343145090596528120
978-1788399081
978-1788399083
978-2-74839-908-0
978-2-74839-908-5
>;</langsyntaxhighlight>
{{out}}
<pre>978-17343145020596528126 : Good
978-17343145090596528120 : Bad check-digit 9; should be 2
978-1788399081 : Good
978-1788399083 : Bad check-digit 3; should be 1
Line 1,749 ⟶ 2,736:
978-2-74839-908-5 : Bad check-digit 5; should be 0
</pre>
 
=={{header|Red}}==
 
<syntaxhighlight lang="red">check_valid_isbn13: function [str] [
is_digit: charset [#"0" - #"9"]
remove-each i str [not pick is_digit i] ; remove non-digits
 
either 13 = length? str [ ; reject strings of incorrect length
sum: 0
repeat i 13 [
mul: either even? i [3] [1] ; multiplier for odd/even digits
sum: sum + (mul * to integer! to string! pick str i)
]
zero? (sum % 10) ; check if remainder mod 10 is zero
] [
false
]
]
 
; check given examples
foreach [str] ["978-0596528126" "978-0596528120" "978-1788399081" "978-1788399083"] [
prin str
prin " - "
print check_valid_isbn13 str
]
</syntaxhighlight>
 
{{out}}
<pre>
978-0596528126 - true
978-0596528120 - false
978-1788399081 - true
978-1788399083 - false
</pre>
 
=={{header|Refal}}==
<syntaxhighlight lang="refal">$ENTRY Go {
= <Test '978-0596528126'>
<Test '978-0596528120'>
<Test '978-1788399081'>
<Test '978-1788399083'>
};
 
Test {
e.X = <Prout e.X ': ' <ISBN e.X>>;
};
 
ISBN {
e.X, <Remove '-' e.X>: e.DS,
<CheckDigits e.DS>: {
False = Bad;
True = <ISBN1 e.DS>;
};
};
 
ISBN1 {
(13 s.Sum), <Mod s.Sum 10>: 0 = Good;
(13 s.Sum) e.X = Bad;
(s.N s.Sum) = Bad;
 
(s.N s.Sum) s.D e.X,
<+ s.N 1>: s.N1,
<Numb s.D>: s.V,
<Mod s.N 2>: {
0 = <ISBN1 (s.N1 <+ s.Sum s.V>) e.X>;
1 = <ISBN1 (s.N1 <+ s.Sum <* 3 s.V>>) e.X>;
};
 
e.X = <ISBN1 (0 0) e.X>;
};
 
Remove {
s.1 = ;
s.1 s.1 e.X = <Remove s.1 e.X>;
s.1 s.2 e.X = s.2 <Remove s.1 e.X>;
};
 
CheckDigits {
= True;
s.D e.X, '0123456789': e.A s.D e.B = <CheckDigits e.X>;
e.X = False;
};</syntaxhighlight>
{{out}}
<pre>978-0596528126: Good
978-0596528120: Bad
978-1788399081: Good
978-1788399083: Bad</pre>
 
=={{header|REXX}}==
A couple of additional checks were made to verify a correct length, &nbsp; and also that the ISBN-13 code is all numerics &nbsp; (with optional minus signs).
<langsyntaxhighlight lang="rexx">/*REXX pgm validates the check digit of an ISBN─13 code (it may have embedded minuses).*/
parse arg $ /*obtain optional arguments from the CL*/
if $='' | if $="," then $= '978-17343145020596528126 978-17343145090596528120 978-1788399081 978-1788399083'
@ISBN= "ISBN─13 code isn't" /*a literal used when displaying msgs. */
/* [↓] remove all minuses from X code.*/
Line 1,770 ⟶ 2,845:
if right(sum, 1)==0 then say ' ISBN-13 code ' x " is valid."
else say ' ISBN-13 code ' x " isn't valid."
end /*j*/ /*stick a fork in it, we're all done. */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the four default inputs:}}
<pre>
Line 1,780 ⟶ 2,855:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
load "stdlib.ring"
 
isbn = ["978-17343145020596528126","978-17343145090596528120", "978-1788399081", "978-1788399083","978-2-74839-908-0","978-2-74839-908-5","978 1 86197 876 9"]
 
for n = 1 to len(isbn)
Line 1,805 ⟶ 2,880:
ok
next
</syntaxhighlight>
</lang>
Output:
<pre>
978-17343145020596528126: true
978-17343145090596528120: bad
978-1788399081: true
978-1788399083: bad
Line 1,817 ⟶ 2,892:
</pre>
 
=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
≪ → isbn
≪ 0 1 CF
1 isbn SIZE FOR j
IF "0123456789" isbn j DUP SUB POS THEN
LAST 1 -
IF 1 FS?C THEN 3 * ELSE 1 SF END
+
END
NEXT
10 MOD NOT
'ISBN?' STO
 
≪ { "978-0596528126" "978-0596528120" "978-1788399081" "978-1788399083" } → tests
≪ 1 tests SIZE FOR j tests GET ISBN? NEXT ≫
≫ EVAL
{{out}}
<pre>
4: 1
3: 0
2: 1
1: 0
</pre>
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">def validISBN13?(str)
cleaned = str.delete("^0-9").chars
return false unless cleaned.size == 13
Line 1,824 ⟶ 2,925:
end
 
isbns = ["978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"]
isbns.each{|isbn| puts "#{isbn}: #{validISBN13?(isbn)}" }
</langsyntaxhighlight>{{out}}
<pre>978-17343145020596528126: true
978-17343145090596528120: false
978-1788399081: true
978-1788399083: false
Line 1,834 ⟶ 2,935:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">fn main() {
let isbns = ["978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"];
isbns.iter().for_each(|isbn| println!("{}: {}", isbn, check_isbn(isbn)));
}
Line 1,848 ⟶ 2,949:
checksum % 10 == 0
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
978-17343145020596528126: true
978-17343145090596528120: false
978-1788399081: true
978-1788399083: false
</pre>
 
=={{header|Seed7}}==
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func boolean: isISBN13 (in var string: input) is func
result
var boolean: isbn is FALSE;
local
var char: c is ' ';
var integer: digit is 0;
var integer: i is 1;
var integer: sum is 0;
begin
input := replace(input, " ", "");
input := replace(input, "-", "");
if length(input) = 13 then
for c range input do
digit := ord(c) - 48;
if not odd(i) then
digit *:= 3;
end if;
sum +:= digit;
incr(i);
end for;
isbn := sum rem 10 = 0;
end if;
end func;
 
const proc: main is func
local
var string: str is "";
begin
for str range [] ("978-0596528126", "978-0596528120", "978-1788399081", "978-1788399083") do
writeln(str <& ": " <& isISBN13(str));
end for;
end func;</syntaxhighlight>
{{out}}
<pre>
978-0596528126: TRUE
978-0596528120: FALSE
978-1788399081: TRUE
978-1788399083: FALSE
</pre>
=={{header|SETL}}==
<syntaxhighlight lang="setl">program isbn13;
loop for test in [
"978-0596528126", "978-0596528120",
"978-1788399081", "978-1788399083"
] do
print(test + if valid_isbn13 test then ": good" else ": bad" end);
end loop;
 
op valid_isbn13(isbn);
if #isbn /= 14
or isbn(4) /= '-'
or exists c in isbn | not c in "0123456789-" then
return false;
end if;
 
m := 3;
loop for ch in isbn | ch in "0123456789" do
s +:= val ch * (m := 4 - m);
end loop;
return s mod 10 = 0;
end op;
end program;</syntaxhighlight>
{{out}}
<pre>978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
 
=={{header|Standard ML}}==
===Easy to read version===
<lang sml>local
<syntaxhighlight lang="sml">(* these type decorations are optional, you could just as well put:
fun isValidISBN s =
*)
fun isValidISBN (s : string) : bool =
let
val digits = List.filter Char.isDigit (explode s)
val nums = map (fn x => ord x - ord #"0") digits
val len = length nums
fun sumISBN [] = raise Domain
| sumISBN [x] = x
| sumISBN (x1::x2::xs) = x1 + 3*x2 + sumISBN xs
in
len = 13 andalso sumISBN nums mod 10 = 0
end
 
val test = ["978-1734314502", "978-1734314509",
"978-1788399081", "978-1788399083"]
 
fun printTest (s : string) : unit =
(print s; print (if isValidISBN s then ": good\n" else ": bad\n"))
 
fun main () = app printTest test</syntaxhighlight>
 
===Original version===
<syntaxhighlight lang="sml">let
fun check (c, p as (m, n)) =
if Char.isDigit c then
Line 1,869 ⟶ 3,066:
end
 
val test = ["978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"]
val () = (print
o concat
o map (fn s => s ^ (if checkISBN s then ": good\n" else ": bad\n"))) test</langsyntaxhighlight>
{{out}}
<pre>978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad</pre>
Line 1,881 ⟶ 3,078:
=={{header|Swift}}==
 
<langsyntaxhighlight lang="swift">func checkISBN(isbn: String) -> Bool {
guard !isbn.isEmpty else {
return false
Line 1,896 ⟶ 3,093:
 
let cases = [
"978-17343145020596528126",
"978-17343145090596528120",
"978-1788399081",
"978-1788399083"
Line 1,904 ⟶ 3,101:
for isbn in cases {
print("\(isbn) => \(checkISBN(isbn: isbn) ? "good" : "bad")")
}</langsyntaxhighlight>
 
 
{{out}}
 
<pre>978-17343145020596528126 => good
978-17343145090596528120 => bad
978-1788399081 => good
978-1788399083 => bad</pre>
Line 1,916 ⟶ 3,113:
=={{header|Tcl}}==
 
<langsyntaxhighlight lang="tcl">
proc validISBN13 code {
regsub -all {\D} $code "" code ;# remove non-digits
Line 1,931 ⟶ 3,128:
}
foreach test {
978-17343145020596528126
978-17343145090596528120
978-1788399081
978-1788399083
} {puts $test:[validISBN13 $test]}
</syntaxhighlight>
</lang>
{{out}}
<pre>978-17343145020596528126:true
978-17343145090596528120:false
978-1788399081:true
978-1788399083:false</pre>
Simpler variant, using two loop vars and constant factors; same output:
<langsyntaxhighlight lang="tcl">
proc validISBN13 code {
regsub -all {\D} $code "" code ;# remove non-digits
Line 1,956 ⟶ 3,153:
return false
}
</syntaxhighlight>
</lang>
 
=={{header|uBasic/4tH}}==
{{works with|version 3.64.0}}
<syntaxhighlight lang="text">a := "978-0596528126"
Print Show(a), Show (Iif (Func(_IsISBN (a)), "good", "bad"))
 
a := "978-0596528120"
Print Show(a), Show (Iif (Func(_IsISBN (a)), "good", "bad"))
 
a := "978-1788399081"
Print Show(a), Show (Iif (Func(_IsISBN (a)), "good", "bad"))
 
a := "978-1788399083"
Print Show(a), Show (Iif (Func(_IsISBN (a)), "good", "bad"))
 
End
 
_IsISBN
Param (1)
Local (4)
 
c@ = 0 : e@ = 1 ' set sum and multiplier
 
For b@ = Len (a@) - 1 To 0 Step -1 ' scan string in reverse
d@ = Peek(a@, b@) - Ord ("0") ' get character
If ((d@ < 0) + (d@ > 9)) = 0 Then c@ = c@ + (d@ * e@)
e@ = (e@ * 3) % 8 ' evaluate character, change multiplier
Next
 
Return ((c@ % 10) = 0) ' modulus 10 must be zero</syntaxhighlight>
{{out}}
<pre>978-0596528126 good
978-0596528120 bad
978-1788399081 good
978-1788399083 bad
 
0 OK, 0:339</pre>
 
=={{header|UNIX Shell}}==
{{works with|Bourne Again Shell}}
<langsyntaxhighlight lang="sh">check_isbn13 () {
local i n t
n=${1//[^0-9]/}
Line 1,970 ⟶ 3,204:
}
 
for isbn in 978-17343145020596528126 978-17343145090596528120 978-1788399081 978-1788399083; do
printf '%s: ' "$isbn"
if check_isbn13 "$isbn"; then
Line 1,977 ⟶ 3,211:
printf '%s\n' 'NOT OK'
fi
done</langsyntaxhighlight>
{{Out}}
<pre>978-17343145020596528126: OK
978-17343145090596528120: NOT OK
978-1788399081: OK
978-1788399083: NOT OK</pre>
Line 1,986 ⟶ 3,220:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<langsyntaxhighlight lang="vbnet">Module Module1
 
Function CheckISBN13(code As String) As Boolean
Line 2,007 ⟶ 3,241:
 
Sub Main()
Console.WriteLine(CheckISBN13("978-17343145020596528126"))
Console.WriteLine(CheckISBN13("978-17343145090596528120"))
Console.WriteLine(CheckISBN13("978-1788399081"))
Console.WriteLine(CheckISBN13("978-1788399083"))
End Sub
 
End Module</langsyntaxhighlight>
{{out}}
<pre>True
Line 2,019 ⟶ 3,253:
True
False</pre>
 
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">
fn check_isbn13(isbn13 string) bool {
// remove any hyphens or spaces
isbn := isbn13.replace('-','').replace(' ','')
// check length == 13
le := isbn.len
if le != 13 {
return false
}
// check only contains digits and calculate weighted sum
mut sum := 0
for i, c in isbn.split('') {
if c.int() < '0'.int() || c.int() > '9'.int() {
return false
}
if i%2 == 0 {
sum += c.int() - '0'.int()
} else {
sum += 3 * (c.int() - '0'.int())
}
}
return sum%10 == 0
}
fn main() {
isbns := ["978-0596528126", "978-0596528120", "978-1788399081", "978-1788399083"]
for isbn in isbns {
mut res := "bad"
if check_isbn13(isbn) {
res = "good"
}
println("$isbn: $res")
}
}</syntaxhighlight>
 
{{out}}
<pre>
978-0596528126: good
978-0596528120: bad
978-1788399081: good
978-1788399083: bad
</pre>
 
=={{header|Wren}}==
<langsyntaxhighlight ecmascriptlang="wren">var isbn13 = Fn.new { |s|
var cps = s.codePoints
var digits = []
Line 2,038 ⟶ 3,317:
}
 
var tests = ["978-17343145020596528126", "978-17343145090596528120", "978-1788399081", "978-1788399083"]
for (test in tests) {
System.print("%(test) -> %(isbn13.call(test) ? "good" : "bad")")
}</langsyntaxhighlight>
 
{{out}}
<pre>
978-17343145020596528126 -> good
978-17343145090596528120 -> bad
978-1788399081 -> good
978-1788399083 -> bad
Line 2,052 ⟶ 3,331:
 
=={{header|XPL0}}==
<langsyntaxhighlight XPL0lang="xpl0">include xpllib; \contains StrLen function
 
proc ISBN13(Str); \Show if International Standard Book Number is good
Line 2,072 ⟶ 3,351:
];
 
[ISBN13("978-17343145020596528126");
ISBN13("978-17343145090596528120");
ISBN13("978-1788399081");
ISBN13("978-1788399083");
ISBN13("978-1-59327-220-3");
ISBN13("978-178839918");
]</langsyntaxhighlight>
 
{{out}}
<pre>
978-17343145020596528126: good
978-17343145090596528120: bad
978-1788399081: good
978-1788399083: bad
Line 2,091 ⟶ 3,370:
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn ISBN13_check(isbn){ // "978-17343145020596528126", throws on invalid digits
var [const] one3=("13"*6 + 1).split("").apply("toInt"); // examine 13 digits
// one3=("13"*6) if you want to calculate what the check digit should be
one3.zipWith('*,isbn - " -").sum(0) % 10 == 0
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">isbns:=
#<<<"
978-17343145020596528126
978-17343145090596528120
978-1788399081
978-1788399083
Line 2,106 ⟶ 3,385:
#<<<
foreach isbn in (isbns)
{ println(isbn.strip()," ",ISBN13_check(isbn) and " Good" or " Bad") }</langsyntaxhighlight>
{{out}}
<pre>
978-17343145020596528126 Good
978-17343145090596528120 Bad
978-1788399081 Good
978-1788399083 Bad
1,006

edits