Umwandlung von ISBN-13 in ISBN-10


21

Einführung

In dieser Herausforderung besteht Ihre Aufgabe darin, den ISBN-10-Code für Bücher mit dem ISBN-13-Code zu generieren, sofern ein solcher Code vorhanden ist. Ein solcher ISBN-13-Code besteht aus mehreren Teilen, die durch Folgendes getrennt sind -:

978-GG-PPPP-TTT-C

Die Buchstaben G(Gruppe), P(Herausgeber), T(Titel) und C(Prüfsumme) stehen alle für eine Ziffer. Für die Zwecke dieser die Gruppierung Herausforderung und die Berechnung C(siehe diese Herausforderung ) sind nicht interessant , und wir werden alle Bindestriche fallen , um diese Aufgabe einfacher zu machen.

Eine ISBN-10-Nummer hat ein sehr ähnliches Layout:

GG-PPPP-TTT-c

Die Buchstaben G, Pund Tdie gleichen wie für die 13 Ziffern sind ISBN jedoch cunterscheidet (und berechnet einen anderen Algorithmus verwendet wird ). Die Ziffer cwird so gewählt, dass die folgende Äquivalenz gilt (Ziffern in Reihenfolge):

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

Beispiel

Betrachten wir die ISBN-Nummer 9780345391803: Um den entsprechenden ISBN-10-Code zu erhalten, lassen wir einfach die führende 978und die Prüfsumme fallen, die 3ergeben 034539180.

Als nächstes müssen wir die neue Prüfsumme berechnen:

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

Die nächste durch teilbare Zahl 11ist 187, daher ist die neue Prüfsumme 2und damit der resultierende ISBN-10-Code 0345391802.

Regeln

  • Ihre Eingabe hat immer eine entsprechende ISBN-10-Nummer (dh sie ist genau 13-stellig und beginnt mit 978).
  • Die Eingabe muss nicht unbedingt eine gültige ISBN-13 sein (z. B. 9780000000002).
  • Sie werden garantiert, dass die resultierende ISBN nicht mit enden wird X
  • Sie können Eingaben als Ganzzahl oder Zeichenfolge (mit oder ohne Bindestriche) vornehmen. Eine vorberechnete Liste von Ziffern ist jedoch nicht zulässig
  • Ihre Ausgabe muss eine gültige ISBN-10-Nummer sein (mit oder ohne Bindestrich)
  • Ihre Ausgabe kann eine Ganzzahl oder eine Zeichenfolge sein (wieder keine Ziffernlisten)

Testfälle

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

Beachten Sie die führenden Nullen!


5
Es hat keinerlei Auswirkungen auf Lösungen, aber nur um dieser Typ zu sein, ist Ihre Beschreibung, wie die Teile einer ISBN (entweder -10 oder -13) getrennt sind, falsch. Das Registrierungsgruppenelement ist variabel lang und die Anzahl der Stellen für nachfolgende Teile kann zwischen und innerhalb von Registrierungsgruppen variieren. Beispielsweise in beide 0-684-84328-5und 99921-58-10-7der erste Teil ( 0und 99921jeweils) die Registrierungsgruppe, ist der zweite Teil der Verleger, und so weiter.
Jordanien

5
10/10 Probe ISBN Entscheidungen
Jakob

Antworten:


10

Retina ,  44  39 28 Bytes

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

_

Probieren Sie es online!

Erläuterung

Es ist Zeit, einige neue Retina-Funktionen vorzuführen. :)

>,L3,-2`.+

Wir gleichen die gesamte Eingabe mit ab .+, geben diese Übereinstimmung zurück L, wählen jedoch nur die Zeichen 3 (nullbasiert) bis einschließlich -2 (vorletzt) ​​aus. Wir drucken das Ergebnis auch ohne nachfolgenden Zeilenumbruch ( >).

Jetzt ist es etwas ärgerlich, Dinge in der Netzhaut zu subtrahieren. Aber zum Glück arbeiten wir mit Modulo 11, also können wir einfach die Koeffizienten der Linearkombination (Mod 11) invertieren und alles aufsummieren. Mit anderen Worten, wenn die Einschränkung ist:

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

dann bekommen wir:

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

Das vereinfacht die Sache hier sehr:

.
$.>`**

Wir ersetzen jedes Zeichen durch das unten stehende. *ist der Wiederholungsoperator von Retina. Es ist rechtsassoziativ und hat implizite Operanden $&links und _rechts. Die Substitution ist also eigentlich eine Abkürzung für $.>`*$&*_. $&*_Erstellt eine Zeichenfolge mit d Unterstrichen, wobei d die Ziffer ist, die derzeit ersetzt wird. Dann $.>`ist die Länge der Zeichenfolge bis einschließlich der Übereinstimmung. 1 Somit ergibt der gesamte Ausdruck eine unäre Darstellung des n- ten Terms unserer linearen Kombination.

_{11}

Das eigentliche Modulo zu machen ist in unary trivial: Wir lassen einfach alle kompletten Sätze von 11 Unterstrichen fallen.

_

Schließlich zählen wir, wie viele Unterstriche noch vorhanden sind, und drucken das Ergebnis aus, wodurch die ISBN-10 vervollständigt wird.


1 Wie wird $.>`die Länge der Zeichenfolge einschließlich der Übereinstimmung angegeben? Vielleicht kennen Sie sich mit $`regulären Ersetzungen aus, bei denen Sie die Zeichenfolge bis zur (aber ausschließlich) Übereinstimmung erhalten. Durch Einfügen von a >können wir den Kontext von $`zum Trennzeichen zwischen der aktuellen und der nächsten Übereinstimmung verschieben (wobei es sich um eine leere Zeichenfolge zwischen der aktuellen und der nächsten Ziffer handelt). Das Trennzeichen $`enthält die aktuelle Übereinstimmung. Ist $>`also eine kürzere Art zu schreiben $`$&. Schließlich können Sie für alle $xSubstitutionselemente vom Typ Retina ein .nach dem einfügen $, um die Länge zu ermitteln.


Was ist das Modulo 11 Magie ?! Das spart mir 4 Bytes ... aber ich bekomme es nicht hin!
Streetster

1
@streetster Grundsätzlich -2 ≡ 9 (mod 11)(da das Addieren oder Subtrahieren von 11 von einer Zahl ihren "Wert" in der Kongruenzklasse mod 11 nicht ändert). Durch Addition und Multiplikation werden Kongruenzklassen berücksichtigt, sodass Sie jeden Wert in einer linearen Kombination durch einen äquivalenten Wert unter dem aktuellen Modulo ersetzen können. Der Grund, warum ich von negativen Zahlen spreche, ist, dass ich die Gleichung so umgestellt habe, dass sie cauf der einen Seite und alle anderen Terme (als Negative) auf der anderen Seite stehen.
Martin Ender

Ich glaube, ich verstehe es jetzt. Also bewegst du dich chinüber, um zu werden, -c = ...und anstatt mit 10 9 8...dir zu multiplizieren , subtrahiere 11von jedem, um zu bekommen, -1 -2 -3...und multipliziere dann alles mit -1, um zu bekommen c.
Streetster

Würde es Ihnen etwas ausmachen zu erklären, warum die letzte Stufe nur die nachgestellten Unterstriche ersetzt? Ich habe eine Weile damit verbracht herauszufinden, was das verursacht, aber ich kann es scheinbar nicht reproduzieren. Dieses Update sieht übrigens toll aus, gute Arbeit!
FryAmTheEggman

1
@FryAmTheEggman Danke :) Zu diesem Zeitpunkt enthält die Zeichenfolge nur Unterstriche. Wir haben bereits die ersten neun Ziffern in der ersten Stufe gedruckt.
Martin Ender

6

05AB1E , 17 15 13 12 Bytes

¦¦¦¨DSƶO11%«

Probieren Sie es online!

Erläuterung

¦¦¦            # 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

Probieren Sie es online!

Nimmt Eingaben entgegen "$args", führt einen regulären Ausdruck durch -replace, um nur den relevanten Teil zu erhalten, und speichert diesen $xals Zeichenfolge. Dann werfen wir das als char-array und durchlaufen jeden Buchstaben. Innerhalb der Schleife dekrementieren wir vor $a(standardmäßig 0) und multiplizieren gemäß der Prüfsummenberechnung. Beachten Sie die Umwandlung in int, da sonst ASCII-Werte verwendet werden.

Wir dann -joindiese Zahlen zusammen mit +und leiten das zu iex( Invoke-Expressionund ähnlich zu eval). Wir nehmen das %11und speichern diese Prüfsumme in $y. Schließlich verketten wir die Zeichenfolge $x + $yund belassen sie in der Pipeline. Die Ausgabe ist implizit.

Dank Emigna 12 Bytes gespart.


Ich weiß nicht wirklich Powershell, aber ich denke , so etwas wie dies kann für 84 arbeiten
Emigna

@Emigna Ja, natürlich. Modul Arithmetik und mein Gehirn spielen nicht gut.
AdmBorkBork

5

Oktave , 46 41 39 37 Bytes

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

Probieren Sie es online!

Der Code nimmt Eingaben als Zeichenfolge entgegen und gibt eine Zeichenfolge zurück.

Der Code setzt sich wie folgt zusammen:

@(a) erstellt eine anonyme Funktion.

Mit [c=a(4:12) ... ]extrahieren wir die Zeichen, die den Hauptcode bilden, speichern eine Kopie cfür die spätere Verwendung und fügen der endgültigen Ausgabezeichenfolge eine weitere Kopie hinzu.

Basierend auf @ cleveren Weg der MartinEnter Swapping 10:-1:2in 1:10, können wir leicht diesen Bereich zu generieren und umzusetzen ein Spaltenvektor zu erhalten. c*(1:10)'Führt eine Array-Multiplikation des Zeilenvektors cund des Bereichsspaltenvektors durch. Dies entspricht einer elementweisen Multiplikation und anschließenden Summierung.

Die Prüfsumme ist normalerweise die mod(11-sum,11)Berechnung der Zahl, die erforderlich ist, damit die Summe ein Vielfaches von 11 ist. Da es sich jedoch cum eine Zeichenfolge handelt, ist die Summe tatsächlich um 2592 (48 * 54) größer als sie sein sollte, da wir mit Zahlen multipliziert haben das waren 48 größer als der tatsächliche Wert.

Wenn wir das Modulo ausführen, werden automatisch alle bis auf 7 von 2592 beseitigt. Als solches und unter Berücksichtigung der Negation des Bereichs wird die tatsächliche Berechnung 48+mod(7+sum,11). Wir addieren 48 zu dem Ergebnis, um es wieder in ein ASCII-Zeichen umzuwandeln.

Das Prüfsummenzeichen wird an das Ende des Ergebnisses angehängt und der Wert zurückgegeben.


5

Gelee , 12 Bytes

ṫ4ṖȮV€xJS%11

Dies ist ein vollständiges Programm, das Zeichenfolgen für E / A verwendet.

Probieren Sie es online!

Wie es funktioniert

ṫ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 Bytes dank @ Shaggys Vorschlag .



1
Oder vielleicht sogar 56 Bytes .
Shaggy

Warum also nicht als Array von Ziffern eingeben? 54 Bytes
tsh


3

Pyth , 16 Bytes

%s.e*ksbpP>Q3hT

Probieren Sie es hier aus!

Pyth , 17 Bytes

%s*VsMKpP>Q3SlK11

Probieren Sie es hier aus!

Erläuterung

%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 Bytes

Kam damit neulich in der Kneipe runter und vergaß alles.

s3J
U+¬x_*°TÃuB

Versuch es


Denken Sie, Sie können ein Byte mit s3Jund U+¬x_*°TÃuB
speichern

Seltsam; hätte schwören können, dass ich das versucht habe. Vielen Dank, @ETHproductions.
Shaggy

Warten Sie, nein, ich hatte das U- D'oh vergessen !
Shaggy

3

Hexagony , 77 61 Bytes

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

Probieren Sie es online!


Farbig:


Hier ist eine größere Version. Es gibt einige Wegkreuzungen, aber da all diese Zellen .(in Hexagony kein Zugriff) vorhanden sind, müssen Sie sich keine Gedanken darüber machen:

(Ich habe auch versucht, die alten Spiegel zu behalten, aber manchmal muss ich etwas ändern)

Der ausgeführte lineare Befehl lautet:

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

Erläuterung: Anstatt einen Zähler zu führen und mit jeder Ziffer zu multiplizieren, führt dieses Programm Folgendes aus:

  • Behalte eine "Teilsummen" -Variable und eine "Gesamtsummen" -Variable ( pund t)
  • Für jede gelesene Ziffer: Addiere sie zur Teilsumme und addiere die Teilsumme zur Gesamtsumme.
  • Drucken (-p-t)%11, wobei %immer positive Ergebnisse zurückgegeben werden.

3

K (oK) , 29 25 24 23 Bytes

Lösung:

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

Probieren Sie es online!

Beispiele:

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"

Erläuterung:

Die Auswertung erfolgt von rechts nach links.

Zwei Tricks aus anderen Lösungen:

  • multiplizieren mit 1 2 3 ... anstelle von 10 9 8 ...
  • Multiplizieren Sie die ASCII-Werte und addieren Sie dann 7 zu der Summe, die Sie ausgleichen möchten

Nervenzusammenbruch:

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

Anmerkungen:

  • -4 Bytes dank Martin Enders " invertiere einfach die Koeffizienten Zauber ".
  • -1 Byte danke an Tom Carpenter für den Wegfall der Konvertierung in Ganzzahlen (durch Addition 7zur Summe)
  • -1 Byte Startet den Akku bei 7

3

C (gcc), 96 95 87 86 85 Bytes

(-1 dank ceilingcat)

*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;}

Probieren Sie es online!

Zu nennen als f(s), wobei sein Zeiger auf das erste Element eines modifizierbaren Zeichenarrays ist. Ändert das Eingabearray und gibt einen Zeiger in das Eingabearray zurück.




2

ECMAScript 6 , 86 67 Bytes

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

Probieren Sie es online!


Vielen Dank für den Kommentar von Arnauld , der von reducezu mapgeändert und das returnKeyword entfernt wurde.


3
Willkommen bei PPCG! Die Antworten müssen entweder vollständige Programme oder aufrufbare Funktionen sein (obwohl es sich möglicherweise um unbenannte Funktionen handelt), nicht nur Schnipsel. Ich glaube, die kürzeste Option in JavaScript ist normalerweise ein unbenanntes Lambda.
Martin Ender

@ MartinEnder Dank, ich habe meine Antwort bearbeitet
Kos

3
Willkommen an Bord! Einige Tipps: Variable Initialisierung kann in der Regel als zusätzliche Parameter gesetzt werden map(), reduce()usw. Mit einigen zusätzlichen Umschreiben, ist es oft möglich loswerden {}und return. Auch ist in diesem speziellen Fall map()wahrscheinlich kürzer als reduce(). ( Hier ist eine 65-Byte-Version.)
Arnauld

Ich bin mir ziemlich sicher, dass f=das nicht notwendig ist. Sie können auch cbei der Verbreitung für so etwas initialisieren : a=>{i=10;s=[...c=a.substr(3,9)].reduce((g,v)=>+g+(i--)*v,0)%11;return c+=s?11-s:0}(-4 Bytes)
Asone Tuhid

2

Retina 0.8.2 , 72 51 Bytes

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

¶(1*)
$.1

Probieren Sie es online! Weil ich Retina 1.0 noch nicht gelernt habe. Erläuterung:

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

Löschen Sie die unerwünschten Zeichen und machen Sie eine zweite Kopie der entsprechenden Ziffern.

r`.\G
$&$'

Suffixieren Sie jede Ziffer in der zweiten Kopie mit ihrem Suffix. Dies wiederholt effektiv jede Ziffer im Suffix nach ihrer Position.

r`.\G
$*

Wandeln Sie die Ziffern in der zweiten Kopie in unäre um und addieren Sie sie so.

1{11}

Modulo 11 reduzieren. (Die erste Kopie enthält nur 9 Ziffern, dies kann sich also nie auf sie auswirken.)

¶(1*)
$.1

Wandle das Ergebnis zurück in eine Dezimalzahl und entferne die neue Zeile wieder.


2

APL (Dyalog Unicode) , 26 24 Bytes

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

Probieren Sie es online!

Tacit-Präfix-Funktion. Übernimmt die Eingabe als String.

2 Bytes gespart dank @ngn.

Wie?

∊⍕¨(⊢,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 Bytes

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

Verschönert

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

Prüfung

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

TryItOnline



1

PHP, 64 Bytes

Leider ist in PHP (-$c)%11das gleiche wie -($c%11); Ich muss also die Differenz auf mindestens die größtmögliche Summe bringen (55 * 9 = 495 = 45 * 11), anstatt nur zu verwenden -$c%11.

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

oder

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

Laufen Sie als Pipe mit -nRoder probieren Sie sie online aus .


0

Java 10, 110 Bytes

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;}

Nimmt Ein- und Ausgaben als longGanzzahl. Probieren Sie es hier online aus .

Ungolfed-Version:

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
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.