Ilegível , 1830 1796 1791 1771 1762 1745 1736 1727 1626 1606 1577 bytes
A saída está em ordem alfabética inversa ( z
para a
), mas de acordo com suas regras que parecem ser permitidas.
'"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""'""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '""' "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '"" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " """ '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" '""' "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""'"" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ '""' "" "" "'" "" "" "" "" "" "" """" '""' "" "" "'" "" "" "" "" "" "" ""
Explicação
Primeiro, para ter uma impressão do que o ilegível pode fazer, aqui está sua operação básica:
- Você tem uma fita infinita de células inteiras de tamanho arbitrário
- Você não tem um ponteiro de memória como no Brainfuck; em vez disso, você desrefere as células pela localização na fita. Isso significa que você pode "ler o valor # 4" ou "ler o valor # (ler o valor # 4)" (desreferência dupla).
- Você pode apenas ler ou gravar células de memória (não diretamente incrementadas / diminuídas como no Brainfuck).
- Você pode aumentar / diminuir os valores dentro de uma expressão. Assim, para incrementar uma célula de memória que você tem que ler , incremento , gravação , ou diferentemente colocar:
write(x, inc(read(x)))
.
- Existem loops while e condicionais ternários que podem apenas verificar zero vs. diferente de zero.
Este programa usa a fita da seguinte maneira. Os nomes das variáveis serão usados no pseudocódigo posteriormente abaixo. Além disso, isso documenta a primeira versão (que era de 1830 bytes); veja as edições na parte inferior do que mudou desde então.
- Célula 0: variável
q
- A célula 1: variáveis
a
, p
,ch
- Célula 2: variáveis
hash
,v
- Célula 3: variáveis
b
,r
- Célula 4: variáveis
aa
,l
- Célula 5: permanece 0 para marcar o "final" da sequência de dígitos decimais
- Células 6–95: armazena a sequência de dígitos decimais ao contrário
- Células 96–121: armazena o número de votos a serem deduzidos dos usuários
a
(96) a z
(121) (o código ASCII da letra menos um).
- Células 4657-7380: lembre-se de quais combinações de eleitor / eleitor foram encontradas quantas vezes. Essas células têm apenas 4 valores possíveis:
0
= ainda não visto, -1
= visto uma vez, -2
= visto duas vezes, -3
= visto qualquer número de vezes mais que 2.
O algoritmo essencialmente procede da seguinte maneira:
- Continue lendo pares de caracteres
a
e b
. Calcule o valor do hash (a-2)*(a-1)+b-1
, que é exclusivo para cada combinação de letras a – z.
- Verifique a célula de memória com esse valor de hash (
*hash
). Se for -3
, o usuário já está qualificado para a remoção de votos, então aumente *(b-1)
. Caso contrário, diminua *hash
. Se for agora -3
, o usuário acabou de se qualificar para a remoção de votos após três ocorrências, então aumente *(b-1)
em 3
.
- Depois disso, repasse os caracteres na ordem inversa (
z
para a
) e produza os que precisam de dedução de votos. Isso requer divisão inteira manual por 10 para converter o número em dígitos decimais.
Com tudo isso esclarecido, é assim que o programa se parece com pseudocódigo:
// Read pairs of characters
while (a = read) + 1 {
b = read
// Calculate hash = (a-1)*(a-2)/2 + b-1
// This also sets a = b-1
hash = 0
while --a {
aa = a
while --aa {
++hash
}
}
while --b {
++a
++hash
}
// If this combination has just been seen for the third time,
// increment *a by 3; if more than third time, increment *a by 1
*a = (*hash + 3) ? ((--*hash) + 3 ? *a : (*a+3)) : (*a+1)
}
// Loop through the characters z to a
l = 27
while --l { // l loops from 26 to 1 (not 0)
(v = *(ch = l + 95)) ? { // 'a' is ASCII 97, but cell 96
print (ch+1) // print the votee
// Now we need to turn the number v into decimal.
// p points to where we are storing decimal digits.
p = 5
while v {
// Integer division by 10 (q=quotient, r=remainder)
r = (q = 0)
while v {
--v
(++r - 10) ? 1 : {
r = 0
++q
}
}
// Store digit ASCII character
*(++p) = r + 48 // 48 = '0'
v = q
}
// Now output all the digit ASCII characters in reverse order
while *p {
print *(--p + 1)
}
} : 1
}
Edit 1, 1830 → 1796: Percebi que posso reutilizar o valor de retorno de um loop while em um só lugar.
Edit 2, 1796 → 1791: Acontece que o programa é um pouco menor se, em vez de usar as células 6–95, eu armazenar os dígitos decimais nas células com números negativos (–1 em diante). Como um bônus adicional, o programa não está mais limitado a 10 votos!
Edit 3, 1791 → 1771: Em vez de atribuir o resultado de *(ch = l + 95)
a v
, agora o atribuo a ele q
e depois movo a atribuição v = q
para a condição while, levando o código para 1777 bytes. Em seguida, troque o local de q
e v
na fita, porque q
agora é 1 mais comum que v
.
Edit 4, 1771 → 1762: Duh. Inicializar hash
para 1 em vez de 0 é 9 bytes mais curto. O código hash agora é mais 1, o que não importa.
Edit 5, 1762 → 1745: Se eu inicializar q
e r
para 1 em vez de 0, tenho que espalhar alguns -1
s em alguns lugares para torná-lo correto e tudo parece cancelar - exceto que o while v { --v; [...] }
loop agora precisa executar uma iteração a menos, o que posso fazer dizendo while --v { [...] }
, que é 26 caracteres menor.
Edit 6, 1745 → 1736: Em vez de { r = 1; ++q }
, podemos escrever q = *((r = 1)+1)+1
. Isso se baseia no fato de q
estar no slot variável nº 2. Se estivesse no slot 1, isso seria ainda mais curto, mas o programa inteiro seria mais longo no geral.
Edit 7, 1745 → 1727: Reverse Edit 6 e, em vez disso, conseguiu salvar salvando o loop while mais interno na expressão que calcula o código ASCII do dígito, que também termina em 1736 bytes ... mas salvou uma instrução de decremento (9 bytes ) alterando ((++r) - 11) ? r :
para (r - 10) ? ++r :
.
Edit 8, 1727 → 1626: Retrabalhou o cálculo de hash. Agora ele usa um loop while a menos. Agora, as localizações das células estão com seus códigos ASCII reais (não são mais 1 desativadas). Reorganizou as variáveis para diferentes locais na fita porque agora elas ocorrem com diferentes frequências.
Edite 9, 1626 → 1606: Inlining mais louco. O corpo do primeiro loop while agora se parece com isso:
// b = next char
*(b = (hash = read)) = {
// hash = b + (a-1)*(a-2)/2
while (a2 = --a) {
while --a2 {
++hash
}
}
// If this combination has just been seen for the third time,
// increment *b by 3; if more than third time, increment *b by 1
(*hash + 3) ? ((--*hash) + 3 ? *b : (*b+3)) : (*b+1)
}
e a atribuição de variáveis agora mudou quase completamente.
Editar 10, 1606 → 1577: Eu observei que a
e a2
são ambos decrementado a 0 enquanto em laços, de modo que se podia emparelhar p
com qualquer um daqueles, mas não com ch
, não seria necessário para inicializar p
a 0
(que custa 29 bytes). Acontece que eu posso fazer isso trocando p
e r
. As mais recentes atribuições de variáveis (e sua frequência de ocorrência no código) são agora:
0 = v (3) (total 3)
1 = hash (6), r (5), ch (2) (total 13)
2 = b (4), q (5) (total 9)
3 = a (3), p (5) (total 8)
4 = a2 (3), l (4) (total 7)
nanananananananabatman
o caso de teste.