Неограниченные Языки

28

Один из моих любимых типов задач на этом сайте - это проблемы с . Эти проблемы налагают компьютерное ограничение, которое должны пройти источники потенциальных ответов. Мне так нравятся эти испытания, что я работаю над языком игры в гольф, предназначенным для победы в этих соревнованиях в течение некоторого времени. Теперь я хочу бросить вам вызов. Ваша задача - разработать язык для решения множества ограниченных исходных задач. У вас будет время разработать и внедрить язык, после чего изменения и новые дополнения станут неконкурентоспособными, и все заявки будут встречаться лицом к лицу в борьбе с проблемами с .

счет

Перед публикацией задачи я составлю список простых задач, которые нужно решить, и список ограничений источника, которым необходимо следовать. За каждое совпадение с заданием и исходными ограничениями ваш язык может заработать от 0 до 2 баллов. (будет 10 испытаний и 10 ограничений, что приведет к 100 комбинациям) Оценка по языку

  • 1 балл, если он может выполнить задачу с ограничением до 150 байт
  • 2 балла, если решение является самым коротким решением из всех конкурирующих языков (оба языка получат 2 балла в случае ничьей)
  • 0 баллов, если они не могут создать программу, которая выполняет задачу с ограничением менее чем в 150 байтов.

Ваш счет будет суммой всех очков, заработанных в каждом возможном матче. Цель состоит в том, чтобы получить самый высокий балл. Другие люди могут помочь вам найти решение для каждой задачи и улучшить ваш счет.

Я покажу 4 пункта каждого списка во время публикации и еще 8 пунктов через неделю после второго ответа. Вам будет разрешено набрать только 1 балл (самое короткое представление не учитывается) в любом совпадении, в котором обе части были обнаружены до первой недели. Таким образом, вы можете получить представление о том, насколько хорошо ваш язык складывается во время работы над ним, но вы не можете создать свой язык просто для того, чтобы учесть все проблемы и ограничения.

Я включу в вопрос хэш предполагаемых категорий, чтобы вы могли быть уверены, что я не буду менять их в течение недели, чтобы дать преимущество любой стороне. Кроме того, я не буду никому рассказывать о скрытых параметрах, пока не закончится неделя, и не буду участвовать в соревнованиях самостоятельно.

Существующие языки

Эта задача открыта для всех ранее существовавших языков, однако, если вы не являетесь автором языка, сделайте ответ в вики сообщества, чтобы другие участники нашего сообщества могли внести непосредственный вклад в оценку. Флаги командной строки не должны подчиняться каким-либо ограничениям, однако каждая программа должна запускаться с одинаковыми аргументами командной строки (т.е. вы должны выбрать один и придерживаться его). Они не добавляют к вашему количеству байтов.

Проблемы и ограничения

Ограничения применяются к кодировке ASCII ваших двоичных файлов независимо от используемой вами кодовой страницы. Некоторые из них ссылаются на существующий на сайте вопрос, от которого они наследуют свои требования к задачам и ограничения источника. Вы можете игнорировать все, что «запрещает встроенные функции» или игнорирует существующие мета-консенсусы по любым из связанных задач.

Как предостережение: не пытайтесь править адвокатом; Я знаю, что это соревнование, но потому что есть по существу 100 различных проблем, и я просто не могу гарантировать, что все они будут полностью беспроблемными. Просто попробуйте повеселиться.

проблемы

ограничения

Остальные критерии имеют хэш sha512:

4de5eca33c6270798606cf1412820c4ce112d8b927ef02877f36795b2b15ffacca51ea598fa89b8d6bc9f4cde53810e0e7ade30e536e52e28f40a6a13841dfc5  -
Мастер пшеницы
источник
1
Пришел сюда, чтобы понизить голосование, затем прочитать спецификацию. +1
трихоплакс
3
Что если я разработаю язык, в котором пустая программа сортирует список целых чисел, печатает hello world, определяет, сбалансированы ли скобки, или проверяет первичность, в зависимости от того, что находится во входных данных? Я предлагаю оставить эти проблемы только в качестве примеров и
Лев,
1
Давайте продолжим эту дискуссию в чате .
Пшеничный волшебник
1
@ComradeSparklePony Флаги командной строки должны быть одинаковыми для всех программ.
Пшеничный волшебник

Ответы:

5

ширина

Переводчик все еще находится в стадии разработки (у меня все еще есть несколько неиспользуемых слотов для команд). Репо с дополнительной документацией можно найти здесь .

Деннис добавил ширину в TIO менее минуты назад: попробуйте онлайн!

Width - это эзотерический язык, основанный на стеке, который я недавно разработал на основе идей, которые я впервые бросил в этом вопросе . Он полностью основан на том, насколько широко, более или менее, буква написана «обычным» шрифтом. Единственные символы, которые делают что-либо, это буквы, прописные и строчные. Все остальные символы игнорируются. Я разбил буквы на 10 категорий ширины, которые образуют 10 различных действий, возможных в ширине:

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, 5И 6обеспечивает доступ к командам, большинство из которых взаимодействуют со стеком. Более подробную информацию можно найти на info.txtстранице репозитория Github.

Это код Python интерпретатора. У меня еще есть несколько команд для добавления, и я думаю, как работать с обработкой ошибок, но в остальном это должно быть завершено. (Я также собираюсь добавить флаг в какой-то момент, чтобы позволить тестирование с более абстрактным синтаксисом, потому что в противном случае этот язык - гигантская боль для работы)

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 = []


# /programming//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
Стивен
источник