ISBN-13 체크 숫자 계산


28

ISBN-13 코드 의 첫 12 자리 숫자가 주어진 경우 적절한 확인 숫자를 계산하고 추가하여 전체 ISBN을 계산 하는 함수를 작성 하십시오.

함수 입력은 ISBN의 처음 12 자리를 포함하는 문자열입니다. 출력은 13 자리 모두를 포함하는 문자열입니다.

공식 사양

문자열 주어진 함수 쓰기 의는 정확히 12 진수 (및 다른 문자)의 전체 구성을, 문자열 반환 t 다음 속성은 :

  • t 는 정확히 13 자리 10 진수로 구성되며 다른 문자는 포함되지 않습니다.
  • st 의 접두사 이고 ;
  • t의 홀수 위치에있는 모든 자릿수의 합계 (예 : 첫 번째, 세 번째, 다섯 번째 등)에 t의 짝수 위치에있는 모든 자릿수의 합계의 세 배 (즉, 두 번째, 네 번째, 여섯 번째 등)는 10의 배수

예 / 테스트 사례

입력
978030640615

산출
9780306406157

승리 조건

A와 도전, 짧은 대답 승리.


1
입력 및 출력에 대시 또는 숫자 만 포함되어야합니까?
sepp2k

1
설명을 업데이트했습니다. 입력 및 출력은 숫자 만입니다
Kevin Brown

전체 ISBN-13 출력도 허용됩니까?
Mr. Llama

6
질문은 실제로 자체적으로 포함되어야하므로 여기에 알고리즘에 대한 설명을 포함시키는 것이 도움이됩니다.
FlipTack 2011

나에게 위의 게시물은 테스트 예제가 좋지 않습니다 ... 마지막 10
십억이있을 것이고

답변:


14

골프 스크립트-25 자

{...+(;2%+{+}*3-~10%`+}:f

전체 프로그램 버전은 19 자입니다

...+(;2%+{+}*3-~10%

나중에 분석하려면 여기를 다시 확인하십시오. 한편 영감을 얻지 못한 나의 오래된 답변을 확인하십시오.

골프 스크립트-32 자

luhn 수 계산과 유사

{.{2+}%.(;2%{.+}%+{+}*~)10%`+}:f

978030640615에 대한 분석

{...}:f this is how you define the function in golfscript
.       store an extra copy of the input string
        '978030640615' '978030640615'
{2+}%   add 2 to each ascii digit, so '0'=>50, I can get away with this instead
        of {15&}% because we are doing mod 10 math on it later
        '978030640615' [59 57 58 50 53 50 56 54 50 56 51 55]
.       duplicate that list
        '978030640615' [59 57 58 50 53 50 56 54 50 56 51 55] [59 57 58 50 53 50 56 54 50 56 51 55]
(;      trim the first element off
        '978030640615' [59 57 58 50 53 50 56 54 50 56 51 55] [57 58 50 53 50 56 54 50 56 51 55]
2%      select every second element
        '978030640615' [59 57 58 50 53 50 56 54 50 56 51 55] [57 50 50 54 56 55]
{.+}%   double each element by adding to itself
        '978030640615' [59 57 58 50 53 50 56 54 50 56 51 55] [114 100 100 108 112 110]
+       join the two lists together
        '978030640615' [59 57 58 50 53 50 56 54 50 56 51 55 114 100 100 108 112 110]
{+}*    add up the items in the list
        '978030640615' 1293
~       bitwise not
        '978030640615' -1294
)       add one
        '978030640615' -1293            
10%     mod 10
        '978030640615' 7
`       convert to str
        '978030640615' '7'
+       join the strings
        '9780306406157'

인터프리터를 통해 코드를 실행 한 후 첫 번째 {문자와 마지막 세 문자를 제거하여 일부 문자 (32 자 Luhn 기반 솔루션)를 저장할 수 있다고 생각합니다 . }:f. 첫 번째 솔루션에 대해 동일한 작업을 수행 할 수 있는지 궁금합니다.
Rob

@ MikeDtrick, 그 문자는 GS가 함수를 정의하는 방법입니다. 19 문자 버전은 당신이 제안하는 것을 수행하지만 질문은 "기능"을 요구했습니다
gnibbler

오 알겠습니다. 설명 감사합니다.
Rob

당신은 필요하지 않습니다 :f(예, 함수는 일반적으로 그 당시 이름이 붙여졌습니다.)
Outgolfer Erik

8

파이썬-44 자

f=lambda s:s+`-sum(map(int,s+s[1::2]*2))%10`

파이썬-53 자

def f(s):d=map(int,s);return s+`-sum(d+d[1::2]*2)%10`

나는 f ( '9780306406159')가 '9780306406157'대신 '97803064061598'을 출력한다고 생각합니다.
Eelvex

@Eelvex, 입력 문자열은 항상 12 자리 여야합니다
gnibbler

아, 어떻게 든 '9'가 몰래 들어
갔습니다

7

하스켈-54 자

i s=s++show(sum[-read[c]*m|c<-s|m<-cycle[1,3]]`mod`10)

GHC ( 플래그 포함) 및 Hugs (플래그 포함)에서 지원하는 병렬 목록 이해 지원이 필요합니다 .-XParallelListComp-98


카운트에 해당 플래그를 포함시킬 필요가 없습니까? 게다가, 당신은 대체 할 수 있습니다 [1,3]에 의해 [9,7]제거합니다 -당신에게 바이트 :)를 저장하는
ბიმო

7

APL (27 자)

F←{⍵,⍕10|10-(12⍴1 3)+.×⍎¨⍵}

통역사로 Dyalog APL을 사용하고 있습니다. 다음은 주로 오른쪽에서 왼쪽으로 (함수 정의 내에서) 간단한 설명입니다 F←{ ... }.

  • ⍎¨⍵: 올바른 인수 ( )로 주어진 ¨문자 ( )를 실행 / 평가 ( )합니다 .
  • (12⍴1 3): 벡터 1 3를- 12요소 벡터 로 재구성 ( ) (갭을 채우기 위해 반복)합니다.
  • +.×: +.×왼쪽 인수 ( (12⍴1 3))와 오른쪽 인수 ( ⍎¨⍵) 의 내적 ( )을 취하십시오 .
  • 10-: 10에서 빼기.
  • 10|:로 나눈 후 나머지를 찾습니다 10.
  • : 숫자 형식을 지정합니다 (즉, 문자 표현 제공).
  • ⍵,: ,계산 된 숫자를 오른쪽 인수에 추가합니다 ( ).

6

PHP- 86 85 82 자

function c($i){for($a=$s=0;$a<12;)$s+=$i[$a]*($a++%2?3:1);return$i.(10-$s%10)%10;}

재 포맷과 설명 :

function c($i){                     // function c, $i is the input

    for($a=$s=0;$a<12;)             // for loop x12 - both $a and $s equal 0
                                    // notice there is no incrementation and
                                    // no curly braces as there is just one
                                    // command to loop through

        $s+=$i[$a]*($a++%2?3:1);    // $s (sum) is being incremented by
                                    // $ath character of $i (auto-casted to
                                    // int) multiplied by 3 or 1, depending
                                    // wheter $a is even or not (%2 results
                                    // either 1 or 0, but 0 == FALSE)
                                    // $a is incremented here, using the
                                    // post-incrementation - which means that
                                    // it is incremented, but AFTER the value
                                    // is returned

    return$i.(10-$s%10)%10;         // returns $i with the check digit
                                    // attached - first it is %'d by 10,
                                    // then the result is subtracted from
                                    // 10 and finally %'d by 10 again (which
                                    // effectively just replaces 10 with 0)
                                    // % has higher priority than -, so there
                                    // are no parentheses around $s%10
}

정확히 C # 답변에 취한 접근법. PHP는 ~ 9 자 더 효율적입니다!
Nellius

6

윈도우 PowerShell, 57

filter i{$_+(990-($_-replace'(.)(.)','+$1+3*$2'|iex))%10}

5

Haskell, 78 71 66 자

i s=s++(show$mod(2-sum(zipWith(*)(cycle[1,3])(map fromEnum s)))10)

5

루비 -73 65 자

f=->s{s+((2-(s+s.gsub(/.(.)/,'\1')*2).bytes.inject(:+))%10).to_s}

"\\1"-> '\1'?
Nemo157

@ Nemo, 고마워, 내 루비는 조금 녹슬다
gnibbler

Ruby 1.9 구문을 사용하십시오 f=->s{...}. 6 문자를 저장하십시오. 또한 s<<(...).to_s48을 추가하는 대신 쓰고을 사용하십시오 Fixnum#chr.
Hauleth

4

C # (94 자)

string I(string i){int s=0,j=0;for(;j<12;)s+=(i[j]-48)*(j++%2<1?1:3);return i+((10-s%10)%10);}

가독성을위한 줄 바꿈 / 공백 포함 :

string I(string i) 
{ 
    int s = 0, j = 0;
    for (; j < 12; )
        s += (i[j] - 48) * (j++ % 2 < 1 ? 1 : 3); 
    return i + ((10 - s % 10) % 10); 
}

선반에있는 책에서 여러 ISBN을 테스트 한 결과 제대로 작동하고 있음을 알았습니다!


4

파이썬 -91 , 89

0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|         |         |         |         |         |         |         |         |         |
 def c(i):return i+`(10-(sum(int(x)*3for x in i[1::2])+sum(int(x)for x in i[::2]))%10)%10`

공백은 첫 번째 인수와 사이에 선택 사항 for(및 in(변수 이름을 사용하지 않음) 및 제 3 호) 너무 오래가 파서에 의해 분할 할 수있는 지능형리스트입니다. -2 문자가 있습니다.
Nick T

4

펄, 53 자

sub i{$_=shift;s/(.)(.)/$s+=$1+$2*3/ge;$_.(10-$s)%10}

4

C # – 89 77 자

string I(string s){return s+(9992-s.Sum(x=>x-0)-2*s.Where((x,i)=>i%2>0).Sum(x=>x-0))%10;}

가독성을위한 형식 :

string I(string s)
{
    return s +
            (9992
            - s.Sum(x => x - 0)
            - 2 * s.Where((x, i) => i%2 > 0).Sum(x => x - 0)
            ) % 10;
}

우리는 1 또는 3을 곱하지 않고 모든 것을 추가하고 모든 짝수 문자를 한 번 더 추가하고 2를 곱합니다.

9992는 모든 ASCII 문자의 합이 그보다 작을 정도로 충분히 크므로 (10으로 수정하고 결과가 양수이고 10으로 두 번 수정할 필요가 없음) 추가하기 때문에 0으로 나눌 수 없습니다. 여분의 2 * 12 * 48 (1과 3으로 무게가 측정 된 12 개의 ASCII 숫자) == 1152. 그러나 990 대신 9992를 작성해야합니다).

그러나 다시, 훨씬 덜 아름답지만 ;-),이 구식 솔루션은 우리를 80 자로 만듭니다 (그러나 이것은 거의 C 호환입니다).

string T(string i){int s=2,j=0;for(;j<12;)s+=i[j]*(9-j++%2*2);return i+s%10;}

4

J- 55 45 38

f=:3 :'y,":10|10-10|+/(12$1 3)*"."0 y'

예 :

f '978030640615'
9780306406157

옛날 방식 :

f=:,":@(10(10&|@-)(10&|@+/@((12$1 3)*(i.12)&(".@{))))

1
(i.12)(".@{)y다음으로 대체 가능"."0 y
J Guy

3

루비-80 자

def f s;s+(10-s.bytes.zip([1,3]*6).map{|j,k|(j-48)*k}.inject(:+)%10).to_s[0];end

3

dc, 44 자

[d0r[I~3*rI~rsn++lndZ0<x]dsxx+I%Ir-I%rI*+]sI

다음과 같이 호출하십시오 lIx.

dc -e'[d0r[I~3*rI~rsn++lndZ0<x]dsxx+I%Ir-I%rI*+]sI' -e '978030640615lIxp'


2

D-97 자

auto f(string s){int n;foreach(i,c;s)n+=((i&1)*2+1)*(c-48);return s~cast(char)((10-n%10)%10+48);}

보다 간결하게 형식화 :

auto f(string s)
{
    int n;

    foreach(i, c; s)
        n += ((i & 1) * 2 + 1) * (c - 48);

    return s ~ cast(char)((10 - n % 10) % 10 + 48);
}

D의 캐스트 연산자의 세부 정보는 확실히 강박 적으로 짧은 코드를 작성하는 것을 어렵게 만듭니다.


2

자바 -161 자 :(

int b[]=new int[a.length];
int d=0,n=0,j=1;
for(char c:a.toCharArray())b[d++]=Integer.valueOf(c+"");
for(int i:b)n+=(j++%2==0)?(i*3):(i*1);
return a+(10-(n%10));

이 답변은 기능이 아니기 때문에 첫 번째 요구 사항을 충족하지 않습니다.
han

1

Q (44 자)

f:{x,string 10-mod[;10]0+/sum@'2 cut"I"$/:x}

이것은 내가 잘못 생각한 것입니다
skeevey

1

스칼라 84

def b(i:String)=i+(10-((i.sliding(2,2).map(_.toInt).map(k=>k/10+k%10*3).sum)%10)%10)

테스트 :

val isbn="978030640615"
b(isbn)

결과:

"9780306406157"

1

기음, 80 79 자

이 함수는 문자열을 제자리에 수정하지만 문제 요구 사항을 충족시키기 위해 원래 문자열 포인터를 반환합니다.

s;char*f(char*p){for(s=2;*p;s+=7**p++)s+=9**p++;*p++=48+s%10;*p=0;return p-13;}

일부 설명 : 0각 입력 문자에서 48 (숫자의 ASCII 값)을 빼는 대신 누적 s기는 10 + 48 + 3 * 48 + 48 + 3 * 48 ... + 48 + 3이되도록 초기화됩니다. * 48 = 24 * 48 = 1152. 덧셈 대신 뺄셈 10-sum으로 누적 s하여 단계 를 피할 수 있습니다 . 그러나 %C 의 모듈 연산자 는 다음과 같은 경우 유용한 결과를 제공하지 않습니다.s 는 음수 인s-= 승수 3과 1 을 사용 하는 대신 각각 -3 = 7 모듈로 10 및 -1 = 9 모듈로 10으로 바꿉니다.

테스트 하네스 :

#include <stdio.h>
#define N 12
int main()
{
     char b[N+2];
     fgets(b, N+1, stdin);
     puts(f(b));
     return 0;
}

1

그루비 75 , 66 문자

i={int i;it+(10-it.inject(0){t,c->t+(i++&1?:3)*(c as int)}%10)%10}

용도:

String z = "978030640615"
println i(z)

-> 9780306406157

1

APL (25)

{⍵,⍕10-10|+/(⍎¨⍵)×12⍴1,3}

Algo는 10으로 끝나야합니다 | 그렇지 않으면 0 대신에 10을 리턴 할 수 있기 때문에
RosLuP


1

파이썬 2 , 78 76 바이트

lambda n:n+`10-(sum(int(a)+3*int(b)for a,b in zip(n[::2],n[1::2]))%10or 10)`

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

문자열을 인수로 사용합니다.

설명:

파이썬 슬라이스 표기법을 사용하여 문자열을 문자 쌍 목록으로 변환합니다. ( "978030640615"-> [( "9", "7"), ( "8", "0"), ( "3", "0"), ( "6", "4"), ( "0 ","6 "), ("1 ","5 ")])

해당 쌍 목록에 대해 각 항목을 정수로 변환하고 a + 3b를 반환합니다.

모든 결과를 합산합니다.

나머지가 0이면 합 모듈로 10 또는 OR 10을 가져옵니다. 이렇게하면 최종 숫자가 0 대신 10이되지 않습니다.

체크 디지트를 얻기 위해 나머지 10을 제거합니다.

더 이상 사용되지 않는 백틱 표현식을 통해 계산 된 체크 숫자를 문자열로 변환합니다.

원래 숫자와 계산 된 확인 숫자를 반환합니다.

편집하다:

공백을 제거하여 2 바이트를 절약했습니다 ( Jo King 감사합니다 !).


당신은 전에 공백을 제거 할 수 foror
조 왕에게

978186197371 8이 아닌 9 ... 난에서 해당 번호를 마지막 숫자를 가지고 나에게 결과 만 내 APL 솔루션으로 인쇄 링크
RosLuP

실례합니다. 잘못된 번호를 붙여 넣은 것 같습니다.
RosLuP

1

APL (Dyalog Unicode) , 18 바이트 SBCS

문자열을 인수로 사용하는 익명의 암묵적 접두사 함수. 사용 버블의 접근을 .

⊢,∘⍕10|⍎¨+.×9 7⍴⍨≢

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

 논쟁의 길이 (12)

9 7⍴⍨ 주기적으로 [9,7]해당 길이로 모양 변경

+.× 그것의 다음의 내적 :

⍎¨ `각 캐릭터를 평가

10| 그것의 mod-10

,∘⍕ 다음의 문자열을 앞에 추가하십시오.

 수정되지 않은 논쟁


1

dc , 25 바이트

dn[A~9z^8+*rd0<M+]dsMxA%p

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

나는 이미 여기에 dc 답변이 있다는 것을 알고 있지만 25 <44이므로 19 바이트의 괜찮다고 생각합니다. 이것은 z가 짝수인지 홀수인지에 따라 mod 10 또는 mod 10 8+9^z과 같은 사실을 사용합니다 . 따라서 스택의 숫자를 숫자로 나누는 데 사용 하지만 스택을 만들 때 각 숫자에 z가 현재 스택 크기 인 위치에 곱 합니다. 그런 다음 함수 스택이 풀릴 때 모두 추가하고 마지막 숫자를 인쇄합니다.-3-1A~8+9^z


0

MATLAB-82 자

function c(i)
[i num2str(mod(10-mod(sum(str2num(i(:)).*repmat([1;3],6,1)),10),10))]

0

R, 147 자

f=function(v){s=as.numeric(strsplit(v,"")[[1]]);t=0;for(i in 1:12)if(i%%2==0)t=t+s[i]*3 else t=t+s[i];paste(v,(10-(t%%10))%%10,collapse="",sep="")}

용법:

f("978030640615")
[1] "9780306406157"

0

J, 25

,[:":10|0(-+/)"."0*1 3$~#
   f = :, [: ": 10 | 0 (-+ /)". "0 * 1 3 $ ~ #
   f '978030640615'
9780306406157
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.