Konvertieren Sie einen Prozentsatz in ein "einfaches" Verhältnis

16

Sie betreiben eine politische Website und haben festgestellt, dass die Menschen ein besseres intuitives Verständnis haben, wenn die Chance, eine Wahl zu gewinnen oder zu verlieren, als Verhältnis ("5 zu 7") ausgedrückt wird, als wenn es als Prozentsatz ausgedrückt wird ("71%"). ).

Aber Sie möchten auch keine verwirrenden Verhältnisse wie "58 in 82" anzeigen, sondern möchten, dass diese leichter verstanden werden, auch wenn sie nicht ganz so präzise sind.

Geben Sie also bei einem Prozentsatz zwischen 0,1% und 99,9% das nächstgelegene "leicht verständliche" Verhältnis " x in y " zurück, indem Sie die folgenden Regeln anwenden :

  1. Die meisten Werte (siehe Ausnahmen unten) sollten den Wert zurückgeben nächstliegende Verhältnis von 10 oder weniger zurückgeben . 55% sollten "5 in 9" zurückgeben, nicht "11 in 20".
  2. Verhältnisse sollten sein ihren niedrigsten Ausdrücken verringert werden . 65% sollten "2 in 3" zurückgeben, nicht "4 in 6".
  3. Werte unter 10% sollten das engste Verhältnis der Form " 1 in n " mit n ergeben eines von (10,12,15,20,30,40,50,60,70,80,90,100) ist . Beispielsweise sollten 6% "1 in 15" zurückgeben.
  4. Werte über 90% sollten das engste Verhältnis der Form " n-1 in n " zurückgeben, wobei n eins von (10,12,15,20,30,40,50,60,70,80,90,100) ist . Beispielsweise sollten 98,7% "79 in 80" zurückgeben.
  5. Werte unter 1% sollten " <1 in 100 " zurückgeben
  6. Werte über 99% sollten " > 99 in 100 " zurückgeben

Oder, um es anders zu betrachten, Ihr Programm sollte das nächstliegende Verhältnis aus den folgenden möglichen Ausgaben zurückgeben (ich habe die ungefähren Werte für Ihre Bequemlichkeit angegeben):

<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

Andere Bestimmungen:

  • Die numerische Eingabe kann im Bereich von 0,1 bis 99,9 oder im Bereich von liegen 0,001 bis 0,999 liegen , je nachdem, was bequemer ist. Sie müssen mindestens 3 signifikante Stellen behandeln.
  • Sie müssen ein Verhältnis ("3 in 4") ausgeben , nicht den entsprechenden Bruch ("3/4").
  • Wenn sich zwei Verhältnisse in der Nähe der Eingabe befinden, kann Ihr Programm eines davon zurückgeben. 7,5% könnten "1 in 12" oder "1 in 15" zurückgeben.
  • Führende / nachfolgende Leerzeichen und / oder neue Zeilen sind in Ordnung

Beispiele :

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

Dies ist eine Herausforderung, der kürzeste Code in jeder Sprache gewinnt.

(Ähnlich, aber nicht dupliziert von: Konvertieren einer Dezimalzahl in einen Bruch , Nächstliegender Bruch , Ungefähre Gleitkommazahl mit n-stelliger Genauigkeit )

BradC
quelle
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"Bedeutet das, dass wir auch zurückkehren können 7 in 100? Übrigens 1 in 14ist in diesem Fall näher an der Eingabe.
DimChtz
@DimChtz Nein, da dies gegen Regel 3 verstößt (Werte unter 10% sollten für bestimmte mögliche Werte von n als "1 in n " ausgedrückt werden ).
BradC
Ohh, das habe ich nicht bemerkt. Okay.
DimChtz
2
Ich würde es begrüßen, wenn wir nur Zähler und Nenner in einem beliebigen Format wie Tupel / Liste oder ähnlichem ausgeben könnten, aber es gibt bereits konkurrierende Antworten, daher ist es wahrscheinlich zu spät für diese Herausforderung. Für zukünftige Herausforderungen würde ich jedoch ein flexibleres E / A-Format in Betracht ziehen, da einige Sprachen bei der Verarbeitung von Zeichenfolgen an Wettbewerbsfähigkeit verlieren als andere.
HyperNeutrino
1
@BradC - LOL. Ich war erst 538 und ich war alles "Wow! Ich muss eine Golf-Herausforderung daraus machen!"
Chas Brown

Antworten:

6

T-SQL, 385 Bytes

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)

Die Eingabe erfolgt über bereits vorhandene Tabelle t mit numerischem Feld i , je unseren IO - Standards .

Diese Eingabetabelle wird mit einer In-Memory-Tabelle verknüpft, die aus einem String-Via STRING_SPLIT(das Zeilen trennt) und PARSENAME(das Zähler und Nenner über trennt) analysiert wird. .

Die Tabelle ist nach dem Abstand vom Eingabewert i sortiert und gibt die oberste Zeile zurück, die entsprechend formatiert ist.

BradC
quelle
5

Kohle , 84 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Nimmt die Eingabe als Dezimalzahl und nicht als Prozentsatz. Erläuterung:

Nθ

Geben Sie den Bruch ein.

F¹¹«

n=0n=10

F⊖ι⊞υ⟦⊕κι⟧

1nn-1n

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

nth12,15,20...100n

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

n-1n1n

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

Berechnen Sie die Dezimalwerte aller Verhältnisse und nehmen Sie die absolute Differenz zur ursprünglichen Eingabe.

≔⌕η⌊ηη

1224

×<‹θ·⁰¹

<0,01

×>›θ·⁹⁹

>0,99

⪫§υη in 

Verbinden Sie den Zähler und Nenner des entsprechenden Verhältnisses mit inund drucken Sie.

Neil
quelle
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)

Probieren Sie es online!

Wie?

p/q

d=(p/q-r)2

mdm .

q zum niedrigsten, so dass im Falle eines Gleichstands ein kleinerer Nenner bevorzugt wird.

Kommentiert

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
quelle
4

Jelly , 58 Bytes

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

Probieren Sie es online!

-16 Bytes dank Arnauld (kann einfach die ganze Phrase voranstellen <und >anstatt sie neu zu schreiben)
-6 Bytes und Bugfixes dank Jonathan Allan

HyperNeutrino
quelle
@Arnauld Oh du hast recht, habe nie darüber nachgedacht: P Danke!
HyperNeutrino
0.3sollte 3 in 10nicht führen2 in 7
Jonathan Allan
Sie sollten nur die entfernen µµ, nein? EDIT - und dann Golf ÐṂṂaufÞḢ
Jonathan Allan
Ändern 9auf sollte den Fehler beheben, glaube ich.
Jonathan Allan
@ JonathanAllan Oh whoops, yep, ich habe 10 nicht als gültigen Nenner verwendet. Vielen Dank. Und nein, das Entfernen der doppelten mu funktioniert nicht, weil dann das "Minimum" an der rechten Seite der dyadischen link-min-Funktion angebracht ist, was definitiv nicht das ist, was ich will, aber nur ein mu zu setzen, scheint es nicht zu beheben . Vielen Dank für das Golfen: D
HyperNeutrino
3

Python 2 , 261 278 261 237 177 Bytes

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

Probieren Sie es online!

TFeld
quelle
1
Unterstützt Python keine Semikolons? Sie könnten ersetzen '\n 'mit ';'... es sei denn , ich bin falsch.
Dev
@
RadC
3

Sauber , 224 198 197 Bytes

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

Probieren Sie es online!

Erklärt:

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
quelle
3

Jelly ,  53  52 Bytes

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

Ein vollständiges Programm, das das Ergebnis druckt.

Probieren Sie es online!

Oder schauen Sie sich die Testsuite an

Beachten Sie, dass die Testsuite geändert wird, um den Code zu einer monadischen Verknüpfung zu machen, indem:

  1. Unter Verwendung des Registers behalten Sie eine Spur des gegenwärtigen "Programmeingangs", mit ³zu ®; und
  2. Schließen Sie die Liste der Zeichen Code für "in" mit “ in bis“ in ”

Wie?

Beginnt mit Code, der das erforderliche Drucken des Zeichens <oder erzwingt >, und dann mit Code, der alle Zähler-Nenner-Paare (mit einigen redundanten, nicht vereinfachten Formularversionen, alle nach ihrer vereinfachten Form) erstellt und den minimal unterschiedlichen, durch Division ausgewerteten Eintrag unter Verwendung eines Stables druckt verbunden mit 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
quelle
2

Perl 6 , 118 Bytes

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

Probieren Sie es online!

nwellnhof
quelle