Écrire un langage de programmation de complétude inconnue

91

Déterminer si une langue est Turing Complete est très important lors de la conception d'une langue. C'est également une tâche assez difficile pour beaucoup de langages de programmation ésotériques, mais passons à la vitesse supérieure. Faisons quelques langages de programmation qui sont si difficiles à prouver Turing Complete que même les meilleurs mathématiciens du monde ne parviendront pas à les prouver de toute façon. Votre tâche consiste à concevoir et à mettre en œuvre un langage dont la complétude Turing repose sur un problème majeur non résolu en mathématiques .

Règles

  • Le problème que vous choisissez doit avoir été posé il y a au moins 10 ans et ne doit pas être résolu, à compter de l'affichage de cette question. Cela peut être toute conjecture prouvable en mathématiques, pas seulement une de celles énumérées sur la page Wikipedia .

  • Vous devez fournir une spécification du langage et une implémentation dans un langage existant.

  • Le langage de programmation doit être complet si et seulement si la conjecture est vérifiée. (ou si et seulement si la conjecture ne tient pas)

  • Vous devez inclure une preuve expliquant pourquoi Turing est complet ou incomplet en fonction de la conjecture choisie. Vous pouvez supposer que vous avez accès à de la mémoire illimitée lors de l'exécution de l'interpréteur ou du programme compilé.

  • Puisque nous sommes concernés par la complétude de Turing, les E / S ne sont pas obligatoires. Cependant, l'objectif est de créer le langage le plus intéressant pour qu'il puisse vous aider.

  • Ceci est un et la réponse avec le plus de votes l'emportera.

Critères cibles

Que devrait faire une bonne réponse? Voici quelques éléments à surveiller lorsque vous votez, mais qui ne sont pas techniquement nécessaires.

  • Ce ne devrait pas être un simple patch d'une langue existante. Modifier une langue existante pour l'adapter aux spécifications convient, mais il est déconseillé d'appliquer des correctifs à une condition, car elle est ennuyeuse. Comme dit par ais523 dans le dix-neuvième octet:

    Je préfère que les gimmicks de mes esolangs soient mieux cuits dans la langue

  • Cela devrait être intéressant en tant que langage ésotérique autonome.

Assistant de blé
la source
Cette conversation a été déplacée pour discuter .
Dennis
13
Dans l’ensemble, je trouve les réponses ici décevantes. Ils sont à peu près "Commencez avec un langage complet de Turing, puis testez si la conjecture X est vraie / fausse et si c'est le cas, mettez fin ou désactivez une fonctionnalité clé".
Xnor
1
@xnor Je suis d'accord avec vous, j'espérais que cette prime susciterait des réponses plus intéressantes, mais il semble que cela ne se produira pas.
Wheat Wizard
2
Je pense que l'un des problèmes est que la plupart des conjectures se sont avérées vraies pour un nombre infini de valeurs, mais que les contre-exemples le seraient également pour un nombre infini de valeurs. En conséquence, il devient presque impossible de prouver la complétude de Turing si et seulement si.
Fəˈnɛtɪk
1
Je pense que l'exigence selon laquelle la complétude de Turing est liée à une conjecture donnée est une exigence assez forte. Je pense que ce serait facile si prouver ou réfuter la complétude de Turing résolvait deux problèmes non résolus, respectivement. (C'est-à-dire que prouver que Turing est complet résout le problème ouvert A et le réfuter décide que le problème ouvert B).
PyRulez

Réponses:

48

Legendre

Cette langue est seulement Turing-complete si et seulement si la conjecture de Legendre est fausse, c'est-à-dire qu'il existe un entier n> 0 tel qu'il n'y a pas de nombres premiers entre n ^ 2 et (n + 1) ^ 2. Ce langage s’inspire de Underload, bien qu’à certains égards, il en soit très différent.

Les programmes dans Legendre sont constitués de séries d’entiers positifs (0 est particulièrement interdit, car il nie l’objet entier du langage). Chaque entier correspond à une commande de base dans Legendre ou à une commande potentielle définie par l'utilisateur. La commande à laquelle il est affecté est basée sur le nombre de nombres premiers entre son carré et le nombre entier suivant (équivalent à la séquence OEIS A014085 ).

Les commandes du langage modifient une pile pouvant contenir des entiers positifs arbitrairement grands. Si la pile contient 0, le 0 est immédiatement supprimé. En détail, les commandes sont:

  • 2 (le plus petit entier produisant cette commande: 1): Poussez l'entier suivant du programme sur la pile.

  • 3 (le plus petit entier producteur: 4): Pop le premier entier sur la pile et exécute la commande qui lui est associée.

  • 4 (le plus petit: 6): Affiche l'entier supérieur. S'il était égal à 1, incrémente l'entier supérieur de la pile.

  • 5 (10): Échangez les deux éléments de la pile supérieurs.

  • 6 (15): décrémente l'entier supérieur de la pile. Si cela donne 0, sautez le 0 et jetez-le.

  • 7 (16): dupliquez l'entier supérieur de la pile.

  • 8 (25): Interrompre l'exécution et imprimer le contenu de la pile.

C'est le jeu d'instructions de base, qui est incapable de faire quoi que ce soit d'intéressant, encore moins de boucler. Cependant, il existe une autre commande à laquelle on ne peut accéder que si la conjecture de Legendre s'avère fausse.

  • 0 (inconnu): Supprime tous les éléments de la pile et les combine dans une nouvelle fonction, qui exécute toutes les commandes commençant au bas de la pile d'origine et se terminant au sommet, accessible en tant que commande dont le "numéro de commande" est égal à celui auquel correspond l'entier suivant dans la source du programme.

Si cette commande est en quelque sorte accessible, le langage devient Turing-complete, car on peut simuler une machine Minsky.

Lorsque la commande 8 est exécutée ou que la fin du programme est atteinte, le programme se termine et le caractère (Unicode) correspondant à chaque entier de la pile est imprimé.

Exemples de programmes

1 2 1 3 1 10 4

Ce programme simple pousse le nombre 2, puis 3 et enfin le 10, avant d'exécuter un 4 (commande: 3), ce qui provoque l'affichage et l'exécution du 10 (commande: 5), en permutant les 2 et 3.

1 5 3 15 2 1 6 7

Ce programme illustre l'utilisation de la correspondance indirecte entier à commande. D'abord, un 5 est poussé, puis un 15 et un 1, en utilisant trois façons différentes d'encoder la commande 2. Ensuite, le 1 est sauté et, en conséquence, le 15 est incrémenté de 16 et finalement exécuté. Le programme se termine par deux instances du nombre 5 sur la pile.

1 1 1 5 ? 24 1 15 1 31 ? 31 24 31

Ce programme montre comment utiliser la commande 0 en utilisant? en tant que numéro d’espace réservé. Le programme enregistre d'abord '1 5' dans la fonction 9, puis '15 31 'dans 10, avant d'exécuter la fonction 9 (avec 24), qui pousse 5 sur la pile et la décrémente de manière répétée jusqu'à ce qu'elle atteigne 0 et soit supprimée. . Ensuite, le programme s’arrête.

Machine de minsky

Pour convertir une machine Minsky en code Legendre, vous devez utiliser la commande 0 . Parce que cette commande est inaccessible à moins que la conjecture de Legendre ne soit fausse, j'ai utilisé un espace réservé? au lieu.

Notez que tous les noms de lignes d’instruction machine Minsky doivent avoir des entiers avec différentes correspondances A014085 et les commandes de base, ainsi que 24 (9) et 31 (10).

Initialisation:
1 1 1 1 ? 24
x INC (A / B) y:

UNE:

1 y 1 24 1 ? 1 6 1 1 16 1 24 ? x

B:

1 y 1 24 1 ? 1 10 1 6 1 1 16 1 10 1 24 ? x
x DEC (A / B) yz:

UNE:

1 4 1 10 1 15 1 10 1 31 1 1 1 10 1 z 1 1 1 16 1 24 1 31 1 ? 1 24 1 15 1 y 1 6 16 1 24 16 1 ? 1 1 16 1 10 1 1 16 1 24 ? x

B:

1 4 1 10 1 15 1 10 1 31 1 1 1 10 1 z 1 1 1 16 1 24 1 31 1 ? 1 24 1 15 1 10 1 y 1 6 16 1 24 16 1 ? 1 1 16 1 10 1 1 16 1 10 1 24 ? x
x HALT:
1 25 ? x

Pour créer le programme final, ajoutez toutes les parties (x, y, z étant remplacés par leurs équivalents) et ajoutez un entier unique pour démarrer la première instruction de la chaîne. Cela devrait prouver la complétude de Turing de la langue dans le cas où la conjecture de Legendre serait fausse par contre-exemple.

Interprète

Cet interpréteur est écrit en Python (3) et a été testé sur les trois exemples ci-dessus. Utilisez les indicateurs -a / - allowZero pour autoriser? à utiliser, -f / - file pour exécuter le code directement à partir d'un fichier et -s / - stackOut pour afficher la pile sous forme de liste Python. Si aucun fichier n'est fourni, l'interpréteur entre dans une sorte de mode REPL, qui est mieux utilisé avec --stackOut.

import sys
import argparse
import io

class I_need_missing(dict): #used to avoid try/except statements. Essentially a dict
    def __missing__(self,key):
        return None 

def appropriate(integer,prev): #returns number of primes between the square of the integer given and the next

    return_value = 0

    if prev[integer]:
        return prev[integer],prev
    if integer == "?":
        return 0,prev
    for i in range(integer ** 2, (integer + 1) ** 2):
        t = False
        if i > 1:
            t = True
            for j in range(2,int(i ** 0.5)+1):
                t = i/j != round(i/j)
                if not t:
                    break
        return_value += t

    prev[integer] = return_value
    return return_value,prev

def run_command(commandseries,stack,functions,prev): #Runs the appropriate action for each command.

    command,prev = appropriate(commandseries.pop(0),prev)

    halt = False

    if command == 0: #store in given number
        functions[appropriate(commandseries.pop(0),prev)[0]] = stack
        stack = []

    elif command == 2:#push
        stack.append(commandseries.pop(0))

    elif command == 3:#execute top instruction
        commandseries.insert(0,stack.pop())

    elif command == 4:#pop, add 1 to new top if popped value was 1
        if stack.pop() == 1:
            stack[-1] += 1

    elif command == 5:#swap top two integers/?
        stack[-1],stack[-2] = stack[-2],stack[-1]

    elif command == 6:#subtract 1 from top of stack
        stack[-1] -= 1
        if stack[-1] == 0:
            stack.pop()

    elif command == 7:#duplicate top of stack
        stack.append(stack[-1])

    elif command == 8:#halt
        halt = True

    else:#run custom
        try:
            commandseries[0:0] = functions[command]
        except TypeError:
            print("Warning: unassigned function " + str(command) + " is unassigned", file = sys.stderr)

    return commandseries,stack,functions,prev,halt

def main(stack,functions,prev):
    #Parser for command line options
    parser = argparse.ArgumentParser(description = "Interpreter for the Legendre esoteric programming language.")
    parser.add_argument("-a","--allowZero", action = "store_true")
    parser.add_argument("-f","--file")
    parser.add_argument("-s","--stackOut", action = "store_true")

    args = parser.parse_args()
    allow_zero = bool(args.allowZero)

    #Program decoding starts
    pre = ""

    if not args.file:
        pre = input()
        if pre == "":
            return
    else:
        pre = open(args.file).read()

    mid = pre.split()
    final = []

    for i in mid:
        if i == "?" and allow_zero:
            final.append("?")
        elif i != 0 or allow_zero: #and allow_zero)
            final.append(int(i))

    halt = False

    #Functional programming at its best
    while final and not halt:
        final,stack,functions,prev,halt = run_command(final,stack,functions,prev)

    #Halting and output
    else:
        if args.stackOut:
            print(stack)
        else:
            for i in stack:
                print(i == "?" and "?" or chr(i),end = "")
            print("")
        if args.file or halt:
            return
        else:
            main(stack,functions,prev)


if __name__ == '__main__':
    main([],I_need_missing(),I_need_missing())
ivzem
la source
14

Union fermée

Ce langage de programmation est complet si et seulement si la conjecture des ensembles fermés dans l' Union est incorrecte.

Contrôles

Liste des commandes:
x ++ Incrément x (INC)
x-- Décrément x (DEC)
j (x, y) Ajout du jeu d'instructions x si y est 0 jusqu'à la fin de la file d'attente des instructions

Toutes les variables sont initialisées à 0

Syntaxe

Les programmes sont écrits comme un ensemble d'ensembles de commandes.
Command1 Command2 Command3 ...
Command1 Command2 ...
...

Pour déterminer si le programme est union fermée, chaque ensemble ne représente que la liste des différentes commandes comprises dans l'ensemble
j (x, y)! = J (a, b)
+ (x)! = + (Y)

Si un type de commande (+, -, j) apparaît dans au moins la moitié des jeux, cela ne fait rien.

Les programmes peuvent se terminer s'il n'y a pas d'instructions à la fin de la file d'instructions

Des boucles infinies, y compris la boucle vide, peuvent être obtenues en utilisant j (x, y)

Interprète

Turing Completeness

Si les trois commandes, j (x, y), incrémenter, décrémenter sont toutes disponibles, une machine de Minsky peut être simulée.

Tout ensemble avec seulement j (x, y) qui est atteint en utilisant j (x, y) est HALT
x ++ est INC
x-- est DEC
j (x, y) est JZ

Si la conjecture des ensembles fermés de l'union est correcte, au moins l'une des trois commandes sera toujours désactivée, rendant ainsi impossible la terminaison de cette langue.

fəˈnɛtɪk
la source
Ce que je ferais, au lieu d'avoir 3 opérateurs, c'est d'avoir un nombre infini de valeurs et de prendre le modulo 4 de chacun pour obtenir l'une des trois opérations plus un no-op. Lorsque le programme démarre, il vérifie la fermeture de l'union des ensembles, puis supprime tous les éléments contenus dans plus de la moitié des ensembles. Il répète ensuite ceci jusqu'à ce qu'il n'y ait plus un tel élément. Si la conjecture est vraie, tous les programmes sont identiques au programme vide. Toutefois, si elle est fausse, vous pouvez exprimer tous les programmes possibles (c'est pourquoi le non-op est inclus).
Wheat Wizard
@WheatWizard La détermination de l'union fermée par l'interpréteur considère le même opérateur sur différentes variables comme différent. x ++ est considéré différent de y ++. En conséquence, il existe une infinité d'ensembles différents pouvant être créés. Avec un nombre infini d'ensembles possibles, si aucun des trois types principaux ne se trouve dans plus de la moitié des ensembles, le processus est complet.
fnɛtɪk
Il est possible qu’une preuve à la conjecture de l’Union des ensembles fermés laisse une conversion complète en un des trois opérateurs aussi complète, car il est possible de laisser tous les opérateurs différents du programme, vous n’auriez besoin que de 3 sur un nombre infini de valeurs à rester.
Fəˈnɛtɪk
13

Prime de Fermat

Le langage fonctionne sur deux bandes potentiellement infinies, où chaque emplacement de la bande peut stocker un entier arbitraire. Les deux bandes sont remplies -1au début. Il existe également deux têtes de bande qui commencent à la position 0 sur les deux bandes.

L'interprète lira d'abord l'entrée et enregistrera les valeurs dans la première bande (de données) en commençant à la position 0.

Ensuite, il lira le programme fourni. Pour chaque numéro rencontré, il va d'abord vérifier si la valeur est une prime de Fermat ou non. Si c'est le cas, il écrira sur la seconde bande (d'instruction) ce que Fermat Prime est, sinon il écrira -1sur la bande d'instruction.

Ensuite, vérifiez la valeur au niveau du pointeur d'instruction et effectuez l'une des opérations suivantes:

  • -1 ou moins: quitter le programme
  • 0: Déplacez la bande de données en position un vers la gauche. Déplacez la bande d'instructions d'un côté vers la droite
  • 1: Déplacez la bande de données en position un à droite. Déplacez la bande d'instructions d'un côté vers la droite
  • 2: Augmente la valeur à la position de la bande de données. Déplacez la bande d'instructions d'un côté vers la droite
  • 3: Diminue la valeur à la position de la bande de données. Déplacez la bande d'instructions d'un côté vers la droite
  • 4: Si la valeur à la position actuelle de la bande de données est égale à zéro, déplacez la bande d'instructions vers la droite, jusqu'à atteindre une valeur correspondante 5(ou supérieure) sur la bande d'instructions ou un nombre inférieur à 0. Si c'est un 5(ou un plus grand), déplacez le pointeur d'instruction de nouveau à droite, s'il est plus petit que 0alors quittez le programme. Si value indique que la position actuelle de la bande de données n’est pas nulle, il suffit de déplacer la bande d’instruction un à droite.
  • 5ou plus: déplacez le pointeur d'instruction vers la gauche jusqu'à ce que vous atteigniez la 4valeur correspondante ou que vous trouviez quelque chose de moins que 0. Dans le cas de ce dernier, quittez le programme.

(en faisant correspondre 5(ou plus) et les 4valeurs, cela signifie que lors de la recherche de la valeur appropriée sur la bande d'instructions chaque fois qu'elle rencontre la même valeur que la commande initiale (soit 5(ou plus) ou 4), il devra ignorer le nombre approprié de l'autre valeur ( 4ou 5(ou plus) respectivement) sur la recherche)

En boucle, jusqu’à ce que l’instruction indique que vous devez quitter le programme.

Lorsque le programme se termine, affichez les valeurs sur la bande de données de la position 0jusqu'à la première position de la bande contenant une -1valeur.

Preuve

Notez que le langage correspond essentiellement à un interprète Brainfuck sans IO, où il F_5est nécessaire de pouvoir effectuer tout type de boucles appropriées.

Cependant, d'après la conjecture des nombres premiers de Fermat, il n'y a que 5 nombres premiers de Fermat ( F_0- F_4). S'il F_5existe, le langage est Turing-complet, car nous savons que Brainfuck est Turing-complet. Toutefois, sans cela, F_5vous ne pourrez ni créer de branche ni faire de boucle, ce qui vous oblige essentiellement à vous lancer dans des programmes très simples.

la mise en oeuvre

(testé avec ruby ​​2.3.1)

#!/usr/bin/env ruby
require 'prime'

CHEAT_MODE = false
DEBUG_MODE = false
NUM_CACHE = {}

def determine_number(n)
  return n.to_i if CHEAT_MODE
  n = n.to_i
  -1 if n<3

  return NUM_CACHE[n] if NUM_CACHE[n]

  i = 0

  loop do
    num = 2**(2**i) + 1
    if num == n && Prime.prime?(n)
      NUM_CACHE[n] = i
      break
    end
    if num > n
      NUM_CACHE[n] = -1
      break
    end
    i += 1
  end

  NUM_CACHE[n]
end

data_tape = Hash.new(-1)
instruction_tape = Hash.new(-1)

STDIN.read.each_char.with_index { |c,i| data_tape[i] = c.ord }
File.read(ARGV[0]).split.each.with_index do |n,i|
  instruction_tape[i] = determine_number(n)
end

data_pos = 0
instruction_pos = 0

while instruction_tape[instruction_pos] >= 0
  p data_tape, data_pos, instruction_tape, instruction_pos,'------------' if DEBUG_MODE

  case instruction_tape[instruction_pos]
  when 0 then data_pos -= 1; instruction_pos += 1
  when 1 then data_pos += 1; instruction_pos += 1
  when 2 then data_tape[data_pos] += 1; instruction_pos += 1
  when 3 then data_tape[data_pos] -= 1; instruction_pos += 1
  when 4 then
    if data_tape[data_pos] == 0
      count = 1
      instruction_pos += 1
      while count>0 && instruction_tape[instruction_pos] >= 0
        count += 1 if instruction_tape[instruction_pos] == 4
        count -= 1 if instruction_tape[instruction_pos] >= 5
        instruction_pos += 1
      end
      break if count != 0
    else
      instruction_pos += 1
    end
  else
    count = 1
    instruction_pos -= 1
    while count>0 && instruction_tape[instruction_pos] >= 0
      count += 1 if instruction_tape[instruction_pos] >= 5
      count -= 1 if instruction_tape[instruction_pos] == 4
      instruction_pos -= 1 if count>0
    end
    break if count != 0
  end
end

data_pos = 0

while data_tape[data_pos] >= 0
  print data_tape[data_pos].chr
  data_pos += 1
end

Exemples:

Cela écrira H(raccourci pour Hello World!) à l'écran avec une nouvelle ligne:

17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17 17 17 17 17 17 17 17
17 17 17
5
17 17 17 17 17 17 17 17 17 17
17

Enregistrez sous example.fermatet exécutez-le comme ceci (note: vous devez toujours avoir une entrée):

$ echo -n '' | ./fermat.rb example.fermat

Cet exemple suivant fera un simple chiffrement de style César en incrémentant chaque valeur de l'entrée de un. Vous devez évidemment remplacer ?par le 5ème prime de Fermat:

17 65537 5 17 ? 257

Vous pouvez essayer son fonctionnement en activant le mode triche et en utilisant 2 4 1 2 5 3comme code source:

$ echo 'Hello' | ./fermat.rb example2_cheat.fermat
SztupY
la source
2
Je suis désolé pour le pauvre codeur qui doit taper le nombre premier correspondant pour arriver à 5. J'espère qu'ils ont un bon clavier.
AdmBorkBork
2
@AdmBorkBork Ne vous inquiétez pas. Il a juste plus de bits que l'univers n'a de particules élémentaires.
Fəˈnɛtɪk
@ LliwTelracs en fait cela n'a pas de sens puisque la quantité de particules élémentaires dans l'univers est Aleph-null (oméga) et d'oméga, cela commence à ne pas signifier la taille réelle du nombre. (Sauf si son numéro un: P)
Matthew Roh
1
@ MatthewRoh j'avais fait une erreur. Je voulais dire dans l'univers observable.
Fəˈnɛtɪk
2
@ MatthewRoh En fait, cela pourrait être fini, infini, indénombrable ou même incompatible avec la théorie des ensembles! Nous ne saurons jamais, cependant :(
CalculatorFeline
10

Hirondelles avec noix de coco v2

Comme la version précédente comportait des erreurs qui l’avaient invalidé pour ce concours, et je ne souhaite pas que les upvotes de la version précédente comptent pour cette version qui est très différente, cette version est soumise en tant que nouvelle publication.

Ce langage n'est pas complet si la conjecture de Collatz peut être vérifiée pour tous les entiers positifs. Sinon, le langage est complet.

Cette langue était basée sur Cardinal .

Premièrement, le contVal du programme est calculé en utilisant la formule
contVal = sum (sum (somme des valeurs ASCII de la ligne) * 2 ^ (rangée-1))

Ensuite, 2 hirondelles dirigées dans des directions opposées sont créées à chaque A ou E et toutes les instructions de retournement conditionnelles sont configurées pour attendre l’initialisation.
Les hirondelles créées à un E sont dirigées gauche / droite et les hirondelles créées à un A sont dirigées vers le haut / bas.

Enfin, le code effectuera des étapes jusqu'à ce que tous les pointeurs aient été supprimés ou que contVal soit tombé à un.

À chaque étape, si contVal% 2 == 0, il sera divisé par 2, sinon, il sera multiplié par trois et incrémenté de un.

Commandes:

0: valeur définie sur 0
+: valeur incrémentée de 1
>: changement de direction vers la droite
v: changement de direction vers le bas
<: changement de direction vers la gauche
^: changement de direction vers le haut
R: les pointeurs suivants le premier pointeur comparent à la valeur de la premier pointeur. Si égal, allez tout droit, sinon tournez à droite.
L: Les pointeurs suivants après le premier pointeur sont comparés à la valeur du premier pointeur. Si égal, allez tout droit, sinon tournez à gauche.
E: dupliquer le pointeur mais en se dirigeant dans les directions gauche et droite
A: dupliquer le pointeur en se dirigeant dans les directions de haut en bas
? : Supprime le pointeur si la valeur est 0

Explication:

Si la conjecture de Collatz peut être vérifiée pour tous les entiers positifs, la durée de tout programme exécuté dans cette langue est finie, car contVal convergera toujours sur 1, mettant ainsi fin au programme.

Sinon, je dois simplement prouver que ce langage peut implémenter les fonctions suivantes

Incrément: représenté par +
Constante 0: représenté par 0
Accès aux variables: les variables sont stockées sous forme de pointeurs au fur et à mesure de leur déplacement
Concaténation des instructions: en modifiant la distance parcourue en opérations, vous pouvez modifier l’ordre dans lequel les opérations sont effectuées
. Dans cette langue

E   > V
    ^+R
      +
      A

agira comme une boucle for> compte jusqu'à 1 (un code supplémentaire pourrait être ajouté à la boucle)

De même, le code

Rv
^<

Agira comme un do jusqu'à ce qu'il soit égal à la valeur conditionnelle définie dans la boucle R.

fəˈnɛtɪk
la source
Tu m'as battu aussi, j'allais faire quelque chose avec la conjecture de collatz. Beau travail, sur le point de vue intéressant sur elle. J'allais juste créer un langage qui ne serait capable de stocker des nombres que s'ils convergeaient vers 1.
Rohan Jhunjhunwala
Je suis confus. Où la fonction Collatz figure-t-elle dans cela? Dans une deuxième lecture, je pense que vous voulez dire que la fonction est appliquée contValà chaque étape (et donc si la conjecture est vraie, il n’ya pas de boucles infinies) - mais je ne vois pas cela explicitement indiqué nulle part dans la réponse. ??
DLosc
Désolé, alors qu'il fait cela, je pense que j'avais accidentellement coupé cela de ma description à un moment donné
fnɛtɪk
10

Perfection / Imperfection

Ouf, c'était amusant.

La perfection / imperfection n'est complète que s'il existe une infinité de nombres parfaits. S'il y en a, cela s'appelle la perfection et s'il n'y en a pas, il s'appelle l'imperfection. Jusqu'à ce que ce mystère soit résolu, il conserve les deux noms.

Un nombre parfait est un nombre dont les diviseurs totalisent le nombre. Six est donc un nombre parfait car 1+2+3=6.

Perfection / Imperfection a les fonctions suivantes:

Perfection / Imperfection est basé sur une pile, avec une pile indexée à zéro.

Commandes:

p(x, y): pousse x sur la pile en yième position.

z(x, y): pousse x à la pile en yième position, supprime ce qui était précédemment en y

r(x): supprime le xième élément de la pile

k(x): retourne le xième élément de la pile

a(x, y): ajoute x et y. Lorsqu'il est utilisé avec des chaînes, il les met ensemble dans l'ordre xy.

s(x, y): soustrait y de x. avec des chaînes, supprime la dernière longueur (y) de x

m(x, y): multiplie x et y. Si utilisé avec des chaînes, multiplie x fois len y.

d(x, y): divise x par y

o(x): impressions x

i(x, y): si x est évalué à true, alors il exécute la fonction y

n(): retourne le compteur sur lequel le bloc de code est appelé.

q(): retourne la longueur de la pile

t(): entrée utilisateur

e(x, y): Si x est un entier, si x et y ont la même valeur, cela retourne 1. Si y est une chaîne, il prend la longueur de y. si x est une chaîne, il convertit y en chaîne et vérifie si elles sont identiques et, si elles le sont, renvoie 1. Sinon, il renvoie 0.

l(x, y): si x est plus grand que y, alors il retourne 1. S'il y a une chaîne, alors il utilise la longueur de la chaîne.

b(): arrête le programme.

c(x, y): court x, puis y.

Pour obtenir l'équivalent d'un Python and, multipliez les deux valeurs ensemble. Pour or, ajoutez les valeurs, et pour not, soustrayez la valeur de 1. Cela ne fonctionne que si la valeur est 1 ou 0, ce qui peut être obtenu en divisant le nombre par lui-même.

Types de données: entiers et chaînes. Les chaînes sont désignées par '', et tous les nombres non entiers sont arrondis.

Syntaxe:

Le code est constitué de fonctions imbriquées à l'intérieur de dix {}s. Par exemple, un programme qui se aux intrants et les imprimer seraient ajoutées: {o(a(t(), t()))}. En arrière-plan du programme, un compteur commence à 0 et progresse de 1 chaque fois qu'il exécute un bloc de code. Le premier bloc de code s’exécute à 0, et ainsi de suite. Une fois que les dix blocs de code sont exécutés, le sixième est exécuté chaque fois que le compteur atteint un nombre parfait. Vous n'avez pas besoin des dix blocs de code pour que le programme fonctionne, mais vous avez besoin de 7 si vous voulez créer une boucle. Pour mieux comprendre comment fonctionne cette langue, exécutez le programme suivant, qui imprime le compteur à chaque fois que le compteur atteint un nombre parfait: {}{}{}{}{}{}{o(n())}.

L'interpréteur peut être trouvé ici: repl.it/GL7S/37 . Soit sélectionnez 1 et tapez votre code dans le terminal, ou collez-le dans l' code.perfectonglet et sélectionnez 2 lorsque vous exécutez. Cela fera du sens quand vous l'essaierez.

Preuve de la complétude de Turing / manque de complétude de Turing.

Selon cet article sur l’échange de pile de génie logiciel , un ensemble de Turing doit pouvoir avoir une forme de répétition conditionnelle de saut et un moyen de lire ou d’écrire de la mémoire. Il peut lire / écrire de la mémoire sous la forme de la pile et peut se mettre en boucle car le 6ème bloc de code est exécuté à chaque fois que le compteur atteint un nombre parfait. S'il y a un nombre infini de nombres parfaits, il peut boucler indéfiniment et Turing est complet, sinon ce n'est pas le cas.

Interpréteur de balises cycliques auto-bit qui prend 5 caractères, 1 ou 0, en entrée:

{p(t(),0)}{(p(t(),0)}{p(t(),0)}{p(t(),0)}{p(t(),0)}{p(0,0)}{c(i(e(k(s(q(),k(0))),0),c(r(q()),i(l(k(0),0),z(s(k(0),1),0)))),i(e(k(s(q(),k(0))),1),c(z(a(k(0),1),0),i(e(k(q()),1),p(k(s(q(),k(0))),1)))))}

Il peut être étendu pour prendre un nombre quelconque de caractères en entrée. Cela pourrait prendre une entrée infinie, mais seulement s'il y a une infinité de nombres parfaits!

Camarade SparklePony
la source
1
Je pense que vous créez peut-être seulement une nouvelle valeur pour la boucle locale car elle n'est pas partagée avec la fonction.
Fəˈnɛtɪk
3
Dans l'état actuel des choses, vous n'avez pas de preuve de TC. L'article d'ingénierie logicielle auquel vous vous associez donne un ensemble approximatif d'exigences, mais TC n'est pas qu'un tas de cases à cocher. Vous devrez implémenter un automate TC (comme une machine de Minsky) ou montrer que votre langage est indécidable.
Wheat Wizard
2
@WheatWizard Là, j'ai ajouté un interpréteur de Bitwise Cyclic Tag. Il peut être modifié pour prendre n'importe quelle quantité de caractères en entrée. Il pourrait éventuellement prendre des caractères infinis en entrée, mais seulement s'il existe une infinité de nombres parfaits!
Camarade SparklePony
2
"Une fois que les dix blocs de code sont exécutés, le sixième est exécuté chaque fois que le compteur atteint un nombre parfait." Ainsi, l'interprète compte directement les nombres parfaits? J'ai l'impression que cela va à l'encontre de l'esprit du défi. La spécification de langue réelle importe peu, il peut s'agir de tout ce que Turing-complete plus "exécute pour une étape seulement lorsque vous atteignez un nombre parfait".
Xnor
10

Semelles

Ce langage de programmation est complet si et seulement si la conjecture de Scholz est vraie.

J'ai écrit ce langage parce que @SztupY disait qu'il n'y aurait aucun résultat qui repose sur la conjecture vraie de Turing complète

Liste de commandes

+(x)      Increment x (INC)   
-(x)      Decrement x (DEC)  
j(x,y)    Jump to instruction x if y is 0 (JZ)  
x         End program (HALT) 

Avec ces commandes, ce langage peut simuler une machine Minsky

Interprète

Je recommanderais fortement de ne pas exécuter ceci. Il utilise une méthode extrêmement lente de vérification de la chaîne d'addition.

Turing complet

Le langage utilise un compteur pour le nombre de commandes exécutées qu'il vérifie par rapport à la conjecture de Scholz afin de modifier l'exhaustivité du langage.

Si la conjecture Scholz est vrai, ce programme fonctionne exactement comme une machine Minsky normale avec
Incrémenter
Décrémenter
Saut si Zéro
Halt

Toutefois, si la conjecture de Scholz est fausse, le compteur atteindra éventuellement une valeur pour laquelle la conjecture de Scholz ne sera pas vraie. Comme le langage a été conçu pour sortir lorsque le nombre que la conjecture de Scholz est atteint est faux, le programme se fermera à chaque fois après avoir exécuté autant de commandes. Par conséquent, tous les programmes auront une durée limitée. Comme cela ne concorde pas avec les exigences relatives au langage complet de Turing,

"La longueur de la bande ne peut pas être fixe, car cela ne correspondrait pas à la définition donnée et limiterait sérieusement la plage de calculs que la machine peut effectuer à ceux d'un automate borné linéaire",

la langue ne serait pas complète si la conjecture de Scholz était fausse

fəˈnɛtɪk
la source
1
+1, car cela enfonce réellement l'exigence de la conjecture dans la langue, plutôt que d'ajouter quelque chose d'étrange pour tuer la langue si la conjecture est vraie / fausse
Gryphon - Rétablit Monica
Je ne comprends pas. Les commandes que vous fournissez sont exactement celles dont vous avez besoin pour simuler une machine Minsky. Si c'est tout ce que vous avez à faire, votre langue est complète, indépendamment de la conjecture de Scholz. Vous devez manquer quelque chose de votre explication.
Nathaniel
@Nathaniel L'une des conditions requises pour un langage complet de Turing est que le langage puisse se retrouver dans une boucle infinie (problème bloquant). Mon code compte le nombre de fois qu'il exécute des instructions. Si la conjecture de Scholz est fausse, le programme s'arrête toujours après un nombre défini d'instructions.
fəˈnɛtɪk
Oui, mais vous avez oublié d’expliquer ce qui l’arrête si la conjecture de Scholz est fausse. Jetez un autre coup d'oeil à votre réponse - ce n'est pas là du tout.
Nathaniel
@Nathaniel Le programme fonctionne littéralement en vérifiant chaque nombre pour savoir s'il fonctionne dans la conjecture de scholz. Il se ferme automatiquement lorsqu'il trouve un nombre en désaccord avec la conjecture.
fəˈnɛtɪk
9

Fiancé

Github Betrothed .

Le readme et les spécifications se trouvent sur le github, sous "README.txt".

Généralement, un programme Betrothed est composé de paires de lignes, dont les longueurs sont des paires de paires primitives distinctes ou des paires fiancées (aucune duplication ne peut se produire). Le programme est exécuté en recherchant des "sous-ensembles pliables" de la première ligne de la paire dans la deuxième ligne. Le nombre de ces sous-ensembles, associé à la distance entre la deuxième ligne d'origine et la deuxième ligne sans les sous-ensembles pliables, détermine la commande à exécuter.

Je vais extraire la preuve pour ce post:

V. PROOF OF TURING COMPLETENESS

Now, no language can be Turing Complete with bounded program size. Therefore, if Betrothed
is Turing Complete, it must have unbounded program size. Since the lengths of the lines of
a Betrothed program must be twin prime pairs or betrothed pairs, and since both sequences
are unproven to be infinite or finite, Betrothed has unbounded program size if and only if
there are infintie betrothed pairs, there are infinite twin prime pairs, or both.

    Next: to prove that if Betrothed has an unbounded program size, then it is Turing
Complete. I will use the op-codes from the above table to demonstrate key factors of a
Turing Complete language; they are of the form  [index]<[ld]> .

  1. Conditional goto: 6<> 5<>, or if-popjump. This can be used to form a loop.
  2. Inequality to a constant K: 10<K> 
  3. Arbitrarily large variable space: you can use some separator constant C.

    With this, I have sufficient reason to believe that Betrothed is Turing Complete.
Conor O'Brien
la source
4
"Désormais, aucune langue ne peut être Turing Complete avec une taille de programme limitée." Je suis confus à propos de cette affirmation ... D'un côté, il est vrai qu'avec une taille de programme délimitée, nous ne pouvons écrire qu'un nombre fini de programmes différents, mais d'un autre côté, une preuve courante de Turing Completeness consiste à écrire un interprète pour un autre. Turing Un langage complet, qui n'exige pas du tout une taille de programme illimitée ...
Leo
1
Eh bien, le programme transmis à l'interprète n'a pas besoin d'être mis dans le code de l'interprète, il doit être donné à l'interprète en tant qu'entrée
Leo,
7
@Leo. Je dirai que, pour que la langue à TC, il doit être capable d'encoder le programme à transmettre à l'interprète (qui est, imaginez que cette langue n'a pas de commande d'entrée.) Imaginez une langue avec une seule commande: b. Cela interprète un programme BF, qui est placé après, comme b+++++.. La taille du programme est toutefois limitée à 10 caractères. Bien qu’elle puisse interpréter le BF, elle ne peut pas calculer tous les programmes qu’une machine de Turing peut gérer.
Conor O'Brien
3
@EriktheOutgolfer le problème principal avec votre problème est "il peut mettre le programme BF qu'il reçoit de l'entrée ..." Pour cela, je vous encourage fortement à lire ou à relire mon commentaire précédent, en particulier cette première phrase. Si la langue est uniquement complète par Turing sur la base de l'entrée, comment peut-elle, sans aucune entrée, être complète? Autrement dit, pour que la langue soit complète, c'est le programme de la langue elle-même qui doit l'encoder. Sinon, on constate qu'ils encodent le programme dans l'entrée, ce qui n'est pas une méthode de programmation valide.
Conor O'Brien
1
Je ne pense pas que ce soit un point fixe. Cet article d'Esolang aborde le problème. (Il y a aussi la question de savoir si un programme qui imprime tous les programmes de terminaison possibles dans un langage complet de Turing , avec sa sortie, est une démonstration de Turing-complétude; cela ne nécessite aucune entrée et peut être réalisé avec un programme de longue durée. .)
5

Parité amiable

Ce langage est basé sur l'existence ou non de nombres à l'amiable avec une parité opposée .

Les commandes

x : End program if not on top line  
+ : increment stored value  
- : decrement stored value  
{ : set next goto x value to current x value
} : goto previous x value set by {  
j : Go down one line if the special value is an amicable number and the
    parity is opposite to the matching number (loops back to top). If the
    special value is not an amicable number and not on the top line, go up
    one line.  

Flux de contrôle

Le programme effectue des cycles répétés de gauche à droite avant de revenir au début. S'il rencontre un "j", il vérifie la valeur pour déterminer s'il doit changer de ligne. Si le numéro est un nombre à l'amiable avec une parité opposée à celle du match, il descend d'une ligne (retour en haut). Sinon, s'il s'agit d'un nombre à l'amiable, il monte d'une ligne s'il ne figure pas déjà dans la ligne du haut.

Le programme ne peut se terminer que si le programme atteint un x dans une ligne en dehors de la ligne supérieure.

Turing Completeness

Ce programme peut être utilisé pour simuler une machine Minsky en supposant qu’il existe une paire de nombres à l’amiable avec une parité opposée.

j, {et} peuvent être utilisés pour simuler JZ (r, x) bien qu’il vérifie les nombres à l’amiable au lieu de zéro.
+ est INC (r)
- est DEC (r)
x est HALT

Si vous ne pouvez pas quitter la première ligne, les commandes x et} ne font rien. Il en résulte que le programme ne peut pas entrer dans un état HALT sauf s'il s'agit d'un programme vide. Par conséquent, selon la description selon laquelle la complétude de Turing nécessite un état HALT , le langage serait incomplet.

Interprète

fəˈnɛtɪk
la source
2

Nouvelle ligne

Disclaimer: C'est un peu le bordel et assez simple. C'est la première langue que j'ai jamais écrite et la conjecture est la seule que j'ai comprise. Je sais qu'un autre utilisateur a eu une réponse plus longue avec le même, mais j'ai quand même décidé de l'écrire.

Pour écrire dans Newline, vous devez disposer de beaucoup de temps et de nouvelles lignes ( \n). Cela fonctionne en dehors de la conjecture de Legendre comme étant vraie. Chaque opérateur doit tomber sur un nombre dans la conjecture de Legendre que nous commençons par n = 1. Chaque fois que vous avez un opérateur, vous prenez la quantité de \ n et vous le connectez à la conjecture de Legendre et vous obtenez la plage que le prochain montant de \ Donc, pour commencer, \n\nvous passez à un opérateur, puis à un \nautre opérateur, nous sommes à 3 nouvelles lignes. La prochaine étape est la suivante: vous devez donc ajouter un \n\nopérateur et vous assurer que la dernière ligne d’opérateur a la bonne quantité de nouvelles lignes et que vous êtes sur un montant premier correspondant à la conjecture de Legendre que nous avons commencée.

Numbers (le tableau) est comme les variables. Chaque fois qu'un opérateur exécute (qui utilise des nombres), il s'incrémente.

+ adds
- subtracts
/ divide
* multiply 
s sqrt
% mod
a push to vars
g sets stack to numbers
q pushes value of stack to numbers
i increment 
d decrement
r stops subtraction at 0
w turns back on subtraction past 0
[ starts loop
] ends loop runs until stack is 0
{ starts loop
} ends loop and loops until loops[ln] is 0
k increment loops

Tant que nous avons des nombres premiers illimités qui suivent les règles, ce langage a une bande non finie.

Machine de minsky

\n\ng\nr\n\n[\n\nd\n\n\n\n]

Comment ça fonctionne:

\n\ng     # the first two newlines are to get to a prime number of newlines (2) then sets the value of stack to the first variable in the array numbers (see code in link)

\nr       # gets to the next number and makes it so subtraction stops at 0

\n\n[     # starts the loop

\n\nd     # decrements stack 

\n\n\n\n] # ends loop

Essayez-le sur KhanAcademy .

Christopher
la source
@wheat il n'a pas besoin de boucler avec une mémoire non finie
Christopher
Cela ne fonctionne que si c'est vrai. Je ne peux pas terminer la rédaction pour le moment car je suis sur le portable, mais je le ferai ce soir
Christopher
Même si vous avez une mémoire infinie, vous devez toujours pouvoir faire une boucle infinie.
Pavel
J'ai des boucles. Essayer de les rendre infinis
Christopher
En ce moment, ils plantent
Christopher
2

Taggis

Taggis est un langage basé sur les systèmes de balises .

La complétude complète de Taggis est basée sur la conjecture de Collatz

Syntaxe

La syntaxe d'un programme Taggis est simplement constituée de trois chaînes (règles de production) entièrement composées des lettres a, b et c, séparées par des espaces.

Exécution

Le seul état du programme de Taggis est une chaîne composée des trois mêmes caractères.

Taggis implémente un système de balises TS (3, 2), dans lequel les deux premières lettres de la "balise" actuelle sont supprimées, et la toute première lettre qui se trouvait dans cette partie supprimée est ajoutée à la fin de la règle de production correspondante. la ficelle.

Par exemple, le programme Taggis bc a aaaimplémente le problème 3n + 1, où les itérations sont représentées par un nombre correspondant de as et l'étape 3n + 1 est remplacée par (3n + 1) / 2 [1], ce qui conduit à la sortie du programme:

aaa // 3
  abc
    cbc
      caaa
        aaaaa // 5
          aaabc
            abcbc
              cbcbc
                cbcaaa
                  caaaaaa
                    aaaaaaaa // 8
                      aaaaaabc
                        aaaabcbc
                          aabcbcbc
                            bcbcbcbc
                              bcbcbca
                                bcbcaa
                                  bcaaa
                                    aaaa // 4
                                      aabc
                                        bcbc
                                          bca
                                            aa // 2
                                              bc
                                                a // 1 and halt because we then begin an infinite loop
                                                 HALT

Turing complet

Bien sûr, ce système simple peut sembler beaucoup trop simple pour imiter la complétude de Turing, mais il s'avère que toute machine de Turing à 2 symboles (une classe qui inclut des machines universelles) peut être convertie en un système de balises avec 2 caractères retirés de la tête, et 32 ​​* m règles de production, où mest le nombre d'états dans la machine de Turing.

La plus petite machine universelle de Turing connue avec seulement 2 symboles utilise 18 états et le système d'étiquettes correspondant contient donc 576 règles de production [2].

Cependant, la classe de calcul de l'ensemble de tous les systèmes de balises avec 3 productions et 2 symboles supprimés est liée à la conjecture de Collatz [2]. S'il s'avère que la conjecture de Collatz est fausse, alors Taggis est complet. Sinon, il est basé sur un AUTRE problème non résolu en mathématiques, trouver une machine de Turing plus petite que celle de

def taggis(inp, a, b, c):
    current = inp
    seen = set()
    while True:
        seen.add(tuple(current))

        yield current

        head = current[0]

        current = current[2:]

        current.extend([a, b, c][head])

        if tuple(current) in seen:
            return

def parse():
    program = input().split(" ")

    assert len(program) == 3, "There has to be exactly 3 production rules!" 

    productions = []

    for production in program:

        production = [{"a": 0, "b": 1, "c": 2}[x] for x in production]
        productions.append(production)  

    program_input = [{"a": 0, "b": 1, "c": 2}[x] for x in input()]

    k = 0   

    for step in taggis(program_input, *productions):
        print(' ' * k +''.join(['abc'[x] for x in step]))

        k += 2
    print(' ' * (k - 1) + 'HALT')

parse()
  1. ce qui équivaut à la fonction Collatz originale, car 3n + 1 d'un impair nsera toujours pair et la division peut donc être appliquée automatiquement

  2. Systèmes de balises et fonctions de type Collatz, Liesbeth De Mol ,

ThePlasmaRailgun
la source