ISBN13 check digit: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Perl 6}}: Add a Perl 6 example)
Line 100: Line 100:
978-1788399081: good
978-1788399081: good
978-1788399083: bad</pre>
978-1788399083: bad</pre>

=={{header|Perl 6}}==
{{works with|Rakudo|2019.11}}
Also test a value that has a zero check digit.

<lang perl6>sub check-digit ($isbn) {
(10 - (sum (|$isbn.comb(/<[0..9]>/)) »*» (1,3)) % 10).substr: *-1
}

{
my $check = .substr(*-1);
my $check-digit = check-digit .chop;
say "$_ : ", $check == $check-digit ??
'Good' !!
"Bad check-digit $check; should be $check-digit"
} for words <
978-1734314502
978-1734314509
978-1788399081
978-1788399083
978-2-74839-908-0
978-2-74839-908-5
>;</lang>
{{out}}
<pre>978-1734314502 : Good
978-1734314509 : Bad check-digit 9; should be 2
978-1788399081 : Good
978-1788399083 : Bad check-digit 3; should be 1
978-2-74839-908-0 : Good
978-2-74839-908-5 : Bad check-digit 5; should be 0
</pre>


=={{header|Python}}==
=={{header|Python}}==

Revision as of 18:14, 4 December 2019

ISBN13 check digit is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Validate the check digit of an ISBN-13 code. Multiply every other digit by 3. Add the digits together. Take the remainder of division by 10. If it is 0, the ISBN-13 check digit is correct.

Use the following codes for testing:

978-1734314502: good
978-1734314509: bad
978-1788399081: good
978-1788399083: bad

Show output here, on this page

See also

See https://isbn-information.com/the-13-digit-isbn.html for details on the method of validation.

Go

<lang go>package main

import (

   "fmt"
   "strings"
   "unicode/utf8"

)

func checkIsbn13(isbn string) bool {

   // remove any hyphens or spaces
   isbn = strings.ReplaceAll(strings.ReplaceAll(isbn, "-", ""), " ", "")
   // check length == 13
   le := utf8.RuneCountInString(isbn)
   if le != 13 {
       return false
   }
   // check only contains digits and calculate weighted sum
   sum := int32(0)
   for i, c := range isbn {
       if c < '0' || c > '9' {
           return false
       }
       if i%2 == 0 {
           sum += c - '0'
       } else {
           sum += 3 * (c - '0')
       }
   }
   return sum%10 == 0

}

func main() {

   isbns := []string{"978-1734314502", "978-1734314509", "978-1788399081", "978-1788399083"}
   for _, isbn := range isbns {
       res := "bad"
       if checkIsbn13(isbn) {
           res = "good"
       }
       fmt.Printf("%s: %s\n", isbn, res)
   }

}</lang>

Output:
978-1734314502: good
978-1734314509: bad
978-1788399081: good
978-1788399083: bad

langur

<lang langur>val .isbn13checkdigit = f(.n) {

   val .s = replace(.n, RE/[\- ]/, ZLS)
   if len(.s) != 13 {
       return false
   }
   # multiply every other number by 3
   val .nums = map(
       f(.i, .d) if(.i rem 2 == 0: .d x 3; .d),
       series(13),
       map f .c-'0', s2cp .s,
   )
   fold(f .x + .y, .nums) rem 10 == 0

}

val .tests = h{

   "978-1734314502": true,
   "978-1734314509": false,
   "978-1788399081": true,
   "978-1788399083": false,

}

for .key in sort(keys .tests) {

   val .pass = .isbn13checkdigit(.key)
   write .key, ": ", if(.pass: "good"; "bad")
   writeln if(.pass == .tests[.key]: ""; " (ISBN-13 CHECK DIGIT TEST FAILED)")

}</lang>

Output:
978-1734314502: good
978-1734314509: bad
978-1788399081: good
978-1788399083: bad

Perl 6

Works with: Rakudo version 2019.11

Also test a value that has a zero check digit.

<lang perl6>sub check-digit ($isbn) {

    (10 - (sum (|$isbn.comb(/<[0..9]>/)) »*» (1,3)) % 10).substr: *-1

}

{

   my $check = .substr(*-1);
   my $check-digit = check-digit .chop;
   say "$_ : ", $check == $check-digit ??
       'Good' !!
       "Bad check-digit $check; should be $check-digit"

} for words <

   978-1734314502
   978-1734314509
   978-1788399081
   978-1788399083
   978-2-74839-908-0
   978-2-74839-908-5

>;</lang>

Output:
978-1734314502 : Good
978-1734314509 : Bad check-digit 9; should be 2
978-1788399081 : Good
978-1788399083 : Bad check-digit 3; should be 1
978-2-74839-908-0 : Good
978-2-74839-908-5 : Bad check-digit 5; should be 0

Python

<lang python>def is_isbn13(n):

   n = n.replace('-',).replace(' ', )
   if len(n) != 13:
       return False
   product = (sum(int(ch) for ch in n[::2]) 
              + sum(int(ch) * 3 for ch in n[1::2]))
   return product % 10 == 0

if __name__ == '__main__':

   tests = 

978-1734314502 978-1734314509 978-1788399081 978-1788399083.strip().split()

   for t in tests:
       print(f"ISBN13 {t} validates {is_isbn13(t)}")</lang>
Output:
ISBN13 978-1734314502 validates True
ISBN13 978-1734314509 validates False
ISBN13 978-1788399081 validates True
ISBN13 978-1788399083 validates False