Konwertuj procent na „prosty” stosunek

16

Prowadzisz polityczną stronę internetową i ustaliłeś, że ludzie mają lepsze intuicyjne zrozumienie, kiedy szansa na wygraną lub przegraną w wyborach jest wyrażona jako stosunek („5 na 7”) niż gdy jest wyrażona jako odsetek („71%” ).

Ale nie chcesz też wyświetlać mylących wskaźników, takich jak „58 na 82”, chciałbyś, aby były łatwiej zrozumiałe, nawet jeśli nie są tak dokładne.

Tak więc, biorąc pod uwagę procent od 0,1% do 99,9%, zwróć najbliższy „łatwy do zrozumienia” stosunek „ xy y ”, stosując następujące reguły :

  1. Większość wartości (patrz wyjątki poniżej) powinna zwracać najbliższy stosunek spośród 10 lub niższych . 55% powinno zwrócić „5 na 9”, a nie „11 na 20”.
  2. Wskaźniki należy obniżyć do najniższych wartości . 65% powinno zwrócić „2 na 3”, a nie „4 na 6”.
  3. Wartości poniżej 10% powinny zwracać najbliższy stosunek postaci „ 1 in n ”, gdzie n jest jednym z (10,12,15,20,30,40,50,60,70,80,90,100) . Na przykład 6% powinno zwrócić „1 na 15”.
  4. Wartości powyżej 90% powinny zwracać najbliższy stosunek postaci „ n-1 in n ”, gdzie n jest jednym z (10,12,15,20,30,30,40,50,60,70,80,90,100) . Na przykład 98,7% powinno zwrócić „79 na 80”.
  5. Wartości poniżej 1% powinny zwracać „ <1 na 100
  6. Wartości powyżej 99% powinny zwracać „ > 99 na 100

Lub, aby pomyśleć o tym w inny sposób, twój program powinien zwrócić najbliższy stosunek z następujących możliwych wyników (dla wygody podałem ich przybliżone wartości):

<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

Inne postanowienia:

  • Wprowadzanie numeryczne może mieścić się w zakresie od 0,1 do 99,9 lub w zakresie od 0,001 do 0,999 , w zależności od tego, który z nich jest wygodniejszy. Musisz obsłużyć co najmniej 3 cyfry znaczące.
  • Musisz wyprowadzić współczynnik („3 na 4”), a nie ułamek równoważny („3/4”).
  • Jeśli dwa wejścia są jednakowo zbliżone do wejścia, twój program może zwrócić jeden z nich. 7,5% mogłoby zwrócić „1 na 12” lub „1 na 15”.
  • Wiodące / końcowe białe znaki i / lub nowe linie są w porządku

Przykłady :

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

To wyzwanie dla , wygrywa najkrótszy kod w każdym języku.

(Podobne do, ale nie duplikowane: Konwertuj liczbę dziesiętną na ułamek , Najbliższy ułamek , Przybliżona liczba zmiennoprzecinkowa z precyzją n-cyfrową )

BradC
źródło
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"Czy to oznacza, że ​​my również możemy wrócić 7 in 100? Btw, 1 in 14w tym przypadku jest bliżej wejścia.
DimChtz,
@DimChtz Nie, ponieważ narusza to zasadę 3 (wartości poniżej 10% należy wyrazić jako „1 in n ”, dla określonych możliwych wartości n ).
BradC,
Och, nie zauważyłem tego. W porządku.
DimChtz,
2
Chciałbym, żebyśmy mogli po prostu wyprowadzić licznik i mianownik jako dowolny format, taki jak krotka / lista lub coś takiego, ale istnieją już konkurencyjne odpowiedzi, więc przypuszczam, że jest za późno na to wyzwanie. W przypadku przyszłych wyzwań rozważę bardziej elastyczny format we / wy, ponieważ niektóre języki tracą większą konkurencyjność niż inne, gdy wymaga się obsługi ciągów.
HyperNeutrino
1
@BradC - LOL. Miałem zaledwie 538 lat i mówiłem: „Wow! Muszę z tego zrobić wyzwanie w golfa!”
Chas Brown,

Odpowiedzi:

6

T-SQL, 385 bajtów

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)

Dane wejściowe pochodzą z wcześniej istniejącej tabeli tz polem numerycznym i , zgodnie z naszymi standardami IO .

Ta tabela wejściowa jest połączona z tabelą w pamięci przeanalizowaną z ciągu znaków przez STRING_SPLIT(który oddziela wiersze) i PARSENAME(który oddziela licznik i mianownik przez .).

Tabela jest sortowana według odległości od wartości wejściowej i i zwraca odpowiednio sformatowany górny wiersz.

BradC
źródło
5

Węgiel drzewny , 84 bajty

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

Wypróbuj online! Link jest do pełnej wersji kodu. Pobiera dane wejściowe jako liczbę dziesiętną, a nie procentową. Wyjaśnienie:

Nθ

Podaj ułamek.

F¹¹«

n=0n=10

F⊖ι⊞υ⟦⊕κι⟧

1nn-1n

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

nth12,15,20...100n

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

n-1n1n

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

Oblicz wartości dziesiętne wszystkich współczynników i weź bezwzględną różnicę przy pierwotnym wprowadzeniu.

≔⌕η⌊ηη

12)2)4

×<‹θ·⁰¹

<0,01

×>›θ·⁹⁹

>0,99

⪫§υη in 

Połącz licznik i mianownik odpowiedniego stosunku za pomocą ini wydrukuj.

Neil
źródło
5

JavaScript (ES7), 164 159 144 bajtów

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

Wypróbuj online!

W jaki sposób?

p/q

re=(p/q-r)2)

mrem

q

Skomentował

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
źródło
4

Galaretka , 58 bajtów

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

Wypróbuj online!

-16 bajtów dzięki Arnauldowi (może po prostu wstawić <i >zamiast przepisywać całą frazę)
-6 bajtów i poprawki błędów dzięki Jonathanowi Allanowi

HyperNeutrino
źródło
@Arnauld Oh masz rację, nigdy nie myślałem o tym: P Dzięki!
HyperNeutrino
0.3powinno skutkować 3 in 10nie2 in 7
Jonathan Allan
Powinieneś po prostu usunąć µµ, nie? EDIT - a następnie golf ÐṂṂdoÞḢ
Jonathan Allan
zmiana 9na powinna rozwiązać problem, który moim zdaniem.
Jonathan Allan
@JonathanAllan Oh, ups, tak, nie użyłem 10 jako ważnego mianownika. Dzięki. I nie, usunięcie podwójnego mu nie działa, ponieważ wtedy „minimum” jest dołączone do prawej strony dyadycznej funkcji link-min, co zdecydowanie nie jest tym, czego chcę, ale umieszczenie tylko jednego mu nie wydaje się naprawiać . Dzięki za golfa: D
HyperNeutrino
3

Python 2 , 261 278 261 237 177 bajtów

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

Wypróbuj online!

TFeld
źródło
1
Czy Python nie obsługuje średników? Można wymienić '\n 'z ';'... chyba że się mylę.
Dev
@BradC Naprawiono :)
TFeld
3

Czysty , 224 198 197 bajtów

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

Wypróbuj online!

Wyjaśniono:

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
  ]
 )
Obrzydliwe
źródło
3

Galaretka ,  53  52 bajty

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

Pełny program, który drukuje wynik.

Wypróbuj online!

Lub zobacz pakiet testowy

Zauważ, że pakiet testowy został zmieniony, aby uczynić kod monadycznym łączem poprzez:

  1. za pomocą rejestru można śledzić bieżące „wejście programu”, używając ³do ®; i
  2. zamykając listę znaków w kodzie „in”, za pomocą “ in do“ in ”

W jaki sposób?

Zaczyna się od kodu, który wymusza wszelkie niezbędne drukowanie znaku <lub, >a następnie kodu, który konstruuje wszystkie pary licznik-mianownik (z pewnymi nadmiarowymi, nieskomplikowanymi wersjami formularza, wszystkie po ich uproszczonej formie) i drukuje minimalnie różny wpis z oceną podziału za pomocą stabilnego sort połączony z 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
źródło
2

Perl 6 , 118 bajtów

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

Wypróbuj online!

nwellnhof
źródło