Introducción
En este desafío, su tarea es generar el código ISBN-10 para libros dado su código ISBN-13, suponiendo que dicho código exista. Tal código ISBN-13 consta de varias partes separadas por -
:
978-GG-PPPP-TTT-C
Las letras G
(grupo), P
(editor), T
(título) y C
(suma de verificación) representan un dígito. Para el propósito de este desafío, la agrupación y el cálculo de C
(ver este desafío ) no son interesantes y eliminaremos todos los guiones para simplificar esta tarea.
Un número ISBN-10 tiene un diseño muy similar:
GG-PPPP-TTT-c
Las letras G
, P
y T
son las mismas que para el ISBN de 13 dígitos, sin embargo, c
son diferentes (y se calculan utilizando un algoritmo diferente). El dígito c
se elige de tal manera que se cumpla la siguiente equivalencia (dígitos en orden):
10*G + 9*G + 8*P + … + 3*T + 2*T + 1*c = 0 (mod 11)
Ejemplo
Consideremos el número ISBN 9780345391803
: para obtener su código ISBN-10 correspondiente, simplemente eliminamos 978
el 3
rendimiento inicial y la suma de comprobación 034539180
.
A continuación, debemos calcular la nueva suma de verificación:
10*0 + 9*3 + 8*4 + 7*5 + 6*3 + 5*9 + 4*1 + 3*8 + 2*0 = 185
El siguiente número divisible por 11
es 187
, entonces la nueva suma de verificación es 2
y, por lo tanto, el código ISBN-10 resultante 0345391802
.
Reglas
- Su entrada siempre tendrá un número ISBN-10 correspondiente (es decir, tiene exactamente 13 dígitos y comienza con
978
) - La entrada no necesariamente tiene que ser un ISBN-13 válido (p. Ej.
9780000000002
) - Le garantizamos que el ISBN resultante no terminará con
X
- Puede tomar la entrada como un entero o cadena (con o sin guiones), sin embargo, no se permite una lista de dígitos calculada previamente
- Su salida debe ser un número ISBN-10 válido (con o sin guiones)
- Su salida puede ser un entero o una cadena (de nuevo, no hay listas de dígitos)
Casos de prueba
9780000000002 -> 0000000000
9780201882957 -> 0201882957
9781420951301 -> 1420951300
9780452284234 -> 0452284236
9781292101767 -> 1292101768
9780345391803 -> 0345391802
Tenga en cuenta los ceros a la izquierda!
0-684-84328-5
y99921-58-10-7
, la primera parte (0
y99921
respectivamente) es el grupo de registro, la segunda parte es el editor, y así sucesivamente.Respuestas:
Retina ,
443928 bytesPruébalo en línea!
Explicación
Es hora de mostrar algunas nuevas características de Retina. :)
Hacemos coincidir toda la entrada con
.+
, devolvemos esa coincidenciaL
, pero seleccionamos solo los caracteres 3 (basados en cero) a -2 (penúltimo), inclusive. También imprimimos el resultado sin un salto de línea final (>
).Ahora, restar cosas en Retina es un poco molesto. Pero afortunadamente, estamos trabajando en el módulo 11, por lo que podemos invertir los coeficientes de la combinación lineal (mod 11) y sumar todo. En otras palabras, si la restricción es:
entonces obtenemos:
Eso simplifica mucho las cosas aquí:
Reemplazamos cada personaje con esa cosa en la parte inferior.
*
es el operador de repetición de Retina. Es asociativo a la derecha y tiene operandos implícitos$&
a la izquierda y_
a la derecha, por lo que la sustitución es realmente la abreviatura de$.>`*$&*_
.$&*_
crea una serie de d guiones bajos, donde d es el dígito que actualmente estamos reemplazando. Luego$.>`
es la longitud de la cadena hasta e incluyendo el partido. 1 Por lo tanto, toda la expresión da como resultado una representación unaria de la n º plazo de nuestra combinación lineal.Hacer el módulo real es trivial en unario: simplemente eliminamos todos los conjuntos completos de 11 guiones bajos.
Finalmente, contamos cuántos guiones bajos quedan e imprimimos el resultado, que completa el ISBN-10.
1 ¿Cómo
$.>`
da la longitud de la cuerda hasta e incluyendo el partido? Es posible que esté familiarizado con las$`
sustituciones de expresiones regulares, que le dan la cadena hasta (pero excluyendo) la coincidencia. Al insertar a>
, podemos cambiar el contexto de$`
al separador entre la coincidencia actual y la siguiente (que es una cadena vacía entre el dígito actual y el siguiente). Ese separador$`
incluirá la coincidencia actual. Entonces,$>`
es una forma más corta de escribir$`$&
. Finalmente, para todos los$x
elementos de sustitución de tipo, Retina le permite insertar un.
después del$
para obtener su longitud.fuente
-2 ≡ 9 (mod 11)
(porque sumar o restar 11 de un número no cambia su "valor" en la clase de congruencia mod 11). Y la suma y la multiplicación respetan las clases de congruencia, por lo que puede reemplazar cualquier valor en una combinación lineal con un valor equivalente bajo el módulo actual. La razón por la que estoy hablando de números negativos es realmente porque he reorganizado la ecuación para tenerlac
en un lado y todos los demás términos (como negativos) en el otro.c
para convertirte-c = ...
y, en lugar de multiplicar por10 9 8...
, restas11
de cada uno para obtener-1 -2 -3...
y luego multiplicas todo por -1 para obtenerc
.05AB1E ,
17151312 bytesPruébalo en línea!
Explicación
fuente
PowerShell ,
9684 bytesPruébalo en línea!
Toma entrada
"$args"
, hace una expresión regular-replace
para obtener solo la parte pertinente, la almacena$x
como una cadena. Luego lo lanzamos como unachar
matriz y recorremos cada letra. Dentro del bucle, pre-decrementamos$a
(que por defecto es0
) y multiplicamos de acuerdo con el cálculo de la suma de verificación. Tenga en cuenta la conversión aint
, de lo contrario esto usaría valores ASCII.Luego
-join
juntamos esos números+
y los canalizamos aiex
(Invoke-Expression
y similares aeval
). Tomamos eso%11
y almacenamos esa suma de verificación$y
. Finalmente, encadenamos$x + $y
y dejamos eso en la tubería. La salida es implícita.Guardado 12 bytes gracias a Emigna.
fuente
Octava ,
46 41 3937 bytesPruébalo en línea!
El código toma la entrada como una cadena y devuelve una cadena.
El código se descompone de la siguiente manera:
@(a)
Crea una función anónima.Con
[c=a(4:12) ... ]
extraemos los caracteres que forman el código principal, guardamos una copiac
para su uso posterior y agregamos otra copia a la cadena de salida final.Sobre la base de @ forma inteligente de MartinEnter de intercambiar
10:-1:2
en1:10
, podemos generar fácilmente ese rango y la transposición a obtener un vector columna.c*(1:10)'
hace una multiplicación de matriz del vector de filac
y del vector de columna de rango. Esto es equivalente a hacer una multiplicación por elementos y luego sumar.La suma de verificación normalmente sería
mod(11-sum,11)
calcular el número requerido para que la suma sea un múltiplo de 11. Sin embargo, debido a quec
era una cadena de caracteres, la suma en realidad será mayor de lo que debería ser por 2592 (48 * 54) porque multiplicamos por números que eran 48 más grandes que el valor real.Cuando realizamos el módulo, eliminará automáticamente todos menos 7 de ese 2592. Como tal, y teniendo en cuenta la negación del rango, el cálculo real se convierte
48+mod(7+sum,11)
. Agregamos 48 al resultado para volver a convertirlo en un carácter ASCII.El carácter de suma de comprobación se agrega al final del resultado y se devuelve el valor.
fuente
Jalea , 12 bytes
Este es un programa completo que utiliza cadenas para E / S.
Pruébalo en línea!
Cómo funciona
fuente
JavaScript (ES6),
5956 bytesMostrar fragmento de código
-3 bytes gracias a la sugerencia de @ Shaggy .
fuente
Perl 5 , 49 + 1 (
-p
) = 50 bytesPruébalo en línea!
fuente
Pyth , 16 bytes
Pruébalo aquí!
Pyth , 17 bytes
Pruébalo aquí!
Explicación
fuente
Japt ,
1615 bytesSe me ocurrió esto en el pub la otra noche y lo olvidé por completo.
Intentalo
fuente
s3J
yU+¬x_*°TÃuB
U
... ¡Oh!Hexagonía ,
7761 bytesPruébalo en línea!
De colores:
Aquí hay una versión más grande. Hay algunos cruces de ruta, pero porque todas esas celdas son
.
(no operativas en Hexagony), no necesita preocuparse por ellas:(También traté de mantener los viejos espejos, pero a veces necesito cambiar algo)
El comando lineal ejecutado es:
Explicación: en lugar de mantener un contador y multiplicar cada dígito, este programa:
p
yt
)(-p-t)%11
, donde%
siempre devuelve resultados positivos.fuente
K (oK) ,
29252423 bytesSolución:
Pruébalo en línea!
Ejemplos:
Explicación:
La evaluación se realiza de derecha a izquierda.
Dos trucos tomados de otras soluciones:
Descompostura:
Notas:
7
a la suma)fuente
C (gcc)
96 95 87 8685 bytes(-1 gracias a ceilingcat)
Pruébalo en línea!
Para ser llamado como
f(s)
, dondes
es un puntero al primer elemento de una matriz de caracteres modificables. Modifica la matriz de entrada, devuelve un puntero en la matriz de entrada.fuente
Python 2 , 62 bytes
Pruébalo en línea!
Toma una cadena como entrada; y genera una cadena.
fuente
Jalea , 14 bytes
¡Banco de pruebas!
Jalea , 17 bytes
Pruébalo en línea! o Test suite!
Toma entradas y salidas como una cadena.
fuente
ECMAScript 6 ,
8667 bytesPruébalo en línea!
Gracias por el comentario de Arnauld , cambiaron de
reduce
amap
y se deshicieron dereturn
la palabra clave.fuente
map()
,reduce()
etc. Con alguna reescritura adicional, a menudo es posible deshacerse de{}
yreturn
. Además, en este caso particular,map()
es probablemente más corto quereduce()
. ( Aquí hay una versión de 65 bytes.)f=
que no es necesario. Además, puede inicializarc
en el spread para algo como esto: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)Retina 0.8.2 ,
7251 bytesPruébalo en línea! Porque todavía no he aprendido Retina 1.0. Explicación:
Elimine los caracteres no deseados y haga una segunda copia de los dígitos apropiados.
Sufije cada dígito en la segunda copia con su sufijo. Esto efectivamente repite cada dígito en el sufijo por su posición.
Convierta los dígitos en la segunda copia a unario y así sumarlos.
Reduzca el módulo 11. (Solo hay 9 dígitos en la primera copia, por lo que esto nunca puede afectarlo).
Convierta el resultado a decimal y elimine la nueva línea nuevamente.
fuente
APL (Dyalog Unicode) ,
2624 bytesPruébalo en línea!
Función de prefijo tácito. Toma la entrada como cadena.
2 bytes guardados gracias a @ngn.
¿Cómo?
fuente
Limpio ,
10410298 bytesPruébalo en línea!
fuente
Kotlin , 83 bytes
Embellecido
Prueba
TIO
TryItOnline
fuente
Ruby ,
69 6864 bytesPruébalo en línea!
fuente
PHP, 64 bytes
Lamentablemente, en PHP
(-$c)%11
es lo mismo que-($c%11)
; así que tengo que obtener la diferencia al menos a la mayor suma posible (55 * 9 = 495 = 45 * 11) en lugar de simplemente usarla-$c%11
.o
Ejecutar como tubería
-nR
o probarlos en línea .fuente
Java 10, 110 bytes
Toma entradas y salidas como un
long
entero. Pruébelo en línea aquí .Versión sin golf:
fuente