Sınırsız Dil


28

Bu sitede en sevdiğim zorluklardan biri zorluklardır. Bu zorluklar, bilgisayara olası cevapların kaynaklarının geçmesi gerektiği konusunda izlenebilir bir kısıtlama getirmektedir. Bu zorlukları o kadar seviyorum ki, bir süredir bu zorlukları kazanmak için tasarlanmış bir golf dili üzerinde çalışıyorum. Şimdi sana meydan okumak istiyorum. Göreviniz, çeşitli sınırlı kaynak görevlerini çözmek için bir dil tasarlamaktır. Bir dil tasarlama ve uygulama zamanınız olacak, bu noktada değişiklikler ve yeni eklemeler rekabet etmeyecek ve tüm başvurular bir el sıkıntısı içinde baş başa gidecek zorlukların .

puanlama

Mücadelenin yayınlanmasından önce çözülmesi gereken basit zorlukların bir listesini ve izlenecek kaynak kısıtlamalarının bir listesini çıkartacağım. Her meydan okuma ve kaynak kısıtlaması eşleştirmesi için diliniz 0 ile 2 puan arasında kazanabilir. (100 toplam kombinasyona yol açan 10 zorluk ve 10 kısıtlama olacak)

  • Kısıtlama ile 150 baytın altındaki görevi tamamlayabiliyorsa 1 puan
  • Eğer çözüm, yarışan herhangi bir dilin en kısa çözümü ise, 2 puan (her iki dilde beraberlik durumunda 2 puan alacaktır)
  • Kısıtlama altında görevi 150 bayttan daha az sürede tamamlayan bir program oluşturamazlarsa 0 puan.

Puanınız, olası her maçta kazanılan tüm puanların toplamı olacaktır. Amaç en yüksek puanı almaktır. Diğer insanlar, her bir zorluğa yönelik çözümlerinizi geliştirmenize ve puanınızı yükseltmenize yardımcı olabilir.

Gönderim sırasında her listenin 4 maddesini ve ikinci cevaptan bir hafta sonra 8 eki daha göstereceğim. İlk haftadan önce her iki kısmı da açıklanmış olan herhangi bir eşleşmede yalnızca 1 puan (en kısa kayıt sayılmaz) puanlanmasına izin verilir. Bu şekilde üzerinde çalışırken dilinizin ne kadar iyi biriktiği hakkında bir fikir edinebilirsiniz, ancak dili tüm zorluklara ve kısıtlamalara dayanacak şekilde tasarlayamazsınız.

Herhangi bir tarafa avantaj sağlamak için hafta boyunca onları değiştirmeyeceğimden emin olabilirsiniz. Ek olarak, haftanın sonuna kadar kimseye saklı parametreler söylemeyeceğim ya da kendimde rekabet edemeyeceğim.

Önceden var olan diller

Bu zorluk önceden mevcut tüm dillere açıktır, ancak dilin yazarı değilseniz, lütfen cevabınızı bir topluluk wiki yapın, böylece topluluğumuzun diğer üyeleri doğrudan puanlamaya katkıda bulunabilir. Komut satırı bayraklarının herhangi bir kısıtlamaya uyması gerekmez, ancak her program aynı komut satırı argümanları ile çalıştırılmalıdır (yani bir tanesini seçip buna bağlı kalmalısınız). Bunlar bayt sayınıza eklenmez.

Zorluklar ve kısıtlamalar

Sınırlamalar, kullandığınız kod sayfasından bağımsız olarak ikili dosyalarınızın ASCII kodlamasına uygulanır. Bunlardan bazıları, sitede zorluklar için io gereksinimlerini ve kısıtlamaların kaynak kısıtlamalarını devraldıkları sitedeki mevcut bir soruyla bağlantılıdır. Bağlantılı zorluklardan herhangi birini "yerleşikleri yasaklayan" veya mevcut meta fikir birliğini geçersiz kılan herhangi bir şeyi görmezden gelebilirsiniz.

Bir uyarı kelimesi olarak: avukata hükmetmeye çalışmayın; Bunun bir rekabet olduğunu biliyorum, çünkü esasen 100 farklı alt zorluklar mücadelesi var ve hepsinin tamamen problemsiz olacağını garanti edemiyorum. Sadece eğlenmeye çalış.

Zorluklar

Kısıtlamalar

Geriye kalan kriterler sha512 karma değerine sahiptir:

4de5eca33c6270798606cf1412820c4ce112d8b927ef02877f36795b2b15ffacca51ea598fa89b8d6bc9f4cde53810e0e7ade30e536e52e28f40a6a13841dfc5  -


1
Oy vermek için buraya geldim, sonra şartnameyi oku. +1
trichoplax

3
Boş programın bir tamsayı listesi sıraladığı, merhaba dünyasını bastığı, parantezlerin dengeli olup olmadığını belirlediği ya da girdide ne olduğuna bağlı olarak birincilliği test ettiği bir dil geliştirirsem ne olur? Bu zorlukları sadece örnek olarak saklamayı ve sadece diğer keşfedilmemiş zorlukları göz
Leo


1
@ComradeSparklePony Komut satırı bayrakları tüm programlar için aynı olmalıdır.
Buğday Sihirbazı,

Yanıtlar:


5

Genişlik

Tercüman halen devam etmekte olan bir çalışma (hala kullanılmayan birkaç komut alanım var). Daha fazla dokümantasyon içeren repo burada bulunabilir . .

Dennis bir dakikadan daha kısa bir süre önce TIO'ya Genişlik ekledi: Çevrimiçi Deneyin!

Genişlik, bu soruya ilk olarak attığım fikirlere dayanarak son zamanlarda geliştirdiğim ezoterik bir yığına dayalı dildir . Tamamen, bir mektubun "normal" bir yazı tipinde ne kadar geniş, az ya da çok olmasına dayanır. Her şeyi yapan tek karakterler harfler, büyük ve küçük harflerdir. Diğer tüm karakterler göz ardı edilir. Harfleri Genişlikte mümkün olan 10 farklı eylemi oluşturan 10 farklı genişlik kategorisine ayırırım:

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, 5ve 6çoğu yığınla etkileşime giren komutlara erişim sağlar. Daha fazla bilgi bulabilirsinizinfo.txt Github deposundaki sayfada bulabilirsiniz.

Bu, tercümanın Python kodudur. Hala ekleyecek birkaç komutum var ve hata işlemeyle nasıl çalışılacağını düşünüyorum, ancak aksi halde tamamlanması gerekiyor. (Aynı zamanda daha soyut bir sözdizimi ile test edilmesine izin vermek için bir noktaya bir bayrak ekleyeceğim, çünkü aksi halde bu dil çalışmak çok büyük bir acıdır)

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.