# Approximate the perfect fifth

Starting at 1-TET, give equal temperaments that have better and better approximation of the perfect fifth(just ratio 3/2). (OEIS sequence A060528)

The formal description of the sequence, copied from the OEIS:

A list of equal temperaments (equal divisions of the octave) whose nearest scale steps are closer and closer approximations to the ratios of two tones of musical harmony: the perfect 4th, 4/3 and its complement the perfect 5th, 3/2.

Note that by symmetry, the perfect fourth doesn't matter.

Let's say we know that 3 is in the sequence. The frequencies in 3-TET are:

2^0, 2^⅓, 2^⅔


Where 2^⅔ is the closest logarithmic approximation of 3/2.

Is 4 in the sequence? The frequencies in 4-TET are:

2^0, 2^¼, 2^½, 2^¾


Where 2^½ is the closest approximation of 3/2. This is not better than 2^⅔, so 4 is not in the sequence.

By similar method, we confirm that 5 is in the sequence, and so on.

When given an integer n as input, the output must be the first N numbers of the sequence in order. For example, when n = 7, the output should be:

1 2 3 5 7 12 29


Sequence description by xnor

The irrational constant $$\ \log_2(3) \approx 1.5849625007211563\dots\$$ can be approximated by a sequence of rational fractions

$$\frac{2}{1}, \frac{3}{2}, \frac{5}{3}, \frac{8}{5}, \frac{11}{7}, \frac{19}{12}, \frac{46}{29}, \dots$$

A fraction is included in the sequence if it's the new closest one by absolute distance $$\ \left| \frac{p}{q} - \log_2(3)\ \right|\$$, that is, closer than any other fraction with a smaller or equal denominator.

Your goal is to output the first $$\n\$$ denominators in order. These are sequence A060528 (table). The numerators (not required) are given by A254351 (table)

Rules:

1. Do not import the sequence A060528 directly.
2. The format doesn't matter as long as the numbers are distinguishable. In the example above, the output can also be:

[1,2,3,5,7,12,29]

3. As this is a code-golf, the shortest code in bytes wins.

• Hi and welcome to Code Golf SE! We require that all challenges be self-contained, so a description here of the sequence would be a great help. Sep 24 '19 at 21:54
• I'm confused by the description from OEIS. It mentions perfect 4th as well (ratio 4/3), but the challenge is about perfect 5ths (ratio 3/2). I think it also needs explanation that the sequence values are the denominators of the rational approximations.
– xnor
Sep 24 '19 at 21:58
• I like the challenge, but I find the stuff added to the description still confusing, not knowing much about music. For instance, I don't know what 1-TET or 4-TET are, and nothing seems to show up on Google. I'll try writing an explanation of how I'd describe this sequence.
– xnor
Sep 24 '19 at 23:06
• @DannyuNDos Ah yes, the 12-tone equal temperament. That's my favourite instrument
– Jo King
Sep 25 '19 at 1:53
• @DannyuNDos Thanks. So the comparison is between 1/2 and log2(1.5), not between 2^(1/2) and 1.5. That should be made clearer in the text Sep 25 '19 at 9:48

# 05AB1E, 19 18 bytes

µ¯ßNLN/3.²<αßDˆ›D–


Try it online!

µ                      # repeat until counter == input
¯                     #  push the global array
ß                    #  get the minimum (let's call it M)
N                   #  1-based iteration count
L                  #  range 1..N
N/                #  divide each by N
3.²             #  log2(3)
<            #  -1
α           #  absolute difference with each element of the range
ß          #  get the minimum
Dˆ        #  add a copy to the global array
›       #  is M strictly greater than this new minimum?
D–     #  if true, print N
#  implicit: if true, add 1 to the counter

• Nice answer, but all I'm wondering right now is why the while-loop has 1-based indices.. :S Sep 25 '19 at 12:48

# Wolfram Language (Mathematica), 62 60 bytes

Denominator@NestList[Rationalize[r=Log2@3,Abs[#-r]]&,2,#-1]&


Try it online!

• How many precision? Sep 25 '19 at 1:38
• @DannyuNDos This function uses exact values, so computations can be done to arbitrary precision.
– att
Sep 25 '19 at 1:39
• You win the challenge. Sep 25 '19 at 1:48
• @DannyuNDos why accept an answer this quickly? It's also arguably better not to accept an answer at all..
– att
Sep 25 '19 at 2:03
• Regarding the floating-point errors other languages are suffering, I'd like to present an alternative method of alloting score. So hold on. Sep 25 '19 at 2:10

# JavaScript (V8), 8180 78 bytes

-2 bytes thanks Arnauld!

n=>{for(d=g=1;w=Math.log2(3),w+=~(w*g-.5)/g,n--;g++)w*w<d?d=print(g)||w*w:n++}


Try it online!

# Python 2, 92 bytes

E=k=input()
n=0
while k:
n+=1;e=abs((3.169925001442312*n-1)%2-1)/n
if e<E:print n;E=e;k-=1


Try it online!

Uses the constant 3.169925001442312 for $$\2 \log_2(3)\$$. I wasn't sure how many digits of accuracy are required, since the inaccuracy will break the sequence eventually, so I used the full float precision of 2 * numpy.log2(3).

• This gives two extra terms after 665: ..., 665, (1995), (4655), 8286, ... Try it online! Sep 25 '19 at 1:31
• @Οurous Yeah, that's pretty much inevitable sooner or later for any language without infinite precision, though I'm surprised it popped up so early with 32-bit floats as Python uses. I'll wait for the challenge writer to clarify on how far answers need to work.
– xnor
Sep 25 '19 at 7:03
• wouldn't it be fewer characters to use 2 * numpy.log2(3) rather than the fully spelled out number? (Or even better, numpy.log2(9))
– JDL
Sep 25 '19 at 13:28
• @JDL that would require this code: from numpy import* and log2(9). Sep 25 '19 at 13:34
• ah, that is what I get for assuming python works like R and you can write package::function without loading package first!
– JDL
Sep 25 '19 at 13:35

# Clean, 128111 108 bytes

import StdEnv
c=ln 3.0/ln 2.0
?d=abs(toReal(toInt(c*d))/d-c)
$i=take i(iterate(\d=until((>)(?d)o?)inc d)1.0)  Try it online! Should work up to the limits of Real's 64-bit double precision type. # MATL, 27 25 bytes 1@:@/Q3Zl-|X<hY<tdzG-}df  Try it online! ### Explanation 1 % Push 1. This initiallizes the vector of distances  % Do...while @: % Range [1, 2, ..., k], where k is the iteration index, staring at 1 @/ % Divide by k, element-wise. Gives [1/k, 2/k, ..., 1] Q % Add 1, element-wise. Gives [(k+1/k, (k+2)/k, ..., 2] 3Zl % Push log2(3) -| % Absolute difference, element-wise X< % Minimum h % Concatenate with vector of previous distances Y< % Cumulative minimum t % Duplicate dz % Consecutive differences, number of nonzeros. This tells how many % times the cumulative minimum has decreased G- % Subtract input n. This is the loop condition. 0 means we are done } % Finally (execute on loop exit) d % Consecutive differences (of the vector of cumulative differences) f % Indices of nonzeros. This is the final result % End. A new iteration is executed if the top of the stack is nonzero % Implicit display  # Perl 5 (-MPOSIX=log2 -M5.01 -n), 73, 78, 71 bytes Fixed following comment, may be improved... -7 bytes thanks to Grimy $o=abs$d-(0|.5+($d=log2 3)*++$;)/$;;$@=$o,$_-=say$;if!$@|$o<$@;$_&&redo


Try it online!

• here's 71 Sep 27 '19 at 15:36