Stern-Brocot sekansına göre rasyonel sayının çıktısını al


30

Stern-Brocot dizisi bir Fibonnaci benzeri dizisi olarak inşa edilebilir aşağıdaki gibidir:

  1. İle sırayı başlat s(1) = s(2) = 1
  2. Sayacı ayarla n = 1
  3. Ekleme s(n) + s(n+1)sekansına
  4. Ekleme s(n+1)sekansına
  5. Artış n, 3. adıma geri dönün

Bu eşdeğerdir:

s (n) = \ begin {cases} 1 & \ textrm {if} n = 1 \ s (\ frak n 2) & \ textrm {if} n \ textrm {, hatta} \ s (\ frac {n-1 } 2) + s (\ frac {n + 1} 2) & \ textrm {else} \ end {cases}

Diğer özellikler arasında, Stern-Brocot sekansı, her olası pozitif rasyonel sayıyı üretmek için kullanılabilir. Her rasyonel sayı tam olarak bir kez üretilecek ve daima en basit haliyle görünecektir; örneğin, 1/3sırayla 4 rasyonel sayı, ancak eşdeğer sayılardır 2/6, 3/9hiç görünmez vb.

Rasyonel sayıyı r(n) = s(n) / s(n+1), s(n)yukarıda açıklandığı gibi, nt Stern-Brocot numarası olarak tanımlayabiliriz.

Buradaki zorluk, Stern-Brocot dizisi kullanılarak oluşturulan rasyonel sayının çıktısını alacak bir program veya işlev yazmaktır.

  • Yukarıda açıklanan algoritmalar 1 indekslidir; Girişiniz 0 dizinli ise, lütfen cevabınızı belirtiniz.
  • Açıklanan algoritmalar sadece açıklama amaçlıdır, çıktı istediğiniz şekilde türetilebilir (sabit kodlama dışında)
  • Giriş, STDIN, fonksiyon parametreleri veya başka herhangi bir makul giriş mekanizması aracılığıyla olabilir.
  • Çıkış, STDOUT, konsol, fonksiyon dönüş değeri veya başka herhangi bir makul çıkış akımı olabilir.
  • Çıktı , Stern-Brocot sekansındaki ilgili girişlerin a/bolduğu ave formdaki bir dize gibi olmalıdır b. Fraksiyonun çıkıştan önce değerlendirilmesine izin verilmemektedir. Örneğin, giriş için 12, çıkış olmalıdır 2/5değil 0.4.
  • Standart boşluklara izin verilmez

Bu , bayt cinsinden en kısa cevap kazanacak.

Test durumları

Buradaki test vakaları 1 indekslidir.

n    r(n)
--  ------
1    1/1
2    1/2
3    2/1
4    1/3
5    3/2
6    2/3
7    3/1
8    1/4
9    4/3
10   3/5
11   5/2
12   2/5
13   5/3
14   3/4
15   4/1
16   1/5
17   5/4
18   4/7
19   7/3
20   3/8
50   7/12
100  7/19
1000 11/39

OEIS girişi: A002487 Sıralamayı tartışan
Excellent Numberphile video: Sonsuz Kesirler


Çıktı Trues yerine 1s kullanabilir mi?
Loovjo

1
@Loovjo Hayır, True/2geçerli bir kesir değil (ilgilendiğim kadarıyla). Bir yana, Trueher zaman değil 1- bazı diller -1biti operatörlerini uygularken olası hataları önlemek için kullanır. [kaynak belirtilmeli]
Sok


2

1
@Sok ama Python'da Trueeşittir 1ve True/2olacaktır 1/2.
Sızdıran Rahibe

Yanıtlar:


3

Jöle , 14 bayt

3ẋḶŒpḄċ
’Ç”/⁸Ç

Çevrimiçi deneyin!

Öyle görünüyor ki @Dennis tarafından kabul edilen cevabı ve aynı dilde bunu yenebilirim. Bu, OEIS'den bir formül kullanarak çalışır: hiperbinaryerde ifade etme yollarının sayısı (eksi 1) (yani rakam olarak 0, 1, 2 ile ikili). Çoğu Jelly programından farklı olarak (tam program veya işlev olarak çalışır), bu sadece tam program olarak çalışır (çünkü çıktının bir kısmını stdout'a gönderir ve geri kalanı döndürür; tam program olarak kullanıldığında dönüş değeri stdout'a dolaylı olarak gönderilir, bu nedenle tüm çıktılar aynı yerdedir, ancak bu bir işlev sunumu için işe yaramaz).

Programın bu sürümü çok verimsiz. İlk satırın hemen arkasına n koyarak, 2ⁿ'ye kadar tüm girişler için çalışan daha hızlı bir program oluşturabilirsiniz ; programın O ( n × 3ⁿ) performansı var, bu nedenle n'nin küçük tutulması burada oldukça önemlidir. Yazılı olarak program n girişine eşit, açıkça yeterince büyük, ama aynı zamanda neredeyse her durumda açıkça çok büyük (ama hey, bayt tasarrufu sağlar).

açıklama

Jelly açıklamalarımda her zamanki gibi, parantez içindeki metin (örn. {the input}) Orijinal programdaki eksik işlenenler nedeniyle Jelly tarafından otomatik olarak doldurulan bir şey gösterir.

Yardımcı fonksiyon (hesaplar n yani inci payda, N + 1th pay):

3ẋḶŒpḄċ
3ẋ       3, repeated a number of times equal to {the argument}
  Ḷ      Map 3 to [0, 1, 2]
   Œp    Take the cartesian product of that list
     Ḅ   Convert binary (or in this case hyperbinary) to a number
      ċ  Count number of occurrences of {the argument} in the resulting list

İlk beş bayt temelde sadece belirli bir uzunluğa kadar olan tüm olası hiperbiner sayıları üretiyor, örneğin giriş 3 ile , [[0,1,2], [0,1,2], [0,1,2 ]] bu yüzden kartezyen ürün [[0,0,0], [0,0,1], [0,0,2], [0,1,0],…, [2,2,1], [2,2,2]]. temel olarak sadece son girişi 1, sonda çarpma sayısını 2, çarpma karşılığını 4, vb. ile çarpar ve sonra ekler; Bu normalde ikiliyi ondalık değere dönüştürmek için kullanılsa da, 2. basamağı gayet iyi idare edebilir ve böylece hiperbinary için de işe yarar. Ardından, sıraya uygun bir giriş elde etmek için girişin sonuç listesinde göründüğü sayıyı sayarız. (Neyse ki, pay ve payda aynı sırayı takip eder).

Ana program (pay ve paydaş için sorar ve çıktıyı formatlar):

’Ç”/⁸Ç
’Ç      Helper function (Ç), run on {the input} minus 1 (‘)
  ”/    {Output that to stdout}; start again with the constant '/'
    ⁸Ç  {Output that to stdout}; then run the helper function (Ç) on the input (⁸)

Her nasılsa, asıl sorunu çözmek için G / Ç ile başa çıkmak için neredeyse bayt harcayan programlar yazmaya devam ediyorum…


Güzel keder, verimsiz olduğu konusunda şaka yapmıyordun - TIO 12’nin tamamlanması 20s’de ve tamamen 13 kez çıktı! Tüm test durumlarını doğrulayamadığım halde kabul edildi.
Sok

11

CJam (20 bayt)

1_{_@_2$%2*-+}ri*'/\

Çevrimiçi demo . Bunun 0 indeksli olduğunu unutmayın. 1 indeksli yapmak için, ilk 1_önce ile değiştirin T1.

teşrih

Bu Moshe Newman nedeniyle karakterizasyonu kullanır

kesir a(n+1)/a(n+2), önceki kesirden şu şekilde elde edilebilir a(n)/a(n+1) = x:1/(2*floor(x) + 1 - x)

Eğer x = s/töyleyse alırız

  1 / (2 * floor(s/t) + 1 - s/t)
= t / (2 * t * floor(s/t) + t - s)
= t / (2 * (s - s%t) + t - s)
= t / (s + t - 2 * (s % t))

Şimdi, bunu kabul edersek sve tcoprime ise

  gcd(t, s + t - 2 * (s % t))
= gcd(t, s - 2 * (s % t))
= gcd(t, -(s % t))
= 1

Bu yüzden a(n+2) = a(n) + a(n+1) - 2 * (a(n) % a(n+1))mükemmel çalışıyor.

1_           e# s=1, t=1
{            e# Loop...
  _@_2$%2*-+ e#   s, t = t, s + t - 2 * (s % t)
}
ri*          e# ...n times
'/\          e# Separate s and t with a /

Buradaki metodolojiyi seviyorum, harika cevap!
Sok

OEIS girişinde daha ileri kaydırırsanız, Mike Stay'in o formülü zaten gönderdiğini göreceksiniz.
Neil

11

Haskell, 78 77 65 58 bayt

Utanmadan optimize edilmiş yaklaşımı çalmak bize şunları verir:

(s#t)0=show s++'/':show t
(s#t)n=t#(s+t-2*mod s t)$n-1
1#1

Bir infix işlevi kullanarak birkaç baytlık golf oynamak için @nimi sayesinde!

(Yine de) 0 tabanlı indeksleme kullanır.


Eski yaklaşım:

s=(!!)(1:1:f 0)
f n=s n+s(n+1):s(n+1):(f$n+1)
r n=show(s n)++'/':(show.s$n+1)

Çıktı formatına lanet olsun ... Ve indeksleme operatörleri. EDIT: Ve öncelik.

Eğlenceli gerçek: eğer heterojen listeler bir şey olsaydı, son satır şöyle olabilirdi:

r n=show>>=[s!!n,'/',s!!(n+1)]

s!!nf n|x<-s!!n=x:x+x+1:f$n+1
Bağlamak

@Likonikon s!!n+1değil (s!!n)+1ama s!!(n+1)bu yüzden bunu yapamam: /
ThreeFx

Aslında, bu açık olmalıydı. Sadece ... s!!norada çok fazla !
Laikoni

1
Sen kullanabilirsiniz ++'/':(show.s$n+1)içinde rbir bayt kaydedin.
nimi

1
Bir bir infix fonksiyonuna geçin: (s#t)0=show..., (s#t)n=t#(s+t-2*mod s t)$n-1, r=1#1. Hatta atlayabilirsiniz r, yani son satır sadece 1#1.
nimi

6

Jöle , 16 bayt

L‘Hị⁸Sṭ
1Ç¡ṫ-j”/

Çevrimiçi deneyin! veya tüm test durumlarını doğrulayın .

Nasıl çalışır

1Ç¡ṫ-j”/  Main link. Argument: n

1         Set the return value to 1.
 Ç¡       Apply the helper link n times.
   ṫ-     Tail -1; extract the last two items.
     j”/  Join, separating by a slash.


L‘Hị⁸Sṭ   Helper link. Argument: A (array)

L         Get the length of A.
 ‘        Add 1 to compute the next index.
  H       Halve.
   ị⁸     Retrieve the item(s) of A at those indices.
          If the index in non-integer, ị floors and ceils the index, then retrieves
          the items at both indices.
    S     Compute the sum of the retrieved item(s).
     ṭ    Tack; append the result to A.

5

05AB1E , 34 33 25 23 bayt

XX‚¹GÂ2£DO¸s¦ìì¨}R2£'/ý

açıklama

XX‚                        # push [1,1]
   ¹G           }          # input-1 times do
     Â                     # bifurcate
      2£                   # take first 2 elements of reversed list
        DO¸                # duplicate and sum 1st copy, s(n)+s(n+1)
           s¦              # cut away the first element of 2nd copy, s(n)
             ìì            # prepend both to list
               ¨           # remove last item in list
                 R2£       # reverse and take the first 2 elements
                    '/ý    # format output
                           # implicitly print

Çevrimiçi deneyin

Adnan sayesinde 2 bayt kaydedildi.


Bu da ?: çalışır mı XX‚¹GÂ2£DO¸s¦ìì¨}R2£'/ý.
Adnan

@Adnan Gerçekten. Bunun ýbir listeyi biçimlendirebileceğini unuttum . Güzel.
Emigna

4

MATL , 20 bayt

FT+"@:qtPXnosV47]xhh

Bu , OEIS sayfasında verilen binom katsayıları açısından karakterizasyonu kullanır .

Algoritma tüm sayılar için teoride çalışır, ancak pratikte MATL'nin sayısal kesinliği ile sınırlıdır ve bu nedenle büyük girdiler için çalışmaz. Sonuç, 20en azından girişlere kadar doğrudur .

Çevrimiçi deneyin!

açıklama

FT+      % Implicitly take input n. Add [0 1] element-wise. Gives [n n+1]
"        % For each k in [n n+1]
  @:q    %   Push range [0 1 ... k-1]
  tP     %   Duplicate and flip: push [k-1 ... 1 0]
  Xn     %   Binomial coefficient, element-wise. Gives an array
  os     %   Number of odd entries in that array
  V      %   Convert from number to string
  47     %   Push 47, which is ASCII for '\'
]        % End for each
x        % Remove second 47
hh       % Concatenate horizontally twice. Automatically transforms 47 into '\'
         % Implicitly display

4

Python 2, 85 81 bayt

x,s=input(),[1,1]
for i in range(x):s+=s[i]+s[i+1],s[i+1]
print`s[x-1]`+"/"+`s[x]`

Bu gönderi 1 indeksli.

Özyinelemeli bir işlev kullanarak, 85 bayt:

s=lambda x:int(x<1)or x%2 and s(x/2)or s(-~x/2)+s(~-x/2)
lambda x:`s(x)`+"/"+`s(x+1)`

Gibi bir çıktı True/2kabul edilebilirse, 81 bayttan bir tanesi:

s=lambda x:x<1 or x%2 and s(x/2)or s(-~x/2)+s(~-x/2)
lambda x:`s(x)`+"/"+`s(x+1)`

3

JavaScript (ES6), 43 bayt

f=(i,n=0,d=1)=>i?f(i-1,d,n+d-n%d*2):n+'/'+d

1 endeksli; n=10 indeksli için değiştirin . Bağlantılı OEIS sayfası, önceki her iki terim açısından her terim için faydalı bir tekrarlama ilişkisine sahiptir; Önceki fraksiyon açısından her fraksiyon için bir nüks olarak yorumladım. Ne yazık ki satır içi TeX'imiz yok, bu yüzden bu formatların nasıl olduğunu öğrenmek için başka bir siteye yapıştırmanız yeterlidir:

birbbbir+b-2(birşıkb)

3

Python 2, 66 bayt

f=lambda n:1/n or f(n/2)+n%2*f(-~n/2)
lambda n:`f(n)`+'/'+`f(n+1)`

Özyinelemeli formülü kullanır.


3

C (GCC), 79 bayt

0 tabanlı endeksleme kullanır.

s(n){return!n?:n%2?s(n/2):s(-~n/2)+s(~-n/2);}r(n){printf("%d/%d",s(n),s(n+1));}

Ideone


1
x?:ybir gcc uzantısıdır.
rici

3

Aslında, 18 bayt

11,`│;a%τ@-+`nk'/j

Çevrimiçi deneyin!

Bu çözüm Peter'in formülünü kullanıyor ve aynı şekilde 0 indeksli. Bir bayt için Leaky Nun'a teşekkürler.

Açıklama:

11,`│;a%τ@-+`nk'/j
11                  push 1, 1
  ,`│;a%τ@-+`n      do the following n times (where n is the input):
                      stack: [t s]
    │                 duplicate the entire stack ([t s t s])
     ;                dupe t ([t t s t s])
      a               invert the stack ([s t s t t])
       %              s % t ([s%t s t t])
        τ             multiply by 2 ([2*(s%t) s t t])
         @-           subtract from s ([s-2*(s%t) s t])
           +          add to t ([t+s-2*(s%t) t])
                      in effect, this is s,t = t,s+t-2*(s%t)
              k'/j  push as a list, join with "/"


@LeakyNun OP'den bir açıklama gelene kadar bu gelişmeye devam edeceğim.
Mego

2

MATL , 32 30 bayt

1i:"tt@TF-)sw@)v]tGq)V47bG)Vhh

Bu doğrudan bir yaklaşım kullanır: sekansın yeterli üyesini oluşturur, istenen ikisini seçer ve çıktıyı formatlar.

Çevrimiçi deneyin!


2

R, 93 bayt

f=function(n)ifelse(n<3,1,ifelse(n%%2,f(n/2-1/2)+f(n/2+1/2),f(n/2)))
g=function(n)f(n)/f(n+1)

Kelimenin tam anlamıyla en basit uygulama. Biraz golf oynamaya çalışıyorum.


2

m4, 131 bayt

define(s,`ifelse($1,1,1,eval($1%2),0,`s(eval($1/2))',`eval(s(eval(($1-1)/2))+s(eval(($1+1)/2)))')')define(r,`s($1)/s(eval($1+1))')

Makro tanımlar rşekilde r(n)değerlendirir spec göre yöntem. Hiç golf oynamıyorum, sadece formülü kodladım.


2

Ruby, 49 bayt

Bu 0 dizinli ve Peter Taylor'ın formülünü kullanıyor. Golf önerileri kabul edilir.

->n{s=t=1;n.times{s,t=t,s+t-2*(s%t)};"#{s}/#{t}"}

1

> <> , 34 + 2 = 36 bayt

Peter Taylor'ın mükemmel cevabını gördükten sonra, test yanıtımı yeniden yazdım (utanç verici bir 82 bayt, çok sakar özyinelemeyi kullanarak).

&01\$n"/"on;
&?!\:@}:{:@+@%2*-&1-:

Girişte yığında olmasını bekliyor, böylece -vbayrak için +2 bayt . Çevrimiçi deneyin!


1

Oktav, 90 bayt

function f(i)S=[1 1];for(j=1:i/2)S=[S S(j)+S(j+1) (j+1)];end;printf("%d/%d",S(i),S(i+1));end

1

C #, 91 90 bayt

n=>{Func<int,int>s=_=>_;s=m=>1==m?m:s(m/2)+(0==m%2?0:s(m/2+1));return$"{s(n)}/{s(n+1)}";};

Atmalarını Func<int, string>. Bu özyinelemeli uygulama.

Ungolfed:

n => 
{
    Func<int,int> s = _ => _; // s needs to be set to use recursively. _=>_ is the same byte count as null and looks cooler.
    s = m =>
        1 == m ? m               // s(1) = 1
        : s(m/2) + (0 == m%2 ? 0 // s(m) = s(m/2) for even
        : s(m/2+1));             // s(m) = s(m/2) + s(m/2+1) for odd
    return $"{s(n)}/{s(n+1)}";
};

Düzenleme: -1 bayt. C # enterpolasyonlu dizgiler arasında returnve arasında bir boşluğa ihtiyaç duymaz $.



1

J, 29 bayt

([,'/',])&":&([:+/2|]!&i.-)>:

kullanım

Büyük n değerleri, xgenişletilmiş tam sayıların kullanımını belirten bir sonek gerektirir .

   f =: ([,'/',])&":&([:+/2|]!&i.-)>:
   f 1
1/1
   f 10
3/5
   f 50
7/12
   f 100x
7/19
   f 1000x
11/39

100"büyük bir değer" olarak sayılır?
dcsohl

1
@dcsohl Bu yöntemde, binom katsayıları hesaplanır ve n = 100 için hesaplanan en büyüğü C (72, 28) = 75553695443676829680> 2 ^ 64'tür ve kayan nokta değerlerini önlemek için genişletilmiş tam sayılar gerektirir.
miller

1

Mathematica, 108 106 101 bayt

(s={1,1};n=1;a=AppendTo;t=ToString;Do[a[s,s[[n]]+s[[++n]]];a[s,s[[n]]],#];t@s[[n-1]]<>"/"<>t@s[[n]])&

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.