Langues illimitées

28

Un de mes types de défis préférés sur ce site sont défis à . Ces défis imposent une restriction exploitable par ordinateur que les sources de réponses potentielles doivent passer. J'aime tellement ces défis que je travaille sur un langage de golf conçu pour gagner à ces défis depuis un certain temps maintenant. Maintenant, je veux vous lancer le défi. Votre tâche consiste à concevoir un langage pour résoudre une variété de tâches source restreintes. Vous aurez le temps de concevoir et de mettre en œuvre un langage, auquel cas les changements et les nouveaux ajouts seront non concurrents et toutes les soumissions se feront face à face dans un gantelet de défis de .

Notation

Avant de publier le défi, je proposerai une liste de défis simples à résoudre et une liste des restrictions de source à suivre. Pour chaque correspondance de restrictions de défi et de source, votre langue peut gagner entre 0 et 2 points. (il y aura 10 défis et 10 restrictions conduisant à 100 combinaisons totales)

  • 1 point s'il peut terminer la tâche avec la restriction en moins de 150 octets
  • 2 points si la solution est la solution la plus courte de n'importe quelle langue en compétition (les deux langues marqueront 2 points en cas d'égalité)
  • 0 point s'ils ne parviennent pas à créer un programme qui termine la tâche sous la restriction en moins de 150 octets.

Votre score sera la somme de tous les points gagnés dans chaque match possible. Le but est d'obtenir le meilleur score. D'autres personnes peuvent vous aider à trouver vos solutions à chaque défi et à améliorer votre score.

Je vais révéler 4 éléments de chaque liste au moment de la publication et 8 autres une semaine après la deuxième réponse. Vous ne serez autorisé à marquer 1 point (la soumission la plus courte ne compte pas) dans toute correspondance qui a révélé les deux parties avant la première semaine. De cette façon, vous pouvez avoir une idée de la façon dont votre langue se cumule pendant que vous travaillez dessus, mais vous ne pouvez pas concevoir votre langue simplement pour intégrer tous les défis et restrictions.

Je vais inclure un hachage des catégories prévues avec la question afin que vous puissiez être sûr que je ne les change pas au cours de la semaine au profit de toute fête. De plus, je ne dirai à personne les paramètres cachés avant la fin de la semaine et je ne participerai pas moi-même au défi.

Langues préexistantes

Ce défi est ouvert à toutes les langues préexistantes mais si vous n'êtes pas l'auteur de la langue, veuillez faire votre réponse sur un wiki communautaire afin que les autres membres de notre communauté puissent contribuer directement au score. Les drapeaux de ligne de commande ne doivent obéir à aucune restriction, mais chaque programme doit être exécuté avec les mêmes arguments de ligne de commande (c'est-à-dire que vous devez en choisir un et le respecter). Ceux-ci ne s'ajoutent pas à votre nombre d'octets.

Défis et restrictions

Des restrictions sont appliquées sur le codage ASCII de vos fichiers binaires, quelle que soit la page de codes que vous utilisez. Certains d'entre eux renvoient à une question existante sur le site dont ils héritent leurs exigences io pour les défis et les restrictions de source pour les restrictions. Vous pouvez ignorer tout ce qui peut "interdire les incorporations" ou remplacer les méta-consensus existants sur l'un des défis liés.

En guise d'avertissement: n'essayez pas de juger un avocat; Je sais que c'est une compétition mais parce qu'il y a essentiellement 100 défis de sous-défis différents et je ne peux tout simplement pas garantir que tous ne poseront aucun problème. Essayez juste de vous amuser.

Défis

Restrictions

Les autres critères ont un hachage sha512 de:

4de5eca33c6270798606cf1412820c4ce112d8b927ef02877f36795b2b15ffacca51ea598fa89b8d6bc9f4cde53810e0e7ade30e536e52e28f40a6a13841dfc5  -
Assistant de blé
la source
Continuons cette discussion dans le chat .
Wheat Wizard
1
Je suis venu ici pour voter, puis lisez les spécifications. +1
trichoplax
3
Que se passe-t-il si je développe un langage où le programme vide trie une liste d'entiers, imprime bonjour le monde, détermine si les parenthèses sont équilibrées ou teste la primalité, selon ce qui est dans l'entrée? Je suggère de ne garder ces défis qu'à titre d'exemples et de noter les soumissions exclusivement sur d'autres défis non découverts
Leo
1
Continuons cette discussion dans le chat .
Wheat Wizard
1
@ComradeSparklePony Les drapeaux de ligne de commande doivent être les mêmes pour tous les programmes.
Wheat Wizard

Réponses:

5

Largeur

L'interpréteur est toujours en cours de réalisation (j'ai encore plusieurs emplacements de commande inutilisés). Le dépôt, avec plus de documentation, peut être trouvé ici .

Dennis a ajouté Width à TIO il y a moins d'une minute: Essayez-le en ligne!

La largeur est un langage ésotérique basé sur la pile que j'ai développé récemment sur la base des idées que j'ai jetées pour la première fois dans cette question . Il est entièrement basé sur la largeur, plus ou moins, d'une lettre dans une police "régulière". Les seuls caractères qui font quoi que ce soit sont les lettres majuscules et minuscules. Tous les autres personnages sont ignorés. J'ai divisé les lettres en 10 catégories de largeur différentes, qui forment les 10 actions différentes possibles dans Largeur:

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, 5et 6permettent d'accéder aux commandes, dont la plupart interagissent avec la pile. Plus d'informations peuvent être trouvées sur la info.txtpage du dépôt Github.

Il s'agit du code Python de l'interpréteur. J'ai encore plusieurs commandes à ajouter, et je réfléchis à la façon de travailler avec la gestion des erreurs, mais sinon, elle devrait être complète. (Je vais également ajouter un drapeau à un moment donné pour permettre des tests avec une syntaxe plus abstraite, car sinon ce langage est une douleur géante à travailler)

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
Stephen
la source