Imaginez que vous avez deux boîtes B(x)
et B(y)
chacune contenant un bit inconnu - 0 ou 1, et une machine F
qui peut les radiographier et produire une troisième boîte pour B(x^y)
( xor ). F
peut également calculer B(x*y)
( et ). En fait, ce ne sont que des cas particuliers de l'opération unique que la machine peut effectuer - produit intérieur chacun , noté F()
ci-dessous.
Pour deux tableaux de même longueur
[B(x[0]), B(x[1]), ..., B(x[n-1])]
[B(y[0]), B(y[1]), ..., B(y[n-1])]
le produit intérieur est défini comme
B(x[0]*y[0] ^ x[1]*y[1] ^ ... ^ x[n-1]*y[n-1])
« Chaque » signifie F()
peut traiter de multiples paires de x[]
, y[]
en une seule fois. Le x[]
et y[]
d'une paire doivent être de la même longueur; x[]
-s et y[]
-s de différentes paires n'en ont pas nécessairement besoin.
Les boîtes sont représentées par des identifiants entiers uniques.
Une implémentation de produit interne chacun en JavaScript pourrait ressembler
var H=[0,1]; // hidden values, indexed by boxId
function B(x) { // seal x in a new box and return the box id
return H.push(x)-1;
}
function F(pairs) { // "inner product each"
return pairs.map(function (pair) {
var r = 0, x = pair[0], y = pair[1];
for (var i = 0; i < x.length; i++) r ^= H[x[i]] * H[y[i]];
return B(r);
})
}
(Veuillez traduire ce qui précède dans la langue de votre choix.)
Étant donné l'accès à une F()
implémentation appropriée à votre langue (mais pas d'accès à H
ou B()
) et compte tenu de deux tableaux d'ID de boîte constituant les représentations binaires 16 bits de deux entiers a
et b
, votre tâche consiste à produire des ID de boîte pour la représentation binaire 16 bits de a+b
(rejet du débordement) avec le nombre minimum d' F()
appels.
La solution qui appelle F()
le moins de fois gagne. Les égalités seront brisées en comptant le nombre total de x[],y[]
paires F()
appelées - moins c'est mieux. S'il est toujours lié, la taille de votre code (à l'exclusion de l'implémentation de F()
et de ses assistants) détermine le gagnant de la manière traditionnelle du golf de code. Veuillez utiliser un titre comme "MyLang, 123 appels, 456 paires, 789 octets" pour votre réponse.
Écrivez une fonction ou un programme complet. Les entrées / sorties / arguments / résultats sont des tableaux int dans n'importe quel format raisonnable. La représentation binaire peut être en petit ou en gros - choisissez-en une.
Annexe 1: Pour rendre le défi un peu plus facile, vous pouvez supposer que les cases avec les identifiants 0 et 1 contiennent les valeurs 0 et 1. Cela vous donne des constantes, utiles par exemple pour la négation ( x^1
n'est "pas"). Il y avait bien sûr des moyens de contourner le manque de constantes, mais le reste du défi est assez difficile de toute façon, alors éliminons cette distraction.
Annexe 2: Pour gagner la prime, vous devez effectuer l'une des actions suivantes:
publier votre score (appels, paires, octets) et votre code avant la date limite
publier votre score et un hachage sha256 de votre code avant la date limite; puis affichez le code réel dans les 23 heures après la date limite
F
qu'une seule fois. Ce serait sûrement de la triche, mais je ne sais pas si ce serait une bonne ou une mauvaise tricherie.y=f(x)
et je vais enx
dépendrey
.data Box = B Int deriving (Show); f :: [[[Box]]] -> [Box]
J'aurai besoin de plus de temps pour comprendre comment l'implémenterf
(Haskell force les minuscules ici) - je vais essayer demain.Réponses:
Python 3 , 5 appels, 92 paires, 922 octets
Python 3 , 5 appels, 134 paires, 3120 octetsPython 3 , 6 appels, 106 paires, 2405 octets[JavaScript (Node.js)], 9 appels, 91 paires, 1405 octetsJavaScript (Node.js), 16 appels, 31 paires, 378 octetsEssayez-le en ligne!
PREMIÈRE VERSION D'accord, ce n'est pas du golf. C'est juste une adaptation du code de @ ngn.
La seule idée ici est que vous n'avez pas besoin de calculer le dernier report puisque vous jetez le débordement. De plus, les appels de
F
sont regroupés par deux. Peut-être qu'ils peuvent être regroupés d'une autre manière, mais je doute que vous puissiez réduire considérablement le nombre de paires, en raison de la nature de l'algorithme d'addition de base.EDIT : Toujours pas joué au golf. Le nombre de paires pourrait certainement être réduit, et probablement aussi le nombre d'appels. Voir https://gist.github.com/jferard/864f4be6e4b63979da176bff380e6c62 pour une "preuve" avec sympy.
EDIT 2 Passé à Python car il est plus lisible pour moi. Maintenant que j'ai la formule générale, je pense que je peux atteindre la limite de 5 (peut-être 4) appels.
EDIT 3 Voici les briques de base:
La formule générale est la suivante:
La version étendue est:
5 appels me semble la limite. Maintenant, j'ai un peu de travail pour retirer les paires et jouer au golf!
EDIT 4 J'ai joué à celui-ci.
Version non golfée:
Essayez-le en ligne!
la source
F()
. Je garantis qu'il existe un moyen de les réduire de manière significative (c'est la partie la plus difficile de ce défi), puis il y aura de la place pour optimiser le nombre de paires, et enfin bien sûr jouer au code (mais c'est le critère le moins important).... + x * y * z + ...
. Nous ne pouvons pas l'utiliserF
pour l'évaluer, mais si nous avons calculéx * y
avec l'F
appel précédent , il nous suffit de faire:... + (x * y) * z + ...
(il correspond au format deF
). En jouant avec sympy, j'ai réussi à épargner un appel (étape1: calculer r0, c0, r1; étape2: calculer c1 et quelques valeurs auxiliaires; étape3: calculer r2, c2, r3, c3), et je cherche maintenant un général Solution.Haskell, 1 appel (triche ???), 32 paires (pourrait être amélioré), 283 octets (même)
S'il vous plaît, ne vous fâchez pas contre moi, je ne veux pas gagner avec ça, mais j'ai été encouragé dans les remarques au défi d'expliquer de quoi je parlais.
J'ai essayé d'utiliser la monade d'état pour gérer l'ajout de boîtes et le comptage des appels et des paires, et cela a fonctionné, mais je n'ai pas réussi à faire fonctionner ma solution dans ce paramètre. J'ai donc fait ce qui était également suggéré dans les commentaires: il suffit de cacher les données derrière un constructeur de données et de ne pas jeter un œil. (La meilleure façon serait d'utiliser un module séparé et de ne pas exporter le constructeur.) Cette version a l'avantage d'être beaucoup plus simple.
Puisque nous parlons de boîtes de bits, je leur mets des
Bool
valeurs. Je définiszero
comme la case donnée avec le bit zéro - unone
n'est pas nécessaire.Nous utilisons la fonction de débogage
trace
pour voir à quelle fréquence af
été appelée et avec combien de paires.&&&
examine les cases par correspondance de motifs, l'inégalité/=
utilisée sur lesBool
valeurs estxor
.La
test
fonction prend un additionneur binaire aveugle comme premier argument, puis deux nombres pour lesquels l'addition est testée. Il renvoie unBool
indiquant si le test a réussi. Les boîtes de saisie sont d'abord créées, puis l'additionneur est appelé, le résultat non encadré (avecunB
) et comparé au résultat attendu.J'ai implémenté deux additionneurs, l'exemple de solution
simple
, afin que nous puissions voir que la sortie de débogage fonctionne correctement, et ma solution en utilisant la récursion de valeurvalrec
.Vous voyez comment je me définis
res
en termes de lui-même? Cela est également connu sous le nom de faire le nœud .Maintenant, nous pouvons voir comment
f
est appelé une seule fois:Ou remplacer
valrec
parsimple
pour voirf
être appelé 32 fois.Essayez-le en ligne! (la sortie de suivi apparaît sous "Debug")
la source
f
est une liste paresseuse, potentiellement infinie, qui se matérialise au fur et à mesure que vous la parcourez? Je crains que cela ne soit contraire à l'esprit du défi - cela vous permet de reporter la décision sur ce qui doit être passé commei+1
-st argument jusqu'à ce que vous ayez obtenu le résultat correspondant aui
-th. Il est beaucoup plus intéressant de savoir combien d'appelsf
vous aurez besoin avec des arguments entièrement matérialisés et immuables :)f
puisse prendre une entrée infinie (ajouter des flux de bits infinis, yay!), Ce n'est pas le point. Oh, et en fait, letrace
message garantit que la longueur est finie et connue au début. De plus, je ne dirais pas qu'il y a une décision différée: tout a été planifié à l'avance, comme demandé, je ne fais que mélanger aveuglément les boîtes. Et notez qu'il ne s'agit pas de l'ordre des arguments: je pourrais le changer pour qu'ilres
contienne d'abord le résultat, puis les bits de retenue.f
; alimentez-vous cette boîte comme un autre argument dans le même appel àf
?JavaScript, 32 appels, 32 paires, 388 octets
Dyalog APL, 32 appels, 32 paires, 270 octets
Il s'agit d'un exemple de solution naïve qui peut servir de modèle.
Notez que le nombre d'octets ne doit inclure que la section entourée de "BEGIN / END SOLUTION".
Explication:
J'ai choisi l'ordre des bits en petit bout (
x[0]
c'est le bit le moins significatif).Observez que l'addition sur un seul bit mod 2 peut être réalisée comme
F([[[x,y],[x,y]]])
(c'est-à-dire:x*x ^ y*y
- la multiplication mod 2 est idempotente) et la multiplication binaire commeF([[[x],[y]]])
.Nous parcourons les bits du moins significatif au plus significatif et calculons à chaque étape un bit de résultat et un report.
La même chose dans Dyalog APL (mais en utilisant des identifiants de boîte aléatoires):
la source