ISBN13 check digit: Difference between revisions
Content deleted Content added
Added OmniMark solution, which includes additional conditions to ignore non-ISBN-13 numbers |
|||
(41 intermediate revisions by 22 users not shown) | |||
Line 9:
::::* 978-
::::* 978-
::::* 978-1788399081 (good)
::::* 978-1788399083 (bad)
Line 26:
{{trans|Python}}
<
n = n.replace(‘-’, ‘’).replace(‘ ’, ‘’)
I n.len != 13
Line 34:
R product % 10 == 0
V tests = |‘978-
978-
978-1788399081
978-1788399083’.split("\n")
L(t) tests
print(‘ISBN13 ’t‘ validates ’is_isbn13(t))</
{{out}}
<pre>
ISBN13 978-
ISBN13 978-
ISBN13 978-1788399081 validates 1B
ISBN13 978-1788399083 validates 0B
Line 52:
=={{header|8080 Assembly}}==
<
jmp demo
;;; ---------------------------------------------------------------
Line 118:
jmp 5
good: db 'good$'
bad: db 'bad$'</
{{out}}
<pre>A>isbn13 978-
good
A>isbn13 978-
bad
A>isbn13 978-1788399081
Line 133:
=={{header|8086 Assembly}}==
<
bits 16
org 100h
Line 186:
section .data
good: db 'good$'
bad: db 'bad$'</
{{out}}
<pre>C:\>isbn13 978-
good
C:\>isbn13 978-
bad
C:\>isbn13 978-1788399081
Line 199:
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}}
<
BYTE FUNC CheckISBN13(CHAR ARRAY t)
Line 241 ⟶ 268:
Put(125) PutE() ;clear screen
Test("978-
Test("978-
Test("978-1788399081")
Test("978-1788399083")
RETURN</
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/ISBN13_check_digit.png Screenshot from Atari 8-bit computer]
<pre>
978-
978-
978-1788399081 is correct
978-1788399083 is incorrect
Line 256 ⟶ 283:
=={{header|Ada}}==
<
procedure ISBN_Check is
Line 288 ⟶ 315:
end Show;
begin
Show ("978-
Show ("978-
Show ("978-1788399081");
Show ("978-1788399083");
end ISBN_Check;</
{{out}}
<pre>978-
978-
978-1788399081 Good
978-1788399083 Bad</pre>
Line 301 ⟶ 328:
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
<
# returns TRUE if the alledged isbn13 has the correct check sum, #
# FALSE otherwise #
Line 323 ⟶ 350:
END; # check isbn13 #
# task test cases #
[]STRING tests = ( "978-
[]BOOL expected = ( TRUE, FALSE, TRUE, FALSE );
FOR pos FROM LWB tests TO UPB tests DO
Line 335 ⟶ 362:
)
OD
END</
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
Line 346 ⟶ 373:
=={{header|APL}}==
{{works with|Dyalog APL}}
<
13≠⍴n←(⍵∊⎕D)/⍵:0
0=10|(⍎¨n)+.×13⍴1 3
}</
{{out}}
<pre> check_isbn13¨ '978-
1 0 1 0</pre>
Line 359 ⟶ 386:
===Composition of pure functions===
<
-- isISBN13 :: String -> Bool
Line 388 ⟶ 415:
end script
map(test, {"978-
"978-1788399081", "978-1788399083"})
end run
Line 563 ⟶ 590:
return lst
end tell
end zipWith</
{{Out}}
<pre>{{"978-
===Straightforward===
Line 571 ⟶ 598:
This task ''can'' be tackled very simply by working through the numeric text two characters at a time:
<
if (ISBN13's class is not text) then return false
Line 599 ⟶ 626:
set output to {}
set verdicts to {"bad", "good"}
repeat with thisISBN13 in {"978-
set isValid to validateISBN13(thisISBN13)
set end of output to thisISBN13 & ": " & item ((isValid as integer) + 1) of verdicts
Line 608 ⟶ 635:
set output to output as text
set AppleScript's text item delimiters to astid
return output</
{{output}}
<pre>"978-
978-
978-1788399081: good
978-1788399083: bad"</pre>
Line 618 ⟶ 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>.
<
if (ISBN13's class is not text) then return false
Line 642 ⟶ 669:
return ((sum + ISBN13) mod 10 = 0)
end validateISBN13</
=={{header|Arturo}}==
<
currentCheck: to :integer to :string last isbn
isbn: map split chop replace isbn "-" ""
s: 0
Line 660 ⟶ 687:
tests: [
"978-
"978-1788399081" "978-1788399083"
]
Line 666 ⟶ 693:
loop tests 'test [
print [test "=>" validISBN? test]
]</
{{out}}
<pre>978-
978-
978-1788399081 => true
978-1788399083 => false</pre>
=={{header|AutoHotkey}}==
<
for i, v in StrSplit(RegExReplace(n, "[^0-9]"))
sum += !Mod(i, 2) ? v*3 : v
return n "`t" (Mod(sum, 10) ? "(bad)" : "(good)")
}</
Examples:<
nums := ["978-
for i, n in nums
output .= ISBN13_check_digit(n) "`n"
MsgBox % output
return</
{{out}}
<pre>978-
978-
978-1788399081 (good)
978-1788399083 (bad)</pre>
=={{header|AWK}}==
<syntaxhighlight lang="awk">
# syntax: GAWK -f ISBN13_CHECK_DIGIT.AWK
BEGIN {
arr[++n] = "978-
arr[++n] = "978-
arr[++n] = "978-1788399081"
arr[++n] = "978-1788399083"
Line 717 ⟶ 744:
return(substr(isbn,13,1) == check_digit ? "OK" : sprintf("NG check digit S/B %d",check_digit))
}
</syntaxhighlight>
{{out}}
<pre>
978-
978-
978-1788399081 OK
978-1788399083 NG check digit S/B 1
Line 727 ⟶ 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}}==
<
let checkISBN(s) = valof
Line 757 ⟶ 809:
let start() be
$( show("978-
show("978-
show("978-1788399081")
show("978-1788399083")
$)</
{{out}}
<pre>978-
978-
978-1788399081: good
978-1788399083: bad</pre>
=={{header|C}}==
<
int check_isbn13(const char *isbn) {
Line 795 ⟶ 847:
int main() {
int i;
const char* isbns[] = {"978-
for (i = 0; i < 4; ++i) {
printf("%s: %s\n", isbns[i], check_isbn13(isbns[i]) ? "good" : "bad");
}
return 0;
}</
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
Line 812 ⟶ 864:
=={{header|C++}}==
{{trans|C}}
<
bool check_isbn13(std::string isbn) {
Line 841 ⟶ 893:
int main() {
auto isbns = { "978-
for (auto isbn : isbns) {
std::cout << isbn << ": " << (check_isbn13(isbn) ? "good" : "bad") << '\n';
Line 847 ⟶ 899:
return 0;
}</
{{out}}
<pre>978-
978-
978-1788399081: good
978-1788399083: bad</pre>
=={{header|C sharp}}==
<
using System.Linq;
Line 861 ⟶ 913:
{
public static void Main() {
Console.WriteLine(CheckISBN13("978-
Console.WriteLine(CheckISBN13("978-
Console.WriteLine(CheckISBN13("978-1788399081"));
Console.WriteLine(CheckISBN13("978-1788399083"));
Line 877 ⟶ 929:
}
}
}</
{{out}}
<pre>
Line 884 ⟶ 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}}
<
* Author: Jay Moseley
* Date: November 10, 2019
Line 914 ⟶ 1,007:
01 IX PIC S9(4) COMP.
01 TEST-ISBNS.
02 FILLER PIC X(14) VALUE '978-
02 FILLER PIC X(14) VALUE '978-
02 FILLER PIC X(14) VALUE '978-1788399081'.
02 FILLER PIC X(14) VALUE '978-1788399083'.
Line 1,026 ⟶ 1,119:
END FUNCTION validISBN13.
</syntaxhighlight>
{{out}}
<pre>978-
978-
978-1788399081 (good)
978-1788399083 (bad)
Line 1,037 ⟶ 1,130:
=={{header|Cowgol}}==
<
sub check_isbn13(isbn: [uint8]): (r: uint8) is
Line 1,063 ⟶ 1,156:
var isbns: [uint8][] := {
"978-
};
Line 1,073 ⟶ 1,166:
print(result[check_isbn13(isbns[n])]);
n := n + 1;
end loop;</
{{out}}
<pre>978-
978-
978-1788399081: good
978-1788399083: bad</pre>
Line 1,082 ⟶ 1,175:
=={{header|D}}==
{{trans|Kotlin}}
<
bool isValidISBN13(string text) {
Line 1,102 ⟶ 1,195:
unittest {
assert(isValidISBN13("978-
assert(!isValidISBN13("978-
assert(isValidISBN13("978-1788399081"));
assert(!isValidISBN13("978-1788399083"));
}</
=={{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}}==
Line 1,116 ⟶ 1,347:
{{Works with|Office 365 betas 2021}}
<
=LAMBDA(s,
LET(
Line 1,141 ⟶ 1,372:
)
)
)</
and also assuming the following generic bindings in the Name Manager for the WorkBook:
<
=LAMBDA(s,
MID(s,
Line 1,169 ⟶ 1,400:
AND(47 < ic, 58 > ic)
)
)</
{{Out}}
Line 1,186 ⟶ 1,417:
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 2
| 978-
| style="background-color:#cbcefb" | TRUE
|-
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 3
| 978-
| FALSE
|-
Line 1,201 ⟶ 1,432:
| FALSE
|}
=={{header|Factor}}==
<
math.functions math.parser math.vectors qw sequences
sequences.extras sets unicode ;
Line 1,216 ⟶ 1,446:
{ [ length 13 = ] [ [ digit? ] all? ] [ (isbn13?) ] } 1&& ;
qw{ 978-
[ dup isbn13? "good" "bad" ? "%s: %s\n" printf ] each</
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
Line 1,228 ⟶ 1,458:
=={{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)
Line 1,235 ⟶ 1,465:
if [char] 0 - * rot + swap 3 * 8 mod else drop drop then
-1 chars +loop drop 10 mod 0= \ now calculate checksum
;</
{{out}}
In Forth, a "true" value is indicated by "-1".
<pre>
s" 978-
s" 978-
s" 978-1788399081" isbn? . -1 ok
s" 978-1788399083" isbn? . 0 ok
Line 1,246 ⟶ 1,476:
=={{header|Fortran}}==
<
program isbn13
implicit none
character(len=14), dimension(4), parameter :: isbns=["978-
integer :: i
Line 1,283 ⟶ 1,513:
end function check_isbn13
end program isbn13
</syntaxhighlight>
{{out}}
<pre>
978-
978-
978-1788399081 : good
978-1788399083 : bad
Line 1,294 ⟶ 1,524:
=={{header|FreeBASIC}}==
<
function is_num( byval c as string ) as boolean
Line 1,322 ⟶ 1,552:
end function
dim as string isbns(0 to 3) = { "978-
dim as uinteger i
for i = 0 to 3
Line 1,330 ⟶ 1,560:
print isbns(i)+": bad"
end if
next i</
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
</pre>
=={{header|F_Sharp|F#}}==
<
open System
Line 1,359 ⟶ 1,589:
else
printfn "%s Invalid ISBN13" argv.[0]
0</
{{out}}
<pre>978-
978-
978-1788399081 Valid ISBN13
978-1788399083 Inalid ISBN13</pre>
Line 1,369 ⟶ 1,599:
=={{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}}==
<
import (
Line 1,408 ⟶ 1,672:
func main() {
isbns := []string{"978-
for _, isbn := range isbns {
res := "bad"
Line 1,416 ⟶ 1,680:
fmt.Printf("%s: %s\n", isbn, res)
}
}</
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
Line 1,427 ⟶ 1,691:
=={{header|Haskell}}==
<
import Text.Printf (printf)
Line 1,450 ⟶ 1,714:
mapM_
(printf "%s: Valid: %s\n" <*> (show . validIsbn13))
[ "978-
"978-
"978-1788399081",
"978-1788399083"
]</
{{out}}
<pre>978-
978-
978-1788399081: Valid: True
978-1788399083: Valid: False</pre>
Line 1,463 ⟶ 1,727:
Or, expressed in terms of ''cycle'':
<
isISBN13 :: String -> Bool
Line 1,478 ⟶ 1,742:
mapM_
(print . ((,) <*> isISBN13))
[ "978-
"978-
"978-1788399081",
"978-1788399083"
]</
{{Out}}
<pre>("978-
("978-
("978-1788399081",True)
("978-1788399083",False)</pre>
=={{header|IS-BASIC}}==
<
110 DO
120 PRINT :INPUT PROMPT "ISBN-13 code: ":IS$
Line 1,515 ⟶ 1,779:
330 LET SUM=SUM+VAL(ISBN$(13))
340 IF MOD(SUM,10)=0 THEN LET ISBN=-1
350 END DEF</
=={{header|J}}==
<
isbn13c =: D&([ check@:i. clean)
Line 1,524 ⟶ 1,788:
lc =: [ +/@:* weight
weight =: 1 3 $~ #
clean =: ] -. a. -. [</
{{out}}
<
1 0 1 0</
=={{header|Java}}==
<syntaxhighlight lang="java">
public static void main(String[] args) {
String[] isbn13s = {
"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,549 ⟶ 1,861:
return false;
}
</
<pre>
true
Line 1,560 ⟶ 1,872:
{{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);
Line 1,571 ⟶ 1,883:
def testingcodes:
["978-
"978-1788399081", "978-1788399083"];
testingcodes[]
| "\(.): \(if isbn_check then "good" else "bad" end)"
</syntaxhighlight>
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
Line 1,586 ⟶ 1,898:
=={{header|Julia}}==
<
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-
"978-1788399081", "978-1788399083"]
Line 1,597 ⟶ 1,909:
println(code, ": ", isbncheck(code) ? "good" : "bad")
end
</
<pre>
978-
978-
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">
fun isValidISBN13(text: String): Boolean {
val isbn = text.replace(Regex("[- ]"), "")
Line 1,613 ⟶ 1,939:
.sum() % 10 == 0
}
</syntaxhighlight>
Tested using Spek
<syntaxhighlight lang="kotlin">
describe("ISBN Utilities") {
mapOf(
"978-
"978-
"978-1788399081" to true,
"978-1788399083" to false
Line 1,633 ⟶ 1,959:
}
}
</syntaxhighlight>
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
Line 1,643 ⟶ 1,969:
=={{header|langur}}==
In this example, we map to multiple functions (actually 1 no-op).
<syntaxhighlight lang="langur">
val isbn13checkdigit = fn(var s) {
s -> re/^[0-9]{13}$/ and
fold(fn{+}, map([_, fn{*3}], s2n(s))) div 10
}
val
"978-
"978-
"978-1788399081": true,
"978-1788399083": false,
}
for
val
write
writeln if(
}
</syntaxhighlight>
{{out}}
<pre>978-
978-
978-1788399081: good
978-1788399083: bad</pre>
Line 1,694 ⟶ 1,999:
=={{header|Lua}}==
{{trans|C}}
<
local count = 0
local sum = 0
Line 1,728 ⟶ 2,033:
function main()
test("978-
test("978-
test("978-1788399081")
test("978-1788399083")
end
main()</
{{out}}
<pre>978-
978-
978-1788399081: good
978-1788399083: bad</pre>
Line 1,743 ⟶ 2,048:
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<
ValidISBNQ[iban_String] := Module[{i},
i = StringReplace[iban, {" " -> "", "-" -> ""}];
Line 1,754 ⟶ 2,059:
]
]
ValidISBNQ["978-
ValidISBNQ["978-
ValidISBNQ["978-1788399081"]
ValidISBNQ["978-1788399083"]</
{{out}}
<pre>True
Line 1,764 ⟶ 2,069:
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}}==
<
FROM InOut IMPORT WriteString, WriteLn;
FROM Strings IMPORT Length;
Line 1,805 ⟶ 2,168:
BEGIN
check('978-
check('978-
check('978-1788399081');
check('978-1788399083');
END ISBN.</
{{out}}
<pre>978-
978-
978-1788399081: good
978-1788399083: bad</pre>
Line 1,818 ⟶ 2,181:
=={{header|Nanoquery}}==
{{trans|Go}}
<
// remove any hyphens or spaces
isbn = str(isbn).replace("-","").replace(" ","")
Line 1,845 ⟶ 2,208:
end
isbns = {"978-
for isbn in isbns
res = "bad"
Line 1,853 ⟶ 2,216:
print format("%s: %s\n", isbn, res)
end</
{{out}}
<pre>978-
978-
978-1788399081: good
978-1788399083: bad</pre>
=={{header|Nim}}==
<
func is_isbn*(s: string): bool =
Line 1,874 ⟶ 2,237:
when is_main_module:
let isbns = [ "978-
"978-1788399081", "978-1788399083" ]
for isbn in isbns:
var quality: string = if is_isbn(isbn): "good" else: "bad"
echo &"{isbn}: {quality}"</
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
</pre>
=={{header|OmniMark}}==
<syntaxhighlight lang="omnimark">
define switch function isbn (value stream vs-s) as
local integer li-total initial {0}
local integer li-check
repeat scan vs-s
; Any digits in an ISBN-13 may be separated by a hyphen or space
match (digit => lpv-1 ('-' | space)? digit => lpv-3 ('-' | space)? ) => p
; Add the first digit to the total and add the second multiplied by 3
increment li-total by (lpv-1 + (lpv-3 * 3))
match any => lpv-c
; This is always the thirteenth digit, the 'check' digit
set li-check to lpv-c
again
do when 10 - li-total modulo 10 = li-check
return true
else when li-total modulo 10 = 0 and li-check = 0
return true
else
return false
done
process
; These are the first four test ISBN-13s from the problem description, with
; the first and third being valid and the second and fourth invalid.
submit "978-0596528126"
submit "978-0596528120"
submit "978-1788399081"
submit "978-1788399083"
; This ISBN-13 is from https://isbn-information.com/the-13-digit-isbn.html
submit "978-1-86197-876-9"
submit "978 1 86197 876 9"
; These ISBNs are from https://en.wikipedia.org/wiki/ISBN
submit "978-3-16-148410-0"
submit "978 3 16 148410 9" ; But this one has had the 'check' digit changed
submit "This is valid: 978-0-306-40615-7^" ; Adding some extra complexity :)
submit "978-03-0640-615 7." ; Formatted as "EAN-Group-Publisher-Title Check"
; These strings show how non-ISBN-13 numbers must be (and are) ignored.
submit "This is a 14-digit number - 555-30640610555 - so it is ignored.%n"
submit "This is an ISBN-10, so it is ignored too: 0-306-40615-2.%n"
; This find rule will only find a string that is an ISBN-13 (digit/-/space)
; combination. It has been split into three lines to make it easier to see
; what is being done.
; 1. The string must either be preceded by any character other than a digit
; or start the stream, and
; 2. It must then have 12 digits (with optional hyphens or spaces
; intermingled) and must conclude with a digit, and
; 3. It either must not be followed by a another digit (making it more
; than 13 digits, so not an ISBN-13) or the stream ends.
find ([any \ digit] | value-start) => lpv-s
((digit ('-' | space)?){12} digit) => lpv-n
([any \ digit] | value-end) => lpv-e
output lpv-s || lpv-n || lpv-e
do when isbn(lpv-n) = true
output ' (good)%n'
else
output ' (bad)%n'
done
; output all other characters verbatim
find any => lpv-char
output lpv-char
</syntaxhighlight>
{{out}}
<pre>
978-0596528126 (good)
978-0596528120 (bad)
978-1788399081 (good)
978-1788399083 (bad)
978-1-86197-876-9 (good)
978 1 86197 876 9 (good)
978-3-16-148410-0 (good)
978 3 16 148410 9 (bad)
This is valid: 978-0-306-40615-7^ (good)
978-03-0640-615 7. (good)
This is a 14-digit number - 555-30640610555 - so it is ignored.
This is an ISBN-10, so it is ignored too: 0-306-40615-2.
</pre>
=={{header|Pascal}}==
{{works with|Extended Pascal}}
<
const
Line 1,969 ⟶ 2,416:
{ === MAIN ============================================================= }
begin
writeLn(isValidISBNString('978-
writeLn(isValidISBNString('978-
writeLn(isValidISBNString('978-1788399081'));
writeLn(isValidISBNString('978-1788399083'))
end.</
{{out}}
<pre>True
Line 1,981 ⟶ 2,428:
=={{header|Perl}}==
<
use warnings;
use feature 'say';
Line 1,991 ⟶ 2,438:
}
for (<978-
my($isbn,$check) = /(.*)(.)/;
my $check_d = check_digit($isbn);
say "$_ : " . ($check == $check_d ? 'Good' : "Bad check-digit $check; should be $check_d")
}</
{{out}}
<pre>978-
978-
978-1788399081 : Good
978-1788399083 : Bad check-digit 3; should be 1
Line 2,005 ⟶ 2,452:
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<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>
<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>
<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>
<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>
<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>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">-=</span> <span style="color: #008000;">'0'</span>
<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>
<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>
<span style="color: #000000;">digits</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<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>
<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>
<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>
<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>
<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-
978-
978-1788399081: good
978-1788399083: bad
Line 2,037 ⟶ 2,487:
=={{header|PicoLisp}}==
<
(let L
(make
Line 2,052 ⟶ 2,502:
(if (isbn13? A) 'ok 'fail) ) )
(quote
"978-
"978-
"978-1-86197-876-9"
"978-2-74839-908-5"
"978 1 86197 876 9" ) )</
{{out}}
<pre>
978-
978-
978-1-86197-876-9 ok
978-2-74839-908-5 fail
Line 2,067 ⟶ 2,517:
=={{header|PL/M}}==
<
CHECK$ISBN13: PROCEDURE (PTR) BYTE;
Line 2,102 ⟶ 2,552:
/* TESTS */
DECLARE TEST (4) ADDRESS;
TEST(0) = .'978-
TEST(1) = .'978-
TEST(2) = .'978-1788399081$';
TEST(3) = .'978-1788399083$';
Line 2,119 ⟶ 2,569:
CALL BDOS(0,0);
EOF</
{{out}}
<pre>978-
978-
978-1788399081: GOOD
978-1788399083: BAD</pre>
=={{header|
<syntaxhighlight lang="powershell">
function Get-ISBN13 {
$codes = (
"978-
"978-
"978-1788399081",
"978-1788399083"
Line 2,166 ⟶ 2,615:
}
}
Get-ISBN13
</syntaxhighlight>
{{out}}
<pre>
978-
978-
978-1788399081 Good
978-1788399083 Bad
Line 2,180 ⟶ 2,627:
=={{header|PureBasic}}==
<
Print(X)
If IsISBN13(X) : PrintN(" good") : Else : PrintN(" bad") : EndIf
Line 2,195 ⟶ 2,642:
If OpenConsole()
TestISBN13("978-
TestISBN13("978-
TestISBN13("978-1788399081")
TestISBN13("978-1788399083")
Input()
EndIf</
{{out}}
<pre>978-
978-
978-1788399081 good
978-1788399083 bad
Line 2,209 ⟶ 2,656:
=={{header|Python}}==
<
n = n.replace('-','').replace(' ', '')
if len(n) != 13:
Line 2,219 ⟶ 2,666:
if __name__ == '__main__':
tests = '''
978-
978-
978-1788399081
978-1788399083'''.strip().split()
for t in tests:
print(f"ISBN13 {t} validates {is_isbn13(t)}")</
{{out}}
<pre>ISBN13 978-
ISBN13 978-
ISBN13 978-1788399081 validates True
ISBN13 978-1788399083 validates False</pre>
Line 2,234 ⟶ 2,681:
Or, expressed in terms of ''itertools.cycle''
<
Line 2,264 ⟶ 2,711:
print('\n'.join(
repr((s, isISBN13(s))) for s
in ["978-
"978-
"978-1788399081",
"978-1788399083"
Line 2,275 ⟶ 2,722:
if __name__ == '__main__':
main()
</syntaxhighlight>
{{Out}}
<pre>('978-
('978-
('978-1788399081', True)
('978-1788399083', False)</pre>
=={{header|Quackery}}==
<
[ 1 & ] is odd? ( n --> b )
Line 2,311 ⟶ 2,758:
else [ say "Bad" ] cr ] is isbn-test ( $ --> )
$ '978-
$ '978-
$ '978-1788399081' isbn-test
$ '978-1788399083' isbn-test</
{{out}}
<pre>
978-
978-
978-1788399081: Good
978-1788399083: Bad
Line 2,325 ⟶ 2,772:
=={{header|Racket}}==
<
(define (isbn13-check-digit-valid? s)
Line 2,336 ⟶ 2,783:
(module+ test
(require rackunit)
(check-true (isbn13-check-digit-valid? "978-
(check-false (isbn13-check-digit-valid? "978-
(check-true (isbn13-check-digit-valid? "978-1788399081"))
(check-false (isbn13-check-digit-valid? "978-1788399083")))</
{{out}}
Line 2,349 ⟶ 2,796:
Also test a value that has a zero check digit.
<syntaxhighlight lang="raku"
(10 - (sum (|$isbn.comb(/<[0..9]>/)) »*» (1,3)) % 10).substr: *-1
}
Line 2,360 ⟶ 2,807:
"Bad check-digit $check; should be $check-digit"
} for words <
978-
978-
978-1788399081
978-1788399083
978-2-74839-908-0
978-2-74839-908-5
>;</
{{out}}
<pre>978-
978-
978-1788399081 : Good
978-1788399083 : Bad check-digit 3; should be 1
Line 2,375 ⟶ 2,822:
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, and also that the ISBN-13 code is all numerics (with optional minus signs).
<
parse arg $ /*obtain optional arguments from the CL*/
if $='' | if $="," then $= '978-
@ISBN= "ISBN─13 code isn't" /*a literal used when displaying msgs. */
/* [↓] remove all minuses from X code.*/
Line 2,396 ⟶ 2,931:
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. */</
{{out|output|text= when using the four default inputs:}}
<pre>
Line 2,406 ⟶ 2,941:
=={{header|Ring}}==
<
load "stdlib.ring"
isbn = ["978-
for n = 1 to len(isbn)
Line 2,431 ⟶ 2,966:
ok
next
</syntaxhighlight>
Output:
<pre>
978-
978-
978-1788399081: true
978-1788399083: bad
Line 2,443 ⟶ 2,978:
</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}}==
<
cleaned = str.delete("^0-9").chars
return false unless cleaned.size == 13
Line 2,450 ⟶ 3,011:
end
isbns = ["978-
isbns.each{|isbn| puts "#{isbn}: #{validISBN13?(isbn)}" }
</
<pre>978-
978-
978-1788399081: true
978-1788399083: false
Line 2,460 ⟶ 3,021:
=={{header|Rust}}==
<
let isbns = ["978-
isbns.iter().for_each(|isbn| println!("{}: {}", isbn, check_isbn(isbn)));
}
Line 2,474 ⟶ 3,035:
checksum % 10 == 0
}
</syntaxhighlight>
{{out}}
<pre>
978-
978-
978-1788399081: true
978-1788399083: false
Line 2,484 ⟶ 3,045:
=={{header|Seed7}}==
<
const func boolean: isISBN13 (in var string: input) is func
Line 2,514 ⟶ 3,075:
var string: str is "";
begin
for str range [] ("978-
writeln(str <& ": " <& isISBN13(str));
end for;
end func;</
{{out}}
<pre>
978-
978-
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===
<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 2,538 ⟶ 3,152:
end
val test = ["978-
val () = (print
o concat
o map (fn s => s ^ (if checkISBN s then ": good\n" else ": bad\n"))) test</
{{out}}
<pre>978-
978-
978-1788399081: good
978-1788399083: bad</pre>
Line 2,550 ⟶ 3,164:
=={{header|Swift}}==
<
guard !isbn.isEmpty else {
return false
Line 2,565 ⟶ 3,179:
let cases = [
"978-
"978-
"978-1788399081",
"978-1788399083"
Line 2,573 ⟶ 3,187:
for isbn in cases {
print("\(isbn) => \(checkISBN(isbn: isbn) ? "good" : "bad")")
}</
{{out}}
<pre>978-
978-
978-1788399081 => good
978-1788399083 => bad</pre>
Line 2,585 ⟶ 3,199:
=={{header|Tcl}}==
<
proc validISBN13 code {
regsub -all {\D} $code "" code ;# remove non-digits
Line 2,600 ⟶ 3,214:
}
foreach test {
978-
978-
978-1788399081
978-1788399083
} {puts $test:[validISBN13 $test]}
</syntaxhighlight>
{{out}}
<pre>978-
978-
978-1788399081:true
978-1788399083:false</pre>
Simpler variant, using two loop vars and constant factors; same output:
<
proc validISBN13 code {
regsub -all {\D} $code "" code ;# remove non-digits
Line 2,625 ⟶ 3,239:
return false
}
</syntaxhighlight>
=={{header|uBasic/4tH}}==
{{works with|version 3.64.0}}
<syntaxhighlight lang="text">a := "978-
Print Show(a), Show (Iif (Func(_IsISBN (a)), "good", "bad"))
a := "978-
Print Show(a), Show (Iif (Func(_IsISBN (a)), "good", "bad"))
Line 2,655 ⟶ 3,269:
Next
Return ((c@ % 10) = 0) ' modulus 10 must be zero</
{{out}}
<pre>978-
978-
978-1788399081 good
978-1788399083 bad
Line 2,666 ⟶ 3,280:
=={{header|UNIX Shell}}==
{{works with|Bourne Again Shell}}
<
local i n t
n=${1//[^0-9]/}
Line 2,676 ⟶ 3,290:
}
for isbn in 978-
printf '%s: ' "$isbn"
if check_isbn13 "$isbn"; then
Line 2,683 ⟶ 3,297:
printf '%s\n' 'NOT OK'
fi
done</
{{Out}}
<pre>978-
978-
978-1788399081: OK
978-1788399083: NOT OK</pre>
Line 2,692 ⟶ 3,306:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<
Function CheckISBN13(code As String) As Boolean
Line 2,713 ⟶ 3,327:
Sub Main()
Console.WriteLine(CheckISBN13("978-
Console.WriteLine(CheckISBN13("978-
Console.WriteLine(CheckISBN13("978-1788399081"))
Console.WriteLine(CheckISBN13("978-1788399083"))
End Sub
End Module</
{{out}}
<pre>True
Line 2,725 ⟶ 3,339:
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}}==
<
var cps = s.codePoints
var digits = []
Line 2,744 ⟶ 3,403:
}
var tests = ["978-
for (test in tests) {
System.print("%(test) -> %(isbn13.call(test) ? "good" : "bad")")
}</
{{out}}
<pre>
978-
978-
978-1788399081 -> good
978-1788399083 -> bad
Line 2,758 ⟶ 3,417:
=={{header|XPL0}}==
<
proc ISBN13(Str); \Show if International Standard Book Number is good
Line 2,778 ⟶ 3,437:
];
[ISBN13("978-
ISBN13("978-
ISBN13("978-1788399081");
ISBN13("978-1788399083");
ISBN13("978-1-59327-220-3");
ISBN13("978-178839918");
]</
{{out}}
<pre>
978-
978-
978-1788399081: good
978-1788399083: bad
Line 2,797 ⟶ 3,456:
=={{header|zkl}}==
<
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
}</
<
#<<<"
978-
978-
978-1788399081
978-1788399083
Line 2,812 ⟶ 3,471:
#<<<
foreach isbn in (isbns)
{ println(isbn.strip()," ",ISBN13_check(isbn) and " Good" or " Bad") }</
{{out}}
<pre>
978-
978-
978-1788399081 Good
978-1788399083 Bad
|