4
\$\begingroup\$

(2 Jan 2018) Because of the winning criteria I am going to accept the Jelly answer, but I am also giving upvotes to all other answers which all use astounding methods as well

Introduction

There are lots of challenges asking for a shortest program to calculate mathematical constants. I saw some with restrictions like banning the literals 3.14 and π etc. However, there seems no such challenges using the number of distinct characters as one of the criteria.

The Challenge

Make a Plain PIE using the fewest kinds and least amount of ingredients but still yummy enough

Write a code that calculates π*e to at least 10 decimal places, that uses as FEW distinct characters (and de facto numeric literal characters) and as short as possible.

This challenge is not banning numeric literals; instead they are discouraged. Numeric literals are seasonings ;)

Requirements

  • The code must be a full program receiving no inputs and outputting the result, or a function which can be called with no arguments either outputting or returning the result. Lambdas are allowed.
  • The result must start with 8.5397342226 and must be in a numeric type. There should only be one output/return in the main program/function. Sub-functions are allowed.

Restrictions

  • String-to-number conversion functions that trivially turn the string literal to a number it represents are not allowed unless explicitly declared and implemented within the code. Also, NO implicit conversions from strings to numbers.
    • eg. eval, Number(), parseInt() and "string" * 1
    • Character-code functions and length functions like ord, String.charCodeAt(n) and String.length are allowed because they do not trivially convert the string into the corresponding number.
  • Use of the following built-ins are not allowed:
    • Mathematical constants, or any built-in functions that evaluates to those constants directly
      • eg. Math.PI in JS, žs in 05AB1E (because it evaluates to π directly)
    • Trigonometric functions and the exponential function, unless explicitly defined and implemented in the code.
      • eg. Math.atan and Math.exp in JS
      • Built-in power functions and exponentiation operators (eg. ** or ^) are allowed, given that they receive 2 arguments/operands (WLOG a and b) and returns ab
  • The length of each run of numeric literal used must not be longer than 5 (eg. 12345 allowed (but not encouraged), but 123456 is not allowed).
  • Standard loopholes apply.

Scoring

  • The scoring is divided into three parts:
    • Distinctness: Scored by counting the number of distinct characters used. Uppercase and lowercase are counted separately. However, the following characters must each be counted as 10 characters:
      • Hexadecimal digits: 0123456789abcdefABCDEF
      • Decimal points: .
      • Any other single characters that may be used as numeric literals (applicable in golfing languages)
    • Size: Scored by the length of the code in bytes.
    • Accuracy: Scored by the number of correct digits counting from the decimal point. Any digits after the first wrong digit are not counted. For fairness, a maximum of 15 digits are counted. The value of π*e according to WolframAlpha is 8.539734222673567(06546...).
  • The total score is calculated by (Distinctness * Size) / Accuracy

Winning Criteria

The answer with the lowest score wins. If tied then the candidate answer which is posted earlier wins.

For non-golfing languages, the score can be calculated using the following snippet (For some golfing languages, the snippet does not work since this checks for UTF-8 length of the code only):

$(document).ready(() => {
 $("#calculate").on("click", () => {
  var count = {};
  var distinct = 0;
  var nonnums = 0;
  var numerals = 0;
  var length = 0;
  for (const c of [...$("#code").val()]) {
   count[c]++;
   if (c.charCodeAt(0) <= 0x7F)
    length += 1;
   else if (c.charCodeAt(0) <= 0x3FF)
    length += 2;
   else if (c.charCodeAt(0) >= 0xD800 && c.charCodeAt(0) <= 0xDFFF)
    length += 4;
   else
    length += 3; 
  }
  for (const c in count) {
   if ("0123456789abcdefABCDEF.".indexOf(c) == -1) {
    nonnums += 1;
    distinct += 1;
   }
   else {
    numerals += 1;
    distinct += 10;
   }
  }
  
  var output = $("#output").val();
  var match = /^8\.(5397342226(7(3(5(67?)?)?)?)?)/.exec(output);
  if (match == null)
   $("#result").html("The result does not have 10-digit accuracy!");
  else {
   var accuracy = match[1].length;
   $("#result").html(`
    Size        : ${length} bytes<br>
    Distinctness: ${distinct} (Numerals: ${numerals}, Non-numerals: ${nonnums})<br>
    Accuracy    : ${accuracy} decimal places<br>
    Score       : ${(distinct * length / accuracy).toFixed(2)}
   `);
  }
 });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Calculator for Non-esoteric Programming Languages (BASIC-like, C-like, Python, Ruby, etc.)</h2>
Code: <br><textarea cols=50 rows=10 id="code"></textarea><br>
Output: <input id="output"><br>
<input type="button" id="calculate" value="Calculate Score">
<pre id="result"></pre>

Example

Submission

JavaScript(ES6), S=141, D=49, A=12, 575.75pt

(t=()=>{for(f=o=9/9;++o<9999;)f+=o**-(9>>9/9);return (f*(9*9+9))**(9/9/(9>>9/9))},u=()=>{for(f=o=r=9/9;++o<99;){f+=r;r/=o}return f})=>t()*u()

Output: 8.53973422267302

Scoring

Size        : 141 bytes
Distinctness: 49 (Numerals: 3 (use of "9", "e" and "f")), Non-numerals: 19)
Accuracy    : 12 decimal places
Score       : 575.75
\$\endgroup\$
  • 2
    \$\begingroup\$ code-challenge because code-golf is specifically for challenges where the sole scoring consideration is number of bytes for the interpreter to obtain the desired result. \$\endgroup\$ – HyperNeutrino Dec 16 '17 at 2:32
  • 1
    \$\begingroup\$ @HyperNeutrino Thank you for the reminder, the clarification and the edit ;) \$\endgroup\$ – Shieru Asakoto Dec 16 '17 at 2:42
  • 2
    \$\begingroup\$ What exactly do you mean by "must be a numerical type"? Also, this prevents certain languages from participating so I'd recommend you consider removing that (somewhat vague) restriction. \$\endgroup\$ – HyperNeutrino Dec 16 '17 at 2:58
  • 4
    \$\begingroup\$ @HyperNeutrino I would say the phrase is to prevent codes which output of the string "8.5397342226..." directly (especially output digit by digit). I am expecting the calculation of the value. \$\endgroup\$ – Shieru Asakoto Dec 16 '17 at 3:07
  • 1
    \$\begingroup\$ Your question should include the actual value of πe to 15 digits. \$\endgroup\$ – Lynn Dec 16 '17 at 14:44
1
\$\begingroup\$

Jelly, 11 × 38 ÷ 10 = 41.8

“Þẹjuụ’÷ȷ10

Try it online!

Explanation

“Þẹjuụ’÷ȷ10  Main Link
“Þẹjuụ’      85397342226
       ÷     Divided by
        ȷ10  1e10
\$\endgroup\$
  • \$\begingroup\$ Since ȷ can be used as 1000 if used separately, I will count it as a single-character numeric literal :) \$\endgroup\$ – Shieru Asakoto Dec 16 '17 at 2:44
  • 1
    \$\begingroup\$ BTW seems to mark a string literal. The answer is invalid if built-in or implicit string-to-number conversion is used as per restrictions. \$\endgroup\$ – Shieru Asakoto Dec 16 '17 at 2:47
  • 1
    \$\begingroup\$ @user71546 Is built-in integer compression forbidden then? That should be specified separately because in this case denotes a number literal, not a string literal. \$\endgroup\$ – HyperNeutrino Dec 16 '17 at 2:51
  • \$\begingroup\$ 11 × 101 ÷ 10 = 111.1. Works in binary too! \$\endgroup\$ – JungHwan Min Dec 16 '17 at 2:53
  • \$\begingroup\$ @JungHwanMin Hm interesting! I wonder, does that work for the general case? I'd think so but I'm not sure. \$\endgroup\$ – HyperNeutrino Dec 16 '17 at 2:53
5
\$\begingroup\$

Mathematica, (18*226)/15 = 271

only 1s

N[1+1+1+1+1+1+1+1+1/(1+1/(1+1/(1+1+1+1+1+1/(1+1/(1+1+1+1/(1+1/(1+1+1+1+1/(1+1+1+1+1+1+1+1+1+1+1+1+1/(1+1+1+1/(1+1+1/(1+1/(1+1+1+1+1+1/(1+1+1/(1+1+1+1+1+1+1+1+1+1+1+1+1/(1+1/(1+1)))))))))))))))),1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1]


Try it online!

Mathematica, 244

1s & 2s

N[2+2+2+2+1/(1+1/(1+1/(1+2+2+1/(1+1/(1+2+1/(1+1/(2+2+1/(12+1/(1+2+1/(2+1/(1+1/(1+2+2+1/(2+1/(12+1/(1+1/(1+1)))))))))))))))),12+2+2]


Try it online!

\$\endgroup\$
  • \$\begingroup\$ WOW, only 1s and 6s. btw the parentheses surrouding 6-1 can be removed for -4 bytes \$\endgroup\$ – Shieru Asakoto Dec 16 '17 at 4:44
  • 1
    \$\begingroup\$ updated. only 1s \$\endgroup\$ – J42161217 Dec 16 '17 at 4:52
  • \$\begingroup\$ Quick explanation: Continued fraction approach. \$\endgroup\$ – user202729 Dec 16 '17 at 4:52
  • 1
    \$\begingroup\$ you people are mind-meltingly clever!!! it makes me angry at myself!! \$\endgroup\$ – Big T Larrity Dec 16 '17 at 12:24
  • \$\begingroup\$ For what it’s worth, this translates to 1+1+1+1+1+1+1+1+1÷1+1÷1+1÷1+1+1+1+1+1÷1+1÷1+1+1+1÷1+1÷1+1+1+1+1÷1+1+1+1+1+1+1+1+1+1+1+1+1÷1+1+1+1÷1+1+1÷1+1÷1+1+1+1+1+1÷1+1+1÷1+1+1+1+1+1+1+1+1+1+1+1+1÷1+1÷1+1 in APL, scoring 12×159÷15 = 127.2 points. \$\endgroup\$ – Lynn Dec 16 '17 at 13:49
4
\$\begingroup\$

Mathematica, 257.6

N[2Integrate[Sqrt[1-n^2],{n,-1,1}],22]Sum[1/n!,{n,0,22}]

Try it online!

Mathematica, 276

this is accurate to 4095 digits

N[2Integrate[Sqrt[1-n^2],{n,-1,1}],2^12]Sum[1/n!,{n,0,2^12}]

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Would it save any points to replace 1/n! with n!^-1? \$\endgroup\$ – numbermaniac Dec 16 '17 at 12:03
  • 1
    \$\begingroup\$ no... it is (69*60)/15=276 (this one) vs (68*61)/15=276.533 (yours) \$\endgroup\$ – J42161217 Dec 16 '17 at 12:17
2
\$\begingroup\$

Imperative Tampio, 2206.46

K:lla on h:t.K:n z on riippuen siitä,onko sen h:iden määrä nolla,joko nolla tai sen ensimmäinen h lisättynä uuden K:n,jonka h:t ovat sen h:t toisesta alkaen eikä muuta,z:aan jaettuna kymmenellä.Kun iso sivu avautuu,se näyttää uuden K:n,jonka h:ita ovat kolme lisättynä viiteen,viisi,kolme,neljä lisättynä viiteen,7,kolme,neljä,kaksi,kaksi,kaksi,kuusi,7,kolme,viisi ja 7 eikä muuta,z:n.

K:lla on h:t.K:n z on riippuen siitä,onko sen h:iden määrä nolla,joko nolla tai sen ensimmäinen h lisättynä uuden K:n,jonka h:t ovat sen h:t toisesta alkaen eikä muuta,z:aan jaettuna kymmenellä.Kun iso sivu avautuu,se näyttää uuden K:n,jonka h:ita ovat kolme lisättynä viiteen,viisi,kolme,neljä lisättynä viiteen,7,kolme,neljä,kaksi,kaksi,kaksi,kuusi,7,kolme,viisi ja 7 eikä muuta,z:n.

Online version

Tampio has an advantage that number literals can be written using letters instead of digits. I also noticed that the interpreter thinks that one-letter words are nouns, so I can use them as identifiers. Of course, this language is so verbose that it won't help it to win any challenge.

Ungolfed:

Listalla on alkiot.

Listan lukuarvo on riippuen siitä, onko sen alkioiden määrä nolla,

  • joko nolla
  • tai sen ensimmäinen alkio lisättynä uuden listan, jonka alkiot ovat sen alkiot toisesta alkaen eikä muuta, lukuarvoon jaettuna kymmenellä.

Kun nykyinen sivu avautuu,

  • se näyttää uuden listan, jonka alkioita ovat 8,5,3,9,7,3,4,2,2,2,6,7,3,5 ja 7 eikä muuta, lukuarvon.
\$\endgroup\$
2
\$\begingroup\$

APL, 6×124÷15 = 49.6 points

zz+zz+zz+zz+÷z+÷z+÷z+zz+zz+÷z+÷z+zz+÷z+÷zz+zz+÷zz+zz+zz+zz+zz+zz+÷z+zz+÷zz+÷z+÷z+zz+zz+÷zz+÷zz+zz+zz+zz+zz+zz+÷z+÷zz←z+z←⍴⍴⍬

Try it online! (Paste in the code then hit Ctrl+Enter.)

Assigns 1 to z, then abbreviates z+z to zz, and then approximates the continued fraction of πe as 8+1/(1+1/(1+1/(5+1/(1+1/(3+1/(1+1/(4+1/(10+1/(3+1/(2+1/(1+1/(5+1/(2+1/(12+1/(1+1/2))))))))))))))) (inspired by Jenny_mathy’s Mathematica answer).

1 is computed as ⍴⍴⍬: the dimensions vector (1) of the dimensions vector (0) of the empty vector ().

Because of APL’s ÷ reciprocal operator and right-to-left grouping rules, this representation doesn’t even need parentheses. We use 6 distinct non-numeric symbols: z+÷←⍴⍬


This code should work in any APL dialect; the only important thing is that there is one where

  • the answer is printed to 15 figures by default;
  • the glyphs are encoded as one byte each (i.e. source code is in some custom APL codepage, not UTF-8).

Graham reports that APL+Win fits the bill.

\$\endgroup\$
  • \$\begingroup\$ Well, this works in Dyalog APL which TIO supports! (note how I put ⎕← to show the output, don't count that) \$\endgroup\$ – Erik the Outgolfer Dec 16 '17 at 14:25
  • \$\begingroup\$ Also, can you please specify what APL dialect you're using? If you're using Dyalog, then you have a precision of 9 decimals, not 15. If you're using ngn/apl, then you should count the bytes in Unicode. \$\endgroup\$ – Erik the Outgolfer Dec 16 '17 at 14:35
  • \$\begingroup\$ Hm… There are enough APL implementations out there that I’d expect one of them to support both an APL SBCS and 15-digit precision by default. I’ll wait for Adám to chime in! \$\endgroup\$ – Lynn Dec 16 '17 at 14:58
  • 1
    \$\begingroup\$ This works in my APL+WIN which is not Unicode and produces the answer 8.539734222673568 \$\endgroup\$ – Graham Dec 16 '17 at 17:18
  • \$\begingroup\$ Further to the above I would be surprised if the precision in Dyalog is limited to 9 decimals. In APL+WIN it is controlled via ⎕PP which by default is 10 but can be set up to 17. In APLX again the default is 10 max 15. \$\endgroup\$ – Graham Dec 17 '17 at 15:02
1
\$\begingroup\$

Swift, 116 * 39 / 14 ≈ 323.14 114 * 39 / 14 ≈ 317.57

print(2+2+2+2+1/(1+1/(1+1/(2+2+1+1/(1+1/(2+1+1/(1+1/(2+2+1/(12+1/(2+1+1/(2+1/(1+1/(2+2+1+1/(2+1/12.2))))))))))))))

Try it online!

Uses a continued fraction to approximate π*e to 14 decimal places

\$\endgroup\$
1
\$\begingroup\$

Pyt, 22*73/11=146 22*72/11=144 23*53/11 22*39/11=78

1⁺1⁺⁺⁺⁺⁺^ř⁻Đ!⇹1⁺*⁺‼/Ʃ1⁺*1⁺⁺1⁺⁺⁺⁺*ř⁻!⅟Ʃ*

Uses approximations for π and e, respectively.

Per the codepage (which is in the interpreter2 file), each character is one byte.

Explanation (stuff in brackets is what is used from the stack):

1⁺1⁺⁺⁺⁺⁺^ř⁻Đ!⇹1⁺*⁺‼/Ʃ1⁺*           makes π

1⁺1⁺⁺⁺⁺⁺^         makes 64
(64)ř             makes a list [1,2,...,64]
([1,...,64])⁻     subtracts one from each element in the list
([0,...,63])Đ     duplicates list (on top of stack twice)
([0,...,63])!     performs element-wise factorial
([...],[...])⇹    swaps top two items on the stack
([...])1⁺*⁺       doubles all values in list and adds one
([...])‼          element-wise double factorial
([...],[...])/    divides element-wise
([...])Ʃ          sums all elements in the list (approximately π/2)
(π/2)1⁺*          doubles (yields π)

1⁺⁺1⁺⁺⁺⁺*ř⁻!⅟Ʃ

1⁺⁺1⁺⁺⁺⁺*         makes 15
         ř⁻       makes a list [0,1,...,14]
           !      Takes the factorial of each element in the list
            ⅟     Finds the multiplicative inverse of each element
             Ʃ    Sums the list (e)

(π,e)*              multiplies
                    (implicit print)

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.