문제

퍼즐

고등학교 때 들었던 작은 퍼즐은 다음과 같았습니다 ...

  • 질문자는 나에게 번호를 알려달라고 요청했습니다.
  • 그 숫자를 들으면서 질문자는 그 숫자에 대해 반복적으로 일종의 변형을 가할 것입니다(예를 들어, 그는 다음과 같이 말할 수 있습니다). 10은 3이다) 결국 4번에 도달할 때까지(그 시점에서 그는 4번은 마법이야).
  • 어떤 숫자든 결국에는 무슨 일이 있어도 4로 변형될 수 있는 것 같습니다.

목표는 변환 함수를 파악한 다음 이 퍼즐을 스스로 안정적으로 감독할 수 있도록 하는 것이었습니다.

해결책

모든 단계의 변환 기능은 다음과 같습니다.

  • 문제의 번호를 받아,
  • 하이픈, 공백 또는 "and"를 무시하고 영어 단어 표현의 문자 수를 셉니다. 20개의 글자가 있습니다.)
  • 해당 문자 수를 반환합니다.

내가 테스트하려고 노력한 모든 숫자에 대해 이는 4로 수렴됩니다."4"에도 4개의 문자가 포함되어 있으므로 여기서는 무한 루프가 발생합니다.대신에 단지 다음과 같이 불린다. 마법 관례적으로 시퀀스를 종료합니다.

도전

귀하의 과제는 사용자로부터 숫자를 읽은 다음 "4 is Magic"에 도달할 때까지 반복적으로 적용되는 변환 함수를 보여주는 줄을 인쇄하는 코드 조각을 만드는 것입니다.

구체적으로:

  1. 솔루션은 그 자체로 완전한 프로그램이어야 합니다.이는 단지 숫자, 즉 입력 요소를 취하는 함수일 수는 없습니다.
  2. 입력은 표준 입력에서 읽어야 합니다.("echo"에서 파이핑하거나 입력 리디렉션을 사용하는 것은 표준 입력에서도 사용되므로 괜찮습니다)
  3. 입력은 숫자 형식이어야 합니다.
  4. 변환 함수를 적용할 때마다 다음 줄이 인쇄되어야 합니다. a is b., 여기서 a와 b는 변환에 포함된 숫자의 숫자 형태입니다.
  5. 마침표(마침표)가 필요합니다!
  6. 마지막 줄은 자연스럽게 다음과 같이 말해야 합니다. 4 is magic..
  7. 코드는 다음의 모든 숫자에 대해 올바른 출력을 생성해야 합니다. 0~99.

예:

> 4
4 is magic.

> 12
12 is 6.
6 is 3.
3 is 5.
5 is 4.
4 is magic.

> 42
42 is 8.
8 is 5.
5 is 4.
4 is magic.

> 0
0 is 4.
4 is magic.

> 99
99 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

승자는 소스 코드 문자 수를 기준으로 최단 제출 그것도 옳은.

보너스

변환 함수를 적용할 때마다 숫자의 영어 이름을 인쇄하는 코드 버전을 작성해 볼 수도 있습니다.원래 입력은 여전히 ​​숫자이지만 출력 라인은 숫자의 단어 형식을 가져야 합니다.

(코드로 모양을 그리면 두 배의 보너스)

(편집하다) 몇 가지 설명:

  1. 나는 적용 가능한 모든 경우에 단어가 양쪽에 나타나기를 원합니다. Nine is four. Four is magic.
  2. 하지만 대문자 사용에는 관심이 없습니다.그리고 단어 토큰을 어떻게 분리하는지 상관하지 않습니다. 하지만 토큰은 분리되어야 합니다. ninety-nine 괜찮다, ninety nine 괜찮다, ninetynine 안 괜찮아요.

나는 이것을 챌린지와 관련된 보너스 경쟁을 위한 별도의 카테고리로 간주하므로 이를 선택하는 경우 코드가 숫자 버전보다 길어지는 것에 대해 걱정하지 마십시오.

각 버전마다 하나의 솔루션을 제출해 주시기 바랍니다.

도움이 되었습니까?

해결책

골프스크립트 - 101 96 93 92 91 90 94 86바이트

90 → 94:10의 배수에 대한 고정 출력입니다.
94 → 86:재구성된 코드.인쇄할 수 없는 문자를 제거하려면 기본 100을 사용합니다.
86 → 85:문자열로의 캐스트가 더 짧습니다.

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."

다른 팁

Perl, 약 147자

Platinum Azure의 솔루션을 대략적으로 기반으로 함:

               chop
              ($_.=
              <>);@
             u="433
            5443554
           366  887
          798   866
         555    766
        "=~     /\d
       /gx      ;#4
      sub       r{4
     -$_        ?$_
    <20         ?$u
   [$_          ]:(
  $'?           $u[
 $']            :0)
+$u[18+$&]:magic}print"
$_ is ",$_=r(),'.'while
                /\d
                /x;
                444

커먼 리스프 157자

보다 적합한 새 버전으로 이제 표준 입력 형식을 읽고 공백과 하이픈을 무시합니다.

(labels((g (x)(if(= x 4)(princ"4 is magic.")(let((n(length(remove-if(lambda(x)(find x" -"))(format nil"~r"x)))))(format t"~a is ~a.~%"x n)(g n)))))(g(read)))

사람이 읽을 수 있는 형식:

 (labels ((g (x)
           (if (= x 4)
            (princ "4 is magic.")
            (let ((n (length (remove-if (lambda(x) (find x " -"))
                                        (format nil "~r" x)))))
               (format t"~a is ~a.~%" x n)
               (g n)))))
    (g (read)))

그리고 몇 가지 테스트를 실행합니다.

>24
24 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

>23152436
23152436 is 64.
64 is 9.
9 is 4.
4 is magic.

보너스 버전은 165자입니다.

 (labels((g(x)(if(= x 4)(princ"four is magic.")(let*((f(format nil"~r"x))(n(length(remove-if(lambda(x)(find x" -"))f))))(format t"~a is ~r.~%"f n)(g n)))))(g(read)))

기부

>24
twenty-four is ten.
ten is three.
three is five.
five is four.
four is magic.

>234235
two hundred thirty-four thousand two hundred thirty-five is forty-eight.
forty-eight is ten.
ten is three.
three is five.
five is four.
four is magic.

파이썬 2.x, 144 150 154 166 문자

숫자를 10과 1로 분리하여 합산합니다.의사 삼항 연산자의 바람직하지 않은 속성 a and b or c 저것 c 다음과 같은 경우 반환됩니다. b 여기서는 0이 남용되고 있습니다.

n=input()
x=0x4d2d0f47815890bd2
while n-4:p=n<20and x/10**n%10or 44378/4**(n/10-2)%4+x/10**(n%10)%10+4;print n,"is %d."%p;n=p
print"4 is magic."

이전 단순 버전(150자).모든 길이를 정수로 인코딩하면 됩니다.

n=input()
while n-4:p=3+int('1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29',36)/10**n%10;print n,"is %d."%p;n=p
print"4 is magic."

C - 숫자 단어 포함

445 431 427 421 399 386 371 359* 356 354 348 347자

그게 다야.더 이상 짧게 만들 수는 없을 것 같아요.

모든 줄 바꿈은 가독성을 위한 것이며 제거할 수 있습니다.

i;P(x){char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,
fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,
4RmagicS,zero,";while(x--)if(*++p-44&&!x++)*p>95|*p<48?putchar(*p),++i:P(*p-48);
}main(c){for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))P(c?c>19?P(c/10+18),
(c%=10)&&putchar(45):0,c:37);P(36);}

아래에서는 다소 축소되지 않았지만 여전히 읽기가 꽤 어렵습니다.더 읽기 쉬운 버전은 아래를 참조하세요.

i;
P(x){
    char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,";
    while(x--)
        if(*++p-44&&!x++)
            *p>95|*p<48?putchar(*p),++i:P(*p-48);
}
main(c){
    for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))
        P(c?
            c>19?
                P(c/10+18),
                (c%=10)&&
                    putchar(45)
            :0,
            c
        :37);
    P(36);
}

확장 및 댓글 달기:

int count; /* type int is assumed in the minified version */

void print(int index){ /* the minified version assumes a return type of int, but it's ignored */
    /* see explanation of this string after code */
    char *word =
        /* 1 - 9 */
        ",one,two,three,four,five,six,sM,eight,nine,"
        /* 10 - 19 */
        "tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,"
        /* 20 - 90, by tens */
        "twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,"
        /* lookup table */
        "en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,";

    while(index >= 0){
        if(*word == ',')
            index--;
        else if(index == 0) /* we found the right word */
            if(*word >= '0' && *word < 'a') /* a compression marker */
                print(*word - '0'/*convert to a number*/);
            else{
                putchar(*word); /* write the letter to the output */
                ++count;
            }
        ++word;
    }
}
int main(int argc, char **argv){ /* see note about this after code */
    scanf("%d", &argc); /* parse user input to an integer */

    while(argc != 4){
        count = 0;
        if(argc == 0)
            print(37/*index of "zero"*/);
        else{
            if(argc > 19){
                print(argc / 10/*high digit*/ + 20/*offset of "twenty"*/ - 2/*20 / 10*/);
                argc %= 10; /* get low digit */

                if(argc != 0) /* we need a hyphen before the low digit */
                    putchar('-');
            }
            print(argc/* if 0, then nothing is printed or counted */);
        }
        argc = count;
        print(34/*" is "*/);
        print(argc); /* print count as word */
        print(35/*".\n"*/);
    }
    print(36/*"four is magic.\n"*/);
}

시작 부분 근처의 인코딩된 문자열 정보

숫자의 이름은 매우 간단한 구성표를 사용하여 압축됩니다.자주 사용되는 하위 문자열은 이름 배열의 한 문자 인덱스로 대체됩니다.추가 이름 항목의 "조회 테이블"은 첫 번째 세트에서 전체적으로 사용되지 않은 하위 문자열의 끝에 추가됩니다.조회는 재귀적입니다.항목은 다른 항목을 참조할 수 있습니다.

예를 들어 11의 압축된 이름은 다음과 같습니다. elM.그만큼 print() 함수는 문자를 출력합니다 e 그리고 l (숫자 '1'이 아닌 소문자 'L') 그대로, 그러나 다음을 찾습니다. M, 따라서 조회 테이블의 29번째 항목(ASCII 'M' - ASCII '0') 인덱스를 사용하여 자신을 호출합니다.이 문자열은 evL, 그래서 출력됩니다 e 그리고 v, 그런 다음 조회 테이블의 28번째 항목 인덱스를 사용하여 자신을 다시 호출합니다. en, 그대로 출력됩니다.이것은 유용합니다. en 에서도 사용됩니다 eL ~을 위한 een (이후에 사용됨 eight ~에 eighteen)에서 사용되는 tO ~을 위한 teen (다른 모든 용도로 사용됨 -teen 이름).

이 방식을 사용하면 숫자 이름이 상당히 압축되는 반면 압축을 푸는 데는 적은 양의 코드만 필요합니다.

문자열의 시작과 끝 부분에 있는 쉼표는 이 문자열 내에서 하위 문자열을 찾는 단순한 방식을 설명합니다.여기에 두 문자를 추가하면 나중에 더 많은 문자를 저장할 수 있습니다.

학대에 대해 main()

argv 무시되고(따라서 압축 버전에서 선언되지 않음) argc의 값은 무시되지만 저장소는 현재 숫자를 유지하기 위해 재사용됩니다.이렇게 하면 추가 변수를 선언할 필요가 없어집니다.

부족하다는 점에 대해 #include

어떤 사람들은 생략했다고 불평할 것이다. #include <stdio.h> 부정 행위입니다.전혀 그렇지 않습니다.주어진 것은 내가 아는 모든 C 컴파일러에서 (경고가 있기는 하지만) 올바르게 컴파일되는 완전히 합법적인 C 프로그램입니다.stdio 함수에 대한 프로토타입이 부족하면 컴파일러는 해당 함수가 반환하는 cdecl 함수라고 가정합니다. int, 전달해야 할 인수를 알고 있다고 믿습니다.어쨌든 이 프로그램에서는 반환 값이 무시되며 모두 cdecl("C" 호출 규칙) 함수이므로 전달해야 할 인수가 무엇인지 실제로 알고 있습니다.

산출

출력은 예상대로입니다.

0
zero is four.
four is magic.
1
one is three.
three is five.
five is four.
four is magic.
4
four is magic.
20
twenty is six.
six is three.
three is five.
five is four.
four is magic.
21
twenty-one is nine.
nine is four.
four is magic.

* 이전 버전에서는 사양의 두 부분에 대한 표시가 누락되었습니다.0을 처리하지 않았고 stdin 대신 명령줄에서 입력을 받았습니다.0으로 추가된 문자를 처리하지만 명령줄 인수 대신 stdin을 사용하고 몇 가지 다른 최적화를 통해 동일한 수의 문자를 저장하여 결과적으로 세척되었습니다.

숫자 단어가 " is "의 양쪽에 인쇄되어야 함을 명확하게 하기 위해 요구 사항이 변경되었습니다.이 새 버전은 해당 요구 사항을 충족하고 필요한 추가 크기를 고려하여 몇 가지 추가 최적화를 구현합니다.

제이, 107 112 문자

'4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.
(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:

(가독성을 위한 줄바꿈)

사용법 및 출력:

    '4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:12
12 is 6.    
6 is 3.     
3 is 5.     
5 is 4.     
4 is magic. 

T-SQL, 413 451 499 문자

CREATE FUNCTION d(@N int) RETURNS int AS BEGIN
Declare @l char(50), @s char(50)
Select @l='0066555766',@s='03354435543668877987'
if @N<20 return 0+substring(@s,@N+1,1) return 0+substring(@l,(@N/10)+1,1) + 0+(substring(@s,@N%10+1,1))END
GO
CREATE proc M(@x int) as BEGIN
WITH r(p,n)AS(SELECT p=@x,n=dbo.d(@x) UNION ALL SELECT p=n,n=dbo.d(n) FROM r where n<>4)Select p,'is',n,'.' from r print '4 is magic.'END

(진지하게 그렇게 하라고 제안하는 건 아닙니다...사실 저는 그냥 CTE를 작성하고 싶었어요)

사용:

M 95

보고

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.

Java(상용구 포함), 308 290 286 282 280자

class A{public static void main(String[]a){int i=4,j=0;for(;;)System.out.printf("%d is %s.%n",i=i==4?new java.util.Scanner(System.in).nextInt():j,i!=4?j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:"magic");}}

나는 Groovy가 그 중 많은 부분을 제거할 것이라고 확신합니다.

설명 및 형식화 (모든 주석, 개행 및 선행/후행 공백이 개수에서 제거됨):

상당히 직설적이지만

//boilerplate
class A{
   public static void main(String[]a){
      //i is current/left number, j right/next number.  i=4 signals to start
      //by reading input
      int i=4,j=0;
      for(;;)
         //print in the form "<left> is <right>."
         System.out.printf(
            "%d is %s.%n",
            i=i==4?
               //<left>: if i is 4 <left> will be a new starting number
               new java.util.Scanner(System.in).nextInt():
               //otherwise it's the next val
               j,
            i!=4?
               //use string to map number to its length (:;< come after 9 in ASCII)
               //48 is value of '0'.  store in j for next iteration
               j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:
               //i==4 is special case for right; print "magic"
               "magic");
   }
}

편집하다:더 이상 16진수를 사용하지 않습니다. 키 입력 횟수가 줄어듭니다.

윈도우 파워셸:152 153 184 바이트

이전 솔루션을 기반으로 하며 다른 솔루션의 영향을 더 많이 받음

$o="03354435543668877988"
for($input|sv b;($a=$b)-4){if(!($b=$o[$a])){$b=$o[$a%10]-48+"66555766"[($a-$a%10)/10-2]}$b-=48-4*!$a
"$a is $b."}'4 is magic.'

C, 158자

main(n,c){char*d="03354435543668877988";for(scanf("%d",&n);n-4;n=c)printf("%d is %d.\n",n,c=n?n<19?d[n]-48:d[n%10]-"_,**+++)**"[n/10]:4);puts("4 is magic.");}

(원래 Vlad의 Python 코드를 기반으로 하며 Tom Sirgedas의 C++ 솔루션에서 몇 가지 문자를 더 짜내는 트릭을 빌렸습니다.)

확장 버전:

main(n, c) {
    char *d = "03354435543668877988";
    for (scanf("%d",&n); n-4; n = c)
        printf("%d is %d.\n", n, c = n ? n<19 ? d[n]-48 : d[n%10] - "_,**+++)**"[n/10]  : 4);
    puts("4 is magic.");
}

파이썬, 129 133 137 148 문자

워밍업으로 여기에 내 첫 번째 버전이 있습니다(이전 최고의 Python에 비해 몇 자 향상됨).

추신.몇 가지 편집을 거친 후 이제 약 20자 정도 짧아졌습니다.

n=input()
while n-4:p=(922148248>>n/10*3&7)+(632179416>>n%10*3&7)+(737280>>n&1)+4*(n<1);print n,'is %d.'%p;n=p
print'4 is magic.'

씨#:210자.

찌그러진:

using C=System.Console;class B{static void Main(){int
x=0,y=int.Parse(C.ReadLine());while(x!=4)C.Write((x=y)+" is {0}.\n",x==4?"magic":""+(y=x==0?4:"03354435543668877988"[x<20?x:x%10]+"0066555766"[x/10]-96));}}

퍼지는:

using C=System.Console;
class B
{
    static void Main()
    {
        int x=0,y=int.Parse(C.ReadLine());
        while(x!=4)
            C.Write((x=y)+" is {0}.\n",
                x==4?
                     "magic":
                     ""+(y= x==0?
                                4:
                                "03354435543668877988"[x<20?x:x%10]+
                                "0066555766"[x/10]-96)
                   );
    }
}

이 접근 방식이 사용하는 트릭은 다음과 같습니다.

  • 숫자에 나타나는 숫자를 기반으로 숫자 이름 길이에 대한 조회 테이블을 만듭니다.
  • 문자열에 대한 문자 배열 조회를 사용하고 숫자 배열 대신 문자 연산을 사용합니다.
  • 클래스 이름 별칭을 사용하여 짧게 사용 Console. 에게 C.
  • 조건부(삼항) 연산자(?:) 대신에 if/else.
  • 사용 \n ~와 함께 Write 대신 이스케이프 코드 WriteLine
  • C#에는 정의된 평가 순서가 있다는 사실을 활용하여 내부 할당을 허용합니다. Write 함수 호출
  • 추가 문과 추가 중괄호를 제거하려면 할당 표현식을 사용하세요.

펄:148자

(펄: 233 181 212 206 200 199 198 185 179 149 148자)

  • 예외 해시를 단위 배열로 이동했습니다.그 결과 많은 캐릭터를 잘라낼 수 있었습니다 :-)
  • mobrule이 불쾌한 버그를 지적했습니다.빠른 수정으로 31자가 추가되었습니다. 아야!
  • 특별한 경우가 없도록 리팩터링되었으며 가벼운 골프도 수행되었습니다.
  • 배열에 저장하는 대신 일회용으로 직접 목록에 액세스하시겠습니까?당근 빠따 지!
  • 단 하나의 피 묻은 캐릭터에 대해 너무 많은 리팩토링이 필요합니다.이것이 바로 골퍼의 삶이다.:-(
  • 이런, 공백 수정은 쉽습니다.지금은 198입니다.
  • 일부 중복 코드를 리팩터링했습니다.
  • 마지막 반환 키워드 r 불필요합니다. 좀 더 삭감했습니다.
  • 댓글당 대규모 리팩토링;불행하게도 이전 코드와 댓글 작성자 버전 모두에 존재했던 버그를 수정해야 했기 때문에 149까지만 얻을 수 있었습니다.
  • 베어워드 "마법"을 시도해 보세요.

Perl에서 적당한 시도를 통해 이 공을 굴려봅시다.

@u=split'','4335443554366887798866555766';$_=<>;chop;print"$_ is ".($_=$_==4?0:$_<20?$u[$_]:($u[$_/10+18]+($_%10&&$u[$_%10]))or magic).".
"while$_

트릭:

너무 많아!

JavaScript 1.8(SpiderMonkey) - 153자

l='4335443554366887798866555766'.split('')
for(b=readline();(a=+b)-4;print(a,'is '+b+'.'))b=a<20?l[a]:+l[18+a/10|0]+(a%10&&+l[a%10])
print('4 is magic.')

용법: echo 42 | js golf.js

산출:

42 is 8.
8 is 5.
5 is 4.
4 is magic.

보너스 포함 - 364자

l='zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty thirty fourty fifty sixty seventy eighty ninety'.split(' ')
z=function(a)a<20?l[a]:l[18+a/10|0]+(a%10?' '+l[a%10]:'')
for(b=+readline();(a=b)-4;print(z(a),'is '+z(b)+'.'))b=z(a).replace(' ','').length
print('four is magic.')

산출:

ninety nine is ten.
ten is three.
three is five.
five is four.
four is magic.

하스켈, 224 270 문자

o="43354435543668877988"
x!i=read[x!!i]
n x|x<20=o!x|0<1="0066555766"!div x 10+o!mod x 10
f x=zipWith(\a b->a++" is "++b++".")l(tail l)where l=map show(takeWhile(/=4)$iterate n x)++["4","magic"]
main=readLn>>=mapM putStrLn.f

그리고 조금 더 읽기 쉽습니다 -

ones = [4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8]
tens = [0,0,6,6,5,5,5,7,6,6]

n x = if x < 20 then ones !! x else (tens !! div x 10) + (ones !! mod x 10)

f x = zipWith (\a b -> a ++ " is " ++ b ++ ".") l (tail l)
    where l = map show (takeWhile (/=4) (iterate n x)) ++ ["4", "magic"]
    
main = readLn >>= mapM putStrLn . f

C++ Stdio 버전, 축소됨:196자

#include <cstdio>
#define P;printf(
char*o="43354435543668877988";main(int p){scanf("%d",&p)P"%d",p);while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]P" is %d.\n%d",p,p);}P" is magic.\n");}

C++ Iostreams 버전, 축소됨:195자

#include <iostream>
#define O;std::cout<<
char*o="43354435543668877988";main(int p){std::cin>>p;O p;while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]O" is "<<p<<".\n"<<p;}O" is magic.\n";}

축소되지 않은 원본:344자

#include <cstdio>

int ones[] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 };
int tens[] = { 0, 3, 6, 6, 5, 5, 5, 9, 6, 6 };

int n(int n) {
    return n<20 ? ones[n] : tens[n/10] + ones[n%10];
}

int main(int p) {
    scanf("%d", &p);
    while(p!=4) {
        int q = n(p);
        printf("%i is %i\n", p, q);
        p = q;
    }
    printf("%i is magic\n", p);
}

델파이:329자

단일 라인 버전:

program P;{$APPTYPE CONSOLE}uses SysUtils;const S=65;A='EDDFEEDFFEDGGIIHHJII';B='DGGFFFJGG';function Z(X:Byte):Byte;begin if X<20 then Z:=Ord(A[X+1])-S else Z:=(Ord(B[X DIV 10])-S)+Z(X MOD 10)end;var X,Y:Byte;begin Write('> ');ReadLn(X);repeat Y:=Z(X);WriteLn(Format('%d is %d.',[X,Y]));X:=Y;until X=4;WriteLn('4 is magic.');end.

형식:

program P;

{$APPTYPE CONSOLE}

uses
  SysUtils;

const
  S = 65;
  A = 'EDDFEEDFFEDGGIIHHJII';
  B = 'DGGFFFJGG';

function Z(X:Byte):Byte;
begin
  if X<20
  then Z := Ord(A[X+1])-S
  else Z := (Ord(B[X DIV 10])-S) + Z(X MOD 10);
end;

var
  X,Y: Byte;

begin
  Write('> ');
  ReadLn(X);

  repeat
    Y:=Z(X);
    WriteLn(Format('%d is %d.' , [X,Y]));
    X:=Y;
  until X=4;

  WriteLn('4 is magic.');
end.

아마도 좀 더 압박할 여지가 있을 것입니다...:-피

씨# 314 286 283 274 289 273 252자.

찌그러진:

252 

정상:

using C = System.Console;
class P
{
    static void Main()
    {
        var x = "4335443554366877798866555766";
        int m, o, v = int.Parse(C.ReadLine());
        do {
            C.Write("{0} is {1}.\n", o = v, v == 4 ? (object)"magic" : v = v < 20 ? x[v] - 48 : x[17 + v / 10] - 96 + ((m = v % 10) > 0 ? x[m] : 48));
        } while (o != 4);
        C.ReadLine();
    }
}

다이캄 편집:꽤 신중하게 삽입하고 변경했습니다.

  • l.ToString()을 캐스트로 변경했습니다. object ~의 string "magic".
  • 임시 변수를 만들었습니다. o, 그래서 나는 break 외부 for 루프, 즉 do-while.
  • 인라인 o 할당, 뿐만 아니라 v 할당, 계속해서 계산 삽입 l 함수 인수에서 모두 사용하면 l.또한 할당을 인라인했습니다. m.
  • 공백을 제거했습니다. int[] x, int[]x 역시 합법적이다.
  • 배열을 문자열 변환으로 변환하려고 시도했지만 using System.Linq 이것을 개선하기에는 너무 많은 일이었습니다.

편집 2 다이캄int 배열을 char 배열/문자열로 변경하고 이를 수정하기 위해 적절한 산술을 추가했습니다.

루아, 176자

o={[0]=4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8}t={3,6,6,5,5,5,7,6,6}n=0+io.read()while n~=4 do a=o[n]or o[n%10]+t[(n-n%10)/10]print(n.." is "..a..".")n=a end print"4 is magic."

또는

  o={[0]=4,3,3,5,4,4
  ,3,5,5,4,3,6,6,8,8
  ,7,7,9,8,8}t={3,6,
   6,5,5,5,7,6,6}n=
   0+io.read()while
   n ~= 4 do a= o[n
   ]or o[n%10]+t[(n
   -n%10)/10]print(
n.." is "..a.."." )n=a
end print"4 is magic."

C - 숫자 단어 없음

180 175* 172 167자

모든 줄 바꿈은 가독성을 위한 것이며 제거할 수 있습니다.

i;V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}main(c){for(scanf("%d",&c);
c-4;)i=c,printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);puts(
"4 is magic.");}

약간 축소됨:

i;
V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}
main(c){
    for(scanf("%d",&c);c-4;)
        i=c,
        printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);
    puts("4 is magic.");
}

* 이전 버전에서는 사양의 두 부분에 대한 표시가 누락되었습니다.0을 처리하지 않았고 stdin 대신 명령줄에서 입력을 받았습니다.추가된 문자를 전혀 처리하지 않지만 명령줄 인수 대신 stdin을 사용하면 훨씬 더 많은 비용이 절약되어 순 비용이 절약됩니다.

펄, 123 122자

STDOUT으로 출력할 필요가 없다는 것을 깨달았으므로 대신 STDERR로 출력하고 다른 문자를 삭제하십시오.

@u='0335443554366887798866555766'=~/./g;$_+=<>;warn"$_ is ",$_=$_-4?$_<20?$u[$_]||4:$u[chop]+$u[$_+18]:magic,".\n"until/g/

그리고 철자된 숫자를 반환하는 버전은 다음과 같습니다.

279 278 276 280자

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2] $n[$n%10]":Zero}$p+=<>;warnt$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/

사양을 충족하기는 하지만 100% 올바른 형식은 아닙니다.0으로 끝나는 숫자 뒤에 추가 공백을 반환합니다.사양은 다음과 같이 말합니다.

"단어 토큰은 분리해야 하지만 어떻게 분리하든 상관없습니다."

그래도 좀 이상하네요.더 정확한 버전은

282 281 279 283자

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("\x8",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2]-$n[$n%10]":Zero}$p+=<>;warn$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/

파이썬:

#!/usr/bin/env python

# Number of letters in each part, we don't count spaces
Decades = ( 0, 3, 6, 6, 6, 5, 5, 7, 6, 6, 0 )
Smalls  = ( 0, 3, 3, 5, 4, 4, 3, 5, 5, 4 )
Teens  =  ( 6, 6, 8, 8, 7, 7, 9, 8, 8 )

def Count(n):
    if n > 10 and n < 20: return Teens[n-11]
    return   Smalls[n % 10 ] + Decades [ n / 10 ]

N = input()

while N-4:
    Cnt = Count(N)
    print "%d is %d" % ( N, Cnt)
    N = Cnt

print "4 is magic"

C++, 171자(#include 생략)

void main(){char x,y,*a="03354435543668877988";scanf("%d",&x);for(;x-4;x=y)y=x?x<19?a[x]-48:"_466555766"[x/10]+a[x%10]-96:4,printf("%d is %d.\n",x,y);puts("4 is magic.");}

루비, 164자

n=gets.to_i;s="03354435543668877987";if n==0;puts"0 is 4.";else;puts"#{n} is #{n=(n<20)?s[n]-48:"0066555766"[n/10]-48+s[n%10]-48}." until n==4;end;puts"4 is magic."

디코딩됨:

n = gets.to_i
s = "03354435543668877987"
if n == 0
  puts "0 is 4."
else
  puts "#{n} is #{n = (n < 20) ? s[n] - 48 : "0066555766"[n / 10] - 48 + s[n % 10] - 48}." until n == 4
end

puts "4 is magic."

루아 185 190 199

마침표 추가, io.read 추가, 마지막 인쇄에서 () 제거

 n=io.read();while(n~=4)do m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;print(n,' is ',m,'.')n=m;end print'4 is magic.'

줄 바꿈 포함

 n=io.read()
 while (n~=4) do
    m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;
    print(n,' is ',m,'.')
    n=m;
 end 
 print'4 is magic.'

PhP 코드

function get_num_name($num){  
    switch($num){  
        case 1:return 'one';  
    case 2:return 'two';  
    case 3:return 'three';  
    case 4:return 'four';  
    case 5:return 'five';  
    case 6:return 'six';  
    case 7:return 'seven';  
    case 8:return 'eight';  
    case 9:return 'nine';  
    }  
}  

function num_to_words($number, $real_name, $decimal_digit, $decimal_name){  
    $res = '';  
    $real = 0;  
    $decimal = 0;  

    if($number == 0)  
        return 'Zero'.(($real_name == '')?'':' '.$real_name);  
    if($number >= 0){  
        $real = floor($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }else{  
        $real = ceil($number) * (-1);  
        $number = abs($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }  
    $decimal = substr($decimal, strpos($decimal, '.') +1);  

    $unit_name[1] = 'thousand';  
    $unit_name[2] = 'million';  
    $unit_name[3] = 'billion';  
    $unit_name[4] = 'trillion';  

    $packet = array();    

    $number = strrev($real);  
    $packet = str_split($number,3);  

    for($i=0;$i<count($packet);$i++){  
        $tmp = strrev($packet[$i]);  
        $unit = $unit_name[$i];  
        if((int)$tmp == 0)  
            continue;  
        $tmp_res = '';  
        if(strlen($tmp) >= 2){  
            $tmp_proc = substr($tmp,-2);  
            switch($tmp_proc){  
                case '10':  
                    $tmp_res = 'ten';  
                    break;  
                case '11':  
                    $tmp_res = 'eleven';  
                    break;  
                case '12':  
                    $tmp_res = 'twelve';  
                    break;  
                case '13':  
                    $tmp_res = 'thirteen';  
                    break;  
                case '15':  
                    $tmp_res = 'fifteen';  
                    break;  
                case '20':  
                    $tmp_res = 'twenty';  
                    break;  
                case '30':  
                    $tmp_res = 'thirty';  
                    break;  
                case '40':  
                    $tmp_res = 'forty';  
                    break;  
                case '50':  
                    $tmp_res = 'fifty';  
                    break;  
                case '70':  
                    $tmp_res = 'seventy';  
                    break;  
                case '80':  
                    $tmp_res = 'eighty';  
                    break;  
                default:  
                    $tmp_begin = substr($tmp_proc,0,1);  
                    $tmp_end = substr($tmp_proc,1,1);  

                    if($tmp_begin == '1')  
                        $tmp_res = get_num_name($tmp_end).'teen';  
                    elseif($tmp_begin == '0')  
                        $tmp_res = get_num_name($tmp_end);  
                    elseif($tmp_end == '0')  
                        $tmp_res = get_num_name($tmp_begin).'ty';  
                    else{  
                        if($tmp_begin == '2')  
                            $tmp_res = 'twenty';  
                        elseif($tmp_begin == '3')  
                            $tmp_res = 'thirty';  
                        elseif($tmp_begin == '4')  
                            $tmp_res = 'forty';  
                        elseif($tmp_begin == '5')  
                            $tmp_res = 'fifty';  
                        elseif($tmp_begin == '6')  
                            $tmp_res = 'sixty';  
                        elseif($tmp_begin == '7')  
                            $tmp_res = 'seventy';  
                        elseif($tmp_begin == '8')  
                            $tmp_res = 'eighty';  
                        elseif($tmp_begin == '9')  
                            $tmp_res = 'ninety';  

                        $tmp_res = $tmp_res.' '.get_num_name($tmp_end);  
                    }  
                    break;  
            }  

            if(strlen($tmp) == 3){  
                $tmp_begin = substr($tmp,0,1);  

                $space = '';  
                if(substr($tmp_res,0,1) != ' ' && $tmp_res != '')  
                    $space = ' ';  

                if($tmp_begin != 0){  
                    if($tmp_begin != '0'){  
                        if($tmp_res != '')  
                            $tmp_res = 'and'.$space.$tmp_res;  
                    }  
                    $tmp_res = get_num_name($tmp_begin).' hundred'.$space.$tmp_res;  
                }  
            }  
        }else  
            $tmp_res = get_num_name($tmp);  
        $space = '';  
        if(substr($res,0,1) != ' ' && $res != '')  
            $space = ' ';  
        $res = $tmp_res.' '.$unit.$space.$res;  
    }  

    $space = '';  
    if(substr($res,-1) != ' ' && $res != '')  
        $space = ' ';  

    if($res)  
        $res .= $space.$real_name.(($real > 1 && $real_name != '')?'s':'');  

    if($decimal > 0)  
        $res .= ' '.num_to_words($decimal, '', 0, '').' '.$decimal_name.(($decimal > 1 && $decimal_name != '')?'s':'');  
    return ucfirst($res);  
}  

//////////// 테스트 ////////////////

 $str2num = 12;
    while($str2num!=4){
        $str = num_to_words($str2num, '', 0, '');  
        $str2num = strlen($str)-1;
        echo $str . '=' . $str2num .'<br/>';
        if ($str2num == 4)
            echo 'four is magic';
    }

////// 결과 /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic

Perl - 130자


5.12.1   (130자) 121 123 132 136 140

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123

@u='4335443554366887798866555766'=~/./g;$_=pop;say"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,"."until/\D/


5.10.1   (134자) 125 127 136 140 144

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234

@u='4335443554366887798866555766'=~/./g;$_=pop;print"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,".\n"until/\D/


변경 내역:

20100714:2223 - 주의를 기울여 변경 사항을 되돌렸습니다. 모브룰, 하지만 ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]), 이는 동일한 문자 수이지만 누군가가 이를 개선할 수 있는 방법을 볼 수 있을 경우를 대비하여 수행했습니다.

20100714:0041 - split//,'...''...'=~/./g
20100714:0025 - ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340 - while$_until/\D/ + 불필요한 괄호 제거
20100713:xxxx - $=<>;chop;$_=pop; - 예의 모브룰


메모: 댓글에서 다른 사람의 답변을 개선하는 데 지쳤기 때문에 이제 욕심이 나서 여기에 변경 사항을 추가할 수 있습니다. :) 플래티넘 Azure님의 답변 - 부분적으로 신용 홉스, 모브룰, 그리고 플래티넘 Azure.

숫자 단어가 포함된 뻔뻔한 Perl(329자)

P Daddy의 C 코드에서 약간의 수정을 거쳐 상당히 직접적으로 적용되었습니다. p() C 대신 Perl 프리미티브를 사용하고 대부분 다시 작성된 메인 루프를 사용하여 동일한 작업을 수행하도록 합니다.설명은 그를 참조하십시오.개행 문자는 모두 선택 사항입니다.

@t=(qw(zero one two three four five six sM eight nine
tL elM twelve NP 4P fifP 6P 7P 8O 9P twLQ NQ forQ fifQ
6Q 7Q 8y 9Q en evL thir eL tO ty 4SmagicT)," is ",".\n");
sub p{local$_=$t[pop];1while s/[0-Z]/$t[-48+ord$&]/e;
print;length}$_=<>;chop;while($_-4){
$_=($_>19?(p($_/10+18),$_&&print("-"),$_%=10)[0]:0)+p$_;
p 35;p$_;p 36}p 34

참고 사항:펄이 너무 안타깝네요 print 단지 true/false를 반환합니다.카운트를 반환하면 7타를 절약할 수 있습니다.

루비, 141자:

n=gets.to_i;m="4335443554366887798866555766";loop{s=n;n=n>20?m[18+n/10]+m[n%10]-96: m[n]-48;puts"#{s} is #{n==s ? 'magic': n}.";n==s &&break}
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top