Nieograniczone języki

28

Jednym z moich ulubionych rodzajów wyzwań na tej stronie są wyzwania o . Wyzwania te nakładają na komputerowe ograniczenie, które muszą przejść źródła potencjalnych odpowiedzi. Tak bardzo lubię te wyzwania, od jakiegoś czasu pracuję nad językiem golfa, który ma na celu wygrać w tych wyzwaniach. Teraz chcę przekazać ci wyzwanie. Twoim zadaniem jest zaprojektowanie języka w celu rozwiązania szeregu ograniczonych zadań źródłowych. Będziesz miał czas zaprojektować i wdrożyć język, w którym to momencie zmiany i nowe dodatki będą niekonkurujące, a wszystkie zgłoszenia zmierzą się w pojedynku z wyzwaniami o .

Punktacja

Przed opublikowaniem wyzwania przedstawię listę prostych wyzwań do rozwiązania oraz listę ograniczeń źródłowych, których należy przestrzegać. Za każde dopasowanie ograniczeń wyzwania i ograniczeń źródłowych Twój język może zarobić od 0 do 2 punktów. (będzie 10 wyzwań i 10 ograniczeń prowadzących do 100 wszystkich kombinacji) A wyniki językowe

  • 1 punkt, jeśli może wykonać zadanie z ograniczeniem poniżej 150 bajtów
  • 2 punkty, jeśli rozwiązanie jest najkrótszym rozwiązaniem dowolnego konkurencyjnego języka (oba języki zdobędą 2 punkty w przypadku remisu)
  • 0 punktów, jeśli nie są w stanie utworzyć programu, który wykonuje zadanie w ramach ograniczenia w mniej niż 150 bajtach.

Twój wynik będzie sumą wszystkich punktów zdobytych w każdym możliwym pojedynku. Celem jest uzyskanie jak najwyższego wyniku. Inne osoby mogą pomóc Ci znaleźć rozwiązania dla każdego wyzwania i poprawić Twój wynik.

Ujawnię 4 pozycje z każdej listy w momencie publikacji i dodatkowe 8 w tydzień po drugiej odpowiedzi. Będziesz mógł zdobyć tylko 1 punkt (najkrótsze zgłoszenie się nie liczy) w żadnym meczu, w którym obie części zostały ujawnione przed pierwszym tygodniem. W ten sposób możesz zorientować się, jak dobrze Twój język kumuluje się podczas pracy nad nim, ale nie możesz zaprojektować swojego języka po prostu, aby sprostać wszystkim wyzwaniom i ograniczeniom.

Do pytania dołączę skrót zamierzonych kategorii, dzięki czemu będziesz mieć pewność, że nie zmienię ich w ciągu tygodnia, aby zyskać przewagę nad jakąkolwiek stroną. Ponadto nie zdradzę nikomu ukrytych parametrów, dopóki tydzień się nie skończy, ani nie wezmę udziału w wyzwaniu.

Wcześniej istniejące języki

To wyzwanie jest otwarte dla wszystkich wcześniej istniejących języków, ale jeśli nie jesteś autorem tego języka, prosimy o zamieszczenie swojej odpowiedzi w wiki społeczności, aby inni członkowie naszej społeczności mogli bezpośrednio przyczynić się do wyniku. Flagi wiersza poleceń nie muszą podlegać żadnym ograniczeniom, jednak każdy program powinien być uruchamiany z tymi samymi argumentami wiersza poleceń (tzn. Powinieneś wybrać jeden i trzymać się go). Nie zwiększają one liczby bajtów.

Wyzwania i ograniczenia

Ograniczenia są egzekwowane w kodowaniu plików binarnych ASCII niezależnie od używanej strony kodowej. Niektóre z nich prowadzą do istniejącego pytania w witrynie, z którego dziedziczą wymagania dotyczące wymagań i ograniczenia źródłowe ograniczeń. Możesz zignorować wszystko, co „blokuje wbudowane” lub zastępuje istniejące meta konsensu w sprawie dowolnego z powiązanych wyzwań.

Jako ostrzeżenie: nie próbuj rządzić prawnikiem; Wiem, że jest to konkurencja, ale ponieważ istnieje w zasadzie 100 różnych wyzwań podzwrotnych i po prostu nie mogę zagwarantować, że wszystkie będą całkowicie bezproblemowe. Po prostu spróbuj się dobrze bawić.

Wyzwania

Ograniczenia

Pozostałe kryteria mają skrót sha512:

4de5eca33c6270798606cf1412820c4ce112d8b927ef02877f36795b2b15ffacca51ea598fa89b8d6bc9f4cde53810e0e7ade30e536e52e28f40a6a13841dfc5  -
Kreator pszenicy
źródło
Daj nam kontynuować tę dyskusję w czacie .
Kreator pszenicy
1
Przyszedł tutaj, aby głosować, a następnie przeczytać specyfikację. +1
trichopaks
3
Co się stanie, jeśli opracuję język, w którym pusty program sortuje listę liczb całkowitych, drukuje hello world, określa, czy nawiasy są zrównoważone, czy testuje pierwszeństwo, w zależności od tego, co jest na wejściu? Proponuję zachować te wyzwania tylko jako przykłady i oceniać zgłoszenia wyłącznie w przypadku innych nieodkrytych wyzwań
Leo
1
Daj nam kontynuować tę dyskusję w czacie .
Wheat Wizard
1
@ComradeSparklePony Flagi wiersza poleceń muszą być takie same dla wszystkich programów.
Wheat Wizard

Odpowiedzi:

5

Szerokość

Tłumacz jest wciąż w toku (wciąż mam kilka nieużywanych miejsc poleceń). Repozytorium z większą dokumentacją można znaleźć tutaj .

Dennis dodał do TIO Szerokość mniej niż minutę temu: Wypróbuj online!

Szerokość to ezoteryczny język oparty na stosach, który opracowałem niedawno na podstawie pomysłów, które po raz pierwszy rzuciłem w to pytanie . Opiera się on całkowicie na tym, jak szeroka, mniej więcej, litera ma „zwykłą” czcionkę. Jedynymi znakami, które cokolwiek robią, są litery, wielkie i małe litery. Wszystkie pozostałe znaki są ignorowane. Dzielę litery na 10 różnych kategorii szerokości, które tworzą 10 różnych akcji możliwych w Width:

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, 5i 6zapewniają dostęp do poleceń, z których większość wchodzi w interakcję ze stosem. Więcej informacji można znaleźć na info.txtstronie w repozytorium Github.

To jest kod Pythona interpretera. Wciąż mam kilka poleceń do dodania i zastanawiam się, jak pracować z obsługą błędów, ale w przeciwnym razie powinno być kompletne. (W pewnym momencie dodam także flagę, aby umożliwić testowanie z bardziej abstrakcyjną składnią, ponieważ w przeciwnym razie ten język jest ogromnym problemem do pracy)

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
Stephen
źródło