Illisible , 2199 2145 2134 2104 2087 2084 octets
Prend en charge les deux k
/ j
ainsi que ▲
/ ▼
syntaxe.
Dans la bonne tradition Illisible, voici le programme formaté en fonte proportionnelle, pour brouiller la distinction entre apostrophes et doubles guillemets:
"" "" "" "" "" "" "" "" "." "" "" "" "" "" "" "" "" "" "" "" "" "" ". « » « « » » « » « « » » « » « « « » » » « » « » « « « » « » « » » » « » « » « » "" « » « « « » » » « « " « » « » « « « » « » « » « » » » « » » » « » « » « » « » « « « » « » » » « »" " « » « »« « » « » » « » « » « « » « » « » » « » « « » » « » « « » » « » « « » « « « » » » « » » « » « » « » "" « » « « » » « » « « »" » « » « » « » « » « " « » « » « « « » « » « » » » « « « » » » » "" « « « » « « « » « » « » « » » » « » « » « » » » « « « » » » « « « » » » « » « « » « » » « » « » »« « " » » « « « » » » « « « » » » « » « « » « » « » « » " » « » « » « » « « « » » » « « « » » » " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " « » « « « » « » « » » » « » « « » « » « » « »" » « » « » « »" « « » « « « » » » « » « » « » »« » « « « » « » « » « » » » « » « » « » « « « » « » « » « » » » « » « » « » « « « » « » « » « » » » « » « « » « » « » « » « « « » » » « » « » « » » « » "" « » « » « » « » « « « » » » « « « » » » « » « » « » " « » « « « » « « « » » » « « « » « « « » » » « » » » « » « » « » « » » » « » « » « »"" « » « « » » « » « « » » « » "" « » « « « » » » « « « » « « « » « » « » » » « » » » « » « » "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "Plusieurs plusieurs plusieurs plusieurs différentes plusieurs différentes plusieurs différentes différentes différentes plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs différentes" "" "" "" "" "" "" "" "plusieurs plusieurs plusieurs plusieurs plusieurs différentes différentes différentes différentes différentes différentes plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs différentes" "" "" plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurschions "" "" un plusieurs plusieurs plusieurs plusieursions "" "" un plusieurs "" un plusieurs plusieursions "un plusieursions unions un unions un unions un un" un un "un unions un un" un unchion "un" "un" un unions "comme un" unchion un un "" un "" un "" "" "". "" "".. « » « » « « » » « » « « » » « » « « » « » « »" » « » « " « » « « « » » » » " « » « « « » » »"« « " « » « » « » « « « » « » « » « « « » » » « « « » » » « « « » » » « » » » « « « » » » « » » » « » « « » « » « « « » « » « » » » « « « » » » « « « » » » « » » « » « » « » « » « « » « » « »" »" « « " » » « « « » » » « » « « » « » » « » « » « « » « » « » « » " » « » « » « » « « « » » » "« « » » « » « « « » « » « » » » « « « » » » « « « » « « « » » » « » « » « » » » « « « » » » "" « » "" "" "" "" "" "" "" "" "" "" "" "" "" "" "". Différentes plusieurs plusieurs plusieurs plusieurs différentes différentes différentes différentes "" "" plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs différentes différentes différentes "" "" plusieurs plusieurs plusieurs plusieurs plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs "" "" "" "" "" "" plusieurs différentes plusieurs différentes plusieurs différentes différentes différentes plusieurs différentes plusieurs plusieurs plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes déc plusieurs plusieurs plusieurs plusieurs plusieurs plusieursch plusieursions déc plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieursions plusieursions plusieursions plusieurs long plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieursions plusieursions long long long plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieursions plusieursions plusieursions plusieursions plusieursions plusieursions plusieursions plusieurs bien plusieurs bien plusieurs bien "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""« » « » « » « » « « » « » « »" » « » « « « » « » » » « » « « « » « » « » » » « « « » » » « " « » » « " « » « » « » » « » « » « » « « « » » » « « « » » » « » « « » « » « » « » " » « » « » « » « " » « « " » » « » « « » « » « » » « » « « » » « » « « « » « » « » « » » » « » « » « » « « » » « »« « »" » « » « « « » « » « » » » « « « » « « « » » » « » « » « » » » « " « » « « « » « » « » » » » « « » « » « » « « « » « » « » « » » » « » » « » « « » « » « » « « « » » » « » » « » « » "" « » « » « » « » « « » « » « » » « » « « » » « » « « » « « « » » » « » « » « » » « » « « » » « » " « » »« « » « » » « » « » « » « « » » « » « « « » « » « » « » » » « » « » « » « « » » « » "" « » « » « » "" « » « « » « « « » » » « » « » « » » « » « « » » « » "" « » « » « « « » « » « » « » » » « » « » « « « » » » « » « « » » « » « » « » « « « » » » « » « « » « » » « » « » « » " « »" « « » »« » « » « » « « « » « » « » « » » » « » « « » « » « « « » « » « » « » » » « » « » « »" » « » « »" « ' « » « « « » « » « » « » » » « » « » « » » « « » « » « »" » « » « « « » « » « » » » « » « » « » "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "". Différentes plusieurs plusieurs plusieurs plusieurs différentes différentes différentes différentes différentes plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs différentes nombreuses différentes nombreuses différentes différentes différentes plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs longions "" "" "" "plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs différentes plusieurs différentes différentes différentes" "" "" "" "" "" "" plusieurs plusieurs plusieurs plusieurs plusieurs différentes différentes différentes différentes différentes différentes plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs différentes plusieurs différentes différentes différentes différentes différentes différentes différents différents différents différents différents différents divers différents divers différents divers différents divers plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurschuions plusieurs plusieurs plusieurs plusieurs plusieurs plusieurschuions différentes plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurschrue plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieursions plusieursions plusieursions plusieurs long plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieursions plusieursions plusieursions plusieursions plusieurs bien long long plusieurs bien plusieurs bien plusieurs bien plusieurs bien "" mais bien "" "" "" « « " « » « » » » « " « » « « « » » » « « « » » » « « « » » » « » « » » « « » « « « » » »" » « » « « » » « » "" « » « » « « « » « » « » « » » » « » « » « » « « « » « » « » « » » » « » « » « »« « " « » « » « » » » « » « » « « « » « » « » « » » » « » « « » « » « » « » » « » « » « » « »" » « » « » « » « « » « » « » « » » « » « " »" « » « » « » « » « « « » « » « » » » « « « » « » « » » » « » « « » » « » « « » « » « » « « « » « « « » « » « » « » » » « » « » « » » »" » « » « » « »« ' « » « « « » » » « « « » » » « « « » » » « « « » » » « « « » » » « « « » » » « « « » » » » " « » "" « » « « » » « » « « » » « » « « » » « » « » « » « « « » » » « » « « » « » « »" » « » « »" « » « « » « « « » « » « » » » « » « » « »" » « » « « « » » » « " « » « » « » » « « »" »" " « »"" "" "" "" "" ""
C'était un défi incroyable. Merci d'avoir posté!
Explication
Pour avoir une idée de ce qu’il peut et ne peut pas faire, imaginez Brainfuck avec une bande infinie dans les deux sens, mais au lieu d’un pointeur de mémoire déplaçant une cellule à la fois, vous pouvez accéder à n’importe quelle cellule de mémoire en déréférencant un pointeur. Cela s’avère très pratique dans cette solution, bien que d’autres opérations arithmétiques - y compris modulo - doivent être effectuées à la main.
Voici le programme sous forme de pseudo-code avec les commentaires du réalisateur:
// Initialize memory pointer. Why 5 will be explained at the very end!
ptr = 5
// FIRST PASS:
// Read all characters from stdin, store them in memory, and also keep track of the
// current line number at each character.
// We need the +1 here so that EOF, which is -1, ends the loop. We increment ptr by 2
// because we use two memory cells for each input character: one contains the actual
// character (which we store here); the other will contain the line number at which the
// character occurs (updated at the end of this loop body).
while ch = (*(ptr += 2) = read) + 1:
// At this point, ch will be one more than the actual value.
// However, the most code-economical way for the following loop is to
// decrement inside the while condition. This way we get one fewer
// iteration than the value of ch. Thus, the +1 comes in handy.
// We are now going to calculate modulo 4 and 5. Why? Because
// the mod 4 and 5 values of the desired input characters are:
//
// ch %5 %4
// ^ 1
// v 2
// k 3
// j 4
// ▲ 0 2
// ▼ 0 0
//
// As you can see, %5 allows us to differentiate all of them except ▲/▼,
// so we use %4 to differentiate between those two.
mod4 = 0 // read Update 2 to find out why mod5 = 0 is missing
while --ch:
mod5 = mod5 ? mod5 + 1 : -4
mod4 = mod4 ? mod4 + 1 : -3
// At the end of this loop, the value of mod5 is ch % 5, except that it
// uses negative numbers: -4 instead of 1, -3 instead of 2, etc. up to 0.
// Similarly, mod4 is ch % 4 with negative numbers.
// How many lines do we need to go up or down?
// We deliberately store a value 1 higher here, which serves two purposes.
// One, as already stated, while loops are shorter in code if the decrement
// happens inside the while condition. Secondly, the number 1 ('""") is
// much shorter than 0 ('""""""""'""").
up = (mod5 ? mod5+1 ? mod5+3 ? 1 : 3 : 2 : mod4 ? 3 : 1)
dn = (mod5 ? mod5+2 ? mod5+4 ? 1 : 3 : 2 : mod4 ? 1 : 3)
// As an aside, here’s the reason I made the modulos negative. The -1 instruction
// is much longer than the +1 instruction. In the above while loop, we only have
// two negative numbers (-3 and -4). If they were positive, then the conditions in
// the above ternaries, such as mod5+3, would have to be mod5-3 etc. instead. There
// are many more of those, so the code would be longer.
// Update the line numbers. The variables updated here are:
// curLine = current line number (initially 0)
// minLine = smallest linenum so far, relative to curLine (always non-positive)
// maxLine = highest linenum so far, relative to curLine (always non-negative)
// This way, we will know the vertical extent of our foray at the end.
while --up:
curLine--
minLine ? minLine++ : no-op
maxLine++
while --dn:
curLine++
minLine--
maxLine ? maxLine-- : no-op
// Store the current line number in memory, but +1 (for a later while loop)
*(ptr + 1) = curLine + 1
// At the end of this, minLine and maxLine are still relative to curLine.
// The real minimum line number is curLine + minLine.
// The real maximum line number is curLine + maxLine.
// The total number of lines to output is maxLine - minLine.
// Calculate the number of lines (into maxLine) and the real minimum
// line number (into curLine) in a single loop. Note that maxLine is
// now off by 1 because it started at 0 and thus the very line in which
// everything began was never counted.
while (++minLine) - 1:
curLine--
maxLine++
// Make all the row numbers in memory positive by adding curLine to all of them.
while (++curLine) - 1:
ptr2 = ptr + 1
while (ptr2 -= 2) - 2: // Why -2? Read until end!
*ptr2++
// Finally, output line by line. At each line, we go through the memory, output the
// characters whose the line number is 0, and decrement that line number. This way,
// characters “come into view” in each line by passing across the line number 0.
while (--maxLine) + 2: // +2 because maxLine is off by 1
ptr3 = 5
while (ptr -= 2) - 5:
print (*((ptr3 += 2) + 1) = *(ptr3 + 1) - 1) ? 32 : *ptr3 // 32 = space
ptr = ptr3 + 2
print 10 // newline
Voilà pour la logique du programme. Maintenant, nous devons traduire cela en illisible et utiliser quelques astuces de golf plus intéressantes.
Les variables sont toujours déréférencées numériquement dans Unreadable (par exemple, a = 1
devient quelque chose comme *(1) = 1
). Certains littéraux numériques sont plus longs que d'autres. le plus court est 1, suivi de 2, etc. Pour montrer combien de nombres négatifs sont encore plus longs, voici les nombres de -1 à 7:
-1 '""""""""'""""""""'""" 22
0 '""""""""'""" 13
1 '""" 4
2 '""'""" 7
3 '""'""'""" 10
4 '""'""'""'""" 13
5 '""'""'""'""'""" 16
6 '""'""'""'""'""'""" 19
7 '""'""'""'""'""'""'""" 22
Clairement, nous voulons affecter la variable n ° 1 à celle qui apparaît le plus fréquemment dans le code. Dans la première boucle while, c’est bien, ça mod5
revient 10 fois. Mais nous n’avons plus besoin de la mod5
fin de la première boucle while, nous pouvons donc réaffecter le même emplacement mémoire aux autres variables que nous utiliserons plus tard. Ce sont ptr2
et ptr3
. Maintenant, la variable est référencée 21 fois au total. (Si vous essayez de compter vous-même le nombre d'occurrences, n'oubliez pas de compter a++
deux fois, une fois pour obtenir la valeur et une fois pour la définir.)
Il n’ya qu’une autre variable que nous puissions réutiliser; après avoir calculé les valeurs modulo, ch
n'est plus nécessaire. up
et dn
revenez le même nombre de fois, donc ça va. Fusionnons ch
avec up
.
Cela laisse un total de 8 variables uniques. Nous pourrions affecter les variables de 0 à 7, puis démarrer le bloc de mémoire (contenant les caractères et les numéros de ligne) à 8. Mais! Puisque 7 a la même longueur dans le code que -1, nous pourrions également utiliser les variables -1 à 6 et démarrer le bloc mémoire à 7. De cette manière, toute référence à la position de départ du bloc mémoire est légèrement plus courte dans le code! Cela nous laisse avec les missions suivantes:
-1 dn
0 ← ptr or minLine?
1 mod5, ptr2, ptr3
2 curLine
3 maxLine
4 ← ptr or minLine?
5 ch, up
6 mod4
7... [data block]
Maintenant, ceci explique l’initialisation tout en haut: c’est 5 car c’est 7 (le début du bloc mémoire) moins 2 (l’incrément obligatoire dans la première condition while). Il en va de même pour les deux autres occurrences de 5 dans la dernière boucle.
Notez que, puisque 0 et 4 ont la même longueur de code ptr
et minLine
peuvent être alloués dans les deux sens. ... ou pourraient-ils?
Qu'en est-il du mystérieux 2 dans l'avant-dernière boucle while? Cela ne devrait-il pas être un 6? Nous voulons seulement décrémenter les nombres dans le bloc de données, non? Une fois que nous atteignons 6, nous sommes en dehors du bloc de données et nous devrions nous arrêter! Ce serait une faille de sécurité liée à un défaut de débordement de mémoire tampon!
Eh bien, réfléchissez à ce qui se passe si nous ne nous arrêtons pas. Nous décrémentons les variables 6 et 4. La variable 6 est mod4
. Ce n'est utilisé que dans la première boucle while et n'est plus nécessaire ici, donc pas de mal. Qu'en est-il de la variable 4? Que pensez-vous, la variable 4 ptr
devrait-elle être ou devrait-elle être minLine
? C'est vrai, minLine
n'est plus utilisé à ce stade non plus! Ainsi, la variable n ° 4 est minLine
et nous pouvons la décrémenter en toute sécurité et ne pas endommager!
MISE À JOUR 1! Golfé de 2199 à 2145 octets en réalisant que dn
peut également être fusionné avec mod5
, même si mod5
est toujours utilisé dans le calcul de la valeur pour dn
! La nouvelle affectation de variable est maintenant:
0 ptr
1 mod5, dn, ptr2, ptr3
2 curLine
3 maxLine
4 minLine
5 ch, up
6 mod4
7... [data block]
MISE À JOUR 2! Passez de 2145 à 2134 octets en réalisant que, depuis mod5
est maintenant dans la même variable que dn
, qui est comptée à 0 dans une boucle while, il mod5
n'est plus nécessaire de l'initialiser explicitement à 0.
MISE À JOUR 3! Golfé de 2134 à 2104 octets en réalisant deux choses. Premièrement, bien que l’idée du «modulo négatif» en vaille la peine mod5
, le même raisonnement ne s’applique pas mod4
car nous n’effectuons jamais de tests, mod4+2
etc. Par conséquent, passer mod4 ? mod4+1 : -3
à mod4 ? mod4-1 : 3
nous prend 2110 octets. Deuxièmement, puisque mod4
vaut toujours 0 ou 2, nous pouvons initialiser mod4
à 2 au lieu de 0 et inverser les deux ternaires ( mod4 ? 3 : 1
au lieu de mod4 ? 1 : 3
).
MISE À JOUR 4! Passez de 2104 à 2087 octets en réalisant que la boucle while qui calcule les valeurs modulo est toujours exécutée au moins une fois. Dans ce cas, Unreadable vous permet de réutiliser la valeur de la dernière instruction dans une autre expression. Ainsi, au lieu de ce que while --ch: [...]; up = (mod5 ? mod5+1 ? [...]
nous avons maintenant up = ((while --ch: [...]) ? mod5+1 ? [...]
(et dans cette boucle while, nous calculons d’ mod4
abord, c’est mod5
donc la dernière déclaration).
MISE À JOUR 5! Je passe de 2087 à 2084 octets en réalisant qu'au lieu d'écrire les constantes 32
et 10
(espace et nouvelle ligne), je peux stocker le nombre 10 dans la variable # 2 (maintenant inutilisée) (appelons-le ten
). Au lieu d' ptr3 = 5
écrire ten = (ptr3 = 5) + 5
, alors 32
devient ten+22
et print 10
devient print ten
.