Bir sayının devam eden kısmını ikiye katlayın


21

Göreviniz verilen xçıktıdır 2*x. Kolay değil mi!? Ancak bir mandal var: x(muhtemelen sonsuz) sürekli bir kesir olarak verilecek ve çıktı sürekli bir kesir olmalıdır. Giriş, derecesi en fazla 2 olan gerçek bir cebirsel sayı olarak garanti edilir.

Giriş : devam eden kesri x. Bu 3 bölüme ayrılmıştır: tamsayı, önek ve yinelenen bölüm. Tamsayı kısmı tek bir tamsayıdan oluşur. Ön ek ve yinelenen kısım, ön eki açıklayan ve sürekli kesimin bir kısmını tekrar eden pozitif tam sayı dizileridir (muhtemelen boş). Örneğin, girdi (3, [1], [2, 4])sürekli kesri temsil eder [3; 1, 2, 4, 2, 4, ...].

Tekrarlanan kısım boşsa, bu rasyonel bir sayıya işaret eder. Örneğin, (3, [1, 2], [])temsil eder [3; 1, 2] = 11/3. Sen (yani rasyonel sayının iki formu kabul etmelidir (3, [1, 1, 1], [])olup, [3; 1, 1, 1] = 11/3ayrıca geçerli giriş olmalıdır).

Çıktı : Girdi ile aynı formatta, girişin iki katı devam eden kısmını yazdırın. Çıktı rasyonel ise, devam eden kesirden herhangi birini ya da çıktısını alabilirsiniz. Cevap doğru cevaba eşdeğer olduğu sürece, sorun yoktur; “sıkıştırma” gerekli değildir, bu yüzden sonsuz kısım biraz “kontrolsüz” [1; 4, 2, 3, 2, 3...]olabilir (örneğin yazılabilir (1, [4], [2, 3])veya yazılabilir (1, [4, 2, 3], [2, 3])). Tüm cevaplar kesin olmalı.

Test durumları : Form sütununa kolaylık sağlamak için verilmiştir.

Input               Exact Form       Output
(0, [] [])          0                (0, [] []) or (-1, [1], [])
(-5, [1, 1], [])    -4.5             (-9, [], []) or (-10, [1], [])
(3, [1, 2], [])     11/3             (7, [3], []) or (7, [2, 1], [])
(1, [], [2])        sqrt(2)          (2, [], [1, 4])
(-1, [2], [2, 1])   -1/sqrt(3)       (-2, [1, 5], [2, 6])

Ve son olarak biraz daha büyük bir test durumu hassas sağlamak için: (0, [1], [6, 1, 3, 1, 42, 1, 3, 1, 6, 2]) --> (1, [], [1, 2, 1, 8, 1, 20, 1, 8, 1, 2, 1, 2]).

En kısa kod kazanır!

İpucu : Burada açıklandığı gibi sürekli kesirler üzerinde aritmetik işlemi oldukça basit bir şekilde gerçekleştirebilirsiniz . Devam eden bir kesriyi iki katına çıkarmak, bu algoritmanın sadece özel bir durumudur (zor kısım, devam eden kesimin tekrar ettiği zamanları bulmak olabilir).



@Pavel Hayır, girişi yalnızca tamsayı, önek ve yinelenen kısımlara dayanarak belirtmelisiniz Sqrt[2].
soktinpk

Üzgünüm, bu benim açımdan bir hataydı. İşte girdi olarak gerçek sürekli kesir ile bağlantı: tio.run/##y00syUjNTSzJTE78n2b73zk/ryQzrzQ1xa0oMbkkMz8v2kjLrSg/…
Pavel

1
[3; 1, 1, 1]Kullanacağımız (3, [1, 1, 1], [])giriş biçiminde olacaktır - bu yüzden sadece netliği sağlamak için soru muhtemelen bu biçimde (üçüncü paragrafta) belirtmelidir.
sundar - Reinstate Monica,

2
Çıktının ne kadar küçültülmesi gerektiği konusunda hangi kısıtlamalar var? Örneğin (-2, [1, 5, 2], [6, 2])girdi için kabul edilebilir çıktı olabilir (-1, [2], [2, 1])mi? Ne dersiniz (-2, [1, 5, 2, 6, 2, 6], [2, 6])?
Peter Taylor

Yanıtlar:


7

Wolfram Dili (Mathematica) , 44 bayt

ContinuedFraction[2FromContinuedFraction@#]&

Çevrimiçi deneyin!

Mathematica bir yerleşik var! Yuppi! Mathematica'nın yerleşik yapısı çok uzun. Ayy.

Mathematica'nın sürekli kesirleri benziyor {integer, ...prefix, {...repeating}}

-1 JungHwan Min sayesinde


4
Sen ihmal olabilir *biri yoksa Mathematica varsayılan sınırlayıcı, çünkü Times.
JungHwan Min

3
Diliniz Scrabble puanlamadan Keçi tanımaya kadar her şey için temel oluşturduğunda , bazı isimlerin gerekliliği gereği "çok uzun" olması gerekir. :)
sundar - Reinstate Monica,

1
@ sundar Hayır, Mathematica'da sadece ~ 5000 tane yerleşik var. Her yerleşik 2 baytı en fazla yapmak mümkündür (bkz. Mthmtca)
user202729

@ user202729 Ama eğer bunu yaparsa Mathematica bu kadar popüler olmazdı: P
mbomb007

3

JavaScript (ES6), 267 bayt

(n,f,r)=>eval(`f=[0,...f];e=i=[0,2,1,0];o=j=[];k=[];m={};while([a,b,c,d]=e,c|d&&o)i*m[s=i+m+(e=c*d&&(q=a/c|0)==(b/d|0)?(o.push(q),[c,d,a-c*q,b-d*q]):1/(++i,[p,...f]=f+f?f:(i=r[0],r),p)?[b,a+b*p,d,c+d*p]:[b,b,d,d])]?k+(o=k)?o=0:(m={})[s]=1:m[s]=1;[2*n+j.shift(),j,k]`)

3 argümanı kabul eder (n = tamsayı parçası, f = önek, r = tekrarlayan kısım). Dizideki üç parçayı çıkarır. Çevrimiçi deneyin!

açıklama

Buradaki zorluklarla bağlantılı sürekli kesirli aritmetik işlemlerini gerçekleştirmek için kullanılan algoritmanın oldukça doğrudan bir uygulamasıdır . Yinelenen terimler ara matrisleri bir arama tablosunda saklamak, bir kopyasını beklemek ve bu kopyanın bir sonraki görünümüne kadar terimleri çıkarmak suretiyle işlenir. Bu inelegant ve neredeyse kesirleri kesmek için gereken bayt'ı ikiye katlıyor, ancak daha iyi bir alternatif düşünemiyorum.

Ana terim, negatif sürekli kesirlerin, birinciyi engelleyen tüm terimler için pozitif değerleri koruduğundan emin olmak için ayrı ayrı hesaplanır.

Tekrarlanan bir döngüsü bekleyen zaman yanlış pozitifleri önlemek için, bir arama tablosu depolar verileri aşağıdaki gibidir: <index of input repeating part><delimiter><matrix values>.

Golf edilen sürümün eval1 byte tasarruf için kullandığını unutmayın .

(n, f, r) => {
    f = [0, ...f];                       // use a 0 to chop off the integer part
    e = i = [0,2,1,0];                   // e: matrix with starting values to handle doubling
                                         // 0 + 2x
                                         // ------
                                         // 1 + 0x
                                         // i: tracks index of repeating part; until the function loops through the
                                         // repeating part, i is equivalent to NaN
    o = j = [];                          // o: alias for group of terms currently being computed
                                         // j: output array of non-repeating terms
    k = [];                              // k: output array of repeating terms
    m = {};                              // lookup table
    while ([a,b,c,d] = e, c | d && o)    // destructure matrix
                                         // c | d stops loop if both a/c and b/d equal infinity
        i * m[s = i + m + (              // m also serves as the delimiter; JS will stringify it as "[object Object]"
                                         // if i equals a value that is coerced to NaN, this multiplication
                                         // will be falsy
            e = c * d && (q=a/c|0) == (b/d|0) // checks if either c or d is 0 to avoid converting an Infinity value to 0 using the bitwise or
                ? (o.push(q), [c, d, a - c*q, b - d*q]) // append the output term and compute the new matrix
                : 1/(++i, [p, ...f] = f+f ? f : (i=r[0], r), p) // 1/(... p) checks if p is a valid number
                                         // f+f is a short way to check length of f; if f is an empty
                                         // array, f+f = '' (which is falsy)
                                         // if f is empty, try to replace with r
                                         // if r is empty, the value of i will be set to undefined (e.g. NaN)
                    ? [b, a + b*p, d, c + d*p]
                    : [b,b,d,d]
            )
        ]                                // checks if matrix has been cached in lookup table
            ? k+(o=k)                    // if the repeating part of the output has a value...
                ? o=0                    // o serves as a flag to halt the loop
                : (m={})[s] = 1          // reset lookup table to only hold the first duplicate matrix
            : m[s] = 1;                  // otherwise flag a matrix as seen
    return [2*n + j.shift(), j, k]       // add the doubled integer part to the first term
}
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.