Игра в гольф ненавистников


20

Настройка:

Социальная сеть сообщает о количестве голосов в сообщении двумя способами: количество чистых голосов (общее количество голосов - общее количество голосов) и процент голосов, которые были проголосовавшими , округляются до ближайшего целого числа (округляется в сторону увеличения до 0,5). Число чистых голосов является целым числом (не обязательно положительным), а второе гарантировано будет целым числом от 0 до +100 включительно. Количество положительных голосов и количество отрицательных голосов являются либо нулевыми, либо положительными 32-разрядными целыми числами (вы можете указать знак со знаком или без знака). Предположим, что при нулевом общем количестве голосов процент проголосовавших считается равным нулю.

Соревнование:

С учетом этих двух целых чисел (нетто-голосов и% голосов), какую самую короткую программу вы можете написать, которая определяет наименьшее количество общих голосов, полученных постом, с соблюдением всех вышеуказанных ограничений?

Входные ограничения гарантированы. Если ввод не удовлетворяет вышеуказанным ограничениям, поведение программы зависит от вас. Бонус слава, если он не входит в бесконечный цикл или иным образом вылетает. Подумайте о возврате отрицательного числа, если вам нужны дополнительные указания

Основные правила:

  • Это , поэтому выигрывает самое короткое действительное решение (измеряется в байтах).
  • Не позволяйте языкам кода-гольфа отговаривать вас от публикации ответов на языках, не относящихся к кодексу. Попробуйте придумать как можно более короткий ответ для «любого» языка программирования. Бонусы за клиентский веб-язык, такой как Javascript.
  • Если у вас есть интересные решения на нескольких языках, опубликуйте их отдельно .
  • К вашему ответу применяются стандартные правила , поэтому вы можете использовать STDIN / STDOUT, функции / метод с правильными параметрами и типом возврата или полные программы. Ваш звонок.
  • Лазейки по умолчанию запрещены.
  • Если возможно, добавьте ссылку с тестом для вашего кода.
  • Также, пожалуйста, добавьте объяснение того, как работает код.
  • Имейте в виду, что если вы выполняете целочисленную операцию деления, которая усекает (например, 20/3 = 6), а не округляет , это может быть не совсем правильно.
  • Дополнительные тестовые случаи, которые исследуют крайние случаи в вышеупомянутых ограничениях, приветствуются.
  • Хотя ожидаемый тип возвращаемого значения является числовым, вместо 0 можно использовать логическое «false» .

Пример тестовых случаев:

Первый столбец - это просто ссылочный номер, включенный для облегчения обсуждения.

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

Этот особый случай с нулевым общим голосованием довольно привередлив. Если число голосов «за» и «против» одинаково, процент голосов «за» составляет 50%, за исключением того, что 0%, когда голосов нет, нарушая симметрию голосов «против».
xnor

2
@xnor 0/0 обычно не определено, поэтому необходимо сделать предположение. При таком выборе вы получаете автоматический «ответ = второй вход», если второй вход равен 0, и автоматический «ответ = первый вход», если второй вход равен 100.
WBT

1
Похожий тест заимствовано из @nwellnhof: 1000, 100. Можете ли вы подтвердить, что ожидаемый ответ 1000?
Арно

1
Понижено, потому что ненавистники должны ненавидеть :)
Hosch250

@Arnauld и nwellnhof: как отмечалось в комментарии перед вашим, если второй вход = 100, ответ = первый вход. Если бы 100 был действительно округленным чуть более низким процентом, то для получения чистых голосов = первого ввода потребовалось бы больше, чем первый ввод числа голосов «против», и эта задача ищет наименьшее количество всех голосов «против».
WBT

Ответы:


10

JavaScript (ES6), 47 байт

Принимает входные данные в синтаксисе карри (n)(p), где n - количество чистых голосов, а p - процент голосов. Может вернуться falseза0 .

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

Попробуйте онлайн!

комментарии

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)

Краевые случаи

Пусть F n (u) = u / (u - n / 2) * 50 + 0,5

  • Если u = 0 и n = 0 , то F n (u) = NaN и F n (u) XOR p = p . Таким образом, мы возвращаем u = 0, если n = p = 0 (первая итерация первого тестового случая), или продолжаем рекурсию, если p! = 0 (первая итерация 7-го тестового случая).

  • Если u> 0 и u = n / 2 , то F n (u) = + бесконечность и - снова - F n (u) XOR p = p . Если p = 0 , мы просто продолжим следующую итерацию. (Это происходит в 9-м и 11-м тестовых случаях.)


Ницца! Вы получаете премию за выбор языка, а также за включение объяснения + ссылку на живую демонстрацию!
WBT

6

Stax , 17 байт

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

Запустите и отладьте его

Это грубая сила. Он начинается с 0 для возможных голосов и увеличивается до тех пор, пока не будет удовлетворять формуле.

Распакованный, размазанный и прокомментированный, это выглядит так.

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

Запустите этот


2

Чисто , 114 107 104 байта

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

Попробуйте онлайн!

Определяет функцию $ :: Int Int -> Real , где аргументы представляют собой целые числа со знаком, а возвращаемое значение представляет собой число с плавающей запятой двойной точности, точно представляемое 32-разрядным целым числом со знаком.

Он проверяет каждое значение cв уравнении, b=-cd/(d+1)чтобы найти bудовлетворяющий, a+c=bи b/(b+c)=d, поскольку наименьший cрезультат приводит к наименьшему b, берут первый элемент множества всех решений.


2

05AB1E , 13 байтов [слегка сломан]

*²·т-/ò²т;Qi1

Попробуйте онлайн!

Объяснение:

Чтобы решить эту проблему, я предположил, что входные данные a, b и ожидаемый результат x. Учитывая информацию в настройке, это дало мне уравнение:

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

Перестановка для х дает

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

Единственный тестовый случай, для которого это не работает, это 0, 50 - я просто жестко запрограммирован, чтобы проверить это.

*²·т-/ò²т;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(...)] }

Это не работает правильно для некоторых входов. 90% с 800 чистыми голосами могут быть сделаны с 894 голосами "за".
рекурсивный

@ рекурсивный, я знаю, что это такое. Предполагается, что 90% точно, а не 89,5%.
Гено Раклин Ашер

Ну, ближе к 90,5% в этом случае, но да.
рекурсивный

1
Теперь я понимаю, что это хитрее, чем я думал. Я подумаю об этом, но пока я отмечу это как сломанный.
Гено Раклин Ашер

@GenoRacklinAsher Теперь я понимаю, что это хитрее, чем я думал. Я подумаю об этом ... Это те комментарии, которые я люблю читать, рассматривая их как отличительный признак хорошей головоломки :-).
WBT

0

Go 1.10, 154 байта

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}

Попробуйте это на Go Playground!(TIO запускает Go 1.9, в котором нет математики. Раунд)

Неуправляемая версия

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
}

В интересах добавления объяснения вышеприведенная формула для r может быть получена путем одновременного решения n=v-dи u = 100 * v/(v + d)для v, где v и d являются числом повышающих и понижающих голосов соответственно. Производная формула не определена для v = 50, поэтому мы должны обработать этот случай (что мы делаем с первым оператором if).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.