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:
- Solusi harus menjadi program yang lengkap di dalam dan dari dirinya sendiri. Mereka tidak bisa hanya menjadi fungsi yang mengambil faktor angka dalam input.
- Input harus dibaca dari input standar. (Menyalurkan dari "echo" atau menggunakan pengalihan input baik-baik saja karena itu juga berlaku dari stdin)
- Masukan harus dalam bentuk numerik.
- 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. - Berhenti penuh (titik) DIPERLUKAN!
- Baris terakhir seharusnya secara alami mengatakan
4 is magic.
,. - 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:
- Saya ingin kata tersebut muncul di kedua sisi dalam semua kasus yang berlaku, mis
Nine is four. Four is magic.
- Saya tidak peduli dengan kapitalisasi. Dan saya tidak peduli bagaimana Anda memisahkan kata token, meskipun mereka harus dipisahkan:
ninety-nine
oke,ninety nine
oke,ninetynine
tidak 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.
sumber
Jawaban:
GolfScript -
10196939291909486 byte90 → 94
: Output tetap untuk kelipatan 1094 → 86
.: Kode yang direstrukturisasi. Menggunakan basis 100 untuk menghapus karakter yang tidak dapat dicetak.86 → 85
: Cast lebih pendek ke string.sumber
"magic."
, itu cukup merangkumnya.d
diekstraksi oleh)
as100
dan digunakan sebagai radix untuk konversi basis.Perl, sekitar 147 karakter
Berdasarkan solusi Platinum Azure:
sumber
pop
, tanpa argumen apa pun. Di luar subrutinpop
menghapus, dan mengembalikan nilai terakhir@ARGV
yang merupakan daftar argumen untuk program Perl. Itu bisa dengan mudah digantishift
, tapi itu menambahkan 2 karakter lain. Lihat: p3rl.org/pop'.'
, yaitu 2 untuk\n
atau 1 jika Anda menghitung spasi putih di'. '
(spasi menjadi literal baris baru)Karakter Lisp 157 Umum
Versi baru yang lebih sesuai, sekarang membaca dari masukan standar dan mengabaikan spasi dan tanda hubung:
Dalam bentuk yang bisa dibaca manusia:
Dan beberapa uji coba:
Dan versi bonus, dengan 165 karakter:
Memberi
sumber
Python 2.x, 144
150154166karakterIni memisahkan angka menjadi puluhan dan satu dan menjumlahkannya. Properti pseudo-ternary
a and b or c
yang tidak diinginkan yangc
dikembalikan jikab
0 sedang disalahgunakan di sini.Versi naif sebelumnya (150 karakter). Cukup encode semua panjangnya sebagai integer.
sumber
n,"is",p,"."
? Saya pikir Anda masih menyimpan beberapa karakter jika saya menghitung dengan benar).
.int()
, katakan sesuatu daristruct
ataubase64
modul ...C - dengan kata-kata angka
445431427421399386371359 *356354 †348347 karakterItu 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
. Theprint()
Fungsi output karaktere
danl
(huruf kecil 'L', tidak nomor '1') verbatim, tapi kemudian menemukanM
, jadi itu menyebut dirinya dengan indeks entri-29 (ASCII 'M' - ASCII '0') ke dalam tabel pencarian. String inievL
, sehingga mengeluarkane
danv
, kemudian memanggil dirinya sendiri lagi dengan indeks entri ke-28 dalam tabel pencarian, yang merupakanen
, dan merupakan keluaran kata demi kata. Ini berguna karenaen
juga digunakan dieL
untukeen
(digunakan setelaheight
dalameighteen
), yang digunakan ditO
untukteen
(digunakan untuk setiap-teen
nama 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()
argv
diabaikan (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 kembaliint
, 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:
* 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.
sumber
J,
107112karakter(Baris baru untuk keterbacaan saja)
Penggunaan dan keluaran:
sumber
T-SQL, 413
451499chars(Bukannya saya serius menyarankan Anda melakukan ini ... sungguh saya hanya ingin menulis CTE)
Menggunakan:
Kembali
sumber
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
Java (dengan boilerplate),
308290286282280 karakterAku 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
Edit: Tidak lagi menggunakan hex, ini lebih sedikit penekanan tombol
sumber
String[]a
sebagai gantiString[] a
.Windows PowerShell: 152
153184bytesberdasarkan solusi sebelumnya, dengan lebih banyak pengaruh dari solusi lain
sumber
$input
harus tetap ada karena Anda tidak dapat mentransmisikan pencacah langsung keint
; ini bekerja ketika melaluistring
pertama :-)C, 158 karakter
(awalnya didasarkan pada kode Python Vlad, meminjam trik dari solusi C ++ Tom Sirgedas untuk memeras beberapa karakter lagi)
versi yang diperluas:
sumber
Python, 129
133137148karakterSebagai pemanasan, inilah versi pertama saya (meningkatkan beberapa karakter dari Python terbaik sebelumnya).
PS. Setelah beberapa reduksi, sekarang menjadi sekitar dua puluh karakter lebih pendek:
sumber
C #: 210 Karakter.
Squished:
Diperluas:
Trik yang digunakan pendekatan ini:
Console.
menjadiC.
?:
) daripadaif/else
.\n
denganWrite
kode escape, bukanWriteLine
Write
pemanggilan fungsisumber
int[] z
akan lebih pendek karena tidak membutuhkannew[]
"magic"
untukobject
, akan secara implisit memanggilToString()
paday
dengan menambahkan""
. Tapi, karena+
memiliki hak lebih tinggi dari?:
, Anda harus meletakkannya di benar bagian bukan palsu bagian:x!=4?y+"":"magic"
.Perl: 148 karakter
(Perl:
233181212206200199198185179149148 karakter)r
tidak perlu, dicukur lagi.Mari kita mulai dengan usaha sederhana di Perl.
Trik:
Terlalu banyak!
sumber
@u=split$x,'43350435543668877988';
koma Anda menggunakan 19 karakter yang tidak perlu, membelah padaundef
setiap karakter, saya gunakan$x
sebagai variabel tak terdefinisi untuk menggantikan `undef` - total penghematan: 11 karakter. Juga, hapus bagianm
dalamchomp
dan Anda mendapatkan karakter lain yang mengurangi skor Anda.sub r
seluruhnya - Anda hanya menggunakannya sekali dan Anda dapat menggantinya dengan satu terner bersarang bahkan tanpa parens. Versi saya adalah 144 chars sekarang: gist.github.com/473289JavaScript 1.8 (SpiderMonkey) - 153 Karakter
Pemakaian:
echo 42 | js golf.js
Keluaran:
Dengan bonus - 364 karakter
Keluaran:
sumber
Haskell, 224
270karakterDan sedikit lebih mudah dibaca -
sumber
Versi C ++ Stdio, diminimalkan: 196 karakter
Versi C ++ Iostreams, diperkecil: 195 karakter
Asli, tidak diperkecil: 344 karakter
sumber
#define
akan menjadi lebih pendek karena bisa menggantikan beberapa token.printf("is magic".\n)
=>puts
.printf("%d",p)
=>puts(atoi(p))
. Tidak hanya lebih pendek tapi juga lebih cepat.while(p!=4)
bisa disingkat menjadiwhile(p-4)
. Satu karakter utuh, saya tahu, tapi tetap saja. :-)Delphi: 329 karakter
Versi Baris Tunggal:
Diformat:
Mungkin ruang untuk memeras lagi ... :-P
sumber
C #
314286283274289273252 chars.Squished:
Normal:
Edit Dykam: Melakukan beberapa penyisipan dan perubahan dengan hati-hati:
object
satustring
"magic"
.o
, jadi saya bisa memindahkan lingkaranbreak
luarfor
, yaitu, menghasilkando-while
.o
, sertav
tugas, melanjutkan memasukkan perhitunganl
dalam argumen fungsi sama sekali, menghilangkan kebutuhan untukl
. Juga sebutkan tugas darim
.int[] x
,int[]x
juga sah.using System.Linq
terlalu banyak untuk membuat ini menjadi perbaikan.Edit 2 Dykam Mengubah larik int menjadi larik / string karakter, menambahkan aritmik yang tepat untuk memperbaikinya.
sumber
Lua, 176 Karakter
atau
sumber
C - tanpa kata angka
180175*172167 karakterSemua 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.
sumber
perl,
123122 karakterBaru menyadari bahwa tidak ada persyaratan untuk mengeluarkan ke STDOUT, jadi keluarkan ke STDERR sebagai gantinya dan keluarkan karakter lain.
Dan, versi yang mengembalikan angka terbilang:
279278276280 karakterMeskipun memenuhi spesifikasi, itu tidak 100% diformat dengan baik. Ini mengembalikan spasi ekstra setelah angka yang diakhiri dengan nol. Spesifikasi mengatakan:
Itu agak buruk. Versi yang lebih tepat di
282281279283 karaktersumber
Python:
sumber
N = input()
(atauraw_input()
) dan menghilangkansys
barang - barang itu.she-bang
dalam jawaban kode-golf ;-)C ++, 171 karakter (#include dihilangkan)
sumber
#include
karena fungsinya hanya akan dianggap mengambilint
parameter. Anda bahkan dapat menyimpan pukulan dengan melakukanmain
pengembalianint
.Ruby, 164 karakter
diterjemahkan:
sumber
Lua
185190199menambahkan titik, menambahkan io.read, menghapus () pada cetakan terakhir
dengan jeda baris
sumber
n=io.read()
(+11 karakter) untuk mematuhi aturan untuk membaca angka dari input standar. Mengubahprint('4 is magic.')
keprint'4 is magic.'
akan menghemat 2 karakter. Menghapus;
setelahnya)
akan menghemat 1 karakter. Penggunaanprint
koma sepertinya curang, tetapi spesifikasinya tidak jelas. Sebaiknya ubahprint(n,'is',m,'.')
untuk menyimpan 2 karakter.Kode PhP
//////////// pengujian ////////////////
////// Hasil /////////
sumber
$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";
Perl - 130 karakter
5.12.1 (130 karakter)
1211231321361405.10.1 (134 karakter)
125127136140144Ubah 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 memperbaikinya20100714:0041
-split//,'...'
→'...'=~/./g
20100714:0025
-($_%10&&$u[$_%10])
→$u[$_%10]
20100713:2340
-while$_
→until/\D/
+ menghapus tanda kurung yang tidak perlu20100713:xxxx
-$=<>;chop;
→$_=pop;
- milik mobruleCatatan: 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 .
sumber
$_%10&&...
konstruksinya, Anda melanggar spesifikasi untuk input 20,30,40, ...ARGV
, yang diisi olehSTDIN
:) atau ..echo bar | xargs perl foo.pl
, secara teknis disalurkan dari echo ke args untuk perl :)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.Catatan tambahan: sayang sekali perl
print
hanya mengembalikan true / false; jika mengembalikan hitungan, saya akan menghemat 7 pukulan.sumber
Ruby, 141 karakter:
sumber
sumber