Pertanyaan ini tidak perlu diterapkan pada penghentian desimal saja - desimal berulang juga dapat dikonversi menjadi pecahan melalui suatu algoritma.
Tugas Anda adalah membuat program yang mengambil desimal berulang sebagai input, dan menampilkan pembilang dan penyebut yang sesuai (dalam istilah terendah) yang menghasilkan ekspansi desimal itu. Pecahan yang lebih besar dari 1 harus dinyatakan sebagai pecahan yang tidak tepat 9/5
. Anda dapat berasumsi bahwa input akan positif.
Desimal berulang akan diberikan dalam format ini:
5.3.87
dengan semua setelah titik kedua diulang, seperti ini:
5.3878787878787...
Program Anda akan menghasilkan dua bilangan bulat yang mewakili pembilang dan penyebut, dipisahkan oleh garis miring (atau bentuk yang setara dalam bahasa Anda jika Anda tidak menampilkan teks biasa):
889/165
Perhatikan bahwa penghentian desimal tidak akan memiliki apa pun setelah titik kedua, dan desimal tanpa bagian desimal yang tidak berulang tidak akan memiliki apa pun di antara kedua titik.
Uji kasus
Kasing uji ini mencakup semua kasing yang diperlukan:
0..3 = 1/3
0.0.3 = 1/30
0.00.3 = 1/300
0.6875. = 11/16
1.8. = 9/5
2.. = 2/1
5..09 = 56/11
0.1.6 = 1/6
2..142857 = 15/7
0.01041.6 = 1/96
0.2.283950617 = 37/162
0.000000.1 = 1/9000000
0..9 = 1/1
0.0.9 = 1/10
0.24.9 = 1/4
Jika diinginkan, Anda juga dapat mengasumsikan bahwa pecahan tanpa bagian bilangan bulat tidak memiliki apa pun di sebelah kiri titik pertama. Anda dapat mengujinya dengan kasus uji opsional ini:
.25. = 1/4
.1.6 = 1/6
..09 = 1/11
.. = 0/1
sumber
9/99
?(in lowest terms)
yaitu fraksi harus disederhanakan.13
bukan13/1
?1.9999...
dan output ini2/1
1.9999.
adalah19999/10000
, untuk memenuhi2/1
kebutuhan Anda1..9
, bukan?Jawaban:
Dyalog APL (
75736968 karakter)Ini adalah upaya lain dan kelima (kemungkinan besar yang terakhir saya); Saya menghabiskan hari itu mencoba menulis beberapa kode lebih pendek dari 80 karakter dan sepenuhnya konsisten dengan aturan. Tantangan ini membuat hariku!
Saya akhirnya mendapat garis APL yang terdiri dari 75 karakter, bekerja dengan Dyalog APL (tetapi tidak pada halaman penerjemah online karena menggunakan fungsi
⍎
eksekusi ), yang adalah sebagai berikut:Tentu saja saya bisa membuatnya sedikit lebih pendek, tetapi kasus-kasus khusus di mana satu, dua atau tiga bidang hilang. Kode saya bahkan dapat menangani
..
case input.Saya tahu APL sulit dibaca, dan karena orang-orang senang memahami bagaimana sepotong kode benar-benar berfungsi, berikut adalah beberapa penjelasannya. Pada dasarnya, saya menghitung penyebut akhir dalam variabel D dan pembilang akhir dalam variabel N.
APL diuraikan dari kanan ke kiri.
I←
).P←'.'=
). Misalnya '1.2.3' akan dipetakan ke 0 1 0 1 0.10⊥
); sekarang '1.2.3' adalah 1010.1-⍨
atau dengan¯1+
, di sini saya memilih yang kedua). Sekarang '1.2.3' adalah 1009.⍕
), dua digit awal dihapus (2↓
), yang membuat 09 dari contoh awal kami '1.2.3'; string dibalik (⌽
).'0',
tetapi saya melakukannya untuk menghindari kesalahan ketika bidang kedua dan pertiga keduanya kosong. String dikonversi kembali ke angka (⍎
) dan disimpan dalam D, yang merupakan penyebut kecuali ketika kedua bidang terakhir kosong, karena dalam kasus tersebut D sama dengan 0.D←D+0=
potongan kode set D untuk 1 jika saat ini nol, dan sekarang D berisi denominator (sebelum pembagian GCD namun).×
) dengan konten string awal I hingga titik kedua(⍎'0',I/⍨2>+\P)
yang dimulai dari P lagi (0 1 0 1 0 dalam contoh saya), menambahkan angka berurutan dengan mengumpulkannya (yang membuat 0 1 1 2 2 dalam contoh saya), periksa nilai mana yang lebih kecil dari 2 (membuat vektor boolean 1 1 1 0 0), dan mengambil karakter yang sesuai di I; 0 lainnya ditambahkan di depan string untuk mencegah jebakan lain (jika dua bidang awal kosong) dan keseluruhan dikonversi ke angka.(⍎'0',1↓I/⍨2=+\P)
, yang mengambil P lagi, menambahkan dengan mengumpulkan lagi, memeriksa nilai mana yang sama dengan 2 (lihat penjelasan sebelumnya), mengambil karakter, menghapus yang pertama yang merupakan titik , menambahkan karakter awal 0 pencegahan dan mengkonversi ke nomor.sunting: Ini adalah perbaikan untuk 73 karakter:
Gagasan hack ini adalah menghitung pertama kasus di mana penambahan kumulatif memiliki nilai sama dengan 2, menyimpannya untuk nanti dan membalikkan topeng bitwise ini untuk mendapatkan kasus pertama; dengan demikian menghitung kasus selanjutnya membutuhkan lebih sedikit karakter.
sunting: Ini adalah perbaikan lain untuk 69 karakter:
Gagasan peretasan ini adalah untuk menyematkan kasus khusus yang paling rumit sebagai kode APL dalam string yang akan dievaluasi (pada tahap konversi string ke angka).
sunting: Ini adalah perbaikan lain untuk 68 karakter:
Gagasan peretasan ini adalah untuk mengganti menambahkan -1 ke nilai untuk mengurangi 1 ke nilai itu dengan operasi mengurangkan nilai itu ke 1 lalu menghapus satu karakter lebih kemudian di awal (yang akan menjadi tanda minus).
sunting: Perubahan kosmetik:
Tidak ada peningkatan dalam ukuran, tetapi lebih puas untuk mendapatkan fungsi maksimal dari kode yang akan dievaluasi.
sumber
INVALID TOKEN
. Apa kamu tahu kenapa?I
): lihat permalinkPerl 6 (
93101100806866 byte)Ukurannya ditingkatkan untuk menangani apa-apa, bukan hanya gagal. Mouq diusulkan untuk digunakan
$/
, jadi sekarang sedang digunakan, dan kodenya lebih pendek 20 byte. Ayiko mengusulkan mengganti/
dengan, sehingga kode ini bahkan lebih pendek (dengan 12 bytes). Kemudian Mouq mengusulkan penggantian
chars
dengancomb
(dalam konteks numerik, mereka identik, karena daftar karakter setelah konversi ke angka adalah jumlah karakter).Output sampel:
sumber
0..09
kembali1/11
, tetapi0.0.09
kembali1/110
.0.1 + 0.2 == 0.3
dalam Perl 6.$/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude
:)J (
859089 karakter)Fungsi asli saya, yang 5 karakter lebih pendek dari yang kedua, memiliki beberapa bug: itu tidak menghasilkan bilangan bulat sebagai "n / 1" dan itu memberikan jawaban yang salah pada angka dengan lebih dari selusin digit. Berikut adalah fungsi yang diperbaiki di J yang juga menggabungkan saran Eelvex untuk menyimpan karakter:
Ini menerima string dan mengembalikan string. Inilah sesi sampel:
sumber
0/1
dan3/1
inf dua kasus uji pertama, Lihat komentar ini('0','x',~])
dan simpan satu byte.C, 171
Cukup lama. Bisa lebih jauh dikurangi. Tidak
scanf
, yang benar-benar tidak bisa mengatasinya jika tidak ada angka di antara titik-titik. Tidak adastrtol
. Hanya angka yang berderak:Uji:
sumber
DC (tidak sepenuhnya umum, disingkat menjadi 76 karakter)
Tidak sepenuhnya umum, tapi tolong, pertimbangkan saya melakukannya dengan salah satu hal tertua di dunia:
Sunting: Saya mengedit solusi saya; itu tidak lebih umum, tetapi sedikit lebih pendek:
Gunakan sebagai:
Bidang pertama tidak diperlukan:
tidak apa-apa.
Bidang kedua dan haus membutuhkan setidaknya satu digit
sumber
Javascript, 203
Terlalu lama, tapi tetap menyenangkan. Baris baru karena titik koma tidak dapat dibaca.
sumber
889/NaN
ketika saya menjalankan5.3.87
... Apakah saya melakukan sesuatu yang salah?"889/165"
ke konsol. Bagaimana Anda menjalankannya? @rafaelcastrocoutob=1
bagian dalamprompt()
.f=(P(10,s[2].length)-1)*P(10,l),f=f?f:1
=>f=(P(10,s[2].length)-1)*P(10,l)||1
J (metode berbeda)
Solusi lain berdasarkan metode yang sangat berbeda; kali ini sepenuhnya umum; hanya yang hilang adalah penyebut 1 ketika integer dikirimkan:
sumber
GolfScript (67 karakter)
NB Ini mendukung bagian integer kosong.
Jika string adalah dari bentuk
'n.p.q'
maka nilainya adalah din + p/E + q/(DE) = ((nD + p)E + q)/DE
manaD = 10^(len p)
danE = 10^(len q) - 1
, kecuali kapanlen q = 0
, dalam hal iniE = 1
(untuk menghindari pembagian dengan 0).Pembedahan:
Demo online yang mensimulasikan menjalankan program dengan masing-masing input tes, satu per satu.
sumber
0.1.
Python
Tanpa perpustakaan - 156 karakter
Menggunakan
fractions
- 127 karaktersumber
fractions
Versi cetak hal-hal seperti "Fraksi (7, 5)" bukan "7/5", bukan?_=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),
ValueError: need more than 1 value to unpack
print
gunakanstr
saat tersedia, tidakrepr
. Ini adalah hasil akhir saya: puu.sh/7w64w.png_=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)
harus masuk semua dalam satu baris.Mathematica, 143
Seperti biasa, Mathematica menawarkan banyak fungsi tingkat tinggi untuk melakukan pekerjaan itu, tetapi memberi mereka nama verbal.
Output sampel untuk ditambahkan nanti ketika saya punya waktu.
sumber
n/1
berkurangn
? Saya akan menambahkan ekstra ~ 50 byte untuk mengkonversi bilangan bulat nanti.FromDigits
jadi saya memutuskan untuk mempostingnya juga.Ruby - 112
Ini adalah eksperimen pertama saya dengan ruby, jadi silakan menyarankan perbaikan.
sumber
If you wish
,. Saya tidak berharap, jadi saya tidak mendukung pecahan tanpa kelompok angka 1 atau 3. Namun saya mendukung pecahan yang tidak memiliki kelompok digit kedua, yang cocok dengan spesifikasi.C, 164
Ini mirip dengan solusi C orion, meskipun saya melakukannya dari awal. Namun saya akui mencuri sejumlah optimasinya. Ini tidak jauh lebih pendek, tetapi menangani 0,25. = 1/4 dan 0.000000.1 = 1/9000000.
sumber
Dua jawaban python tidak menggunakan pustaka. Pertama menangani input opsional tanpa digit sebelum yang pertama. dan 162 karakter
Kedua tidak menangani apa-apa sebelum digit pertama tetapi menangani semua input yang diperlukan dengan benar dan 150 karakter
sumber
Haskell
sumber
span
untuk mengimplementasikan, menambahkan alias pendek untuk fungsi, menghapus ruang jika memungkinkan.import Data.Ratio v=span(/='.');w=tail;l=length;f n=(r x)%1+(r y)%p+(r z)%((10^t-1)*p)where{(x,b)=v n;(y,d)=v(w b);z=w d;p=10^(l y);r""=0;r n=read n;t=if null z then 9 else l z}
- 178 karakter, turun dari 321. NBTrue
adalah sinonim untukotherwise
,null z
adalahlength z==0
JavaScript (ECMASCript 6)
180175Meskipun ini bukan pemenang yang jelas untuk 300 karunia ... ini adalah yang terpendek yang bisa saya buat:
P
fungsi Power dengan mengubahnya untuk+("1e"+a)
bukannyaMath.pow(10,a)
menyimpan beberapa karakter ...sumber
Mathematica 175
Sebagian besar rutinitas dilakukan untuk memijat input. Sekitar 50 karakter digunakan untuk menangani bilangan bulat.
Contohnya
Lebih banyak contoh:
Bagaimana hal itu biasanya dicapai dalam Mathematica
FromDigits
dapat memperoleh sebagian kecil dari desimal berulang berulang, asalkan input dari bentuk tertentu. Bilangan bulat ditampilkan sebagai bilangan bulat.sumber
J (96 karakter)
Saya tidak menggunakan simbol garis miring sebagai pemisah (tetapi solusi dalam Mathematica juga tidak karena ia menggunakan representasi grafis yang lebih baik); dalam bahasa J fraksi ditampilkan dengan
r
sebagai/
:sumber
APL (tidak sepenuhnya umum)
Tidak sepenuhnya umum (seperti solusi saya untuk dc); bekerja dengan Dyalog APL (tetapi tidak pada versi online Dyalog APL, tidak yakin mengapa):
Bidang pertama adalah opsional, tetapi setidaknya satu digit diperlukan untuk kedua bidang lainnya.
sumber
JavaScript (189)
Contoh:
Memasukkan:
Keluaran:
sumber
C (420 karakter seperti yang tertulis; lebih sedikit setelah menghapus spasi yang tidak perlu)
Perhatikan bahwa ini mengasumsikan 64-bit
long
(mis. 64 bit Linux); itu akan gagal untuk kasus uji0.2.283950617
pada sistem menggunakan 32-bitlong
. Ini dapat diperbaiki dengan mengorbankan beberapa karakter dengan mengubah jenisnyalong long
dan mengubahprintf
format string yang sesuai.sumber
'0'
ke48
.switch
pernyataan sebagaiif(c==46) n[++i]=1; else d[i]=10*d[i]+c-48,n[i]*=10;
.GTB , 81
Contoh
sumber
GTB
tautan di atas jika Anda tidak percaya kepada saya. Anda akan mendapatkan beberapa barang terkompresi untuk program berpemilik, kemudian Anda akan mencari program itu dan menemukan bahwa situs yang mengklaim menyediakan unduhan mengatakan itu tidak tersedia. Jadi bagaimana kita mengkompilasinya?