Golf một phiên dịch màu tím


13

Golf một phiên dịch màu tím

Màu tím là một esolang được thiết kế với hai mục đích chính:

  • Để giảm thiểu Aubergine , vì không có đủ các ngôn ngữ một hướng dẫn tự sửa đổi xung quanh.
  • Phải thừa nhận khả năng phiên dịch golf nhỏ đáng sợ . Vượt qua đầu tiên của tôi tại một trình thông dịch Python 2 đầy đủ tính năng hợp lý chỉ có 702 byte và tôi chắc chắn một người chơi gôn có kinh nghiệm hơn có thể cạo khá nhiều từ đó.

Mục tiêu của bạn là viết một thông dịch viên cho ngôn ngữ này.

Thông tin về màu tím:

Một chương trình màu tím là một chuỗi các ký tự được đặt vào một mảng bộ nhớ có thể định địa chỉ vô hạn sao cho ký tự đầu tiên của chương trình được đặt ở địa chỉ 0. Phần còn lại của mảng (cả trước và sau khi chương trình Purple được lưu trữ) được khởi tạo thành không.

Có ba thanh ghi màu Tím, được gọi là abi , mỗi thanh ghi có thể chứa một số nguyên đã ký và được khởi tạo thành không. i cũng là con trỏ lệnh và luôn trỏ đến lệnh Purple hiện đang thực thi.

Mỗi chu kỳ, trình thông dịch sẽ đọc một chuỗi gồm ba ký tự liền kề bắt đầu từ vị trí bộ nhớ được chỉ định bởi con trỏ lệnh và cố gắng thực hiện chuỗi này dưới dạng lệnh Purple. Sau đó, con trỏ lệnh luôn được tăng thêm 3.

Về mặt cú pháp, lệnh Purple bao gồm ba ký tự (hoặc mã hóa chúng) liên tiếp, như " xyz ".

Ký tự đầu tiên x có thể là một trong các ký tự sau:

abABio

Những biểu tượng này có ý nghĩa như sau:

a - Place the result in register a.
b - Place the result in register b.
A - Place the result in the location in memory referred to by register a.
B - Place the result in the location in memory referred to by register b.
i - Set the instruction pointer to the result.
o - Output the result to stdout.

Hai byte yz khác có thể là bất kỳ thứ nào sau đây:

abABio1

Mỗi biểu tượng này có ý nghĩa như sau:

a - Return the contents of register a.
b - Return the contents of register b.
A - Return the contents of the memory array at the address stored in register a.
B - Return the contents of the memory array at the address stored in register b.
i - Return the contents of register i (the instruction pointer).
o - Return the value of a single character read from stdin.
1 - Return the literal numeric value 1.

Sau khi tìm nạp hướng dẫn, trình thông dịch Purple sẽ đánh giá y và sau đó z , trừ kết quả của z khỏi kết quả của y và sau đó thực hiện hành động được chỉ định bởi x về sự khác biệt.

Nếu chuỗi ba ký tự (hoặc mã hóa) không phải là một lệnh Purple hợp lệ, trình thông dịch sẽ dừng ngay lập tức mà không đưa ra bất kỳ lỗi nào.

Thông dịch viên của bạn phải:

  • Hãy là một chương trình hoàn chỉnh, không phải là một chức năng.
  • Không bao giờ xuất ra stderr, trừ khi EOF được đọc .
  • Hành xử giống hệt với việc thực hiện tham chiếu trên tất cả các đầu vào được hình thành tốt không liên quan đến số lượng rất lớn, bao gồm các chương trình thử nghiệm được đưa ra dưới đây. (Chà, giống hệt với thời gian - nó có thể chạy chậm hơn, nhưng không quá nhiều!)

Bạn có thể cung cấp chương trình cho trình thông dịch dưới bất kỳ hình thức nào bạn muốn: đọc nó từ một tệp, nhúng nó vào chương trình dưới dạng một chuỗi hoặc đọc nó từ stdin.

Các trường hợp thử nghiệm:

Chương trình

ooo

khi chạy với đầu vào

z!

nên nhường

Y

Chương trình

bbboobiii

khi chạy với đầu vào

It's a cat program.

(hoặc bất kỳ đầu vào nào khác) sẽ mang lại

It's a cat program.

(hoặc bất cứ thứ gì nó nhận được) và sau đó bắt đầu lại và làm lại điều tương tự .


Chương trình

Aoab11bi1bABoAaiba

khi chạy với đầu vào

0

nên nhường

0

và sau đó dừng lại, nhưng khi chạy với đầu vào

1

nên tiếp tục xuất ra

1

mãi mãi.


Chương trình

b1bbb1oAbabaa1ab1Ab1Bi1b

nên nhường

b1bbb1oAbabaa1ab1Ab1Bi1b

Chương trình

aA1aa1bb1oAbbi1bb1bbAb1Bi1b Purple is the awesomest! Why haven't you tried it yet?
!dlroW ,olleG

nên nhường

Hello, World!

Ghi điểm:

Đây là , vì vậy nguồn ngắn nhất tính bằng byte, có khả năng được sửa đổi bởi phần thưởng sau, sẽ thắng.

Tặng kem:

  • -10% nếu trình thông dịch của bạn đọc tên tệp từ stdin hoặc từ đối số dòng lệnh và tải chương trình từ tệp.

1
Kích thước của các ô nhớ là gì? byte, ký tự (unicode?), (tùy ý) số nguyên lớn? Có vẻ như bạn đang sử dụng "ký tự" và "byte" với cùng một nghĩa.
Paŭlo Ebermann

@ PaŭloEbermann dự đoán của tôi là cụ thể thực hiện; ví dụ tôi cần sử dụng uint32cho các ký tự và MAXINT cho ints
cat

2
@sysreq Đó thực sự là một công cụ chặn? Việc thực hiện của bạn chỉ đơn giản là có hai băng, một cho âm và một cho các chỉ số tích cực. (Vâng, điều này sẽ mất thêm một chút mã, nhưng tôi nghĩ là không nhiều.)
Paŭlo Ebermann

1
@sysreq về cơ bản, một trình thông dịch tự tím sẽ là một chương trình đọc chương trình Purple từ stdin và sau đó làm bất cứ điều gì chương trình đó sẽ làm. Chương trình Purple đầu tiên (trình thông dịch) có thể chạy trong bất kỳ trình thông dịch nào bạn thích. Một chương trình ghi đè hoàn toàn các địa chỉ bộ nhớ thấp nhất bằng đầu vào, sau đó xóa chính nó trước khi bằng cách nào đó chuyển sang mã đọc sẽ đủ điều kiện (mặc dù tôi không nghĩ rằng điều này thực sự có thể).
quintopia

2
Tôi đã đến rất gần để có một thời gian chạy có khả năng tự giải thích, nhưng tôi đã quá muộn.
con mèo

Câu trả lời:


7

Pyth, 148 128 121 byte (hoặc 124 * .9 = 111.6, xem phía dưới)

J,00=kjb.z .eXHkCbz#=b-Fm?=zx"oabABi1"C@H+Zd@s[0Jm.x@Hk0JZ1H)zCh~tkS2 ?hKx"abAB"=YC@HZ?PKXH@JKbXJKb?qY\i=Zb?qY\opCbvN=+Z3

Bộ kiểm tra

Mã được đưa ra trên dòng đầu tiên của STDIN, nhập vào chương trình Purple trên phần còn lại của STDIN. Để sử dụng mã với dòng mới, sử dụng phiên bản thay thế ở phía dưới.

Chơi golf hợp lý. Đây là phần ngắt dòng và thụt lề cho rõ ràng:

J,00
=kjb.z
 .eXHkCbz
#
  =b-Fm
    ?=zx"oabABi1"C@H+Zd
      @
        s[0Jm.x@Hk0JZ1H)
        z
      Ch~tk
    S2
   ?hKx"abAB"=YC@HZ
    ?PK
      XH@JKb
      XJKb
  ?qY\i=Zb
  ?qY\opCb
  vN
  =+Z3

Về cơ bản, một #vòng lặp thực hiện và tạm dừng thông qua lỗi phá vỡ.

abđược kết hợp thành một biến duy nhất , J. Zlà con trỏ chỉ dẫn. klà đầu vào cho chương trình Purple. Hlà băng, đại diện như một từ điển. blà kết quả hiện tại. Ylà byte đầu tiên hiện tại của hướng dẫn.

Đọc từ tập tin:

J,00=kjb.z .eXHkCbjb'z#=b-Fm?q\o=zC@H+ZdCh~tk@s[Jm.x@Hk0JZ1H)x"abABi1"zS2 ?hKx"abAB"=YC@HZ?PKXH@JKbXJKb?qY\i=Zb?qY\opCbvN=+Z3

Đặt tên tệp là dòng đầu tiên của STDIN. Chạy thử nghiệm:

$ cat purple-final.pyth 
J,00=kjb.z .eXHkCbjb'z#=b-Fm?=zx"oabABi1"C@H+Zd@s[0Jm.x@Hk0JZ1H)zCh~tkS2 ?hKx"abAB"=YC@HZ?PKXH@JKbXJKb?qY\i=Zb?qY\opCbvN=+Z3
$ cat purple-code.txt 
aA1aa1bb1oAbbi1bb1bbAb1Bi1b Purple is the awesomest! Why haven't you tried it yet?
!dlroW ,olleG
$ pyth purple-final.pyth <<< 'purple-code.txt' 
Hello, World!

5

JavaScript (ES6), 292 byte

eval(`a=b=i=d=0;v=n=>(x=m[i+n])==97?a_98?b_65?m[a]_66?m[b]_105?i_111?p()[c]()_49?1:d=1;for(m=[...(p=prompt)()].map(b=>b[c="charCodeAt"]());!d;i+=3)(y=v(1),d)||(z=v(2),d)?1:(x=m[r=y-z,i])==97?a=r_98?b=r_65?m[a]=r_66?m[b]=r_105?i=r-3_111?alert(String.fromCharCode(r)):d=1`.replace(/_/g,":x=="))

Giải trình

Câu trả lời JavaScript luôn kỳ lạ khi STDINSTDOUTđược yêu cầu ...

Dấu nhắc đầu tiên là đầu vào cho chuỗi chương trình. Mỗi dấu nhắc kết quả từ một olệnh sẽ chỉ đọc ký tự đầu tiên.

evalđược sử dụng để thay thế một cụm từ phổ biến giúp tiết kiệm một vài byte. Ungolfed và không có evalchương trình trông như thế này:

// Initialisation
a=b=i=                            // initialise registers to 0
  d=0;                            // d is set to true when the program should die

// Gets the result of Y or Z
v=n=>                             // n = offset from i
  (x=m[i+n])==97?a:               // x = value of instruction
  x==98?b:
  x==65?m[a]:
  x==66?m[b]:
  x==105?i:
  x==111?p()[c]():
  x==49?1:
  d=1;                            // if it was none of the valid values, die

// Execution loop
for(
  m=                              // m = memory array
    [...(p=prompt)()]             // receive the program
    .map(b=>b[c="charCodeAt"]()); // initialise m to the ASCII values of the program
  !d;                             // finish if an error occured
  i+=3                            // increment i
)
  (y=v(1),d)||                    // get the value of Y and check for errors
  (z=v(2),d)?1:                   // get the value of Z and check for errors

    // Get the result of X
    (x=m[r=y-z,i])==97?a=r:       // r = result of y - z
    x==98?b=r:
    x==65?m[a]=r:
    x==66?m[b]=r:
    x==105?i=r-3:
    x==111?alert(String.fromCharCode(r)):
    d=1

2
Thứ hai c="charCodeAt"có thể được thay thế bằng chỉ c?
Dendrobium

Có truy cập mảng với các chỉ số tiêu cực làm việc trong JavaScript?
nimi

@Dendrobium Wow, tôi không biết làm thế nào tôi bỏ lỡ điều đó haha! Cảm ơn.
dùng81655

2
@nimi Nó hoạt động. Bản thân mảng không hỗ trợ các chỉ số tiêu cực, nhưng điều này lợi dụng thực tế là chúng cũng hành xử như các đối tượng. array[-1] = 1cũng giống như array = { "-1": 1 }. Cả hai có thể được truy cập với array[-1].
dùng81655

@ user81655: Ah đẹp, không biết điều đó.
nimi

3

Ceylon, 827 792 671 byte

import ceylon.language{l=variable,I=Integer,x=nothing,p=process,m=map}shared void run(){try{if(exists d=p.arguments[0]){l value t=m{*d*.hash.indexed};l I a=0;l I b=0;l I i=0;I g(I j)=>t[j]else 0;l{I*}c=[];I o{if(c==[]){if(exists e=p.readLine()){c=e*.hash.chain{10};}else{c={-1}.cycled;}}assert(is I r=c.first);c=c.rest;return r;}value f=m{97->{a},98->{b},65->{g(a)},66->{g(b)},105->{i},111->{o},49->{1}};value s=m{97->((I v)=>a=v),98->((I v)=>b=v),65->((I v)=>t=m{a->v,*t}),66->((I v)=>t=m{b->v,*t}),105->((I v)=>i=v),111->((I v)=>p.write("``v.character``"))};I h(I v)=>f[v]?.first else x;while(0<1){(s[g(i)]else x)(h(g(i+1))-h(g(i+2)));i+=3;}}}catch(AssertionError e){}}

Nó hoạt động hơi khác so với triển khai tham chiếu khi chương trình cố đọc đầu vào tại EOF - việc triển khai tham chiếu gặp sự cố với TypeError, quá tốn kém để tái tạo ở đây (và cũng có thể là lỗi), vì vậy điều này sẽ trả về -1 thay vào đó ( nhiều lần, nếu cần thiết).

(Tuy nhiên, khi cố gắng viết -1 này vào thiết bị xuất chuẩn, trình thông dịch sẽ kết thúc với OverflowError. Tuy nhiên, điều tương tự sẽ xảy ra nếu một số nguyên nằm ngoài phạm vi Unicode được xuất ra.)

Trình thông dịch lấy chương trình làm đối số dòng lệnh đầu tiên của nó (đảm bảo trích dẫn nó cho trình bao của bạn khi nó chứa khoảng trắng hoặc các nội dung thú vị khác).

Trong Ceylon, chúng ta chỉ có thể dễ dàng đọc dòng đầu vào (tôi đoán điều này sẽ thay đổi ở một trong các phiên bản tiếp theo), vì vậy khi ođược sử dụng để đọc, tôi đang đọc toàn bộ dòng và đệm các phần để sử dụng trong tương lai. Tôi đoán nó hoạt động tương tự trong triển khai Python khi được kết nối với một thiết bị đầu cuối.


Khi cố gắng thực thi một lệnh (một phần) không phải là một trong các ký tự hợp lệ, nothingnó sẽ khiến Ass AssError bị ném, sau đó chúng ta sẽ bắt trong khối bắt xung quanh vòng lặp chính.

Tôi nghĩ rằng tốt nhất nên là loại Ngoại lệ tùy chỉnh (vì AssertsError cũng có thể xảy ra ở những nơi khác nếu tôi gặp lỗi), nhưng điều đó sẽ tốn nhiều không gian hơn, ăn hầu hết các cải tiến tôi đã thực hiện từ phiên bản đầu tiên.

Một số thủ thuật được sử dụng để chơi gôn:

  • Các phiên bản trước đã sử dụng ceylon.collection.HashMap - thay vào đó chúng ta sử dụng bản đồ bất biến như được tạo bởi maphàm và tạo một bản đồ mới mỗi lần Ahoặc Bđược sử dụng dưới dạng x .
  • Tôi sử dụng nhập khẩu bí danh cho tất cả các định danh từ ceylon. Ngôn ngữ được sử dụng nhiều lần (bao gồm cả variablechú thích, hiện làl ).
  • Tôi đã thoát khỏi lớp E(đối với môi trường) và sphương thức (bước) - mọi thứ bây giờ xảy ra bên trongrun hàm.
  • Thay vì sử dụng .integerđể lấy mật mã của một ký tự, .hashcho kết quả tương tự. Như vậy string*.hashlà giống nhưstring.map(Character.integer) (đưa ra một lần lặp của các điểm mã từ một chuỗi).
  • Khi một loại được nhập bí danh, is I ...ngắn hơn exists ....
  • Khi chuyển đổi một cái gì đó (ví dụ x) thành một chuỗi, "``t``"ngắn hơn t.string(hoặc, những gì tôi đã sử dụng cho một ký tự, String{t}).
  • các chức năng được sử dụng chỉ một lần thường có thể được nội tuyến.

Đây là phiên bản được định dạng (và nhận xét):

// Purple – a self-modifying, "one-instruction" language.
//
// Question:  http://codegolf.stackexchange.com/q/65411/2338
// My answer: http://codegolf.stackexchange.com/a/65492/2338

import ceylon.language {
    l=variable,
    I=Integer,
    x=nothing,
    p=process,
    m=map
}

shared void run() {
    try {
        // Reading code from file certainly takes more than 73 characters,
        // this isn't worth the 10% bonus.
        if (exists d = p.arguments[0]) {

            // The memory tape, as a Map<Integer, Integer>.
            // We can't modify the map itself, but we
            // can replace it by a new map when update is needed.
            l value t = m {
                // It is initialized with the code converted to Integers.
                // We use `.hash` instead of `.integer` because it is shorter.
                *d*.hash.indexed };

            // three registers
            l I a = 0;
            l I b = 0;
            l I i = 0;

            // get value from memory
            I g(I j) =>
                    t[j] else 0;

            // cached input which is still to be read
            l {I*} c = [];

            // get value from stdin.
            // we can only comfortably access stdin by line, so we read a whole line
            // and cache the rest for later.
            I o {
                if (c == []) {
                    if (exists e = p.readLine()) {
                        c = e*.hash.chain { 10 }; // convert string into ints, append \n
                    } else {
                        // EOF – return just -1 from now on.
                        c = { -1 }.cycled;
                    }
                }
                assert (is I r = c.first);
                c = c.rest;
                return r;
            }


            // Map of "functions" for fetching values.
            // We wrap the values in iterable constructors for lazy evaluation
            //  – this is shorter than using (() => ...).
            // The keys are the (Unicode/ASCII) code points of the mapped
            // source code characters.
            value f = m {
                // a
                97 -> { a },
                // b
                98 -> { b },
                // A
                65 -> { g(a) },
                // B
                66 -> { g(b) },
                // i
                105 -> { i },
                // o
                111 -> { o },
                // 1
                49 -> { 1 }
            };

            // Map of functions for "storing" results.
            // The values are void functions taking an Integer,
            // the keys are the ASCII/Unicode code points of the corresponding
            // source code characters.
            value s = m {
                // a
                97 -> ((I v) => a = v),
                // b
                98 -> ((I v) => b = v),
                // Modification of the memory works by replacing the map with a new one.
                // This is certainly not runtime-efficient, but shorter than importing
                // ceylon.collections.HashMap.
                // A
                65 -> ((I v) => t = m { a->v, *t }),
                // B
                66 -> ((I v) => t = m { b->v, *t }),
                // i
                105 -> ((I v) => i = v),
                // o – output as a character.
                111 -> ((I v) => p.write("``v.character``"))
            };

            // accessor function for the f map
            I h(I v) =>
                    f[v]?.first else x;

            // the main loop, can only be left by exception
            while (0 < 1) {
                (s[g(i)] else x)(h(g(i + 1)) - h(g(i + 2)));
                i += 3;
            }
        }
    } catch (AssertionError e) {
        // abort silently
    }
}

Tôi đã sử dụng lại một phần của mã đó cho một "trình thông dịch song song" đang cố gắng tìm tất cả các chương trình tạm dừng. (. Có rất nhiều trong số họ) (Ở đó tôi sử dụng một phiên bản không-I / O của màu tím, như I / O mất rất nhiều không gian và không được sử dụng trong nhiệm vụ đó.)
Paulo Ebermann
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.