Chuyển đổi ISBN-13 thành ISBN-10


21

Giới thiệu

Trong thử thách này, nhiệm vụ của bạn là tạo mã ISBN-10 cho các cuốn sách được cung cấp mã ISBN-13, giả sử rằng mã đó tồn tại. Mã ISBN-13 như vậy bao gồm một số phần được phân tách bằng -:

978-GG-PPPP-TTT-C

Các chữ cái G(nhóm), P(nhà xuất bản), T(tiêu đề) và C(tổng kiểm tra) đều có nghĩa là một chữ số. Với mục đích của thử thách này, việc nhóm và tính toán C(xem thử thách này ) không thú vị và chúng tôi sẽ bỏ tất cả các dấu gạch nối để làm cho nhiệm vụ này đơn giản hơn.

Một số ISBN-10 có bố cục rất giống nhau:

GG-PPPP-TTT-c

Tuy nhiên G, các chữ cái PTgiống như đối với 13 chữ số ISBN, tuy nhiên lại ckhác nhau (và được tính bằng thuật toán khác). Chữ số cđược chọn theo cách giữ tương đương sau (chữ số theo thứ tự):

10*G + 9*G + 8*P + … + 3*T + 2*T + 1*c = 0 (mod 11)

Thí dụ

Chúng ta hãy xem xét số ISBN 9780345391803: Để có được mã ISBN-10 tương ứng, chúng ta chỉ cần bỏ phần đầu 978và tổng kiểm tra 3năng suất 034539180.

Tiếp theo chúng ta cần tính toán tổng kiểm tra mới:

10*0 + 9*3 + 8*4 + 7*5 + 6*3 + 5*9 + 4*1 + 3*8 + 2*0 = 185

Số tiếp theo chia hết cho 11187, do đó, tổng kiểm tra mới 2và do đó là mã ISBN-10 0345391802.

Quy tắc

  • Đầu vào của bạn sẽ luôn có một số ISBN-10 tương ứng (nghĩa là nó dài chính xác 13 chữ số và bắt đầu bằng 978)
  • Đầu vào không nhất thiết phải là một số hợp lệ-13 (ví dụ 9780000000002:)
  • Bạn được đảm bảo rằng kết quả ISBN sẽ không kết thúc bằng X
  • Bạn có thể lấy đầu vào dưới dạng số nguyên hoặc chuỗi (có hoặc không có dấu gạch ngang) tuy nhiên không được phép liệt kê danh sách các chữ số được tính toán trước
  • Đầu ra của bạn phải là số ISBN-10 hợp lệ (có hoặc không có dấu gạch ngang)
  • Đầu ra của bạn có thể là một số nguyên hoặc chuỗi (một lần nữa không có danh sách các chữ số)

Tủ thử

9780000000002 -> 0000000000
9780201882957 -> 0201882957
9781420951301 -> 1420951300
9780452284234 -> 0452284236
9781292101767 -> 1292101768
9780345391803 -> 0345391802

Lưu ý các số 0 hàng đầu!


5
Nó hoàn toàn không ảnh hưởng đến các giải pháp, nhưng chỉ vì mục đích là Người đó, mô tả của bạn về cách các phần của một mã số (-10 hoặc -13) được phân tách là không chính xác. Phần tử nhóm đăng ký có độ dài thay đổi và số chữ số cho các phần tiếp theo có thể khác nhau giữa và trong các nhóm đăng ký. Ví dụ: trong cả hai 0-684-84328-599921-58-10-7, phần đầu tiên ( 099921tương ứng) là nhóm đăng ký, phần thứ hai là nhà xuất bản, v.v.
Jordan

5
10/10 lựa chọn ISBN mẫu
Jakob

Câu trả lời:


10

Võng mạc ,  44  39 28 byte

>,L3,-2`.+
.
$.>`**
_{11}

_

Hãy thử trực tuyến!

Giải trình

Thời gian để thể hiện một số tính năng Retina mới. :)

>,L3,-2`.+

Chúng tôi khớp toàn bộ đầu vào với .+, trả về kết quả khớp đó L, nhưng chỉ chọn các ký tự 3 (không dựa trên) thành -2 (áp chót), bao gồm. Chúng tôi cũng in kết quả mà không có linefeed ( >).

Bây giờ, trừ đi những thứ trong Retina là một chút khó chịu. Nhưng may mắn thay, chúng tôi đang làm việc modulo 11, vì vậy chúng tôi có thể đảo ngược các hệ số của tổ hợp tuyến tính (mod 11) và thêm mọi thứ lên. Nói cách khác, nếu ràng buộc là:

10*G + 9*G + 8*P + … + 3*T + 2*T + 1*c = 0 (mod 11)

sau đó chúng tôi nhận được:

c = 1*G + 2*G + 3*P + … + 8*T + 9*T (mod 11)

Điều đó đơn giản hóa mọi thứ rất nhiều ở đây:

.
$.>`**

Chúng tôi thay thế mỗi nhân vật với điều đó ở phía dưới. *là toán tử lặp lại của Retina. Đó là liên kết bên phải và nó có các toán hạng ngầm $&bên trái và _bên phải, vì vậy sự thay thế thực sự là viết tắt của $.>`*$&*_. $&*_tạo một chuỗi các dấu gạch dưới d , trong đó d là chữ số chúng ta hiện đang thay thế. Sau đó $.>`là độ dài của chuỗi lên đến và bao gồm cả trận đấu. 1 Do đó, toàn bộ biểu thức dẫn đến một biểu diễn đơn nhất của số hạng thứ n của tổ hợp tuyến tính của chúng tôi.

_{11}

Làm modulo thực tế là không quan trọng trong unary: chúng tôi chỉ cần bỏ tất cả các bộ hoàn chỉnh của 11 dấu gạch dưới.

_

Cuối cùng, chúng tôi đếm số lượng dấu gạch dưới còn lại và in kết quả, hoàn thành mã số-10.


1 Làm thế nào để $.>`cung cấp độ dài của chuỗi lên đến và bao gồm cả trận đấu? Bạn có thể quen thuộc với các $`thay thế regex, cung cấp cho bạn chuỗi lên đến (nhưng không bao gồm) trận đấu. Bằng cách chèn một >, chúng tôi có thể thay đổi bối cảnh $`cho tách giữa các trận đấu hiện nay và tiếp theo (đó là một chuỗi rỗng giữa các chữ số hiện nay và tiếp theo). Dải phân cách đó $`sẽ bao gồm trận đấu hiện tại. Vì vậy, $>`là một cách ngắn hơn để viết $`$&. Cuối cùng, đối với các $xyếu tố thay thế tất cả các loại, Retina cho phép bạn chèn .sau một $để có được chiều dài của nó.


Phép thuật modulo 11 này là gì?! Điều đó sẽ giúp tôi tiết kiệm 4 byte ... nhưng tôi không nhận được!
streetster

1
@streetster Về cơ bản, -2 ≡ 9 (mod 11)(vì việc cộng hoặc trừ 11 từ một số không làm thay đổi "giá trị" của nó trong lớp 11 đồng dư mod). Và phép cộng và phép nhân tôn trọng các lớp đồng dư, vì vậy bạn có thể thay thế bất kỳ giá trị nào trong tổ hợp tuyến tính bằng một giá trị tương đương theo modulo hiện tại. Lý do tôi đang nói về các số âm thực sự chỉ là tôi đã sắp xếp lại phương trình cần có cở một bên và tất cả các thuật ngữ khác (dưới dạng phủ định) ở bên kia.
Martin Ender

Tôi nghĩ rằng tôi nhận được nó ngay bây giờ. Vì vậy, bạn di chuyển cđể trở thành -c = ...và thay vì nhân với 10 9 8...bạn trừ đi 11từng cái để nhận -1 -2 -3...và sau đó nhân mọi thứ với -1 để có được c.
streetster

Bạn có thể giải thích lý do tại sao giai đoạn cuối cùng chỉ thay thế dấu gạch dưới? Tôi đã dành một khoảng thời gian để cố gắng tìm ra nguyên nhân gây ra điều đó nhưng dường như tôi không thể tái tạo nó. Bản cập nhật này trông tuyệt vời bằng cách này, công việc tốt đẹp!
FryAmTheEggman

1
@FryAmTheEggman Cảm ơn :) Tại thời điểm đó, chuỗi chỉ chứa dấu gạch dưới. Chúng tôi đã in chín chữ số đầu tiên trong giai đoạn đầu tiên.
Martin Ender

6

05AB1E , 17 15 13 12 byte

¦¦¦¨DSƶO11%«

Hãy thử trực tuyến!

Giải trình

¦¦¦            # remove the first 3 characters
   ¨           # remove the last character
    D          # duplicate
     S         # split to list of digits
      ƶ        # multiply each by its 1-based index
       O       # sum
        11%    # mod by 11
           «   # concatenate

5

PowerShell , 96 84 byte

$y=-(([char[]]($x="$args"-replace'^978|.$')|%{--$a*[int]"$_"})-join'+'|iex)%11;$x+$y

Hãy thử trực tuyến!

Đưa đầu vào "$args", thực hiện một regex -replaceđể chỉ lấy phần thích hợp, lưu trữ nó thành $xmột chuỗi. Sau đó, chúng tôi sử dụng nó như một char-array và lặp qua từng chữ cái. Trong vòng lặp, chúng tôi giảm trước $a(mặc định 0) và nhân ra theo tính toán tổng kiểm tra. Lưu ý chuyển sang int, nếu không, điều này sẽ sử dụng các giá trị ASCII.

Chúng tôi sau đó -joinnhững con số đó cùng với +và dẫn đến iex( Invoke-Expressionvà tương tự eval). Chúng tôi lấy đó %11và lưu trữ tổng kiểm tra vào $y. Cuối cùng, chúng tôi xâu chuỗi $x + $yvà để nó trên đường ống. Đầu ra là ẩn.

Đã lưu 12 byte nhờ Emigna.


Tôi thực sự không biết powershell, nhưng tôi nghĩ một cái gì đó như thế này có thể hoạt động cho 84
Emigna

@Emigna Vâng, tất nhiên. Modulus số học và bộ não của tôi không chơi độc đáo.
admBorkBork

5

Octave , 46 41 39 37 byte

@(a)[c=a(4:12) 48+mod(7+c*(1:9)',11)]

Hãy thử trực tuyến!

Mã nhận đầu vào dưới dạng một chuỗi và trả về một chuỗi.

Mã bị hỏng như sau:

@(a) tạo ra một chức năng ẩn danh.

Với việc [c=a(4:12) ... ]chúng tôi trích xuất các ký tự tạo thành mã chính, lưu một bản sao để csử dụng sau và thêm một bản sao khác vào chuỗi đầu ra cuối cùng.

Dựa trên @ cách thông minh MartinEnter của trao đổi 10:-1:2vào 1:10, chúng ta có thể dễ dàng tạo ra phạm vi đó và transpose nó để có được một vector cột. c*(1:10)'không nhân mảng của vectơ hàng cvà vectơ cột phạm vi. Điều này tương đương với việc thực hiện phép nhân phần tử sau đó tính tổng.

Tổng kiểm tra thường sẽ mod(11-sum,11)tính số cần thiết cho tổng là bội số của 11. Tuy nhiên, vì clà một chuỗi ký tự, nên tổng sẽ thực sự lớn hơn 2592 (48 * 54) vì chúng tôi nhân với số lớn hơn 48 so với giá trị thực tế.

Khi chúng tôi thực hiện modulo, nó sẽ tự động loại bỏ tất cả trừ 7 trong số 2592 đó. Như vậy, và tính đến sự phủ định của phạm vi, phép tính thực tế trở thành 48+mod(7+sum,11). Chúng tôi thêm vào 48 vào kết quả để chuyển đổi trở lại thành ký tự ASCII.

Ký tự tổng kiểm tra được thêm vào cuối kết quả và giá trị được trả về.


5

Thạch , 12 byte

ṫ4ṖȮV€xJS%11

Đây là một chương trình đầy đủ sử dụng các chuỗi cho I / O.

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

ṫ4ṖȮV€xJS%11  Main link. Argument: s (string of length 13)

ṫ4            Tail 4; discard the first three characters.
  Ṗ           Pop; discard the last characters.
   Ȯ          Output; print the result to STDOUT and return it.
    V€        Eval each; turn digit characters into digits.
       J      Indices; yield [1, ..., 13].
      x       Repeat the first digit once, the second digit twice, etc.
        S%11  Take the sum, modulo 11.
              (implicit) Print the checksum to STDOUT.

4

JavaScript (ES6), 59 56 byte

s=>(s=s.slice(3,-1))+[...s].reduce(n=>n+s[i++]*i,i=0)%11

-3 byte nhờ đề xuất của @ Shaggy .



1
Hoặc thậm chí có thể 56 byte .
Xù xì

Vậy tại sao không nhập vào dưới dạng các chữ số? 54 byte
tsh


3

Bình thường , 16 byte

%s.e*ksbpP>Q3hT

Hãy thử nó ở đây!

Bình thường , 17 byte

%s*VsMKpP>Q3SlK11

Hãy thử nó ở đây!

Giải trình

%s.e*hksbpP>Q3hT || Full program. Uses string for input and output.

            Q    || The input.
           > 3   || With elements at indexes smaller than 3 trimmed.
          P      || Pop (remove the last item).
         p       || Print the result without a linefeed, but also return it.
  .e             || Enumerated map. For each (index, value), assign two variables (k, b).
       sb        || b converted to an integer.
    *hk          || And multiplied by k + 1.
 s               || Summation.
%                || Modulo by:
               T || The literal 10.
              h  || Incremented by 1.

3

Japt , 16 15 byte

Đến với quán rượu này đêm nọ và quên tất cả về nó.

s3J
U+¬x_*°TÃuB

Thử nó


Hãy nghĩ rằng bạn có thể lưu một byte bằng s3JU+¬x_*°TÃuB
ETHproductions

Kỳ dị; có thể đã thề tôi đã thử điều đó. Cảm ơn, @ETHproductions.
Xù xì

Đợi đã, không, tôi đã quên U- D'oh!
Xù xì

3

Lục giác , 77 61 byte

,,,,'~'11=\.A&.=\./';"-'"{4.8}}\'.A.>.,<\'+'%!@}/=+'+{./&{{&/

Hãy thử trực tuyến!


Màu:


Đây là một phiên bản lớn hơn. Có một số giao cắt đường dẫn, nhưng vì tất cả các ô đó là .(không có trong Hexagony), bạn không cần phải lo lắng về chúng:

(Tôi cũng đã cố gắng giữ những chiếc gương cũ, nhưng đôi khi tôi cần thay đổi một cái gì đó)

Lệnh tuyến tính được thực thi là:

,,,,'48}}
,
while memory > 0:
    ';"-'"{+'+{=A&=''A
    if memory < 0:
        undefined behavior
    &{{&}
    ,
'"''+~'11='%!@

Giải thích: Thay vì giữ một bộ đếm và thực hiện phép nhân ở mỗi chữ số, chương trình này:

  • giữ một biến "tổng một phần" và biến "tổng cộng" ( pt)
  • cho mỗi chữ số đọc: thêm nó vào tổng một phần và thêm tổng một phần vào tổng tổng.
  • in (-p-t)%11, nơi %luôn trả lại kết quả tích cực.

3

K (oK) , 29 25 24 23 byte

Dung dịch:

x,$11!7+/(1+!9)*x:-1_3_

Hãy thử trực tuyến!

Ví dụ:

x,$11!7+/(1+!9)*x:-1_3_"9780000000002"
"0000000000"
x,$11!7+/(1+!9)*x:-1_3_"9780345391803"
"0345391802"
x,$11!7+/(1+!9)*x:-1_3_"9781292101767"
"1292101768"
x,$11!7+/(1+!9)*x:-1_3_"9780452284234"
"0452284236"

Giải trình:

Đánh giá được thực hiện từ phải sang trái.

Hai thủ thuật được lấy từ các giải pháp khác:

  • nhân với 1 2 3 ... thay vì 10 9 8 ...
  • nhân các giá trị ASCII và sau đó thêm 7 vào tổng để cân bằng

Phá vỡ:

x,$11!7+/(1+!9)*x:-1_3_ / the solution
                     3_ / drop three items from the start
                  -1_   / drop one item from the end
                x:      / save this as variable x
               *        / multiply by
         (    )         / all this together
            !9          / til, !9 => 0 1 2 3 4 5 6 7 8
          1+            / add 1 => 1 2 3 4 5 6 7 8 9
      7+/               / sum (+) over (/), start from 7
   11!                  / mod by 11
  $                     / convert back to a string
x,                      / join with x

Ghi chú:

  • -4 byte nhờ vào phép thuật " chỉ đảo ngược các hệ số " của Martin Enders .
  • -1 byte nhờ Tom Carpenter đã loại bỏ nhu cầu chuyển đổi sang số nguyên (bằng cách thêm 7vào tổng)
  • -1 byte bắt đầu bộ tích lũy ở 7

3

C (gcc), 96 95 87 86 85 byte

(-1 nhờ trần nhà)

*f(s,r,c,d)char*s,*r;{for(d=13;--d;s+=*++s<48)r=d>8?c=3,s:r,c-=~d**s;*s=58-c%11;s=r;}

Hãy thử trực tuyến!

Được gọi là f(s), trong đó smột con trỏ tới phần tử đầu tiên của mảng ký tự có thể sửa đổi. Sửa đổi mảng đầu vào, trả về một con trỏ vào mảng đầu vào.




2

ECMAScript 6 , 86 67 byte

a=>(c=a.substr(3,9))+([...c].map(v=>g+=--i*v,e=i=g=11)?(e-g%e)%e:0)

Hãy thử trực tuyến!


Cám ơn ý kiến Arnauld của , chuyển từ reduceđến mapvà đã thoát khỏi returntừ khóa.


3
Chào mừng đến với PPCG! Câu trả lời phải là chương trình đầy đủ hoặc chức năng có thể gọi được (mặc dù chúng có thể là chức năng chưa được đặt tên), không chỉ là đoạn trích. Tôi tin rằng tùy chọn ngắn nhất trong JavaScript thường là lambda không tên.
Martin Ender

@MartinEnder cảm ơn, tôi đã chỉnh sửa câu trả lời của mình
Kos

3
Chào mừng bạn trên tàu! Một số mẹo: Khởi tạo biến thường có thể được đặt dưới dạng tham số bổ sung map(), reduce()v.v ... Với một số cách viết bổ sung, thường có thể loại bỏ {}return. Ngoài ra, trong trường hợp cụ thể này, map()có lẽ ngắn hơn reduce(). ( Đây là phiên bản 65 byte.)
Arnauld

Tôi khá chắc chắn f=là không cần thiết. Ngoài ra, bạn có thể khởi tạo ctại mức a=>{i=10;s=[...c=a.substr(3,9)].reduce((g,v)=>+g+(i--)*v,0)%11;return c+=s?11-s:0}
chênh lệch

2

Võng mạc 0.8.2 , 72 51 byte

...(.*).
$1¶$1
r`.\G
$&$'
r`.\G
$*
1{11}

¶(1*)
$.1

Hãy thử trực tuyến! Bởi vì tôi chưa học Retina 1.0. Giải trình:

...(.*).
$1¶$1

Xóa các ký tự không mong muốn và tạo một bản sao thứ hai của các chữ số thích hợp.

r`.\G
$&$'

Hậu tố mỗi chữ số trong bản sao thứ hai với hậu tố của nó. Điều này có hiệu quả lặp lại mỗi chữ số trong hậu tố bởi vị trí của nó.

r`.\G
$*

Chuyển đổi các chữ số trong bản sao thứ hai thành unary do đó thêm chúng lại với nhau.

1{11}

Giảm modulo 11. (Chỉ có 9 chữ số trong bản sao đầu tiên, vì vậy điều này không bao giờ có thể ảnh hưởng đến nó.)

¶(1*)
$.1

Chuyển đổi kết quả trở lại thập phân và xóa dòng mới một lần nữa.


2

APL (Dyalog Unicode) , 26 24 byte

∊⍕¨(⊢,11|⊢+.×⍳∘≢)3↓¯1↓⍎¨

Hãy thử trực tuyến!

Hàm tiền tố ngầm. Lấy đầu vào dưới dạng chuỗi.

2 byte được lưu nhờ @ngn.

Làm sao?

∊⍕¨(⊢,11|⊢+.×⍳∘≢)3↓¯1↓⍎¨     Main function.
                       ⍎¨     Execute each; turns the string into a vector of digits.
                 3↓¯1        Drop (↓) the last 1) and the first 3 digits.
   (           ≢)             Tally; returns the number of digits in the vector.
             ⍳∘                Then (∘) index (⍳) from 1
            ×                 Multiply the resulting vector [1..9]
         ⊢+.                  Dot product with sum with the original vector;
                              This will multiply both vectors, and sum the resulting vector.
      11|                     Mod 11
     ,                        Concatenate
                             With the original vector
 ⍕¨                           Format each; returns a vector of digits as strings.
                             Flatten to get rid of the spaces.


1

Kotlin , 83 byte

i.drop(3).dropLast(1).let{it+(11-(it.mapIndexed{i,c->(10-i)*(c-'0')}.sum()%11))%11}

Làm đẹp

i.drop(3).dropLast(1).let {
    it + (11 - (it.mapIndexed { i, c -> (10 - i) * (c - '0') }.sum() % 11)) % 11
}

Kiểm tra

data class Test(val input: String, val output: String)

fun f(i: String) =

i.drop(3).dropLast(1).let{it+(11-(it.mapIndexed{i,c->(10-i)*(c-'0')}.sum()%11))%11}

val tests = listOf(
        Test("9780000000002", "0000000000"),
        Test("9780201882957", "0201882957"),
        Test("9781420951301", "1420951300"),
        Test("9780452284234", "0452284236"),
        Test("9781292101767", "1292101768"),
        Test("9780345391803", "0345391802")
)

fun main(args: Array<String>) {
    for (c in tests) {
        val answer = f(c.input)
        val good = answer == c.output
        println("$good ${c.input} -> ${c.output} | $answer")
    }
}

TIO

Dùng thử



1

PHP, 64 byte

Thật không may, trong PHP (-$c)%11cũng giống như -($c%11); vì vậy tôi phải lấy chênh lệch ít nhất là số tiền lớn nhất có thể (55 * 9 = 495 = 45 * 11) thay vì chỉ sử dụng -$c%11.

for($f=11;--$f>1;print$d)$c+=$f*$d=$argn[13-$f];echo(495-$c)%11;

hoặc là

for($c=45*$f=11;--$f>1;print$d)$c-=$f*$d=$argn[13-$f];echo$c%11;

Chạy như ống với -nRhoặc thử chúng trực tuyến .


0

Java 10, 110 byte

l->{var s=l+"";int c=0,i=3;for(;i<12;)c+=(13-i)*(s.charAt(i++)-48);return(l-(long)978e10)/10*10+(11-c%11)%11;}

Lấy đầu vào và đầu ra như một longsố nguyên. Hãy thử trực tuyến tại đây .

Phiên bản bị đánh cắp:

l -> { // lambda taking a long as argument
    var s = l + ""; // convert the input to a String
    int c = 0, // the check digit
    i = 3; // variable for iterating over the digits
    for(; i < 12 ;) // go from the first digit past 978 to the one before the check digit
        c += (13 - i) * (s.charAt(i++) - 48); // calculate the check sum
    return (l - (long) 978e10) // remove the leading 978
           /10 *10 // remove the original check digit
           + (11 - c % 11) % 11; // add the new check digit
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.