Code Golf: Four is magic

88

Teka-teki

Sebuah teka-teki kecil yang saya dengar ketika saya masih di sekolah menengah terjadi seperti ini ...

  • Penanya akan meminta saya untuk memberinya nomor;
  • Saat mendengar nomor tersebut, penanya akan melakukan semacam transformasi berulang kali (misalnya, ia mungkin mengatakan sepuluh adalah tiga ) hingga akhirnya tiba di nomor 4 (di mana ia akan menyelesaikannya dengan empat adalah sihir ).
  • Setiap nomor tampaknya dapat diubah menjadi empat pada akhirnya, tidak peduli apa.

Tujuannya adalah untuk mencoba mencari tahu fungsi transformasi dan kemudian dapat menjalankan sendiri teka-teki ini dengan andal.

Solusinya

Fungsi transformasi pada setiap langkah adalah untuk

  • Catat nomor yang dimaksud,
  • Hitung jumlah huruf dalam representasi kata bahasa Inggrisnya, abaikan tanda hubung atau spasi atau "dan" (misalnya, "sepuluh" memiliki 3 huruf di dalamnya, "tiga puluh empat" memiliki 10 huruf di dalamnya, "seratus empat puluh tiga" memiliki 20 huruf di dalamnya).
  • Kembalikan jumlah huruf itu.

Untuk semua angka yang ingin saya uji, ini menyatu dengan 4. Karena "empat" juga memiliki empat huruf di dalamnya, akan ada putaran tak terbatas di sini; sebaliknya itu hanya disebut sebagai sihir dengan konvensi untuk mengakhiri urutan.

Tantangan

Tantangan Anda adalah membuat sepotong kode yang akan membaca nomor dari pengguna dan kemudian mencetak baris yang menunjukkan fungsi transformasi yang diterapkan berulang kali hingga "empat ajaib" tercapai.

Secara khusus:

  1. Solusi harus menjadi program yang lengkap di dalam dan dari dirinya sendiri. Mereka tidak bisa hanya menjadi fungsi yang mengambil faktor angka dalam input.
  2. Input harus dibaca dari input standar. (Menyalurkan dari "echo" atau menggunakan pengalihan input baik-baik saja karena itu juga berlaku dari stdin)
  3. Masukan harus dalam bentuk numerik.
  4. Untuk setiap penerapan fungsi transformasi, sebuah garis harus dicetak:, di a is b.mana a dan b adalah bentuk numerik dari angka-angka dalam transformasi.
  5. Berhenti penuh (titik) DIPERLUKAN!
  6. Baris terakhir seharusnya secara alami mengatakan 4 is magic.,.
  7. Kode tersebut harus menghasilkan keluaran yang benar untuk semua angka dari 0 hingga 99 .

Contoh:

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

Pemenangnya adalah pengiriman terpendek berdasarkan jumlah karakter kode sumber yang juga benar .

BONUS

Anda juga dapat mencoba menulis versi kode yang mencetak NAMA BAHASA INGGRIS untuk angka-angka dengan setiap aplikasi fungsi transformasi. Masukan asli masih berupa angka, tetapi baris keluaran harus memiliki bentuk kata dari angka tersebut.

(Bonus ganda untuk menggambar bentuk dengan kode Anda)

(EDIT) Beberapa klarifikasi:

  1. Saya ingin kata tersebut muncul di kedua sisi dalam semua kasus yang berlaku, mis Nine is four. Four is magic.
  2. Saya tidak peduli dengan kapitalisasi. Dan saya tidak peduli bagaimana Anda memisahkan kata token, meskipun mereka harus dipisahkan: ninety-nineoke, ninety nineoke, ninetyninetidak oke.

Saya mempertimbangkan ini sebagai kategori terpisah untuk kompetisi bonus sehubungan dengan tantangannya, jadi jika Anda melakukan ini, jangan khawatir kode Anda lebih panjang dari versi numerik.

Jangan ragu untuk mengirimkan satu solusi untuk setiap versi.

Platinum Azure
sumber
1
Seberapa tinggi angka yang harus kita tangani? <100? <1000? <1000000? <2 ** 31?
P Daddy
1
Karena ini hanya harus pergi dari 0 hingga 99, saya menduga solusi cepat dan singkat adalah dengan melakukan hardcode nilai yang dipetakan 0-99, dan kemudian mengulang sampai Anda mencapai 4. Setelah itu, microtweaking dimulai.
Beska
@P Ayah ... bagian 6 hanya mengatakan 0-99.
Beska
14
4 hanyalah sihir karena dipilih dengan lemparan dadu yang adil.
VirtuosiMedia

Jawaban:

57

GolfScript - 101 96 93 92 91 90 94 86 byte

90 → 94: Output tetap untuk kelipatan 10
94 → 86.: Kode yang direstrukturisasi. Menggunakan basis 100 untuk menghapus karakter yang tidak dapat dicetak.
86 → 85: Cast lebih pendek ke string.

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
Nabb
sumber
mengapa ini sangat jauh? lebih pendek dari cadel dan tidak menggunakan fungsi pemformatan
bawaan
36
Saya suka bagaimana kode diakhiri "magic.", itu cukup merangkumnya.
Aistina
@ Aistina: Itu mudah dilakukan dalam tantangan ini, saya pikir. :-)
Platinum Azure
9
@Aistina: haha, itu agak lucu. "omong kosong yada yada..magic"
vol7ron
1
@P Daddy The ddiekstraksi oleh )as 100dan digunakan sebagai radix untuk konversi basis.
Nabb
85

Perl, sekitar 147 karakter

Berdasarkan solusi 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
mob
sumber
1
@Platinum Azure cara ini mendapatkan masukannya adalah melalui penggunaan pop, tanpa argumen apa pun. Di luar subrutin popmenghapus, dan mengembalikan nilai terakhir @ARGVyang merupakan daftar argumen untuk program Perl. Itu bisa dengan mudah diganti shift, tapi itu menambahkan 2 karakter lain. Lihat: p3rl.org/pop
Brad Gilbert
sepertinya Anda memerlukan karakter baris baru di '.', yaitu 2 untuk \natau 1 jika Anda menghitung spasi putih di '. '(spasi menjadi literal baris baru)
vol7ron
Sedikit lebih lama, tetapi kreativitas sangat berpengaruh dalam buku saya.
Beska
@ Platinum Azure dkk: Dia mendapatkan masukannya dari stdin. Itulah cara melakukannya di Perl. (Mungkin dia mengubahnya setelah komentar Anda?)
Frank
@P Ayah: mengerang tapi tetap memberi +1 pada komentar Anda
Platinum Azure
30

Karakter Lisp 157 Umum

Versi baru yang lebih sesuai, sekarang membaca dari masukan standar dan mengabaikan spasi dan tanda hubung:

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

Dalam bentuk yang bisa dibaca manusia:

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

Dan beberapa uji coba:

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

Dan versi bonus, dengan 165 karakter:

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

Memberi

>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.
pengguna110763
sumber
5
Saya pikir "dua puluh empat" hanya memiliki 10 huruf?
kennytm
1
Angka setelah "adalah" juga harus berupa teks.
Mike DeSimone
5
kenapa ini begitu tinggi? yang lain tidak menggunakan fungsi format bawaan dan karakternya lebih sedikit
Claudiu
3
@Claudiu Karena Common Lisp mengagumkan.
Mornedhel
3
Tidak masalah berapa banyak pukulan yang Anda lakukan jika Anda tidak memasukkan bola ke dalam lubang. Orang-orang sepertinya lupa bahwa ketika mereka memberikan suara positif untuk solusi yang salah.
Mark Peters
21

Python 2.x, 144 150 154 166 karakter

Ini memisahkan angka menjadi puluhan dan satu dan menjumlahkannya. Properti pseudo-ternary a and b or cyang tidak diinginkan yang cdikembalikan jika b0 sedang disalahgunakan di sini.

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

Versi naif sebelumnya (150 karakter). Cukup encode semua panjangnya sebagai integer.

n=input()
while n-4:p=3+int('1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29',36)/10**n%10;print n,"is %d."%p;n=p
print"4 is magic."
KennyTM
sumber
Maaf, saya secara khusus ingin berhenti penuh hanya karena hal-hal seperti ini. :-) Entri yang bagus! (EDIT: Saya tidak tahu Python, tetapi bisakah Anda n,"is",p,"."? Saya pikir Anda masih menyimpan beberapa karakter jika saya menghitung dengan benar)
Platinum Azure
2
@ Plat: Itu akan menyebabkan spasi ekstra sebelum ..
kennytm
@KennyTM: Oh, ya, saya seharusnya memperhatikan itu bahkan dari cuplikannya. Ups! Yah, bagaimanapun, seperti yang saya katakan, beberapa spesifikasi dirancang khusus untuk sedikit memperumit masalah. :-)
Platinum Azure
Bisakah kita mempersingkat ini dengan menggunakan basis yang lebih tinggi dari 36?
MikeD
@ MikeD: Tidak. Dari dokumentasi Python: " Parameter dasar memberikan dasar untuk konversi (defaultnya adalah 10) dan dapat berupa bilangan bulat apa pun dalam kisaran [2, 36], atau nol." Sekarang Anda mungkin dapat menggunakan fungsi selain int(), katakan sesuatu dari structatau base64modul ...
Mike DeSimone
20

C - dengan kata-kata angka

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

Itu dia. Saya tidak berpikir saya bisa mempersingkat ini.

Semua baris baru untuk dibaca dan dapat dihapus:

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

Di bawah ini, agak tidak diubah, tetapi masih cukup sulit untuk dibaca. Lihat di bawah untuk versi yang lebih mudah dibaca.

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

Diperluas dan dikomentari:

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

Tentang string yang disandikan di dekat awal

Nama-nama angka dikompresi menggunakan skema yang sangat sederhana. Substring yang sering digunakan diganti dengan indeks satu karakter ke dalam larik nama. Sebuah "tabel pemeta" dari entri nama tambahan ditambahkan di akhir substring yang tidak digunakan secara keseluruhan pada set pertama. Pencarian bersifat rekursif: entri dapat merujuk ke entri lain.

Misalnya, nama terkompresi untuk 11 adalah elM. The print()Fungsi output karakter edan l(huruf kecil 'L', tidak nomor '1') verbatim, tapi kemudian menemukan M, jadi itu menyebut dirinya dengan indeks entri-29 (ASCII 'M' - ASCII '0') ke dalam tabel pencarian. String ini evL, sehingga mengeluarkan edan v, kemudian memanggil dirinya sendiri lagi dengan indeks entri ke-28 dalam tabel pencarian, yang merupakan en, dan merupakan keluaran kata demi kata. Ini berguna karena enjuga digunakan di eLuntuk een(digunakan setelah eightdalam eighteen), yang digunakan di tOuntuk teen(digunakan untuk setiap -teennama lain ).

Skema ini menghasilkan kompresi nama nomor yang cukup signifikan, sementara hanya membutuhkan sedikit kode untuk mendekompresi.

Koma di awal dan akhir string menjelaskan cara sederhana substring ditemukan dalam string ini. Menambahkan dua karakter di sini akan menyimpan lebih banyak karakter nanti.

Tentang penyalahgunaan main()

argvdiabaikan (dan karena itu tidak dideklarasikan dalam versi terkompresi), nilai argc diabaikan, tetapi penyimpanan digunakan kembali untuk menyimpan nomor saat ini. Ini hanya menyelamatkan saya dari keharusan mendeklarasikan variabel ekstra.

Tentang kekurangan #include

Beberapa akan mengeluh bahwa menghilangkan #include <stdio.h>itu curang. Tidak semuanya. Yang diberikan adalah program C yang sepenuhnya legal yang akan dikompilasi dengan benar pada kompiler C apa pun yang saya ketahui (meskipun dengan peringatan). Karena kekurangan protoypes untuk fungsi stdio, kompilator akan menganggap bahwa mereka adalah fungsi cdecl yang kembali int, dan akan percaya bahwa Anda tahu argumen apa yang harus diteruskan. Nilai yang dikembalikan diabaikan dalam program ini, bagaimanapun, dan semuanya adalah fungsi cdecl ("C" calling convention), dan kita memang tahu argumen apa yang harus dilewati.

Keluaran

Output seperti yang diharapkan:

0
nol adalah empat.
empat adalah keajaiban.
1
satu tiga.
tiga adalah lima.
lima adalah empat.
empat adalah keajaiban.
4
empat adalah keajaiban.
20
dua puluh enam.
enam adalah tiga.
tiga adalah lima.
lima adalah empat.
empat adalah keajaiban.
21
dua puluh satu sembilan.
sembilan adalah empat.
empat adalah keajaiban.

* Versi sebelumnya melewatkan tanda pada dua bagian dari spesifikasi: itu tidak menangani nol, dan itu mengambil masukan pada baris perintah, bukan stdin. Menangani angka nol menambahkan karakter, tetapi menggunakan stdin sebagai ganti argumen baris perintah, serta beberapa pengoptimalan lainnya menyimpan jumlah karakter yang sama, menghasilkan pencucian.

Persyaratan telah diubah untuk memperjelas bahwa kata bilangan harus dicetak pada kedua sisi "adalah". Versi baru ini memenuhi persyaratan tersebut, dan menerapkan beberapa pengoptimalan lebih banyak untuk (lebih dari) memperhitungkan ukuran ekstra yang diperlukan.

P Ayah
sumber
Ini adalah jawaban kata favorit saya dengan mudah ... Bravo, bagus. +1 untuk Anda, dan jika saya dapat memberikan dua tanda centang, saya akan melakukannya.
Platinum Azure
5
Itu menyenangkan untuk dibaca, saya rasa saya akan menggunakan angka-angka ini mulai sekarang dalam kehidupan sehari-hari. Enam, sem, delapan, sembilan, tel, elem, duabelas, enpee, fourpee, fifpee, sixpee, sevenpee, eightoh, ninepee, twelkyu ... =)
menipu
10

J, 107112 karakter

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

(Baris baru untuk keterbacaan saja)

Penggunaan dan keluaran:

    '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. 
David
sumber
15
Ini dikompilasi dalam bahasa Cina
Dr. belisarius
3
Silakan pilih wasit non-Cina
Dr. belisarius
3
@beli: 멩, 겻, 곋, 멩 adalah bahasa Korea.
kennytm
1
Istri saya (penutur asli bahasa Mandarin) mengatakan itu campuran dari bahasa Mandarin dan Korea.
Loren Pechtel
3
@belisarius: 1) Dia tidak tahu bahasa Korea. 2) Orang Cina itu omong kosong.
Loren Pechtel
10

T-SQL, 413 451 499 chars

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

(Bukannya saya serius menyarankan Anda melakukan ini ... sungguh saya hanya ingin menulis CTE)

Menggunakan:

M 95

Kembali

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.
Leon Bambrick
sumber
Tidak bisakah Anda mencetak hasil individu dan bukan mengembalikan tabel? Itu akan membuat keluaran terlihat lebih bagus.
Joey
1
Saya tidak berpikir itu menangani nol dengan benar. Bagaimana dengan sesuatu seperti ini: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 (dengan boilerplate), 308 290 286 282 280 karakter

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

Aku yakin Groovy akan menyingkirkan semua itu.

Penjelasan dan pemformatan (semua komentar, baris baru, dan spasi di depan / di belakang dihapus dalam hitungan):

Cukup lurus ke depan, tapi

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

Edit: Tidak lagi menggunakan hex, ini lebih sedikit penekanan tombol

Mark Peters
sumber
1
249 tanpa impor, kelas def atau def utama.
Mark Peters
1
Itu jahat. Saya suka basis 16. (+1)
Platinum Azure
Anda dapat menghemat satu ruang dengan menggunakan String[]asebagai ganti String[] a.
BalusC
Terima kasih @Balus, juga menghilangkan banyak hal dengan melakukan aritmatika sederhana pada karakter daripada menggunakan penguraian hex.
Mark Peters
@ Mark Peters: Bahkan lebih buruk. Saya merasa sangat vanilla dibandingkan dengan itu.
Platinum Azure
9

Windows PowerShell: 152 153 184 bytes

berdasarkan solusi sebelumnya, dengan lebih banyak pengaruh dari solusi lain

$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.'
saja
sumber
Diperbaiki untuk mendukung kelipatan 10 ("sembilan puluh" bukan "sembilan puluh nol").
Gabe
Hai @Gabe :), terima kasih; tidak punya banyak waktu untuk bermain golf belakangan ini. Namun, kutipan di sekitar $inputharus tetap ada karena Anda tidak dapat mentransmisikan pencacah langsung ke int; ini bekerja ketika melalui stringpertama :-)
Joey
8

C, 158 karakter

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

(awalnya didasarkan pada kode Python Vlad, meminjam trik dari solusi C ++ Tom Sirgedas untuk memeras beberapa karakter lagi)

versi yang diperluas:

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.");
}
Ferruccio
sumber
Sepertinya tidak berhasil untuk saya: ./magic 10 10 adalah -27. Segmentasi kesalahan
Casey
@ Casey - panggilan scanf () agak samar. Itu membaca int menjadi karakter. Saya lolos dengan itu di OSX dan di Windows itu bekerja tetapi macet saat keluar. Jadi, saya membuat n & c ints lagi. Saya menyadari saya bisa menjatuhkan kata kunci int dengan menjadikannya parameter menggunakan notasi K&R. Hasilnya lebih aman dan satu karakter lebih pendek.
Ferruccio
Anda dapat menyimpan 3 karakter dengan mengganti " 466555766" [n / 10] + d [n% 10] -96 dengan d [n% 10] - " , +++) " [n / 10]
Tom Sirgedas
6

Python, 129 133 137 148 karakter

Sebagai pemanasan, inilah versi pertama saya (meningkatkan beberapa karakter dari Python terbaik sebelumnya).

PS. Setelah beberapa reduksi, sekarang menjadi sekitar dua puluh karakter lebih pendek:

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.'
Nas Banov
sumber
6

C #: 210 Karakter.

Squished:

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

Diperluas:

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

Trik yang digunakan pendekatan ini:

  • Buat tabel pencarian untuk panjang nama nomor berdasarkan digit yang muncul di nomor tersebut.
  • Gunakan pencarian array karakter pada string, dan aritmatika aritmatika, bukan array numerik.
  • Gunakan nama kelas aliasing untuk disingkat Console.menjadiC.
  • Gunakan operator kondisional (terner) ( ?:) daripada if/else.
  • Gunakan \ndengan Writekode escape, bukanWriteLine
  • Gunakan fakta bahwa C # memiliki urutan evaluasi yang ditentukan untuk memungkinkan penugasan di dalam Writepemanggilan fungsi
  • Gunakan ekspresi tugas untuk menghilangkan pernyataan ekstra, dan dengan demikian tanda kurung ekstra
LBushkin
sumber
int[] zakan lebih pendek karena tidak membutuhkannew[]
Joey
Direvisi untuk menggunakan aritmatika karakter daripada pencarian array.
LBushkin
@ mdm20: Anda benar. Saya memiliki kesalahan dalam tabel pencarian. Diperbaiki sekarang.
LBushkin
Nah, kedua belas kalinya adalah pesona: * D
LBushkin
Sebuah quicky untuk menyimpan 5 karakter: Lebih pendek dari pengecoran "magic"untuk object, akan secara implisit memanggil ToString()pada ydengan menambahkan "". Tapi, karena +memiliki hak lebih tinggi dari ?:, Anda harus meletakkannya di benar bagian bukan palsu bagian: x!=4?y+"":"magic".
P Daddy
6

Perl: 148 karakter

(Perl: 233 181 212 206 200 199 198 185 179 149 148 karakter)

  • Hash pengecualian dipindahkan ke dalam larik unit. Ini mengakibatkan saya bisa memotong banyak karakter :-)
  • mobrule menunjukkan serangga jahat. Perbaikan cepat menambahkan 31 karakter, aduh!
  • Refactored untuk zero special case, golf ringan juga dilakukan.
  • Akses daftar langsung untuk penggunaan tunggal daripada menyimpan ke array? Yeah!
  • BEGITU BANYAK REFAKTOR hanya untuk SATU karakter berdarah. Inilah kehidupan seorang pegolf. :-(
  • Ups, perbaikan spasi putih mudah. 198 sekarang.
  • Memperbaiki beberapa kode yang berlebihan.
  • Kata kunci pengembalian terakhir rtidak perlu, dicukur lagi.
  • Pemfaktoran ulang besar-besaran per komentar; sayangnya saya hanya bisa membuatnya menjadi 149 karena saya harus memperbaiki bug yang ada di kode saya sebelumnya dan versi pemberi komentar.
  • Mencoba kata bareword "ajaib".

Mari kita mulai dengan usaha sederhana di Perl.

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

Trik:

Terlalu banyak!

Platinum Azure
sumber
ACK! Bagaimana saya tidak pernah menguji yang saya tidak akan pernah tahu.
Platinum Azure
Apakah Anda memiliki beberapa kode mati di sana? Saya tidak melihat bagaimana kasus khusus untuk nol diperlukan ketika $ u [0] adalah 4. Saya memiliki versi kode @ 166 karakter Anda yang tampaknya berfungsi, dan saya pikir ada ruang untuk mendapatkan sedikit lebih pendek dari itu.
Hobbs
@hobbs: Poin yang bagus, saya akan melihat lagi. Ceritanya adalah bahwa saya mendapat setengah jalan melalui beberapa revisi dan tiba-tiba ada yang rusak (pada titik di mana saya memilih untuk memiliki 4 -> 0). Saya pikir Anda benar pada saat ini, meskipun :-)
Platinum Azure
Saya tidak menganggap diri saya sebagai pemrogram Perl yang hebat, tetapi Anda dapat mengurangi beberapa karakter: @u=split$x,'43350435543668877988';koma Anda menggunakan 19 karakter yang tidak perlu, membelah pada undefsetiap karakter, saya gunakan $xsebagai variabel tak terdefinisi untuk menggantikan `undef` - total penghematan: 11 karakter. Juga, hapus bagian mdalam chompdan Anda mendapatkan karakter lain yang mengurangi skor Anda.
vol7ron
Berfungsi lebih baik, tetapi Anda masih dapat menghemat lebih banyak dengan kehilangan sub rseluruhnya - Anda hanya menggunakannya sekali dan Anda dapat menggantinya dengan satu terner bersarang bahkan tanpa parens. Versi saya adalah 144 chars sekarang: gist.github.com/473289
hobbs
5

JavaScript 1.8 (SpiderMonkey) - 153 Karakter

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

Pemakaian: echo 42 | js golf.js

Keluaran:

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

Dengan bonus - 364 karakter

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

Keluaran:

sembilan puluh sembilan adalah sepuluh.
sepuluh adalah tiga.
tiga adalah lima.
lima adalah empat.
empat adalah keajaiban.
gnarf
sumber
4

Haskell, 224 270 karakter

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

Dan sedikit lebih mudah dibaca -

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
Matajon
sumber
4

Versi C ++ Stdio, diminimalkan: 196 karakter

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

Versi C ++ Iostreams, diperkecil: 195 karakter

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

Asli, tidak diperkecil: 344 karakter

#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);
}
Karl von Moor
sumber
Tetap. Itu membuatnya sedikit lebih pendek juga.
Mike DeSimone
Bagus sekali. (Saya banyak tertawa pada teka-teki 20 karakter!)
Platinum Azure
Ya, itu benar-benar headbanger, sampai saya sadar bahwa itu #defineakan menjadi lebih pendek karena bisa menggantikan beberapa token.
Mike DeSimone
printf("is magic".\n)=> puts. printf("%d",p)=> puts(atoi(p)). Tidak hanya lebih pendek tapi juga lebih cepat.
Ben Voigt
2
@Mike DeSimone: Saya rasa while(p!=4)bisa disingkat menjadi while(p-4). Satu karakter utuh, saya tahu, tapi tetap saja. :-)
Platinum Azure
3

Delphi: 329 karakter

Versi Baris Tunggal:

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.

Diformat:

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.

Mungkin ruang untuk memeras lagi ... :-P

Jørn E. Angeltveit
sumber
3

C # 314 286 283 274 289 273 252 chars.

Squished:

252 

Normal:

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

Edit Dykam: Melakukan beberapa penyisipan dan perubahan dengan hati-hati:

  • Mengubah l.ToString () ke cor untuk objectsatu string "magic".
  • Membuat variabel sementara o, jadi saya bisa memindahkan lingkaran breakluar for, yaitu, menghasilkan do-while.
  • Tugaskan sebaris o, serta vtugas, melanjutkan memasukkan perhitungan ldalam argumen fungsi sama sekali, menghilangkan kebutuhan untuk l. Juga sebutkan tugas dari m.
  • Menghapus spasi di int[] x, int[]xjuga sah.
  • Mencoba mengubah array menjadi transformasi string, tetapi using System.Linqterlalu banyak untuk membuat ini menjadi perbaikan.

Edit 2 Dykam Mengubah larik int menjadi larik / string karakter, menambahkan aritmik yang tepat untuk memperbaikinya.

mdm20
sumber
Ya, lebih pendek dari versi Java.
Dykam
3

Lua, 176 Karakter

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

atau

  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."
gwell
sumber
3

C - tanpa kata angka

180 175 * 172 167 karakter

Semua baris baru untuk dibaca dan dapat dihapus:

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

Sedikit tidak diubah:

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

* Versi sebelumnya melewatkan tanda pada dua bagian dari spesifikasi: itu tidak menangani nol, dan itu mengambil masukan pada baris perintah, bukan stdin. Menangani nol karakter yang ditambahkan, tetapi menggunakan stdin alih-alih argumen baris perintah disimpan lebih banyak lagi, menghasilkan penghematan bersih.

P Ayah
sumber
2

perl, 123 122 karakter

Baru menyadari bahwa tidak ada persyaratan untuk mengeluarkan ke STDOUT, jadi keluarkan ke STDERR sebagai gantinya dan keluarkan karakter lain.

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

Dan, versi yang mengembalikan angka terbilang:

279 278 276 280 karakter

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

Meskipun memenuhi spesifikasi, itu tidak 100% diformat dengan baik. Ini mengembalikan spasi ekstra setelah angka yang diakhiri dengan nol. Spesifikasi mengatakan:

"Saya tidak peduli bagaimana Anda memisahkan kata token, meskipun mereka harus dipisahkan"

Itu agak buruk. Versi yang lebih tepat di

282 281 279 283 karakter

@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/
Pengguna 5 revs397369
sumber
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"
Vlad
sumber
4
Saya suka itu. Anda mungkin bisa sedikit mengencangkannya.
Josh K
@Vlad: Input harus dibaca dari stdin, bukan dari argumen. Itu berarti Anda bisa menggunakan N = input()(atau raw_input()) dan menghilangkan sysbarang - barang itu.
kennytm
Anda juga bisa membuat yang kecil termasuk remaja, maka pernyataan if hanya akan menjadi "if n <20: return Smalls [n]". Smalls akan tetap bekerja untuk> = 20 case, karena modulus oleh 10.
Jon Smock
5
Ini harus menjadi pertama kalinya saya melihat (opsional penuh) she-bangdalam jawaban kode-golf ;-)
ChristopheD
Sepertinya awal yang baik ... Pasti perkuat, bahkan Python tidak membutuhkan SEMUA spasi ini. :-) Selain itu, seperti yang ditunjukkan Ferruccio, 0 tidak berfungsi, khususnya tampaknya masuk ke loop tak terbatas.
Platinum Azure
1

C ++, 171 karakter (#include dihilangkan)

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.");}
Tom Sirgedas
sumber
Saya rasa jika Anda menganggap ini sebagai C, Anda dapat menghindari kebutuhan #includekarena fungsinya hanya akan dianggap mengambil intparameter. Anda bahkan dapat menyimpan pukulan dengan melakukan mainpengembalian int.
Gabe
1

Ruby, 164 karakter

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

diterjemahkan:

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."
Jon Smock
sumber
Solusi Ruby yang bagus, membuatnya tetap sederhana. :-) (+1)
Platinum Azure
Menjaga agar tetap sederhana bukanlah alasan untuk menyimpannya terlalu lama ;-)
Joey
Saya pikir Anda dapat mengganti 'if n == 0' dengan 'if! N'
Vincent
2
Di Ruby? Saya selalu berpikir bahwa semua nilai kecuali salah dan nihil dievaluasi menjadi benar :-(
Platinum Azure
1

Lua 185 190 199

menambahkan titik, menambahkan io.read, menghapus () pada cetakan terakhir

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

dengan jeda baris

 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.'
Nick
sumber
Membutuhkan n=io.read()(+11 karakter) untuk mematuhi aturan untuk membaca angka dari input standar. Mengubah print('4 is magic.')ke print'4 is magic.'akan menghemat 2 karakter. Menghapus ;setelahnya )akan menghemat 1 karakter. Penggunaan printkoma sepertinya curang, tetapi spesifikasinya tidak jelas. Sebaiknya ubah print(n,'is',m,'.')untuk menyimpan 2 karakter.
gwell
Apakah koma dirender sebagai baris baru di Lua berdiri sendiri? Sudah lama sejak saya menggunakannya.
Nick Van Brunt
Koma dirender sebagai tab.
baik
0

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

//////////// pengujian ////////////////

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

////// Hasil /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic
Pengembang
sumber
4
@wallacoloo: Solusi buruk untuk bahasa yang buruk: D
Thomas Eding
5
Atau 178 karakter yang jauh lebih pendek:$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
Lelucon yang bagus. :-D Diprogram dengan sangat baik.
Tom Pažourek
0

Perl - 130 karakter


5.12.1 (130 karakter) 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 karakter) 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/


Ubah Sejarah:

20100714:2223- mengembalikan perubahan pada perhatian mobrule , tetapi ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]), yang merupakan # karakter yang sama, tetapi saya melakukannya jika seseorang mungkin melihat cara untuk memperbaikinya

20100714:0041- split//,'...''...'=~/./g
20100714:0025- ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340- while$_until/\D/+ menghapus tanda kurung yang tidak perlu
20100713:xxxx- $=<>;chop;$_=pop;- milik mobrule


Catatan: Saya lelah memperbaiki jawaban orang lain di komentar, jadi sekarang saya serakah dan bisa menambahkan perubahan saya di sini :) Ini adalah pemisahan dari jawaban Platinum Azure - sebagian kredit untuk Hobbs , mobrule , dan Platinum Azure .

vol7ron
sumber
Ketika Anda menyingkirkan $_%10&&...konstruksinya, Anda melanggar spesifikasi untuk input 20,30,40, ...
mob
+1 Bagus sekali. Anda telah keluar dari stdin menjadi args :-(
Platinum Azure
Benar, diganti dengan ARGV, yang diisi oleh STDIN:) atau .. echo bar | xargs perl foo.pl, secara teknis disalurkan dari echo ke args untuk perl :)
vol7ron
0

Perl Tak Tahu Malu dengan Kata Angka (329 karakter)

Diadaptasi secara langsung dari kode P Daddy's C, dengan beberapa penyesuaian untuk p()membuatnya melakukan hal yang sama menggunakan primitif Perl, bukan C, dan mainloop yang sebagian besar ditulis ulang. Lihat penjelasannya. Baris baru semuanya opsional.

@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

Catatan tambahan: sayang sekali perl printhanya mengembalikan true / false; jika mengembalikan hitungan, saya akan menghemat 7 pukulan.

hobbs
sumber
0

Ruby, 141 karakter:

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}
Krzysztof
sumber
-7
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
pengguna368038
sumber