6
\$\begingroup\$

Introduction

From Esolangs.org :

Pi is based on the brainfuck language and uses the same instructions as it. Pi works by calculating pi digits and introducing errors in some random digits of them, encoding obfuscated brainfuck instructions. Instructions are encoded as below:

'>' '<' '+' '-' '.' ',' '[' ']'
 0   1   2   3   4   5   6   7   8

But, as we need to identify which pi digits are incorrect, we move each instruction in the table one position to the right starting at the position that is initially over the correct pi digit that is where we are inserting the instruction. For example, if the pi digit in the position we are inserting the instruction is 4, the table would be moved as follows:

'>' '<' '+' '-'     '.' ',' '[' ']'
 0   1   2   3   4   5   6   7   8   9

Then the instruction would be converted to a digit that would be inserted replacing the correct digit.

Brainfuck explanation

Brainfuck is not very difficult.
Imagine an infinite byte array, initialized to zero, and a pointer on a value of this array.

  • > increments the pointer
  • < decrements the pointer
  • + increments the pointed value
  • - decrements the pointed value
  • . prints the pointed value
  • , sets the pointed value (value is taken from stdin)
  • [ defines the beginning of a loop, this loop is entered if current value is not zero
  • ] is the end of the loop

Objective

In any language, write an interpreter for the esoteric Pi language.

  • Correct pi digits must be taken from http://pastebin.com/raw.php?i=gUbdbzLr, no URL shortener allowed. (JavaScript is allowed to run from pastebin.com domain but the full URL must appear in the code)
  • Only []<>+-. equivalent have to be handled, you can ignore inputs (, equivalent)
  • The input string length will be below 100,000
  • You can write a full program and take the input string from stdin, or write a function and take the input string from argument.
  • You don't have to support inifinite array (100 bytes is fine), but you have to support negative pointers.
  • In case of overflow, wrap the value : -1 => 255 and 256 => 0.

Examples

3.14159265358979323842264332327250288412716939927513582397492459230721640628220899867803480534311206298214838653322233664709084463955358323172235940832848311725028410370193853110525964460294895293032196422880097562591344612147514823378178346528120090214562856642346134861345532264821332360736034914137372428700663631558417448152392396222925459170536432789259026051133013014882046252138214295194153160243205227036275959395309212613732192261379310211855807440237946274952735182575273489122743848301134912983467436444065634308652133494633522473749030217386093370277033921317659317670238267581846066440

This input value must return Hello World!

3.14152322358878323222264326032220288236031386837182584807480228230223643448624338864343482343244432222334808651322320664708322260855054333172535843232848113435028410274433852444334335

Taken from here and converted to Pi, outputs 6*7=42 (don't forget to upvote this awesome answer)

3.1415826535887832384626433832785028846644334334334433443333333344433433434334433333434470302114801731130077382277380418061543333433343344443434333434433344433344334443443702032238007311300810737227041222326030211380073113008107373170312223223233332323222222222322232222332222324738807122323233223233222322223322322322223222232332332443434334343434352222232232233332232232222332222332225222232232332322223223232222222232223233223344343443443344434433334333344333343333334343333343433344433434344443334433443344432232222223223332222222223322223232333222232222332232223323223223222232222222322222243434444443335434534343343433333344343333333434343434333443333343444433343444333333334353232233222223222322233322223333323332232223222323222322322222232322232322323335333333334453423522233222232232344334433335722222764333434443343444434344333334434343444334348644444433433343333333444434343443434333334334443704811648806122222233222232222232222222222232222232222232233444433433444443442222333222323322333222223223223333225222223222222223222232322223232332233222332253333333343443333443344333443334343334443433333334343334343333343433444433343433422223223222232222222222222323223232332322332233223322222323332222232322222322233322354343343333335333533333433333334334333333433334434333433334434333334334333344344443334442223233322233233222223323223223233222333222232233222222233222222223222323223234434333443443432422232223322232353344433434654434444334732222222324737038217381103711688856808272107

This one is taken from my answer here and can be used to test input if you decide to handle it.

Winning criteria

This is a , lowest score wins !

Score computation :

  • 1 byte = 1 point
  • +100 points if you choose to take the pi digits from a local file.
  • -50 points if you handle inputs (,) too (single ASCII character per input; if your language does not support STDIN, prompt for input once and then read a character at a time from that input).
  • -100 points if you compute the pi digits yourself.
\$\endgroup\$
10
  • \$\begingroup\$ Small note : I have wrote an interpreter and checked the example, it is correct and is equivalent to ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. BF code. \$\endgroup\$
    – Michael M.
    May 28, 2014 at 20:40
  • \$\begingroup\$ "-200 points if you compute the pi digits yourself." That may be a bit extreme; isn't the tag code-golf sufficient? \$\endgroup\$
    – primo
    May 29, 2014 at 7:07
  • \$\begingroup\$ @primo, what's extreme ? The value of the bonus or the difficulty to compute pi digits ? \$\endgroup\$
    – Michael M.
    May 29, 2014 at 7:12
  • \$\begingroup\$ The value of the bonus. For example, Perl: use bigint;$\=$\/~(2*$_)*~$_+2e999for-3319..-2;print - 52 bytes. Similarly short representations exist for many other languages. \$\endgroup\$
    – primo
    May 29, 2014 at 7:48
  • \$\begingroup\$ @primo, well, the bonus is now -100. \$\endgroup\$
    – Michael M.
    May 29, 2014 at 7:51

3 Answers 3

3
\$\begingroup\$

PHP, 532 - 50 = 482

<?php $P=file_get_contents("http://pastebin.com/raw.php?i=gUbdbzLr");$I=trim(fgets(STDIN));$i=2;$l=strlen($I)-1;$A=$R=array_fill(0,999,0);$a=$r=0;while($i<$l){$X=intval($I[$i]);$Z=intval($P[$i]);if($X==$Z){$i++;continue;}$O=($X>$Z)?$X-1:$X;switch($N[$X]){case 0:$A[$a]=($A[$a]+1)%256;break;case 1:$A[$a]-=$A[$a]==-1?-256:1;break;case 2:$a+=$a==998?-998:1;break;case 3:$a-=$a==0?-998:1;break;case 4:echo chr($A[$a]);break;case 5:$A[$a]=fgetc(STDIN);break;case 6:$R[$r++]=$i;break;case 7:$A[$a]==0?$R[$r--]=0:$i=$R[$r-1];break;}$i++;}

allow_url_fopen should be 1. Run this in command line like php 28718.php, because it takes input from STDIN.

Array size is 999. It handles negative pointers, overflow, and ,. So I can get -50 points.

Tested with the code above, and

3.14159265358979323846262338227250282419716929927510782090492459233781640638623899262833482534311206728234808621328230264709314460935058223872535941812844111745008410220193853110552964262292895493028192443881097266523344712047564223378672316522123190934562856693346034261045422624821339160726424914827372058703665631558217288153092396282225439171532436789559536003133023024882044652108412695192151163943305737036565959095309212611738393261379210511254207426237992274952735388572272489222793813301174910983367536244265624308632129494679502473713070247986034370277453921711629317375838467480846766440513202056822724526351082178577132275778260917362717672046844093122295323014624928531103079228968920892354501995011202902196586203421812981362477473130996451870724134999399337297803995104973473281603634859504445345544690330263252250825304468003522193158817101

from http://blog.progopedia.com/2011/mar/14/pi-programming-languages/. Can I have more test code?

Readable

<?php
// get pi digits
$P = file_get_contents("http://pastebin.com/raw.php?i=gUbdbzLr");

// input
$I = trim(fgets(STDIN));
$i = 2;
$l = strlen($I)-1;

// bf init
$A = $R = array_fill(0, 999, 0);
$a = $r = 0;

while($i < $l) {
  $X = intval($I[$i]);
  $Z = intval($P[$i]);
  if($X == $Z) { $i++; continue; }

  // operations
  $O = ($X > $Z) ? $X - 1 : $X;

  // bf process
  switch($O) {
    case 0: $a += $a == 998 ? -998 : 1; break;
    case 1: $a -= $a == 0 ? -998 : 1; break;
    case 2: $A[$a] = ($A[$a] + 1) % 256; break;
    case 3: $A[$a] -= $A[$a] == -1 ? -256 : 1; break;
    case 4: echo chr($A[$a]); break;
    case 5: $A[$a] = fgetc(STDIN); break;
    case 6: $R[$r++] = $i; break;
    case 7: if($A[$a] == 0) $R[$r--] = 0; else $i = $R[$r-1]; break;
  }
  $i++;
}
\$\endgroup\$
3
  • \$\begingroup\$ Well done ! I'll give more examples later to test your code. \$\endgroup\$
    – Michael M.
    May 29, 2014 at 7:56
  • \$\begingroup\$ I've added some examples but I don't understand how I can run it. I tried php -d allow_url_fopen=1 and enter the pi value but I have no result. PHP 5.4, OSX. \$\endgroup\$
    – Michael M.
    May 29, 2014 at 19:39
  • \$\begingroup\$ Oh, not working for me too... I think I need to fix this. \$\endgroup\$
    – Snack
    May 30, 2014 at 1:24
3
\$\begingroup\$

Update 2 (on hold)

This code does not accommodate nested loops. Under revision.

Mathematica: 415 (bytes) - 100 (pi -- apparently this counts) - 50 (input) = 265

Handles overflow, only prompts user once when first , is encountered.

v@u_ := (
  f = RealDigits[##][[1]] &;
   q@x_ := q@x = 0;
   r@x_ := q@x~Mod~256;
   z = Length;
   n = Input;
   k = StringSplit[#, ""] &;
   i = k["><+-.,[]"][[If[#1 < #2, #1 + 1, #1]]] & @@@ 
     Select[Transpose@{d = f[u], f[Pi, 10, z@d]}, ! Equal @@ ## &];
   j = 1;
   p = 1;
   y = 1;
   w = 1;
   FromCharacterCode@
    Last@Reap@
      While[j <= z@i, 
       Switch[i[[j]], "[", l = j, "]", If[r@p != 0, j = l - 1], ">", 
        p++, "<", p--, "+", q[p]++, "-", q[p]--, ".", Sow[r@p], ",", 
        If[y-- == 1, c = k@ToString@n[]]; 
        q@p = ToCharacterCode[c[[w++]]][[1]]]; j++]);

Original

Mathematica: 439 bytes - 50 (input) - 100 (pi calc) = 289. Updated to accept interactive input at start.

Readable:

in = StringSplit["><+-.,[]", ""][[#]] &;
c = Input[];
s1 = Cases[
  SequenceAlignment[
    (rd = RealDigits)[
      N[Sum[(i!)^2*2^(i + 1)/(2 i + 1)!, {i, 0, Infinity}], 
     StringLength@c - 1]][[1]], 
    rd[ToExpression@c][[1]]] /. {{r_}, {w_}} :> 
     in@If[r > w, w + 1, w], _String] //. {h___, "[", b___, "]", 
       t___} :> {h, {b}, t};
p = 1;
rt[x_] := rt[x] = 0;
sc[l_] := 
  Scan[Switch[#, ">", p++, "<", p--, "+", rt[p]++, "-", rt[p]--, ".", 
     Sow[rt[p]], ",", Input[], lp_List, While[rt[p] != 0, sc[#]]] &, l];
FromCharacterCode@Last@Reap@sc@s1

{"Hello World! "}

Dense:

in=StringSplit["><+-.,[]",""][[#]]&;c=Input[];s1=Cases[SequenceAlignment[(rd=RealDigits)[N[Sum[(i!)^2*2^(i+1)/(2 i+1)!,{i,0,Infinity}],StringLength@c-1]][[1]],rd[ToExpression@c][[1]]]/.{{r_},{w_}}:>in@If[r>w,w+1,w],_String]//.{h___,"[",b___,"]",t___}:>{h,{b},t};p=1;rt[x_]:=rt[x]=0;sc[l_]:=Scan[Switch[#,">",p++,"<",p--,"+",rt[p]++,"-",rt[p]--,".",Sow[rt[p]],",",Input[],lp_List,While[rt[p]!=0,sc[#]]]&,l];FromCharacterCode@Last@Reap@sc@s1
\$\endgroup\$
5
  • \$\begingroup\$ @m.buettner Yeah I was trying to "compute" Pi, but it's sort of artificial because MMA recognizes the series and makes the replacement symbolically. \$\endgroup\$
    – mfvonh
    May 29, 2014 at 8:29
  • \$\begingroup\$ My mathematica knowledge is limited but it seems that the input value is hardcoded in c. Can you declare a function to be able to run your algorithm without copying the whole code each time ? \$\endgroup\$
    – Michael M.
    May 29, 2014 at 10:14
  • \$\begingroup\$ 3.1415826532222223222702222223022332223220222021112480334024222232344322503241222222323222322250523243344335333444345124070438446 gives me the error : Part::partw: "Part 9 of {>, <, +, -, ., ,, [, ]} does not exist. " \$\endgroup\$
    – Michael M.
    May 29, 2014 at 11:36
  • \$\begingroup\$ @Michael I may have not understood the instructions exactly. c can be replaced with Input[] which will solicit input from the user. The instruction table also fires Input[] when it encounters a ,. I can revise if appropriate. \$\endgroup\$
    – mfvonh
    May 29, 2014 at 15:23
  • \$\begingroup\$ Doesn't work for the second example, answer of @m.buettner works. \$\endgroup\$
    – Michael M.
    May 29, 2014 at 19:25
2
\$\begingroup\$

Mathematica, 362 bytes - 100 (π) = 262

f=(c=Which[#>#2,#,#<#2,#+1,0<1,9]&@@@Thread@{d=(r=RealDigits[##][[1]]&)@#,r@@{Pi,10,(g=Length)@d}};b=0&~Array~100;l=b[[#]]&;p=50;i=0;j={};While[++i<=g@c,{++p&,--p&,++b[[p]]&,--b[[p]]&,j~AppendTo~FromCharacterCode@l@p&,0&,If[l@p>0,j~PrependTo~i,d=1;While[d>0,Switch[c[[++i]],7,++d,8,--d]]]&,If[l@p>0,i=j[[1]],j=Rest@j]&,0&}[[c[[i]]]][];b[[p]]=l@p~Mod~256];j<>"")&

I didn't look at the other Mathematica solution at all to write this. If I hardcode the input variable (which the other answer currently does), I'll save another 5 characters.

This snippet defines a function f though, which takes the input as a string, like

f = (c = Which[# > #2, #, # < #2, # + 1, 0 < 1, 9] & @@@ 
     Thread@{d = (r = RealDigits[##][[1]] &)@#, 
       r @@ {Pi, 10, (g = Length)@d}};
   b = 0 &~Array~100;
   l = b[[#]] &;
   p = 50;
   i = 0;
   j = {};
   While[++i <= g@c,
    {
       ++p &,
       --p &,
       ++b[[p]] &,
       --b[[p]] &,
       j~AppendTo~FromCharacterCode@l@p &,
       0 &,
       If[l@p > 0,
         j~PrependTo~i
         ,
         d = 1;
         While[d > 0,
          Switch[c[[++i]],
           7, ++d,
           8, --d
           ]
          ]
         ] &,
       If[l@p > 0,
         i = j[[1]],
         j = Rest@j] &,
       0 &
       }[[c[[i]]]][];
    b[[p]] = l@p~Mod~256
    ];
   j <> "") &
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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