Convertir un pourcentage en un rapport «simple»

16

Vous dirigez un site Web politique et avez déterminé que les gens ont une meilleure compréhension intuitive lorsque la chance de gagner ou de perdre une élection est exprimée sous forme de ratio ("5 sur 7") que lorsqu'elle est exprimée en pourcentage ("71%"). ).

Mais vous ne voulez pas non plus afficher des rapports confus comme "58 en 82", vous souhaitez qu'ils soient plus faciles à comprendre, même s'ils ne sont pas aussi précis.

Donc, étant donné un pourcentage compris entre 0,1% et 99,9%, renvoyez le rapport "facile à comprendre" le plus proche " x en y ", en utilisant les règles suivantes :

  1. La plupart des valeurs (voir les exceptions ci-dessous) doivent renvoyer le rapport plus proche sur 10 ou moins . 55% devraient renvoyer "5 en 9", pas "11 en 20".
  2. Les ratios devraient être réduits à leur plus bas niveau . 65% devraient retourner "2 en 3", pas "4 en 6".
  3. Les valeurs inférieures à 10% devraient renvoyer le rapport le plus proche de la forme " 1 sur n " où n est l'un de (10,12,15,20,30,40,50,60,70,80,90,100) . Par exemple, 6% devraient renvoyer "1 sur 15".
  4. Les valeurs supérieures à 90% doivent renvoyer le rapport le plus proche de la forme " n-1 en n ", où n est l'un de (10,12,15,20,30,40,50,60,70,80,90,100) . Par exemple, 98,7% devraient renvoyer "79 en 80".
  5. Les valeurs inférieures à 1% doivent renvoyer " <1 sur 100 "
  6. Les valeurs supérieures à 99% devraient renvoyer " > 99 sur 100 "

Ou, pour y penser autrement, votre programme devrait renvoyer le rapport le plus proche des sorties possibles suivantes (j'ai inclus leurs valeurs approximatives pour votre commodité):

<1 in 100
 1 in 100  = 1.00%
 1 in 90   = 1.11%
 1 in 80   = 1.25%
 1 in 70   = 1.43%
 1 in 60   = 1.67%
 1 in 50   = 2.00%
 1 in 40   = 2.50%
 1 in 30   = 3.33%
 1 in 20   = 5.00%
 1 in 15   = 6.67%
 1 in 12   = 8.33%
 1 in 10   = 10.00%
 1 in 9    = 11.11%
 1 in 8    = 12.50%
 1 in 7    = 14.29%
 1 in 6    = 16.67%
 1 in 5    = 20.00%
 2 in 9    = 22.22%
 1 in 4    = 25.00%
 2 in 7    = 28.57%
 3 in 10   = 30.00%
 1 in 3    = 33.33%
 3 in 8    = 37.50%
 2 in 5    = 40.00%
 3 in 7    = 42.86%
 4 in 9    = 44.44%
 1 in 2    = 50.00%
 5 in 9    = 55.56%
 4 in 7    = 57.14%
 3 in 5    = 60.00%
 5 in 8    = 62.50%
 2 in 3    = 66.67%
 7 in 10   = 70.00%
 5 in 7    = 71.43%
 3 in 4    = 75.00%
 7 in 9    = 77.78%
 4 in 5    = 80.00%
 5 in 6    = 83.33%
 6 in 7    = 85.71%
 7 in 8    = 87.50%
 8 in 9    = 88.89%
 9 in 10   = 90.00%
 11 in 12  = 91.67%
 14 in 15  = 93.33%
 19 in 20  = 95.00%
 29 in 30  = 96.67%
 39 in 40  = 97.50%
 49 in 50  = 98.00%
 59 in 60  = 98.33%
 69 in 70  = 98.57%
 79 in 80  = 98.75%
 89 in 90  = 98.89%
 99 in 100 = 99.00%
>99 in 100

Autres stipulations:

  • L'entrée numérique peut être comprise entre 0,1 et 99,9 ou entre 0,001 et 0,999 , selon ce qui est le plus pratique. Vous devez gérer au moins 3 chiffres significatifs.
  • Vous devez générer un rapport ("3 en 4"), pas l'équivalent fraction ("3/4").
  • S'il y a deux ratios également proches de l'entrée, votre programme peut retourner l'un ou l'autre. 7,5% pourraient renvoyer «1 sur 12» ou «1 sur 15».
  • Les espaces blancs en tête / arrière et / ou les nouvelles lignes sont très bien

Exemples :

Input  :   Output
 0.5   :  <1 in 100
 1.0   :   1 in 100
 1.5   :   1 in 70
 7.5   :   1 in 15  or  1 in 12 (either is acceptable)
 9.2   :   1 in 10
13.1   :   1 in 8
29.2   :   2 in 7
29.3   :   3 in 10
52.7   :   1 in 2
52.8   :   5 in 9
72.0   :   5 in 7
73.9   :   3 in 4
88.8   :   8 in 9
90.8   :   9 in 10
94.2   :  19 in 20
98.7   :  79 in 80
98.9   :  89 in 90
99.0   :  99 in 100
99.1   : >99 in 100

Ceci est un défi de , le code le plus court dans chaque langue gagne.

(Similaire à, mais pas en double: convertir une décimale en fraction , fraction la plus proche , nombre à virgule flottante approximatif avec une précision à n chiffres )

BradC
la source
If there are two ratios equally close to the input, your program can return either one. 7.5% could return "1 in 12" or "1 in 15"Est-ce à dire que nous pouvons également revenir 7 in 100? Btw, 1 in 14est plus proche de l'entrée dans ce cas.
DimChtz
@DimChtz Non, car cela viole la règle 3 (les valeurs inférieures à 10% doivent être exprimées par "1 sur n ", pour des valeurs spécifiques possibles de n ).
BradC
Ohh, je ne l'ai pas remarqué. D'accord.
DimChtz
2
J'aimerais que nous puissions simplement sortir le numérateur et le dénominateur sous n'importe quel format comme un tuple / liste ou quelque chose, mais il y a déjà des réponses concurrentes, donc je suppose qu'il est trop tard pour ce défi. Pour les défis futurs, je considérerais un format d'E / S plus flexible car certains langages perdent plus de compétitivité que d'autres lorsque vous avez besoin de la gestion des chaînes.
HyperNeutrino
1
@BradC - LOL. J'étais à 538, et j'étais tout "Wow! Je dois faire un défi de golf avec ça!"
Chas Brown

Réponses:

6

T-SQL, 385 octets

SELECT TOP 1IIF(i>.99,'>',IIF(i<.01,'<',''))+n+' in '+d
FROM t,(SELECT ISNULL(PARSENAME(value,2),'1')n,PARSENAME(value,1)d FROM
STRING_SPLIT('100,90,80,70,60,50,40,30,20,15,12,10,9,8,7,6,5,2.9,4,2.7,3.10,3,3.8,2.5,3.7,4.9,2,5.9,4.7,3.5,5.8,2.3,7.10,5.7,3.4,7.9,4.5,5.6,6.7,7.8,8.9,9.10,11.12,14.15,19.20,29.30,39.40,49.50,59.60,69.70,79.80,89.90,99.100',','))m
ORDER BY ABS(i-ABS(n)/d)

L'entrée se fait via la table préexistante t avec le champ numérique i , selon nos normes IO .

Cette table d'entrée est jointe à une table en mémoire analysée à partir d'une chaîne via STRING_SPLIT(qui sépare les lignes) et PARSENAME(qui sépare le numérateur et le dénominateur via .).

Le tableau est trié par distance de la valeur d'entrée i et renvoie la ligne supérieure, formatée de manière appropriée.

BradC
la source
5

Fusain , 84 octets

NθF¹¹«F⊖ι⊞υ⟦⊕κι⟧≔⎇⊖ι∨×χι¹²¦¹⁵ιF²⊞υ⟦∨κ⊖ιι⟧»≔Eυ↔⁻θ∕§ι⁰§ι¹η≔⌕η⌊ηη×<‹θ·⁰¹×>›θ·⁹⁹⪫§υη in 

Essayez-le en ligne! Le lien est vers la version détaillée du code. Prend l'entrée sous forme décimale plutôt que sous forme de pourcentage. Explication:

Nθ

Saisissez la fraction.

F¹¹«

n=0n=dix

F⊖ι⊞υ⟦⊕κι⟧

1nn-1n

≔⎇⊖ι∨×χι¹²¦¹⁵ι

nth12,15,20...100n

F²⊞υ⟦∨κ⊖ιι⟧»

n-1n1n

≔Eυ↔⁻θ∕§ι⁰§ι¹η

Calculez les valeurs décimales de tous les ratios et prenez la différence absolue avec l'entrée d'origine.

≔⌕η⌊ηη

Trouvez l'indice de la différence la moins absolue. En cas d'égalité (ex.1224 ), prenez le rapport généré en premier.

×<‹θ·⁰¹

Imprimer un <si l'entrée est inférieure à0,01 .

×>›θ·⁹⁹

Imprimer un >si l'entrée est supérieure à0,99.

⪫§υη in 

Joignez le numérateur et le dénominateur du rapport approprié avec inet imprimez.

Neil
la source
5

JavaScript (ES7), 164 159 144 octets

Attend un rapport d'entrée ]0,1[.

r=>(g=m=>--n+11?g((q=n>1?n*10:n+10-~'13'[n],d=((p=r<.1?1:r>.9?q-1:n<0&&r*q+.5|0)/q-r)**2)>m?m:(o=p+' in '+q,d)):r<.01?'<'+o:r>.99?'>'+o:o)(n=11)

Essayez-le en ligne!

Comment?

Nous essayons tous les ratios possibles p/q. Pour chacun d'eux, nous calculons:

=(p/q-r)2

Nous mettons à jour le meilleur score m (plus bas, mieux c'est) à chaque fois est inférieur ou égal à m.

Nous partons de la valeur la plus élevée de q au plus bas, de sorte qu'un plus petit dénominateur est préféré en cas d'égalité.

Commenté

r => (g = m =>               // r = input; g() = recursive function, taking m = best score
  --n + 11 ?                 // decrement n; if n is still greater than or equal to -10:
    g(                       //   do a recursive call to g():
      ( q =                  //     compute q = denominator:
        n > 1 ?              //       if n is greater than 1:
          n * 10             //         q = n * 10 (20, 30, ..., 100)
        :                    //       else:
          n + 10 - ~'13'[n], //         q = 12 if n = 0, 15 if n = 1, n + 11 if n < 0
        d = ((               //     compute d = (p / q - r)²:
          p =                //       compute p = numerator:
          r < .1 ?           //         if r is less than 0.01:
            1                //           p = 1
          :                  //         else:
            r > .9 ?         //           if r is greater than 0.90:
              q - 1          //             p = q - 1
            :                //           else:
              n < 0 &&       //             if n is negative (i.e. q is in [1,10]):
              r * q + .5 | 0 //               p = round(r * q)
                             //             otherwise: p = 0 (which will be ignored)
          ) / q - r          //       compute p / q - r
        ) ** 2               //       and square the result (cheaper than absolute value)
      ) > m ?                //     if d is greater than m:
        m                    //       leave m unchanged
      : (                    //     else:
        o = p + ' in ' + q,  //       update the output string o
        d                    //       and update m to d
    ))                       //   end of recursive call
  :                          // else (all possible ratios have been tried out):
    r < .01 ? '<' + o :      //   if r is less than 0.01, prefix with '<'
    r > .99 ? '>' + o :      //   if r is greater than 0.99, prefix with '>'
    o                        //   otherwise, just return o
)(n = 11)                    // initial call to g() with m = n = 11
Arnauld
la source
4

Gelée , 58 octets

⁵R×⁵;12,15µ’,1,€)Ẏ;⁵Œc¤ð÷/ạ¥ÞḢj“ in ”
”<”>“”>.99$?<.01$?;Ç

Essayez-le en ligne!

-16 octets grâce à Arnauld (peut simplement ajouter le <et >au lieu de réécrire toute la phrase)
-6 octets et corrections de bugs grâce à Jonathan Allan

HyperNeutrino
la source
@Arnauld Oh tu as raison, je n'y ai jamais pensé: P Merci!
HyperNeutrino
0.3devrait se traduire par 3 in 10pas2 in 7
Jonathan Allan
Vous devez simplement supprimer le µµ, non? EDIT - puis golf ÐṂṂpourÞḢ
Jonathan Allan
changer 9pour devrait résoudre le bogue je crois.
Jonathan Allan
@JonathanAllan Oh oups, ouais je n'utilisais pas 10 comme dénominateur valide. Merci. Et non, la suppression du double mu ne fonctionne pas car le "minimum" est attaché au côté droit de la fonction dyadique link-min, ce qui n'est certainement pas ce que je veux, mais le fait de ne mettre qu'un seul mu ne semble pas le réparer . Merci pour le golf cependant: D
HyperNeutrino
3

Python 2 , 261 278 261 237 177 octets

lambda n:' <>'[(n<.01)-(n>.99)]+'%d in %d'%min([(a,b)for b in[[12,15]+r(10,110,10),r(1,11)][.1<n<.9]for a in r([1,b-1][n>.9],[b,2][n<.1])],key=lambda(a,b):abs(1.*a/b-n))
r=range

Essayez-le en ligne!

TFeld
la source
1
Python ne prend-il pas en charge les points-virgules? Vous pouvez remplacer '\n 'par ';'... sauf erreur.
Dev
@BradC Fixed :)
TFeld
3

Nettoyer , 224 198 197 octets

import StdEnv,Data.List,Text
t=toReal
$p=if(p<1.0)"<"if(p>99.0)">"""+snd(minimum[(abs(p-t n*1E2/t d),n<+" in "<+d)\\i<-[10,12,15:[20,30..100]],(n,d)<-[(1,i),(i-1,i):diag2[1..10][1..10]]|gcd n d<2])

Essayez-le en ligne!

Expliqué:

t = toReal                              // give `toReal` a shorter name
$ p
 = if(p < 1.0)                          // if the percentage is less than 1%
  "<"                                   // prepend "<"
 if(p > 99.0)                           // if the percentage is > 99%
  ">"                                   // prepend ">"
  ""                                    // otherwise prepend nothing
 + snd (                                // to the second element of
  minimum [                             // the smallest item in a list composed of
   (                                    // pairs of
    abs (                               // the absolute value of
     p -                                // the difference between the percentage
     t n*1E2 / t d                      // and the ratio
    ) 
   ,                                    // associated with
    n <+ " in " <+ d                    // the string representation of the ratio
   )                                    // in the form of a tuple
   \\ i <- [10, 12, 15: [20, 30..100]]  // for every special denominator `i`
   , (n, d) <- [(1, i), (i - 1, i): diag2 [1..10] [1..10]]
                                        // for every ratio `n` : `d`
   | gcd n d < 2                        // where `n` / `d` cannot be further simplified
  ]
 )
Οurous
la source
3

Gelée ,  53  52 octets

_.01,.99Ṡµ<0ịØ<ḣE⁵Ż×⁵+12,5Ṡ,’Ɗż€$Ẏ;⁵Œc¤÷/ạ¥Þ³Ḣj“ in 

Un programme complet qui imprime le résultat.

Essayez-le en ligne!

Ou consultez la suite de tests

Notez que la suite de tests est modifiée pour faire du code un lien monadique en:

  1. en utilisant le registre, garder une trace de l '"entrée de programme" en cours, avec ³to ®; et
  2. la fermeture de la liste des codes de caractères « dans », avec “ in pour“ in ”

Comment?

Commence par un code qui force toute impression nécessaire du signe <ou >, puis un code qui construit toutes les paires numérateur-dénominateur (avec certaines versions de formulaire redondantes non simplifiées, toutes après leur forme simplifiée) et imprime l'entrée évaluée par division à minima différente en utilisant une stable sorte rejoint avec in .

_.01,.99Ṡµ<0ịØ<ḣE⁵Ż×⁵+12,5Ṡ,’Ɗż€$Ẏ;⁵Œc¤÷/ạ¥Þ³Ḣj“ in  - Main Link: number in [0,1], n
 .01,.99                                             - literal pair = [0.01, 0.99]
_                                                    - subtract -> [n - 0.01, n - 0.99]
        Ṡ                                            - sign (vectorises) (-1 if <0; 1 if >0; else 0) 
         µ                                           - start a new monadic link
                                                     -   call that X
          <0                                         - less than zero? (vectorises)
             Ø<                                      - literal list of characters = "<>"
            ị                                        - index into (vectorises) ("<<" if n < 0.01; ">>" if n >= 0.99; else "><")
                E                                    - all (of X) equal? (1 if ((n < 0.01) OR (n > 0.99)) else 0
               ḣ                                     - head to index ("<" if n < 0.01; ">" if n > 0.99; else "")
                                                     -   (the following nilad forces a print of that)
                 ⁵                                   - literal 10
                  Ż                                  - zero-range -> [0,1,2,3,4,5,6,7,8,9,10]
                   ×⁵                                - multiply by 10 -> [0,10,20,30,40,50,60,70,80,90,100]
                      12,5                           - literal pair = [12,5]
                     +                               - add -> [12,15,20,30,40,50,60,70,80,90,100]
                                $                    - last two links as a monad
                             Ɗ                       -   last three links as a monad
                          Ṡ                          -     sign -> [1,1,1,1,1,1,1,1,1,1,1]
                            ’                        -     decrement -> [11,14,19,29,39,49,59,69,79,89,99]
                           ,                         -     pair -> [[1,1,1,1,1,1,1,1,1,1,1],[11,14,19,29,39,49,59,69,79,89,99]]
                              ż€                     -   zip with for €ach -> [[[1,12],[1,15],[1,20],[1,30],[1,40],[1,50],[1,60],[1,70],[1,80],[1,90],[1,100]],[[11,12],[14,15],[19,20],[29,30],[39,40],[49,50],[59,60],[69,70],[79,80],[89,90],[99,100]]]
                                 Ẏ                   - tighten -> [[1,12],[1,15],[1,20],[1,30],[1,40],[1,50],[1,60],[1,70],[1,80],[1,90],[1,100],[11,12],[14,15],[19,20],[29,30],[39,40],[49,50],[59,60],[69,70],[79,80],[89,90],[99,100]]
                                      ¤              - nilad followed by link(s) as a nilad:
                                   ⁵                 -   literal 10
                                    Œc               -   unordered pairs -> [[1,2],[1,3],[1,4],[1,5],[1,6],[1,7],[1,8],[1,9],[1,10],[2,3],[2,4],[2,5],[2,6],[2,7],[2,8],[2,9],[2,10],[3,4],[3,5],[3,6],[3,7],[3,8],[3,9],[3,10],[4,5],[4,6],[4,7],[4,8],[4,9],[4,10],[5,6],[5,7],[5,8],[5,9],[5,10],[6,7],[6,8],[6,9],[6,10],[7,8],[7,9],[7,10],[8,9],[8,10],[9,10]]
                                  ;                  - concatenate -> [[1,12],[1,15],[1,20],[1,30],[1,40],[1,50],[1,60],[1,70],[1,80],[1,90],[1,100],[11,12],[14,15],[19,20],[29,30],[39,40],[49,50],[59,60],[69,70],[79,80],[89,90],[99,100],[1,2],[1,3],[1,4],[1,5],[1,6],[1,7],[1,8],[1,9],[1,10],[2,3],[2,4],[2,5],[2,6],[2,7],[2,8],[2,9],[2,10],[3,4],[3,5],[3,6],[3,7],[3,8],[3,9],[3,10],[4,5],[4,6],[4,7],[4,8],[4,9],[4,10],[5,6],[5,7],[5,8],[5,9],[5,10],[6,7],[6,8],[6,9],[6,10],[7,8],[7,9],[7,10],[8,9],[8,10],[9,10]]
                                           Þ         - sort by:
                                          ¥          -   last two links as a dyad:
                                                     -       ...(with right argument of
                                            ³        -           the program input, n)
                                        /            -     reduce by:
                                       ÷             -       division
                                         ạ           -     absolute difference
                                             Ḣ       - head
                                               “ in  - literal list of characters " in "
                                              ;      - concatenate
                                                     - implicit print
Jonathan Allan
la source
2

Perl 6 , 118 octets

{'<'x(.01>$_)~'>'x($_>.99)~(|(1..9 X ^11),|map({|(1,$_-1 X$_)},12,15,|(^11 X*10))).min({abs $_-[/] @^a}).join(' in ')}

Essayez-le en ligne!

nwellnhof
la source