Jogando golfe todos os caracteres ASCII em 99

11

99 é uma linguagem de programação que inventei no início desta semana para o meu desafio. Escreva um intérprete para 99 . (Inventado, mas nunca necessário para implementar, graças a meia dúzia de vocês.;)) A especificação completa do idioma está nesse desafio, então não estou me preocupando em repassar tudo aqui.

Em 99, você pode imprimir caracteres ASCII individuais para stdout, mas devido às restrições do idioma, nem sempre é claro como imprimir um caractere específico da maneira mais concisa possível.

Para cada um dos 128 caracteres ASCII, escreva um programa 99 que não aceite nenhuma entrada e produz esse único caractere. Você pode codificar uma ou todas essas respostas manualmente ou pode escrever outro programa (em qualquer idioma que desejar) para gerá-las para você.

A soma dos caracteres em cada um dos seus 128 99 programas é a sua pontuação. A pontuação mais baixa vence. As novas linhas contam como um caractere.

Lembre-se, em 99 , apenas variáveis ​​de tamanho par, como 9999caracteres ASCII de saída (variáveis ​​de tamanho ímpar, números inteiros de saída). Seu valor é dividido por 9 e, em seguida, utilizado o mod 128, portanto, os valores não precisam estar em um determinado intervalo para mapear para caracteres ASCII. Por exemplo, os valores internos 297, 1449 e -855 correspondem ao caractere, !porque quando são divididos por 9 e tomados pelo mod 128, todos se tornam 33, que é o código de caractere !.

Se você precisar de um intérprete para 99 , sugiro a resposta Python do Mac .

Eu sei que disse que meu próximo desafio seria mais interativo, mas ainda estou trabalhando nas coisas para esse.

Passatempos de Calvin
fonte

Respostas:

7

Uma tarefa, 2075 (ideal)

Esse deve ser o valor ideal (a menos que eu tenha um grande erro de raciocínio ou meus testes sejam uma porcaria).

Em primeiro lugar. Existem apenas 7 números diferentes (mod 128) que você pode expressar em 99. Todos os valores de 7 ou mais 9 são avaliados para o mesmo número 71. (Como 10 ^ 8 mod 128 == 0, 10 ^ 9 mod 128 == 0, ...)

Se um dos 4 valores puder ser expresso com um número par de noves, a saída desse número é claramente a solução ideal.

Caso contrário, tento alcançar o número com uma declaração de atribuição (atribuir a 99) e imprimir 99. Como se vê, o tamanho máximo do programa com essa abordagem é 22 caracteres. Claramente usar Goto leva definitivamente mais do que isso. A única possibilidade de uma solução de uma tarefa ser vencida é uma solução com duas tarefas. Eu testei isso (espero que sem erros, o código para isso seja bastante confuso) e não encontrei solução para nenhum caractere ASCII.

Portanto, apenas verificar os 4 números diretos e a abordagem de atribuição única deve ser suficiente para encontrar a solução ideal. O seguinte programa Python (compatível com 2 e 3) gera todos os programas e resume seus comprimentos. Ele usa uma abordagem simples da IDA *.

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))

A saída é da seguinte forma:

....
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
....

Você pode encontrar a saída completa em: http://pastebin.com/bKXLAArq

O caractere com o programa mais curto (2 caracteres) tem vertical tab - 11a duração de 2, os caracteres com os programas mais longos (22 caracteres) são bell - 7e A - 65.

A soma de todos os programas é 2075.

E, a propósito, usei o interpretador k / q do tmartin . Eu tenho alguns problemas com os outros (Python, Perl, CJam). Não tenho certeza se foi minha culpa.

Jakube
fonte
Ajudaria os implementadores de intérpretes se você pudesse descrever quais problemas teve. Ótima resposta.
Coredump
3

Uma variedade de técnicas, 42109

Para os números, em vez de calcular o caractere ASCII grande, apenas calculei o valor do número. Você disse apenas ser capaz de produzir o personagem, então isso ainda deve funcionar.

EDIT: Mudou os números para usar os caracteres ASCII, então desconsidere isso. Deixei o código numérico original no código Java, mas comentei caso alguém quisesse usá-lo.

Alguns deles eu fiz manualmente, a maioria acabei de escrever um programa para digitar.

Elas são compostas de 1 a 4 linhas cada, portanto, são bastante amigáveis ​​apenas copiar e colar em um programa. Note-se que eles não funcionam em sucessão devido ao meu código gerado não preservar estados variáveis.

A técnica mais comum usada aqui foi a mesma da abordagem do orlp:

Continue subtraindo 9 de 99 e depois a saída.

Minha versão difere usando alguns casos personalizados e compondo grande parte da matemática em apenas uma linha. Casos personalizados são exatamente onde o personagem pode ser representado com apenas um monte de 9 e nenhuma matemática ou meu código de geração podem ser encurtados.

Programas

Coloquei a saída no Pastebin para aqueles que não desejam executar o programa:

http://pastebin.com/Cs6WZUfb

Código Java que usei:

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
fonte
Você realmente precisa exibir o caractere, não apenas o número. Portanto, todos os programas 999no final precisam ser corrigidos.
Calvin's Hobbies
Ah, tudo bem então, eu vou consertar isso em um momento.
bloo
Deve ser corrigido agora, a menos que eu tenha perdido alguma coisa. Deixei o código original, mas comentei caso alguém quisesse usar os números assim. Pastebin também foi editado.
bloo
Ótimo. Embora, para alguns, eu acho que você poderia ter adicionado 99 999\n99(para reatribuir 999para 99que seja impresso como um personagem).
Calvin's Hobbies
1

Subtração repetida, 65280

Uma solução trivial para comparar. Continue subtraindo 9 de 99 e depois a saída. Exemplo para o caractere ASCII 10:

99 99 9
99

Existem 128 programas. O primeiro programa tem dois caracteres (99), cada um depois com 8 caracteres (99 99 9 \ n) a mais que o anterior.

Programa Python que gera programas separados por linhas vazias e pontuação de computação:

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

print(score)
orlp
fonte