Bermain golf para pembenci

20

Pengaturan:

Sebuah jejaring sosial melaporkan jumlah suara yang dimiliki suatu pos dengan dua cara: jumlah upvote bersih (total upvotes - total downvotes), dan % suara yang upvotes , dibulatkan ke bilangan bulat terdekat (0,5 bulat ke atas). Jumlah upvote bersih adalah bilangan bulat (tidak harus positif), dan yang kedua dijamin bilangan bulat antara 0 dan +100 inklusif. Jumlah upvotes dan jumlah downvotes adalah nol atau bilangan bulat positif 32-bit (Anda dapat menentukan yang ditandatangani atau tidak ditandatangani). Asumsikan bahwa jika tidak ada total suara nol, persentase yang dipvotasikan dilaporkan sebagai nol.

Tantangan:

Dengan kedua bilangan bulat ini (upvote bersih dan% tervotasikan), program apa yang paling singkat yang dapat Anda tulis yang menentukan jumlah terendah total upvote yang diterima pos, dengan semua kendala di atas terpenuhi?

Batasan input dijamin. Jika input tidak memenuhi kendala di atas, perilaku program terserah Anda. Bonus pujian jika tidak memasuki loop tak terbatas atau crash. Pertimbangkan untuk mengembalikan nomor negatif jika Anda menginginkan panduan lebih lanjut.

Aturan umum:

  • Ini adalah , sehingga solusi terpendek yang valid (diukur dalam byte) menang.
  • Jangan biarkan bahasa kode-golf mencegah Anda memposting jawaban dengan bahasa non-codegolf. Cobalah untuk memberikan jawaban sesingkat mungkin untuk bahasa pemrograman 'apa saja'. Bonus pujian untuk bahasa Web sisi klien seperti Javascript.
  • Jika Anda memiliki solusi menarik dalam berbagai bahasa, poskan secara terpisah .
  • Aturan standar berlaku untuk jawaban Anda, jadi Anda diperbolehkan menggunakan STDIN / STDOUT, fungsi / metode dengan parameter dan tipe pengembalian yang tepat, atau program lengkap. Panggilanmu.
  • Celah default dilarang.
  • Jika memungkinkan, silakan tambahkan tautan dengan tes untuk kode Anda.
  • Selain itu, harap tambahkan penjelasan tentang cara kerja kode.
  • Ingatlah bahwa jika Anda melakukan operasi pembagian bilangan bulat yang memotong (mis. 20/3 = 6) daripada putaran , itu mungkin tidak sepenuhnya benar.
  • Kasus uji tambahan yang mengeksplorasi kasus tepi dalam kendala di atas dipersilakan.
  • Sementara tipe pengembalian yang diharapkan adalah angka, boolean "false" dapat digunakan sebagai pengganti 0 .

Contoh uji kasus:

Kolom pertama hanyalah nomor referensi yang disertakan untuk memfasilitasi diskusi.

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
sumber
Kasus nol total suara khusus ini cukup rewel. Jika ada jumlah upvote dan downvotes yang sama, persentase upvotes adalah 50%, kecuali 0% ketika tidak ada suara, memecah simetri upvote-downvote.
xnor
2
@xnor 0/0 umumnya tidak terdefinisi, jadi asumsi harus dibuat. Dengan pilihan ini, Anda mendapatkan "answer = second input" otomatis jika input kedua adalah 0, dan "answer = first input" otomatis jika input kedua adalah 100.
WBT
1
Kasus uji menyarankan dipinjam dari @nwellnhof: 1000, 100. Bisakah Anda mengonfirmasi bahwa jawaban yang diharapkan adalah 1000?
Arnauld
1
Diturunkan, karena pembenci harus membenci :)
Hosch250
@Arnauld dan nwellnhof: seperti yang tercantum dalam komentar tepat sebelum Anda, jika input kedua = 100, jawabannya = input pertama. Jika 100 benar-benar persentase bulat sedikit lebih rendah, lebih dari input pertama # upvotes akan diperlukan untuk mendapatkan suara bersih = input pertama, dan tantangan ini mencari jumlah terendah total upvotes.
WBT

Jawaban:

10

JavaScript (ES6), 47 byte

Mengambil input dalam sintaks currying (n)(p), di mana n adalah jumlah upvote bersih dan p adalah persentase upvote. Dapat kembali falseuntuk0 .

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

Cobalah online!

Berkomentar

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)

Kasus tepi

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

  • Jika u = 0 dan n = 0 , maka F n (u) = NaN dan F n (u) XOR p = p . Jadi, kita mengembalikan u = 0 jika n = p = 0 (iterasi pertama dari kasus uji pertama) atau melanjutkan dengan rekursi jika p! = 0 (iterasi pertama dari kasus uji ke-7).

  • Jika u> 0 dan u = n / 2 , maka F n (u) = + Infinity dan - lagi - F n (u) XOR p = p . Kecuali p = 0 , kita lanjutkan dengan iterasi berikutnya. (Ini terjadi pada kasus uji 9 dan 11.)

Arnauld
sumber
Bagus! Anda mendapatkan bonus pujian untuk pilihan bahasa, dan untuk menyertakan tautan + penjelasan ke demo langsung!
WBT
6

Stax , 17 byte

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

Jalankan dan debug itu

Ini adalah kekuatan kasar. Dimulai dengan 0 untuk kandidat upvotes, dan naik hingga memenuhi formula.

Dibongkar, tidak diserang, dan dikomentari, sepertinya ini.

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

Jalankan yang ini

rekursif
sumber
2

Bersih , 114 107 104 byte

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

Cobalah online!

Menentukan fungsi $ :: Int Int -> Real, di mana argumen bertanda integer dan nilai kembalinya adalah float presisi ganda yang dapat direpresentasikan dengan integer bertanda 32-bit.

Ini memeriksa setiap nilai cdalam persamaan b=-cd/(d+1)untuk menemukan yang bmemuaskan a+c=bdan b/(b+c)=d, karena chasil terkecil dalam terkecil b, ambil elemen pertama dari set semua solusi.

Suram
sumber
2

05AB1E , 13 byte [rusak ringan]

*²·т-/ò²т;Qi1

Cobalah online!

Penjelasan:

Untuk mengatasi ini, saya mengasumsikan input a, b dan hasil yang diharapkan x. Diberikan info dalam pengaturan, yang memberi saya persamaan:

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

Mengatur ulang untuk x memberi

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

Satu-satunya test case yang tidak berfungsi adalah 0, 50 - Saya hanya melakukan hardcode untuk memeriksa ini.

*²·т-/ò²т;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
sumber
Ini tidak berfungsi dengan benar untuk beberapa input. 90% dengan 800 suara bersih dapat dilakukan dengan 894 suara.
rekursif
@ Rekursif Saya tahu apa itu. Diasumsikan 90% tepat, bukan 89,5%.
Geno Racklin Asher
Nah, lebih dekat ke 90,5% dalam hal ini, tetapi ya.
rekursif
1
Sekarang saya sadar itu lebih sulit dari yang saya kira. Saya akan memikirkannya, tetapi untuk sekarang saya akan menandainya sudah rusak.
Geno Racklin Asher
@GenoRacklinAsher Sekarang saya menyadari itu lebih sulit daripada yang saya kira. Saya akan memikirkannya ... Itu adalah jenis komentar yang saya suka baca, melihatnya sebagai ciri khas teka-teki yang bagus :-).
WBT
0

Go 1.10, 154 byte

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}

Cobalah di Playground Go! (TIO menjalankan Go 1.9, yang tidak memiliki matematika. Putaran)

Versi tidak disatukan

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
}

Untuk menambahkan penjelasan, rumus di atas untuk r dapat diturunkan dengan menyelesaikan secara simultan n=v-ddan u = 100 * v/(v + d)untuk v, di mana v dan d adalah jumlah upvote dan downvotes masing-masing. Rumus turunan tidak terdefinisi untuk v = 50, jadi kita harus menangani kasus itu (yang kita lakukan dengan pernyataan if pertama).

ollien
sumber