不受限制的语言


28

我在此站点上最喜欢的挑战之一是挑战。这些挑战给计算机带来了难以处理的限制,潜在答案的来源必须通过。我非常喜欢这些挑战,一段时间以来,我一直在研究一种旨在赢得这些挑战的高尔夫语言。现在,我想向您提出挑战。您的任务是设计一种语言来解决各种受限的源任务。您将需要设计和实现一种语言,到那时,更改和新添加的内容将不具竞争性,并且所有提交的内容将在挑战的严峻挑战中齐头并进。

计分

在发布挑战之前,我将提供一个要解决的简单挑战列表和一个要遵循的源限制列表。对于挑战和来源限制的每次匹配,您的语言都可以赚取0到2分。(将有10个挑战和10个限制导致总共100种组合)A语言得分

  • 如果可以在150字节以内的限制下完成任务,则为1分
  • 如果该解决方案是所有语言竞赛中最短的解决方案,则为2分(如果出现并列,则两种语言均获得2分)
  • 如果他们不能在少于150个字节的限制下创建完成该任务的程序,则为0分。

您的分数将是每次可能的比赛中赢得的所有积分的总和。目标是获得最高分。其他人可能会帮助您针对每种挑战寻找解决方案并提高得分。

发布时,我将显示每个列表的4个项目,第二个答案一周后,我将显示另外8个项目。在第一周之前揭示两部分内容的任何匹配项中,您只会获得1分(最短提交数不计)。这样一来,您就可以了解语言在处理过程中的堆叠程度,但是您不能仅仅为了应对所有挑战和限制而设计语言。

我将在问题中包含预期类别的哈希值,以便您可以确定在本周内不会为了有利于任何一方而更改它们。另外,在本周结束之前,我不会告诉任何人隐藏的参数,也不要自己参加挑战。

预先存在的语言

这项挑战对所有先前存在的语言都是开放的,但是,如果您不是该语言的作者,请将您的答案作为社区Wiki,以便我们社区的其他成员可以直接为得分做出贡献。命令行标志不需要遵守任何限制,但是每个程序都应使用相同的命令行参数运行(即,应选择一个并坚持使用)。这些不会增加您的字节数。

挑战与限制

不管您使用的是什么代码页,对二进制文件的ASCII编码都实施了限制。其中一些链接到网站上的现有问题,他们从中继承挑战的io要求和限制的来源限制。您可以忽略任何“禁止内置”或在任何相关挑战上覆盖现有的元共识。

提醒一下:不要试图统治律师;我知道这是一场比赛,但是因为本质上有100种不同的子挑战,所以我无法保证所有挑战都是完全没有问题的。只是尝试去玩。

挑战性

限制条件

其余条件的sha512哈希为:

4de5eca33c6270798606cf1412820c4ce112d8b927ef02877f36795b2b15ffacca51ea598fa89b8d6bc9f4cde53810e0e7ade30e536e52e28f40a6a13841dfc5  -


1
来到这里进行投票,然后阅读规格。+1
trichoplax

3
如果我开发了一种语言,其中空程序对整数列表进行排序,打印问候世界,根据输入的内容确定括号是否平衡或测试素数,该怎么办?我建议仅将这些挑战作为示例,并只对未发现的其他挑战进行评分
-Leo


1
@ComradeSparklePony所有程序的命令行标志都必须相同。
小麦巫师

Answers:


5

宽度

解释器仍在进行中(我还有几个未使用的命令槽)。可在此处找到带有更多文档的仓库。

不到一分钟前,Dennis将Width添加到TIO:在线试用!

宽度是我根据我在这个问题中首次提出的想法最近开发的一种深奥的基于堆栈的语言。它完全基于一个字母或多或少的“常规”字体的宽度。唯一可以执行任何操作的字符是字母,大写和小写。所有其他字符将被忽略。我将字母分为10种不同的宽度类别,这些类别构成Width中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

256提供对命令的访问,其中大多数命令与堆栈交互。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 = []


# 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.