Wprowadzenie
W tym wyzwaniu Twoim zadaniem jest wygenerowanie kodu ISBN-10 dla książek, biorąc pod uwagę jego kod ISBN-13, przy założeniu, że taki kod istnieje. Taki kod ISBN-13 składa się z kilku części oddzielonych -
:
978-GG-PPPP-TTT-C
Litery G
(grupa), P
(wydawca), T
(tytuł) i C
(suma kontrolna) oznaczają jedną cyfrę. Na potrzeby tego wyzwania grupowanie i obliczanie C
(patrz to wyzwanie ) nie są interesujące, a my upuszczamy wszystkie łączniki, aby uprościć to zadanie.
Numer ISBN-10 ma bardzo podobny układ:
GG-PPPP-TTT-c
Litery G
, P
i T
są takie same jak dla 13 cyfr ISBN, jednak c
różni się (i jest obliczany przy użyciu innego algorytmu). Cyfra c
jest wybierana w taki sposób, aby zachowała się następująca równoważność (cyfry w kolejności):
10*G + 9*G + 8*P + … + 3*T + 2*T + 1*c = 0 (mod 11)
Przykład
Rozważmy numer ISBN 9780345391803
: Aby uzyskać odpowiadający mu kod ISBN-10 po prostu upuścić wiodącym 978
i suma kontrolna 3
plonowanie 034539180
.
Następnie musimy obliczyć nową sumę kontrolną:
10*0 + 9*3 + 8*4 + 7*5 + 6*3 + 5*9 + 4*1 + 3*8 + 2*0 = 185
Następną liczbą podzielną przez 11
jest 187
więc nowa suma kontrolna, 2
a tym samym wynikowy kod ISBN-10 0345391802
.
Zasady
- Twój wpis zawsze będzie miał odpowiedni numer ISBN-10 (tzn. Ma dokładnie 13 cyfr i zaczyna się od
978
) - Dane wejściowe niekoniecznie muszą być poprawne ISBN-13 (np.
9780000000002
) - Masz gwarancję, że wynikowy numer ISBN się nie skończy
X
- Możesz przyjmować dane wejściowe jako liczbę całkowitą lub ciąg znaków (z łącznikami lub bez), jednak wstępnie obliczona lista cyfr jest niedozwolona
- Twój wynik musi być poprawnym numerem ISBN-10 (z łącznikami lub bez)
- Twój wynik może być liczbą całkowitą lub łańcuchem (ponownie bez list cyfr)
Przypadki testowe
9780000000002 -> 0000000000
9780201882957 -> 0201882957
9781420951301 -> 1420951300
9780452284234 -> 0452284236
9781292101767 -> 1292101768
9780345391803 -> 0345391802
Uwaga wiodące zera!
0-684-84328-5
i99921-58-10-7
pierwszej części (0
i99921
odpowiednio) jest grupa rejestracyjna, druga część to wydawca i tak dalej.Odpowiedzi:
Retina ,
443928 bajtówWypróbuj online!
Wyjaśnienie
Czas pochwalić się nowymi funkcjami Retina. :)
Dopasowujemy całe dane wejściowe
.+
, zwracamy to dopasowanieL
, ale wybieramy tylko znaki od 3 (od zera) do -2 (przedostatnie) włącznie. Drukujemy również wynik bez końcowego linefeed (>
).Odejmowanie rzeczy w Retinie jest trochę denerwujące. Ale na szczęście pracujemy modulo 11, więc możemy po prostu odwrócić współczynniki kombinacji liniowej (mod 11) i zsumować wszystko. Innymi słowy, jeśli ograniczenie jest następujące:
wtedy otrzymujemy:
To bardzo upraszcza rzeczy tutaj:
Zastępujemy każdą postać tą rzeczą na dole.
*
jest operatorem powtarzania Retiny. Jest asocjacyjnie prawy i ma ukryte operandy$&
po lewej i_
po prawej stronie, więc podstawienie jest w rzeczywistości krótkie$.>`*$&*_
.$&*_
tworzy ciąg d podkreślników, gdzie d jest cyfrą, którą obecnie zastępujemy. Następnie$.>`
jest długość ciągu do dopasowania włącznie. 1 Stąd całe wyrażenie powoduje jednoznaczne przedstawienie n- tego terminu naszej kombinacji liniowej.Wykonanie rzeczywistego modulo jest jednoznaczne: po prostu upuszczamy wszystkie komplety 11 znaków podkreślenia.
Na koniec liczymy, ile jeszcze znaków podkreślenia, i drukujemy wynik, który uzupełnia ISBN-10.
1 W jaki sposób
$.>`
podaje się długość ciągu aż do dopasowania? Możesz być zaznajomiony z$`
podstawieniami wyrażeń regularnych, które dają ci ciąg do (ale z wyłączeniem) dopasowania. Wstawiając>
możemy przesunąć kontekście$`
do separatora między bieżącym i następnym meczu (który jest pusty ciąg cyfr pomiędzy bieżącym i następnym). Separatory$`
będą obejmować bieżące dopasowanie. Więc$>`
jest krótsza droga do pisania$`$&
. Na koniec, w przypadku$x
elementów podstawienia wszystkich typów Retina pozwala wstawić znak.
po,$
aby uzyskać jego długość.źródło
-2 ≡ 9 (mod 11)
(ponieważ dodawanie lub odejmowanie 11 od liczby nie zmienia jej „wartości” w klasie 11 mod zgodności). Dodawanie i mnożenie uwzględnia klasy zgodności, dzięki czemu można zastąpić dowolną wartość w kombinacji liniowej równoważną wartością w ramach bieżącego modułu. Powodem, dla którego mówię o liczbach ujemnych, jest tak naprawdę to, że przestawiłem równanie tak, aby mieć jec
z jednej strony, a wszystkie inne terminy (jako negatywy) z drugiej.c
do stawania się,-c = ...
a nie mnożenia przez10 9 8...
odejmowanie11
od każdego z nich, aby uzyskać,-1 -2 -3...
a następnie mnożenie wszystkiego przez -1, aby uzyskaćc
.05AB1E ,
17151312 bajtówWypróbuj online!
Wyjaśnienie
źródło
PowerShell ,
9684 bajtówWypróbuj online!
Pobiera dane wejściowe
"$args"
, dokonuje wyrażenia regularnego,-replace
aby uzyskać tylko odpowiednią część, zapisuje je$x
jako ciąg. Następniechar
rzucamy to jako tablicę i przeglądamy każdą literę. Wewnątrz pętli wstępnie dekrementujemy$a
(domyślnie to0
) i mnożymy zgodnie z obliczeniem sumy kontrolnej. Uwaga rzutowania naint
, w przeciwnym razie użyłoby to wartości ASCII.Następnie
-join
łączymy te liczby razem+
i potokujemy toiex
(Invoke-Expression
i podobnie doeval
). Bierzemy to%11
i przechowujemy tę sumę kontrolną w$y
. Na koniec łączymy łańcuch$x + $y
i zostawiamy to w przygotowaniu. Wynik jest niejawny.Zaoszczędź 12 bajtów dzięki Emignie.
źródło
Oktawa ,
46 41 3937 bajtówWypróbuj online!
Kod pobiera dane wejściowe jako ciąg znaków i zwraca ciąg znaków.
Kod dzieli się w następujący sposób:
@(a)
tworzy anonimową funkcję.Dzięki
[c=a(4:12) ... ]
nam wyodrębnić znaki, które stanowią główny kod, oszczędzając jego kopięc
do późniejszego wykorzystania i dodając kolejną kopię do końcowego łańcucha wyjściowego.W oparciu o sprytny sposób zamiany @ MartinEnter
10:-1:2
na1:10
, możemy łatwo wygenerować ten zakres i przetransponować go, aby uzyskać wektor kolumny.c*(1:10)'
dokonuje mnożenia tablicowego wektora wierszac
i wektora kolumny zakresu. Jest to równoważne z mnożeniem elementarnym, a następnie sumowaniem.Suma kontrolna normalnie polegałaby
mod(11-sum,11)
na obliczeniu liczby wymaganej, aby suma była wielokrotnością 11. Jednak ponieważc
był to ciąg znaków, suma będzie faktycznie większa niż powinna być o 2592 (48 * 54), ponieważ pomnożymy przez liczby które były o 48 większe niż rzeczywista wartość.Kiedy wykonamy modulo, automatycznie pozbędzie się on wszystkich oprócz 7 z tego 2592. Jako taki, i uwzględniając negację zakresu, obliczenia stają się rzeczywiste
48+mod(7+sum,11)
. Dodajemy 48 do wyniku w celu konwersji z powrotem na znak ASCII.Znak sumy kontrolnej jest dołączany na końcu wyniku i zwracana jest wartość.
źródło
Galaretka , 12 bajtów
Jest to pełny program, który używa ciągów dla operacji we / wy.
Wypróbuj online!
Jak to działa
źródło
JavaScript (ES6),
5956 bajtówPokaż fragment kodu
-3 bajty dzięki sugestii @ Shaggy .
źródło
Perl 5 , 49 + 1 (
-p
) = 50 bajtówWypróbuj online!
źródło
Pyth , 16 bajtów
Wypróbuj tutaj!
Pyth , 17 bajtów
Wypróbuj tutaj!
Wyjaśnienie
źródło
Japt ,
1615 bajtówPrzyszedł do tego pubu innej nocy i zupełnie o tym zapomniał.
Spróbuj
źródło
s3J
iU+¬x_*°TÃuB
U
- D'oh!Sześciokąt ,
7761 bajtówWypróbuj online!
Kolorowy:
Oto większa wersja. Istnieje kilka skrzyżowań ścieżek, ale ponieważ wszystkie te komórki są
.
(brak sześciokątów), nie musisz się o nie martwić:(Próbowałem również zachować stare lustra, ale czasami muszę coś zmienić)
Wykonywane polecenie liniowe to:
Objaśnienie: Zamiast utrzymywać licznik i pomnożyć każdą cyfrę, ten program:
p
it
)(-p-t)%11
, gdzie%
zawsze zwracają pozytywne wyniki.źródło
K (oK) ,
29252423 bajtówRozwiązanie:
Wypróbuj online!
Przykłady:
Wyjaśnienie:
Ocena jest przeprowadzana od prawej do lewej.
Dwie sztuczki zaczerpnięte z innych rozwiązań:
Awaria:
Uwagi:
7
do sumy)źródło
C (gcc),
96 95 87 8685 bajtów(-1 dzięki ceilingcat)
Wypróbuj online!
Można go nazwać as
f(s)
, gdzies
jest wskaźnikiem do pierwszego elementu modyfikowalnej tablicy znaków. Modyfikuje tablicę wejściową, zwraca wskaźnik do tablicy wejściowej.źródło
Python 2 , 62 bajty
Wypróbuj online!
Pobiera ciąg jako dane wejściowe; i wyprowadza ciąg.
źródło
Galaretka , 14 bajtów
Zestaw testowy!
Galaretka , 17 bajtów
Wypróbuj online! lub pakiet testowy!
Pobiera dane wejściowe i wyjściowe jako ciąg.
źródło
ECMAScript 6 ,
8667 bajtówWypróbuj online!
Dzięki za komentarz Arnaulda , zmieniono z
reduce
namap
i pozbyłem sięreturn
słowa kluczowego.źródło
map()
,reduce()
itp z dodatkowymi przepisywanie, to często możliwe, aby pozbyć{}
ireturn
. Również w tym konkretnym przypadkumap()
jest prawdopodobnie krótszy niżreduce()
. ( Oto wersja 65-bajtowa.)f=
nie jest to konieczne. Możesz także zainicjowaćc
na rozkładówce coś takiego:a=>{i=10;s=[...c=a.substr(3,9)].reduce((g,v)=>+g+(i--)*v,0)%11;return c+=s?11-s:0}
(-4 bajty)Retina 0.8.2 ,
7251 bajtówWypróbuj online! Ponieważ jeszcze nie nauczyłem się Retina 1.0. Wyjaśnienie:
Usuń niepotrzebne znaki i zrób drugą kopię odpowiednich cyfr.
Dodawaj każdą cyfrę w drugiej kopii sufiksem. To skutecznie powtarza każdą cyfrę w sufiksie według pozycji.
Konwertuj cyfry w drugiej kopii na jednoargumentowe, dodając je razem.
Zmniejsz moduł 11. (W pierwszym egzemplarzu jest tylko 9 cyfr, więc to nigdy nie ma na to wpływu).
Przekształć wynik z powrotem na dziesiętny i ponownie usuń znak nowej linii.
źródło
APL (Dyalog Unicode) ,
2624 bajtówWypróbuj online!
Funkcja ukrytego przedrostka. Pobiera dane wejściowe jako ciąg.
2 bajty zapisane dzięki @ngn.
W jaki sposób?
źródło
Czysty ,
10410298 bajtówWypróbuj online!
źródło
Kotlin , 83 bajty
Upiększony
Test
TIO
TryItOnline
źródło
Rubin ,
69 6864 bajtówWypróbuj online!
źródło
PHP, 64 bajty
Niestety w PHP
(-$c)%11
jest taki sam jak-($c%11)
; więc muszę uzyskać różnicę do co najmniej największej możliwej kwoty (55 * 9 = 495 = 45 * 11) zamiast po prostu użyć-$c%11
.lub
Uruchom jako potok z
-nR
lub wypróbuj je online .źródło
Java 10, 110 bajtów
Pobiera dane wejściowe i wyjściowe jako
long
liczbę całkowitą. Wypróbuj online tutaj .Wersja bez golfa:
źródło