TransWikia.com

Music with pi and e

Code Golf Asked on October 27, 2021

Because I forgot to celebrate Pi Day (14.3), let’s celebrate with $pi$, $e$ (Euler’s number) and music!

Challenge

No, we don’t have time to eat a pi-pizza, let’s make a program.
What you need is $500$ digits of $pi$, and $10$ digits of $e$.

The input is an integer $n$ between $0$ and $499$ inclusive.

Then you should loop through the first $n$ digits of $pi$:

If the digit is:

  • $0$ then the note is C
  • $1$ then the note is D
  • $2$ then the note is E
  • $3$ then the note is F
  • $4$ then the note is G
  • $5$ then the note is A
  • $6$ then the note is B
  • $7$ then the note is C'
  • $8$ then the note is D'
  • $9$ then the note is E'

Next, for each digit in $pi$, take a digit from $e$ based on this mapping:

  • If the digit from $pi$ is $0$, take the $1$st digit from $e$
  • If the digit from $pi$ is $1$, take the $2$st digit from $e$
  • If the digit from $pi$ is $2$, take the $3$st digit from $e$
  • etc.

You need only $10$ digits of $e$, because the digits in $pi$ are between $0$ and $9$.

Finally, take the note and the digit from $e$. Return a tuple (or equivalent) containing:

  • the note
  • the $e$ digit divided by $4$ (representing the beat)

Test cases

In:10
Out:
('D', 0.25)
('G', 2.0)
('D', 0.25)
('A', 0.25)
("E'", 1.0)
('E', 2.0)
('B', 2.0)
('A', 0.25)
('F', 0.5)
('A', 0.25)
In:5
Out:
('D', 0.25)
('G', 2.0)
('D', 0.25)
('A', 0.25)
("E'", 1.0)

Help

Here are $500$ digits of $pi$:

3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912

And $10$ digits of $e$:

2.7182818284

Note that ‘3.’ and ‘2.’ don’t count in the digits of $pi$ and $e$, and that we are using $0$ indexing (so the $0$th digit of $pi$ is $1$ etc.).

Rules

  • This is so the shortest answer wins.
  • Optional; After every tuple or list output, there can be a trailing newline.

As one week is over, here is an ungolfed code in Python 2:

Python 2, 526 bytes

def music_maker(n):
 i=p=1;x=3*100**n
 while x:x=x*i/-~i/4;i+=2;p+=x/i
 pi_number=str(p)[:-1] #First 3 lines calculates Calculate Pi
 euler='7182818284'
 del x,i,p #You don't need those Variables any more. They were ment for calculating
 for i in range(n):
  current_pi = pi_number[i] #Current Pi
  current_e = euler[int(current_pi)] #Current e
  number_to_note = {0:"C", 1:"D",2:"E",3:"F",4:"G",5:"A",6:"B",7:"C'",8:"D'",9:"E'"} #Dict number to note
  print((number_to_note[int(current_pi)], int(current_e)/4)) #Prints result

Try it online!

7 Answers

Wolfram Language (Mathematica), 97 bytes

Print[C[D,E,F,G,A,B,"C'","D'","E'"][[#]]|R[E,10,2+#][[1,-1]]/4]&/@#&@@R[Pi,10,#,-1]&
R=RealDigits

Try it online!

Prints notes as [key] | [duration], with one note per line.

Since Mathematica's number->string functions are so bulky (FromCharacterCode, anyone?), hardcoding the keys' names as symbols seems to be shorter.

Answered by att on October 27, 2021

Perl 5 -Mbignum=bpi, 86 84 bytes

say+(C..G,A..E)[$_],"'"x($_>6),$",((exp 1)=~/./g)[$_+3]/4for(substr bpi<>+1,2)=~/./g

Try it online!

How?

for               # loop over
  (substr         # a substring of
     bpi<>+1,     #   PI to the appropriate number of decimals
     2)           #   starting after the second character
  =~/./g          # split into characters

    say+              # output
      (C..G,A..E)[$_],  # the note letter
      "'"x($_>6),       # a ' if it is in the next octave higher
      $",               # a space
      ((exp 1)          # Euler's number
       =~/./g)           # split into characters
       [$_+3]            # skipping the first 3 (2.7)
       /4                # divided by 4 beats

Answered by Xcali on October 27, 2021

perl -MMath::BigFloat -pl, 170 bytes

$n=$_;$p=new Math::BigFloat;$p->accuracy(500);$_=$p->bpi;s/..//;s!.!'('.substr(CDEFGABCDE,$&,1).("'"x($&>6)).', '.((substr 7182818284,$&,1)/4).")n"!eg;/(.+n){$n}/;$_=$&

Try it online!

How does this work?

$n = $_;

This gets the input (which is in $_ due to the -p switch; the -l switch removes the newline).

$p = new Math::BigFloat;
$p -> accuracy (500);
$_ = $p -> bpi;
s/..//;

This gets us the 500 required digits from $pi$. First we create a Math::BigFloat object, give it an accuracy of 500 (so, 500 decimals behind the comma). We then query the object to get $pi$, which we store in $_. And we then remove the first two characters, to set rid of the leading 3..

s !.!
  '(' .    substr (CDEFGABCDE, $&, 1) . ("'" x ($& > 6)) .
  ', ' . ((substr  7182818284, $&, 1) / 4) .
  ")n"
  !eg

This does the majority of the work. We take each digit of $pi$ and replace it with the result of the middle three lines of code above. During the replacement, the digit being replaced is in $&. We start with an opening paren, then we look up the note by using the current digit as in index into a string (substr (CDEFGABCDE, $&, 1). If the digit is greater than 6, we need to add a prime (("'" x ($& > 6))). We then add a comma. Then, to get the beat, we index into the digits of $epsilon$, and divide by four (((substr 7182818284, $&, 1) / 4)). Finally, we add an closing paren and a newline.

/(.+n){$n}/;
$_ = $&

This trims the resulting string to the desired length. We're grabbing n times a group of non-newline characters followed by a newline character, and store the result into $_, which gets printed due to the -p command line switch.

Answered by Abigail on October 27, 2021

Python 2, 173 164 162 156 150 149 143 141 bytes

def f(n):
 i=p=1;x=3*100**n
 while x:x=x*i/-~i/4;i+=2;p+=x/i
 while x<n:i=int(`p`[x]);print"CDEFGAB"[i%7]+"'"[i<8:],1907986849/9**i%9/4.;x+=1

Try it online.

Prints the pairs newline-delimited to STDOUT in the format string-note beat-decimal (space-delimited).

Port of @Arnauld's JavaScript answer, so make sure to upvote him!
-6 bytes thanks to @ovs, which opened up -6 more bytes by switching to Python 2
-1 byte thanks to @Arnauld
-2 bytes thanks to @Tanmay

Answered by Kevin Cruijssen on October 27, 2021

Charcoal, 52 bytes

P×φψ¤≕Pi→→≔EKDN→Iιθ⎚Eθ⁺⁺⁺§…α⁷⁺²ι×'›ι⁶ ∕I§⪫74ײ1828ι⁴

Try it online! Link is to verbose version of code. Actually works up to n=998. Explanation:

P×φψ¤≕Pi

Charcoal apparently has a built-in for π, but unfortunately the only way I know how to use it is copied from the Charcoal answer to Bake a slice of Pi which involves using it as a flood fill. Here I just output 1,000 null characters which therefore gives me 998 decimals of π, well above the 499 required by the challenge.

→→≔EKDN→Iιθ

Now input the number of decimals required, read them from the canvas, and convert them to integers.

Clear the canvas ready for the actual output.

Eθ⁺⁺⁺

Map over the digits and concatenate...

§…α⁷⁺²ι

... the first 7 letters of the uppercase alphabet, cyclically indexed by 2 more than the digit...

×'›ι⁶

... an ' if the digit is greater than 6...

 

... a space...

∕I§⪫74ײ1828ι⁴

... and the appropriate digit divided by 4, taken from the string 7182818284, constructed by doubling the string 1828 and inserting it into the string 74.

Answered by Neil on October 27, 2021

05AB1E, 33 30 bytes

LεAuS7£ÀÀD3£''««žsyè©èžt¦®è4/‚

Outputs as a list of pairs in the ["string-note", beat-decimal] format.

Try it online.

Explanation:

L                # Push a list in the range [1, (implicit) input]
 ε               # Map each integer to:
  Au             #  Push the uppercase alphabet
    S            #  Convert it to a list of characters
     7£          #  Only leave the first 7: ["A","B","C","D","E","F","G"]
       ÀÀ        #  Rotate it twice towards the left: ["C","D","E","F","G","A","B"]
         D       #  Duplicate it
          3£     #  Only leave the first 3 character of this copy: ["C","D","E"]
            ''«  #  Append a "'" to each: ["C'","D'","E'"]
               « #  Merge the two lists together:
                 #   ["C","D","E","F","G","A","B","C'","D'","E'"]
  žs             #  Push an infinite list of pi-digits: [3,1,4,1,5,...]
    yè           #  Index the current integer into it (0-based, so leading 3 is skipped)
      ©          #  Store it in variable `®` (without popping)
       è         #  Index this pi-digit into the notes string-list
  žt             #  Push an infinite list of e-digits: [2,7,1,8,2,...]
    ¦            #  Remove the leading 2
     ®           #  Push the pi-digit from variable `®`
      è          #  Index it into the infinite list of decimal e-digits
       4/        #  Divide it by 4
  ‚              #  Pair the pi-note and e-digit/4 together
                 # (after which the resulting list of pairs is output implicitly)

Answered by Kevin Cruijssen on October 27, 2021

JavaScript (Node.js),  150 ... 134  133 bytes

Saved 3 bytes thanks to @KevinCruijssen

Expects a BigInt as input and prints the music to STDOUT. This also works for $n>500$.

n=>{for(k=p=1n,x=3n*100n**n;x;p+=x/k)x=x*k++/k++/4n;for(;x<n;)console.log('CDEFGABCDE'[d=(p+'')[x++]]+" '"[d/7|0]+'7182818284'[d]/4)}

Try it online!

How?

Part 1: compute $n$ digits of $pi$

This is based on the following formula:

$$pi-3=sum_{n=1}^{infty}frac{3}{4^n}left(prod_{k=1}^{n}frac{2k-1}{2k}right)timesfrac{1}{2n+1}$$

Instead of using floats -- whose precision is obviously far too limited -- we use a Big Integer $x$ initialized to $3$ times a large enough power of $10$ and process integer divisions until we have $x=0$.

For 500 digits, we could just use $x=3cdot10^{503}$. We instead start with $x=3cdot100^n$, which is more than enough to get $n$ correct digits and easier to golf.

for(                    // loop:
  k = p = 1n,           //   start with k = p = 1
  x = 3n * 100n ** n;   //   start with x = 3 * 100 ** n
  x;                    //   stop when x = 0
  p += x / k            //   add x / k to p after each iteration
)                       //
  x =                   //   update x to:
    x * k++ / k++ / 4n  //     x * k / (k + 1) / 4 (and increment k twice)

Part 2: convert to music notes

for(; x < n;)           // repeat as many times as requested:
  console.log(          //   print:
    'CDEFGABCDE'[       //     string of notes
      d = (p + '')[x++] //     d = x-th digit of pi, extracted from p
    ] +                 //
    " '"[d / 7 | 0] +   //     append a quote if d is greater than or equal to 7,
                        //     or a space otherwise
    '7182818284'[d]     //     get the d-th digit of e (using Math.E would be longer)
    / 4                 //     and divide it by 4 for the beat
  )                     //   end of console.log()

Answered by Arnauld on October 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP