Jouer aux ennemis

20

La mise en place:

Un réseau social rapporte le nombre de votes d'une publication de deux manières: le nombre de votes positifs nets (nombre total de votes positifs - nombre total de votes négatifs) et le % de votes qui étaient des votes positifs , arrondi à l'entier le plus proche (0,5 arrondi). Le nombre de votes positifs nets est un entier (pas nécessairement positif), et le second est garanti comme étant un entier compris entre 0 et +100 inclus. Le nombre de votes positifs et le nombre de votes négatifs sont tous deux des nombres entiers 32 bits positifs ou nuls (vous pouvez spécifier signé ou non signé). Supposons que s'il n'y a aucun total de votes, le pourcentage de votes positifs est signalé comme nul.

Le défi:

Compte tenu de ces deux entiers (votes positifs nets et% votes positifs), quel est le programme le plus court que vous pouvez écrire qui détermine le plus petit nombre total de votes positifs que le message a reçus, avec toutes les contraintes ci-dessus satisfaites?

Les contraintes d'entrée sont garanties. Si l'entrée ne satisfait pas aux contraintes ci-dessus, le comportement du programme dépend de vous. Bravo en prime s'il n'entre pas dans une boucle infinie ou s'il tombe en panne. Pensez à renvoyer un nombre négatif si vous souhaitez plus de conseils.

Règles générales:

  • Il s'agit de , donc la solution valide la plus courte (mesurée en octets) l'emporte.
  • Ne laissez pas les langues de golf de code vous décourager de publier des réponses avec des langues autres que le golf de code. Essayez de trouver une réponse aussi courte que possible pour «n'importe quel» langage de programmation. Bravo en prime pour un langage Web côté client comme Javascript.
  • Si vous avez des solutions intéressantes dans plusieurs langues, postez-les séparément .
  • Des règles standard s'appliquent à votre réponse, vous êtes donc autorisé à utiliser STDIN / STDOUT, des fonctions / méthodes avec les paramètres et le type de retour appropriés, ou des programmes complets. Ton appel.
  • Les failles par défaut sont interdites.
  • Si possible, veuillez ajouter un lien avec un test pour votre code.
  • Veuillez également ajouter une explication du fonctionnement du code.
  • Gardez à l'esprit que si vous effectuez une opération de division entière qui tronque (par exemple 20/3 = 6) plutôt que des arrondis , cela pourrait ne pas être entièrement correct.
  • Des cas de test supplémentaires qui explorent les cas limites dans les contraintes ci-dessus sont les bienvenus.
  • Alors que le type de retour attendu est numérique, le booléen "false" peut être utilisé à la place de 0 .

Exemples de cas de test:

La première colonne est juste un numéro de référence inclus pour faciliter la discussion.

ref net  %up    answer
1   0    0   => 0    
2   -5   0   => 0    
3   -4   17  => 1    
4   -3   29  => 2    
5   -2   38  => 3    
6   -1   44  => 4    
7   0    50  => 1    
8   5    100 => 5    
9   4    83  => 5    
10  3    71  => 5    
11  2    63  => 5    
12  1    56  => 5    
13  1234 100 => 1234
14  800  90  => 894  (tip: don't refer to this as the "last test case;" others may be added.)
WBT
la source
Ce cas spécial de vote total nul est assez capricieux. S'il y a un nombre égal de votes positifs et négatifs, le pourcentage de votes positifs est de 50%, sauf qu'il est de 0% lorsqu'il n'y a pas de votes, brisant ainsi la symétrie de vote positif / négatif.
xnor
2
@xnor 0/0 n'est généralement pas défini, donc une hypothèse doit être faite. Avec ce choix, vous obtenez une "réponse = deuxième entrée" automatique si la deuxième entrée est 0, et une "réponse = première entrée" automatique si la deuxième entrée est 100.
WBT
1
Cas de test suggéré emprunté à @nwellnhof: 1000, 100. Pouvez-vous confirmer que la réponse attendue est 1000?
Arnauld
1
Downvoted, because haters gotta haine :)
Hosch250
@Arnauld et nwellnhof: comme indiqué dans le commentaire juste avant le vôtre, si la deuxième entrée = 100, la réponse = la première entrée. Si le 100 était vraiment un pourcentage arrondi légèrement inférieur, plus que la première entrée # de votes positifs serait nécessaire pour obtenir des votes nets = première entrée, et ce défi recherche le plus petit nombre de votes positifs totaux.
WBT

Réponses:

10

JavaScript (ES6), 47 octets

Prend la saisie dans la syntaxe de curry (n)(p), où n est le nombre de votes positifs nets et p est le pourcentage de votes positifs. Peut revenir falsepour0 .

n=>p=>(g=u=>u/(u-n/2)*50+.5^p?g(u+1):u)(n>0&&n)

Essayez-le en ligne!

Commenté

n => p => (          // given n and p
  g = u =>           // g = recursive function taking u = number of upvotes
    u / (u - n / 2)  //   compute u / (total_votes / 2)
    * 50 + .5        //   turn it into a percentage, add 1/2
    ^ p ?            //   XOR it with p, which gives 0 if the integer parts are matching
                     //   if the result is not equal to 0:
      g(u + 1)       //     try again with u + 1
    :                //   else:
      u              //     stop recursion and return u
)(n > 0 && n)        // initial call to g() with u = max(0, n)

Cas de bord

Soit F n (u) = u / (u - n / 2) * 50 + 0,5

  • Si u = 0 et n = 0 , alors F n (u) = NaN et F n (u) XOR p = p . Donc, nous retournons u = 0 si n = p = 0 (première itération du premier cas de test) ou continuons avec la récursion si p! = 0 (première itération du 7ème cas de test).

  • Si u> 0 et u = n / 2 , alors F n (u) = + Infinity et - encore - F n (u) XOR p = p . À moins que p = 0 , nous continuons simplement avec l'itération suivante. (Cela se produit dans les 9e et 11e cas de test.)

Arnauld
la source
Agréable! Vous obtenez des félicitations supplémentaires pour le choix de la langue et pour inclure une explication + un lien vers une démo en direct!
WBT
6

Stax , 17 octets

ëI╩½• ╠☺Vì∞«S↑♠αS

Exécuter et déboguer

C'est la force brute. Il commence par 0 pour les votes positifs candidats et augmente jusqu'à ce qu'il satisfasse la formule.

Déballé, non golfé et commenté, il ressemble à ceci.

0       push zero
{       start filter block...
        candidate upvotes is on the stack
  cHx-  calculate candidate downvotes for denominator (upvotes * 2 - net)
  c1?   if denominator is zero, replace it with 1
  :_    floating point division
  AJ*   multiply by 100
  j     round to integer
  ;=    is equal to second input?
        increment until a match is found
}gs

Exécutez celui-ci

récursif
la source
2

Propre , 114 107 104 octets

import StdEnv
? =toReal o toInt
$a d#e= ?d
= ?a+until(\c#b= ~c*e/(e-100.0)
= ?(?100*b/(?b+c))==e)inc 0.0

Essayez-le en ligne!

Définit la fonction $ :: Int Int -> Real, où les arguments sont des entiers signés et la valeur de retour est un flottant double précision exactement représentable par un entier signé 32 bits.

Il vérifie chaque valeur de cdans l'équation b=-cd/(d+1)pour trouver une bréponse satisfaisante a+c=bet b/(b+c)=d, puisque le plus petit cdonne le plus petit b, prend le premier élément de l'ensemble de toutes les solutions.

Οurous
la source
2

05AB1E , 13 octets [légèrement cassé]

*²·т-/ò²т;Qi1

Essayez-le en ligne!

Explication:

Pour résoudre ce problème, j'ai supposé les entrées a, b et le résultat attendu x. Compte tenu des informations dans la configuration, cela m'a donné l'équation:

 2x         100x
———— - a = ——————
 a           b

Réorganiser pour x donne

        ab
x = ——————————
     2b - 100

Le seul cas de test pour lequel cela ne fonctionne pas est 0, 50 - j'ai simplement codé en dur pour vérifier cela.

*²·т-/ò²т;Qi1     Implicit Inputs: a, b              STACK (bottom to top)
*                 Multiply the inputs together       [ab]
 ²·               Take the second input * 2          [ab, 2b]
   т-             Subtract 100                       [ab, 2b - 100]
     /ò           Divide and round                   [round(ab/(2b-100))]
       ²т;Qi1     If 2nd input = 50, push 1 to stack
                  { Implicitly output top item of stack [either 1, or round(...)] }
Geno Racklin Asher
la source
Cela ne fonctionne pas correctement pour certaines entrées. 90% avec 800 votes nets peuvent se faire avec 894 votes positifs.
récursif
@recursive Je sais ce que c'est. Cela suppose 90% exactement, pas 89,5%.
Geno Racklin Asher
Bon, plus proche de 90,5% dans ce cas mais oui.
récursif
1
Maintenant, je me rends compte que c'est plus délicat que je ne le pensais. J'y penserai, mais pour l'instant je le marquerai comme cassé.
Geno Racklin Asher
@GenoRacklinAsher Maintenant, je me rends compte que c'est plus compliqué que je ne le pensais. J'y penserai ... Voilà le genre de commentaires que j'aime lire, les voyant comme la marque d'un bon puzzle :-).
WBT
0

Go 1.10, 154 octets

func h(n,u float64)float64{if u==50{return 1};r:=Round(n*u/(2*u-100));s:=Round(n*(u+.5)/(2*u-99));v:=s/(2*s-n);if v>1||Round(v*100)!=u{return r};return s}

Essayez-le sur Go Playground! (TIO exécute Go 1.9, qui n'a pas de calcul mathématique).

Version non golfée

func haters(n, u float64) float64 {
    if u == 50 {
        return 1
    }
    r := Round(n * u / (2*u - 100))
    //Test the case where we were given a percentage that was rounded down (e.g. 90.4% given as 90%)
    //We test this by adding 0.5% to u. The denominator is just a simplified form of 2*(u+0.5) - 100
    s := Round(n * (u + .5) / (2*u - 99))
    //Check if s is a valid result
    v := s / (2*s - n)
    if v > 1 || Round(v*100) != u {
        return r
    }
    //s is strictly less than r, so we don't need to check the minimum.
    return s
}

Afin d'ajouter une explication, la formule ci-dessus pour r peut être dérivée en résolvant simultanément n=v-det u = 100 * v/(v + d)pour v, où v et d sont le nombre de votes positifs et négatifs respectivement. La formule dérivée n'est pas définie pour v = 50, nous devons donc gérer ce cas (ce que nous faisons avec la première instruction if).

ollien
la source