Thông dịch viên ngôn ngữ Turing-Complete


42

Một thách thức tôi nghĩ rằng sẽ rất tuyệt vời là làm phiên dịch cho một ngôn ngữ hoàn chỉnh Turing mà bạn chọn.

Các quy tắc rất đơn giản:

  1. Bạn có thể sử dụng bất kỳ ngôn ngữ nào để tạo trình thông dịch này ngay cả khi nó mới hơn thử thách này.
  2. Bạn có thể sử dụng bất kỳ ngôn ngữ hoàn chỉnh Turing nào miễn là nó không giống với ngôn ngữ bạn đang viết.
  3. Bạn không thể đơn giản đánh giá mã ví dụ sử dụng các hàm eval.
  4. Một lời giải thích về cách bạn tiếp cận điều này sẽ tốt đẹp nhưng không bắt buộc.
  5. Điều này sẽ được ghi bằng byte.
  6. Mỗi bài nộp phải hoạt động đầy đủ có nghĩa là mọi tính năng mà ngôn ngữ bạn chọn phải có.

Nói một cách đơn giản:

Nhiệm vụ của bạn là tạo một trình thông dịch làm việc cho bất kỳ ngôn ngữ hoàn chỉnh Turing nào với bất kỳ ngôn ngữ nào bạn chọn.

Chúc may mắn!


3
Tôi cũng muốn đề xuất một quy tắc rằng ngôn ngữ được triển khai phải khác với ngôn ngữ mà bạn sử dụng để triển khai nó, để ngăn chặn các evalgiải pháp giống như tầm thường .
Sản xuất ETH

1
Trên thực tế, bạn có thể muốn chỉ cấm evalcác lệnh / hàm, vì một số ngôn ngữ đã tích hợp sẵn để đánh giá mã bằng ngôn ngữ khác.
Sản xuất ETH

2
@arodebaugh Đối với những thách thức trong tương lai, bạn có thể đăng ý tưởng của mình vào hộp cát nơi bạn có thể nhận phản hồi và giải thích chi tiết như thế trước khi các thách thức được triển khai và được trả lời.
Martin Ender

1
OK, có lẽ bạn nên cụ thể hơn một chút và nói điều gì đó như "Bạn không thể đơn giản thực thi mã, thông qua bất kỳ phương thức nào" để tránh các câu trả lời tầm thường khác như Bash + perl.
Sản phẩm ETH

Câu trả lời:


16

Brachylog (2) → Bài toán tương ứng bài , 9 byte

~h=∋ᵐ\cᵐ=

Hãy thử trực tuyến!

Đầu vào là danh sách các chuỗi. (Trong bài toán tương ứng Post như được định nghĩa trên Wikipedia, các danh sách bên trong có hai phần tử, mặc dù chương trình này thực sự có thể xử lý tổng quát hóa cho bất kỳ số phần tử nào.) Chương trình này cung cấp các giải pháp cho vấn đề, theo thứ tự độ dài, cho đến khi một giải pháp được tìm thấy. Vấn đề tương ứng Post được biết là có thể mô phỏng một máy Turing, và do đó, các giải pháp buộc vũ phu đối với nó là Turing hoàn tất. Nếu chạy như một hàm, thay vì một chương trình, nó thực sự cũng tạo ra đầu ra có ý nghĩa.

Chương trình trong liên kết TIO ở trên là [["a","baa"],["ab","aa"],["bba","bb"]], mà tôi đã sao chép từ Wikipedia. Giải pháp (mà chương trình tìm thấy khá nhanh) là ["bbaabbbaa","bbaabbbaa"].

Giải trình

Đây là khá nhiều chỉ là một bản dịch trực tiếp của vấn đề tương ứng Post cho Brachylog.

~h=∋ᵐ\cᵐ=
~h         Find {the shortest possible} list which starts with {the input}
  =        and for which all elements are equal
   ∋ᵐ      such that taking an element of each element,
     \cᵐ   and concatenating elements in corresponding positions,
        =  produces a list all of whose elements are equal.

Về cơ bản, chúng tôi tạo một danh sách lặp lại các bản sao của đầu vào (càng ít càng tốt, nghĩa là chúng tôi không bỏ lỡ bất kỳ khả năng nào khi bắt buộc), lấy một phần tử từ mỗi bản sao, sau đó ghép các phần tử tương ứng (như trong phần tương ứng của Bài đăng vấn đề).


1
Và "danh sách những thứ có ý nghĩa và sẽ tiết kiệm byte thông thường nhưng trình thông dịch Brachylog không thể xử lý được": năm byte đầu tiên có thể được biểu thị là ~dp(điều đó không có nghĩa hoàn toàn giống nhau nhưng vẫn đủ gần Turing-Complete), ngoại trừ trình thông dịch Brachylog chưa biết cách đảo ngược d.

12

Jelly → "Thêm tối thiểu để hoán vị", 5 4 byte

+"Ṃẞ

Hãy thử trực tuyến! (chỉ chạy một lần lặp, để tránh thời gian chờ)

Cấu trúc Turing-Complete rất đơn giản: chúng ta lấy một ma trận vuông làm chương trình và lặp mãi mãi, xác định hàng nhỏ nhất theo từ vựng, sau đó tăng từng phần tử của hàng đầu tiên bằng phần tử đầu tiên của phần tử nhỏ nhất, từng phần tử của hàng thứ hai bởi yếu tố thứ hai của từ vựng nhỏ nhất, v.v. (Chương trình Jelly là " +"thêm các phần tử tương ứng {của đầu vào và} tối thiểu {của bản gốc}, vòng lặp"; đây là một byte ngắn hơn chương trình trước đây của tôi Z+ṂZß, nó đã làm chính xác điều tương tự. Rõ ràng tôi nên tập trung vào việc chơi golf Jelly, không chỉ chơi golf ngôn ngữ đã thực hiện.)

Ngôn ngữ kết quả là Turing-Complete vì nhiều lý do tương tự như Kangaroo. Phần tử đầu tiên của mỗi hàng hoạt động giống như số lần bỏ qua (mặc dù thay vì số lần bỏ qua của mỗi lệnh giảm khi bị bỏ qua, chúng tôi thay vào đó tăng số lần bỏ qua của mỗi lệnh khi nó chạy và tìm kiếm lệnh có số lần bỏ qua thấp nhất hơn các lệnh có số lần bỏ qua bằng 0, điều này đi đến cùng một điều). Chúng tôi đảm bảo rằng phần tử đầu tiên này cao hơn các phần tử khác (đại diện cho số lần mỗi lệnh xuất hiện trong nhiều trang của mỗi lệnh), do đó đảm bảo rằng hàng đầu tiên không bao giờ là tối thiểu; phần còn lại của hàng đầu tiên có thể là rác. Rắc rối duy nhất còn lại là mô hình hóa cách các lệnh có số lần bỏ qua bằng nhau chạy theo chu kỳ theo trình tự, nhưng chúng ta có thể làm điều đó bằng cách nhân tất cả số lần bỏ qua với một hằng số lớn, sau đó thêm vào "ban đầu" nhỏ bỏ qua đếm đến cột đầu tiên để phục vụ như là một tiebreak. Điều này mang lại cho chúng ta một sự kết hợp của "các lệnh không được chạy đầu tiên", không phải là "các lệnh không được chạy theo chu kỳ", nhưng cấu trúc Turing-perfect cho Kangaroo không quan tâm đến sự khác biệt này.


10

Mathicala diễn giải Trò chơi cuộc sống của Conway, 64 byte

CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}~Nest~##&

Trò chơi cuộc sống của Conway được biết là hoàn thành Turing; và automata di động là nỗi ám ảnh chân thật nhất của Stephen Wolfram. CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}là một quy tắc biến đổi một mảng hai chiều 0 và 1 theo một bước của Trò chơi cuộc sống của Conway. (Tôi nghĩ rằng hành vi mặc định là mảng này bao quanh các cạnh của nó, vì vậy thực sự là một hình xuyến rời rạc.) ~Nest~##&Biến quy tắc này thành một hàm, khi được đưa ra một trạng thái bảng ban đầu (của bất kỳ kích thước nào) và một số nguyên nlàm đối số, sẽ đưa ra kết quả của các nlần lặp của quy tắc Trò chơi Cuộc sống.

Để thưởng thức, bạn có thể sử dụng phiên bản được bọc

b = RandomInteger[1,{50,50}];
Manipulate[ArrayPlot[
  CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}~Nest~##&
    [b, n] ]
, {{n,0}, 0, 100, 1}]

và di chuyển theo cách của bạn qua 100 thế hệ trên một bảng 50x50.


Nếu tôi hiểu chính xác, cái này có kích thước bảng cố định? Trong trường hợp đó, tôi nghĩ nó không thể hoàn thành, phải không?
DLosc

Bất kỳ cuộc gọi cụ thể nào đến chức năng đều có kích thước bảng cố định, nhưng kích thước bảng đó có thể lớn tùy ý. (Lưu ý rằng nửa sau của bài viết mô tả một ví dụ về việc quan sát mã đang hoạt động, chứ không phải chính mã thực tế.)
Greg Martin

Điều tôi đang nói là để GoL trở thành Turing-Complete, nó phải có khả năng phát triển vô hạn. (Chẳng hạn như súng lượn.) Nếu việc triển khai này không thể phát triển mảng từ bước này sang bước khác, nhưng thay vào đó, nó kết thúc bằng hình xuyến, thì nó đã thất bại trong bài kiểm tra tăng trưởng vô hạn.
DLosc

Đó là một quan điểm hợp lý, để chắc chắn. Nhưng việc triển khai các ngôn ngữ lập trình trên máy tính vật lý thậm chí không thỏa mãn bài kiểm tra đó! Người ta có thể hài lòng với một chuỗi (giả thuyết) các máy tính vật lý có bộ nhớ ngày càng nhiều, mỗi máy có khả năng tính thêm một giá trị của hàm tính toán đó; Tuy nhiên, tại thời điểm đó, người ta phải có cùng nội dung với một chuỗi (giả thuyết) đầu vào cho chương trình GoL như vậy.
Greg Martin

9

Turtlèd phiên dịch CT , 49 byte

Tôi có thể chơi gôn này

Ngoài ra, điều này không tạo ra bất cứ điều gì hữu ích. nó chỉ dừng lại khi và chỉ khi chương trình CT đã cho dừng lại.

Đây là một cái tôi đã thực hiện một thời gian trước đây (sau đó đã chơi golf một số)

!-l[*+.r_]' !l[ l]r[ u.(;d' u)d(1[ r].[ l])( r)+]

Làm thế nào nó hoạt động:

Turtlèd sử dụng các ô lưới. Khi tôi nói "viết một cái gì đó lên lưới", ý tôi là một nhóm ký tự liền kề được đặt trên lưới. thí dụ

[ ][ ][ ][ ][ ][ ][ ]
[ ][H][E][L][L][O][ ]
[ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ]

vào chương trình

dữ liệu được nhập trước:

!-l[*+.r_]' 

đây thực chất là một chương trình mèo. nó ghi đầu vào lên lưới.

sau đó các lệnh được nhập vào:

!

những gì nó làm với các lệnh này:

các lệnh này là "sản phẩm". nếu bit dữ liệu ngoài cùng bên trái là 1, nó sao chép việc sản xuất vào cuối chuỗi dữ liệu. nếu không thì không có gì xảy ra sau đó bit dữ liệu ngoài cùng bên trái được loại bỏ và nó sử dụng sản xuất tiếp theo với bit dữ liệu bên trái tiếp theo. chương trình tạm dừng khi không có bit trong chuỗi dữ liệu. Một cách để thực hiện các sản phẩm này là xử lý các bit và kết thúc sản phẩm một cách riêng biệt. đây là những gì chương trình của chúng tôi làm. nó sao chép riêng các bit từ chuỗi lệnh vào cuối chuỗi dữ liệu và xóa riêng các bit khỏi kho dữ liệu

về cách chương trình này làm điều đó. sau khi nhập các lệnh, con trỏ rùa / lưới di chuyển trở lại bit ngoài cùng bên trái của kho dữ liệu. sau đó đi vào một vòng lặp

[ u.(;d' u)d(1[ r].[ l])( r)+]

những gì nó làm trong vòng lặp này, là nó di chuyển lên từ kho dữ liệu ngoài cùng bên trái và ghi lại ký tự lệnh hiện tại (u.). nếu nó là ;, kết thúc của một sản phẩm, nó di chuyển xuống và xóa bit dữ liệu ngoài cùng bên dưới nó và di chuyển ngược lên ( (;d' u)). sau đó, một trong hai cách, nó di chuyển xuống một ( d). nếu bit ở đó không bị xóa, điều đó có nghĩa là nó phải kiểm tra xem có sao chép một chút từ các lệnh ở cuối không. vì vậy, nếu ký tự này là hoặc là cơ sở dữ liệu ngoài cùng bên trái là 1, nó sẽ di chuyển đến cuối đầu bên phải của chuỗi dữ liệu, sao chép bit từ chuỗi lệnh và di chuyển trở lại khoảng trống bên trái của dữ liệu ngoài cùng bên trái bit ( (1[ r].[ l])). bây giờ, nó ở trên cơ sở dữ liệu ngoài cùng bên trái, là số 0 hoặc bên trái của cơ sở dữ liệu ngoài cùng bên trái. vì vậy, chúng tôi di chuyển sang phải nếu trên một không gian (( r)). sau đó, con trỏ lệnh được tăng lên, vì vậy chúng ta sẽ ghi lại lệnh tiếp theo trong lần lặp tiếp theo của vòng lặp. Nếu không còn kho dữ liệu nữa, điều này có nghĩa là chúng ta sẽ ở trên một khoảng trắng và vòng lặp sẽ kết thúc. nếu không, chúng tôi chạy lại vòng lặp.


Hãy cố gắng để chơi golf này nhiều hơn nữa!
arodebaugh

9

Perl → Biến thể lập trình ba sao , 26 + 1 = 27 byte

++$a[$a[$a[$_]]]for@F;redo

Hãy thử trực tuyến! (Liên kết này chứa một tiêu đề thoát khỏi chương trình sau một số lần lặp được đặt (để TIO không hết thời gian) và để in trạng thái bên trong mỗi lần lặp (để nó có thể quan sát được).)

Chạy với -a(hình phạt 1 byte, vì bạn có thể lắp nó trước khi -M5.010sản xuất -aM5.010).

Cụ thể, điều này thực hiện Trình lập trình ba sao trong đó các lệnh được phân tách bằng dấu cách và không cho phép nhận xét nào trong tệp, không có phần mở rộng I / O. (Rõ ràng những thay đổi này không khác biệt gì với tính đầy đủ của Turing trong ngôn ngữ.) Không có bằng chứng về tính đầy đủ của Turing cho Lập trình viên ba sao trực tuyến, nhưng đó là Turing-Complete (Tôi đã chia sẻ một bằng chứng phác thảo về Turing của nó - Tính đồng bộ với các chương trình esopro lập trình khác, nhưng đã ngừng hoạt động với ngôn ngữ khi tôi phát hiện ra rằng nó thực sự khá dễ dàng để lập trình ngay khi bạn đã vượt qua cú sốc ban đầu).

Chương trình không thực sự cần nhiều lời giải thích; Lập trình viên ba sao có một đặc điểm kỹ thuật rất đơn giản và đây là bản dịch trực tiếp của nó. Các điểm tinh tế duy nhất: @Flà đầu vào cho chương trình ở dạng mảng (đây là hệ quả của -a); và redosẽ lặp lại toàn bộ chương trình như trong một vòng lặp ngầm (cũng là hệ quả của -a).


1
Tôi nghĩ rằng nó có ý nghĩa hơn cho mũi tên có nghĩa là "được giảm xuống" so với "phiên dịch".
quintopia

9

lắp ráp x86 (cú pháp Intel / MASM) -Brainfuck 2127 byte.

Vẫn có thể chơi gôn

.386
.model flat,stdcall
.stack 4096
include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib
ExitProcess proto,dwExitCode:dword
.data
bfsrc BYTE 200 dup(0) 
bfcells BYTE 100 dup(0) 
loopStack DD 5 dup(0) 
charBuf BYTE 5 dup(0) 
newline BYTE 10,0 
prompt BYTE "$",0 
hr BYTE 50 dup('-'),0 
space BYTE ' ',0
.code
EvalBf proc
    start:
    invoke StdOut, addr prompt
    invoke StdIn, addr bfsrc,200
    cmp bfsrc,0
    je exit
    mov eax,0 
    mov ebx,0 
    mov ecx,0 
    processInstruction:
    cmp BYTE PTR bfsrc[ebx], '+'
    je plus
    cmp BYTE PTR bfsrc[ebx], '-'
    je minus
    cmp BYTE PTR bfsrc[ebx], '>'
    je fwd
    cmp BYTE PTR bfsrc[ebx], '<'
    je back
    cmp BYTE PTR bfsrc[ebx], '['
    je open
    cmp BYTE PTR bfsrc[ebx], ']'
    je close
    cmp BYTE PTR bfsrc[ebx], '.'
    je dot
    jmp processNextInstruction
    plus:
    inc BYTE PTR bfcells[eax]
    jmp processNextInstruction
    minus:
    dec BYTE PTR bfcells[eax]
    jmp processNextInstruction
    fwd:
    inc eax
    jmp processNextInstruction
    back:
    dec eax
    jmp processNextInstruction
    open:
    mov loopStack[ecx*4],ebx
    inc ecx
    jmp processNextInstruction
    close:
    dec ecx
    cmp BYTE PTR bfcells[eax], 0
    je processNextInstruction
    mov ebx,loopStack[ecx*4]
    inc ecx
    jmp processNextInstruction
    dot:
    mov dl, BYTE PTR bfcells[eax]
    mov BYTE PTR charBuf[0], dl
    mov BYTE PTR charBuf[1],0anything
    push eax
    push ecx
    invoke StdOut, addr charBuf
    pop ecx
    pop eax
    jmp processNextInstruction
    processNextInstruction:
    inc ebx
    cmp BYTE PTR bfsrc[ebx], 0
    je done
    jmp processInstruction
    done:
    invoke StdOut, addr newline
    mov eax, 0
    printNext:
    cmp eax, 100
    jge reset
    push eax
    invoke dwtoa, BYTE PTR bfcells[eax], addr charBuf
    invoke StdOut, addr charBuf
    invoke StdOut, addr space
    pop eax
    inc eax
    jmp printNext
    reset:
    invoke StdOut, addr newline
    invoke StdOut, addr hr
    invoke StdOut, addr newline
    jmp start

    exit:
    invoke ExitProcess,0
EvalBf endp
end EvalBf

3
Thông thường các câu trả lời lắp ráp được tính theo kích thước của mã máy kết quả, vì vậy bạn không cần phải đánh golf lắp ráp, chỉ cần giảm thiểu số lượng / kích thước của hướng dẫn.
Robert Fraser

@RobertFraser uhh Tôi không biết cách đếm: P
Christopher

3
Trên thực tế, lúc đầu, bằng cách nào đó tôi đã đọc tiêu đề là "x86 asm được triển khai ở Brainfuck" và rất ấn tượng :)
quetzalcoatl

@Quetzalcoatl Điều đó thật ấn tượng
Christopher

1
xin vui lòng biến golf / tên nhãn ty
ASCII-only

8

Pip phiên dịch hệ thống thẻ tuần hoàn , 16 byte

YqWyyPBg@++vXPOy

Lấy các sản phẩm của hệ thống thẻ làm đối số dòng lệnh và chuỗi dữ liệu ban đầu từ stdin.

Đoạn mã trên hơi khó kiểm chứng vì nó không tạo ra bất kỳ đầu ra nào (vì vậy hành vi duy nhất có thể quan sát được là "chấm dứt" so với "không chấm dứt"). Do đó, đây là phiên bản không được cung cấp chuỗi dữ liệu sau mỗi bước và cũng chấm dứt sau 20 bước để TIO không phải xử lý hàng tấn đầu ra từ các vòng lặp vô hạn: Hãy thử trực tuyến!

Hệ thống thẻ tuần hoàn

Hệ thống thẻ tuần hoàn là một mô hình tính toán cực kỳ đơn giản nhưng hoàn chỉnh Turing . Chúng bao gồm một danh sách các sản phẩm xác định các hoạt động trên một chuỗi dữ liệu . Các sản phẩm và chuỗi dữ liệu bao gồm 1 và 0.

Ở mỗi bước, ký tự ngoài cùng bên trái của chuỗi dữ liệu sẽ bị xóa.

  • Nếu ký tự là 1, sản phẩm hiện tại được gắn vào bên phải của chuỗi dữ liệu.
  • Nếu ký tự là 0, không có gì được thêm vào.

Trong cả hai trường hợp, sản xuất hiện tại chuyển sang sản xuất tiếp theo trong danh sách, theo chu kỳ: nếu chúng tôi ở sản xuất cuối cùng, chúng tôi sẽ lặp lại sản phẩm đầu tiên. Thực thi tiếp tục cho đến khi chuỗi dữ liệu trống.

Giải trình

                  g is list of cmdline args; v is -1 (implicit)
 q                Read a line of stdin for the data string
Y                 and yank it into the y variable
  Wy              While data string is nonempty:
       g@++v       Retrieve the next production from g (using cyclic indexing)
             POy   Pop the first character of y
            X      String-multiply: result is the production if the first character of y
                   was 1, or empty string if it was 0
    yPB            Push that string to the back end of y

này, tôi chỉ nhớ rằng bạn không cần phải nhập chuỗi dữ liệu; nó chỉ có thể là 1nguồn: esolangs liên kết đến arxiv.org/abs/1312.6700 này . Tôi sẽ sớm chỉnh sửa câu trả lời của mình và nếu điều này giúp bạn trả lời thì bạn nên (tbh đầu vào của bạn có vẻ đủ thực sự)
Lemon phá hủy

8

Các hàm Collatz được lặp lại tổng quát -> Python 2, 46 byte

a,b,x,m=input()
while-~x%m:x=x/m*a[x%m]+b[x%m]

Gọi hàm này với danh sách m-1 a và b's, giá trị bắt đầu x và ước số m, tạo thành một "chương trình" cho IGCF. Thay vì lấy một mảng thứ ba để chỉ ra các mô đun dừng lại, điều này chỉ dừng lại bất cứ khi nào mô đun là m-1. Đơn giản hóa này có nghĩa là có thể cần thêm một số nỗ lực để chuyển đổi một chương trình Fractran đã cho thành biến thể này, nhưng nó sẽ tiết kiệm được một vài byte trong trình thông dịch.

Hãy thử trực tuyến! TIO này trình bày cách thêm 5 + 5 với ngôn ngữ này. Chương trình a = [3], b = [0], m = 2 thực hiện bổ sung và bắt đầu với 7776 = 2 ^ 5 * 3 ^ 5 cuối cùng mang lại 59049 = 3 ^ 10.


Dang công việc tốt. Tôi đã hy vọng giành được tiền thưởng nhưng công việc tốt
Christopher

7

Biến thể ResPlicate -> Python 2, 47 byte

l=input()
while l:l=l[2+l[0]:]+l[2:2+l[0]]*l[1]

Hàm này diễn giải một biến thể của ResPlicate

  • trong đó một chương trình là một danh sách python có độ dài chẵn với các phần tử chẵn ở các chỉ số chẵn.
  • không có I / O.
  • trong đó cố gắng sao chép nhiều giá trị hơn tồn tại trong phần còn lại của hàng đợi chỉ đơn giản là sao chép phần còn lại của hàng đợi (nghĩa là bit đã sao chép không được đệm bằng số 0 đến độ dài cần thiết).

Thay đổi cuối cùng có nghĩa là một số chương trình ResPlicate (đáp ứng điều kiện đầu tiên) sẽ không hoạt động giống nhau trong biến thể này, nhưng may mắn thay, trình thông dịch BCT không yêu cầu chức năng loại bỏ và vì vậy ngôn ngữ vẫn là TC.

Hãy thử trực tuyến! TIO này có một bản in được nêm vào để cho thấy rằng nó hoạt động và một tiêu đề giết chương trình sau 1 giây và một ví dụ quản lý để tạo ra nhiều đầu ra hơn TIO có thể xử lý trong một giây đó.


2
Tại sao không l=input()? Sẽ là một byte ngắn hơn.
frageum

7

Perl -a → Máy I / D , 24 byte

$p=$a[$p]+=$_ for@F;redo

Hãy thử trực tuyến! (chứa một tiêu đề in trạng thái bên trong và tạm dừng sau 10 lần lặp, để hành vi có thể quan sát được)

Về ngôn ngữ

Tôi đã dành vài ngày qua để làm việc trên máy I / D , một trong những ý tưởng mới nhất của tôi cho các ngôn ngữ lập trình rất đơn giản. Nó hoạt động như sau: bộ lưu trữ dữ liệu bao gồm RAM không giới hạn, ban đầu là tất cả các số không. Mỗi phần tử có thể lưu trữ một số nguyên không giới hạn (mặc dù trong thực tế, hầu hết các chương trình máy I / D sẽ chỉ lưu trữ các số nguyên nhỏ trong hầu hết chúng và chỉ sử dụng các số nguyên không giới hạn như một cách giải quyết các ô có địa chỉ lớn). Ngoài ra còn có một con trỏ dữ liệu, trỏ đến một ô (tức là giữ địa chỉ dưới dạng một ô); ban đầu nó cũng bằng không.

Chỉ có hai lệnh:

  • I: Tăng ô mà con trỏ dữ liệu trỏ tới. (Con trỏ dữ liệu vẫn không thay đổi.)
  • D: Dereference con trỏ dữ liệu, tức là đọc giá trị của ô mà con trỏ dữ liệu trỏ đến. Sau đó lưu trữ giá trị kết quả mà bạn đọc lại vào con trỏ dữ liệu.

Thực thi chỉ đơn giản là chạy chương trình trong một vòng lặp liên tục, mãi mãi.

Thật đáng ngạc nhiên khi một ngôn ngữ đơn giản này là Turing-Complete, vì vậy tôi đã nghiên cứu để chứng minh điều đó. Đây là bằng chứng . Nó khá giống với (nhưng đơn giản hơn) bằng chứng cho Lập trình viên ba sao, một ngôn ngữ rất giống nhau (và trên thực tế, bài nộp này sử dụng cùng một "vỏ" OISC cơ bản xung quanh chương trình, chỉ khác với hướng dẫn thực tế được triển khai).

Về chương trình

Sử dụng

Đầu vào phải được cung cấp trên đầu vào tiêu chuẩn và là chương trình máy I / D không có nhận xét và sử dụng cú pháp RLE / OISC. (Máy I / D có hai cú pháp tương đương, khác nhau, nhưng đối với tính golf, chương trình này chỉ hỗ trợ một trong số chúng.) Trong cú pháp này, một chương trình là một chuỗi các số thập phân, biểu thị độ dài của các Ilệnh giữa Dcác lệnh. (Bạn có thể chỉ định hai hoặc nhiều Dlệnh liên tiếp bằng cách đặt "chạy 0 Ilệnh" giữa chúng, vì vậy cú pháp hoàn toàn chung.)

Giải trình

Như có thể thấy từ chương trình, điều này không thực hiện riêng lẻ IDcác lệnh. Trên thực tế, đó là một trình thông dịch tối ưu hóa (rất nhẹ) (hoàn toàn vì viết ngắn hơn theo cách này). Điều quan trọng là để thấy rằng một lệnh chạy n lệnh tăng làm tăng mục tiêu của con trỏ dữ liệu n lần, tức là thêm n vào nó; và việc chạy các lệnh tăng 0 cũng có thể được thực hiện theo cách này, vì việc thêm 0 vào bộ nhớ không có hiệu lực. Vì vậy, hoạt động chúng tôi thực sự thực hiện là xen kẽ giữa thực hiện một hoạt động Ivà a D. Hay nói cách khác, "thêm nđến giá trị được trỏ bởi con trỏ dữ liệu (lưu trữ lại giá trị được trỏ bởi con trỏ dữ liệu), sau đó đọc giá trị được trỏ bởi con trỏ dữ liệu và lưu trữ nó trong con trỏ dữ liệu ". để được, và chúng ta có thể đơn giản hóa hơn nữa để "thêm n vào giá trị được trỏ bởi con trỏ dữ liệu, sau đó lưu trữ giá trị đó cả trong mục tiêu của con trỏ dữ liệu và chính con trỏ dữ liệu".

Vì vậy, điều đó làm cho cốt lõi của chương trình của chúng tôi. Chúng tôi đang sử dụng một mảng $ađể lưu trữ RAM và $plà con trỏ dữ liệu (lập chỉ mục vào mảng):

$p=$a[$p]+=$_
         + $_  add {the run length}
   $a[$p]      to the element of $a pointed to by $p
   $a[$p] =    storing the result back into that element
$p=            and also in the pointer itself

Thuận tiện, Perl diễn giải các phần tử mảng chưa được xác định thành 0 khi chúng được coi như số, vì vậy mảng sẽ được khởi tạo một cách lười biếng thành số không cho chúng tôi mà không cần bất kỳ mã rõ ràng nào cho việc đó. (Một vấn đề tiềm ẩn là độ chính xác về số khi số lượng lớn; tuy nhiên, điều đó sẽ chỉ xảy ra nếu số lượng mảng được sử dụng vượt quá không gian địa chỉ của máy (số nguyên Perl đủ lớn để giữ con trỏ), điều không thể xảy ra trên một máy lý tưởng hóa.)

Cuối cùng, tất cả những gì chúng ta cần làm là đặt chương trình này vào một vài vòng lặp. Các for@Fvòng lặp, kết hợp với các -atùy chọn dòng lệnh, sẽ lặp trên các lĩnh vực đầu vào tiêu chuẩn (định nghĩa mặc định của "trường" ở đây sẽ chia vào khoảng trắng). Các redovòng lặp sẽ đặt toàn bộ chương trình trong một vòng lặp ngầm (trừ, thuận tiện, cách đọc của đầu vào tiêu chuẩn), mà sẽ làm cho chương trình để chạy trong một vòng lặp liên tục, theo yêu cầu của ngữ nghĩa của máy I / D.


Chào mừng trở lại! Chúng tôi không còn cần phải chấm cờ cho thông dịch viên, chỉ cần lưu ý rằng đây là 'Perl with -a'. codegolf.meta.stackexchange.com/a/14339/9365
Dom Hastings

6

Hệ thống Jelly2-Tag , 8 byte

µḢị⁴⁸;Ḋß

Hãy thử trực tuyến!

Tôi có một tiền thưởng sẽ thiên về các ngôn ngữ thực tế, nhưng nghĩ rằng tôi cũng có thể cố gắng để giành được nhiệm vụ ban đầu khi tôi ở đó (vì tôi không thể chính xác giành được tiền thưởng của mình).

Triển khai một biến thể của các hệ thống thẻ không có trạng thái dừng, vì nó không cần thiết cho tính hoàn chỉnh của Turing. Các trạng thái được đánh số từ 1, liên tiếp và chuỗi ban đầu xuất hiện trước chương trình.

Ví dụ, Wikipedia đưa ra một ví dụ về một hệ thống thẻ { a, b, c}, { abc, ba, caaa} với chuỗi ban đầu aaa; trong định dạng đầu vào này, đó là [1,1,1], [[2,3],[1],[1,1,1]]. (Hệ thống thẻ không có cú pháp cố định và đây có vẻ là một cách hợp lý để làm điều đó.)

Liên kết TIO có thêm ("ghi trạng thái nội bộ và dòng mới vào thiết bị xuất chuẩn") để cho thấy rằng chương trình này thực tế đang hoạt động.

Giải trình

µḢị⁴⁸;Ḋß
           {implicit: initialise internal state from first argument}
µ          Disregard the second command-line argument by default
 Ḣ         Take the first element, removing it from the internal state
  ị⁴       Use the value to index into the second argument
    ⁸;     Prepend (the rest of) the internal state
      Ḋ    Discard the first element of the internal state
       ß   Loop forever

6

BF / P "được triển khai trong Máy Turing, 842 byte

Bảng chuyển tiếp (được liên kết vì độ dài)

Bàn chuyển tiếp, phiên bản ít chơi gôn

Mô phỏng máy Turing tôi đã sử dụng

Điều này chắc chắn sẽ không giành được bất kỳ giải thưởng nào về chiều dài, nhưng đó là điều tôi luôn muốn làm, vì BF rất giống với Turing Machine. Mỗi ô lưu trữ một giá trị từ 0x0- 0xF. Tuy nhiên, chiều rộng của trang web Turing Machine có thể đi mà không làm sập trình duyệt của bạn. Các hàm ,.hàm (đầu vào và đầu ra) không được xác định, do đó, nó giống P hơn một chút so với BF thực.

Để chạy nó, dán bảng chuyển đổi vào trình giả lập Turing Machine, đặt đầu vào thành một số mã BF và nhấn run.

Băng của TM lưu trữ cả mã BF và dữ liệu BF, với một khoảng trống ở giữa. Nó theo dõi vị trí của nó trong mã bằng cách sửa đổi ký tự mà nó hiện đang chạy ( [-> (, v.v.) và vị trí của nó trong dữ liệu với một ^ở phía trước ô. Khi nó đọc một ký tự lệnh, nó sẽ di chuyển cho đến khi chạm vào dấu mũ, di chuyển một ô sang bên phải và thực hiện chức năng thích hợp. Sau đó, nó quay trở lại, tìm kiếm một trong các ký tự lệnh "đã sửa đổi" trong mã BF và chuyển sang mã tiếp theo, lặp lại toàn bộ quá trình. Một khi nó hết mã, nó dừng lại.

Cách tốt nhất để hiểu cách thức hoạt động của nó là chạy phiên bản không được chỉnh sửa, đưa nó vào chế độ bước và xem dòng nào dẫn đến dòng nào khác và mỗi trạng thái / khối dòng làm gì.

Các phiên bản golf và không có người lái hoàn toàn giống nhau về cách chúng hoạt động, nhưng phiên bản không có người thân có nhiều tên thân thiện với con người hơn và được chia thành nhiều phần.


1
Giới hạn độ dài bài đăng là quá đủ để phù hợp với bảng chuyển đổi
ASCII - chỉ

6

C triển khai ( T ) Máy Turing , 236 205 byte (giảm 46 31 nếu bạn không quan tâm đến các đầu vào khó xử)

Cảm ơn Appleshell cho -11 byte, VisualMelon cho -12 byte và Johan du Toit cho -7 byte.

BareCat đã tạo một phiên bản chỉ sử dụng 144 byte, xem tại đây .

(Tôi đã thêm một vài ngắt dòng ở đây để bạn không phải cuộn, nhưng thông thường hầu hết các dòng sẽ bị xóa)

#define c char
j;i;k;c s,d[256];c main(){c*p=d+128;gets(d);
for(;k<256&&d[k];)d[k++]-=48;for(;++j<256;)
{c t=*p;*p=-t*t+(2-s)*t+1+s;p+=(s^t==0)*2-1;s=s?t%2:!t%3;
for(i=0;++i<256;)printf("%d",d[i]);puts("");}}

Hãy thử trực tuyến!

Để sử dụng: Nhập một chuỗi tối đa 256 cái, số không và twos để khởi tạo băng. Bất kỳ giá trị chưa được khởi tạo sẽ bằng không. (Các giá trị khác 0, 1 và 2 có thể gây ra hành vi không xác định.) Chương trình sẽ lặp lại hơn 256 bước. Số lượng các bước lặp đi lặp lại có thể được tăng lên bằng cách sửa đổi mã, nhưng rõ ràng điều đó đòi hỏi nhiều ký tự hơn.

Đây là một mục khá dài, nhưng đây là lần đầu tiên tôi thực hiện một trong những điều này và tôi đã không sử dụng ngôn ngữ chơi gôn chuyên dụng. Tôi đã có rất nhiều niềm vui, ngay cả khi nó bật ra lâu hơn tôi mong đợi.

Rất nhiều byte là từ việc xử lý đầu vào và đầu ra, và tôi đã mất toàn bộ 42 byte bằng cách làm cho nó chấp nhận 0, 1 và 2 thay vì NUL, SOH, STX. (Để thay đổi điều đó, hãy xóa k;từ phía trước và for(;k<256&&d[k];)d[k++]-=48;từ dòng thứ hai.)

Bảng transistion, đặc biệt là dòng *p=-t*t+(2-s)*t+1+s;(đặt các giá trị trên băng) có thể cũng được nén nhiều hơn.


1
Wow, và đây là mã golf đầu tiên của bạn ở đây! Tuyệt vời!
Zacharý

Bạn có thể rút ngắn các khai báo biến toàn cục như thế này: k,j;c s,d[256];( intẩn trong C, sau đó bạn cũng có thể chuyển isang khai báo toàn cầu để tiết kiệm thêm 3 byte)
Appleshell

@Appleshell Cảm ơn, tôi sẽ làm điều đó.
a52

Bạn có thể di chuyển chuỗi kiểm tra null-terminal bên trong vòng lặp for. Xếp hàng k++và loại bỏ {}tiết kiệm thêm một vài byte: for(;k<256&d[k];)d[k++]-=-48;Bởi vì jchỉ là máy chấm công (giá trị không bao giờ được sử dụng), bạn có thể thay thế nó (và i) bằng kcách đếm ngược: bạn biết k==256sau vòng lặp đầu tiên, vì vậy hãy đếm ngược về 0 trong giây for(;k>0;), lá nào k==-1, vì vậy vòng lặp cuối cùng có thể trở thành for(;++k<256;). (Tuyên bố miễn trừ trách nhiệm: Tôi thường chơi gôn C#, nhưng điều này dường như được biên dịch).
VisualMelon

1
@VisualMelon Tôi xác định vấn đề. Tôi cần phải sử dụng k<256&&d[k], không &, bởi vì d[k]đã được đánh giá tại k==256. Ngoài ra, vì kkhông còn được đảm bảo 256sau vòng lặp đó, tôi đã phải đặt lại nó sau đó để đảm bảo 256 bước. (Nếu bạn (nghĩa là VisualMelon) có bất kỳ đề xuất nào khác, có lẽ chúng ta nên đưa chúng vào trò chuyện để chúng tôi không nhận được quá nhiều bình luận)
a52

5

Röda triển khai Fractran , 114 112 106 byte

Lưu 1 byte nhờ @fergusq bằng cách sắp xếp lại các tham số

f&n,a{x=1{x=0;(a/" ")()|[_/`/`]|[parseInteger(_[0],_1[1])]|{|q,w|{n*=q/w;x=1}if[n%w<1,x<1]}_,_}while[x>0]}

Hãy thử trực tuyến!

Gọi hàm như vậy : f reference_to_input program. Đầu ra sẽ được lưu trữ trong vị trí của input.


Dấu chấm phẩy sau e[1]là dư thừa. Ngoài ra, bạn có thể lưu một byte bằng cách thay đổi thứ tự tham số : f&n,a.
fergusq

@fergusq Cảm ơn vì f&n,amánh khóe, và tôi vừa định xóa dấu chấm phẩy đó khi bạn bình luận :)
Kritixi Lithos

5

Clojure, 82 81 byte (Máy Turing)

Cập nhật: xóa một khoảng trắng từ t{} s.

#(loop[p 0 t{}s 1](if-let[[S M N](%[(or(t p)0)s])](recur(+ p M)(assoc t p S)N)t))

Triển khai Máy Turing như một vòng lặp, trả lại băng khi đạt đến trạng thái tạm dừng. Trong quy tắc chuyển đổi trạng thái, điều này được chỉ định bằng cách sử dụng trạng thái chuyển tiếp. Điều này giải Nquyết nilvà sau đó if-letsẽ hủy bỏ vì quá trình chuyển đổi trạng thái tương ứng không được tìm thấy từ bản đồ băm đầu vào %. Trên thực tế, bất kỳ giá trị nào cho trạng thái này sẽ làm, chẳng hạn như :abort, 0 hoặc -1.

Ungolfed với một ví dụ hải ly bận rộn 3 biểu tượng 2 trạng thái từ Wikipedia .

(def f #(loop[pos 0 tape {} state 1]
          (if-let [[sym move next-state](%[(get tape pos 0)state])]
            (do (println [pos tape state])
                (recur(+ pos move)(assoc tape pos sym)next-state))
            tape)))

(f {[0 1] [1  1 2]
    [0 2] [1 -1 1]
    [0 3] [1 -1 2] 
    [1 1] [1 -1 3]
    [1 2] [1  1 2]
    [1 3] [1  1]})

{0 1, 1 1, -1 1, -2 1, -3 1, 2 1}

Hãy thử trực tuyến .

Trên lõi đơn 6700K, điều này chạy hải ly bận rộn 5 biểu tượng 2 trạng thái (47,1 triệu bước) trong khoảng 29 giây, tương đương 1,6 triệu bước / giây.


5

MMẹo , 4 byte

Ṅ×ịß

Hãy thử trực tuyến!

Liên kết TIO thêm chân trang để gọi chức năng với chương trình Mẹo ví dụ được hiển thị trên trang Esolang ("trình bao bọc tự động" của M để gọi các chức năng như thể chúng là các chương trình không thể xử lý các số có điểm hợp lý hoặc cố định hoặc ít nhất là tôi ẩn Tôi đã tìm ra cách để nói với nó như thế nào, vì vậy tôi cần phải thực hiện chức năng thành một chương trình đầy đủ bằng tay để có thể chạy nó.)

Điều này thực sự in đầu ra gỡ lỗi hữu ích; chương trình không thể được viết bằng 3 byte bằng M vì một chương trình bao gồm chính xác ba dyads kích hoạt một trường hợp đặc biệt trong trình phân tích cú pháp, vì vậy tôi phải thêm một lệnh bổ sung để tránh trường hợp đặc biệt. Làm cho nó (in với dòng mới) ít nhất cung cấp cho nó một mục đích hữu ích.

ıi=1

Không thực hiện I / O (trừ dừng / không dừng). I / O là một phần mở rộng cho Mẹo (không phải là một phần của ngôn ngữ) và không bắt buộc đối với tính đầy đủ của Turing.

Giải thích / lý lịch

Ṅ×ịß
Ṅ     Print {the left argument} and a newline; also resolves a parser ambiguity
  ị   {The left argument}th element of {the right argument}, wrapping on OoB
 ×    Multiply {the left argument} by {the chosen element}
   ß  Recursive call; arguments: {the product} and {the same right argument}

[1,2,3][1,2,3,1,2,3,1,2,3,…]rx+s, đó là một đa thức, và tích hợp "chuyển đổi cơ sở" mà nhiều ngôn ngữ chơi gôn thực sự là một công cụ đánh giá đa thức có mục đích chung được ngụy trang. Vì vậy, tất cả những gì chúng ta phải làm là lập chỉ mục vào một danh sách các danh sách các chữ số, chuyển đổi cơ sở chúng và chúng ta đã hoàn thành, phải không?

xx

x(xy)xy. Chắc chắn, chúng ta có thể ghi đè hành vi xâu chuỗi vào hầu hết mọi thứ chúng ta muốn, nhưng điều đó sẽ tốn cả byte và các mục ngôn ngữ chơi gôn cho câu hỏi này ngày càng ngắn đến mức một byte rất nhiều.

Vì vậy, tôi nhìn lại và đánh giá lại một chút. Có bất kỳ hoạt động chúng ta có thể sử dụng thay vì đánh giá đa thức? Lý tưởng nhất là những cái giao hoán, vì vậy chúng ta không phải lo lắng về thứ tự tranh luận? Ngay sau đó, tôi nhận ra rằng các hàm Collatz phức tạp hơn mức cần thiết.

s

Và tất nhiên, không giống như chuyển đổi cơ sở ( ), phép nhân ( ×) là giao hoán, và do đó, không có vấn đề gì theo thứ tự các đối số được đặt vào. Vì vậy, tất cả những gì chúng ta cần viết là ×ị, và sau đó đặt chương trình vào một đệ quy vô hạn với ß, và chúng tôi có một ngôn ngữ Turing-Complete. Đúng?

(xy)(xy)¹×ịß¹¹ là một lựa chọn tốt vì nó tạo ra đầu ra gỡ lỗi hữu ích.

Là ba byte có thể? Trừ khi tôi thiếu một cái gì đó, không phải với sự lựa chọn cụ thể về ngôn ngữ triển khai và triển khai cụ thể này, nhưng tại thời điểm này chắc chắn có vẻ như có thể bằng cách nào đó, vì có rất nhiều cách để thực hiện trong bốn và rất nhiều Turing-perfect ngôn ngữ bạn có thể thực hiện.


Sau khi suy nghĩ thêm về điều này, chúng ta có thể giảm xuống còn ba byte bằng cách sử dụng thay vì ×; ngôn ngữ kết quả không hoàn toàn giống ngôn ngữ với Tip, nhưng nó khá giống nhau và gần như chắc chắn là Turing-perfect vì lý do tương tự. Thật không may, không được triển khai trong M và tôi không thể tìm ra cách nào để Jelly thực hiện các phép tính chính xác tùy ý khi một trong hai đầu vào là một số thực không nguyên. Tuy nhiên, nếu bất cứ ai biết bất kỳ ngôn ngữ chơi gôn nào khác, nơi công trình này có thể hoạt động, hãy thoải mái cho nó đi.
ais523

4

C giải thích Brainfuck, 187 byte

t[999],*p=t,c,i,l;f(char*t){for(i=0;c=t[i];i++){c^62?c^60?c^43?c^45?c^46?c^44?c^91:(*p=getchar()):putchar(*p):--*p:++*p:--p:++p;if(c==93&&*p)for(l=1;l>0;)c=t[--i],c==91?l--:c==93?l++:0;}}

Dùng thử trực tuyến


3
Welp, chắc chắn đã có câu trả lời bằng BF.
Zacharý

4

Lua phiên dịch Brainf ***, 467 byte

b,r,a,i,n,s=0,io.read,{0},1,1,"><+-.,[]"c,f=r(),{function()n=n+1;a[n]=a[n]or 0;end,function()n=n-1;a[n]=a[n]or 0;end,function()a[n]=a[n]+1;end,function()a[n]=a[n]-1;end,function()io.write(string.char(a[n]))end,function()a[n]=io.read():byte()end,function()i=a[n]~=0 and i or c:find("]",i)end,function()if a[n]~=0 then b,x=1,""repeat i=i-1 x=c:sub(i,i)b=x=="["and b-1 or x=="]"and b+1 or b until b==0 and x=="["end end}repeat f[s:find(c:sub(i,i),1,1)]()i=i+1 until i>#c

Tôi biết vẫn còn một số giảm béo tôi có thể làm sau này, nhưng đây là nơi lần đầu tiên vượt qua của tôi. Lấy mã brainf từ đầu vào tiêu chuẩn.


2
+1 cho brains, thật thú vị khi người chơi golf gán cho một danh sách các biến.
Zacharý

4

Biến thể CJam → ResPlicate, 15 14 13 byte

-1 byte nhờ @ ais523

l~{(/((*+e_}h

Biến thể giống như trong câu trả lời này , ngoại trừ số lượng vật phẩm được lấy ra khỏi hàng đợi ít hơn một số so với số hàng đầu trên hàng đợi.

Phần l~{ ... }hchỉ lấy một mảng làm đầu vào và lặp lại cho đến khi mảng đó trống.

Giải thích cho vòng lặp chính:

    e# Stack:             | [3 2 1 1 2 2 2 1]
(   e# Pop first element: | [2 1 1 2 2 2 1] 3
/   e# Split chunks:      | [[2 1 1] [2 2 2] [1]]
(   e# Pop first:         | [[2 2 2] [1]] [2 1 1]
(   e# Pop first:         | [[2 2 2] [1]] [1 1] 2
*   e# Repeat array:      | [[2 2 2] [1]] [1 1 1 1]
+   e# Concatenate:       | [[2 2 2] [1] 1 1 1 1]
e_  e# Flatten:           | [2 2 2 1 1 1 1 1]

Bạn không thực sự cần sự gia tăng ở đây. Chỉ cần xác định rằng độ dài khối nên được tăng thêm 1 trong chương trình gốc; điều đó không ảnh hưởng đến tính đầy đủ của Turing của ResPlicate (có các cấu trúc TC trong đó độ dài khối và số lượng lặp lại không bao giờ được trộn lẫn với nhau).

3

Chip , 20 + 3 = 23 byte (Quy tắc 110)

AZZ
>}/a
`)\'E~Zte*f

+3 cho cờ -z

Hãy thử trực tuyến!

Việc gửi này không hoàn hảo, vì Chip không (chưa) có bất kỳ khả năng lặp nào, do đó, đầu ra phải được chuyển vào làm đầu vào để mô phỏng nhiều thế hệ, với một cái gì đó như thế này (tất nhiên, bạn có thể chạy vòng lặp đó vô thời hạn, và Chip có thể xử lý đầu vào dài tùy ý, vì vậy sự kết hợp này là Turing Complete).

Việc triển khai này nhận đầu vào và đầu ra đã cho dưới dạng ASCII 0s và 1s. Logic ở đây như sau:

p := value of left neighbor cell    AZZ
q := value of current cell          AZ
r := value of right neighbor cell   A

q' := ((r xor q) and p) or          >}/a
      ((r or q) and ~p)             `)\'

Phần còn lại của các phần tử là dành cho vệ sinh: e*fgây ra đầu ra số ASCII và E~Ztchấm dứt thực thi hai byte sau khi đầu vào hết (vì chiều rộng tăng thêm 2 mỗi thế hệ).


3

Clojure, 75 byte (hệ thống thẻ tuần hoàn)

Cập nhật 1: thay thế some?bằng nil?.

Cập nhật 2: Đã sửa lỗi thiếu Strong nhánh khác của if s.

#(loop[[p & P](cycle %)[s & S]%2](if(nil? s)S(recur P(if s(concat S p)S))))

Triển khai hệ thống thẻ tuần hoàn , trả về nilnếu chương trình tạm dừng, lặp lại mãi mãi. Clojure thực sự tỏa sáng ở đây với các chuỗi lười biếng vô hạn (như chu kỳ ) và phá hủy . Những người và số không được chỉ định là giá trị đúng và sai. Khi chuỗi dữ liệu chạy ra ngoài strở thành nil.

Ung dung:

(def f #(loop[[p & P] (cycle %) [s & S] %2 i 5]
          (do
            (pprint [p (concat [s] S)])
            (if (and (some? s) (pos? i))
              (recur P (if s (concat S p) S) (dec i))))))

Kết quả ví dụ:

(f [[false]] [true true])
[[false] (true true)]
[[false] (true false)]
[[false] (false false)]
[[false] (false)]
[[false] (nil)]

(f [[false true true] [true false] [true false true]] [true])
[[false true true] (true)]
[[true false]      (false true true)]
[[true false true] (true true)]
[[false true true] (true true false true)]
[[true false]      (true false true false true true)]
[[true false true] (false true false true true true false)]

2

JavaScript diễn giải Quy tắc 110 , 131 byte (99 byte?, 28 byte?)

a=(p,q,r)=>q+r+q*r+p*q*r
b=l=>{r="";for(i=0;i<l.length-2;i++)r+=a(l[i],+l[i+1],+l[i+2])%2;return r}
c=(l,n)=>!n?l:c(b(0+l+0),n-1)

Như bạn có thể thấy, mã xác định 3 chức năng, a, bc. Có lẽ bạn có thể lưu byte bằng cách kết hợp chúng trong 1 hàm (tôi không biết làm thế nào), nhưng thật tốt khi tách ra vì mỗi trong số chúng đã hoàn thành thử thách này theo một nghĩa nào đó.

Hàm alấy 3 số làm đầu vào và tính một số đa thức kỳ lạ của chúng. Khi 3 số này là 0hoặc 1chúng có thể được xem là quy tắc 110 ô. Tính chẵn lẻ của đầu ra asau đó có thể được coi là giá trị của ô giữa trong thế hệ tiếp theo. Vì vậy, theo một nghĩa nào đó, hàm đơn giản này đã là một 'trình thông dịch' Quy tắc 110 (28 byte):

a=(p,q,r)=>(q+r+q*r+p*q*r)%2

Sau đó chúng ta có thể tạo một hàm mới bđể đánh giá atrên mỗi ký tự của một chuỗi các số và số không. Đây blà một cách tốt hơn so với a, một trình thông dịch Quy tắc 110. Lấy mod 2 sau khi đánh giá dấu ngoặc lưu (99 byte):

a=(p,q,r)=>q+r+q*r+p*q*r
b=l=>{r="";for(i=0;i<l.length-2;i++)r+=a(l[i],+l[i+1],+l[i+2])%2;return r}

Để thực sự tính toán một hàm với Quy tắc 110, người dùng phải chỉ định trạng thái bắt đầu và số lượng thế hệ sau đó đầu ra sẽ 'xuất hiện'. Chúng ta có thể tạo một hàm thứ ba clấy một chuỗi gồm các số 0 và số nguyên dương n, sau đó đánh giá btrên chuỗi, nlần. Như thế này, chúng ta thực sự có thể thấy Quy tắc 110 là ngôn ngữ lập trình, trong đó chương trình là trạng thái nội tâm và số n, và đầu ra là trạng thái sau nnhiều thế hệ. Hàm cbây giờ là một trình thông dịch thực tế cho ngôn ngữ lập trình đó, vì vậy mã cuối cùng cho thử thách này là những gì tôi đã trình bày ở trên.


Điều này có tính toán 110 với nền phù hợp không? Một câu trả lời trước đó của tôi đã bị xóa vì nó không có nền.
Phù thủy lúa mì

@WheatWizard nền là một phần của đầu vào, câu trả lời của bạn không nên xóa nbeen cho điều đó
Jens Render

Nền nên là vô hạn, bạn có thể lấy đầu vào vô hạn?
Thuật sĩ lúa mì

@WheatWizard nó không phải là vô hạn, nó phải có thể được làm cho lớn một cách tùy tiện, và nó có thể
Jens Riders

1
Quy tắc 110 không hoàn thành Turing nếu bạn quyết định thế hệ trước và bạn cần đầu vào vô hạn trong công trình tôi biết. Ngay cả khi ai đó tìm thấy một công trình có trạng thái ban đầu hữu hạn, bạn không thể biết bộ nhớ hoặc thời gian cần thiết trước khi chương trình chạy, bởi vì sau đó bạn có thể giải quyết vấn đề Dừng.
Ørjan Johansen

2

JS -> Dòng mới 854 byte

(function(d){var b=0;var n=!0;var c=[];var h=[];var e=0;var l=[];var m=0;var f=2;var a=0;var g=!1;var k=function(a){if(a===1)return!1;if(a%2===0&&a!==2)return!1;if(a%3===0&&a!==3)return!1;if(a%5===0&&a!==5)return!1;if(a%7===0&&a!==7)return!1;for(var b=7;b<d.round(d.sqrt(a))+1;b++)if(a%b===0)return!1;return f=a,!0;};var j=0;var i=0;var o=function(q){var o=d.__split(q,'\n');d.println(o);for(var n=0;n<o.length;n++)if(n>=f^2&&n<=f+1^2&&k(n)){f=n;for(var p=0;p<o[n].length;p++){if(o[n]==='+'&&(a+=c[b],b++),o[n]==='-')if(g===!0&&a<=0)break;else a-=c[b],b++;if(o[n]==='*'&&(a*=c[b],b++),o[n]==='/'&&(a/=c[b],b++),o[n]==='s'&&(a=d.sqrt(a)),o[n]==='%'&&(a%=c[b],b++),o[n]==='a'&&l.push(a),o[n]==='g'&&(a=c[b],b++),o[n]==='q'&&c.push(a),o[n]==='i'&&a++,o[n]==='d')if(g===!0&&a<=0)break;else a--;o[n]==='r'&&(g=!0),o[n]==='w'&&(g=!1),o[n]==='['&&(j=n),o[n]===']'&&a>0&&(n=j,h[e]--),o[n]==='{'&&(i=n),o[n]==='}'&&h[e]>0&&(n=i,h[e]--),m=a,o[n]==='k'&&e++;}}};});

Siêu golf nhờ google.


Tôi nghĩ rằng bạn đã đăng câu trả lời này cho thử thách sai. Bạn có ý định gửi nó đến thử thách này ?

1
Trong trường hợp đó, bạn cần sửa đổi việc thực hiện để nhắm đến điều kiện chiến thắng khác nhau; Đây là môn đánh gôn , không phải cuộc thi phổ biến . Ví dụ: bạn có rất nhiều tên biến rõ ràng có thể ngắn hơn, nghĩa là giải pháp này không phải là một ứng cử viên nghiêm trọng. Bạn có thể xóa nó ngay bây giờ và sau đó phục hồi nó khi bạn có thời gian để chơi nó.

1
Tuy nhiên, câu trả lời không thực hiện một nỗ lực nghiêm túc để tối ưu hóa cho điều kiện chiến thắng là trái với quy tắc . Đó là một lý do đủ tốt để xóa nó cho đến khi bạn có thể làm cho nó phù hợp với các quy tắc.

1
Bạn có thể kết hợp tất cả các vartuyên bố:var b=0,n=!0,c=[],h=[],e=0,l=[],m=0,f=2,a=0,g=!1;
Esolanging Fruit

1
Xin vui lòng xóa tất cả varty
ASCII-chỉ

1

Clojure, 87 byte (Quy tắc 110)

Tín dụng cho mã chẵn lẻ được chuyển đến Jens Render! Tôi đã thực sự đấu tranh về cách thể hiện điều này và tôi sẽ chuyển sang chuyển đổi [p q r]từ nhị phân sang số nguyên và sử dụng bảng tra cứu.

#(iterate(fn[S](for[[p q r](partition 3 1(concat[0]S[0]))](mod(+ q(* q(+ 1 p)r)r)2)))%)

partitionViệc phá hủy ở đây và Clojure làm cho ứng dụng logic khá đơn giản. Hàm này trả về một chuỗi trạng thái vô hạn, vì vậy người gọi có trách nhiệm đến mức takehọ cần hoặc chỉ nthđể chuyển sang trạng thái cụ thể. Nếu phần đệm có số 0 là hai phần tử thay vì chỉ một phần thì băng sẽ liên tục phát triển, tránh các vấn đề về ranh giới. Bây giờ nó vẫn giữ nguyên chiều rộng ban đầu.

Thí dụ:

(def f #(iterate(fn[S](for[[p q r](partition 3 1(concat[0]S[0]))](mod(+ q(* q(+ 1 p)r)r)2)))%))

(pprint (take 5 (f '(0 0 0 0 0 1 1 1 0 0 1 0 0))))
((0 0 0 0 0 1 1 1 0 0 1 0 0)
 (0 0 0 0 1 1 0 1 0 1 1 0 0)
 (0 0 0 1 1 1 1 1 1 1 1 0 0)
 (0 0 1 1 0 0 0 0 0 0 1 0 0)
 (0 1 1 1 0 0 0 0 0 1 1 0 0))

1
Nếu bạn chỉ làm việc với chiều rộng ban đầu, thì điều này có thể không hoàn thành, vì nó chỉ có bộ nhớ hữu hạn. (Trên thực tế, tất cả các cấu trúc Turing-đầy đủ đã biết từ Quy tắc 110 đều yêu cầu "phần đệm" được sử dụng để mở rộng chiều rộng khi chương trình tiếp tục có một mẫu được chỉ định từ đầu vào của người dùng và khác ở bên trái và bên phải, thay vì chỉ sử dụng số không.)

Tôi thấy, điều đó làm cho việc mô phỏng của nó khá khó khăn sau đó. Clojure cyclesẽ có thể xây dựng mô hình đệm vô hạn, nhưng thực hiện bước đầu tiên sẽ mất vô số thời gian: /
NikoNyrh

Hãy nghĩ về nó, sẽ không quá khó để lấy các mẫu đệm đó làm đối số bổ sung và mở rộng băng mô phỏng thêm 1 khối trái và phải. Tốc độ của thông tin ở đây là 1 khối / lần lặp nên chúng ta chỉ cần mô phỏng "hình nón ánh sáng" xung quanh khối trung tâm có cấu trúc không đối xứng. (CMIIW)
NikoNyrh

1

APL (Dyalog) → Biến thể Fractran , 15 byte

(⊃0~⍨××0=1|×)⍣≡

Hãy thử trực tuyến!

Hàm lấy các số hữu tỷ dưới dạng một danh sách các số thay vì hai danh sách chứa tử số và mẫu số và đưa ra kết quả nếu chương trình kết thúc. Điều này thực hiện một biến thể của Fractran có tỷ lệ 1/1 (= 1) hợp lý vào cuối chương trình. Số 1 không ảnh hưởng đến tính đầy đủ của Turing (theo như tôi hiểu) bởi vì đầu vào của chương trình chỉ nằm trên 1 khi không có bất kỳ lý do nào khác hoạt động, và khi đó, đầu vào không thay đổi. Điều này chỉ được sử dụng để chức năng biết khi nào kết thúc.

Liên kết TIO chạy chức năng cho 2 lần lặp (để bạn có thể thấy đầu ra khi chương trình không kết thúc) ở đầu vào đầu tiên và chạy đầu vào thứ hai cho đến khi hoàn thành, sau đó nó sẽ trả lại đầu ra.

(⊃0~⍨××0=1|×)⍣≡ lấy danh sách các số hữu tỷ làm đối số bên trái, được gọi là và đầu vào là đối số bên phải, được gọi là

(⊃0~⍨××0=1|×) chức năng đào tạo

  • 1|×lấy phần sau dấu thập phân (modulo 1) ×của tích và

  • 0= nó có bằng 0 không?

  • ×× nhân kết quả này với ⊣ ×, bất cứ nơi nào hợp lý × không phải là số nguyên, nó được thay thế bằng 0

  • 0~⍨ xóa tất cả 0

  • lấy phần tử đầu tiên

lặp cho đến khi đầu vào không thay đổi, lưu ý rằng kết quả của (⊃0~⍨××0=1|×)được sử dụng lại làm đầu vào, vì vậy nếu nó dừng thay đổi (kết quả là 1 ở cuối) thì chương trình dừng lại


1

JavaScript: Lambda Tính ( 123 114)

Đại diện sử dụng Debruijn Ind khâu trong Duples.

V=function b(c,d){if(!isNaN(c)){for(;--c;)d=d[1];return d[0]}return 0==c[0]?e=>b(c[1],[e,d]):b(c[0],d)(b(c[1],d))}

Tổ hợp S là [0, [0, [0, [[3, 1], [2, 1]]]]]

K là [0, [0, 2]]

Tôi là [0, 1]

Chỉnh sửa: Cạo 9 byte bằng cách thay thế "number"==typeof cbằng!isNaN(c)


0

APL (Dyalog Unicode) , 15 byte SBCS

Chương trình đầy đủ thực hiện một trình thực thi tự động di động một chiều tổng quát. Điều này bao gồm Quy tắc 110 được hoàn thành. Nhắc stdin cho trạng thái ban đầu, số lần lặp (hoặc tiếp tục cho đến khi ổn định hoặc {⍵≡⎕←⍺}hiển thị tất cả các giá trị trung gian cho đến khi ổn định) và đặt quy tắc.

⎕∊⍨∘(⊢∘⊂⌺3)⍣⎕⊢⎕

Hãy thử trực tuyến! (4 lần lặp của Quy tắc 110)

 nhắc về trạng thái ban đầu và

 mang lại kết quả đó (tách trạng thái khỏi số lần lặp)

⍣⎕ nhắc số lần lặp và áp dụng hàm sau nhiều lần:

(... ) áp dụng các chức năng ngầm như sau:

  ⌺3 lấy tất cả các vùng lân cận dài 3 (với thông tin về việc chúng có ở cạnh không) và áp dụng hàm ngầm định sau cho mỗi cặp:

    bao vây khu phố

    và

    mang lại điều đó (loại bỏ thông tin về việc ở rìa)

 sau đó

∊⍨ kiểm tra xem họ có phải là thành viên của

 nhắc về danh sách các vùng lân cận dẫn đến việc lặp lại

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.