n의 0이 아닌 마지막 자리수!


22

입력으로 1 ≤ N ≤ 1,000,000 의 정수가 주어지면, 0이 아닌 마지막 N을 출력하십시오 ! 어디 ! 계승입니다 ( 1 에서 N 까지의 모든 숫자의 곱 ). OEIS 시퀀스 A008904 입니다.

유효한 입력을 위해서는 합리적인 기계에서 10 초 이내에 프로그램을 완료해야합니다.

테스트 사례

1 => 1
2 => 2
3 => 6
4 => 4
5 => 2
6 => 2
7 => 4
8 => 2
9 => 8
10 => 8
100 => 4
1000 => 2
10000 => 8
100000 => 6
1000000 => 4

이것은 이므로 바이트 단위의 가장 짧은 코드가 이깁니다!


단일 기능 또는 완전한 프로그램?
Joey

@joey 아니요, 테스트 사례 일뿐입니다. 단일 입력, 단일 출력.
fR0DDY

@joey 완전한 프로그램.
fR0DDY

1
전체 프로그램에 대한 요구 사항은 권장되지 않습니다 ...
Outgolfer Erik

2
@EriktheOutgolfer 이것은 ~ 7 년 전의 것이므로, 당시에 결정된 것 같지 않습니다
NoOneIsHere

답변:


8

루비-63 자

f=->n{n<2?1:6*[1,1,2,6,4,4,4,8,4,6][n%10]*3**(n/5%4)*f[n/5]%10}

출처 -http : //oeis.org/A008904

f를 초당 1000 자리까지 처리합니다.

테스트

irb(main):014:0> for n in 2..6
irb(main):015:1> puts f[10**n]
irb(main):016:1> end
4
2
8
6
4

11

Mathematica, 45 36 바이트

Last@Select[IntegerDigits[#!],#>0&]&

성공적인 답변을 읽을 수 있습니다. :) (또 다시 GolfScript & Co. 제출은 없습니다.)

이것은 내 컴퓨터에서 약 5 초 안에 1,000,000 입력을 처리합니다.


1
Mathematica는이 질문에 대한 완벽한 언어입니다.
Michael Stern

4

파이썬-75

n=input()
g=1
while n:
 g*=n
 while g%10<1:g/=10
 g%=10**9
 n-=1
print g%10

3

PARI / GP-27 바이트

크기에 따라 속도가 바뀌므로 테스트 케이스에 시간이 오래 걸립니다 (~ 6 초).

n->n!/10^valuation(n!,5)%10

이 버전은 훨씬 빠르지 만 (~ 15 마이크로 초) 81 바이트가 걸립니다.

n->r=1;while(n,r*=Mod(4,10)^(n\10%2)*[1,2,6,4,2,2,4,2,8][max(n%10,1)];n\=5);lift(r)

이 (골프가 아닌) 코드를 사용하여 다음 중 하나를 테스트 할 수 있습니다.

[%(10^n) | n <- [1..6]]

2

Windows PowerShell, 53 56 59 60 63 73 90

($a=1).."$input"|%{$a="$($a*$_)".trim('0')%1e7}
$a%10

노트:

  • 100,000에 가까운 숫자의 경우 1 분 이상 걸립니다. 그러나 마지막에 0을 제거하려면 문자열로 변환해야하며 계산을 수행하려면 숫자가 필요하므로 변환은 불가피합니다.

역사:

  • 2011-02-08 10:31 (90) – 첫 번째 시도.
  • 2011-02-08 10:33 (73) – 계수는 슬라이싱 및 조인보다 짧습니다.
  • 2011-02-08 10:34 (63) – 불필요한 트림.
  • 2011-02-08 10:37 (60) – 불필요한 숫자로 캐스트되었습니다. 모듈러스는 이미 잘하고 있습니다.
  • 2011-02-08 10:40 (59) – 일부 인라인.
  • 2011-02-08 11:00 (56) – 모듈러스가 짧아지기 전에 무엇을 말했습니까? 출력에도 적용됩니다.
  • 2011-02-08 11:01 (53) – $input문자열로 캐스팅 하면 충분합니다. 캐스트 int는 내재적으로 적용됩니다.

2

펄, 53 58 61 문자

모든 공백을 제거 할 수는 있지만 "가독성"을 위해 남겨 두었습니다. 참고 : Sloane의 바보 같은 명시 적 수식을 사용하지 마십시오.

sub f {
    $_ = $1 * ++$n || 1, /(.{1,7}?)0*$/ while $n < $_[0];
    $1 % 10
}

내 컴퓨터에서 8.7 초 안에 f (10 ^ 6)를 계산합니다.

업데이트 : OP는 전체 프로그램이되기를 원했습니다.

$_ = $1 * ++$n || 1, /(.{1,7}?)0*$/ while $n < $ARGV[0];
print $1 % 10

그것은 55자를 만듭니다.


2

CJam-28

1ri{I)*_AbW%{}#A\#/1e7%}fIA%

http://cjam.aditsu.net/ 에서 최대 10000 정도의 값으로 시도 할 수 있습니다 . 더 큰 숫자의 경우 java 인터프리터를 사용해야합니다 . 1000000은 내 노트북에서 약 3 초 안에 실행됩니다.

설명:

불행히도 직접적인 해결책은 너무 느리므로 각 곱셈 후에 마지막 7 자리 (후행 0 이전) 만 유지합니다.

1           push 1 on the stack
ri          read a token and convert to integer
{           loop (for I from 0 to N - 1)
    I)      push I and increment
    *       multiply with the previous value (initially 1)
    _Ab     duplicate and convert to array of digits
    W%      reverse array
    {}#     find the position of the first non-zero digit
    A\#     raise 10 to that power
    /       divide, thus removing all trailing zeros
    1e7%    keep the remainder modulo 10000000
}fI         end for loop
A%          get the last digit

참고 : 이 언어는 질문보다 훨씬 새로운 언어입니다.



2

05AB1E , 4 바이트

!0м¤

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

설명

!0    # Push the factorial of the input and 0
  м   # Remove the occurences of 0 in the factorial
   ¤  # Push the last element, implicit display

1
마지막 테스트 사례에서 TIO 버전 시간이 초과되었습니다 (60 초). "합리적인 컴퓨터"에서 10 초 이내에 어떻게 얻었습니까?
Toby Speight

2

젤리 , 4 바이트

!Ṛȯ/

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

설명

(리스트를 역전하고 벡터화하지 않음)이 정수에 적용될 때 자동으로 D(숫자) 먼저 사용한다는 사실을 사용합니다 .

입력 8시

!Ṛȯ/
!     Factorial: 8! = 40320
 Ṛ    Reverse: [0,2,3,0,4]
   /  Reduce by...
  ȯ   ...logical OR: ((((0ȯ2)ȯ3)ȯ0)ȯ4) = first truthy element = 2

나는 1 바이트 "첫 번째 진실한 요소"가있는 것으로 생각하지 않지만 ( ȯ/있다면) 3 바이트로 단축 될 수 있습니다.


2

자바 (OpenJDK 8) , 62 바이트

n->{long f=n;for(;n>1||f%10==0;)f=n>1?f*--n:f/10;return f%10;}

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

@Kevin Cruijssen과 유사하지만 루프를 결합하여 5 바이트를 절약합니다.


PPCG에 오신 것을 환영합니다! 좋은 첫 포스트! 당신이 주위에 붙어 있기를 바랍니다!
Rɪᴋᴇʀ

PPCG에 오신 것을 환영합니다! 나는 첫 번째 게시물 인 @Riker에 동의한다. 루프를 결합하여 내 코드를 골프화했습니다. 당신은 골프 1 개 교체하여 현재의 대답 바이트 수 |||및 교체하여 추가 바이트 ==0<1. 체류를 즐길 수!
Kevin Cruijssen

2

C, 150 (140) 135 바이트

r,d;f(k,x){r=x<5?3:f(k+1,x/5);return(d=x%5)?r*"33436"[d]*(1<<d*k%4)%5:r;}main(int c,char**v){c=atoi(*++v);printf("%d",c<2?1:2*f(0,c));}

이것은 ASCII 시스템의 버전입니다. 문자열 3343611214EBCDIC 시스템 또는 \1\1\2\1\4휴대용 프로그램으로 바꿉니다.

C 솔루션은 전체 프로그램을 제공해야한다는 요구 사항에 약간 방해가됩니다. 그러나 이것은 질문에 완전히 대답합니다.

온라인으로 사용해보십시오 (Javascript 필요) :

설명

그것은 n의 최소 중요하지 않은 자릿수에 요약 된 알고리즘을 기반으로합니다 ! , 우리는 5의 최대 거듭 제곱을 찾기 위해 되풀이되어 나갈 때 계산을 수행합니다. 상수 테이블이 너무 커서 이전 잔차 r, 현재 숫자 d및 재귀 깊이 사이의 관계를 찾아서 축소했습니다 k.

     0    1       2       3    4  =d
  0  0  3×2^k  1×2^2k  3×2^3k  2
  1  1  1×2^k  2×2^2k  1×2^3k  4
r 2  2  2×2^k  4×2^2k  2×2^3k  3
  3  3  3×2^k  3×2^2k  3×2^3k  2
  4  4  4×2^k  4×2^2k  4×2^3k  1

의 경우 r>0, 이는 일정한 시간 r시간 2^dk(mod 5)으로 해결됩니다 . 상수는 a[]아래 에 있습니다 (골프 코드에 인라인되어 있음). 또한이 값 (2^4)%5이 1 임을 관찰 하여의 범위가 넘치지 않도록 지수를 줄일 수 있습니다 int.

const int a[] = { 1, 1, 2, 1, 4 };
int f(int k, int x){
    int r = x<5 ? 3 : f(k+1,x/5); /* residue - from recursing to higher-order quinary digits */
    int d = x%5;
    if (!d)
        return r;
    return r * a[d] * (1<<d*k%4) % 5;
}

int main(int c, char **v)
{
    c = atoi(*++v);
    printf("%d",
           c<2
           ? 1                  /* special-case 0 & 1 */
           : 2*f(0,c));         /* otherwise, it's 2 times r */
}

테스트 :

$ for i in 100 1000 10000 100000; do echo $i: `./694 $i`; done
100: 4
1000: 2
10000: 8
100000: 6
1000000: 4

성능도 훌륭합니다. 다음은 32 비트 시스템의 최대 입력입니다 int.

$ time ./694 2147483647
8
real    0m0.001s
user    0m0.000s
sys     0m0.000s

최대 64 비트 int에서도 동일한 타이밍을 얻었 습니다.


1
그것은 주에 관심을 가질 2147483647!이상 190 억 자리하고있다 (2^63-1)!이 계승을 계산하는 동안 큰 승리가 있으므로, 이상 170,000,000,000,000,000,000 자리. 1000000!질문에 명시된 바와 같이 현재 하드웨어에서 계산하는 것이 가능합니다. 그것은 5½ 백만 자리입니다. :-)
Toby Speight

1

PHP-105

 <?foreach(explode("\n",`cat`)as$n)if($n){$f=rtrim(gmp_strval(gmp_fact($n)),'0');echo substr($f,-1)."\n";}

주어진 테스트 케이스에서 10 초 이내에 실행됩니다.


1

파이썬 3

239 문자

~ 3.2 초 10000 을 수행 할 수 있습니다 (Ideone은 8 초 만에 차단합니다.하지만 10 초 이상 걸릴 것이라고 확신합니다 :()

from functools import *
N=100
r=range
s=(p for p in r(2,N)if all(p%n>0for n in r(2,p)))
f=lambda n,x:n//x+(n//x>0and f(n//x,x)or 0)
e=list([p,f(N,p)]for p in s)
e[0][1]-=e[2][1]
e[2][1]=0
print(reduce(lambda x,y:x*y,map(lambda x:x[0]**x[1],e))%10)

파이썬 2.6

299 자 (약간 빠름)

from itertools import *
N=100000
r=xrange
def s(c=count(2)):
        while 1:p=c.next();c=ifilter(p.__rmod__,c);yield p
f=lambda n,x:n//x+(n//x>0and f(n//x,x)or 0)
e=[[p,f(N,p)]for p in takewhile(lambda x:x<N,s())]
e[0][1]-=e[2][1]
e[2][1]=0
print(reduce(lambda x,y:x*y,map(lambda x:pow(x[0],x[1],10),e))%10)

1

하스켈, 78 자

f n=head$dropWhile(=='0')$reverse$show$product[1..n]
main=interact(show.f.read)

(아마도 10 초 안에 1,000,000!을 계산하려면 컴파일해야합니다).


두 개의 문자를 저장 foldl1하고이를 product(cf codegolf.stackexchange.com/questions/607/find-the-factorial/… )으로 바꾸십시오 . 그러나 실제로 1000000으로 시도해 보셨습니까? ?
JB

추신 : 완전한 프로그램이 아닙니다.
JB

죄송합니다, 그 의견에 명확하게하기 전에 그것을 했어. 업데이트하겠습니다.
stusmith

1

J – 42 40 자

전체 프로그램. 이 프로그램을 파일로 저장하고로 실행하십시오 jconsole script.ijs 1234. 이 프로그램은 결과를 인쇄 한 후 인터프리터를 종료하지 않습니다. 인터프리터를 종료하려면 ^D또는 exit]0을 입력 하십시오.

echo([:{:@(#~*)10&#.inv@*)/1+i.".>{:ARGV

여기에 설명이 있습니다 :

  • x #. y정수 벡터 y를 기본 x숫자 로 해석합니다 . 예를 들어 10 #. 1 2 3 4yields 1234입니다.
  • u inv동사 의 역수 를 산출합니다 u. 특히, 기본 번호 로 x #. inv y나타냅니다 . 예를 들어 yields 입니다. 통지 로서 정의된다 이고, 인가 시간 -1.yx10 #. 12341 2 3 4inv^:_1u
  • x * y는 IS 제품x그리고 y, 이와 x 10&#.inv@* y의 생성물베이스 (10) 표현을 산출 x하고 y.
  • x # y복사 N 의 번째 항목 y종종만큼 N 의 번째 항목 x; x부울로 구성된 벡터 인 경우 가져갈 x항목을 선택합니다 y. 예를 들어 1 0 1 0 # 1 2 3 4yields 1 3입니다.
  • * y부호 를 산출합니다 y.
  • x u~ y반사 입니다 . 즉와u 같습니다 y u x.
  • 따라서 y #~ * y모든 항목의 벡터 y가 양수입니다. 암묵적인 표기법에서 이것은 으로 쓸 수 있습니다 (#~ *).
  • {: y의 마지막 항목을 산출합니다 y.
  • 함께 모여서 암묵적인 문구를 얻습니다 ([:{:@(#~*)10&#.inv@*).
  • u/ y는 IS 환원y상기 이항 동사, u요소 사이에 삽입 y. 예를 들어 +/1 2 3 4like 1 + 2 + 3 + 4와 yields 10입니다.
  • 따라서이 문구 ([:{:@(#~*)10&#.inv@*)/ y는의 항목 중 곱의 마지막 숫자를 산출합니다 y.
  • ARGV 명령 행 인수로 구성된 박스형 벡터입니다.
  • ".>{:ARGV unboxed하고 숫자로 해석되는 마지막 인수입니다.
  • i. y에서 0까지의 자연수를 계산 합니다 y - 1.
  • 따라서 1+i. y에서 1까지의 자연수를 산출 합니다 y. 여기에서 >: 증가 를 사용할 수도 있지만 1+같은 문자 비용으로 더 명확합니다.
  • 전체 프로그램은 방금 동사에 마지막 명령 행 인수의 숫자로 1+i.".>{:ARGV구성된 벡터를 적용 하고을 사용하여 결과를 인쇄합니다 .1([:{:@(#~*)10&#.inv@*)/echo


1

R , 63 55 51 46 바이트

계승을 계산하고 0이 아닌 마지막 숫자를 추출합니다. 기본 구조를 제공 한 Giuseppe에게 감사드립니다.

(y=(gamma(scan()+1))%/%10^(0:1e5)%%10)[!!y][1]

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

또는 이전 51 바이트 답변 :

계승을 계산하고 문자로 변환 0한 후 모든을 제거한 다음 최종 문자를 취합니다. 주세페 덕분에 2 바이트를 절약했습니다.

substring(x<-gsub("0","",gamma(scan())+1),nchar(x))

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


1
gamma(x+1)다음보다 짧습니다factorial(x)
Giuseppe

문자열 변환없이 얻을 수있는 최선 (y=(x<-gamma(scan()+1))%/%10^(0:nchar(x))%%10)[!!y][1]은 54 바이트였습니다.
주세페

우리는 대체 할 수 @Giuseppe nchar(x)1e546 바이트의 솔루션! 잘가요
rturnbull


1

펄 6 ,  26  35 바이트

{[*](1..$_)~~/.*<(<-[0]>/}

시도 해봐


전체 프로그램으로 :

put [*](1..@*ARGS[0])~~/.*<(<-[0]>/

시도 해봐

넓히는:

{
  [*]( 1..$_ ) # reduce using &infix:« * »
  ~~           # match with
  /
    .*         # any number of values (so it matches from the end)
    <(         # only capture the following
    <-[0]>     # any value but 0 (negated character class)
  /
}

1

C (gcc) , 72 바이트 (기능)

f(n,d)long long n,d;{for(d=1;n;d%=10000)for(d*=n--;d%10<1;d/=10);d%=10;}

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

C (gcc) , 101 99 바이트 (전체 프로그램)

main(){long long n,d=1;for(scanf("%lld",&n);n;d%=10000)for(d*=n--;d%10<1;d/=10);printf("%d",d%10);}

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

이 질문은 8 살이 넘었으므로 "합리적인 기계"는 당시와 같지 않지만 모든 테스트 사례를 함께 수행 할 때 컴퓨터에서 ~ .01 초의 시간이 걸리므로 컴퓨터 속도가 향상되지 않는 한 지난 10 년 동안 1000 배 정도면 충분합니다.


무어의 법칙은 여전히 ​​유효하기 때문에 약 x16 배 더 빨라야합니다
ASCII 전용

또한, 기능은 괜찮습니다
ASCII 전용


0

첨부 , 26 바이트

Last@`\&:(All@V)@Digits@`!

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

설명

Last@`\&:(All@V)@Digits@`!

이것은 4 가지 기능으로 구성되어 있습니다.

  • `! -이것은 계승 연산자의 기능 버전입니다
  • Digits -계승의 자릿수를 얻습니다.
  • \&:(All@V)-선택 기능입니다. 이 &:함수 All@V를 (에 ) 왼쪽 결합 ( )하여 \선택합니다. 차례로 All@V숫자가 0이 아닌 경우 테스트하는 간단한 방법입니다. 입력을 벡터 0 -> [0]로 캐스팅 한 다음 모든 멤버가 진실인지 (예 : 0이 아닌지) 쿼리 하여 작동합니다 . 숫자가 0이 아닌 숫자를 나타냅니다.
  • Last -이것은 단순히이 배열의 마지막 멤버를 얻습니다.

100000 테스트 사례에서 TIO가 시간 초과 (1 분)되었습니다. 10 초 내에 어떻게 1000000 결과를 얻었습니까?
Toby Speight

@TobySpeight이 과제에 답변했을 때 해당 요구 사항이 없었습니다 (수정 내역 확인).
코너 O'Brien

아, 나는 역사를 보았어야했다! 그래도 질문의 모든 테스트 사례를 확인 했습니까?
Toby Speight

시간 제한이 질문에서 제거 된 기간 동안 답변이 혼란스러워 보였습니다. 실제로는 불행합니다.
Toby Speight

@TobySpeight 그렇습니다. 불행한 일이며 이에 관한 정책을 잘 모르겠습니다.
코너 O'Brien

0

APL (Dyalog Unicode) , 18 15 바이트

{⊢/⍵/⍨0≠⍎¨⍵}⍕∘!

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

암묵적 접두사 기능. 단일 테스트 사례의 정확한 자릿수 또는 여러 테스트 사례의 자릿수를 반환합니다.

3 바이트 씩 @ Adám과 @ErikTheOutgolfer에게 감사합니다.

방법?

{⊢/⍵/⍨0≠⍎¨⍵}⍕∘!  Main function. Argument is a number following the !.
              !  Factorial
                then
                Format (stringify)
        ⍎¨⍵}     Execute (turn to number) each digit of the argument
      0         Check if each is 0. This returns a boolean vector
                Swap arguments for the following fn/op
   ⍵/            Replicate. This takes a boolean vector as left arg and returns the truthy elements of the right arg. E.g.: 1 1 0/1 2 3  1 2.
{⊢/              Reduce. This returns the rightmost (last) element of a vector argument.

0

APL NARS, 28 바이트, 14 자

{↑≠v/v←⌽⍎¨⍕!⍵}

왜 그런지 모르겠지만 이것이 테스트를 통과했습니다.

  q←{↑≠v/v←⌽⍎¨⍕!⍵}       
  q¨1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 6 4 2 2 4 2 8 8 8 6 8 2 

0

AWK , 47 57 바이트

{for(p=$1;--$1;p=(p*$1)%1e4)while(!(p%10))p/=10;$0=p%10}1

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

원래 솔루션은 "큰"입력 값을 잘 처리하지 못했습니다. -M강제로 작동하도록 추가 할 수 는 있지만 처리 시간이 훨씬 더 걸립니다.


예, @TobySpeight inf는별로 좋지 않습니다 %. :(
Robert Benson

아 ... 내가 대답 한 질문의 버전을 보면 많은 숫자가 필요하지 않았습니다.
Robert Benson

-2

apt , 6 바이트

몇 가지 다른 6 바이트로 나왔지만 나는 이것을 가장 좋아했습니다. 그래도 5에서 할 수있는 방법이 있어야한다고 확신합니다.

Êsw ìv

시도 해봐


설명

Ê입력의 계승을 계산하고, 입력 s을 문자열로 변환 한 후 w역순으로 정수로 되돌리고 ì, 결과를 숫자 배열로 변환 v하고 첫 번째 요소를 반환합니다.


대안

Êì w æ
ÊìÈf Ì
Êì f o
Êsw sg
Êìf ìo
Êìf ìÌ

모든 테스트 사례를 실행하는 데 시간이 얼마나 걸립니까?
Toby Speight 2016 년

@TobySpeight; 링크를 따라 가면 테스트하기가 매우 쉽습니다. 계승이 JavaScript의 최대 정수보다 크면 마지막 4 개의 테스트 사례가 실패합니다.
얽히고 설킨

그렇다면 실제로 문제를 해결하지 못합니까? 문제는 그것이 1 ≤ N ≤ 1,000,000 동안 성공해야한다고 말합니다 . 다른 답변은 답을 계산하기 위해 계승을 저장할 필요가 없음을 보여줍니다.
Toby Speight 2016 년

온라인 테스트를 시도했지만 첫 번째 테스트 사례에서 시간이 초과되었습니다 (1000).
Toby Speight 2016 년

-2

Perl 5 , 36 + 10 ( -p -Mbigint) = 46 바이트

$"=$_;$_*=$"while$"-=1;($_)=/(.)0*$/

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


TIO 버전은 내가 시도한 첫 두 가지 테스트 사례 : 1000000 ⇒ f( 4 이어야 함 ) 및 100 ⇒ 7( 4 이어야 함 )
Toby Speight

int 크기가 넘칩니다. 새 버전은 bigint를 사용하여 작동합니다. 성능은 여전히 ​​무차별 대입 계산이므로 원하는 것을 남겨 둡니다. 그것은 더 큰 숫자를 위해 TIO에서 시간이 초과됨을 의미합니다.
Xcali
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.