Codegolf — Преобразование Isbn-13 В Isbn-10

  • Автор темы WW_
  • Обновлено
  • 23, Oct 2024
  • #1

Введение

В этом задании ваша задача — сгенерировать код ISBN-10 для книг с учетом их кода ISBN-13, предполагая, что такой код существует. Такой код ISBN-13 состоит из нескольких частей, разделенных

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

X

Буквы 9780000000002 (group), 978 (издатель), 0345391802 (title) and 2 (контрольная сумма) все обозначают одну цифру. Для целей этой задачи группировка и вычисление 187 (see этот вызов) не интересны, и мы опустим все дефисы, чтобы упростить задачу.

Номер ISBN-10 имеет очень похожую структуру:

11

Буквы 10*0 + 9*3 + 8*4 + 7*5 + 6*3 + 5*9 + 4*1 + 3*8 + 2*0 = 185 , 034539180 и 3 are the same as for the 13 digits ISBN, however 978 отличается (и вычисляется с использованием другого алгоритма). цифра 9780345391803 is chosen in a way such that the following equivalence holds (digits in order):

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

Пример

Давайте рассмотрим номер ISBN c : To get its corresponding ISBN-10 code we simply drop the leading c и контрольная сумма T yielding P .

Далее нам нужно вычислить новую контрольную сумму:

G

Следующее число, которое делится на GG-PPPP-TTT-c is C , поэтому новая контрольная сумма C and thus the resulting ISBN-10 code T .

Правила

  • Ваш ввод всегда будет иметь соответствующий номер ISBN-10 (т. е. он имеет длину ровно 13 цифр и начинается с P )
  • Ввод не обязательно должен быть действительным ISBN-13 (например. G )
  • Вам гарантировано, что полученный ISBN не будет заканчиваться на 978-GG-PPPP-TTT-C
  • Вы можете принимать входные данные в виде целого числа или строки (с дефисами или без них), однако заранее вычисленный список цифр не допускается.
  • Ваш вывод должен быть действительным номером ISBN-10 (с дефисами или без них).
  • Ваш вывод может быть целым числом или строкой (опять же без списков цифр).

Тестовые случаи

-

Обратите внимание на ведущие нули!

#код-гольф #математика #контрольная сумма

WW_


Рег
10 Apr, 2006

Тем
67

Постов
194

Баллов
579
  • 26, Oct 2024
  • #2

Сетчатка, 44 39 28 байт

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 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
}
 

Попробуйте онлайн!

Объяснение

Пришло время продемонстрировать некоторые новые функции Retina. :)

long

Мы сопоставляем весь ввод с 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);} , return that match -nR , но выберите только символы от 3 (начинается с нуля) до -2 (предпоследний) включительно. Мы также печатаем результат без конечного перевода строки ( for($c=45*$f=11;--$f>1;print$d)$c-=$f*$d=$argn[13-$f];echo$c; ).

Теперь вычитание вещей в Retina немного раздражает. Но, к счастью, мы работаем по модулю 11, поэтому можем просто инвертировать коэффициенты линейной комбинации (по модулю 11) и все сложить. Другими словами, если ограничение:

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

тогда мы получим:

-$c

Здесь это сильно упрощает ситуацию:

-($c)

Мы заменяем каждый символ тем, что внизу. (-$c) is Retina's repetition operator. It's right-associative and it has implicit operands ->n{v=n[3,9];c=11;v+"#{(c-v.chars.map{|i|i.to_i*c-=1}.sum)}"} слева и 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()))} 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") } } on the right, so the substitution is actually short for i.drop(3).dropLast(1).let { it + (11 - (it.mapIndexed { i, c -> (10 - i) * (c - '0') }.sum() % 11)) % 11 } . i.drop(3).dropLast(1).let{it+(11-(it.mapIndexed{i,c->(10-i)*(c-'0')}.sum()))} creates a string of д подчеркивает, где д это цифра, которую мы сейчас заменяем. Затем import StdEnv $s#s=s%(3,11) #i=sum[digitToInt d*p\\d<-s&p<-[10,9..]]+10 =s++[toChar(i/11*11-i+58)] is the length of the string up to and including the match.1 Следовательно, все выражение приводит к унарному представлению н-й член нашей линейной комбинации.

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

Выполнение фактического модуля в унарном виде тривиально: мы просто отбрасываем все полные наборы из 11 символов подчеркивания.

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

Наконец, мы подсчитываем, сколько символов подчеркивания осталось, и печатаем результат, который завершает ISBN-10.


1 Как ¶(1*) $.1 give the length of the string up to and including the match? You might be familiar with 1{11} в заменах регулярных выражений, что дает вам строку до совпадения (но исключая его). Вставив r`.\G $* , we can shift the context of the r`.\G $&$' к сепаратор между текущим совпадением и следующим (это пустая строка между текущей цифрой и следующей). Этот разделитель ...(.*). $1¶$1 will include the current match. So ...(.*). $1¶$1 r`.\G $&$' r`.\G $* 1{11} ¶(1*) $.1 это более короткий способ записи return . Finally, for all map -типа элементов замены, Retina позволяет вставлять reduce after the a=>(c=a.substr(3,9))+([...c].map(v=>g+=--i*v,e=i=g=11)?(e-g%e)%e:0) чтобы получить его длину.

 

Ultra-D


Рег
25 Nov, 2012

Тем
75

Постов
166

Баллов
571
  • 26, Oct 2024
  • #3

05AB1E, 17 15 13 12 байт

Ṛḣ⁵µVD×JḊSN;ḊṚ

Попробуйте онлайн!

Объяснение

ṫ4ṖµV€×JS;@ ||answer||

PowerShell, 96 84 байт

lambda n:n[3:12]+`-sum(i*int(n[13-i])for i in range(2,11))`

Попробуйте онлайн!

Принимает ввод s , does a regex f(s) чтобы получить только соответствующую часть, сохраняет ее в *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;s=r;} as a string. Then we cast that as a 7 -массив и цикл по каждой букве. Внутри цикла мы предварительно уменьшаем 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 (which defaults to 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" ) и умножить в соответствии с расчетом контрольной суммы. Обратите внимание на актерский состав x,$11!7+/(1+!9)*x:-1_3_ , else this would use ASCII values.

Мы тогда % those numbers together with (-p-t) и передать это по каналу t ( p и похоже на ,,,,'48}} , while memory > 0: ';"-'"{+'+{=A&=''A if memory < 0: undefined behavior &{{&} , '"''+~'11='%!@ ). We take that and store that checksum into . . Наконец, мы объединяем строки ,,,,'~'11=\.A&.=\./';"-'"{4.8}}\'.A.>.,<\'+'%!@}/=+'+{./&{{&/ , and leave that on the pipeline. Output is implicit.

Сэкономлено 12 байт благодаря Emigna.

 

Planar15


Рег
13 Nov, 2019

Тем
70

Постов
184

Баллов
554
  • 26, Oct 2024
  • #4

Октава, 46 41 39 37 байт

s3J U+¬x_*°TÃuB

Попробуйте онлайн!

Код принимает входные данные в виде строки и возвращает строку.

Код разбивается следующим образом:

%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. creates an anonymous function.

С %s*VsMKpP>Q3SlK11 we extract the characters that form the main code, saving a copy to %s.e*ksbpP>Q3hT для дальнейшего использования и добавления еще одной копии в окончательную выходную строку.

На основе умного способа обмена @MartinEnter. s/^...|.$//g;$\=(eval s/./"-$&0+".$i++*$&/ger) into -p , мы можем легко сгенерировать этот диапазон и транспонировать его, чтобы получить вектор-столбец. f= s=>(s=s.slice(3,-1))+[...s].reduce(n=>n+s[i++]*i,i=0) //s=>(s=s.slice(3,-1))+(n=0,[...s].map((c,i)=>n+=c*-~i),n) //s=>(s=s.slice(3,-1))+(n=0,[...s].map(c=>n+=c*i++,i=1),n) //s=>(n=0,[...(s=s.slice(3,-1))].map((c,i)=>n+=c*-~i),s+n) //s=>(s=s.slice(3,-1,n=i=0))+eval(`for(c of s)n+=c*-~i++`) console.log(...[ '9780000000002', '9780201882957', '9781420951301', '9780452284234', '9781292101767', '9780345391803' ].map(f)) does array multiplication of the row vector s=>(s=s.slice(3,-1))+[...s].reduce(n=>n+s[i++]*i,i=0) и вектор-столбец диапазона. Это эквивалентно поэлементному умножению и затем суммированию.

Контрольная сумма обычно равна ṫ4ṖȮV€xJS 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 Take the sum, modulo 11. (implicit) Print the checksum to STDOUT. to calculate the number required for the sum to be a multiple of 11. However, because ṫ4ṖȮV€xJS была символьной строкой, сумма на самом деле будет больше, чем должна быть, на 2592 (48*54), поскольку мы умножили на числа, которые на 48 больше фактического значения.

Когда мы выполняем по модулю, он автоматически избавится от всего, кроме 7, из этих 2592. Таким образом, с учетом отрицания диапазона, фактический расчет становится 48+mod(7+sum,11) . We add on 48 to the result to convert back to an ASCII character.

Символ контрольной суммы добавляется в конец результата и возвращается значение.

 

Антинка1211


Рег
05 Jul, 2013

Тем
66

Постов
207

Баллов
577
  • 26, Oct 2024
  • #7

АлёнаXXX


Рег
26 Sep, 2007

Тем
72

Постов
203

Баллов
603
  • 26, Oct 2024
  • #8

шестиугольник, 77 61 байт

$x + $y

Попробуйте онлайн!


Цветной:


Вот увеличенная версия. Есть некоторые пересечения путей, но поскольку все эти ячейки $y (no-op in Hexagony), you don't need to worry about them:

(старые зеркала я тоже старался сохранить, но иногда нужно что-то менять)

Выполняемая линейная команда:

eval

Пояснение: Вместо того, чтобы вести счетчик и умножать каждую цифру, эта программа:

  • сохраните переменную «частичная сумма» и переменную «общая сумма» ( Invoke-Expression and iex )
  • для каждой прочитанной цифры: добавьте ее к частичной сумме и добавьте частичную сумму к общей сумме.
  • распечатать + , where -join всегда возвращайте положительные результаты.
 

Mimu


Рег
12 Apr, 2006

Тем
70

Постов
182

Баллов
542
  • 26, Oct 2024
  • #9

К (ОК), 29 25 24 23 байта

Решение:

int

Попробуйте онлайн!

Примеры:

0

Объяснение:

Оценка производится справа налево.

Два трюка, взятые из других решений:

  • умножьте на 1 2 3... вместо 10 9 8...
  • умножьте значения ASCII, а затем добавьте 7 к сумме, чтобы сбалансировать

Авария:

$a

Примечания:

  • -4 байта благодаря Мартин Эндерс "просто инвертируйте коэффициенты"волшебство.
  • -1 байт благодаря Том Карпентер для устранения необходимости преобразования в целые числа (путем добавления char to the sum)
  • -1 байт запустить аккумулятор на 7
 

Jekajuk3


Рег
19 Nov, 2019

Тем
62

Постов
180

Баллов
530
  • 26, Oct 2024
  • #10

С (ГЦК), 96 95 87 86 85 байт

(-1 спасибо потолочному коту)

$x

Попробуйте онлайн!

Чтобы называться как -replace , where "$args" — указатель на первый элемент модифицируемого массива символов. Изменяет входной массив, возвращает указатель на входной массив.

 

JktuBdfyjdbx


Рег
20 Oct, 2011

Тем
85

Постов
191

Баллов
646
  • 26, Oct 2024
  • #12

Kamyshev1985


Рег
30 Nov, 2019

Тем
73

Постов
210

Баллов
615
  • 26, Oct 2024
  • #14

Ретина 0.8.2, 72 51 байт

$>`

Попробуйте онлайн! Потому что я еще не освоил Retina 1.0. Объяснение:

$`

Удалите ненужные символы и сделайте вторую копию соответствующих цифр.

$`

Закрепите каждую цифру во втором экземпляре ее суффиксом. Это эффективно повторяет каждую цифру в суффиксе по ее позиции.

>

Преобразуйте цифры во второй копии в унарные, сложив их.

$`

Уменьшите по модулю 11. (В первом экземпляре всего 9 цифр, поэтому на него это никак не повлияет.)

$.>`

Преобразуйте результат обратно в десятичный формат и снова удалите новую строку.

 

SerGooo


Рег
26 Jun, 2017

Тем
76

Постов
185

Баллов
575
  • 26, Oct 2024
  • #15

Dark_foundryman


Рег
21 Nov, 2012

Тем
75

Постов
198

Баллов
593
  • 26, Oct 2024
  • #18

PHP, 64 байта

К сожалению, в PHP * is the same as . $.>`** ; поэтому мне нужно получить разницу хотя бы до максимально возможной суммы (55*9 = 495 = 45*11), а не просто использовать c = 1*G + 2*G + 3*P + … + 8*T + 9*T (mod 11) .

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

или

>

Запустить как трубу с L or попробуйте их онлайн.

 

Readoc


Рег
23 May, 2010

Тем
59

Постов
202

Баллов
517
  • 26, Oct 2024
  • #19

Java 10, 110 байт

.+

Принимает входные и выходные данные как >,L3,-2`.+ integer. Try it online здесь.

Негольфированная версия:

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

Vlpasha


Рег
07 Jun, 2010

Тем
68

Постов
177

Баллов
547
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно