Sederhanakan fraksi lanjutan


21

Fraksi lanjutan adalah ekspresi yang menggambarkan fraksi secara iteratif. Mereka dapat direpresentasikan secara grafis:

masukkan deskripsi gambar di sini

Atau mereka dapat direpresentasikan sebagai daftar nilai: [a0; a1, a2, a3, ... an]

Tantangan:

ambil nomor pangkalan: dan daftar nilai penyebut: dan sederhanakan fraksi lanjutan menjadi pecahan rasional yang disederhanakan: kembalikan atau cetak pembilang dan penyebut secara terpisah.a0[a1, a2, a3, ... an]

Contoh:

  • √19 : [4;2,1,3,1,2]: 170/39
  • ℯ: [1;0,1,1,2,1,1]: 19/7
  • π: [3;7,15,1,292,1]: 104348/33215
  • ϕ: [1;1,1,1,1,1]: 13/8

Contoh implementasi: (python)

def foo(base, sequence):
    numerator = 1
    denominator = sequence[-1]
    for d in sequence[-2::-1]:
        temp = denominator
        denominator = d * denominator + numerator
        numerator = temp
    return numerator + base * denominator, denominator

Kemenangan:

kode terpendek dalam byte: --tidak ada builtin yang melakukan seluruh masalah diizinkan--


Anda harus membuat kalimat ini lebih jelas, "dan menyederhanakan fraksi lanjutan menjadi fraksi tunggal"; kecuali jika Anda bermaksud kata-kata yang berarti hasil 2.002dapat dinyatakan sebagai 2002/1000. Secara teknis itu adalah "fraksi tunggal", Anda mungkin ingin mengatakan, "fraksi tunggal, dalam bentuk yang paling sederhana."
Magic Octopus Urn

@carusocomputing point diambil .. walaupun saya tidak akan merasa terlalu buruk tentang 2/4 (atau serupa) karena masih menyederhanakan struktur fraksi ganda menjadi fraksi tunggal
Aaron

Hmm ... Saya pikir ada cara untuk mengeksploitasi itu, tetapi dengan jawaban 13 byte golfscript, saya mungkin harus menggunakan MATL untuk menang.
Magic Octopus Urn

@carusocomputing saya akan mengatakan pergi untuk itu ... Jika Anda dapat mengalahkan jawaban 13 byte, itu akan luar biasa
Aaron

Anda dapat membuat pi berhenti lebih awal - 355/113.
Thorbjørn Ravn Andersen

Jawaban:


15

J, 8 5 byte

Sama seperti ini , tetapi menggunakan built-in untuk rasional.

Argumen adalah {a0, a1, a2, a3, ...} sebagai daftar angka rasional presisi J yang diperluas. Hasilnya adalah fraksi sebagai angka rasional presisi J yang diperluas.

(+%)/

(+%) plus-yang-kebalikan dari

/ pengurangan lebih

Cobalah online!

-3 berkat mil .


Jika Anda mengambil input sebagai daftar bilangan bulat, Anda dapat menyimpan 3 byte. Anda juga menggunakan divisi APL dalam penjelasannya.
mil

@miles, terima kasih. Tidak bisa lebih dekat dengan larangan bawaan dari itu. Sayang sekali J tidak memiliki karakter komposisi pengait seperti Dyalog APL .
Adám

Tautan coba J online rusak
Chiel ten Brinke

@ChieltenBrinke Terima kasih. Tetap.
Adám

12

Haskell, 37 36 18 byte

foldr1$(.(1/)).(+)

Fungsi ini mengharapkan Ratiotipe Haskell sebagai input. Contoh penggunaan:

Prelude Data.Ratio> ( foldr1$(.(1/)).(+) )  [4%1,2,1,3,1,2] 
170 % 39

Catatan: satu eksplisit Ratiodalam daftar input ( 4%1) sudah cukup, sistem tipe menemukan bahwa yang lain juga harus Ratios.

Sunting: @Lynn menyimpan satu byte. Terima kasih!

Sunting II: menghapus import(lihat diskusi ini tentang meta ).


1
Oooh, kasing tepi yang bagus. Fungsi itu sendiri adalah polimorfik, jadi tidak perlu import. Namun untuk menyebutnya, Anda harus memberi makan Ratiountuk itu yang memang membutuhkan import. Haruskah saya menambahkan importke jumlah byte atau tidak?
nimi

1
Itu terdengar seperti pertanyaan yang bagus untuk meta.
Martin Ender

Saya tidak pernah menggunakan Haskell, jadi perbaiki saya jika saya salah, tetapi jika python equivelent adalah: from fractions import Fractionuntuk melakukan operasi dengan Fractionobjek, pernyataan impor juga dihitung.
Aaron


@ Harun: masalahnya adalah: definisi fungsi tidak perlu impor, karena itu polimorfik. Ketika Anda ingin menyebutnya, Anda perlu memberikan nomor jenis Ratioyang hanya dapat dibangun melalui %, yang membutuhkan impor. Biasanya kita tidak menghitung byte untuk memanggil overhead, hanya untuk fungsi itu sendiri.
nimi

11

GolfScript , 13 byte

~]-1%{\-1?+}*

Cobalah online!

Yay untuk alasan tersembunyi GolfScript . :)

Penjelasan

Satu-satunya jenis nomor "resmi" GolfScript adalah bilangan bulat. Tetapi operator eksponensial tidak memberikan hasilnya ke integer dan dengan mudah hasil asli dari eksponensial integer di Ruby (bahasa juru bahasa GolfScript) adalah bilangan rasional. Jadi kita bisa dengan mudah mendapatkan pecahan dengan menaikkan sesuatu ke kekuatan -1. Dengan mudah, kami tetap ingin balasan ...

~]     # Evaluate input and wrap all a_i in a list.
-1%    # Reverse the list so that a_n is at the start and a_0 at the end.
{      # Fold... (apply this block to each element from a_n-1 down to a_0, with
       # the previous result on the stack)
  \    #   Swap previous result with current a_i.
  -1?  #   Raise previous result to the power of -1, computing its reciprocal
       #   as a rational number.
  +    #   Add a_i.
}*

11

Mathematica, 23 22 byte

Fold[#2+1/#&]@*Reverse

Pada dasarnya port jawaban GolfScript saya . Berikut ini beberapa alternatif:

Untuk 24 byte, kita dapat menulis fungsi variadic rekursif:

f@n_=n
n_~f~m__:=n+1/f@m

Untuk 21 byte, kita bahkan dapat menentukan "operator variadic", tapi konvensi panggilannya akan begitu aneh, bahwa aku enggan untuk menghitung satu ini:

±n_=n
n_ ±m__:=n+1/±m

Anda harus memanggil ini dengan urutan nilai input, misalnya ±Sequence[3, 7, 15, 1, 292, 1]atau ±##&[3, 7, 15, 1, 292, 1].

Dan juga untuk 21 byte, akan ada built-in (dilarang):

FromContinuedFraction

10

LabVIEW, 36 byte setara

Implementasi naif lurus ke depan dengan menggunakan algoritma OP. Apakah ada cara yang lebih baik untuk melakukan ini?

masukkan deskripsi gambar di sini


5
Gelar teknik listrik Anda menunjukkan.
Magic Octopus Mm

1
@ijustlovemath Props, tapi ..... relevan
Aaron

Ya itu bahasa yang kontroversial untuk memastikan. Saya melihat LabVIEW sebagai "Aku benci matematika" dari dunia programmer. Masalahnya bukan matematika itu sendiri, tetapi bagaimana itu diajarkan (atau seringkali kurangnya mengajar sama sekali).
ijustlovemath

6

Dyalog APL , 10 byte

Bahkan tidak menggunakan built-in untuk rasional.

Membawa {a 0 , a 1 , a 2 , 3 , ...} sebagai argumen, menghasilkan {denominator, numerator}.

1(,÷∨)+∘÷/

1(,÷∨) 1-prepended-to dibagi oleh GCD 1 dan

+∘÷ plus-the-kebalikan dari

/ pengurangan lebih

TryAPL online!


6

Python 2, 62 byte

a=d=0
b=c=1
for n in input():a,b=b,n*b+a;c,d=d,n*d+c
print b,d

Sayangnya ini bukan golfy (lihat jawaban @ xnor untuk lebih pendek), tetapi menghitung fraksi tanpa perlu membalikkan input. Ini menggunakan pendekatan "tabel ajaib" untuk konvergen - mengingat dua fraksi terakhir a/cdan b/d, fraksi berikutnya adalah (n*b+a)/(n*c+d).

Misalnya, untuk pi:

          3    7    15     1      292        1

  0   1   3   22   333   355   103993   104348
  1   0   1    7   106   113    33102    33215

Kita bisa melihat bahwa 15*22 + 3 = 333, 15*7 + 1 = 106, 1*333 + 22 = 355, 1*106 + 7 = 113, dll


4

M, 5 byte

Ṛİ+¥/

Input adalah daftar nilai [a0, a1, ..., aN]dan menghasilkan bilangan rasional.

Cobalah online! atau Verifikasi semua kasus uji.

Penjelasan

Ṛİ+¥/  Input: list A
Ṛ      Reverse A
    /  Reduce A from left to right using
   ¥     A dyadic chain
 İ         Take the reciprocal of the left value
  +        Add the reciprocal to the right value
       Return and print implicitly

1
Apa ini? Beberapa dialek Jelly baru?
Adám

@miles sebenarnya 9 byte maaf :(
Aaron

@ Adam Ini adalah garpu lama Jelly yang diperuntukkan untuk matematika dan simbolis. Ini repo Github -nya .
mil

1
@ Harun M menggunakan halaman kode yang sama dengan Jelly, dan dapat dikodekan menggunakan byte untuk setiap karakter.
mil

@miles OK, ditambahkan .
Adám

4

Haskell, 30 byte

foldr(\h(n,d)->(h*n+d,n))(1,0)

Secara rekursif menambahkan setiap lapisan keluar, memperbarui n/dke h+(1/(n/d)), yang sama dengan h+d/natau (h*n+d)/n. Fraksi disimpan sebagai tuple (num,denom). Bagian awal dari (1,0)flips 0/1yang mana adalah 0.


3

Python, 50 byte

f=lambda l,n=1,d=0:l and f(l,l.pop()*n+d,n)or(n,d)

Membangun fraksi lanjutan dari akhir daftar mundur, berulang kali memperbarui fraksi n/dpada elemen terakhir xsebagai n/d -> 1+1/(n/d) == (x*n+d)/n.


3

 Common Lisp, 54

Lipatan kanan agak verbose:

(lambda(s)(reduce(lambda(a r)(+(/ r)a))s :from-end t))

Tes

PASS  NAME  ACTUAL               EXPECTED
===============================================
T     √19   170/39               170/39              
T     ℯ     19/7                 19/7                
T     π     104348/33215         104348/33215        
T     ϕ     13/8                 13/8                

2

Julia (53 Bytes)

Ini adalah pertama kalinya saya menggunakan Julia, jika saya mengabaikan iterator yang bisa saya gunakan untuk kehilangan beberapa byte lagi, beri tahu saya. Berikut adalah petunjuk bagi siapa saja yang tidak tahu bahasa apa yang harus dipilih untuk tantangan khusus ini: https://en.wikipedia.org/wiki/Rational_data_type

f(x,c)=(a=0;for b in x[end:-1:1];a=1//(b+a);end;a+c;)
  • Membalikkan array input.
  • Iterasi melalui itu dengan pembagian rasional.
  • Tambahkan c ke hasil desimal.

Anda dapat menyimpan dua byte dengan mendefinisikan operator (mis. ) alih-alih fungsi
Tasos Papastylianou

juga, ganti for for sebentar dan pop:x∘c=(a=0;while x!=[];a=1//(pop!(x)+a);end;a+c;)
Tasos Papastylianou

1
25: x->foldr((x,y)->x+1//y,x)(sama dengan solusi Haskell). penggunaan:(x->foldr((x,y)->x+1//y,x))([4//1,2,1,3,1,2])
Fengyang Wang

Ooo ... Fungsi lipat terbalik? Itu indah! Saya tidak pantas menerima pujian untuk itu meskipun haha.
Magic Octopus Mm

2

Javascript (ES6), 55 byte

s=>eval('for(F=[1,0];s+"";)F=[s.pop()*F[0]+F[1],F[0]]')

Uji kasus

var f =
s=>eval('for(F=[1,0];s+"";)F=[s.pop()*F[0]+F[1],F[0]]')

console.log(f([4, 2, 1, 3, 1, 2]));
console.log(f([1, 0, 1, 1, 2, 1, 1]));
console.log(f([3, 7, 15, 1, 292, 1]));
console.log(f([1, 1, 1, 1, 1, 1]));


2

CJam , 18 16 byte

XUq~W%{2$*+\}/]p

Penerjemah online .

XU                  Push 1 and 0 to the stack
  q~W%              Push input, eval and reverse it
      {     }/      For each n in the reversed input...
       2$             Copy numerator
         *+           Calculate n*denominator + numerator
           \          Swap numerator and denominator
              ]p   Wrap in array and output

2

05AB1E , 19 17 byte

R¬V¦vyY*X+YUV}YX)

Penjelasan

Input diambil sebagai daftar angka

                     # variable X is initialized as 1
R¬V¦                 # reverse the list, remove the first item and store it in variable Y
    v        }       # for each item N left in list
     yY*X+  V        # store N*Y+X in Y
          YU         # store Y in X
              YX)    # wrap X and Y in a list

Cobalah online!


2

JavaScript (ES6), 44 byte

a=>a.reduceRight(([n,d],v)=>[v*n+d,n],[1,0])

1

Javascript (ES6), 50 byte

f=(s,n=1,d=s.pop())=>s+""?f(s,d,s.pop()*d+n):[d,n]

Ini berkat jawaban Arnauld, sebelum melihatnya saya terjebak pada 66 byte:

f=(b,s,i=s.length-1,n=1,d=s[i])=>i?f(b,s,--i,d,s[i]*d+n):[n+b*d,d]

Contoh:
Panggilan: f([1, 0, 1, 1, 2, 1, 1])
Keluaran:Array [ 19, 7 ]


1

Perl 6 , 24 byte

{[R[&(1/*+*)]](@_).nude}

Penjelasan:

  • 1 / * + *adalah lambda dengan dua parameter ( *) yang mengambil kebalikan dari yang pertama, dan menambahkan yang kedua. (mengembalikan Tikus )

  • R[&(…)]menggunakan itu seolah-olah itu operator infiks dan membalikkannya.
    (termasuk membuatnya asosiatif dengan benar)

  • […](@_) mengambil itu dan menggunakannya untuk mengurangi input.

  • … .nudemengembalikan nu merator dan de nominator of the Rat .

  • { … }menjadikannya lambda blok kosong dengan parameter implisit @_.

Pemakaian:

say {[R[&(1/*+*)]](@_).nude}(3,7,15,1,292,1) #*/# (104348 33215)

my &code = {[R[&(1/*+*)]](@_).nude}; # stupid highlighter */

say code 4,2,1,3,1,2;    # (170 39)
say code 1,0,1,1,2,1,1;  # (19 7)
say code 1,1,1,1,1,1;    # (13 8)

1

Zephyr , 145 byte

input n as Integer
set a to Array(n)
for i from 1to n
input a[i]as Integer
next
set r to a[n]
for i from 1to n-1
set r to(/r)+a[n-i]
next
print r

Zephyr adalah bahasa pemrograman pertama yang pernah saya buat. Itu dirancang untuk menjadi intuitif dan memiliki sintaksis bersih - bukan dengan mengorbankan singkatnya. Mengapa saya bermain golf dengannya, Anda bertanya? Karena, tidak seperti bahasa apa pun yang saya tulis sejak itu, ia memiliki tipe bawaan Fraction. Anda bahkan dapat menggunakan operator divisi /sebagai operator unary untuk "terbalik" (fitur yang saya pinjam untuk Pip).

Sekarang, ada batasan yang signifikan. Masalah terbesar untuk tantangan ini adalah bahwa array harus didefinisikan dengan ukuran tetap, yang berarti bahwa program dimulai dengan membaca ukuran array dari pengguna. (Saya harap ini baik-baik saja; alternatifnya adalah ukuran hardcoding.) Ada juga masalah kecil yang tidak ada diutamakan operator, artinya ekspresi multi-operator harus memiliki tanda kurung.

Berikut ini contoh yang dijalankan:

C:\Zephyr> python zephyr.py contfrac.zeph
6
1
1
1
1
1
1
13/8

1

Ruby, 34 byte

->a{a.reverse.inject{|b,i|i+1r/b}}

Ini melakukan lipatan kanan (dengan membalik dan kemudian melipat kiri), menambahkan setiap elemen ke 1 di atas total running (elemen di sebelah kanan). Ruby memiliki tipe Rasional, yang sangat bagus. Dan rasional literal adalah nomor dengan akhiran r.


1

Stax , 4 byte

╣╩┼►

Jalankan dan debug itu

Sekecil itu, itu bukan built-in. Rasional bawaan cukup membantu. Dibongkar ke ascii, programnya adalah rksu+.

  1. Membalikkan array.
  2. Lipat array menggunakan (a, b) => (a + 1/b).

1

APL (NARS), 15 + 1 karakter, 30 + 2 byte

{1=≢⍵:↑⍵⋄+∘÷/⍵}

Terjemahan dalam Apl (Nars) dari solusi Adam J ... input yang diizinkan untuk fungsi tersebut adalah semua daftar bilangan bulat, di mana elemen pertama akan bertipe rasional. Uji:

  f←{1=≢⍵:↑⍵⋄+∘÷/⍵}      
  f 4x 2 1 3 1 2
170r39 
  f 1x 0 1 1 2 1 1
19r7 
  f 3x 7 15 1 292 1
104348r33215 
  f 1x 1 1 1 1 1
13r8 
  f 3x 89 888 999 11 222 373 7282 9272 3839 2828 
158824716824887954093160207727r52744031585005490644982548907 
  f ,0x
0 
  f ,9x
9 

jadi itu akan menjadi 15 karakter sebagai panjang fungsi dan 1 karakter untuk "x" untuk memasukkan tipe input yang saya inginkan dan keluar dari tipe yang saya inginkan ...

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.