| Bytes | Lang | Time | Link |
|---|---|---|---|
| 020 | APLNARS | 251005T080410Z | Rosario |
| 162 | Python 3 | 210406T044610Z | hyperneu |
| 074 | Retina | 210406T193515Z | Neil |
| 069 | Haskell | 210406T150840Z | Delfad0r |
| 080 | R | 210406T114928Z | Kirill L |
| 038 | Charcoal | 210406T113945Z | Neil |
| 067 | JavaScript ES6 | 210406T065143Z | Arnauld |
| 047 | Wolfram Language Mathematica | 210406T054220Z | ZaMoC |
| 014 | Stax | 210406T045105Z | Razetime |
| 2523 | J | 210406T051342Z | Jonah |
APL(NARS), 20 chars
{↑k/⍨⍺≥÷1∨¨k←⌽+∘÷\⍵}
Input ⍺ one positive integer, ⍵ one array of elements rational type. Output one rational.
↑k/⍨⍺≥÷1∨¨k←⌽+∘÷\⍵
⍺ ⍵ ⍺ is the input left, ⍵ is the input right
+∘÷\⍵ this would make +∘÷/⍵ save each '+∘÷ partial sums' in a array of rational numbers
k←⌽ this would reverse the array of rationals found, and put that array in the k variable
note that here in k each element has a better approximation of the input ⍵
than the next in the array k.
÷1∨¨ this would find each denominator of the array of rationals k, and return the array of them
⍺≥ this would build one boolean array ⍺≥denominators
↑k/⍨ this would get the first in the array k that has denominator with ⍺≥denominator
so it return the better approximation of the number in ⍵ that has ⍺≥denominator
The array of rational type it seems can be defined write one "x" after the first element of the array.
test:
f←{↑k/⍨⍺≥÷1∨¨k←⌽+∘÷\⍵}
43 f 0x 2 3 6 1 3 3
3r7
44 f 0x 2 3 6 1 3 3
19r44
99 f 5x 6 7
222r43
43 f ,1x
1
1 f ,1x
1
1 f 0x 2 3 6 1 3 3
0
Python 3, 162 bytes
lambda x,y:min((abs(q-g(*x)),q)for q in[g(*x[:i+1])for i in range(len(x))]if q.denominator<=y)[1]
g=lambda v,*k:v+Fraction(*k and(1,g(*k)))
from fractions import*
-28 bytes thanks to ovs
Retina, 74 bytes
,
¶$%`,
¶
/1¶
+`\d+,(\d+)/(.+)
$.($2*_$1**)/$1
N$r`.*(\d+)
$1
L`.+¶(?!.+/)
Try it online! Takes the continued fraction and denominator on separate lines, but link includes test suite that splits on ; for convenience. Explanation:
,
¶$%`,
Get all prefixes of the continued fraction.
¶
/1¶
Start each prefix with a denominator of 1.
+`\d+,(\d+)/(.+)
$.($2*_$1**)/$1
Calculate each resulting rational number from right to left.
N$r`.*(\d+)
$1
Sort the desired denominator into the list of rational numbers.
L`.+¶(?!.+/)
Output the rational number whose denominator is the largest that does not exceed the desired denominator.
Haskell, 70 69 bytes
x?m=last[y|y<-f x,y!!1<=m]
f(h:t)=[h,1]:[[a*h+b,a]|[a,b]<-f t]
f[]=[]
The relevant function is (?), which takes as input the continued fraction x (as a list of integers) and the maximum denominator m. The output is a list of integers [numerator,denominator].
How?
x?m= -- x=continued fraction, y=maximum denominator
last[ -- return the last
y|y<-f x, -- convergent of x
y!!1 -- whose denominator (i.e. second element)
<=m -- is at most m
]
f -- helper function for computing convergents
(h:t)= -- h=first number, t=rest of the continued fraction
[h,1]: -- the first convergent is h (i.e. h/1)
[[a*h+b,a] -- the other convergents are h+b/a (i.e. (a*h+b)/a)
|[a,b]<-f t] -- where a/b ranges over the convergents of t
f[]=[] -- base case for the empty continued fraction
R, 88 80 bytes
function(x,y,`~`=cbind,z=1:0~0:1){for(i in x)z=z[,1]*i+z[,2]~z;z[,z[2,]<=y][,1]}
Charcoal, 38 bytes
FLθ«≔⟦§θι¹⟧ζF⮌…θι≔⁺⁺⊟ζ×ζκζζ¿¬›§ζ¹ηP⪫ζ/
Try it online! Link is to verbose version of code. Explanation:
FLθ«
Loop over the prefixes.
≔⟦§θι¹⟧ζ
Form a "fraction" of the current element.
F⮌…θι
Loop over the preceding elements.
≔⁺⁺⊟ζ×ζκζζ
Invert the fraction and add on the element. This is some decidedly tricky coding. The old denominator is popped from the fraction, leaving behind the old numerator as a list of one element. This is vectorised multiplied by the element and added to the denominator, thus making a list of just the new numerator. The old numerator, still in its list, is then list concatenated to it, where it becomes the new denominator.
¿¬›§ζ¹ηP⪫ζ/
If the denominator is still small enough, overprint the previous fraction (if any) with the current fraction.
JavaScript (ES6), 72 68 67 bytes
Expects (max_denominator)(seq). Returns [numerator, denominator].
m=>g=([v,...a],n=0,d=1,N=1,D=0)=>(d+=D*v)<=m?g(a,N,D,N*v+n,d):[N,D]
Commented
m => // outer function taking m = maximum denominator
g = ( // inner recursive function taking:
[v, // v = next term from the continued fraction
...a], // a[] = remaining terms
n = 0, // n = previous numerator
d = 1, // d = previous denominator
N = 1, // N = current numerator
D = 0 // D = current denominator
) => //
(d += D * v) // we compute the new denominator d = D * v + d
// this results in NaN if v is undefined,
// which forces the comparison to fail
<= m ? // if it's less than or equal to m:
g( // do a recursive call:
a, // pass the remaining terms of the continued fraction
N, D, // pass the current numerator and denominator
N * v + n, // pass the new numerator
d // pass the new denominator
) // end of recursive call
: // else:
[N, D] // we're done: return [N, D]
Wolfram Language (Mathematica), 47 bytes
Last@*Cases[a_/;Denominator@a<=#]@*Convergents&
-25 bytes from @att
Stax, 14 bytes
╪£pÇUßi⌂Ω♫M⌂░◘
takes inputs as <max denominator>,<continued fraction>.
Explanation
|[{r{su+km{Rn^<oH
|[{ m for each prefix of the continued fraction
r reverse
{ k reduce by:
su+ swap, reciprocal and add
{ o order by:
R denominator
n^< lesser than 2nd input + 1 ?
H last element
J, 25 23 bytes
(]{:@#~0#.>:)2 x:(+%)/\
-2 thanks to Bubbler
how
We'll use 43 f 0, 2, 3, 6, 1, 3, 3x as an example...
(+%)/\For each prefix\, reduce from the right/using the J hook(+%), which adds its left arg to the inverse of its right argument. This returns rational numbers:0 1r2 3r7 19r44 22r51 85r197 277r6422 x:Convert to pairs:0 1 1 2 3 7 19 44 22 51 85 197 277 642]...#~...Filter that list for valid denominators with the following mask:>:Is each number less than or equal to the left arg:1 1 1 1 1 1 1 0 1 0 0 0 0 00#.Convert to a "base 0" number. This will be1only for pairs whose 2nd element (denominator) is1:1 1 1 0 0 0 0
Our filtered list becomes:
0 1 1 2 3 7{:@Return the last element.