Viết một ngôn ngữ lập trình không hoàn chỉnh


91

Xác định liệu một ngôn ngữ là Turing Complete là rất quan trọng khi thiết kế một ngôn ngữ. Đây cũng là một nhiệm vụ khá khó khăn đối với nhiều ngôn ngữ lập trình bí truyền, nhưng hãy để nó phát triển. Hãy tạo ra một số ngôn ngữ lập trình rất khó để chứng minh Turing Complete đến nỗi ngay cả những nhà toán học giỏi nhất trên thế giới cũng sẽ không thể chứng minh chúng theo cách nào. Nhiệm vụ của bạn là đưa ra và thực hiện một ngôn ngữ mà Turing Completeness dựa trên một vấn đề lớn chưa được giải quyết trong Toán học .

Quy tắc

  • Vấn đề bạn chọn phải được đặt ra ít nhất 10 năm trước và phải được giải quyết, kể từ khi đăng câu hỏi này. Nó có thể là bất kỳ phỏng đoán có thể chứng minh được trong toán học, không chỉ là một trong những phỏng đoán được liệt kê trên trang Wikipedia .

  • Bạn phải cung cấp một đặc điểm kỹ thuật của ngôn ngữ và triển khai bằng ngôn ngữ hiện có.

  • Ngôn ngữ lập trình phải là Turing hoàn chỉnh khi và chỉ khi phỏng đoán được giữ. (hoặc nếu và chỉ khi phỏng đoán không giữ)

  • Bạn phải bao gồm một bằng chứng về lý do tại sao nó sẽ là Turing hoàn chỉnh hoặc không đầy đủ dựa trên phỏng đoán đã chọn. Bạn có thể giả sử quyền truy cập vào bộ nhớ không giới hạn khi chạy trình thông dịch hoặc chương trình được biên dịch.

  • Vì chúng tôi quan tâm đến I / O Turing Hoàn thành không bắt buộc, tuy nhiên mục tiêu là tạo ra ngôn ngữ thú vị nhất để có thể giúp ích.

  • Đây là một vì vậy câu trả lời có nhiều phiếu nhất sẽ giành chiến thắng.

Tiêu chí mục tiêu

Một câu trả lời tốt nên làm gì? Dưới đây là một số điều cần tìm khi bỏ phiếu nhưng không bắt buộc về mặt kỹ thuật


Cuộc trò chuyện này đã được chuyển sang trò chuyện .
Dennis

13
Nhìn chung, tôi đang tìm thấy câu trả lời ở đây đáng thất vọng. Chúng có khá nhiều "Bắt đầu với một ngôn ngữ hoàn chỉnh Turing, sau đó kiểm tra xem phỏng đoán X có đúng / Sai không và nếu có, hãy chấm dứt hoặc vô hiệu hóa một tính năng chính."
xnor

1
@xnor Tôi đồng ý với bạn, tôi đã hy vọng rằng tiền thưởng này sẽ gây ra một số câu trả lời thú vị hơn nhưng có vẻ như điều đó sẽ không xảy ra.
Phù thủy lúa mì

2
Tôi nghĩ một trong những vấn đề là hầu hết các phỏng đoán đã được chứng minh là đúng với số lượng giá trị vô hạn nhưng các mẫu đối lập cũng sẽ đúng với số lượng giá trị vô hạn. Kết quả là, gần như không thể chứng minh sự hoàn chỉnh của Turing là đúng.
fnɛtɪk

1
Tôi nghĩ rằng yêu cầu về tính hoàn chỉnh của Turing gắn liền với một với một phỏng đoán nhất định là một yêu cầu khá mạnh mẽ. Tôi nghĩ sẽ dễ dàng nếu việc chứng minh hoặc từ chối tính hoàn chỉnh của Turing quyết định hai vấn đề mở khác nhau, tương ứng. (tức là chứng minh tính hoàn chỉnh của Turing quyết định vấn đề mở A và từ chối quyết định vấn đề mở B).
PyRulez

Câu trả lời:


48

Huyền thoại

Ngôn ngữ này chỉ hoàn thành Turing khi và chỉ khi phỏng đoán của Legendre là sai, tức là tồn tại số nguyên n> 0 sao cho không có số nguyên tố nào giữa n ^ 2 và (n + 1) ^ 2. Ngôn ngữ này lấy một số cảm hứng từ Underload, mặc dù trong một số khía cạnh, nó rất khác với nó.

Các chương trình trong Legendre được tạo thành từ một loạt các số nguyên dương (0 đặc biệt bị cấm, vì về cơ bản nó phủ nhận toàn bộ mục đích của ngôn ngữ). Mỗi số nguyên tương ứng với một lệnh cơ sở trong Legendre hoặc tiềm năng do người dùng xác định. Lệnh nào được gán dựa trên số lượng số nguyên tố giữa bình phương của nó và số nguyên tiếp theo (tương đương với chuỗi OEIS A014085 ).

Các lệnh của ngôn ngữ sửa đổi một ngăn xếp, có thể chứa các số nguyên dương lớn tùy ý. Nếu ngăn xếp giữ 0, 0 sẽ bị xóa ngay lập tức. Cụ thể, các lệnh là:

  • 2 (số nguyên nhỏ nhất tạo lệnh này: 1): Đẩy số nguyên tiếp theo trong chương trình lên ngăn xếp.

  • 3 (số nguyên sản xuất nhỏ nhất: 4): Bật số nguyên trên cùng trên ngăn xếp và thực hiện lệnh được liên kết với nó.

  • 4 (nhỏ nhất: 6): Pop số nguyên trên cùng. Nếu là 1, hãy tăng số nguyên trên cùng của ngăn xếp.

  • 5 (10): Hoán đổi hai mục trên cùng.

  • 6 (15): Giảm số nguyên trên cùng của ngăn xếp. Nếu kết quả là 0, hãy bật 0 và loại bỏ nó.

  • 7 (16): Sao y số nguyên trên cùng của ngăn xếp.

  • 8 (25): Dừng thực thi và in nội dung ngăn xếp.

Đây là tập lệnh cơ bản, không thể làm bất cứ điều gì thú vị, hãy để một mình vòng lặp. Tuy nhiên, có một lệnh khác, chỉ có thể được truy cập nếu phỏng đoán của Legendre chứng minh là sai.

  • 0 (không xác định): Xóa tất cả các mục khỏi ngăn xếp và kết hợp chúng vào một hàm mới, nó sẽ thực thi tất cả các lệnh bắt đầu ở dưới cùng của ngăn xếp và kết thúc ở trên cùng, có thể truy cập dưới dạng một lệnh có "số lệnh" bằng một số nguyên tiếp theo trong nguồn chương trình tương ứng với.

Nếu lệnh này bằng cách nào đó có thể truy cập được, ngôn ngữ sẽ trở thành Turing-Complete, vì người ta có thể mô phỏng một máy Minsky trong đó.

Khi lệnh 8 được thực thi hoặc kết thúc chương trình, chương trình kết thúc và ký tự (Unicode) tương ứng với mỗi số nguyên trên ngăn xếp được in.

Chương trình ví dụ

1 2 1 3 1 10 4

Chương trình đơn giản này đẩy số 2, rồi 3 và cuối cùng là 10, trước khi thực hiện lệnh 4 (lệnh: 3), khiến cho số 10 (lệnh: 5) được bật và thực thi, hoán đổi 2 và 3.

1 5 3 15 2 1 6 7

Chương trình này cho thấy việc sử dụng tương ứng số nguyên-lệnh gián tiếp. Đầu tiên, 5 được đẩy, sau đó là 15 và 1, sử dụng ba cách mã hóa khác nhau cho lệnh 2. Sau đó, 1 được bật lên và kết quả là 15 được tăng lên 16 và cuối cùng được thực thi. Chương trình kết thúc với hai trường hợp của số 5 trên ngăn xếp.

1 1 1 5 ? 24 1 15 1 31 ? 31 24 31

Chương trình này cho thấy việc sử dụng lệnh 0, sử dụng? như một số giữ chỗ. Chương trình trước tiên lưu trữ '1 5' trong chức năng 9, sau đó '15 31 'trong 10, trước khi chạy chức năng 9 (sử dụng 24), đẩy 5 lên ngăn xếp và liên tục giảm xuống, cho đến khi nó về 0 và bị xóa . Sau đó, chương trình tạm dừng.

Máy Minsky

Để chuyển đổi máy Minsky thành mã Legendre, phải sử dụng lệnh 0 . Bởi vì lệnh này không thể truy cập được trừ khi phỏng đoán của Legendre là sai, tôi đã sử dụng trình giữ chỗ? thay thế.

Lưu ý rằng tất cả các tên dòng lệnh của máy Minsky cần phải có các số nguyên với các tương ứng A014085 khác nhau và các lệnh cơ sở cũng như 24 (9) và 31 (10).

Khởi tạo:
1 1 1 1 ? 24
x INC (A / B) y:

A:

1 y 1 24 1 ? 1 6 1 1 16 1 24 ? x

B:

1 y 1 24 1 ? 1 10 1 6 1 1 16 1 10 1 24 ? x
x tháng 12 (A / B) yz:

A:

1 4 1 10 1 15 1 10 1 31 1 1 1 10 1 z 1 1 1 16 1 24 1 31 1 ? 1 24 1 15 1 y 1 6 16 1 24 16 1 ? 1 1 16 1 10 1 1 16 1 24 ? x

B:

1 4 1 10 1 15 1 10 1 31 1 1 1 10 1 z 1 1 1 16 1 24 1 31 1 ? 1 24 1 15 1 10 1 y 1 6 16 1 24 16 1 ? 1 1 16 1 10 1 1 16 1 10 1 24 ? x
x NÓI:
1 25 ? x

Để tạo chương trình cuối cùng, nối thêm tất cả các phần (với x, y, z được thay thế bằng các đối tác của chúng) và thêm một số nguyên duy nhất để bắt đầu lệnh đầu tiên trong chuỗi. Điều này sẽ chứng minh tính hoàn chỉnh của ngôn ngữ trong trường hợp phỏng đoán của Legendre được chứng minh là sai bằng ví dụ mẫu.

Thông dịch viên

Trình thông dịch này được viết bằng Python (3) và đã được thử nghiệm trên cả ba ví dụ trên. Sử dụng cờ -a / - allowZero để cho phép? được sử dụng, tập tin -f / - để chạy mã trực tiếp từ tệp và -s / - stackOut để xuất ngăn xếp dưới dạng danh sách Python thay thế. Nếu không có tệp nào được đưa ra, trình thông dịch sẽ nhập vào một loại chế độ REPL, được sử dụng tốt nhất với --stackOut.

import sys
import argparse
import io

class I_need_missing(dict): #used to avoid try/except statements. Essentially a dict
    def __missing__(self,key):
        return None 

def appropriate(integer,prev): #returns number of primes between the square of the integer given and the next

    return_value = 0

    if prev[integer]:
        return prev[integer],prev
    if integer == "?":
        return 0,prev
    for i in range(integer ** 2, (integer + 1) ** 2):
        t = False
        if i > 1:
            t = True
            for j in range(2,int(i ** 0.5)+1):
                t = i/j != round(i/j)
                if not t:
                    break
        return_value += t

    prev[integer] = return_value
    return return_value,prev

def run_command(commandseries,stack,functions,prev): #Runs the appropriate action for each command.

    command,prev = appropriate(commandseries.pop(0),prev)

    halt = False

    if command == 0: #store in given number
        functions[appropriate(commandseries.pop(0),prev)[0]] = stack
        stack = []

    elif command == 2:#push
        stack.append(commandseries.pop(0))

    elif command == 3:#execute top instruction
        commandseries.insert(0,stack.pop())

    elif command == 4:#pop, add 1 to new top if popped value was 1
        if stack.pop() == 1:
            stack[-1] += 1

    elif command == 5:#swap top two integers/?
        stack[-1],stack[-2] = stack[-2],stack[-1]

    elif command == 6:#subtract 1 from top of stack
        stack[-1] -= 1
        if stack[-1] == 0:
            stack.pop()

    elif command == 7:#duplicate top of stack
        stack.append(stack[-1])

    elif command == 8:#halt
        halt = True

    else:#run custom
        try:
            commandseries[0:0] = functions[command]
        except TypeError:
            print("Warning: unassigned function " + str(command) + " is unassigned", file = sys.stderr)

    return commandseries,stack,functions,prev,halt

def main(stack,functions,prev):
    #Parser for command line options
    parser = argparse.ArgumentParser(description = "Interpreter for the Legendre esoteric programming language.")
    parser.add_argument("-a","--allowZero", action = "store_true")
    parser.add_argument("-f","--file")
    parser.add_argument("-s","--stackOut", action = "store_true")

    args = parser.parse_args()
    allow_zero = bool(args.allowZero)

    #Program decoding starts
    pre = ""

    if not args.file:
        pre = input()
        if pre == "":
            return
    else:
        pre = open(args.file).read()

    mid = pre.split()
    final = []

    for i in mid:
        if i == "?" and allow_zero:
            final.append("?")
        elif i != 0 or allow_zero: #and allow_zero)
            final.append(int(i))

    halt = False

    #Functional programming at its best
    while final and not halt:
        final,stack,functions,prev,halt = run_command(final,stack,functions,prev)

    #Halting and output
    else:
        if args.stackOut:
            print(stack)
        else:
            for i in stack:
                print(i == "?" and "?" or chr(i),end = "")
            print("")
        if args.file or halt:
            return
        else:
            main(stack,functions,prev)


if __name__ == '__main__':
    main([],I_need_missing(),I_need_missing())

14

Liên minh đóng cửa

Ngôn ngữ lập trình này là Turing hoàn chỉnh nếu phỏng đoán Tập hợp đóng là không chính xác.

Kiểm soát

Danh sách các lệnh:
x ++ Tăng x (INC)
x-- Giảm x (DEC)
j (x, y) Thêm tập lệnh x nếu y là 0 vào cuối hàng đợi lệnh

Tất cả các biến được khởi tạo là 0

Cú pháp

Các chương trình được viết dưới dạng một tập hợp các lệnh.
Command1 Command2 Command3 ...
Command1 Command2 ...
...

Để xác định xem chương trình có đóng liên kết không, mỗi bộ chỉ chiếm danh sách các lệnh khác nhau có trong tập
j (x, y)! = J (a, b)
+ (x)! = + (Y)

Nếu bất kỳ loại lệnh nào (+, -, j) xuất hiện trong ít nhất một nửa bộ, thì nó không làm gì cả.

Các chương trình có thể kết thúc nếu không có hướng dẫn nào ở cuối hàng đợi lệnh

Các vòng lặp vô hạn, bao gồm cả vòng lặp trống, có thể đạt được bằng cách sử dụng j (x, y)

Thông dịch viên

Turing hoàn thiện

Nếu tất cả ba lệnh, j (x, y), tăng, giảm các lệnh đều có sẵn, do đó, một máy Minsky có thể được mô phỏng.

Bất kỳ tập hợp nào chỉ có j (x, y) đạt được bằng j (x, y) là HALT
x ++ là INC
x-- là DEC
j (x, y) là JZ

Nếu phỏng đoán tập hợp đóng là chính xác, ít nhất một trong ba lệnh sẽ luôn bị vô hiệu hóa, do đó làm cho ngôn ngữ này không thể hoàn thành Turing.


Những gì tôi sẽ làm là thay vì có 3 toán tử là có vô số giá trị và lấy modulo 4 của mỗi toán tử để có được một trong ba phép toán cộng với một phép toán không. Khi chương trình khởi động, nó kiểm tra xem sự kết hợp của các tập hợp đã được đóng chưa và sau đó loại bỏ bất kỳ phần tử nào nằm trong hơn một nửa các tập hợp. Sau đó nó lặp lại điều này cho đến khi không có yếu tố đó. Nếu phỏng đoán là đúng thì tất cả các chương trình đều giống như chương trình trống, tuy nhiên nếu nó sai, bạn có thể diễn đạt mọi chương trình có thể (đó là lý do tại sao không có op-op).
Phù thủy lúa mì

@WheatWizard Việc xác định liên minh được đóng bởi trình thông dịch coi cùng một toán tử trên các biến khác nhau là khác nhau. x ++ được coi là khác với y ++. Kết quả là, có vô số các bộ khác nhau có thể được tạo ra. Với vô số bộ có thể có, nếu không có loại nào trong ba loại chính nằm trong hơn một nửa số bộ thì nó đã hoàn tất.
fnɛtɪk

Có thể một bằng chứng cho các phỏng đoán tập hợp đóng của Liên minh sẽ để lại một chuyển đổi cho một trong ba toán tử khi hoàn thành, vì có thể để tất cả các toán tử khác nhau trong chương trình, bạn chỉ cần 3 trong số vô số giá trị còn lại.
fnɛtɪk

13

Số nguyên tố Fermat

Ngôn ngữ hoạt động trên hai băng có khả năng vô hạn, trong đó mỗi vị trí của băng có thể lưu trữ một số nguyên tùy ý. Cả hai băng được lấp đầy -1khi bắt đầu. Ngoài ra còn có hai đầu băng bắt đầu ở vị trí 0 trên cả hai băng.

Trình thông dịch trước tiên sẽ đọc đầu vào và lưu các giá trị vào băng (dữ liệu) đầu tiên, bắt đầu từ vị trí 0.

Sau đó, nó sẽ đọc chương trình được cung cấp. Đối với mỗi số mà nó gặp phải, trước tiên, nó sẽ kiểm tra xem giá trị có phải là số nguyên tố Fermat hay không. Nếu có, nó sẽ ghi vào băng thứ hai (hướng dẫn) mà Fermat là chính, nếu không nó sẽ ghi -1vào băng hướng dẫn.

Tiếp theo kiểm tra giá trị tại con trỏ lệnh và thực hiện một trong các thao tác sau:

  • -1 hoặc ít hơn: Thoát khỏi chương trình
  • 0: Di chuyển vị trí băng dữ liệu một bên trái. Di chuyển vị trí băng hướng dẫn một bên phải
  • 1: Di chuyển vị trí băng dữ liệu một bên phải. Di chuyển vị trí băng hướng dẫn một bên phải
  • 2: Tăng giá trị tại vị trí băng dữ liệu. Di chuyển vị trí băng hướng dẫn một bên phải
  • 3: Giảm giá trị tại vị trí băng dữ liệu. Di chuyển vị trí băng hướng dẫn một bên phải
  • 4: Nếu giá trị tại vị trí băng dữ liệu hiện tại bằng 0, sau đó di chuyển băng lệnh sang phải, cho đến khi bạn đạt được 5giá trị khớp (hoặc lớn hơn) trên băng lệnh hoặc nhỏ hơn 0. Nếu nó là một 5(hoặc lớn hơn), di chuyển con trỏ lệnh bên phải một lần nữa, nếu nó nhỏ hơn 0thì thoát khỏi chương trình. Nếu giá trị vị trí băng dữ liệu hiện tại không bằng 0, chỉ cần di chuyển băng hướng dẫn sang bên phải
  • 5hoặc hơn: Di chuyển con trỏ lệnh sang trái, cho đến khi bạn đạt được 4giá trị tương ứng hoặc bạn tìm thấy một cái gì đó nhỏ hơn 0. Trong trường hợp sau, thoát khỏi chương trình.

(bằng cách khớp 5(hoặc nhiều hơn) và 4các giá trị, điều đó có nghĩa là trong khi tìm kiếm giá trị phù hợp trên băng lệnh bất cứ khi nào nó gặp cùng giá trị với lệnh ban đầu (hoặc 5(hoặc nhiều hơn) hoặc 4), nó sẽ phải bỏ qua số thích hợp của giá trị khác ( 4hoặc 5(hoặc nhiều hơn) tương ứng) trên tìm kiếm)

Lặp lại, cho đến khi hướng dẫn nói bạn phải thoát khỏi chương trình.

Khi chương trình thoát, xuất các giá trị trên băng dữ liệu từ vị trí 0cho đến vị trí băng đầu tiên có chứa -1giá trị.

Bằng chứng

Lưu ý rằng về cơ bản, ngôn ngữ ánh xạ tới trình thông dịch Brainfuck không có IO, nơi F_5bắt buộc phải có khả năng thực hiện bất kỳ loại vòng lặp thích hợp nào.

Tuy nhiên, dựa trên phỏng đoán nguyên tố Fermat , chỉ có 5 số nguyên tố Fermat ( F_0- F_4). Nếu F_5tồn tại ngôn ngữ là Turing-Complete, như chúng ta biết rằng Brainfuck là Turing-Complete. Tuy nhiên, nếu không có F_5bạn sẽ không thể thực hiện phân nhánh cũng không lặp, về cơ bản khóa bạn vào các chương trình rất đơn giản.

Thực hiện

(thử nghiệm với ruby ​​2.3.1)

#!/usr/bin/env ruby
require 'prime'

CHEAT_MODE = false
DEBUG_MODE = false
NUM_CACHE = {}

def determine_number(n)
  return n.to_i if CHEAT_MODE
  n = n.to_i
  -1 if n<3

  return NUM_CACHE[n] if NUM_CACHE[n]

  i = 0

  loop do
    num = 2**(2**i) + 1
    if num == n && Prime.prime?(n)
      NUM_CACHE[n] = i
      break
    end
    if num > n
      NUM_CACHE[n] = -1
      break
    end
    i += 1
  end

  NUM_CACHE[n]
end

data_tape = Hash.new(-1)
instruction_tape = Hash.new(-1)

STDIN.read.each_char.with_index { |c,i| data_tape[i] = c.ord }
File.read(ARGV[0]).split.each.with_index do |n,i|
  instruction_tape[i] = determine_number(n)
end

data_pos = 0
instruction_pos = 0

while instruction_tape[instruction_pos] >= 0
  p data_tape, data_pos, instruction_tape, instruction_pos,'------------' if DEBUG_MODE

  case instruction_tape[instruction_pos]
  when 0 then data_pos -= 1; instruction_pos += 1
  when 1 then data_pos += 1; instruction_pos += 1
  when 2 then data_tape[data_pos] += 1; instruction_pos += 1
  when 3 then data_tape[data_pos] -= 1; instruction_pos += 1
  when 4 then
    if data_tape[data_pos] == 0
      count = 1
      instruction_pos += 1
      while count>0 && instruction_tape[instruction_pos] >= 0
        count += 1 if instruction_tape[instruction_pos] == 4
        count -= 1 if instruction_tape[instruction_pos] >= 5
        instruction_pos += 1
      end
      break if count != 0
    else
      instruction_pos += 1
    end
  else
    count = 1
    instruction_pos -= 1
    while count>0 && instruction_tape[instruction_pos] >= 0
      count += 1 if instruction_tape[instruction_pos] >= 5
      count -= 1 if instruction_tape[instruction_pos] == 4
      instruction_pos -= 1 if count>0
    end
    break if count != 0
  end
end

data_pos = 0

while data_tape[data_pos] >= 0
  print data_tape[data_pos].chr
  data_pos += 1
end

Ví dụ:

Điều này sẽ ghi H( viết tắt Hello World!) vào màn hình với một dòng mới:

17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17
5
17 17 17 17 17 17 17 17 17 17
17

Lưu dưới dạng example.fermatvà chạy nó như thế này (lưu ý: bạn luôn cần phải có đầu vào):

$ echo -n '' | ./fermat.rb example.fermat

Ví dụ tiếp theo này sẽ thực hiện một cypher kiểu Caesar đơn giản bằng cách tăng từng giá trị của đầu vào. Bạn rõ ràng phải thay thế ?bằng thủ tướng Fermat thứ 5:

17 65537 5 17 ? 257

Bạn có thể dùng thử rằng nó hoạt động bằng cách bật chế độ gian lận và sử dụng 2 4 1 2 5 3làm mã nguồn:

$ echo 'Hello' | ./fermat.rb example2_cheat.fermat

2
Tôi cảm thấy tiếc cho các lập trình viên nghèo, người phải gõ số nguyên tố tương ứng để có được 5. Tôi hy vọng họ có một bàn phím tốt.
admBorkBork

2
@AdmBorkBork Đừng lo lắng. Nó chỉ có nhiều bit hơn vũ trụ có các hạt nguyên tố.
fnɛtɪk

@LliwTelracs thực sự không có ý nghĩa vì số lượng hạt nguyên tố trong vũ trụ là Aleph-null (omega) và từ omega, nó bắt đầu không có nghĩa là kích thước thực tế của số lượng. (Trừ khi aleph one: P)
Matthew Roh

1
@MatthewRoh Tôi đã phạm sai lầm. Tôi có nghĩa là trong vũ trụ quan sát được.
fnɛtɪk

2
@MatthewRoh Trên thực tế, nó có thể là hữu hạn, vô hạn, không thể đếm được, hoặc thậm chí không phù hợp với lý thuyết tập hợp! Tuy nhiên, chúng tôi sẽ không bao giờ biết :(
CalculatorFeline

10

Nuốt w / Dừa v2

Vì phiên bản trước có lỗi khiến nó không hợp lệ cho cuộc thi này và tôi không muốn có sự nâng cấp từ số phiên bản trước cho phiên bản này khác biệt đáng kể, phiên bản này đang được gửi dưới dạng bài đăng mới.

Ngôn ngữ này không hoàn chỉnh nếu Giả thuyết Collatz có thể được chứng minh cho tất cả các số nguyên dương. Nếu không, ngôn ngữ là Turing hoàn chỉnh.

Ngôn ngữ này được dựa trên Hồng y .

Đầu tiên, contVal của chương trình được tính bằng công thức
contVal = sum (sum (giá trị ASCII của hàng) * 2 ^ (hàng số-1))

Tiếp theo, 2 Swallows đi theo hướng ngược lại được tạo ra ở mỗi A hoặc E và tất cả các câu lệnh rẽ có điều kiện được đặt để chờ khởi tạo.
Những con én được tạo ra tại một E đang hướng sang trái / phải và những con én được tạo ra tại A đang hướng lên / xuống.

Cuối cùng, mã sẽ thực hiện các bước cho đến khi tất cả các con trỏ đã bị xóa hoặc contVal đã giảm xuống một.

Ở mỗi bước, nếu contVal% 2 == 0, nó sẽ được chia cho 2, nếu không, nó sẽ được nhân với ba và tăng lên một.

Các lệnh:

0: đặt giá trị thành 0
+: giá trị tăng thêm 1
>: thay đổi hướng sang phải
v: thay đổi hướng xuống dưới
<: đổi hướng sang trái
^: thay đổi hướng lên trên
R: Con trỏ tiếp theo sau khi con trỏ đầu tiên so sánh với giá trị của con trỏ đầu tiên. Nếu bằng nhau, đi thẳng, khác rẽ phải.
L: Con trỏ tiếp theo sau con trỏ đầu tiên so sánh với giá trị của con trỏ đầu tiên. Nếu bằng nhau, đi thẳng, khác rẽ trái.
E: Sao y con trỏ nhưng hướng theo hướng trái và phải
A: Sao chép con trỏ nhưng hướng theo hướng lên và xuống
? : Xóa con trỏ nếu giá trị bằng 0

Giải trình:

Nếu Giả thuyết Collatz có thể được chứng minh cho tất cả các số nguyên dương, thì thời lượng của bất kỳ chương trình nào chạy bằng ngôn ngữ này là hữu hạn, vì contVal sẽ luôn hội tụ đến 1, do đó kết thúc chương trình.

Mặt khác, tôi chỉ cần chứng minh rằng ngôn ngữ này có thể thực hiện các chức năng sau

Gia tăng: được biểu thị bằng +
Hằng số 0: được biểu thị bằng 0
Truy cập biến: các biến được lưu trữ dưới dạng con trỏ khi chúng di chuyển Kết
nối câu lệnh: bằng cách thay đổi khoảng cách di chuyển đến các hoạt động, có thể thay đổi thứ tự các thao tác được thực hiện
Đối với vòng lặp: Trong ngôn ngữ này

E   > V
    ^+R
      +
      A

sẽ hoạt động như một vòng lặp for> đếm tối đa 1 (có thể thêm mã vào vòng lặp)

Tương tự, mã

Rv
^<

Sẽ hoạt động như một cho đến khi bằng với giá trị có điều kiện được đặt trong vòng lặp R.


Bạn đánh tôi quá nó, tôi sẽ làm một cái gì đó theo phỏng đoán collatz. Công việc tốt, trên thú vị đảm nhận nó. Tôi sẽ tạo ra một ngôn ngữ chỉ có thể lưu trữ số nếu chúng hội tụ đến 1.
Rohan Jhunjhunwala

Tôi bối rối. Hàm Collatz nằm ở đâu trong số này? Từ lần đọc thứ hai tôi nghĩ bạn muốn nói rằng hàm này được áp dụng cho contValmọi bước (và do đó nếu phỏng đoán là đúng, không có vòng lặp vô hạn) - nhưng tôi không thấy điều đó được nêu rõ ở bất cứ đâu trong câu trả lời. ??
DLosc

Xin lỗi, trong khi nó đang làm điều đó tôi nghĩ rằng tôi đã vô tình cắt nó ra khỏi mô tả của tôi tại một số điểm
fnɛtɪk

10

Sự hoàn hảo / không hoàn hảo

Whew, đó là niềm vui.

Sự hoàn hảo / Không hoàn hảo chỉ hoàn thành nếu có những con số hoàn hảo vô hạn. Nếu có, nó được gọi là Sự hoàn hảo, và nếu không có, nó được gọi là Sự không hoàn hảo. Cho đến khi bí ẩn này được giải quyết, nó giữ cả hai tên.

Một số hoàn hảo là một số có ước số của nó bằng số đó, vì vậy sáu là một số hoàn hảo bởi vì 1+2+3=6.

Sự hoàn hảo / không hoàn hảo có các chức năng sau:

Sự hoàn hảo / Không hoàn hảo là dựa trên ngăn xếp, với ngăn xếp không có chỉ mục.

Các lệnh:

p(x, y): đẩy x đến ngăn xếp ở vị trí thứ y.

z(x, y): đẩy x đến ngăn xếp ở vị trí thứ y, thoát khỏi những gì trước đây ở vị trí thứ

r(x): xóa mục thứ x khỏi ngăn xếp

k(x): trả về mục thứ x trên ngăn xếp

a(x, y): thêm x và y. Khi được sử dụng với các chuỗi, nó đặt chúng lại với nhau theo thứ tự xy.

s(x, y): trừ y từ x. với các chuỗi, loại bỏ len (y) cuối cùng khỏi x

m(x, y): nhân x và y. Nếu được sử dụng với chuỗi, nhân x lần len y.

d(x, y): chia x cho y

o(x): in x

i(x, y): nếu x đánh giá là đúng, thì nó thực thi hàm y

n(): trả về bộ đếm khối mã đang được gọi.

q(): trả về chiều dài của ngăn xếp

t(): đầu vào của người dùng

e(x, y): Nếu x là một số nguyên, nếu x và y có cùng giá trị, thì giá trị này trả về 1. nếu y là một chuỗi thì nó nhận được độ dài của y. if x là một chuỗi, sau đó nó chuyển đổi y thành một chuỗi và kiểm tra xem chúng có giống nhau không và nếu có, trả về 1. Nếu không, nó trả về 0.

l(x, y): nếu x lớn hơn y, thì nó trả về 1. Nếu có một chuỗi, thì nó sử dụng độ dài của chuỗi.

b(): dừng chương trình.

c(x, y): chạy x, rồi y.

Để có được tương đương với Python and, nhân hai giá trị với nhau. Cho or, thêm các giá trị và nottrừ, trừ giá trị từ 1. Điều này chỉ hoạt động nếu giá trị là 1 hoặc 0, có thể đạt được bằng cách chia số cho chính nó.

Kiểu dữ liệu: số nguyên và chuỗi. Các chuỗi được ký hiệu bởi ''và tất cả các số không nguyên được làm tròn.

Cú pháp:

Mã bao gồm các hàm lồng nhau trong mười {}s. Ví dụ, một chương trình nhận đầu vào và in chúng được thêm vào sẽ là : {o(a(t(), t()))}. Trong nền của chương trình, có một bộ đếm bắt đầu từ 0 và tăng lên 1 mỗi khi nó thực thi một khối mã. Khối mã đầu tiên chạy tại 0, v.v. Khi mười khối mã được thực thi, khối thứ sáu được thực thi mỗi khi bộ đếm đạt đến một số hoàn hảo. Bạn không cần phải có tất cả mười khối mã để chương trình hoạt động, nhưng bạn cần 7 khối nếu bạn muốn tạo một vòng lặp. Để hiểu rõ hơn về cách thức hoạt động của ngôn ngữ này, hãy chạy chương trình sau, in ra bộ đếm mỗi khi bộ đếm đạt đến một số hoàn hảo : {}{}{}{}{}{}{o(n())}.

Trình thông dịch có thể được tìm thấy ở đây: repl.it/GL7S/37 . Chọn 1 và nhập mã của bạn vào thiết bị đầu cuối hoặc dán mã của bạn vào code.perfecttab và chọn 2 khi bạn chạy. Nó sẽ có ý nghĩa khi bạn thử nó.

Bằng chứng về tính đầy đủ của Turing / thiếu tính hoàn chỉnh của Turing.

Theo bài viết trao đổi ngăn xếp kỹ thuật phần mềm này , một Turing hoàn chỉnh phải có thể có một hình thức lặp lại có điều kiện của bước nhảy và có cách đọc hoặc ghi bộ nhớ. Nó có thể đọc / ghi bộ nhớ ở dạng ngăn xếp và nó có thể lặp do thực tế là khối mã thứ 6 được thực thi mỗi khi bộ đếm đạt đến một số hoàn hảo. Nếu có vô số số hoàn hảo, nó có thể lặp vô hạn và hoàn thành Turing, và nếu không thì không.

Trình thông dịch thẻ tuần hoàn tự bitwise có 5 ký tự, 1 hoặc 0, làm đầu vào:

{p(t(),0)}{(p(t(),0)}{p(t(),0)}{p(t(),0)}{p(t(),0)}{p(0,0)}{c(i(e(k(s(q(),k(0))),0),c(r(q()),i(l(k(0),0),z(s(k(0),1),0)))),i(e(k(s(q(),k(0))),1),c(z(a(k(0),1),0),i(e(k(q()),1),p(k(s(q(),k(0))),1)))))}

Nó có thể được mở rộng để lấy bất kỳ số ký tự nào làm đầu vào. Nó có thể mất đầu vào vô hạn, nhưng chỉ khi có những con số hoàn hảo vô hạn!


1
Tôi nghĩ rằng bạn chỉ có thể tạo một giá trị mới để lặp cục bộ vì nó không được chia sẻ với hàm.
fnɛtɪk

3
Vì nó đứng bạn không có bằng chứng về TC. Bài viết về kỹ thuật phần mềm mà bạn liên kết để đưa ra một loạt các yêu cầu sơ bộ, tuy nhiên TC không chỉ là một loạt các hộp để kiểm tra. Bạn sẽ cần triển khai một máy tự động TC (như Máy Minsky) hoặc cho thấy rằng ngôn ngữ của bạn là không thể giải quyết được.
Phù thủy lúa mì

2
@WheatWizard Ở đó, tôi đã thêm một trình thông dịch Thẻ theo chu kỳ Bitwise. Nó có thể được sửa đổi để lấy bất kỳ số lượng ký tự nào làm đầu vào. Nó có thể có thể lấy ký tự vô hạn làm đầu vào, nhưng chỉ khi có số hoàn hảo vô hạn!
Đồng chí SparklePony

2
"Một khi mười khối mã được thực thi, khối thứ sáu được thực thi mỗi khi bộ đếm đạt đến một số hoàn hảo." Vậy trình thông dịch chỉ đếm trực tiếp các số hoàn hảo? Tôi cảm thấy như điều này đi ngược lại với tinh thần của thử thách. Đặc tả ngôn ngữ thực tế không quan trọng lắm, nó có thể là bất cứ điều gì Turing-Complete cộng với "chỉ chạy một bước chỉ khi bạn đạt được một số hoàn hảo".
xnor

10

Đế

Ngôn ngữ lập trình này là Turing hoàn chỉnh nếu phỏng đoán Scholz là đúng.

Tôi đã viết ngôn ngữ này bởi vì @SztupY đã nói rằng sẽ không có bất kỳ kết quả nào dựa trên sự phỏng đoán là đúng để hoàn thành Turing

Danh sách các lệnh

+(x)      Increment x (INC)   
-(x)      Decrement x (DEC)  
j(x,y)    Jump to instruction x if y is 0 (JZ)  
x         End program (HALT) 

Với các lệnh này, ngôn ngữ này có thể mô phỏng một máy Minsky

Thông dịch viên

Tôi rất khuyên bạn không nên chạy này. Nó sử dụng một phương pháp cực kỳ chậm để kiểm tra chuỗi bổ sung.

Turing hoàn chỉnh

Ngôn ngữ sử dụng bộ đếm cho số lượng lệnh chạy mà nó kiểm tra theo phỏng đoán Scholz để sửa đổi tính hoàn chỉnh của ngôn ngữ.

Nếu phỏng đoán Scholz là đúng, chương trình này hoạt động giống hệt như một máy Minsky bình thường với
Tăng
Decrement
Jump nếu Zero,
Halt

Tuy nhiên, nếu phỏng đoán Scholz là sai, cuối cùng bộ đếm sẽ đạt đến một giá trị mà phỏng đoán Scholz không đúng. Vì ngôn ngữ đã được thiết kế để thoát khi đạt đến một số mà phỏng đoán Scholz là sai, chương trình sẽ thoát mỗi lần sau khi chạy nhiều lệnh đó. Do đó, tất cả các chương trình sẽ có độ dài hạn chế. Vì điều này không đồng ý với các yêu cầu để ngôn ngữ được hoàn thành,

"Băng không thể cố định về chiều dài, vì điều đó sẽ không tương ứng với định nghĩa đã cho và sẽ hạn chế nghiêm trọng phạm vi tính toán mà máy có thể thực hiện đối với máy tự động giới hạn tuyến tính",

ngôn ngữ sẽ không hoàn thành Turing nếu phỏng đoán Scholz là sai


1
+1, vì điều này thực sự khó thực hiện yêu cầu phỏng đoán vào ngôn ngữ, thay vào đó thêm một thứ gì đó không liên quan để giết ngôn ngữ nếu phỏng đoán là đúng / sai
Gryphon

Tôi không hiểu Các lệnh bạn cung cấp chính xác là các lệnh bạn cần để mô phỏng máy Minsky, vì vậy nếu đó là tất cả thì ngôn ngữ của bạn đã hoàn thành bất kể phỏng đoán Scholz. Bạn phải thiếu một cái gì đó từ lời giải thích của bạn.
Nathaniel

@Nathaniel Một trong những yêu cầu đối với một ngôn ngữ hoàn chỉnh Turing là ngôn ngữ có thể kết thúc trong một vòng lặp vô hạn (vấn đề tạm dừng). Mã của tôi được tính khi nó chạy các hướng dẫn và nếu phỏng đoán Scholz là sai, chương trình sẽ luôn dừng sau một số hướng dẫn đã đặt.
fnɛtɪk

Có, nhưng bạn đã quên giải thích nguyên nhân khiến nó dừng lại nếu phỏng đoán Scholz là sai. Hãy xem lại câu trả lời của bạn - nó hoàn toàn không có.
Nathaniel

@Nathaniel Chương trình thực sự hoạt động bằng cách kiểm tra từng số duy nhất nếu nó hoạt động trong phỏng đoán scholz. Nó tự động thoát khi tìm thấy một số không đồng ý với phỏng đoán.
fnɛtɪk

9

Hứa hôn

Github hứa hôn .

Readme và đặc tả là trên github, trong "README.txt".

Nói chung, một chương trình Betrothed bao gồm các cặp dòng, có độ dài là các cặp nguyên tố sinh đôi riêng biệt hoặc các cặp được hứa hôn (không có sự trùng lặp nào có thể xảy ra). Chương trình được thực hiện bằng cách tìm "tập con đáng tin cậy" của dòng đầu tiên trong cặp trong dòng thứ hai. Số lượng các tập hợp con như vậy, kết hợp với khoảng cách levenshtein giữa dòng thứ hai ban đầu và dòng thứ hai không có các tập hợp con đáng tin cậy, xác định lệnh để thực thi.

Tôi sẽ trích dẫn bằng chứng cho bài viết này:

V. PROOF OF TURING COMPLETENESS

Now, no language can be Turing Complete with bounded program size. Therefore, if Betrothed
is Turing Complete, it must have unbounded program size. Since the lengths of the lines of
a Betrothed program must be twin prime pairs or betrothed pairs, and since both sequences
are unproven to be infinite or finite, Betrothed has unbounded program size if and only if
there are infintie betrothed pairs, there are infinite twin prime pairs, or both.

    Next: to prove that if Betrothed has an unbounded program size, then it is Turing
Complete. I will use the op-codes from the above table to demonstrate key factors of a
Turing Complete language; they are of the form  [index]<[ld]> .

  1. Conditional goto: 6<> 5<>, or if-popjump. This can be used to form a loop.
  2. Inequality to a constant K: 10<K> 
  3. Arbitrarily large variable space: you can use some separator constant C.

    With this, I have sufficient reason to believe that Betrothed is Turing Complete.

4
"Bây giờ, không có ngôn ngữ nào có thể là Turing Complete với kích thước chương trình giới hạn." Tôi bối rối về tuyên bố này ... Một mặt, đúng là với quy mô chương trình bị ràng buộc, chúng tôi chỉ có thể viết một số lượng hữu hạn các chương trình khác nhau, nhưng mặt khác, một bằng chứng chung cho Turing Completeness là viết một trình thông dịch cho một người khác Ngôn ngữ Turing Complete, hoàn toàn không cần kích thước chương trình không giới hạn ...
Leo

1
Chà, chương trình được chuyển cho trình thông dịch không cần phải nhập mã của trình thông dịch, nó nên được trao cho trình thông dịch làm đầu vào
Leo

7
@Sư Tử. Tôi sẽ nói rằng, để ngôn ngữ là TC, nó phải có khả năng mã hóa chương trình được chuyển đến trình thông dịch (nghĩa là hãy tưởng tượng rằng ngôn ngữ này không có lệnh đầu vào.) Hãy tưởng tượng một ngôn ngữ với một lệnh : b. Điều này diễn giải một chương trình BF, được đặt sau nó, như thế b+++++.. Kích thước của chương trình, tuy nhiên, giới hạn trong 10 ký tự. Mặc dù nó có thể giải thích BF, nhưng nó không thể tính toán tất cả các chương trình mà máy Turing có thể.
Conor O'Brien

3
@EriktheOutgolfer vấn đề chính với vấn đề của bạn là "nó có thể đặt chương trình BF mà nó nhận được từ đầu vào ..." Đối với điều này, tôi khuyến khích bạn đọc hoặc đọc lại nhận xét trước đó của tôi, đặc biệt là câu đầu tiên này. Nếu ngôn ngữ chỉ Turing hoàn thành dựa trên đầu vào, thì làm thế nào mà ngôn ngữ đó không thể hoàn thành? Đó là, để ngôn ngữ được Turing hoàn thành, chính chương trình của ngôn ngữ phải mã hóa chương trình. Mặt khác, người ta thấy rằng họ đang mã hóa chương trình trong đầu vào, đây không phải là một cách lập trình hợp lệ.
Conor O'Brien

1
Tôi không nghĩ rằng đây là một điểm giải quyết. Bài báo Esolang này thảo luận về vấn đề này. (Ngoài ra còn có câu hỏi liệu một chương trình in ra mọi chương trình kết thúc có thể bằng ngôn ngữ Turing-perfect , cùng với đầu ra của nó, có phải là một minh chứng về tính đầy đủ của Turing hay không; có yêu cầu đầu vào và có thể được thực hiện với một chương trình dài .)

5

Chẵn lẻ

Ngôn ngữ này dựa trên việc có bất kỳ số hòa giải nào có tính chẵn lẻ ngược nhau hay không .

Các lệnh

x : End program if not on top line  
+ : increment stored value  
- : decrement stored value  
{ : set next goto x value to current x value
} : goto previous x value set by {  
j : Go down one line if the special value is an amicable number and the
    parity is opposite to the matching number (loops back to top). If the
    special value is not an amicable number and not on the top line, go up
    one line.  

Kiểm soát dòng chảy

Chương trình lặp đi lặp lại từ trái sang phải trước khi lặp lại từ đầu. Nếu nó gặp "j", nó sẽ kiểm tra giá trị để xác định xem nó có thay đổi hàng không. Nếu số này là một số hòa hợp có tính chẵn lẻ đối xứng với khớp của nó, nó sẽ đi xuống một hàng (lặp lại trên cùng), nếu không, nếu số đó là một số có thể hòa giải, nó sẽ tăng lên một hàng nếu chưa ở hàng trên cùng.

Chương trình chỉ có thể kết thúc nếu chương trình đạt đến một x ở bất kỳ hàng nào bên ngoài hàng trên cùng.

Turing hoàn thiện

Chương trình này có thể được sử dụng để mô phỏng một cỗ máy Minsky giả sử rằng có một cặp số hòa hợp với tính chẵn lẻ đối diện.

j, {và} có thể được sử dụng để mô phỏng JZ (r, x) mặc dù nó sẽ kiểm tra các số có thể thay vì bằng không.
+ là INC (r)
- là DEC (r)
x là HALT

Nếu bạn không thể rời khỏi hàng đầu tiên, các lệnh x và} không làm gì cả. Điều này dẫn đến việc chương trình không thể vào trạng thái HALT trừ khi đó là chương trình trống. Do đó, theo mô tả rằng tính đầy đủ của Turing yêu cầu trạng thái HALT , ngôn ngữ sẽ là Turing không đầy đủ.

Thông dịch viên


2

Dòng mới

Disclaimer: Đó là một chút lộn xộn và khá đơn giản. Đây là ngôn ngữ đầu tiên tôi từng viết và phỏng đoán là ngôn ngữ duy nhất tôi hiểu. Tôi biết một người dùng khác đã có câu trả lời dài hơn với cùng một câu hỏi nhưng tôi vẫn quyết định viết nó.

Để viết trong Newline, bạn phải có nhiều thời gian và dòng mới ( \n). Điều này làm việc ra khỏi phỏng đoán Legendre là đúng. Mọi toán tử phải rơi vào một số trong phỏng đoán Legendre mà chúng ta bắt đầu bằng n = 1. Mỗi khi bạn có một toán tử, bạn lấy số lượng \ n's và cắm số đó vào Giả thuyết Legendre và lấy phạm vi số tiền chính tiếp theo của \ n phải rơi vào. Vì vậy, để bắt đầu, \n\nbạn chuyển sang một nhà điều hành, sau \nđó một nhà điều hành khác, chúng tôi đang ở 3 dòng mới. Bây giờ, cái tiếp theo là 5 vì vậy bạn thêm \n\nvà vào toán tử để đảm bảo rằng dòng toán tử cuối cùng có số lượng dòng mới phù hợp với số tiền gốc nằm trong phỏng đoán Legendre mà chúng tôi đã bắt đầu.

Các số (mảng) giống như các biến. Mỗi khi một toán tử chạy (sử dụng số), nó sẽ tăng lên.

+ adds
- subtracts
/ divide
* multiply 
s sqrt
% mod
a push to vars
g sets stack to numbers
q pushes value of stack to numbers
i increment 
d decrement
r stops subtraction at 0
w turns back on subtraction past 0
[ starts loop
] ends loop runs until stack is 0
{ starts loop
} ends loop and loops until loops[ln] is 0
k increment loops

Miễn là chúng ta có các số nguyên tố không giới hạn tuân theo các quy tắc, ngôn ngữ này có băng không hữu hạn.

Máy Minsky

\n\ng\nr\n\n[\n\nd\n\n\n\n]

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

\n\ng     # the first two newlines are to get to a prime number of newlines (2) then sets the value of stack to the first variable in the array numbers (see code in link)

\nr       # gets to the next number and makes it so subtraction stops at 0

\n\n[     # starts the loop

\n\nd     # decrements stack 

\n\n\n\n] # ends loop

Hãy dùng thử trên KhanAcademy .


@ tại sao nó không cần phải lặp với bộ nhớ không hữu hạn
Christopher

Nó chỉ hoạt động nếu nó là sự thật. Tôi không thể hoàn thành việc viết ngay bây giờ vì tôi đang ở trên điện thoại di động nhưng sẽ tối nay
Christopher

Ngay cả khi bạn có bộ nhớ vô hạn, bạn vẫn cần có khả năng lặp vô hạn.
Pavel

Tôi có vòng lặp. Cố gắng làm cho chúng vô hạn
Christopher

Ngay bây giờ họ gặp sự cố
Christopher

2

Taggis

Taggis là một ngôn ngữ dựa trên hệ thống thẻ .

Tính hoàn chỉnh của Taggis dựa trên Giả thuyết Collatz

Cú pháp

Cú pháp của chương trình Taggis chỉ đơn giản là ba chuỗi (quy tắc sản xuất) bao gồm toàn bộ các chữ cái a, b và c, được phân cách bằng dấu cách.

Chấp hành

Trạng thái chương trình duy nhất của Taggis là một chuỗi bao gồm ba ký tự giống nhau.

Taggis thực hiện một hệ thống thẻ TS (3, 2), trong đó ở mỗi bước, 2 chữ cái đầu tiên của "thẻ" hiện tại sẽ bị xóa và chữ cái đầu tiên trong phần bị loại bỏ đó sẽ được thêm vào quy tắc sản xuất tương ứng. chuỗi.

Ví dụ: chương trình Taggis bc a aaathực hiện bài toán 3n + 1, trong đó các lần lặp được biểu thị bằng một số as tương ứng và bước 3n + 1 được thay thế bằng (3n + 1) / 2 [1], dẫn đến đầu ra của chương trình:

aaa // 3
  abc
    cbc
      caaa
        aaaaa // 5
          aaabc
            abcbc
              cbcbc
                cbcaaa
                  caaaaaa
                    aaaaaaaa // 8
                      aaaaaabc
                        aaaabcbc
                          aabcbcbc
                            bcbcbcbc
                              bcbcbca
                                bcbcaa
                                  bcaaa
                                    aaaa // 4
                                      aabc
                                        bcbc
                                          bca
                                            aa // 2
                                              bc
                                                a // 1 and halt because we then begin an infinite loop
                                                 HALT

Turing hoàn chỉnh

Tất nhiên, hệ thống đơn giản này có vẻ quá đơn giản để mô phỏng tính hoàn chỉnh của Turing, nhưng hóa ra bất kỳ máy Turing nào có 2 ký hiệu (một lớp bao gồm các máy vạn năng) đều có thể được chuyển đổi thành hệ thống thẻ có 2 ký tự bị xóa khỏi đầu, và quy tắc sản xuất 32 * m, trong đó msố lượng trạng thái trong máy Turing.

Máy Turing phổ dụng nhỏ nhất được biết đến chỉ có 2 biểu tượng sử dụng 18 trạng thái và do đó hệ thống thẻ tương ứng chứa 576 quy tắc sản xuất khổng lồ [2].

Tuy nhiên, lớp tính toán của tập hợp tất cả các hệ thống thẻ với 3 sản phẩm và 2 biểu tượng bị loại bỏ được gắn với Giả thuyết Collatz [2]. Nếu Giả thuyết Collatz được chứng minh là sai, thì Taggis là Turing-Complete. Mặt khác, nó dựa trên vấn đề chưa được giải quyết trong toán học, tìm ra một máy Turing nhỏ hơn

def taggis(inp, a, b, c):
    current = inp
    seen = set()
    while True:
        seen.add(tuple(current))

        yield current

        head = current[0]

        current = current[2:]

        current.extend([a, b, c][head])

        if tuple(current) in seen:
            return

def parse():
    program = input().split(" ")

    assert len(program) == 3, "There has to be exactly 3 production rules!" 

    productions = []

    for production in program:

        production = [{"a": 0, "b": 1, "c": 2}[x] for x in production]
        productions.append(production)  

    program_input = [{"a": 0, "b": 1, "c": 2}[x] for x in input()]

    k = 0   

    for step in taggis(program_input, *productions):
        print(' ' * k +''.join(['abc'[x] for x in step]))

        k += 2
    print(' ' * (k - 1) + 'HALT')

parse()
  1. tương đương với hàm Collatz ban đầu vì 3n + 1 của số lẻ nsẽ luôn là số chẵn và do đó phép chia có thể được áp dụng tự động

  2. Hệ thống thẻ và các chức năng giống Collatz, Liesbeth De Mol ,

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.