Tulis penerjemah 0815


26

Saya suka konsep 0815 , kecuali penerjemah di situs web pembuatnya mengembalikan Kesalahan 404. Jadi saya memutuskan untuk meminta Anda semua untuk membantu!

Dasar

0815 didasarkan pada tiga (3) register dan antrian. Register diberi nama X, Y, dan Z, dengan X menjadi hanya-tulis, Z menjadi hanya-baca, dan Y menjadi register "pembantu" yang tidak dapat diakses secara langsung. Semua register mulai diatur ke 0. Semua angka dalam heksadesimal.

Instruksi

Catatan: Beberapa instruksi mengambil parameter yang diformat seperti di }:hello:mana :hello:parameternya. Catatan lain: Beberapa deskripsi instruksi tidak jelas, jadi saya mengambil beberapa kebebasan dengannya. (Instruksi asli di sini )

~ berarti parameter diperlukan

----------|---|--------------------------------------------
  ~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
----------|---|--------------------------------------------

Instruksi Antrian

----------|---|--------------------------------------------
   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  |   | 
----------|---|--------------------------------------------

Instruksi aritmatika

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

Contoh program

Halo dunia: (Sedikit golf)

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

Kucing:

}:_t:!~$^:_t:

Mesin kebenaran:

|~}:i:%^:i:

Ini adalah , jadi pengiriman dengan byte paling sedikit akan menang!


3
Apa perbedaan antara ~dan ~dalam perintah "roll register" Anda? Apakah Anda memiliki contoh program yang dapat digunakan orang untuk menguji?
AdmBorkBork

3
Adakah contoh yang bisa Anda berikan kepada kami?
Conor O'Brien

1
@DanTheMan Saya melihat "Hello, Wlrod" ketika saya menjalankan contoh Hello World menggunakan implementasi (masih-WIP) saya ... Tidak yakin apakah itu bug dalam kode saya atau contoh itu sendiri
Ruslan

2
@DanTheMan Ya, tetapi mengubah tautan membuat Anda menjadi juru bahasa. :-)
Sven Menulis Kode

1
@penggunaandiperbaiki!
DanTheMan

Jawaban:


8

Pip , 321 262 248 byte

Sangat dipersingkat menggunakan eval dan beberapa trik Kolmogorov-kompleksitas.

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)}

Cobalah online! (Contohnya adalah program nomor Collatz / hailstone dari situs web penulis bahasa.)

Catatan:

  • Mengambil kode 0815 sebagai argumen baris perintah pertama dan input sebagai yang kedua. Ya, ini agak canggung (apalagi di TIO, di mana Anda mendapatkan kotak teks terpisah), tetapi Pip tidak terlalu pandai membaca semua stdin.
  • Angka dalam input harus menggunakan digit hex huruf besar (sesuai OP: cocok dengan regex [0-9A-F]+). Jika, pada |instruksi, karakter input berikutnya tidak 0-9A-F, pembacaan gagal dan menyebabkan perilaku yang berpotensi aneh. Ini berarti program genap penulis tidak bekerja seperti yang tertulis ... Saya tidak yakin bagaimana ia mengharapkan beberapa angka dibaca berfungsi, tapi saya hanya menerapkan sesuai dengan apa yang dikatakan spec.
  • Jika label digandakan, lompatan masuk ke yang pertama. Jika label tidak ada, lompatan menghentikan program.

Versi ungolfed saya dengan komentar:

;;; 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 byte

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;}}}

atau dengan spasi putih:

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;
}}}

Berhasil bermain golf dengan haxe? Wow.


1
+1 untuk Haxe, jawaban terpendek di salah satu langs yang paling tidak golf
kucing

1
Tahukah Anda, jika Anda mengompilasi ini ke JS, apakah ini akan lebih pendek? maka kamu bisa membuatnya ES6 / ES7
cat

5

Python 3, 1320 byte

Versi yang tidak disatukan, serta analisis (dan jika perlu, versi yang diperbaiki) dari program pengujian, dapat ditemukan di intisari ini .

Keputusan desain:

  • Berbagai definisi label diabaikan. Hanya definisi pertama label yang digunakan. (Sebelumnya definisi yang paling baru dilihat akan digunakan, tetapi itu dihapus.)
  • Input sesuai dengan spesifikasi OP: input numerik membaca karakter hex dengan rakus. (Awalnya akan membaca hingga baris baru, dan kesalahan ketika karakter non-hex dibaca.)
  • Input "ASCII" diartikan sebagai input "byte-oriented". (Awalnya itu memiliki dukungan Unicode penuh, yang mengambil lebih sedikit kode berkat menjadi Python 3 ... tetapi memenuhi poin-poin berikutnya berarti membaca byte demi byte sekarang lebih pendek.)
  • Parameter di mana tidak ada parameter yang diharapkan diabaikan; karenanya, mereka dapat digunakan sebagai komentar.

Ada masalah dengan contoh program menggunakan CR saja sebagai baris baru mereka (kadang-kadang), yang membuat shell saya menimpa baris saat ini daripada memulai yang baru. Ini memengaruhi program Fibonacci Sequence dan 99 Bottles of Beer. Ayat terakhir dari 99 Botol Bir juga tidak mencetak dengan benar, dan saya masih menyelidiki sebabnya.

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 byte

Selain kendala yang dijabarkan dalam pertanyaan, juru bahasa ini ditulis untuk bersandar sebanyak mungkin terhadap prinsip-prinsip FP. Secara khusus:

  • Hanya struktur abadi
  • Semua fungsi murni

Ini dicapai, dengan pengecualian dari empat baris kode yang menggerakkan loop utama dari interpreter. Struktur yang tidak dapat diubah sangat sulit untuk digunakan di sini karena keadaan register mendorong aliran kontrol dari loop (khususnya dua pernyataan GOTO). Saya masih berpikir tentang bagaimana mengubahnya menjadi menggunakan struktur murni & tidak dapat diubah, tetapi itu tidak relevan dengan tantangan golf kode.

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}

Saya akan memposting versi tidak berjubah di Github dan akan memberikan tautan ketika saya melakukannya. Untuk saat ini, saya akan memposting versi aslinya di sini:

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 byte

%{
#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();}

Dikompilasi dengan:

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

Mungkin dikompilasi dengan lexes lain juga, tapi saya tidak memeriksanya. Ia bekerja dalam dua lintasan, sehingga lompatan ke depan ditangani dengan benar. Nama label diizinkan untuk memulai dengan angka, karena itu terjadi lebih dari satu kali dalam kasus uji. Hex literal hanya dapat huruf besar, sesuai dengan spesifikasi.

Lewati semua kasus uji, termasuk yang ditemukan di Esolangs Wiki dan halaman 0815. Penanganan kesalahan tidak ada dan keluar pada label yang tidak dikenal tidak anggun, setelah semua ini adalah kode-golf.

Saya sedang mempersiapkan penerjemah yang tidak disolf (dan jauh lebih baik) untuk rilis, sehingga OP dapat terus bermain-main dengan 0815. Tetap disini :)


99 botol bir yang digunakan contoh \rbukan \nsebagai baris baru (OS OS jadul?), Jadi jika Anda ingin melihat sesuatu dicetak pada penggunaan layar ./0815 99bb.0815 | tr "\r" "\n". Sama untuk Fibonacci.
Stefano Sanfilippo

2

Common Lisp, 1088 bytes

(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))))))))))))

Tidak disatukan

Dengan penelusuran opsional saat runtime.

;;; 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)))))))))))

Fibonnaci

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

Ekspansi makro

(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)))))

Keluaran

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

Mungkin lebih banyak penjelasan nanti


1

Python 3, 1573 , 1499 byte

Menjalankan contoh program di http://paulo-jorente.de/poncho/esolang/0815/ dan mengimplementasikan semua instruksi (bahkan yang tertulis, sesuai dengan spesifikasi asli).

Menjalankan file sumber yang diteruskan pada baris perintah.

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
" Berjalan dengan beberapa bug " biasanya bukan jawaban yang dapat diterima.
fase

@phase: sudah diperbaiki sekarang.
Gabriele D'Antona

1
Ini golf kode, kawan! mengapa semua spasi? mengapa semua nama variabel 2-byte?
kuintopia

Ini mungkin karena saya menjalankannya dalam Python 3 (yang bekerja, omong-omong, setelah berganti j=raw_inputke j=input), tetapi itu tidak berhasil bagi saya pada program "99 Bottles of Beer". Contoh ("//" untuk baris baru): "0x63 // 0x63jelas bir di dinding // 0x62 satu turun dan letakkan sekitar // 0x62jelas bir di dinding // 0x62jelas bir di dinding // 0x61 satu bir turun dan menyebarkannya ")
Tim Pederick

@TimPederick: Anda benar. Apakah Anda berhasil menjalankan juru bahasa asli (.exe)? Apa hasil yang diharapkan?
Gabriele D'Antona
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.