Jugando golf a los que odian

20

La puesta en marcha:

Una red social informa el número de votos que tiene una publicación de dos maneras: el número de votos a favor netos ( votos a favor totales - votos a favor totales) y el % de votos que fueron votos a favor , redondeados al número entero más cercano (.5 redondeos ). El número de votos a favor netos es un número entero (no necesariamente positivo), y se garantiza que el segundo sea un número entero entre 0 y +100 inclusive. La cantidad de votos a favor y la cantidad de votos a la baja son enteros de cero o positivos de 32 bits (puede especificar con signo o sin signo). Suponga que si hay cero votos totales, el porcentaje de votos votados se informa como cero.

El reto:

Dados estos dos enteros (votos a favor netos y% de votos a favor), ¿cuál es el programa más corto que puede escribir que determina el número más bajo de votos a favor totales que recibió la publicación, con todas las restricciones anteriores satisfechas?

Las restricciones de entrada están garantizadas. Si la entrada no satisface las restricciones anteriores, el comportamiento del programa depende de usted. Felicitaciones adicionales si no entra en un bucle infinito o si no se bloquea. Considere devolver un número negativo si desea más orientación.

Reglas generales:

  • Este es el , por lo que gana la solución válida más corta (medida en bytes).
  • No permita que los lenguajes de code-golf lo desanimen a publicar respuestas con lenguajes que no sean codegolfing. Trate de encontrar una respuesta lo más breve posible para 'cualquier' lenguaje de programación. Felicitaciones adicionales para un lenguaje web del lado del cliente como Javascript.
  • Si tiene soluciones interesantes en varios idiomas, publíquelas por separado .
  • Se aplican reglas estándar para su respuesta, por lo que puede usar STDIN / STDOUT, funciones / método con los parámetros adecuados y el tipo de retorno, o programas completos. Tu llamada.
  • Las lagunas predeterminadas están prohibidas.
  • Si es posible, agregue un enlace con una prueba para su código.
  • Además, agregue una explicación de cómo funciona el código.
  • Tenga en cuenta que si está realizando una operación de división de enteros que se trunca (por ejemplo, 20/3 = 6) en lugar de rondas , eso podría no ser completamente correcto.
  • Se aceptan casos de prueba adicionales que exploren los casos límite en las restricciones anteriores.
  • Si bien el tipo de retorno esperado es numérico, se puede usar "falso" booleano en lugar de 0 .

Ejemplos de casos de prueba:

La primera columna es solo un número de referencia incluido para facilitar la discusión.

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
fuente
Ese caso especial de cero votos totales es bastante delicado. Si hay un número igual de votos positivos y negativos, el porcentaje de votos positivos es del 50%, excepto que es del 0% cuando no hay votos, lo que rompe la simetría de votos positivos.
xnor
2
@xnor 0/0 generalmente no está definido, por lo que se debe hacer una suposición. Con esta opción, obtiene una "respuesta = segunda entrada" automática si la segunda entrada es 0, y una "respuesta = primera entrada" automática si la segunda entrada es 100.
WBT
1
Caso de prueba sugerido tomado de @nwellnhof: 1000, 100. ¿Puedes confirmar que la respuesta esperada es 1000?
Arnauld
1
Votados en contra, porque los que odian
deben
@Arnauld y nwellnhof: como se señaló en el comentario justo antes del suyo, si la segunda entrada = 100, la respuesta = primera entrada. Si el 100 fuera realmente un porcentaje ligeramente inferior redondeado, se requeriría más que el primer número de votos a favor para obtener votos netos = primer ingreso, y este desafío busca el número más bajo de votos a favor totales.
WBT

Respuestas:

10

JavaScript (ES6), 47 bytes

Toma información en la sintaxis de curry (n)(p), donde n es el número de votos a favor netos y p es el porcentaje de votos a favor. Puede volver falsepor0 .

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

Pruébalo en línea!

Comentado

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)

Casos de borde

Sea F n (u) = u / (u - n / 2) * 50 + 0.5

  • Si u = 0 y n = 0 , entonces F n (u) = NaN y F n (u) XOR p = p . Entonces, devolvemos u = 0 si n = p = 0 (primera iteración del primer caso de prueba) o continuamos con la recursividad si p! = 0 (primera iteración del séptimo caso de prueba).

  • Si u> 0 y u = n / 2 , entonces F n (u) = + Infinity y - de nuevo - F n (u) XOR p = p . A menos que p = 0 , simplemente continuamos con la siguiente iteración. (Esto sucede en los casos de prueba 9 y 11).

Arnauld
fuente
¡Agradable! ¡Obtienes felicitaciones adicionales por elegir el idioma y por incluir una explicación + enlace a una demostración en vivo!
WBT
6

Stax , 17 bytes

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

Ejecutar y depurarlo

Esta es la fuerza bruta. Comienza con 0 para los votos a favor del candidato y aumenta hasta que satisface la fórmula.

Desempaquetado, sin golf y comentado, se ve así.

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

Ejecute este

recursivo
fuente
2

Limpias , 114 107 104 bytes

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

Pruébalo en línea!

Define la función $ :: Int Int -> Real, donde los argumentos son enteros con signo y el valor de retorno es un flotante de doble precisión exactamente representable por un entero con signo de 32 bits.

Comprueba cada valor de cen la ecuación b=-cd/(d+1)para encontrar un resultado bsatisfactorio a+c=by b/(b+c)=d, dado que los cresultados más pequeños son los más pequeños b, toma el primer elemento del conjunto de todas las soluciones.

Οurous
fuente
2

05AB1E , 13 bytes [ligeramente roto]

*²·т-/ò²т;Qi1

Pruébalo en línea!

Explicación:

Para resolver esto, asumí las entradas a, by el resultado esperado x. Dada la información en la configuración, eso me dio la ecuación:

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

Reorganizar para x da

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

El único caso de prueba para el que esto no funciona es 0, 50, simplemente codifiqué para verificar esto.

*²·т-/ò²т;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
fuente
Esto no funciona correctamente para algunas entradas. El 90% con 800 votos netos se puede hacer con 894 votos.
recursivo
@recursivo Sé lo que es. Asume 90% exactamente, no 89.5%.
Geno Racklin Asher
Bueno, más cerca del 90.5% en este caso, pero sí.
recursivo
1
Ahora me doy cuenta de que es más complicado de lo que pensaba. Lo pensaré, pero por ahora lo marcaré como roto.
Geno Racklin Asher
@GenoRacklinAsher Ahora me doy cuenta de que es más complicado de lo que pensaba. Lo pensaré ... Esos son los tipos de comentarios que me gusta leer, viéndolos como el sello distintivo de un buen rompecabezas :-).
WBT
0

Ir 1.10, 154 bytes

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}

Pruébalo en Go Playground! (TIO ejecuta Go 1.9, que no tiene matemática. Redonda)

Versión sin golf

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
}

En aras de agregar una explicación, la fórmula anterior para r puede derivarse resolviendo simultáneamente n=v-dy u = 100 * v/(v + d)para v, donde v y d son el número de votos a favor y en contra, respectivamente. La fórmula derivada no está definida para v = 50, por lo que tenemos que manejar ese caso (lo que hacemos con la primera instrucción if).

ollien
fuente