Retina , 530 220 210 202 201 201 193 191 187 185 (184) octets
Crédits à randomra pour la sauvegarde de 3 octets! (Et ouvrant la voie pour un couple de plus.)
+`\.(\d)(.+)( .+)
$1.$2_$3_
\b
#
+`(\d*)#((((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|\w)
$1$1$1$1$1$1$1$1$1$1$3$4$5$6$7$8$9$10$11#
\d
11
(?=(1*)\1)[^.]
$1
^(1+)\.\1{90000}1+
Retina!
1.+
Trash!
Pour le comptage d'octets, chaque ligne est placée dans un fichier séparé, mais vous pouvez exécuter le code ci-dessus tel quel à partir d'un seul fichier en appelant Retina avec l' -s
indicateur.
Cela attend d'abord la densité (qui doit contenir un point décimal, même s'il s'agit d'un point final), suivie de la largeur et de la hauteur, c'est-à-dire d w h
.
C'est un peu lent. Je ne voudrais pas essayer la plupart des cas de test donnés, car il durera des siècles. Cependant, vous pouvez vérifier qu'il fonctionne correctement avec les cas de test
19. 4096 2160 -> Trash!
1. 180 240 -> Trash!
1. 181 240 -> Retina!
1. 180 241 -> Retina!
0.04 10 10 -> Retina!
En gros, après avoir multiplié tous les nombres pour que la densité soit un entier, vous ne voulez pas que la largeur et la hauteur aient plus de 4 chiffres.
Bien que ce soit lent, il est tout à fait exact ... il n'y a pas de problèmes de virgule flottante ou quelque chose comme ça. Toute l'arithmétique utilise des entiers (unaires).
En principe, je pourrais supprimer un octet de plus: ^
on peut l'omettre, mais cela Trash!
ralentira horriblement les tests en raison du nombre excessif de retours en arrière.
Explication
Tout d'abord, réorganisons l'inégalité pour éviter les opérations en virgule flottante:
√(w2 + h2) / d > 300
√(w2 + h2) > 300 d
w2 + h2 > 90000 d2
On peut aussi remarquer que ceci est invariant en multipliant w
, h
et d
par le même nombre x
:
w2 + h2 > 90000 d2
(x w)2 + (x h)2 > 90000 (x d)2
x2 (w2 + h2) > 90000 x2 d2
w2 + h2 > 90000 d2
Il y a plusieurs façons de mettre en correspondance un nombre unaire, mais nous allons utiliser l'identité
n2 = Σi=1..2n ⌊i/2⌋
Cela nous donne un moyen de résoudre le problème en utilisant uniquement l'arithmétique entière (représentant des entiers dans unaire).
Passons en revue le code. Chaque paire de lignes est une substitution de regex.
+`\.(\d)(.+)( .+)
$1.$2_$3_
Cela déplace à plusieurs reprises le point décimal de la densité vers la droite tout en multipliant la largeur et la hauteur par 10 (valeur x
ci - dessus). Cela permet de s'assurer que tous les nombres sont des entiers. Au lieu d’ajouter des zéros, je l’ajoute _
, ce que je considérerai comme zéro plus tard. (Ceci est une astuce de golf, car sinon, je devrais écrire ...${3}0
pour éviter toute ambiguïté $30
.) Le +
texte placé devant la regex indique à Retina de répéter cette substitution jusqu'à ce que le résultat cesse de changer (ce qui est le cas lorsque le motif ne correspond plus). .
\b
#
Nous préparons les trois chiffres pour la conversion en unaire maintenant. En principe, nous avons besoin d’un marqueur (le #
) devant chaque numéro, mais il est plus court d’ajouter un à la fin de chaque numéro, ce qui n’affectera pas l’étape de conversion.
+`(\d*)#((((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|\w)
$1$1$1$1$1$1$1$1$1$1$3$4$5$6$7$8$9$10$11#
C'est la conversion au unaire, utilisant une astuce développée par dan1111 . Essentiellement, je traduis chaque chiffre en un chiffre de rep, tout en multipliant les chiffres existants par 10 (en déplaçant le #
marqueur à droite dans le processus). Cette représentation binaire sera un mélange de chiffres différents, mais le nombre total sera égal à la valeur de l'entier original. Notez le \w
à la fin - normalement c'est juste 0
, mais nous voulons _
aussi traiter comme zéro (ce qui est considéré comme un caractère de mot dans une regex).
\d
11
Nous transformons chaque chiffre en deux 1
, ce qui permet a) de nous assurer que tous les chiffres sont identiques (ce qui sera nécessaire ultérieurement) et b) de doubler chacun des nombres.
(?=(1*)\1)[^.]
$1
Cela fait deux choses: il met tous les nombres au carré (ou plutôt la moitié de chaque nombre, en calculant une somme 2n
), et ajoute les carrés résultants de la largeur et de la hauteur. Notez que [^.]
correspond à 1
s, aux #
marqueurs et aux espaces. Si c'est un #
ou un espace, le lookahead ne capturera rien, ce qui signifie que tous ceux-ci sont simplement supprimés, c'est-à-dire que les résultats pour la largeur et la hauteur sont concaténés / ajoutés. Le point décimal .
reste à séparer le résultat d
de ceux-ci. Si [^.]
correspond à un à la 1
place, le lookahead garantit que nous capturons la moitié du 1
s après celui-ci (arrondi au bas) dans le groupe 1
. Ceci calcule la somme que j'ai mentionnée ci-dessus, qui donnera alors le carré du nombre original.
^(1+)\.\1{90000}1+
Retina!
La chaîne est maintenant (en unaire), alors , ensuite (en unaire). Nous voulons savoir si le premier nombre unaire est plus court que le second. Nous pouvons facilement faire cette multiplication en utilisant une syntaxe de groupe de capture et de répétition. Nous utilisons (au lieu de ) par la suite pour nous assurer que le deuxième nombre est réellement supérieur à celui-ci et pas simplement égal. Si c'est le cas, nous remplaçons tout cela par .d2
.
w2 + h2
90000
{n}
1+
1*
Retina!
1.+
Trash!
Si le second nombre n'était pas assez grand, alors l'étape précédente n'aura rien changé et la chaîne commencera toujours par un 1
. Si c'est le cas, nous remplaçons simplement la chaîne entière par Trash!
et nous avons terminé.