Code Golf: Bốn là phép thuật


88

Câu đố

Một câu đố nhỏ mà tôi nghe được khi còn học trung học đã giống như thế này ...

  • Người hỏi sẽ yêu cầu tôi cho anh ta một con số;
  • Khi nghe con số, người hỏi sẽ thực hiện một số kiểu biến đổi liên tục (ví dụ, anh ta có thể nói mười là ba ) cho đến khi cuối cùng đến số 4 (lúc đó anh ta sẽ kết thúc với bốn là phép thuật ).
  • Bất kỳ số nào dường như có thể biến đổi thành bốn cuối cùng, không có vấn đề gì.

Mục đích là cố gắng tìm ra hàm biến đổi và sau đó có thể tự giải câu đố này một cách đáng tin cậy.

Giải pháp

Hàm chuyển đổi ở bất kỳ bước nào là

  • Lấy số được đề cập,
  • Đếm số chữ cái trong biểu diễn từ tiếng Anh của nó, bỏ qua dấu gạch ngang hoặc dấu cách hoặc "và" (ví dụ: "mười" có 3 chữ cái trong đó, "ba mươi tư" có 10 chữ cái trong đó, "một trăm bốn mươi ba" có 20 chữ cái trong đó).
  • Trả lại số lượng chữ cái.

Đối với tất cả các số tôi từng quan tâm để kiểm tra, điều này hội tụ thành 4. Vì "bốn" cũng có bốn chữ cái trong đó, sẽ có một vòng lặp vô hạn ở đây; thay vào đó nó chỉ đơn thuần được gọi là ma thuật theo quy ước để kết thúc chuỗi.

Các thách thức

Thử thách của bạn là tạo một đoạn mã sẽ đọc một số từ người dùng và sau đó in các dòng hiển thị chức năng biến đổi được áp dụng nhiều lần cho đến khi đạt được "bốn là ma thuật".

Đặc biệt:

  1. Các giải pháp phải là các chương trình hoàn chỉnh trong và của chính chúng. Chúng không thể chỉ là các hàm lấy một số - hệ số trong đầu vào.
  2. Đầu vào phải được đọc từ đầu vào chuẩn. (Đường ống từ "echo" hoặc sử dụng chuyển hướng đầu vào đều tốt vì điều đó cũng đi từ stdin)
  3. Đầu vào phải ở dạng số.
  4. Đối với mọi ứng dụng của hàm chuyển đổi, một dòng sẽ được in: a is b. trong đó a và b là dạng số của các số trong phép biến đổi.
  5. Bắt buộc phải dừng đầy đủ (khoảng thời gian)!
  6. Dòng cuối cùng nên nói một cách tự nhiên, 4 is magic. ,.
  7. Mã phải tạo ra đầu ra chính xác cho tất cả các số từ 0 đến 99 .

Ví dụ:

> 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.

Người chiến thắng là người gửi ngắn nhất tính theo số ký tự mã nguồn cũng chính xác .

TẶNG KEM

Bạn cũng có thể thử viết một phiên bản của mã in ra các TÊN TIẾNG ANH cho các số với mỗi ứng dụng của hàm chuyển đổi. Đầu vào ban đầu vẫn là số, nhưng các dòng đầu ra phải có dạng từ của số.

(Nhân đôi tiền thưởng cho việc vẽ hình bằng mã của bạn)

(EDIT) Một số làm rõ:

  1. Tôi muốn từ xuất hiện ở cả hai mặt trong tất cả các trường hợp áp dụng, ví dụ: Nine is four. Four is magic.
  2. Tôi không quan tâm đến việc viết hoa. Và tôi không quan tâm đến cách bạn tách các thẻ từ, mặc dù chúng nên được tách biệt: ninety-nineđược, ninety nineđược, ninetyninekhông được.

Tôi đang coi đây là một danh mục riêng để cạnh tranh tiền thưởng liên quan đến thử thách, vì vậy nếu bạn tiếp tục điều này, đừng lo lắng về việc mã của bạn dài hơn phiên bản số.

Vui lòng gửi một giải pháp cho mỗi phiên bản.


1
Chúng ta nên xử lý một số cao như thế nào? <100? <1000? <1000000? <2 ** 31?
P Daddy,

1
Vì điều này chỉ phải đi từ 0 đến 99, tôi nghi ngờ một giải pháp ngắn gọn, nhanh chóng sẽ là mã hóa cứng các giá trị mà 0-99 ánh xạ tới, và sau đó lặp lại cho đến khi bạn đạt đến 4. Sau đó, vi chỉnh sửa bắt đầu.
Beska

@P Daddy ... phần 6 chỉ nói 0-99.
Beska


14
4 chỉ là phép thuật vì nó được chọn bởi một cuộn xúc xắc công bằng.
VirtuosiMedia

Câu trả lời:


57

GolfScript - 101 96 93 92 91 90 94 86 byte

90 → 94: Đầu ra cố định cho bội số của 10
94 → 86.: Mã được cấu trúc lại. Sử dụng cơ số 100 để xóa các ký tự không in được.
86 → 85: Truyền tới chuỗi ngắn hơn.

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

tại sao điều này là quá xa? nó ngắn hơn một lisp và không sử dụng một built-in chức năng định dạng
Claudiu

36
Tôi thích cách mã kết thúc bằng "magic.", nó tổng hợp khá nhiều.
Aistina

@Aistina: Tôi nghĩ điều đó rất dễ thực hiện trong thử thách này. :-)
Platinum Azure

9
@Aistina: haha, thật là buồn cười. "mumbo jumbo yada yada..magic"
vol7ron

1
@P Daddy The dđược trích xuất bởi )as 100và được sử dụng làm cơ số cho chuyển đổi cơ sở.
Nabb

85

Perl, khoảng 147 ký tự

Dựa trên giải pháp của Platinum Azure một cách lỏng lẻo:

               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

1
@Platinum Azure cách mà nó nhận được đầu vào là thông qua việc sử dụng popmà không có bất kỳ đối số nào. Bên ngoài một chương trình con poploại bỏ và trả về giá trị cuối cùng @ARGVlà danh sách các đối số của chương trình Perl. Nó có thể dễ dàng được thay thế bằng shift, nhưng điều đó thêm 2 ký tự khác. Xem: p3rl.org/pop
Brad Gilbert

có vẻ như bạn cần một ký tự xuống dòng trong '.', đó là 2 \nhoặc 1 nếu bạn đang trắng đếm trong '. '(không gian là đen newline)
vol7ron

Dài hơn một chút, nhưng sự sáng tạo đi một chặng đường dài trong cuốn sách của tôi.
Beska

@Platinum Azure và cộng sự: Anh ấy đang nhận thông tin đầu vào từ stdin. Đó là cách để làm điều đó ở Perl. (Có thể anh ấy đã thay đổi nó sau nhận xét của bạn?)
Frank

@P Daddy: tiếng rên nhưng 1 khi viết phản hồi nào
Platinum Azure

30

Lisp chung 157 ký tự

Phiên bản mới phù hợp hơn, hiện đang đọc đầu vào chuẩn của biểu mẫu và bỏ qua dấu cách và dấu gạch ngang:

(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)))

Ở dạng con người có thể đọc được:

 (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)))

Và một số lần chạy thử nghiệm:

>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.

Và phiên bản tiền thưởng, với 165 ký tự:

 (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)))

Cho

>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.

5
Tôi nghĩ "hai mươi tư" chỉ có 10 chữ cái?
kennytm

1
Các số sau "is" cũng phải là văn bản.
Mike DeSimone,

5
tại sao điều này lại cao như vậy? những người khác không sử dụng một built-in chức năng định dạng và họ là những nhân vật ít
Claudiu

3
@Claudiu Vì Common Lisp thật tuyệt vời.
Mornedhel

3
Bạn thực hiện bao nhiêu cú đánh không quan trọng nếu bạn không đưa được bóng vào lỗ. Mọi người dường như quên điều đó khi họ ủng hộ các giải pháp không chính xác.
Mark Peters

21

Python 2.x, 144 150 154 166 ký tự

Điều này phân tách số thành hàng chục và hàng đơn vị và cộng lại. Thuộc tính không mong muốn của các nhà điều hành pseudo-ternary a and b or cđó cđược trả lại nếu blà 0 đang bị lạm dụng ở đây.

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."

Phiên bản ngây thơ trước (150 ký tự). Chỉ cần mã hóa tất cả độ dài dưới dạng số nguyên.

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

Xin lỗi, tôi đặc biệt muốn dừng hoàn toàn chỉ vì những thứ như thế này. :-) Mục nhập tốt mặc dù! (EDIT: Tôi không biết Python, nhưng bạn có thể n,"is",p,"."tôi nghĩ rằng bạn vẫn tiết kiệm một số chararacters nếu tôi đếm đúng không?)
Platinum Azure

2
@Plat: Điều đó sẽ gây ra một khoảng trống thừa trước ..
kennytm

@KennyTM: Ồ, tôi phải nhận ra điều đó ngay cả từ đoạn trích. Giáo sư! Vâng, dù sao, như tôi đã nói, một số thông số kỹ thuật được thiết kế đặc biệt để làm phức tạp mọi thứ một chút. :-)
Platinum Azure,

Chúng ta có thể rút ngắn điều này bằng cách sử dụng cơ số cao hơn 36 không?
MikeD

@MikeD: Không. Từ tài liệu Python: " Tham số cơ sở cung cấp cơ sở cho chuyển đổi (theo mặc định là 10) và có thể là bất kỳ số nguyên nào trong phạm vi [2, 36] hoặc 0." Bây giờ bạn có thể có thể sử dụng một chức năng khác hơn int(), nói điều gì đó ra khỏi structhoặc base64module ...
Mike Desimone

20

C - với các từ số

445 431 427 421 399 386 371 359 * 356 354 348 347 ký tự

Đó là nó. Tôi không nghĩ rằng tôi có thể làm cho điều này ngắn hơn nữa.

Tất cả các dòng mới là để dễ đọc và có thể bị xóa:

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

Dưới đây, nó có phần chưa được làm rõ, nhưng vẫn khá khó đọc. Xem bên dưới để có phiên bản dễ đọc hơn.

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

Đã mở rộng và nhận xét:

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"*/);
}

Giới thiệu về chuỗi mã hóa gần đầu

Tên của các con số được nén bằng một lược đồ rất đơn giản. Các chuỗi con được sử dụng thường xuyên được thay thế bằng các chỉ số một ký tự vào mảng tên. Một "bảng tra cứu" các mục tên phụ được thêm vào cuối cho các chuỗi con không được sử dụng toàn bộ trong tập hợp đầu tiên. Tra cứu là đệ quy: các mục nhập có thể tham chiếu đến các mục nhập khác.

Ví dụ, tên nén cho 11 là elM. Các print()chức năng kết quả đầu ra các nhân vật el(thấp hơn trường hợp 'L', chứ không phải số '1') đúng nguyên văn, nhưng sau đó nó tìm M, vì vậy nó tự gọi mình với chỉ số của mục 29 (ASCII 'M' - ASCII '0') vào bảng tra cứu. Chuỗi này evL, do đó, nó xuất ra evsau đó tự gọi lại với chỉ mục của mục nhập thứ 28 trong bảng tra cứu en, và là đầu ra nguyên văn. Điều này rất hữu ích vì encũng được sử dụng trong eLfor een(được sử dụng sau eightin eighteen), được sử dụng trong tOfor teen(được sử dụng cho mọi -teentên khác ).

Lược đồ này dẫn đến việc nén khá nhiều tên số, trong khi chỉ cần một lượng nhỏ mã để giải nén.

Dấu phẩy ở đầu và cuối chuỗi biểu thị một cách đơn giản rằng các chuỗi con được tìm thấy trong chuỗi này. Thêm hai ký tự ở đây giúp tiết kiệm nhiều ký tự hơn sau này.

Về việc lạm dụng main()

argvbị bỏ qua (và do đó không được khai báo trong phiên bản nén), giá trị của argc bị bỏ qua, nhưng bộ nhớ được sử dụng lại để giữ số hiện tại. Điều này chỉ giúp tôi không phải khai báo thêm một biến.

Về việc thiếu #include

Một số người sẽ phàn nàn rằng việc bỏ qua #include <stdio.h>là gian lận. Nó không phải là ở tất cả. Đã cho là một chương trình C hoàn toàn hợp pháp sẽ biên dịch chính xác trên bất kỳ trình biên dịch C nào mà tôi biết (mặc dù có cảnh báo). Thiếu các protoypes cho các hàm stdio, trình biên dịch sẽ giả định rằng chúng là các hàm cdecl trả về intvà sẽ tin tưởng rằng bạn biết những đối số nào cần chuyển. Dù sao thì các giá trị trả về cũng bị bỏ qua trong chương trình này và chúng đều là các hàm cdecl (quy ước gọi "C") và chúng tôi thực sự biết những đối số nào cần chuyển.

Đầu ra

Đầu ra như mong đợi:

0
số không là bốn.
bốn là phép thuật.
1
một là ba.
ba là năm.
năm là bốn.
bốn là phép thuật.
4
bốn là phép thuật.
20
hai mươi là sáu.
sáu là ba.
ba là năm.
năm là bốn.
bốn là phép thuật.
21
hai mốt là chín.
chín là bốn.
bốn là phép thuật.

* Phiên bản trước thiếu dấu hiệu ở hai phần của thông số kỹ thuật: nó không xử lý số 0 và nó lấy đầu vào trên dòng lệnh thay vì stdin. Việc xử lý các ký tự được thêm vào số không, nhưng sử dụng stdin thay vì args dòng lệnh, cũng như một vài cách tối ưu khác đã lưu cùng một số ký tự, dẫn đến một lỗi.

Các yêu cầu đã được thay đổi để làm rõ ràng rằng từ số phải được in trên cả hai mặt của "is". Phiên bản mới này đáp ứng yêu cầu đó và triển khai thêm một số tối ưu hóa để (nhiều hơn) tính đến kích thước bổ sung cần thiết.


Đây là câu trả lời dễ hiểu mà tôi yêu thích nhất ... Xin chào, làm tốt lắm. +1 cho bạn và nếu tôi có thể đưa ra hai dấu kiểm, tôi sẽ làm.
Platinum Azure

5
Đọc thấy vui quá, mình nghĩ từ nay mình sẽ dùng những con số này trong cuộc sống hàng ngày. Sáu, sem, tám, chín, tel, elem, mười hai, enpee, fourpee, fifpee, sixpee, sevenpee, eightoh, ninepee, twelkyu ... =)
deceze

10

J, 107 112 ký tự

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

(Dòng mới chỉ để đọc)

Sử dụng và đầu ra:

    '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. 

15
Đó là lập thành Trung Quốc
TS Belisarius

3
Vui lòng chọn một trọng tài không Trung Quốc
TS Belisarius

3
@beli: 멩, 겻, 곋, 멩 là tiếng Hàn.
kennytm

1
Vợ tôi (một người nói tiếng Trung bản ngữ) nói rằng đó là sự pha trộn giữa tiếng Trung và tiếng Hàn.
Loren Pechtel,

3
@belisarius: 1) Cô ấy không biết tiếng Hàn. 2) Tiếng Trung là vô nghĩa.
Loren Pechtel,

10

T-SQL, 413 451 499 ký tự

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

(Không phải tôi thực sự đề nghị bạn làm điều này ... thực sự tôi chỉ muốn viết một CTE)

Để sử dụng:

M 95

Lợi nhuận

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

Bạn không thể chỉ in các kết quả riêng lẻ thay vì trả về một bảng? Điều đó sẽ làm cho đầu ra trông đẹp hơn.
Joey

1
Tôi không nghĩ rằng nó xử lý số 0 đúng cách. Làm thế nào về một cái gì đó như thế này:CREATE FUNCTION d(@ int) RETURNS int AS BEGIN Declare @l char(9),@s char(50) Select @l='066555766',@s='03354435543668877987' if @=0 return 4 if @<20 return 0+substring(@s,@+1,1)return 0+substring(@l,@/10,1)+substring(@s,@%10+1,1)END
Gabe

9

Java (với bản soạn sẵn), 308 290 286 282 280 ký tự

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

Tôi chắc rằng Groovy sẽ loại bỏ phần lớn điều đó.

Giải thích và định dạng (tất cả nhận xét, dòng mới và khoảng trắng ở đầu / cuối bị xóa trong số):

Về phía trước một cách hợp lý, nhưng

//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");
   }
}

Chỉnh sửa: Không còn sử dụng hex, đây là số lần gõ phím ít hơn


1
249 không có nhập khẩu, phân loại lớp hoặc phân loại chính.
Mark Peters

1
Thật là quái đản. Tôi thích căn cứ 16. (+1)
Platinum Azure

Bạn có thể tiết kiệm một không gian bằng cách sử dụng String[]athay vì String[] a.
BalusC

Cảm ơn @Balus, cũng đã loại bỏ một loạt bằng cách thực hiện số học đơn giản trên ký tự thay vì sử dụng phân tích cú pháp hex.
Mark Peters

@Mark Peters: Thậm chí còn tệ hơn. Tôi cảm thấy rất vani so với điều đó.
Platinum Azure

9

Windows PowerShell: 152 153 184 byte

dựa trên giải pháp trước đó, với nhiều ảnh hưởng hơn từ các giải pháp khác

$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.'

Đã sửa để hỗ trợ bội số của 10 ("chín mươi" thay vì "chín mươi").
Gabe

Này @Gabe :), cảm ơn; gần đây không có nhiều thời gian chơi gôn. Tuy nhiên, các dấu ngoặc kép xung quanh $inputphải được giữ nguyên vì bạn không thể truyền trực tiếp một điều tra viên đến int; nó hoạt động khi đi qua stringđầu tiên :-)
Joey

8

C, 158 ký tự

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.");}

(ban đầu dựa trên mã Python của Vlad, mượn một mẹo từ giải pháp C ++ của Tom Sirgedas để rút ra một vài ký tự khác)

phiên bản mở rộng:

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.");
}

Dường như không hiệu quả với tôi: ./magic 10 10 là -27. Lỗi segmentation
Casey

@Casey - lệnh gọi scanf () hơi sơ sài. Nó đang đọc một int thành một char. Tôi đã sử dụng nó trên OSX và trên Windows, nó hoạt động nhưng bị lỗi khi thoát. Vì vậy, tôi đã tạo n & c ints một lần nữa. Tôi nhận ra rằng mình có thể bỏ từ khóa int bằng cách tạo các tham số cho chúng bằng cách sử dụng ký hiệu K&R. Kết quả là an toàn hơn và ngắn hơn một ký tự.
Ferruccio

Bạn có thể lưu 3 ký tự bằng cách thay thế " 466555766" [n / 10] + d [n% 10] -96 bằng d [n% 10] - " , +++) " [n / 10]
Tom Sirgedas

6

Python, 129 133 137 148 ký tự

Để khởi động, đây là phiên bản đầu tiên của tôi (cải thiện một vài ký tự so với Python tốt nhất trước đó).

Tái bút. Sau một vài giao dịch, giờ nó ngắn hơn khoảng 20 ký tự:

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.'

6

C #: 210 ký tự.

Lộn xộn:

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

Đã mở rộng:

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

Các thủ thuật mà cách tiếp cận này sử dụng:

  • Tạo bảng tra cứu độ dài tên số dựa trên các chữ số xuất hiện trong số.
  • Sử dụng tra cứu mảng ký tự trên một chuỗi và số học ký tự thay vì một mảng số.
  • Sử dụng tên lớp răng cưa để ngắn Console.đểC.
  • Sử dụng toán tử có điều kiện (bậc ba ?:) thay vì if/else.
  • Sử dụng \nvới Writemã thoát thay vìWriteLine
  • Sử dụng thực tế là C # có một thứ tự đánh giá xác định để cho phép các phép gán bên trong lệnh Writegọi hàm
  • Sử dụng các biểu thức gán để loại bỏ các câu lệnh thừa và do đó các dấu ngoặc nhọn

int[] zsẽ ngắn hơn vì nó không cầnnew[]
Joey

Đã sửa đổi để sử dụng số học ký tự thay vì tra cứu mảng.
LBushkin

@ mdm20: Bạn nói đúng. Tôi đã có một sai lầm trong bảng tra cứu. Đã sửa ngay.
LBushkin

Vâng, thời gian thứ mười hai là sự quyến rũ: * D
LBushkin

Một quicky để cứu 5 ký tự: ngắn hơn so với đúc "magic"để object, sẽ được mặc nhiên gọi ToString()trên ybằng cách thêm "". Nhưng, vì +có độ ưu tiên cao hơn ?:, bạn cần phải đặt nó trong đúng một phần thay vì các sai phần: x!=4?y+"":"magic".
P Daddy,

6

Perl: 148 ký tự

(Perl: 233 181 212 206 200 199 198 185 179 149 148 ký tự)

  • Đã chuyển hàm băm ngoại lệ vào mảng đơn vị. Điều này dẫn đến việc tôi có thể cắt rất nhiều ký tự :-)
  • mobrule đã chỉ ra một lỗi khó chịu. Sửa nhanh thêm 31 ký tự, ouch!
  • Tái cấu trúc cho trường hợp đặc biệt bằng không, chơi gôn nhẹ cũng được thực hiện.
  • Truy cập danh sách trực tiếp để sử dụng một lần thay vì lưu trữ vào mảng? Đúng vậy!
  • RẤT NHIỀU SỰ TẠO RA chỉ cho MỘT nhân vật có máu mặt. Đây thực sự là cuộc sống của một người chơi golf. :-(
  • Rất tiếc, sửa khoảng trắng dễ dàng. 198 bây giờ.
  • Đã cấu trúc lại một số mã thừa.
  • Từ khóa quay lại cuối cùng trong rlà không cần thiết, bị loại bỏ thêm một số.
  • Tái cấu trúc hàng loạt cho mỗi nhận xét; Rất tiếc, tôi chỉ có thể nhận được nó đến 149 vì tôi phải sửa một lỗi có trong cả mã trước đó của tôi và phiên bản của người bình luận.
  • Thử "phép thuật" từ trần.

Hãy để quả bóng này lăn với một nỗ lực khiêm tốn ở Perl.

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

Thủ thuật:

Quá nhiều!


ACK! Làm thế nào tôi chưa bao giờ kiểm tra mà tôi sẽ không bao giờ biết.
Platinum Azure

Bạn có một số mã chết trong đó? Tôi không thấy trường hợp đặc biệt cho số 0 cần thiết như thế nào khi $ u [0] là 4. Tôi có một phiên bản mã @ 166 ký tự của bạn dường như đang hoạt động và tôi nghĩ nó có chỗ để ngắn hơn một chút.
hobbs

@hobbs: Tốt, tôi sẽ xem xét lại. Câu chuyện là tôi đã xem được nửa chừng một vài lần sửa đổi và đột nhiên mọi thứ bị vỡ lở (vào khoảng thời gian tôi chọn có 4 -> 0). Mặc dù vậy, tôi nghĩ bạn đã đúng vào thời điểm này :-)
Platinum Azure

Tôi không tự coi mình là một lập trình viên Perl giỏi, nhưng bạn có thể giảm bớt một số ký tự: @u=split$x,'43350435543668877988';dấu phẩy của bạn sử dụng 19 ký tự không cần thiết, chia thành một undefphần tách ở mỗi ký tự, tôi sử dụng $xnhư một biến không xác định để thay thế cho `undef` - total tiết kiệm: 11 ký tự. Ngoài ra, loại bỏ chữ min chompvà bạn sẽ có được một nhân vật khác bị loại khỏi điểm số của mình.
vol7ron

Làm tốt hơn, nhưng bạn vẫn có thể tiết kiệm nhiều hơn bằng cách mất sub rhoàn toàn - bạn chỉ sử dụng nó một lần và bạn có thể thay thế tất cả bằng một con chim nhạn lồng nhau duy nhất mà không cần parens. Phiên bản của tôi hiện tại có 144 ký tự: gist.github.com/473289
hobbs 13/07/10

5

JavaScript 1.8 (SpiderMonkey) - 153 ký tự

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.')

Sử dụng: echo 42 | js golf.js

Đầu ra:

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

Có tiền thưởng - 364 ký tự

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.')

Đầu ra:

chín mươi chín là mười.
mười là ba.
ba là năm.
năm là bốn.
bốn là phép thuật.

4

Haskell, 224 270 ký tự

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

Và dễ đọc hơn một chút -

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

4

Phiên bản C ++ Stdio, rút ​​gọn: 196 ký tự

#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");}

Phiên bản C ++ Iostreams, rút ​​gọn: 195 ký tự

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

Bản gốc, chưa được rút gọn: 344 ký tự

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

Đã sửa. Nó cũng làm cho nó ngắn hơn một chút.
Mike DeSimone

Tốt lắm. (Tôi đã cười rất nhiều tại 20 ký tự std câu hỏi hóc búa!)
Platinum Azure

Vâng, đó là một headbanger thực sự, cho đến khi tôi nhận ra rằng nó #definesẽ còn ngắn hơn vì nó có thể thay thế một số mã thông báo.
Mike DeSimone

printf("is magic".\n)=> puts. printf("%d",p)=> puts(atoi(p)). Không chỉ ngắn hơn mà còn nhanh hơn.
Ben Voigt

2
@Mike DeSimone: Tôi nghĩ while(p!=4)có thể được rút ngắn thành while(p-4). Toàn bộ một nhân vật, tôi biết, nhưng vẫn còn. :-)
Platinum Azure

3

Delphi: 329 ký tự

Phiên bản dòng đơn:

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.

Hình thành:

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.

Có lẽ là chỗ cho một số siết chặt hơn ... :-P


3

C # 314 286 283 274 289 273 252 ký tự.

Lộn xộn:

252 

Bình thường:

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

Chỉnh sửa Dykam: Đã thực hiện một số chèn và thay đổi cẩn thận:

  • Đã thay đổi l.ToString () thành một tập hợp objectcủa string "magic".
  • Đã tạo một biến tạm thời o, vì vậy tôi có thể di chuyển ra breakbên ngoài forvòng lặp, tức là, dẫn đến a do-while.
  • Nội dung obài tập, cũng như vbài tập, tiếp tục chèn hoàn toàn phép tính ltrong các đối số của hàm, loại bỏ sự cần thiết l. Cũng có nội dung việc phân công m.
  • Đã xóa một khoảng trống trong int[] x, int[]xcũng là hợp pháp.
  • Đã cố gắng biến đổi mảng thành một phép biến đổi chuỗi, nhưng using System.Linqquá nhiều để biến điều này thành một cải tiến.

Chỉnh sửa 2 Dykam Đã thay đổi mảng int thành mảng / chuỗi ký tự, thêm số học thích hợp để sửa lỗi này.


Vâng, nó ngắn hơn phiên bản Java.
Dykam

3

Lua, 176 ký tự

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."

hoặc là

  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."

3

C - không có từ số

180 175 * 172 167 ký tự

Tất cả các dòng mới là để dễ đọc và có thể bị xóa:

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.");}

Hơi chưa được xác minh:

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.");
}

* Phiên bản trước thiếu dấu hiệu ở hai phần của thông số kỹ thuật: nó không xử lý số 0 và nó lấy đầu vào trên dòng lệnh thay vì stdin. Xử lý không có ký tự được thêm vào, nhưng sử dụng stdin thay vì args dòng lệnh đã tiết kiệm được nhiều hơn, dẫn đến tiết kiệm ròng.


2

perl, 123 122 ký tự

Chỉ cần nhận ra rằng không có yêu cầu xuất ra STDOUT, vì vậy hãy xuất ra STDERR để thay thế và loại bỏ một ký tự khác.

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

Và, một phiên bản trả về các số được đánh vần:

279 278 276 280 ký tự

@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/

Mặc dù đáp ứng các thông số kỹ thuật, nhưng nó không được định dạng tốt 100%. Nó trả về một khoảng trắng thừa sau các số kết thúc bằng không. Thông số kỹ thuật nói:

"Tôi không quan tâm cách bạn tách các mã thông báo từ, mặc dù chúng nên được tách biệt"

Tuy nhiên, đó là loại mệt mỏi. Một phiên bản chính xác hơn tại

282 281 279 283 ký tự

@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/

1

Python:

#!/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"

4
Tôi thích nó. Bạn có thể thắt chặt nó một chút.
Josh K

@Vlad: Đầu vào phải được đọc từ stdin thay vì từ các đối số. Điều đó có nghĩa là bạn chỉ có thể sử dụng N = input()(hoặc raw_input()) và loại bỏ những systhứ đó.
kennytm 12/07/10

Ngoài ra, bạn có thể đặt smalls bao gồm cả thanh thiếu niên, khi đó câu lệnh if sẽ chỉ là "if n <20: return Smalls [n]". Smalls vẫn sẽ làm việc cho> = 20 trường hợp, vì các module bằng 10
Jon Smock

5
Đây phải là lần đầu tiên tôi nhìn thấy (hoàn toàn không bắt buộc) she-bangtrong một câu trả lời mã golf ;-)
ChristopheD

Có vẻ như một khởi đầu tốt ... Chắc chắn phải thắt chặt nó, thậm chí Python không cần TẤT CẢ khoảng trắng này. :-) Ngoài ra, như Ferruccio chỉ ra, 0 không hoạt động, cụ thể là nó dường như đi vào một vòng lặp vô hạn.
Platinum Azure,

1

C ++, 171 ký tự (đã bỏ qua #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.");}

Tôi nghĩ rằng nếu bạn coi đây là C, bạn có thể tránh được sự cần thiết của nó #includevì các hàm sẽ chỉ được giả định là nhận inttham số. Bạn thậm chí có thể cứu một cơn đột quỵ bằng cách mainquay trở lại int.
Gabe

1

Ruby, 164 ký tự

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."

đã giải mã:

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."

Giải pháp Ruby tốt, giữ cho nó đơn giản. :-) (+1)
Bạch kim Azure,

Giữ nó đơn giản là không có lý do gì để giữ nó quá lâu, mặc dù ;-)
Joey

Tôi nghĩ bạn có thể thay thế 'if n == 0' bằng 'if! N'
Vincent

2
Trong Ruby? Tôi luôn luôn nghĩ rằng tất cả các giá trị ngoại trừ sai và nil đánh giá là true :-(
Platinum Azure

1

Lua 185 190 199

đã thêm khoảng thời gian, đã thêm io.read, remove () trên bản in cuối cùng

 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.'

có ngắt dòng

 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.'

Cần một n=io.read()(+11 ký tự) tuân thủ quy tắc để đọc số từ đầu vào chuẩn. Thay đổi print('4 is magic.')thành print'4 is magic.'sẽ lưu 2 ký tự. Xóa ;sau )sẽ tiết kiệm được 1 ký tự. Việc printsử dụng dấu phẩy có vẻ giống như gian lận, nhưng thông số kỹ thuật không rõ ràng. Cũng có thể thay đổi nó thành print(n,'is',m,'.')để lưu 2 ký tự.
gwell

Các dấu phẩy được hiển thị dưới dạng dòng mới trong Lua có đứng riêng không? Đã lâu rồi tôi chưa sử dụng nó.
Nick Van Brunt,

Các dấu phẩy được hiển thị dưới dạng tab.
gwell

0

Mã 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);  
}  

//////////// thử nghiệm //////////////////

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

////// Các kết quả /////////

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

4
@wallacoloo: Một giải pháp dể thương cho một ngôn ngữ dể thương: D
Thomas Việc chỉnh sửa

5
Hoặc ngắn hơn nhiều với 178 ký tự:$l='4335443554366887798866555766';for($b=(int)fgets(fopen('php://stdin','r'));($a=$b)-4;){$b=$a<20?$l[$a]:$l[18+$a/10]+($a%10?$l[$a%10]:0);echo"$a is $b.\n";}echo"4 is magic.\n";
gnarf

Trò đùa vui vẻ. :-D được lập trình rất tốt.
Tom Pažourek

0

Perl - 130 ký tự


5.12.1 (130 ký tự) 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 ký tự) 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/


Thay đổi lịch sử:

20100714:2223- hoàn nguyên thay đổi khi có sự chú ý của mobrule , nhưng ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]), cùng một # ký tự, nhưng tôi đã làm điều đó trong trường hợp ai đó có thể thấy cách cải thiện nó

20100714:0041- split//,'...''...'=~/./g
20100714:0025- ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340- while$_until/\D/+ bỏ dấu ngoặc đơn không cần thiết
20100713:xxxx- $=<>;chop;$_=pop;- lịch sự với mobrule


Lưu ý: Tôi đã quá mệt mỏi với việc cải thiện câu trả lời của những người khác trong nhận xét, vì vậy bây giờ tôi đang tham lam và chỉ có thể thêm các thay đổi của mình ở đây :) Đây là phần tách ra từ câu trả lời của Platinum Azure - một phần tín dụng cho Hobbs , mobruleBạch kim Azure .


Khi bạn đã thoát khỏi những $_%10&&...cấu trúc, bạn đã phá vỡ spec cho đầu vào 20,30,40, ...
đám đông

+1 Rất tốt. Bạn đã đi ra khỏi stdin vào args dù :-(
Platinum Azure

Đúng vậy, thay thế bằng ARGV, đó là dân cư bởi STDIN:) hay .. echo bar | xargs perl foo.pl, về mặt kỹ thuật cấp nước tập trung từ tiếng vang vào args cho perl :)
vol7ron

0

Shameless Perl với Number Words (329 ký tự)

Được điều chỉnh khá trực tiếp từ mã C của P Daddy, với một số chỉnh sửa để p()làm cho nó hoạt động tương tự bằng cách sử dụng các nguyên thủy Perl thay vì C và một mainloop được viết lại gần hết. Gặp anh ấy để được giải thích. Các dòng mới đều là tùy chọn.

@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

Lưu ý phụ: quá tệ khi perl printchỉ trả về true / false; nếu nó trả về một số đếm, nó sẽ giúp tôi tiết kiệm được 7 nét.


0

Ruby, 141 ký tự:

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}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.