ISBN-13을 ISBN-10으로 변환


21

소개

이 과제에서는 해당 코드가 존재한다고 가정하여 ISBN-13 코드가 지정된 도서의 ISBN-10 코드를 생성해야합니다. 이러한 ISBN-13 코드는 다음과 같이 구분 된 여러 부분으로 구성됩니다 -.

978-GG-PPPP-TTT-C

문자 G(그룹), P(게시자), T(제목) 및 C(체크섬)은 모두 한 자리를 나타냅니다. 이 과제의 목적을 위해 그룹화와 계산 C( 이 과제 참조 )은 흥미롭지 않으며이 작업을 단순화하기 위해 모든 하이픈을 삭제합니다.

ISBN-10 숫자는 레이아웃이 매우 유사합니다.

GG-PPPP-TTT-c

글자 G, PT13 자릿수의 경우와 동일하다 ISBN 그러나 c상이한 (및 다른 알고리즘을 이용하여 계산된다). 숫자 c는 다음과 같은 동등성을 유지하는 방식으로 선택됩니다 (숫자 순서).

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

우리가 ISBN 번호를 생각해 보자 9780345391803: 그 해당 ISBN-10 코드는 우리가 단순히 선도 드롭 얻으려면 978및 체크섬이 3항복 034539180.

다음으로 새로운 체크섬을 계산해야합니다.

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

다음으로 나눌 수있는 숫자 11는입니다 187. 따라서 새로운 체크섬은 2결과 ISBN-10 코드 0345391802입니다.

규칙

  • 입력 한 내용은 항상 해당 ISBN-10 번호를 갖습니다 (예 : 정확히 13 자리 숫자이며로 시작 함 978)
  • 입력은 반드시 유효한 ISBN 13 일 필요는 없다 (예. 9780000000002)
  • 결과 ISBN이 끝나지 않는다는 보장 X
  • 하이픈이 있거나없는 정수 또는 문자열로 입력 할 수 있지만 사전 계산 된 숫자 목록은 허용되지 않습니다.
  • 출력은 유효한 ISBN-10 숫자 여야합니다 (하이픈 포함 또는 제외).
  • 출력은 정수 또는 문자열 일 수 있습니다 (숫자 목록 없음)

테스트 케이스

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

선행 0을 참고하십시오!


5
그것은 솔루션에 전혀 영향을 미치지 않지만 That Guy이기 때문에 ISBN의 일부 (-10 또는 -13)가 분리되는 방법에 대한 설명이 잘못되었습니다. 등록 그룹 요소는 가변 길이이며 후속 부품의 자릿수는 등록 그룹간에 그리고 등록 그룹 내에서 달라질 수 있습니다. 예를 들어, 모두 0-684-84328-599921-58-10-7, 첫 번째 부분 ( 099921각각) 번째 부분은 발행자, 등, 등록 그룹이다.
Jordan

5
10/10 샘플 ISBN 선택
Jakob

답변:


10

망막 ,  44  39 28 바이트

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

_

온라인으로 사용해보십시오!

설명

몇 가지 새로운 Retina 기능을 선보일 시간입니다. :)

>,L3,-2`.+

전체 입력을와 일치시키고 .+해당 일치를 반환 L하지만 3 (0부터 시작)부터 -2 (끝까지)까지만 선택하십시오. 또한 줄 바꿈 ( >) 없이 결과를 인쇄합니다 .

이제 Retina에서 물건을 빼는 것은 약간 성가신 일입니다. 그러나 운 좋게도 모듈로 11을 사용하고 있으므로 선형 조합의 계수를 뒤집고 모든 것을 더할 수 있습니다. 즉, 제약 조건이 다음과 같은 경우

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

우리는 얻는다 :

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

그것은 여기에 많은 것을 단순화시킵니다 :

.
$.>`**

각 캐릭터를 맨 아래에있는 것으로 바꿉니다. *Retina의 반복 연산자입니다. 오른쪽 연결이며 $&왼쪽과 _오른쪽에 암시 적 피연산자 가 있으므로 대체는 실제로 짧습니다 $.>`*$&*_. d 밑줄로 $&*_이루어진 문자열을 만듭니다. 여기서 d 는 현재 바꾸고있는 숫자입니다. 그런 다음 일치까지의 문자열 길이입니다. 1 따라서 전체 표현 은 선형 조합 의 n 번째 항을 단항으로 표현합니다 .$.>`

_{11}

실제 모듈로를 수행하는 것은 단항에서는 사소한 일입니다. 11 개의 밑줄을 모두 삭제합니다.

_

마지막으로 남은 밑줄 수를 세고 결과를 인쇄하여 ISBN-10을 완성합니다.


하나는 어떻게 $.>`와 경기를 포함하여 최대 문자열의 길이를 줄? $`정규식 대체에 익숙 할 수 있습니다 . 이는 일치하는 문자열을 제외하지만 문자열을 제공합니다. 를 삽입하여 >, 우리의 상황을 이동할 수 $`받는 세퍼레이터 (현재 자리와 다음과 빈 문자열) 현재 매치하고 다음과. 해당 구분 기호 $`에는 현재 일치 항목이 포함됩니다. 따라서 $>`쓰는 더 짧은 방법 $`$&입니다. 마지막으로 모든 $x유형 대체 요소의 경우 Retina를 사용하면 .이후 를 삽입하여 $길이를 얻을 수 있습니다.


이 모듈로 11 매직은 무엇입니까?! 그것은 4 바이트를 절약 할 것입니다 ...하지만 나는하지 않습니다!
streetster

1
@streetster 기본적으로, -2 ≡ 9 (mod 11)숫자에서 11을 더하거나 빼 더라도 일치 클래스 mod 11에서 "값"이 변경되지 않기 때문입니다. 덧셈과 곱셈은 합동 클래스를 존중하므로 선형 조합의 모든 값을 현재 모듈로에서 동등한 값으로 바꿀 수 있습니다. 내가 음수에 대해 이야기하는 이유는 실제로 방정식을 c한쪽과 다른 모든 항 (음수로)으로 재정렬 했기 때문입니다.
마틴 엔더

나는 지금 그것을 얻는다 생각한다 . 따라서 여러분 은 각각을 빼기 위해 가하는 대신 c에 점점 -c = ...가늘어 지도록 이동 한 다음 모든 것에 -1을 곱하여 얻습니다 . 10 9 8...11-1 -2 -3...c
streetster

마지막 단계가 후행 밑줄 만 바꾸는 이유를 설명해 주시겠습니까? 그 원인을 알아 내려고 잠시 시간을 보냈지 만 그것을 재현 할 수없는 것 같습니다. 이 업데이트는 정말 훌륭합니다.
FryAmTheEggman

1
@FryAmTheEggman Thanks :)이 시점에서 문자열에는 밑줄 만 포함됩니다. 우리는 이미 첫 단계에서 처음 9 자리를 인쇄했습니다.
마틴 엔더

6

05AB1E , 17 15 13 12 바이트

¦¦¦¨DSƶO11%«

온라인으로 사용해보십시오!

설명

¦¦¦            # 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 바이트

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

온라인으로 사용해보십시오!

input 을 가져 와서 "$args"정규 -replace부분을 ​​가져 와서 관련 부분 만 가져 와서 $x문자열 로 저장 합니다. 그런 다음 char-array 로 캐스팅하고 각 문자를 반복합니다. 루프 안에서 우리는 사전 감소$a (기본값은 0)하고 체크섬 계산에 따라 곱해집니다. 에 캐스트하십시오 int. 그렇지 않으면 ASCII 값을 사용합니다.

그런 다음 -join그 숫자를 함께 사용 +하여 iex( Invoke-Expression와 유사하게 eval) 파이프합니다 . 우리는 그것을 가지고 그 %11체크섬을 저장합니다$y . 마지막으로 문자열을 연결 $x + $y하고 파이프 라인에 그대로 둡니다. 출력은 암시 적입니다.

Emigna 덕분에 12 바이트를 절약했습니다.


나는 정말로 powershell을 모른다. 그러나 나는 이것 과 같은 것을 생각한다 (84)에 대해 작업 할 수 있습니다
Emigna

@Emigna 물론입니다. 모듈러스 산술과 내 뇌는 잘 재생되지 않습니다.
AdmBorkBork

5

옥타브 , 46 41 39 37 바이트

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

온라인으로 사용해보십시오!

코드는 입력을 문자열로 받아서 문자열을 반환합니다.

코드는 다음과 같이 분류됩니다.

@(a) 익명 함수를 만듭니다.

[c=a(4:12) ... ]우리에게 사본을 저장, 주요 코드를 형성하는 문자를 추출c 나중에 사용하기 위해, 최종 출력 문자열에 다른 복사본을 추가.

교환의 MartinEnter의 영리한 방법 @를 바탕 10:-1:2으로 1:10, 우리는 쉽게 그 범위를 생성하고 열 벡터를 얻을 수 조옮김 할 수 있습니다. c*(1:10)'행 벡터 c와 범위 열 벡터 의 배열 곱셈을 수행합니다 . 이는 요소 별 곱셈을 수행 한 다음 합산하는 것과 같습니다.

체크섬은 일반적으로 mod(11-sum,11)합이 11의 배수가되는 데 필요한 수 를 계산하는 것 입니다. 그러나c 문자열 합계는 실제로 숫자가 곱 해져 2592 (48 * 54)보다 커야합니다. 실제 값보다 48이 컸습니다.

모듈로를 수행하면 해당 2592 중 7 개를 제외한 모든 모듈이 자동으로 제거됩니다. 따라서 범위의 부정을 고려하면 실제 계산은 48+mod(7+sum,11) . 결과에 48을 더하여 ASCII 문자로 다시 변환합니다.

체크섬 문자가 결과 끝에 추가되고 값이 반환됩니다.


5

젤리 , 12 바이트

ṫ4ṖȮV€xJS%11

이것은 I / O에 문자열을 사용하는 전체 프로그램입니다.

온라인으로 사용해보십시오!

작동 원리

ṫ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

자바 스크립트 (ES6), 59 56 바이트

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

@Shaggy의 제안 덕분에 -3 바이트 .



1
또는 56 바이트 일 수도 있습니다.
얽히고 설킨

그렇다면 왜 숫자 배열로 입력하지 않습니까? 54 바이트
tsh


3

Pyth , 16 바이트

%s.e*ksbpP>Q3hT

여기 사용해보십시오!

Pyth , 17 바이트

%s*VsMKpP>Q3SlK11

여기 사용해보십시오!

설명

%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

헥사 고니 , 77 61 바이트

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

온라인으로 사용해보십시오!


색깔 :


여기 더 큰 버전이 있습니다. 경로 교차점이 있지만 모든 세포가. (헥사 고니에서는 작동하지 않기 때문에) 걱정할 필요가 없습니다.

(또한 오래된 거울을 유지하려고했지만 때로는 무언가를 변경해야합니다)

실행되는 선형 명령은 다음과 같습니다.

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

설명 : 카운터를 유지하고 각 숫자에 곱셈을하는 대신이 프로그램은 다음을 수행합니다.

  • "부분 합계"변수 및 "총계"변수 유지 ( pt )를 유지
  • 읽은 각 자릿수에 대해 : 부분 합계에 추가하고 부분 합계를 총계에 추가하십시오.
  • 인쇄 할 (-p-t)%11경우, %항상 긍정적 인 결과를 반환합니다.

3

K (oK) , 29 25 24 23 바이트

해결책:

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

온라인으로 사용해보십시오!

예 :

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"

설명:

평가는 오른쪽에서 왼쪽으로 수행됩니다.

다른 솔루션에서 가져온 두 가지 트릭 :

  • 10 9 8 대신 1 2 3을 곱합니다 ...
  • ASCII 값을 곱한 다음 합계에 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

노트:

  • -4 바이트 덕분에 마틴 엔더의 " 단지 계수 반전을 "마법 .
  • -1 바이트 덕분에 톰 카펜터 (추가하여 정수로 변환 할 필요가 제거 7합을)
  • -1 바이트 는 7에서 누산기를 시작합니다

3

C (gcc), 96 95 87 86 85 바이트

(천장 고양이 덕분에 -1)

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

온라인으로 사용해보십시오!

로 호출 될 f(s)경우, s변경 가능한 문자 배열의 첫 번째 요소에 대한 포인터이다. 입력 배열을 수정하고 입력 배열로 포인터를 반환합니다.




2

ECMAScript 6 , 86 67 바이트

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

온라인으로 사용해보십시오!


감사합니다 Arnauld의 코멘트 에서 전환 reducemap하고 제거있어 return키워드.


3
PPCG에 오신 것을 환영합니다! 답은 스 니펫뿐만 아니라 완전한 프로그램이거나 호출 가능한 함수 여야합니다 (이름이없는 함수일 수도 있음). JavaScript에서 가장 짧은 옵션은 일반적으로 명명되지 않은 람다라고 생각합니다.
Martin Ender

@MartinEnder 감사합니다. 답변을 수정했습니다.
Kos

3
보드에 오신 것을 환영합니다! 몇 가지 팁 : 변수 초기화가 보통의 추가 매개 변수로 넣어 수 있습니다 map(), reduce()몇 가지 추가 재 작성으로 등, 그것은 종종 제거하는 것이 가능 {}하고 return. 또한이 특정한 경우 map()에는 아마도보다 짧을 것 reduce()입니다. ( 여기서는 65 바이트 버전입니다.)
Arnauld

나는 f=필요하지 않다고 확신 합니다. 또한 c다음과 같이 스프레드에서 초기화 할 수 있습니다 . a=>{i=10;s=[...c=a.substr(3,9)].reduce((g,v)=>+g+(i--)*v,0)%11;return c+=s?11-s:0}(-4 바이트)
Asone Tuhid

2

레티 나 0.8.2 , 72 51 바이트

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

¶(1*)
$.1

온라인으로 사용해보십시오! 레티 나 1.0을 아직 배우지 않았기 때문입니다. 설명:

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

원치 않는 문자를 삭제하고 적절한 숫자의 두 번째 사본을 만드십시오.

r`.\G
$&$'

두 번째 사본의 각 숫자에 접미사를 붙입니다. 이렇게하면 접미사의 각 숫자가 해당 위치에 따라 효과적으로 반복됩니다.

r`.\G
$*

두 번째 사본의 숫자를 단항으로 변환하여 함께 추가하십시오.

1{11}

모듈로 11을 줄입니다. (첫 번째 사본에는 9 자리 만 있으므로 영향을 미치지 않습니다.)

¶(1*)
$.1

결과를 다시 10 진수로 변환하고 개행을 다시 제거하십시오.


2

APL (Dyalog Unicode) , 26 24 바이트

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

온라인으로 사용해보십시오!

암묵적 접두사 기능. 입력을 문자열로받습니다.

@ngn 덕분에 2 바이트가 절약되었습니다.

방법?

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

코 틀린 , 83 바이트

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() % 11)) % 11
}

테스트

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 바이트

불행히도 PHP (-$c)%11에서와 동일합니다 -($c%11); 그래서 나는 단지을 사용하는 대신 가능한 가장 큰 합계 (55 * 9 = 495 = 45 * 11)와 차이를 얻어야합니다 -$c%11.

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

또는

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

파이프로 실행 -nR하거나 온라인으로 사용해보십시오 .


0

자바 10, 110 바이트

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

입력 및 출력을 long정수 로 취합니다 . 여기에서 온라인으로 사용해보십시오 .

언 골프 버전 :

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
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.