Jouer à chaque personnage ASCII en 99

11

99 est un langage de programmation que j'ai inventé plus tôt cette semaine pour mon défi Écrivez un interprète pour 99 . (Inventé mais jamais nécessaire à mettre en œuvre grâce à une demi-douzaine d'entre vous.;)) La spécification de langue complète fait partie de ce défi, donc je ne prends pas la peine de tout republier ici.

En 99, vous pouvez imprimer des caractères ASCII individuels sur stdout, mais en raison des contraintes de la langue, il n'est pas toujours clair comment imprimer un caractère particulier de manière aussi concise que possible.

Pour chacun des 128 caractères ASCII, écrivez un programme 99 qui ne prend aucune entrée et génère ce seul caractère. Vous pouvez coder une ou toutes ces réponses à la main, ou vous pouvez écrire un autre programme (dans n'importe quelle langue que vous aimez) pour les générer pour vous.

La somme des caractères de chacun de vos 128 99 programmes est votre score. Le score le plus bas l'emporte. Les sauts de ligne comptent comme un seul caractère.

Souvenez-vous qu'en 99 , seules les variables de taille paire comme 9999les caractères ASCII de sortie (les variables de taille impaire produisent des entiers). Leur valeur est divisée par 9, puis prise en mod 128, les valeurs n'ont donc pas besoin d'être dans une certaine plage pour correspondre aux caractères ASCII. Par exemple, les valeurs internes 297, 1449 et -855 correspondent toutes au caractère !car lorsqu'elles sont divisées par 9 et prises en mod 128, elles deviennent toutes 33, ce qui est le code de caractère pour !.

Si vous avez besoin d'un interprète pour 99 , je suggère la réponse Python de Mac .

Je sais que j'ai dit que mon prochain défi serait plus interactif, mais je travaille toujours sur le truc pour celui-ci.

Loisirs de Calvin
la source

Réponses:

7

Une affectation, 2075 (optimal)

Cela devrait être la valeur optimale (sauf si j'ai une grosse erreur de raisonnement ou que mes tests sont nulles).

Tout d'abord. Il n'y a que 7 nombres différents (mod 128) que vous pouvez exprimer en 99. Toutes les valeurs de 7 ou plus 9 correspondent au même nombre 71. (Parce que 10 ^ 8 mod 128 == 0, 10 ^ 9 mod 128 == 0, ...)

Si l'une des 4 valeurs que vous pouvez exprimer avec un nombre pair de neuf, la sortie de ce nombre est clairement la solution optimale.

Sinon, j'essaie d'atteindre le nombre avec une instruction d'affectation (attribuer à 99) et d'imprimer 99. Comme il s'avère que la taille maximale du programme avec cette approche est de 22 caractères. De toute évidence, utiliser Goto prend bien plus que cela. La seule possibilité qu'une solution à une affectation puisse être battue est une solution à deux affectations. J'ai testé cela (j'espère sans erreur, le code est assez compliqué) et je n'ai trouvé aucune solution pour aucun caractère ASCII.

Par conséquent, seule la vérification des 4 nombres directs et de l'approche à une affectation devrait suffire pour trouver la solution optimale. Le programme Python suivant (compatible 2 et 3) génère tous les programmes et résume leurs longueurs. Il utilise une approche IDA * simple.

from itertools import count

def nines_to_dec(nines):
    return ((10**nines - 1) // 9) % 128

def shortest_representation(ascii_value):
    # try simple output,
    # max code length is 8, (8 nines == 10 nines == 12 nines == ...)
    # if this works, than this is the shortest representation

    for nines in range(2, 9, 2):
        if nines_to_dec(nines) == ascii_value:
            return "9" * nines

    # otherwise try one assignment
    for length in count(1):
        result = assignment(ascii_value, length, [])
        if result:
            return "99 " + result + "\n99"

def assignment(value, left, nines_list):
    if left == 0:
        eval_numbers = [nines_to_dec(nines) for nines in nines_list]

        if (sum(eval_numbers[::2]) - sum(eval_numbers[1::2])) % 128 == value:
            return " ".join("9" * nines for nines in nines_list)
        else:
            return False

    for nines in range(1, 8):
        left2 = left - nines - 1 # -1 for space
        if left2 >= 0:
            result = assignment(value, left2, nines_list + [nines])
            if result:
                return result

    return False

lengths = []
for i in range(128):
    program =shortest_representation(i)
    lengths.append(len(program))
    print("ASCII-value: {}, ASCII-char: {}".format(i, chr(i)))
    print(program)

print(sorted(lengths))
print(sum(lengths))

La sortie est de la forme suivante:

....
ASCII-value: 65, ASCII-char: A
99 9 999999 9999999
99
ASCII-value: 66, ASCII-char: B
99 9 99 9999 99
99
ASCII-value: 67, ASCII-char: C
99 9 99 9 99 9999
99
....

Vous pouvez trouver la sortie complète sur: http://pastebin.com/bKXLAArq

Le caractère avec le programme le plus court (2 caractères) est vertical tab - 11 une longueur de programme de 2, les caractères avec les programmes les plus longs (22 caractères) sont bell - 7et A - 65.

La somme pour tous les programmes est de 2075.

Et au fait, j'ai utilisé l' interpréteur k / q de tmartin . Je déteste pas mal de problèmes avec les autres (Python, Perl, CJam). Je ne sais pas si c'était ma faute.

Jakube
la source
Cela aiderait les réalisateurs d'interprètes si vous pouviez décrire les problèmes que vous avez rencontrés. Très bonne réponse.
coredump
3

Une variété de techniques, 42109

Pour les nombres, au lieu de calculer le grand caractère ASCII, je viens de calculer la valeur du nombre. Vous avez seulement dit de pouvoir sortir le personnage, donc cela devrait toujours fonctionner.

EDIT: a changé les chiffres pour utiliser les caractères ASCII, alors ne tenez pas compte de cela. J'ai laissé le code numérique d'origine dans le code Java, mais je l'ai commenté au cas où quelqu'un voudrait l'utiliser.

Certains d'entre eux, je l'ai fait à la main, la plupart j'ai juste écrit un programme à taper.

Celles-ci sont composées de 1 à 4 lignes chacune, elles sont donc assez conviviales pour simplement copier et coller dans un programme. Il convient de noter qu'ils ne fonctionnent pas successivement car mon code généré ne préserve pas les états des variables.

La technique la plus couramment utilisée ici était la même que l'approche orlp:

Continuez à soustraire 9 de 99, puis sortez.

Ma version diffère en utilisant des cas personnalisés et en composant une grande partie des calculs sur une seule ligne. Les cas personnalisés sont juste où le personnage peut être représenté avec juste un tas de 9 et aucun math ou mon code de génération n'a pu être raccourci.

Programmes

J'ai mis la sortie sur Pastebin pour ceux d'entre vous qui n'ont pas envie d'exécuter le programme:

http://pastebin.com/Cs6WZUfb

Code Java que j'ai utilisé:

public class AsciiGen99 {

  public static void main(String[] args) {
    long totalsize = 0;
    for (int i = 0; i < 128; i++) {
      System.out.println("\n The program for ASCII code " + i + " is as follows:\n");
      String yea = find(i);
      if (yea != null) {
        System.out.println(yea);
        totalsize += yea.length();
      } else {
        String v = "99 9 9\n9 99 9";
        if (i != 0) {
          v += "\n99";
          for (int j = 0; j < i; j++) {
            v += " 99 9";
          }
        }

        v += "\n99";

        System.out.println(v);
        totalsize += v.length();
      }
    }
    System.out.println(totalsize);
  }

  public static String find(int i) {
    switch (i) {
      case '\0':
        return "99 9 9\n99";
      case '\1':
        return "99 9\n99";
    }
//    if (48 <= i && i <= 57) {
//      switch (i) {
//        case '0':
//          return "9 9 9\n9";
//        case '1':
//          return "9";
//        case '2':
//          return "999 9 9\n9 999 9\n999 999 9 999 9\n999";
//        case '3':
//          return "999 9 9\n9 999 9\n999 999 9 999 9 999 9\n999";
//        case '4':
//          return "999 9 9\n9 999 9\n999 999 9 999 9 999 9 999 9\n999";
//        case '5':
//          return "999 9 9\n9 999 9\n999 999 9 999 9 999 9 999 9 999 9\n999";
//        case '6':
//          return "99 9 9\n9 99 9\n999 99 9 99 9 99 9 99 9 99 9 99 9\n999";
//        case '7':
//          return "99 9 9\n9 99 9\n999 99 9 99 9 99 9 99 9 99 9 99 9 99 9\n999";
//        case '8':
//          return "99 9 9\n9 99 9\n999 99 9 99 9 99 9 99 9 99 9 99 9 99 9 99 9\n999";
//        case '9'://ironic
//          return "99 9 9\n9 99 9\n999 99 9 99 9 99 9 99 9 99 9 99 9 99 9 99 9 99 9\n999";
//      }
//    }
    int x, a;
    for (x = 0; x < 100000; x++) {
      a = i + 128 * x;
      String s = "" + a*9;
      if (containsOnly9(s) && (s.length() & 1) == 0) {
        return ("" + (a * 9));
      }
    }

    return null;
  }
  public static boolean containsOnly9(String s) {
    for (char c : s.toCharArray()) {
      if (c != '9' && c != ' ' && c != '\n' && c != '\r' && c != '\t') {
        return false;
      }
    }
    return true;
  }
}
bloo
la source
Vous devez réellement sortir le caractère, pas seulement le nombre. Tous les programmes avec 999à la fin doivent donc être corrigés.
Calvin's Hobbies
Ah, très bien alors, je vais arranger ça dans un instant.
bloo
Devrait être corrigé maintenant, sauf si j'ai oublié quelque chose. J'ai laissé le code d'origine mais j'ai commenté au cas où quelqu'un voudrait utiliser les chiffres comme ça. Pastebin a également été modifié.
bloo
Génial. Bien que pour certains, je pense que vous auriez pu simplement ajouter 99 999\n99(pour réaffecter 999à 99afin qu'il s'imprime en tant que personnage).
Calvin's Hobbies
1

Soustraction répétée, 65280

Une solution triviale à comparer. Continuez à soustraire 9 de 99, puis sortez. Exemple pour le caractère ASCII 10:

99 99 9
99

Il y a 128 programmes. Le premier programme comporte deux caractères (99), chacun après 8 caractères (99 99 9 \ n) de plus que le précédent.

Programme Python générant des programmes séparés par des lignes vides, et calculant le score:

score = 0
for n in range(128):
    program = "99 99 9\n" * n + "99"
    score += len(program)
    print(program + "\n")

print(score)
orlp
la source