0815インタープリターを書く


26

作成者のWebサイトのインタープリターがエラー404を返すことを除いて、私は0815の概念が好きです。だから私は皆さんに助けを求めることにしました!

基礎

0815は、3つのレジスタと1つのキューに基づいています。レジスタにはX、Y、Zという名前が付けられ、Xは書き込み専用、Zは読み取り専用、Yは直接アクセスできない「ヘルパー」レジスタです。すべてのレジスタは、0に設定されて開始されます。すべての数値は16進数です。

説明書

注:一部の命令は、パラメーターの}:hello:場所のようにフォーマットされ:hello:たパラメーターを使用します。その他の注意:命令の説明のいくつかは不明瞭なので、私はそれらにいくつかの自由を取りました。(ここに元の指示)

~ パラメータが必須であることを意味します

----------|---|--------------------------------------------
  ~Move   | < | <:8: will write 8 to X (parameter required) 
----------|---|--------------------------------------------
   Swap   | x | Swap X and Y
----------|---|--------------------------------------------
  ~Label  | } | }:hello: makes a label called 'hello'
----------|---|--------------------------------------------
  Input   | | | Set X to an integer from input in 
 Number   |   | hexadecimal greedily (regex: [0-9A-F]+)
----------|---|--------------------------------------------
  Input   | ! | Set X to the ASCII code of one ASCII
  ASCII   |   | character in the input
----------|---|--------------------------------------------
  Print   | % | Prints an integer stored in Z 
  number  |   | (hexadecimal base)
----------|---|--------------------------------------------
  Print   | $ | Prints an ASCII char stored in Z
  ASCII   |   |
----------|---|--------------------------------------------
  Roll    |   | Rolls all registers to the left
Registers | ~ | X <- Y <- Z <- X
  Left    |   | After roll: X = Y, Y = Z and Z = X
----------|---|--------------------------------------------
  Roll    |   | Rolls all registers to the right
Registers | = | X -> Y -> Z -> X
  Right   |   | After roll: Y = X, Z = Y and X = Z
----------|---|--------------------------------------------
 ~Jump if | ^ | ^:loop: Jumps to the label 'loop' if Z is
 not zero |   | not zero
----------|---|--------------------------------------------
 ~Jump if | # | #:loop: Jumps to the label 'loop' if Z is
   zero   |   | zero
----------|---|--------------------------------------------

キュー命令

----------|---|--------------------------------------------
   Clear  | ? | Clears the queue
----------|---|--------------------------------------------
  Enqueue | > | Enqueue the number stored in Z
----------|---|--------------------------------------------
  Dequeue | { | Dequeue a number into X
----------|---|--------------------------------------------
          |   | Rolls the queue to the left, wrapping as
   Roll   |   | necessary. The first number becomes the 
   Queue  | @ | last; second becomes first and so on. Can  
   Left   |   | take a parameter to roll a certain number
          |   | of times. @:b: rolls 11 times.
----------|---|--------------------------------------------
   Roll   |   | 
   Queue  | & | The opposite of @
   Right  |   | 
----------|---|--------------------------------------------

算術命令

----------|---|--------------------------------------------  
   Add    | + | Z = X + Y
----------|---|--------------------------------------------
 Subtract | - | Z = X - Y
----------|---|--------------------------------------------
 Multiply | * | Z = X * Y
----------|---|--------------------------------------------
  Divide  | / | Z = X / Y
          |   | Y = remainder
----------|---|--------------------------------------------

サンプルプログラム

Hello world:(ややゴルフ)

<:48:~$<:65:~$<:6C:~$$><:6F:~$>@<:2C:~$<:20:~$<:57:~${~$<:72:~${~$<:64:~$

ネコ:

}:_t:!~$^:_t:

真実のマシン:

|~}:i:%^:i:

これはであるため、最小バイト数の送信が勝ちます!


3
区別は何だ~~あなたの「ロールレジスタ」コマンドでは?人々がテストに使用できるサンプルプログラムはありますか?
AdmBorkBork

3
例を挙げてください。
コナーオブライエン

1
@DanTheMan私は(まだWIP)実装を使用してHello Worldの例を実行すると「Hello、Wlrod」と表示されます...それが私のコードのバグなのか、それ自体のサンプルなのかわかりません
Ruslan

2
@DanTheManはい、ただしリンクを変更するとインタープリターになります。:-)
スベンはコードを

1
@usandfriends修正済み!
DanTheMan

回答:


8

PIP321の 262 248バイト

evalおよびKolmogorov-complexityトリックを使用して大幅に短縮されました。

a@:`.(:.*?:)?`z:Y0w:2**64W++v<#a{UnpWa@v^':;V("Yp57Syi7UybWb^@(b@?`[^0-9A-F]|$`)Yy57Y APOb7OzTB167O Cz7SyzSyi7SyiSyz7I2I!2l:[]7lPBz7Y3B3UDQl7z:(y+4-4*4//i)i:y%i"R2`zv:a@?"}:".p.':7`R3"POl7Lp?p5olP"R4"i)%w7z:(y"R5"FB16%w"^7"<x|!%$~=^#?>{@&+-*/"@?n)}

オンラインでお試しください!(例は、言語作成者のWebサイトのCollat​​z / hailstone numbersプログラムです。)

ノート:

  • 最初のコマンドライン引数として0815コードを取り、2番目として入力を取ります。はい、それは少し厄介です(TIOでは、テキストボックスが個別に表示されます)
  • 入力の数値は大文字の16進数を使用する必要があります(OP:正規表現に一致[0-9A-F]+)。、でた場合は|指示、入力の次の文字ではありません0-9A-F、読み込みに失敗し、潜在的に奇妙な行動を引き起こします。これは、作者の偶奇プログラムが書かれたとおりに機能しないことを意味します...複数の数値の読み取りがどのように機能するかはわかりませんが、仕様の説明に従って実装しました。
  • ラベルが重複している場合、最初のラベルにジャンプします。ラベルが存在しない場合、ジャンプはプログラムを終了します。

コメント付きの私のバージョン:

;;; INITIALIZATION ;;;

; a is the code, analyzed with regex into a list of instructions
a @: `.(:.*?:)?`
; b is the input
; x, y, z are registers (initially three 0s)
x:y:z:0
; l is the queue (initially empty list)
; v is the instruction pointer (initially -1, but gets incremented at top of loop)
; w represents the width of the registers
w:2**64

;;; MAIN LOOP ;;;

; Loop while IP hasn't gone past last instruction
W ++v<#a {
 ; Unify n with first char of current iNstruction, p with the parameter (or nil)
 U np W a@v ^ ':

 ; If n eQuals "<": move p value into x
 InQ'<
  ; Convert p from hex and truncate to register width
  x : pFB16%w
 ; Swap x and y
 InQ'x
  Sxy
 ; Input number (in hex, uppercase only)
 InQ'| {
  ; Find index of first non-hex character in b and split at that index
  ; Unify left half with x and right with b
  U xb W b^@(b @? `[^0-9A-F]|$`)
  ; Convert x from hex and truncate to register width
  x : xFB16%w
 }
 ; Input ASCII
 InQ'!
  ; Pop 1st char of b and get ASCII code
  x : A POb
 ; Print number (in hex)
 InQ'%
  ; Output z converted to hex
  O zTB16
 ; Print ASCII
 InQ'$
  ; Output chr(z)
  O Cz
 ; Roll registers left
 InQ'~ {
  ; With three registers, a roll is just two swaps
  Sxz
  Sxy
 }
 ; Roll registers right
 InQ'= {
  Sxy
  Sxz
 }
 ; Jump (combines if-nonzero and if-zero cases)
 I nQ'^ & z | nQ'# & !z
  ; Construct the corresponding label, find its index in a, and set IP to that
  v : a @? "}:".p.':
  ; If the label doesn't exist, v becomes nil, which makes the loop condition nil,
  ; which (being falsy) exits the loop and terminates the program

 ; Clear queue
 InQ'?
  l:[]
 ; Enqueue
 InQ'>
  ; Push z to back of l
  lPBz
 ; Dequeue
 InQ'{
  ; Pop l and assign to x
  x:POl
 ; Roll queue left
 ; NOTE: doesn't work if 0 is a valid parameter for roll operation
 ; If we want to handle that case, use #p?... instead of p?... for +1 byte
 InQ'@
  ; Loop specified number of times (converted from hex), or 1 if not specified
  L p ? pFB16 1
   ; Pop (front of) l and push that value to the back of l
   l PB POl
 ; Roll queue right
 InQ'&
  L p ? pFB16 1
   ; Dequeue from back of l and push that value to (the front of) l
   l PU DQl

 ; Add (truncating as needed)
 InQ'+
  z:(x+y)%w
 ; Subtract (truncating as needed)
 InQ'-
  z:(x-y)%w
 ; Multiply (truncating as needed)
 InQ'*
  z:x*y%w
 ; Divide (truncating not needed)
 InQ'/ {
  z:x//y
  y:x%y
 }
}

7

haxe、987バイト

class Main{static function main(){var c=sys.io.File.getContent(Sys.args()[0]).split(""),i=0,x=0,y=0,z=0,t=0,m=0,g=Sys.getChar.bind(false),f=String.fromCharCode,b="",B="",l="",A=[];while(i<c.length)switch(l=c[i++]){case"<"|"}"|"^"|"#":b=l=="<"?"0x":"";if(c[i++]==":")while((B=c[i++])!=":")b+=B;if(l=="<")x=Std.parseInt(b);else if(l!="}"&&(z==0)==(l=="#")){t=0;while(t!=(m=(i+t++)%c.length)){if(c[m]==":")t+=c.indexOf(":",m+1)-m;else if(c[m]=="}"){l="";if(c[++m]==":")while((B=c[++m])!=":")l+=B;if(b==l){i=m;break;}}}return;}case"x":t=x;x=y;y=t;case"|":b="0x";while(((t=g())>47&&t<58)||(t>96&&t<103))b+=f(t);x=Std.parseInt(b);case"!":x=g();x=x<0?0:x;case"%"|"$":Sys.print(l=="%"?[for(j in 0...8){"0123456789abcdef".split("")[z>>((7-j)*4)&15];}].join(""):f(z));case"?":A=[];case">":A.push(z);case"{":x=A.shift();case"@":A.push(A.shift());case"&":A.unshift(A.pop());case"+":z=x+y;case"-":z=x-y;case"*":z=x*y;case"~":t=x;x=y;y=z;z=t;case"=":t=x;x=z;z=y;y=t;case"/":z=Math.floor(x/y);y=x%y;}}}

またはいくつかの空白を使用:

class Main{static function main(){
var c=sys.io.File.getContent(Sys.args()[0]).split(""),
    i=0,
    x=0,
    y=0,
    z=0,
    t=0,
    m=0,
    g=Sys.getChar.bind(false),
    f=String.fromCharCode,
    b="",
    B="",
    l="",
    A=[];
while(i<c.length)switch(l=c[i++]){
    case"<"|"}"|"^"|"#":
        b=l=="<"?"0x":"";
        if(c[i++]==":")
            while((B=c[i++])!=":")
                b+=B;
        if(l=="<")
            x=Std.parseInt(b);
        else if(l!="}"&&(z==0)==(l=="#")){
            t=0;
            while(t!=(m=(i+t++)%c.length)){
                if(c[m]==":")
                    t+=c.indexOf(":",m+1)-m;
                else if(c[m]=="}"){
                    l="";
                    if(c[++m]==":")
                        while((B=c[++m])!=":")
                            l+=B;
                        if(b==l){
                            i=m;
                            break;
                        }
                }
            }
            return;
        }
    case"x":
        t=x;x=y;y=t;
    case"|":
        b="0x";
        while(((t=g())>47&&t<58)||(t>96&&t<103))
            b+=f(t);
        x=Std.parseInt(b);
    case"!":
        x=g();
        x=x<0?0:x;
    case"%"|"$":
        Sys.print(l=="%"?[
            for(j in 0...8){
                "0123456789abcdef".split("")[z>>((7-j)*4)&15];
            }
        ].join(""):f(z));
    case"?":
        A=[];
    case">":
        A.push(z);
    case"{":
        x=A.shift();
    case"@":
        A.push(A.shift());
    case"&":
        A.unshift(A.pop());
    case"+":
        z=x+y;
    case"-":
        z=x-y;
    case"*":
        z=x*y;
    case"~":
        t=x;x=y;y=z;z=t;
    case"=":
        t=x;x=z;z=y;y=t;
    case"/":
        z=Math.floor(x/y);
        y=x%y;
}}}

haxeでゴルフに成功しましたか?ワオ。


1
Haxeの+1、最もゴルファーの少ない言語の1つでの最短回答
cat

1
これをJSにコンパイルすると、短くなりますか?その後、あなたはそれES6 / ES7作ることができます

5

Python 3、1320バイト

ungolfedバージョン、ならびに分析のテストプログラム(及び必要は、のバージョンを修正)、見つけることができ、この要旨に

設計上の決定:

  • ラベルの複数の定義は無視されます。ラベルの最初の定義のみが使用されます。(以前は最も最近見られた定義が使用されますが、それはゴルフアウトされました。)
  • 入力はOPの仕様に準拠しています。数値入力は16進文字を貪欲に読み取ります。(元々は改行まで読み込まれ、非16進文字が読み込まれるとエラーが発生しました。)
  • 「ASCII」入力は、「バイト指向」入力を意味すると解釈されます。(もともとはUnicode 3が完全にサポートされていたため、Python 3のおかげでコードが少なくなりましたが、次の箇条書きを満たすことで、バイト単位の読み取りが短くなりました。)
  • パラメーターが予期されていないパラメーターは無視されます。したがって、コメントとして使用できます。

CRのみを改行として使用するサンプルプログラムには問題があり(時々)、新しい行を開始するのではなく現在の行を上書きします。これは、フィボナッチシーケンスと99本のビールプログラムに影響します。99本のビールの最後の詩も正しく印刷されていないので、私はまだその理由を調査しています。

import sys as y
import sys as y
b=y.stdin.buffer
I=int
g=getattr
X=2**64
R=lambda a:property(lambda s:g(s,a)-[X,0][0<=g(s,a)<X/2],lambda s,v:setattr(s,a,I(v)&X-1))
M,*Q=':<}^#@&xX|!%$~=?>{+-*/'
class A:
 x,y,z=map(R,'uvw')
 def R(s,p):
  s.p,s.s,*s.q=p,3,;s.x=s.y=s.z=s.i=0
  while s.s<4:
   t='';p=s.s=i=0
   while s.s<3:
    k=s.p[s.i];s.i+=1
    if s.s==1:
     if k==M:
      if p==2:s.t=s.i;g(s,s.I[i])(t);s.s=max(s.s,3)
     else:t+=k
    elif k==M:p,s.s=s.s,1
    elif k in Q:
     i=k;m=M==s.p[s.i]
     if k in Q[:6]and m:s.s=2
     elif k in Q[6:]or k in'@&'and m<1:g(s,s.I[i])()
 def B(s,v):s.x=I(v,16)
 def C(s):s.x,s.y=s.y,s.x
 def D(s,l):0
 def E(s):
  s.x=0
  try:
   while 1:s.x=s.x*16+I(b.peek()[:1],16);b.read(1)
  except:0
 def F(s):s.x=b.read(1)[0]
 def G(s):print(format(s.z,'x'),end='')
 def H(s):print(chr(s.z),end='')
 def J(s):s.x,s.y,s.z=s.y,s.z,s.x
 def K(s):s.J();s.J()
 def j(s,l):
  a=s.p.find('}:'+l+M)
  if a<0:s.s=4
  else:s.i=a
 def L(s,l):
  if s.z:s.j(l)
 def T(s,l):
  if s.z==0:s.j(l)
 def U(s):s.q=[]
 def V(s):s.q+=s.z,
 def W(s):s.x,*s.q=s.q
 def Y(s,d='1'):d=I(d,16);s.q=s.q[d:]+s.q[:d]
 def Z(s,d='1'):Y('-'+d)
 def a(s):s.z=s.x+s.y
 def b(s):s.z=s.x-s.y
 def c(s):s.z=s.x*s.y
 def d(s):s.z,s.y=divmod(s.x,s.y)
 I=dict(zip(Q,'BDLTYZCCEFGHJKUVWabcd'))
try:A().R(open(y.argv[1]).read())
except:0

4

Scala、3,123 2,844 2,626 2,540バイト

質問で概説された制約に加えて、このインタープリターは、FP原則に可能な限り傾くように書かれました。具体的には:

  • 不変の構造のみ
  • すべての機能は純粋です

これは、インタープリターのメインループを駆動する4行のコードを除き、達成されました。不変構造は、レジスタの状態がループの制御フロー(具体的には2つのGOTOステートメント)を駆動するため、ここでの使用は非常に困難でした。私はまだそれを純粋で不変の構造を使用するように変換する方法を考えていますが、それはコードゴルフの挑戦とは無関係です。

import java.util.Scanner
import scala.util._
object Z extends App{type K=Long
type G=List[K]
type I=String
type E=Boolean
val(f,t,ф,д,б)=(false,true,(z:G)=>z(0),(z:G)=>z.tail,(q:K,w:K,e:K)=>q::w::e::Nil)
trait O{def h(z:I)=BigInt(z,16).longValue()}
trait S extends O
trait B extends S with P{def apply(r:G):E}
trait R extends O{def a(r:G):G}
trait T extends O{def a(r:G,s:G):(G,G)}
trait P{def p:I}
case class L(p:I)extends S with P
case class U(p:I)extends B{def apply(r:G):E=r(2)==0}
case class J(p:I)extends B{def apply(r:G):E=r(2)!=0}
case class M(p:I)extends R with P{def a(r:G):G=h(p)::д(r)}
class Y extends R{def a(r:G):G=б(r(0),r(0)%r(1),r(0)/r(1))}
case class Q(p:I)extends T with P{def r(q:G,i:Int):G={val s=д(q):+ф(q)
if(i>0)r(s,i-1)else s}
def a(e:G,t:G)=e->r(t,Try(p.toInt).getOrElse(1))}
case class N(p:I)extends T with P{def r(q:G,i:Int):G={
val s=q.last::q.iterator.sliding(2).map(_(0)).toList
if(i>0)r(s,i-1)else s}
def a(e:G,t:G)=e->r(t,Try(p.toInt).getOrElse(1))}
case class A(n:Array[O], l:Map[I,Int]){def e={var (r,t,x)=(List(0L,0,0),List[K](),0)
while(x<n.length){x=n(x)match{case i:B=>if(i(r))l(i.p)else x+1
case i:R=>r=i.a(r);x+1
case i:T=>val(y,u)=i.a(r,t);r=y;t=u;x+1
case _=>x+1}}}}
object A{def apply(i:Seq[O]):A={A(n=i.toArray,l=Map(i.zipWithIndex.flatMap{case(e:L,i)=>Some(e.p->i)
case _=>None}.toList:_*))}}
object X{def v(y:(Char, Option[Z.I]))=y._2.getOrElse("");val F=Map('x->new R{def a(t:G)=б(t(1),t(0),t(2))},'|'->new R{def a(r:G)=h(new Scanner(System.in).next("[0-9a-fA-F]+"))::д(r)},'!'->new R{def a(r:G)=(System.in.read match{case i if i== -1=>0;case i=>i})::д(r)},'%'->new R{def a(r:G)={print(Integer.toHexString(r(2).toInt));r}},'$'->new R{def a(r:G)={print(r(2).toChar);r}},'~'->new R{def a(r:G)=д(r):+ф(r)},'='->new R{def a(r:G)=б(r(2),r(0),r(1))},'?'->new T{def a(r:G,s:G)=r->List()},'>'->new T{def a(r:G,s:G)=r->(r(2)::s)},'{'->new T{def a(r:G, s:G)=(ф(s)::д(r))->д(s)},'+'->new R{def a(r:G)=б(r(0),r(1),r(0)+r(1))},'-'->new R{def a(r:G)=б(r(0),r(1),r(0)-r(1))},'*'->new R{def a(r:G)=б(r(0),r(1),r(0)*r(1))},'/'->new Y);def apply(i:I)={(i+" ").foldLeft((List[(Char,Option[I])](),None:Option[Char],"",f))((a,n)=>{n match{case i if i==':'=>if(a._4)(a._1:+(a._2.get->Some(a._3)),None,"",f)else(a._1,a._2,"",t)
case i if a._4=>(a._1,a._2,a._3+i,t)
case i if a._2.isEmpty=>(a._1,Some(i),"",f)
case i=>(a._1:+(a._2.get->None),Some(i),"",f)}})._1.map(x=>x._1 match{
case'<'=>M(v(x))
case'}'=>L(v(x))
case'^'=>J(v(x))
case'#'=>U(v(x))
case'@'=>Q(v(x))
case'&'=>N(v(x))
case c=>F(c)})}}
A(X(args(0))).e}

私はGithubに未ゴルフ版を投稿し、その際にリンクを提供します。今のところ、元のバージョンをここに投稿します。

import java.util.Scanner
import scala.util.Try

trait Operation {
  def hexToLong(hex:String):Long = BigInt(hex, 16).longValue()
}

trait Parameter {
  def param:String
}


trait RegisterOperation extends Operation { def apply(registers:List[Long]):List[Long] }
trait StackOperation extends Operation { def apply(registers:List[Long], stack:List[Long]):(List[Long], List[Long]) }
trait SpecialOperation extends Operation
trait SpecialRegisterOperation extends SpecialOperation with Parameter  { def apply(registers:List[Long]):Boolean }

class Move(val param:String) extends RegisterOperation with Parameter { override def apply(registers:List[Long]): List[Long] = hexToLong(param) :: registers.tail }
class Swap extends RegisterOperation { override def apply(registers:List[Long]): List[Long] = registers(1) :: registers(0) :: registers(2) :: Nil }
class InputNumber extends RegisterOperation { override def apply(registers:List[Long]): List[Long] = hexToLong(new Scanner(System.in).next("[0-9a-fA-F]+")) :: registers.tail }
class InputAscii extends RegisterOperation {
  override def apply(registers:List[Long]): List[Long] = (System.in.read() match {
  case i if i == -1 => 0
  case i => i}) :: registers.tail }

class PrintNumber extends RegisterOperation { override def apply(registers:List[Long]): List[Long] = { print(Integer.toHexString(registers(2).toInt)); registers } }
class PrintAscii extends RegisterOperation { override def apply(registers:List[Long]): List[Long] = { print(registers(2).toChar); registers } }
class RegisterRollLeft extends RegisterOperation { override def apply(registers:List[Long]): List[Long] = registers.tail :+ registers.head }
class RegisterRollRight extends RegisterOperation { override def apply(registers:List[Long]): List[Long] = registers(2) :: registers(0) :: registers(1) :: Nil }

class Add extends RegisterOperation { override def apply(registers:List[Long]): List[Long] =  registers(0) :: registers(1) :: (registers(0) + registers(1)) :: Nil }
class Subtract extends RegisterOperation { override def apply(registers:List[Long]): List[Long] =  registers(0) :: registers(1) :: (registers(0) - registers(1)) :: Nil }
class Multiply extends RegisterOperation { override def apply(registers:List[Long]): List[Long] =  registers(0) :: registers(1) :: (registers(0) * registers(1)) :: Nil }
class Divide extends RegisterOperation { override def apply(registers:List[Long]): List[Long] =  registers(0) :: (registers(0) % registers(1)) :: (registers(0) / registers(1)) :: Nil }

class Clear extends StackOperation { override def apply(registers:List[Long], stack:List[Long]) = registers -> List() }
class Enqueue extends StackOperation { override def apply(registers:List[Long], stack:List[Long]) = registers -> (registers(2) :: stack) }
class Dequeue extends StackOperation { override def apply(registers:List[Long], stack:List[Long]) = (stack.head :: registers.tail) -> stack.tail }
class QueueRollLeft(val param:String) extends StackOperation with Parameter {
  def roll(stack:List[Long], i:Int):List[Long] = {
    val s = stack.tail :+ stack.head
    if (i > 0) roll(s, i-1) else s
  }

  override def apply(registers:List[Long], stack:List[Long]) = registers -> roll(stack, Try(param.toInt).toOption.getOrElse(1))
}

class QueueRollRight(val param:String) extends StackOperation with Parameter {
  def roll(stack:List[Long], i:Int):List[Long] = {
    val s = stack.last :: stack.iterator.sliding(2).map(_.head).toList
    if (i > 0) roll(s, i-1) else s
  }

  override def apply(registers:List[Long], stack:List[Long]) = registers -> roll(stack, Try(param.toInt).toOption.getOrElse(1))
}

class SetLabel(val param:String) extends SpecialOperation with Parameter
class JumpLabelIfZero(val param:String) extends SpecialRegisterOperation { override def apply(registers: List[Long]): Boolean = registers(2) == 0 }
class JumpLabelIfNotZero(val param:String) extends SpecialRegisterOperation { override def apply(registers: List[Long]): Boolean = registers(2) != 0 }

class Script(val instructions:Array[Operation],
             val labels:Map[String, Int]) {
  def execute() = {
    var registers = List[Long](0, 0, 0)
    var stack = List[Long]()
    var idx = 0;

    while(idx < instructions.length) {
      idx = instructions(idx) match {
        case i: SpecialRegisterOperation => if(i(registers)) labels(i.param) else idx + 1
        case i: RegisterOperation => { registers = i(registers); idx + 1 }
        case i: StackOperation => { val (zregisters, zstack) = i(registers, stack); registers = zregisters; stack = zstack; idx + 1 }
        case _ => idx + 1
      }
    }
  }
}

object Script {
  def apply(instructions: Seq[Operation]):Script = {
    new Script(instructions = instructions.toArray, labels = Map(instructions.zipWithIndex.flatMap {
      case (e:SetLabel, i) => Some(e.param -> i)
      case _ => None
    }.toList:_*))
  }
}

object Parser {
  def apply(input:String): Seq[Operation] = {
    case class Accumulator(val list: List[(Char, Option[String])] = List(), val char:Option[Char] = None, val str:String = "", val parsingVar:Boolean = false)

    (input + " ").foldLeft(Accumulator())((acc, next) => {
      next match {
        case i if i == ':' => if(acc.parsingVar) Accumulator(acc.list :+ (acc.char.get -> Some(acc.str)), None, "", false) else Accumulator(acc.list, acc.char, "", true)
        case i if acc.parsingVar => Accumulator(acc.list, acc.char, acc.str + i, true)
        case i if !acc.char.isDefined => Accumulator(acc.list, Some(i), "", false)
        case i => Accumulator(acc.list :+ (acc.char.get -> None), Some(i), "", false)
      }
    }).list.map(x => x._1 match {
      case '<' => new Move(x._2.getOrElse(""))
      case 'x' => new Swap
      case '}' => new SetLabel(x._2.getOrElse(""))
      case '|' => new InputNumber
      case '!' => new InputAscii
      case '%' => new PrintNumber
      case '$' => new PrintAscii
      case '~' => new RegisterRollLeft
      case '=' => new RegisterRollRight
      case '^' => new JumpLabelIfNotZero(x._2.getOrElse(""))
      case '#' => new JumpLabelIfZero(x._2.getOrElse(""))
      case '?' => new Clear
      case '>' => new Enqueue
      case '{' => new Dequeue
      case '@' => new QueueRollLeft(x._2.getOrElse(""))
      case '&' => new QueueRollRight(x._2.getOrElse(""))
      case '+' => new Add
      case '-' => new Subtract
      case '*' => new Multiply
      case '/' => new Divide
    })
  }
}

object Go extends App {
  Script(Parser(args(0))).execute()
}

2

Flex / C ++、848 838バイト

%{
#include<map>
#include<deque>
using namespace std;typedef uint64_t I;I X,Y,Z,P,T,i;map<string,I>L;deque<I>Q;
#define YY_USER_ACTION P+=yyleng;
#define A for(i=0;i<(yyleng>2?stoull(yytext+2,0,16):1);++i
#define B fseek(yyin,L.at(yytext+1),0),yyrestart(yyin);
%}
H :[0-9A-F]+:
B :[0-9a-zA-Z_]+:
%x E
%%
<E>\}{B} L[yytext+1]=P;
<E>.|\n
\<{H} X=stoull(yytext+2,0,16);
x T=X;X=Y;Y=T;
\}{B}
\| scanf("%lx",&X);
! X=getchar();
% printf("%lx",Z);
\$ putchar(Z);
~ T=X;X=Y;Y=Z;Z=T;
= T=Y;Y=X;X=Z;Z=T;
\^{B} if(Z)B
#{B} if(!Z)B
\? Q.clear();
> Q.push_back(Z);
\{ X=Q.front();Q.pop_front();
@{H}? A)T=Q.front(),Q.pop_front(),Q.push_back(T);
&{H}? A)T=Q.back(),Q.pop_back(),Q.push_front(T);
\+ Z=X+Y;
- Z=X-Y;
\* Z=X*Y;
\/ Z=X/Y;Y=X%Y;
.|\n
%%
main(int,char**v){yyin=fopen(v[1],"r");BEGIN(E);yylex();rewind(yyin);yyrestart(yyin);BEGIN(0);yylex();}

コンパイル済み:

flex -o 0815.cpp 0815.ll
g++ -std=c++11 0815.cpp -o 0815 -ll

他のlexesでもコンパイルできるかもしれませんが、チェックしませんでした。2つのパスで機​​能するため、前方ジャンプは正しく処理されます。ラベル名は、テストケースで複数回発生するため、数字で始めることができます。仕様に従って、16進リテラルは大文字のみにすることができます。

Esolangs Wikiおよび0815ページで見つかったものを含む、すべてのテストケースに合格します。エラー処理は存在せず、未知のラベルでの終了は優雅ではありません。これはすべてコードゴルフです。

OPが0815をいじくり続けることができるように、私はリリースのために、無料の(そしてもっと素晴らしい)インタプリタを準備しています。


ビールのサンプルの99本のボトルは、新しい行の\r代わりに使用します\n(古い学校のMac OS?)./0815 99bb.0815 | tr "\r" "\n"。フィボナッチも同様です。
ステファノサンフィリッポ

2

Common Lisp、1088バイト

(progn(defun r(s)(parse-integer s :radix 16))(defun h(k)(coerce(loop for c =(#7=read-char()())while(funcall k c)collect c finally(unread-char c))'string))(defun w(c)(find c"0123456789ABCDEFabcdef"))(defmacro c(s)(with-input-from-string(*standard-input* s)(labels((L()(intern(p #'u)))(o()(case(peek-char()())(#\:(r(q))(#7#))(t 1)))(q()(p #'w))(p(k)(prog2(#7#)(h k)(#7#)))(u(c)(char/= c #\:)))`(let((x 0)(y 0)(z 0)(q(list())))(labels((&(n)(q(nconc(last(car q)n)(butlast(car q)n))))(@(n)(q(nconc(nthcdr n(car q))(subseq(car q)0 n))))(q(x)(#3=setf q(cons x(last x)))))(prog(),@(loop for c =(#7#()())while c collect(case c(#\<`(#3#x,(r(q))))(#\x`(#5=rotatef x y))(#\}(L))(#\|`(#3#x(r(h'w))))(#\!`(#3#x(char-code(#7#))))(#\%`(format t"~x"z))(#\$`(princ(code-char z)))(#\~`(#5#x y z))(#\=`(#5#z y x))(#\^`(if(/= z 0)(go,(L))))(#\#`(if(= 0 z)(go,(L))))(#\?`(#3#q(q())))(#\>'(if(car q)(#3#(cddr q)(list z)(cdr q)(cddr q))(#3#(cdr q)(#3#(car q)(list z)))))(#\{'(#3#x(pop(car q))))(#\@`(@,(o)))(#\&`(&,(o)))(#\/'(#3#(values z y)(truncate x y)))(t`(#3#z(,(elt'(+ * -)(position c"+*-"))x y))))))))))))

非ゴルフ

実行時にオプションのトレースを使用します。

;;; Those auxiliary functions are needed both
;;; during macroexpansion and evaluation

(defun r(s)
  (parse-integer s :radix 16))

(defun h(k)
  (coerce (loop for c = (read-char nil nil)
                while (funcall k c)
                collect c
                finally (unread-char c))
          'string))

(defun w(c)
  (find c "0123456789ABCDEFabcdef"))


;;; C is a macro, it takes a string, replaces it by 
;;; code, which is then evaluated.

(defmacro C(s &optional tracep)
  (with-input-from-string(*standard-input* s)
    (labels((L()(intern(p #'u)))
            (d()(assert(eql #\:(read-char))))
            (o(d)(case (peek-char () () ())
                   (#\:(r(q))(d))
                   (t d)))
            (q()(p #'w))
            (p(k)(prog2(d)(h k)(d)))
            (u(c)(not(eql c #\:))))
      `(let((x 0)(y 0)(z 0)(q(list())))
         (labels((&(n)(q(append(last(car q)n)(butlast(car q)n))))
                 (@(n)(q(nconc(nthcdr n(car q))(subseq(car q)0 n))))
                 (q(x)(setf q(cons x(last x)))))
           (tagbody
              ,@(loop for c =(read-char nil ())
                      while c
                      when tracep
                        collect '(fresh-line)
                        and collect `(print (list :c ,c :x x :y y :z z :q q :s (map'string'code-char(car q))))
                      collect
                      (ecase c
                        (#\<`(setf x ,(r(q))))
                        (#\x`(rotatef x y))
                        (#\}(L))
                        (#\|`(setf x(r(h'w))))
                        (#\!`(setf x(char-code(read-char))))
                        (#\%`(format t"~x"z))
                        (#\$`(princ(code-char z)))
                        (#\~`(rotatef x y z))
                        (#\=`(rotatef z y x))
                        (#\^`(if(not(zerop z))(go,(L))))
                        (#\#`(if(zerop z)(go,(L))))
                        (#\?`(setf q(q())))
                        (#\>'(if(car q)(setf(cddr q)(list z)(cdr q)(cddr q))(setf(cdr q)(setf(car q)(list z)))))
                        (#\{'(setf x(pop(car q))))
                        (#\@`(@,(o 1)))
                        (#\&`(&,(o 1)))
                        (#\/'(multiple-value-setq(z y)(truncate x y)))
                        ((#\+ #\* #\-)`(,(intern(string c)"CL")x y)))
                      when tracep
                        collect `(print (list :c ,c :x x :y y :z z :q q :s (map'string'code-char(car q)))))))))))

フィボナチ

(c "%<:0A:>~$<:01:~%>=<:68a3dd8e61eccfbd:>~>}:_s:{x{={~$x+%{=>~>x~-x<:0A:~>~>~^:_s:?")

マクロ展開

(LET ((X 0) (Y 0) (Z 0) (Q (LIST NIL)))
  (LABELS ((& (N)
             (Q (NCONC (LAST (CAR Q) N) (BUTLAST (CAR Q) N))))
           (@ (N)
             (Q (NCONC (NTHCDR N (CAR Q)) (SUBSEQ (CAR Q) 0 N))))
           (Q (X)
             (SETF Q (CONS X (LAST X)))))
    (PROG ()
      (FORMAT T "~x" Z)
      (SETF X 10)
      (IF (CAR Q)
          (SETF (CDDR Q) (LIST Z)
                (CDR Q) (CDDR Q))
          (SETF (CDR Q) (SETF (CAR Q) (LIST Z))))
      (ROTATEF X Y Z)
      (PRINC (CODE-CHAR Z))
      (SETF X 1)
      (ROTATEF X Y Z)
      (FORMAT T "~x" Z)
      (IF (CAR Q)
          (SETF (CDDR Q) (LIST Z)
                (CDR Q) (CDDR Q))
          (SETF (CDR Q) (SETF (CAR Q) (LIST Z))))
      (ROTATEF Z Y X)
      (SETF X 7540113804746346429)
      (IF (CAR Q)
          (SETF (CDDR Q) (LIST Z)
                (CDR Q) (CDDR Q))
          (SETF (CDR Q) (SETF (CAR Q) (LIST Z))))
      (ROTATEF X Y Z)
      (IF (CAR Q)
          (SETF (CDDR Q) (LIST Z)
                (CDR Q) (CDDR Q))
          (SETF (CDR Q) (SETF (CAR Q) (LIST Z))))
     |_s|
      (SETF X (POP (CAR Q)))
      (ROTATEF X Y)
      (SETF X (POP (CAR Q)))
      (ROTATEF Z Y X)
      (SETF X (POP (CAR Q)))
      (ROTATEF X Y Z)
      (PRINC (CODE-CHAR Z))
      (ROTATEF X Y)
      (SETF Z (+ X Y))
      (FORMAT T "~x" Z)
      (SETF X (POP (CAR Q)))
      (ROTATEF Z Y X)
      (IF (CAR Q)
          (SETF (CDDR Q) (LIST Z)
                (CDR Q) (CDDR Q))
          (SETF (CDR Q) (SETF (CAR Q) (LIST Z))))
      (ROTATEF X Y Z)
      (IF (CAR Q)
          (SETF (CDDR Q) (LIST Z)
                (CDR Q) (CDDR Q))
          (SETF (CDR Q) (SETF (CAR Q) (LIST Z))))
      (ROTATEF X Y)
      (ROTATEF X Y Z)
      (SETF Z (- X Y))
      (ROTATEF X Y)
      (SETF X 10)
      (ROTATEF X Y Z)
      (IF (CAR Q)
          (SETF (CDDR Q) (LIST Z)
                (CDR Q) (CDDR Q))
          (SETF (CDR Q) (SETF (CAR Q) (LIST Z))))
      (ROTATEF X Y Z)
      (IF (CAR Q)
          (SETF (CDDR Q) (LIST Z)
                (CDR Q) (CDDR Q))
          (SETF (CDR Q) (SETF (CAR Q) (LIST Z))))
      (ROTATEF X Y Z)
      (IF (/= Z 0)
          (GO |_s|))
      (SETF Q (Q NIL)))))

出力

0
1
1
2
3
5
8
D
15
22
37
59
90
...
5D4D629E80D5489
96F75D79B354522
F444C01834299AB
18B3C1D91E77DECD
27F80DDAA1BA7878
40ABCFB3C0325745
68A3DD8E61ECCFBD

多分後で説明する


1

Pythonの3、1573、1499のバイト

http://paulo-jorente.de/poncho/esolang/0815/でサンプルプログラムを実行し、すべての命令を実装します(元の仕様によると、記述も含めて)。

コマンドラインで渡されたソースファイルを実行します。

import sys
from collections import deque
class w:
    q=deque()
    X=Y=Z=c=0
    def __init__(k):k.s=open(sys.argv[1],'r').read()
    def a(k,l):
        i=k.s.find("}:"+l+":")
        if (i<0):sys.exit()
        return i
    def l(k):
        k.c+=1
        if k.s[k.c]!=":":sys.exit(":")
        k.c+=1
        return k.s[k.c:k.c+k.s[k.c:].find(":")]
    def u(k):
        k.c+=1
        if k.s[k.c]!=":":sys.exit(":")
        k.c+=1
        h=k.s[k.c:k.c+k.s[k.c:].find(":")]
        k.c+=len(h)
        return h
    def b(k):
        g=range
        j=input
        z=len
        w=sys.stdout.write
        o=k.s[k.c]
        y=k.q.rotate
        if o=='<':k.X=int(k.u(),16)
        elif o=='x':t=k.X;k.X=k.Y;k.Y=t
        elif o=='=':t=k.X;k.X=k.Z;v=k.Y;k.Y=t;k.Z=v;
        elif o=='$':
            if (k.Z==0x0d):w('\n')
            else:w(str(chr(k.Z%256)))
        elif o=='%':w(str(k.Z))
        elif o=='~':t=k.X;v=k.Y;k.X=v;k.Y=k.Z;k.Z=t;
        elif o=='?':k.q.clear()
        elif o=='>':k.q.append(k.Z)
        elif o=='{':k.X=k.q.popleft()
        elif o=='@':
            if k.s[k.c+1]==':':
                t=k.u()
                for i in g(0,int(t,16)):y(-1)
            else:
                y(-1)
        elif o=='&':
            if k.s[k.c+1]==':':
                t=k.u()
                for i in g(0,int(t,16)):y(1)
            else:
                y(1)
        elif o=='}':
            k.c+=z(k.l())
        elif o=='#':
            l=k.l()
            if (k.Z==0):
                k.c=k.a(l)-1
            else:
                k.c+=z(l)
        elif o=='^':
            l=k.l()
            if (k.Z!=0):
                k.c=k.a(l)-1
            else:
                k.c+=z(l)
        elif o=='|':k.X=int(j("?"),16)
        elif o=='!':k.X=ord(j(">")[0])
        elif o=='+':k.Z=k.X+k.Y
        elif o=='-':k.Z=k.X-k.Y
        elif o=='*':k.Z=k.X*k.Y
        elif o=='/':
            k.Z=int(k.X/k.Y)
            k.Y=k.X%k.Y
        k.c+=1
    def x(k):
        while k.c<len(k.s):k.b()
w().x()

2
いくつかのバグで実行する」は通常、受け入れられる答えではありません。
フェーズ

@phase:修正されました。
ガブリエーレダントーナ

1
これはコードゴルフです!なぜすべての空白がありますか?なぜすべての2バイト変数名ですか?
キントピア

これは、Python 3で実行しているためかもしれません(ちなみに、に変更j=raw_inputした後でもj=input機能します)が、「99 Bottles of Beer」プログラムでは機能しません。サンプル(改行の場合は「//」):「壁にビール0x63 // 0x63tles // 0x62を1つ下に置き、壁にビール0 / 62xtles // 0x62tleにビールを」// 0x61 oneダウンして、それを渡す」)
ティムペデリック

@TimPederick:そのとおりです。元のインタープリター(.exe)を実行できましたか?期待される結果は何ですか?
ガブリエレダントーナ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.