Ngôn ngữ không hạn chế


28

Một trong những loại thử thách yêu thích của tôi trên trang web này là thử thách . Những thách thức này đặt ra một hạn chế về máy tính mà các nguồn của câu trả lời tiềm năng phải vượt qua. Tôi thích những thử thách này rất nhiều, tôi đã làm việc với một ngôn ngữ golf được thiết kế để giành chiến thắng tại những thử thách này trong một thời gian. Bây giờ tôi muốn mở rộng thử thách cho bạn. Nhiệm vụ của bạn là thiết kế một ngôn ngữ để giải quyết nhiều nhiệm vụ nguồn bị hạn chế. Bạn sẽ có thời gian để thiết kế và thực hiện một ngôn ngữ, tại đó các thay đổi và bổ sung mới sẽ không cạnh tranh và tất cả các bài nộp sẽ đối đầu trong một thách thức về .

Chấm điểm

Trước khi thử thách được đăng, tôi sẽ đưa ra một danh sách các thử thách đơn giản để giải quyết và một danh sách các hạn chế nguồn cần tuân theo. Đối với mỗi kết hợp thách thức và giới hạn nguồn, ngôn ngữ của bạn có thể kiếm được từ 0 đến 2 điểm. (sẽ có 10 thử thách và 10 hạn chế dẫn đến tổng số 100 kết hợp) Điểm số ngôn ngữ

  • 1 điểm nếu nó có thể hoàn thành nhiệm vụ với hạn chế dưới 150 byte
  • 2 điểm nếu giải pháp là giải pháp ngắn nhất trong mọi ngôn ngữ cạnh tranh (cả hai ngôn ngữ sẽ ghi được 2 điểm trong trường hợp hòa)
  • 0 điểm nếu họ không thể tạo chương trình hoàn thành nhiệm vụ theo giới hạn dưới 150 byte.

Điểm của bạn sẽ là tổng của tất cả các điểm kiếm được trong mỗi trận đấu có thể lên. Mục tiêu là để có được điểm số cao nhất. Những người khác có thể giúp bạn đánh golf các giải pháp của bạn cho từng thử thách và cải thiện điểm số của bạn.

Tôi sẽ tiết lộ 4 mục của mỗi danh sách tại thời điểm đăng và thêm 8 mục một tuần sau câu trả lời thứ hai. Bạn sẽ chỉ được phép ghi 1 điểm (lần gửi ngắn nhất không được tính) trong bất kỳ trận đấu nào có cả hai phần được tiết lộ trước tuần đầu tiên. Bằng cách này, bạn có thể có được ý tưởng về việc ngôn ngữ của bạn tích lũy tốt như thế nào trong khi bạn đang làm việc với nó, nhưng bạn không thể thiết kế ngôn ngữ của mình đơn giản để xây dựng trong tất cả các thách thức và hạn chế.

Tôi sẽ bao gồm một hàm băm của các danh mục dự định với câu hỏi để bạn có thể chắc chắn rằng tôi không thay đổi chúng trong tuần để tạo lợi thế cho bất kỳ bên nào. Ngoài ra, tôi sẽ không nói cho ai biết các thông số ẩn cho đến khi hết tuần và cũng không tự mình cạnh tranh trong thử thách.

Ngôn ngữ có sẵn

Thử thách này dành cho tất cả các ngôn ngữ có sẵn, tuy nhiên nếu bạn không phải là tác giả của ngôn ngữ này, vui lòng đặt câu trả lời của bạn lên wiki cộng đồng để các thành viên khác trong cộng đồng của chúng tôi có thể đóng góp trực tiếp vào điểm số. Cờ dòng lệnh không cần tuân theo bất kỳ hạn chế nào, tuy nhiên mọi chương trình nên được chạy với cùng một đối số dòng lệnh (tức là bạn nên chọn một và gắn với nó). Chúng không thêm vào số byte của bạn.

Những thách thức và hạn chế

Các hạn chế được thi hành theo mã hóa ASCII của các nhị phân của bạn bất kể trang mã bạn sử dụng là gì. Một số trong số này liên kết đến một câu hỏi hiện có trên trang web mà từ đó họ thừa hưởng các yêu cầu io của họ đối với các thách thức và hạn chế nguồn cho các hạn chế. Bạn có thể bỏ qua bất cứ điều gì "cấm các nội dung" hoặc ghi đè các thỏa thuận meta hiện có vào bất kỳ thách thức nào được liên kết.

Như một lời cảnh báo: đừng cố gắng cai trị luật sư; Tôi biết đó là một cuộc thi nhưng vì về cơ bản có 100 thử thách phụ khác nhau và tôi đơn giản là không thể đảm bảo rằng tất cả chúng sẽ hoàn toàn không có gì khó khăn. Chỉ cần cố gắng để vui chơi.

Thử thách

Hạn chế

Các tiêu chí còn lại có hàm băm sha512 là:

4de5eca33c6270798606cf1412820c4ce112d8b927ef02877f36795b2b15ffacca51ea598fa89b8d6bc9f4cde53810e0e7ade30e536e52e28f40a6a13841dfc5  -


1
Đến đây để downvote, sau đó đọc thông số kỹ thuật. +1
trichoplax

3
Điều gì sẽ xảy ra nếu tôi phát triển một ngôn ngữ trong đó chương trình trống sắp xếp danh sách các số nguyên, in thế giới xin chào, xác định xem dấu ngoặc đơn có được cân bằng hoặc kiểm tra tính nguyên thủy hay không, tùy thuộc vào nội dung đầu vào? Tôi đề nghị chỉ giữ những thử thách này làm ví dụ và để ghi điểm gửi riêng cho các thử thách khác, chưa được khám phá
Leo


1
@ComradeSparklePony Các cờ dòng lệnh cần giống nhau cho tất cả các chương trình.
Phù thủy lúa mì

Câu trả lời:


5

Chiều rộng

Trình thông dịch vẫn đang trong quá trình hoàn thành (Tôi vẫn còn một số khe lệnh chưa sử dụng). Các repo, với nhiều tài liệu hơn, có thể được tìm thấy ở đây .

Dennis đã thêm Width vào TIO chưa đầy một phút trước: Dùng thử trực tuyến!

Width là một ngôn ngữ dựa trên ngăn xếp bí truyền mà tôi đã phát triển gần đây dựa trên những ý tưởng mà lần đầu tiên tôi bỏ trong câu hỏi này . Nó hoàn toàn dựa trên mức độ rộng, nhiều hay ít, một chữ cái trong một phông chữ "thông thường". Các ký tự duy nhất làm bất cứ điều gì là chữ cái, chữ hoa và chữ thường. Tất cả các nhân vật khác được bỏ qua. Tôi chia các chữ cái thành 10 loại chiều rộng khác nhau, tạo thành 10 hành động khác nhau có thể có trong Chiều rộng:

0: i j l                     # do while counter > 0
1: f r t I                   # end
2: c k s v x y z J           # 0 in commands
3: a b d e g h n o p q u L   # separator (no-op)
4: F T Z                     # push base 10 number, using left side row titles (width numbers); terminated with original char
5: A B E K P S V X Y         # 1 in commands
6: w C D H N R U             # 2 in commands
7: G O Q                     # push string literal; sets of 2 width numbers equate to index in printable ASCII; terminated with original char
8: m M                       # if top of stack
9: W                         # else

2, 56cung cấp quyền truy cập vào các lệnh, hầu hết trong số đó tương tác với ngăn xếp. Thông tin thêm có thể được tìm thấy tại info.txttrang trong repo Github.

Đây là mã Python của trình thông dịch. Tôi vẫn còn một số lệnh để thêm và tôi đang xem xét cách làm việc với xử lý lỗi, nhưng nếu không thì nó sẽ hoàn thành. (Tôi cũng sẽ thêm một cờ vào một lúc nào đó để cho phép thử nghiệm với một cú pháp trừu tượng hơn, bởi vì nếu không thì ngôn ngữ này là một nỗi đau rất lớn để làm việc với)

import sys
import math
import numbers
import functools

try:
    file = sys.argv[1]
except IndexError:
    file = "source.wide"

with open(file) as f:
    source = f.read()

translation = ("ijl", "frtI", "cksvxyzJ", "abdeghnopquL", "FTZ", "ABEKPSVXY", "wCDHNRU", "GOQ", "mM", "W")
chars = "".join(sorted("".join(translation)))
strings = """ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n\t"""


def trans(letter):
    for each in translation:
        if letter in each:
            return translation.index(each)

COMMAND = "COMMAND"
COMMANDS = (2, 5, 6)
NUMBER = "NUMBER"
STRING = "STRING"
DO = "DO"
IF = "IF"
ELSE = "ELSE"
END = "END"
SEPARATOR = "SEPARATOR"


class Token:
    def __init__(self, val, type_):
        self.val = val
        self.type = type_


class Lexer:
    def __init__(self, src):
        self.src = src
        self.pos = 0
        self.char = self.src[self.pos]

    def read(self):
        if self.char is None:
            return None

        command = trans(self.char)

        if command == 0:
            self.advance()
            return Token(0, DO)
        elif command == 1:
            self.advance()
            return Token(1, END)
        elif command == 3:
            self.advance()
            return Token(3, SEPARATOR)
        elif command == 4:
            return self.read_num()
        elif command == 7:
            return self.read_str()
        elif command == 8:
            self.advance()
            return Token(8, IF)
        elif command == 9:
            self.advance()
            return Token(9, ELSE)
        else:
            return self.read_cmd()

    def advance(self):
        self.pos += 1

        try:
            self.char = self.src[self.pos]
        except IndexError:
            self.char = None

    def read_num(self):
        delim = self.char
        self.advance()

        res = ""
        while self.char is not None and self.char != delim:
            res += str(trans(self.char))
            self.advance()

        self.advance()

        return Token(int(res), NUMBER)

    def read_str(self):
        def read_char():
            res_ = str(trans(self.char))
            self.advance()
            res_ += str(trans(self.char))
            self.advance()
            try:
                return strings[int(res_)]
            except IndexError:
                return " "

        delim = self.char
        self.advance()

        res = ""
        while self.char is not None and self.char != delim:
            res += read_char()

        self.advance()

        return Token(res, STRING)

    def read_cmd(self):
        command = ""
        while self.char is not None and trans(self.char) in COMMANDS and len(command) <= 4:
            command += str(COMMANDS.index(trans(self.char)))
            self.advance()

        return Token(command, COMMAND)

source = "".join(filter(lambda c: c in chars, source))

stack = []
backburner = []
counter = 0


def set_counter(val):
    global counter
    counter = int(val)

    if counter < 0:
        counter = 0


def set_stack(val):
    global stack
    stack = val


def num_input():
    inp = input()
    try:
        stack.append(int(inp))
    except ValueError:
        try:
            stack.append(float(inp))
        except ValueError:
            pass


def flip_ends():
    if len(stack) > 1:
        stack[0], stack[-1] = stack[-1], stack[0]


def clear_stack():
    global stack
    stack = []


def reload_stack(is_top):
    global backburner, stack

    if is_top:
        stack.extend(backburner)
    else:
        stack = backburner + stack

    backburner = []


# https://stackoverflow.com/a/15285588/7605753
def is_prime(n):
    if n == 2 or n == 3:
        return True
    if n < 2 or n % 2 == 0:
        return False
    if n < 9:
        return True
    if n % 3 == 0:
        return False
    r = int(math.sqrt(n))
    _f = 5
    while _f <= r:
        if n % _f == 0:
            return False
        if n % (_f + 2) == 0:
            return False
        _f += 6
    return True


def error():
    raise Exception

commands = {
    "0": lambda: stack.append(stack[-1]),
    "1": lambda: stack.append(stack.pop(-2)),
    "2": lambda: stack.pop(),
    "00": lambda: set_counter(stack[-1]),
    "01": lambda: stack.append(len(stack)),
    "02": lambda: stack.append(input()),
    "10": num_input,
    "11": lambda: stack.append(str(stack.pop())),
    "12": lambda: stack.append(int(stack.pop())),
    "20": lambda: set_counter(counter + 1),
    "21": lambda: set_counter(counter - 1),
    "22": lambda: print(stack.pop()),
    "000": lambda: stack.append(float(stack.pop())),
    "001": lambda: stack.append(-stack.pop()),
    "002": lambda: stack.append(not stack.pop()),
    "010": lambda: stack.append(stack.pop(-2) + stack.pop()),
    "011": lambda: stack.append(stack.pop(-2) - stack.pop()),
    "012": lambda: stack.append(stack.pop(-2) / stack.pop()),
    "020": lambda: stack.append(stack.pop(-2) // stack.pop()),
    "021": lambda: stack.append(stack.pop(-2) * stack.pop()),
    "022": lambda: stack.append(stack.pop(-2) % stack.pop()),
    "100": lambda: stack.append(math.factorial(stack.pop())),
    "101": lambda: stack.append(str(stack.pop(-2)) + str(stack.pop())),
    "102": lambda: stack.append(math.pow(stack.pop(-2), stack.pop())),
    "110": lambda: stack.append(math.sqrt(stack.pop())),
    "111": lambda: stack.append(math.log(stack.pop(-2), stack.pop())),
    "112": lambda: stack.append(~stack.pop()),
    "120": lambda: stack.append(stack.pop(-2) | stack.pop()),
    "121": lambda: stack.append(stack.pop(-2) & stack.pop()),
    "122": lambda: stack.append(stack.pop(-2) << stack.pop()),
    "200": lambda: stack.append(stack.pop(-2) >> stack.pop()),
    "201": lambda: stack.append(stack.pop(-2)[stack.pop()]),
    "202": lambda: stack.append(str(stack.pop(-2)) * stack.pop()),
    "210": lambda: stack.append(counter),
    "211": lambda: set_counter(stack.pop()),
    "212": lambda: stack.extend(list(str(stack.pop()))),
    "220": flip_ends,
    "221": lambda: stack.append(len(stack[-1])),
    "222": lambda: print(stack[-1]),
    "0000": lambda: stack.reverse(),
    "0001": lambda: stack.sort(),
    "0002": lambda: stack.append(stack[counter]),
    "0010": lambda: stack.append(stack[stack.pop()]),
    "0011": 0,
    "0012": 0,
    "0020": lambda: stack.append(sum(n for n in stack if isinstance(n, numbers.Number))),
    "0021": lambda: stack.append(functools.reduce(lambda x, y: x*y, [n for n in stack if isinstance(n, numbers.Number)], 1)),
    "0022": 0,
    "0100": lambda: (backburner.extend(stack), clear_stack()),
    "0101": lambda: reload_stack(True),
    "0102": lambda: reload_stack(False),
    "0110": lambda: backburner.append(stack.pop()),
    "0111": lambda: backburner.append(list(stack.pop())),
    "0112": lambda: stack.pop().split(stack.pop()),
    "0120": lambda: stack.append(backburner[-1]),
    "0121": lambda: (lambda depth=stack.pop(): (set_stack(stack[-depth:]), backburner.append(stack[:depth])))(),
    "0122": lambda: (lambda depth=stack.pop(): (set_stack(stack[:-depth]), backburner.append(stack[depth:])))(),
    "0200": lambda: set_stack([stack.pop().join(stack)]),
    "0201": lambda: set_stack(["".join(stack)]),
    "0202": lambda: (lambda depth=stack.pop(-2): set_stack(stack[-depth:] + [stack.pop().join(stack[:depth])]))(),
    "0210": lambda: (lambda depth=stack.pop(): set_stack(stack[-depth:] + ["".join(stack[:depth])]))(),
    "0211": 0,
    "0212": 0,
    "0220": lambda: stack.append(stack.pop().split(stack.pop())),
    "0221": lambda: stack.append(stack.pop().split(", ")),
    "0222": 0,
    "1000": lambda: stack.append(is_prime(stack[-1])),
    "1001": lambda: stack.append((lambda s=stack.pop(): s == s[::-1])()),
    "1002": lambda: stack.append(1 / stack.pop()),
    "1010": lambda: stack.append(stack.pop() - 1),
    "1011": lambda: stack.append(stack.pop() + 1),
    "1012": lambda: stack.append(stack.pop() * 2),
    "1020": lambda: stack.append(stack.pop() / 2),
    "1021": lambda: stack.append(stack.pop() ** 2),
    "1022": lambda: float("." + str(stack.pop())),
    "1100": lambda: stack.append(stack.pop() == stack.pop()),
    "1101": lambda: stack.append(stack.pop() != stack.pop()),
    "1102": lambda: stack.append(stack.pop() > stack.pop()),
    "1110": lambda: stack.append(stack.pop() < stack.pop()),
    "1111": lambda: stack.append(stack.pop() >= stack.pop()),
    "1112": lambda: stack.append(stack.pop() <= stack.pop()),
    "1120": lambda: stack.append(stack.pop() in stack),
    "1121": lambda: stack.append(stack.pop() in backburner),
    "1122": lambda: stack.append(stack.pop() == counter),
    "1200": lambda: stack.append(stack.pop() in stack.pop()),
    "1201": lambda: stack.append(stack.pop(-2).find(stack.pop())),
    "1202": 0,
    "1210": 0,
    "1211": 0,
    "1212": lambda: stack.append(stack.pop().lower()),
    "1220": lambda: stack.append(stack.pop().upper()),
    "1221": lambda: stack.append(ord(stack.pop())),
    "1222": lambda: stack.append(chr(stack.pop())),
    "2000": lambda: stack.append(math.floor(stack.pop())),
    "2001": lambda: stack.append(math.ceil(stack.pop())),
    "2002": lambda: stack.append(round(stack.pop())),
    "2010": lambda: stack.append(abs(stack.pop())),
    "2011": 0,
    "2012": 0,
    "2020": lambda: stack.append(len(stack.pop())),
    "2021": 0,
    "2022": 0,
    "2100": lambda: stack.append(min(stack)),
    "2101": lambda: stack.append(max(stack)),
    "2102": lambda: stack.append(stack.count(stack.pop())),
    "2110": lambda: stack.append(sum(stack) / len(stack)),
    "2111": 0,
    "2112": 0,
    "2120": 0,
    "2121": 0,
    "2122": 0,
    "2200": lambda: stack.append(stack.pop(-3).replace(stack.pop(-2), stack.pop())),
    "2201": lambda: stack.append(stack.pop(-3).replace(stack.pop(-2), stack.pop(), 1)),
    "2202": lambda: stack.append(stack.pop(-2).replace(stack.pop(), "")),
    "2210": lambda: stack.append(stack.pop(-2).replace(stack.pop(), "", 1)),
    "2211": 0,
    "2212": lambda: stack.append(eval(stack.pop())),
    "2220": lambda: stack.append(eval(input())),
    "2221": lambda: print(stack[-1]),
    "2222": lambda: error()
}


def run_cmd(name):
    global stack, counter, backburner

    state = {
        "stack": list(stack),
        "counter": counter,
        "backburner": list(backburner)
    }

    # TODO: unknown command

    try:
        commands[name]()
    except IndexError:
        stack = state["stack"]
        counter = state["counter"]
        backburner = state["backburner"]


class AST:
    pass


class Main(AST):
    def __init__(self):
        self.nodes = []


class Do(AST):
    def __init__(self, node):
        self.node = node


class If(AST):
    def __init__(self, first, second):
        self.first = first
        self.second = second


class Literal(AST):
    def __init__(self, val):
        self.val = val


class Command(AST):
    def __init__(self, val):
        self.val = val


class Parser:
    def __init__(self, lexer):
        self.lexer = lexer
        self.token = None

    def parse(self):
        pgm = Main()
        self.token = self.lexer.read()

        while self.token is not None and self.token.type != END and self.token.type != ELSE:
            if self.token.type == DO:
                pgm.nodes.append(Do(self.parse()))

            elif self.token.type == NUMBER or self.token.type == STRING:
                pgm.nodes.append(Literal(self.token.val))

            elif self.token.type == IF:
                first = self.parse()

                if self.token.type == ELSE:
                    second = self.parse()
                else:
                    second = None

                pgm.nodes.append(If(first, second))

            elif self.token.type == COMMAND:
                pgm.nodes.append(Command(self.token.val))

            self.token = self.lexer.read()

        return pgm


class Interpreter:
    def __init__(self, tree):
        self.tree = tree

    def visit(self, node):
        method_name = "visit_" + type(node).__name__
        visitor = getattr(self, method_name.lower())
        return visitor(node)

    def interpret(self):
        self.visit(self.tree)

    def visit_main(self, node):
        for each in node.nodes:
            self.visit(each)

    def visit_do(self, node):
        while counter:
            self.visit(node)

    def visit_if(self, node):
        if stack[-1]:
            self.visit(node.first)
        elif node.second:
            self.visit(node.second)

    def visit_literal(self, node):
        stack.append(node.val)

    def visit_command(self, node):
        run_cmd(node.val)


if source == "":
    with open("info.txt") as f:
        info = f.read()

    print(info)
else:
    main = Parser(Lexer(source)).parse()

    interpreter = Interpreter(main)
    interpreter.interpret()

    try:
        sys.exit(stack[-1])
    except IndexError:
        pass
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.