Haskell , 1080 1033 octets
;
f=
g
ij=f
a =hi
hi = g
hij= ij
g ' ' =0
g '"' =0;
g '$' =0;
g '&' =0-0
g '(' =0-0-0
g '*' =0-0-0;
g ',' =0-0-0;
g '.' =0-0-0-0
g '0' =0-0-0-0-0
g '2' =0-0-0-0-0;
g '4' =0-0-0-0-0;
g '6' =0; g '8' =0
g ':' =0; g '<' =0-0
g '>' =0; g '@' =0-0;
g 'B' =0; g 'D' =0-0;
g 'F' =0; g 'H' =0-0-0
g 'J' =0; g 'L' =0-0-0-0
g 'N' =0; g 'P' =0-0-0-0;
g 'R' =0; g 'T' =0-0-0-0;
g 'V' =0; g 'X' =0-0-0-0-0
g 'Z' =0; g '^' =0; g '`' =0
g 'b' =0; g 'd' =0; g 'f' =0;
g 'h' =0; g 'j' =0; g 'l' =0;
g 'n' =0; g 'p' =0; g 'r' =0-0
g 't' =0; g 'v' =0; g 'x' =0-0-0
g 'z' =0; g '\92' =0-0; g '|' =0;
g '~' =0; g y = 1 ;z=0; i(-0)z=z;
i m('\10':y ) ="y"; ; ; ; ; ; ; ;
i m(mnmnmnmnm:y ) = i(m - 1 ) y ; ;
i k m ="y"; ; k i [ ] =01<1010101010;
k m('\10':y ) = k(m + 1 )(i m y ) ; ;
k m y =01>10; m o = k 1$'\10':o ; ; ;
o i('\10':y ) = o i y ; ; ; ; ; ; ; ; ;
o i(k:y )|g k<i = o(1 - i ) y ; ; ; ; ; ;
o i(k:y )|g k>i = o(1 - i ) y ; ; ; ; ; ;
o i [ ] =01<10; o i y =01>10;v=01>10101010
s y|o 1 y = m y|o(-0) y = m y ; s y =v; ; ;
Essayez-le en ligne!
Explication
Cela a été une tâche très intéressante pour Haskell.
Parité
Pour commencer, nous avons besoin d'un moyen de déterminer si un caractère a un point de code pair ou impair. La façon normale de le faire est d'obtenir le point de code et de le modifier par 2. Cependant, comme vous le savez peut-être, obtenir le point de code d'un caractère nécessite une importation qui, en raison de la restriction de la source, signifie qu'il ne peut pas être utilisé. Un Haskeller plus expérimenté penserait à utiliser la récursivité. Charfont partie de la Enumclasse de type afin que nous puissions obtenir leurs prédécesseurs et successeurs. Cependant pred, ils succsont également inutilisables car ils n'alternent pas la parité des octets.
Donc, cela nous laisse assez coincés, nous ne pouvons pratiquement pas faire de manipulation avec les caractères. La solution est de tout coder en dur. Nous pouvons représenter (la plupart) même les caractères comme des littéraux, les probabilités avec lesquelles nous avons des problèmes parce qu'ils 'sont étranges, donc ils ne peuvent pas être à côté du caractère lui-même, ce qui rend le littéral impossible d'exprimer la plupart des caractères impairs. Nous codons donc en dur tous les octets pairs, puis ajoutons un catch all pour les octets impairs à la fin.
Les octets problématiques
Vous pouvez remarquer qu'il existe certains octets pairs pour lesquels des littéraux ne peuvent pas être créés en les encapsulant entre guillemets simples. Ce sont les non imprimables, les nouvelles lignes et \. Nous n'avons pas à nous soucier des non imprimables, tant que nous n'en utilisons aucun, nous n'avons pas besoin de le vérifier. En fait, nous pouvons toujours utiliser d'étranges non imprimables, comme tab, je n'en ai tout simplement pas besoin. Le retour à la ligne peut être ignoré car il sera de toute façon supprimé du programme. (Nous pourrions inclure la nouvelle ligne, car son point de code est plutôt pratique, mais nous n'en avons pas besoin). Cela laisse \, a maintenant \le point de code 92, qui est commodément un nombre impair suivi d'un nombre pair, \92alterne donc entre les evens et les cotes donc le littéral'\92'est parfaitement valable. Plus tard, lorsque nous aurons besoin de représenter une nouvelle ligne, nous remarquerons qu'elle a heureusement cette même propriété '\10'.
Problèmes d'espacement
Maintenant, pour commencer à écrire du code réel, nous devons pouvoir mettre un nombre important de caractères sur une seule ligne. Pour ce faire, j'ai écrit la casquette:
;
f=
g
ij=f
a =hi
hi = g
hij= ij
La casquette ne fait rien d'autre que d'être Haskell valide. J'avais initialement espéré faire des définitions qui nous aideraient dans le code plus tard, mais ce n'est pas le cas. Il existe également des moyens plus simples de créer un plafond, par exemple des espaces et des points-virgules, mais ils n'économisent pas d'octets de cette manière, je n'ai donc pas pris la peine de le modifier.
Hardcoder
Alors maintenant que j'ai assez d'espace sur une ligne, je commence à coder en dur les valeurs. C'est surtout assez ennuyeux, mais il y a quelques choses intéressantes. Pour une fois que les lignes commencent à devenir encore plus longues, nous pouvons utiliser ;pour mettre plusieurs déclarations sur une ligne, ce qui nous permet d'économiser une tonne d'octets.
La seconde est que, comme nous ne pouvons pas toujours commencer une ligne avec un de gtemps en temps, nous devons indenter un peu les lignes. Maintenant, Haskell se soucie vraiment de l'indentation, donc il s'en plaindra. Cependant, si la dernière ligne avant la ligne en retrait se termine par un point-virgule, cela sera autorisé. Pourquoi? Je n'ai pas le moindre, mais ça marche. Il suffit donc de se rappeler de mettre les points-virgules à la fin des lignes.
Blocs fonctionnels
Une fois le hardcoder terminé, la navigation se fait en douceur jusqu'à la fin du programme. Nous devons construire quelques fonctions simples. Je construis d'abord une version de drop, appelée i. iest différent de ce dropque si nous essayons de passer au-delà de la fin de la chaîne, il retourne simplement "y". iest différent de drop également en ce que s'il tente de supprimer une nouvelle ligne, il reviendra "y", ceux-ci seront utiles car plus tard, lorsque nous vérifierons que le programme est un triangle, cela nous permettra de revenir Falselorsque la dernière ligne n'est pas terminée, ou lorsque une ligne se termine tôt.
Ensuite, nous avons kqui vérifie en fait qu'une chaîne est triangulaire. kest assez simple, il faut un nombre et une chaîne . Si est vide, il revient . Si la chaîne commence par une nouvelle ligne, elle supprime la nouvelle ligne et caractères du premier plan. Il rappelle ensuite avec et la nouvelle chaîne. Si la chaîne ne commence pas par une nouvelle ligne, elle retourne .s s n n + 1nssTruenkn+1False
Nous faisons ensuite un alias pour k, m. mest juste kavec 1dans le premier argument, et une nouvelle ligne est ajoutée au second argument.
Ensuite, nous avons o. oprend un nombre et une chaîne. Il détermine si les octets de chaîne (ignorant les nouvelles lignes) alternent en parité (en utilisant notre g) en commençant par le numéro d'entrée.
Enfin, nous avons squi fonctionne oavec les deux 1et 0, si l'un ou l'autre réussit, il s'en remet m. S'il échoue, il revient simplement False. C'est la fonction que nous voulons. Il détermine que l'entrée est triangulaire et alternée.