Contexte
Dans certains futurs possibles, le monde convertira leurs systèmes numériques de la décimale (base 10 ou b10
) à une autre base (binaire b2
, octale b8
, hexadécimale b16
ou même unaire b1
, auquel cas nous sommes foutus!). Ainsi, en prévision de cet éventuel événement qui changera le monde, vous décidez d'éprouver à la base tous vos programmes. Cela peut être fait en utilisant uniquement des 0
s et 1
s singuliers conjointement avec des opérateurs pour remplacer les constantes numériques existantes.
Cependant, il n'y a qu'un seul problème: vous avez une tonne de programmes à modifier, et la conversion manuelle de chaque nombre en une expression prendrait des semaines! Ainsi, vous décidez d'écrire un programme (ou une fonction) pour décider pour vous quelle expression doit remplacer chaque nombre.
Contribution
L'entrée sera un entier positif. Votre code doit être capable de gérer n'importe quel entier jusqu'à 1000.
(Si votre code prend en charge les décimales et / ou les entrées négatives, voir Score ci-dessous.)
Production
Votre code doit générer une expression qui évalue l'entrée en au moins une langue. Cela peut être n'importe quelle langue; il ne doit pas nécessairement être le même que celui dans lequel votre programme ou fonction est écrit. De plus, cette expression n'a pas besoin d'être un programme ou une fonction complète.
Pour plus de clarté, la sortie peut contenir l'une de ces opérations:
- incrémenter / décrémenter
- ajouter / somme
- soustraire / annuler
- multiplier / doubler (seulement si cela n'implique pas directement le nombre
2
!) - diviser / modulo
- exposants / logarithmes
- square / sqrt (encore une fois, seulement si ceux-ci n'impliquent pas directement le nombre
2
!) - opérations au niveau du bit (bOR, BAND, bNOT, bXOR, décalage de bits)
- définition / obtention de variables
- manipulation de pile
Vous ne pouvez pas utiliser eval()
ou toute fonction similaire dans la sortie. Vous ne pouvez pas non plus utiliser dans la sortie des fonctions qui exécutent une ou plusieurs actions autres que celles mentionnées ci-dessus.
Oh, et encore une chose: puisque nous voulons que la sortie soit valide dans autant de bases que possible, les seules constantes numériques qu'elle peut contenir sont 0
et 1
. Des nombres tels que 10
(dix) sont interdits, sauf si la langue l'interprète comme un 1
et un 0
. L'utilisation de chaînes pour contenir des nombres n'est pas autorisée non plus, tout comme l'utilisation de caractères tels que CJam A
- K
(qui représentent 10
- 20
).
Cas de test
(Toutes les sorties sont en JavaScript, mais peuvent fonctionner dans d'autres langues.)
Entrée 1:
2
Sortie possible 1:
1+1
Entrée 2:
13
Sortie possible 2:
(a=1+1+1)*a+a+1
Entrée 3:
60
Sortie possible 3:
(b=(a=1+1+1+1)*a)*a-a
Entrée 4:
777
Sortie possible 4:
(c=(b=((a=1+1+1+1)*a-a+1)*a)*a+b)+c+c-a+1
Entrée 5:
1000
Sortie possible 5:
Math.pow((a=1+1+1)*a+1,a)
Notation
Le but de ce défi est de raccourcir autant que possible la sortie de votre code. Votre score sera calculé de cette manière:
Score de base: nombre moyen d'octets de toutes les sorties pour les entiers 1 à 1000.
Score décimal: si votre code prend en charge au moins 3 décimales, il s'agit du nombre moyen d'octets de toutes les sorties de la séquence de nombres commençant par
0.001
et se terminant par1000
, augmentant de1.001
chaque fois.0.001, 1.002, 2.003...998.999, 1000.000
Ensuite, retirez 50% de ce score.Score négatif: si votre code prend en charge les nombres négatifs et zéro, il s'agit du nombre moyen d'octets des sorties de tous les entiers de
-1000
à0
. Ensuite, retirez 10% de ce score.
(Le moyen le plus simple de les calculer serait probablement une boucle avec votre programme / fonction à l'intérieur.)
Votre score final est la moyenne de la formule applicable ci-dessus.
Si la sortie n'est pas déterministe (c'est-à-dire quelque peu aléatoire; plusieurs exécutions avec la même entrée produisent plusieurs sorties uniques), alors le score de chaque entrée est déterminé par la plus grande sortie sur dix exécutions sur mon processeur.
De plus, comme vous ne savez pas à quel point les données informatiques seront précieuses à l'avenir, le nombre d'octets de votre code générateur doit être inférieur à 512 octets.
Le score le plus bas en deux semaines (le 30 septembre) sera déclaré vainqueur. Félicitations à votre gagnant, @ThomasKwa !
Classement
Pour vous assurer que votre réponse s'affiche correctement, veuillez commencer par cet en-tête:
# Language name/Other language name, X points
Où X
est le score de votre réponse. Exemple:
# CJam/Pyth, 25.38 points
Si vous avez des questions ou des suggestions, faites-le moi savoir. Bonne chance!
la source
0
ou1
par défaut?Integer.parseInt("1000", 1+1+1+1+1+1+1+1+1+1)
? Je suis sûr queparseInt
n'utilise que les opérations autorisées ;-)Réponses:
Code machine Python / Zilog Z80,
11.65311.488Bonus: nombres négatifs.
Suppose que la
hl
paire de registres contient initialement 0 et renvoie le résultathl
.Seules ces trois instructions sont utilisées:
Nous utilisons une petite modification de la représentation binaire équilibrée de poids minimum BBR2 . Puisque BBR2 minimise le poids (nombre de chiffres non nuls), mais nous voulons minimiser le poids plus le nombre de décalages de bits, nous modifions une constante dans l'algorithme de
3/2
à5/3
.Pour calculer le score et vérifier, utilisez ce code:
Exemple de sortie:
Ou en montage:
Plus d'exemples de programmes:
Optimisations possibles: les règles OP interdisant les instructions
inc h
etdec h
, qui modifient directement l'octet supérieurhl
, maissla h
les non documentéessl1 h
(les décalages du bit gauche de 1 surh
ce décalage dans a0
et1
respectivement) sont autorisées.sla h
etsl1 h
sont deux octets chacun, mais ils peuvent parfois raccourcir la sortie.la source
+
traduitdec
. Je continue de mal lire les exemples négatifs.CJam / CJam,
143,26342,71328,89923,90121,90320,468Aucun bonus ne s'applique.
Essayez-le en ligne: exemple de course | calculateur de score | vérification
Exemple d'exécutions
la source
%
par une expression plus longue. Les liens devraient fonctionner maintenant.ß / BrainFuck, 34,201 points
ß source (194B):
Si quelqu'un est intéressé, j'ajouterai une explication. La sortie BF est déjà assez optimisée, mais je suppose que je pourrais utiliser les 318B restants de code ß pour implémenter
suppression des collisions par l'opérateur.Échantillons:
Exécution sous Windows:
Sous Linux:
Validez dans l' interpréteur BF en ligne .
Scores:
= 37.495
.= 60.959 * 0.5 = ~30.48
.= 38.4765234765235 * 0.9 = ~34.629
= (37.495 + 30.48 + 34.629)/3 = 34.201
.la source
Rubis / Rubis, 29.77885
31,873 * 0,9 (négatif) 30,872 (positif).
La stratégie de base est une représentation symétrique en base 3 ("ternaire équilibré"), c'est-à-dire lorsque les chiffres sont
-1,0,1
au lieu de0,1,2
Voici la sortie de 0 à 40 avant le nettoyage
Et après le nettoyage
la source
Ceylan / Ceylan,
49,8640,95 pointsLa troisième version utilise Ceylon 1.2 pour le générateur et 509 octets de code:
import ceylon.language{S=String,I=Integer,e=expand}S q(I n)=>n==0then"0"else(n<0then"-"+p(-n,"-")else p(n,"+"));variable Map<[I,S],S>c=map{};S p(I n,S s){S v=c[[n,s]]else(n<8then s.join([1].repeat(n)))else(let(a="+-".replace(s,""))e(e{for(x in 2..8)let(l=(n^(1.0/x)).integer){for(r in l:2)if(r>1)let(w=r^x){if(w-n<n)"("+p(r,"+")+")^("+p(x,"+")+")"+(w<n then s+p(n-w,s)else(n<w then a+p(w-n,a)else""))}}}).reduce<S>((x,y)=>x.size<y.size then x else y))else"";c=[n,s]in c then c else map{[n,s]->v,*c};return v;}
Il descend à 35,22 points, mais je ne mettrai pas cela dans la ligne de titre car Celyon 1.2 n'a été publié que le 29 octobre. Je ne pense pas que je serais en mesure d'implémenter cet algorithme dans Ceylon 1.1 dans cette taille.). Plus de détails là-bas, je vais décrire ici la deuxième version. (La première version peut être vue dans l'histoire - elle ne supportait que les nombres positifs, mais elle tenait en 256 octets.)
Deuxième version
Maintenant, la deuxième version, qui prend en charge les entiers négatifs (et 0), et crée généralement une sortie un peu plus courte en utilisant en plus
-
. (Cette version utilise en fait la longueur autorisée, la première a essayé de rester sous 256 octets au lieu de 512.)Le code a une longueur de 487, il y a donc encore de la place pour plus d'optimisations plus tard. (Il existe également de nombreuses réserves sous forme d'espaces et de noms de variables longs.)
Le score:
Quelques exemples de sorties:
Comme vous pouvez le voir, les négatifs sont toujours d'un octet (le début
-
) plus longs que les positifs correspondants.L'idée de base est la même que le programme précédent: trouver un carré près de notre nombre cible, et représenter sa racine et le reste de manière récursive. Mais maintenant, nous permettons à notre carré d'être également plus grand que le nombre cible, ce qui rend le reste négatif. (La
+0.5
peut être changée en une constante différente pour modifier l'algorithme, mais il semble que j'aie déjà atteint l'optimum ici - 0.4 et 0.6 donnent des résultats moins bons.)Pour rendre les valeurs négatives négatives (et autrement avoir la même structure que les positives, nous passons l'opérateur
sign
à notre fonction récursivep
- c'est-à-dire soit"+"
ou"-"
. Nous pouvons également l'utiliser pour le jointeur dans les cas triviaux (c'est-à-dire n <9)) comme pour le reste s'il est positif, et utilisez le signe opposé pour le reste s'il est négatif.La
proof
fonction gère le signe initial (avec un cas spécial pour 0), lap
fonction fait le travail réel, avec récursivité.Troisième version, pour Ceylon 1.2
La version golfée (c'est-à-dire les commentaires et les espaces supprimés) est affichée en haut, avec exactement 509 octets de code.
Cela utilise le même principe de base que la deuxième version, mais au lieu de simplement des carrés, il essaie également d'utiliser des puissances de nombres plus élevées (en essayant des exposants de 2 à 8), et utilise le résultat le plus court. Il met également en cache les résultats, sinon cela serait trop lent pour de plus grands nombres avec de nombreux appels récursifs.
Notation:
La grande construction en retrait au milieu sont trois compréhensions itérables imbriquées, les deux intérieures à l'intérieur d'une expression let. Celles-ci sont ensuite non imbriquées à l'aide de la fonction d'expansion deux fois, et la
reduce
fonction trouve la plus courte de ces chaînes.J'ai déposé une demande de fonctionnalité pour pouvoir le faire en une seule compréhension.
À l'intérieur de la compréhension, nous construisons une chaîne à partir de la racine
r
, de l'exposantx
et du reste (n-w
ouw-n
).L'
let
expression et lamap
fonction sont nouvelles dans Ceylan 1.2.map
aurait pu être remplacé parHashMap
(qui aurait eu besoin de plus de caractères pour l'importation, bien que ce serait probablement encore plus rapide, car je ne construirais pas la carte nouvelle pour chaque nouvelle entrée). Leslet
expressions commelet (w = r ^ x)
auraient pu être remplacées en utilisant uneif
clause commeif(exists w = true then r ^ x)
(et alors je n'aurais pas eu besoin des deuxexpand
appels non plus), mais cela serait encore un peu plus long, ne cadrant pas dans les 511 octets autorisés.Voici les exemples de sorties correspondant à ceux sélectionnés ci-dessus, tous sauf les très petits nombres sont plus courts:
Par exemple, nous avons maintenant 1000 = (3 ^ 2 + 1) ^ 3, au lieu de 1000 = (6 ^ 2-4) ^ 2-5 ^ 2 + 1.
la source
less than 512
. Sou vous pouvez utiliser un max. de 511 octets;)Ruby / dc,
20.29618.41416,968Programmation dynamique! Définit une liste de fonctions qui, étant donné une instruction dc, renvoient une nouvelle expression et la valeur numérique de cette expression. Ensuite, en commençant par
1
prédéfini, il construit une liste de toutes les valeurs accessibles jusqu'à et y compris la valeur souhaitée.Éditer:
Ajout d'une fonction pour n-1 et l'a fait exécuter l'algorithme à travers plusieurs passes. Il semble avoir besoin de 7 passes pour se stabiliser. J'ai dû raccourcir certains noms de variables pour rester dans les 512 octets.
modifier 2:
Ajout de fonctions pour n (n-1) , n (n + 1) et n ^ 3 pendant que j'y étais. Raccourci un peu plus le code, atteignant exactement 512 octets.
Numéros générés:
La sortie se compose entièrement de cinq caractères différents:
1
pousse la valeur 1 sur la pile;d
duplique le haut de la pile;+
,-
Et*
saute les deux valeurs de début et pousse leur somme, la différence, et le produit, respectivement. Chaque expression générée ajoute une seule valeur à la pile après l'exécution....
la source
-
opérateur tout en restant dans le nombre d'octets?Python 2.6,
78,069- 66,265 pointsSoumettre ma réponse pour ce qu'elle vaut (pas beaucoup dans ce cas ... mais démontrer clairement que pour ce défi, il ne suffit pas de simplement penser à composer la sortie comme une somme de valeurs décalées en bits; si l'on prend en compte qu'aucun chiffre en dehors de 0 ou 1 peut apparaître dans la sortie). Je pourrais revenir plus tard avec une manière différente de générer de la sortie.
Le code lui-même n'est pas trop long (176 caractères):
Il génère une sortie correcte mais détaillée:
Extrait qui calcule le score:
la source