퍼즐
고등학교 때 들었던 작은 수수께끼는 이런 식으로 진행되었습니다.
- 질문자는 나에게 번호를 물어볼 것입니다.
- 숫자를 듣고 질문자는 결국 숫자 4에 도달 할 때까지 (예를 들어 10은 3 이라고 말할 수 있음) 반복적으로 변형을 수행합니다 ( 4로 끝나는 시점 은 마술입니다 ).
- 어떤 숫자라도 결국 4 개로 변환 될 수있는 것 같습니다.
목표는 변형 함수를 알아 내고이 퍼즐을 스스로 확실하게 감독 할 수 있도록하는 것이 었습니다.
해결책
모든 단계에서 변환 기능은
- 문제의 번호를 가지고
- 하이픈이나 공백 또는 “and”를 무시하고 영어 단어 표현의 문자 수를 계산합니다 (예 : “ten”에는 3 개의 문자가 있고, “thirty-four”에는 10 개의 문자가 있습니다. “1 백 사십 삼”) 20 글자 포함).
- 그 수의 문자를 반환하십시오.
내가 테스트 해 본 모든 숫자에 대해, 이것은 4로 수렴됩니다. “four”도 그 안에 4 개의 문자가 있기 때문에 여기에 무한 루프가 있습니다. 대신 시퀀스를 끝내는 것은 관례 상 마법 이라고합니다 .
도전
당신의 도전은 사용자로부터 숫자를 읽을 코드 조각을 만들고 “four is magic”에 도달 할 때까지 반복적으로 적용되는 변환 함수를 보여주는 줄을 인쇄하는 것입니다.
구체적으로 특별히:
- 솔루션은 그 자체로 완전한 프로그램이어야합니다. 그것들은 단순히 숫자를 취하는 함수가 될 수 없습니다.
- 입력은 표준 입력에서 읽어야합니다. ( “echo”에서 파이핑하거나 입력 리디렉션을 사용하는 것은 stdin에서도 오기 때문에 괜찮습니다)
- 입력은 숫자 형식이어야합니다.
- 변환 함수를 적용 할 때마다 한 줄을 인쇄해야합니다.
a is b.여기서 a와 b는 변환에서 숫자의 숫자 형식입니다. - 마침표 (마침표)가 필요합니다!
- 마지막 줄은 당연히
4 is magic.. - 코드는 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.
우승자는 또한 정확한 소스 코드 문자 수에 의한 가장 짧은 제출 입니다.
보너스
변환 함수의 각 응용 프로그램과 함께 숫자에 대한 영어 이름을 인쇄하는 코드 버전을 작성할 수도 있습니다. 원래 입력은 여전히 숫자이지만 출력 행에는 숫자의 단어 형식이 있어야합니다.
(편집) 일부 설명 :
- 해당하는 모든 경우에 단어가 양쪽에 나타나기를 원합니다. 예 :
Nine is four. Four is magic. - 하지만 대소 문자는 신경 쓰지 않습니다. 그리고 토큰이라는 단어를 분리하는 방법은 신경 쓰지 않습니다. 비록 분리되어야하지만 :
ninety-nine괜찮아,ninety nine괜찮아,ninetynine괜찮지 않습니다.
도전과 관련하여 보너스 경쟁을위한 별도의 범주로 간주하고 있으므로,이 경우 코드가 숫자 버전보다 길다는 것에 대해 걱정하지 마십시오.
각 버전에 대해 하나의 솔루션을 자유롭게 제출하십시오.
답변
GolfScript- 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
답변
Common Lisp 157 Chars
새롭고 더 적합한 버전, 이제 표준 입력 형식을 읽고 공백과 하이픈을 무시합니다.
(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.
답변
Python 2.x, 144 150 154 166 문자
이것은 숫자를 10과 1로 분리하고 합산합니다. 의사 – 삼원 연산자의 바람직하지 못한 특성 경우 반환 0 여기 학대이다.a and b or ccb
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’)을 그대로 출력하지만를 찾아서 M29 번째 항목의 인덱스 (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 0은 4입니다. 4는 마법입니다.
1 하나는 셋입니다. 3은 5입니다. 5는 4입니다. 4는 마법입니다.
4 4는 마법입니다.
20 20은 6입니다. 6은 3입니다. 3은 5입니다. 5는 4입니다. 4는 마법입니다.
21 21은 9입니다. 9는 4입니다. 4는 마법입니다.
* 이전 버전은 사양의 두 부분에서 표시를 놓쳤습니다. 0을 처리하지 않았고 stdin 대신 명령 줄에 입력을 받았습니다. 0으로 추가 된 문자를 처리하지만 명령 줄 인수 대신 stdin을 사용하고 몇 가지 다른 최적화를 사용하면 동일한 수의 문자가 저장되어 세척이 발생했습니다.
† “is”의 양면에 숫자 단어를 인쇄해야 함을 명확히하기 위해 요구 사항이 변경되었습니다. 이 새 버전은 해당 요구 사항을 충족하고 필요한 추가 크기를 설명하기 위해 몇 가지 더 많은 최적화를 구현합니다.
답변
J 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, 413451 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.
