Converti una percentuale in un rapporto "semplice"


16

Gestisci un sito Web politico e hai stabilito che le persone hanno una migliore comprensione intuitiva quando la possibilità di vincere o perdere un'elezione è espressa come un rapporto ("5 in 7") rispetto a quando è espressa in percentuale ("71%" ).

Ma anche tu non vuoi mostrare rapporti confusi come "58 in 82", ti piacerebbe che fossero compresi più facilmente, anche se non sono così precisi.

Quindi, data una percentuale compresa tra lo 0,1% e il 99,9%, restituisce il rapporto "facile da capire" più vicino " x in y ", usando le seguenti regole :

  1. La maggior parte dei valori (vedere le eccezioni di seguito) dovrebbe restituire il rapporto più vicino tra 10 o inferiore . Il 55% dovrebbe restituire "5 in 9", non "11 in 20".
  2. I rapporti dovrebbero essere ridotti ai termini più bassi . Il 65% dovrebbe restituire "2 in 3", non "4 in 6".
  3. I valori inferiori al 10% dovrebbero restituire il rapporto più vicino della forma " 1 in n " dove n è uno di (10,12,15,20,30,40,50,60,70,80,90,100) . Ad esempio, il 6% dovrebbe restituire "1 su 15".
  4. I valori superiori al 90% dovrebbero restituire il rapporto più vicino della forma " n-1 in n " dove n è uno di (10,12,15,20,30,40,50,60,70,80,90,100) . Ad esempio, il 98,7% dovrebbe restituire "79 in 80".
  5. I valori inferiori all'1% dovrebbero restituire " <1 su 100 "
  6. I valori superiori al 99% dovrebbero restituire " > 99 su 100 "

Oppure, per pensarci in un altro modo, il tuo programma dovrebbe restituire il rapporto più vicino dai seguenti output possibili (ho incluso i loro valori approssimativi per comodità):

<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

Altre clausole:

  • L'input numerico può essere compreso tra 0,1 e 99,9 o tra 0,001 e 0,999 , a seconda di quale sia più conveniente. È necessario gestire almeno 3 cifre significative.
  • È necessario generare un rapporto ("3 in 4"), non la frazione equivalente ("3/4").
  • Se ci sono due rapporti ugualmente vicini all'ingresso, il programma può restituire uno dei due. Il 7,5% potrebbe restituire "1 su 12" o "1 su 15".
  • Lo spazio bianco iniziale / finale e / o le nuove linee vanno bene

Esempi :

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

Questa è una sfida di , vince il codice più corto in ogni lingua.

(Simile a, ma non duplicato di: Converti un decimale in una frazione , Frazione più vicina , Numero in virgola mobile approssimativo con precisione a n cifre )


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"Significa che anche noi possiamo tornare 7 in 100? A proposito, 1 in 14in questo caso è più vicino all'ingresso.
DimChtz,

@DimChtz No, poiché viola la regola 3 (i valori inferiori al 10% devono essere espressi come "1 in n ", per specifici possibili valori di n ).
BradC,

Ohh, non l'ho notato. Va bene.
DimChtz,

2
Mi piacerebbe se potessimo semplicemente produrre il numeratore e il denominatore in qualsiasi formato come una tupla / lista o qualcosa del genere, ma ci sono già risposte in competizione quindi suppongo che sia troppo tardi per questa sfida. Per le sfide future, prenderei in considerazione un formato I / O più flessibile perché alcune lingue perdono più competitività di altre quando si richiede la gestione delle stringhe.
HyperNeutrino,

1
@BradC - LOL. Ero solo al 538, ed ero tutto "Wow! Devo fare una sfida golfistica da questo!"
Chas Brown,

Risposte:


6

T-SQL, 385 byte

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'immissione avviene tramite una tabella preesistente t con campo numerico i , secondo i nostri standard IO .

Quella tabella di input è unita con una tabella in memoria analizzata da una stringa via STRING_SPLIT(che separa le righe) e PARSENAME(che separa numeratore e denominatore via .).

La tabella viene ordinata in base alla distanza dal valore di input i e restituisce la riga superiore, formattata in modo appropriato.


5

Carbone , 84 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Prende l'input come decimale anziché come percentuale. Spiegazione:

Nθ

Inserisci la frazione.

F¹¹«

n=0n=10

F⊖ι⊞υ⟦⊕κι⟧

1nn-1n

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

nth12,15,20...100n

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

n-1n1n

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

Calcola i valori decimali di tutti i rapporti e prendi la differenza assoluta con l'input originale.

≔⌕η⌊ηη

1224

×<‹θ·⁰¹

<0.01

×>›θ·⁹⁹

>0.99

⪫§υη in 

Unisci il numeratore e il denominatore del rapporto appropriato con ine stampa.


5

JavaScript (ES7), 164 159 144 byte

]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)

Provalo online!

Come?

p/q

d=(p/q-r)2

mdm

q

Commentate

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

4

Gelatina , 58 byte

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

Provalo online!

-16 byte grazie ad Arnauld (può semplicemente anteporre <e >invece di riscrivere l'intera frase)
-6 byte e correzioni di bug grazie a Jonathan Allan


@Arnauld Oh hai ragione, non ci ho mai pensato: P Grazie!
HyperNeutrino,

0.3dovrebbe risultare 3 in 10non2 in 7
Jonathan Allan il

Dovresti semplicemente rimuovere il µµ, no? MODIFICA - e poi golf ÐṂṂaÞḢ
Jonathan Allan il

la modifica 9a dovrebbe risolvere il bug che credo.
Jonathan Allan,

@JonathanAllan Oh whoops, sì, non stavo usando 10 come denominatore valido. Grazie. E no, rimuovere il doppio mu non funziona perché allora il "minimo" è attaccato al lato destro della funzione diadica link-min che non è sicuramente quello che voglio, ma solo mettere un mu non sembra risolverlo . Grazie per il golf: D
HyperNeutrino,

3

Python 2 , 261 278 261 237 177 byte

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

Provalo online!


1
Python non supporta i punti e virgola? Potresti sostituire '\n 'con ';'... a meno che non mi sbagli.
Dev

@ Brad risolto :)
TFeld il

3

Puliti , 224 198 197 byte

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])

Provalo online!

Ha spiegato:

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
  ]
 )

3

Gelatina ,  53  52 byte

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

Un programma completo che stampa il risultato.

Provalo online!

Oppure vedi la suite di test

Si noti che la suite di test viene modificata per rendere il codice un collegamento monadico mediante:

  1. usando il registro tenere traccia dell'attuale "input di programma", con ³to ®; e
  2. chiudendo l'elenco dei caratteri in codice per "in", con “ in to“ in ”

Come?

Inizia con il codice che forza qualsiasi stampa necessaria del segno <o >e quindi del codice che costruisce tutte le coppie numeratore-denominatore (con alcune versioni ridondanti non semplificate del modulo, tutte dopo la loro forma semplificata) e stampa la voce valutata in divisione minimamente diversa usando una stalla ordinamento unito a 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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.