Jogando golfe fora dos inimigos

20

A configuração:

Uma rede social relata o número de votos de uma postagem de duas maneiras: o número de votos líquidos (total de votos - total de votos negativos ) e a % de votos que foram votados , arredondados para o número inteiro mais próximo (0,5 arredondamentos para cima). O número de upvotes líquidos é um número inteiro (não necessariamente positivo), e o segundo é garantido como um número inteiro entre 0 e +100, inclusive. O número de votos upvotes e o número de downvotes são números inteiros de zero ou positivos de 32 bits (você pode especificar assinado ou não). Suponha que, se houver zero total de votos, a porcentagem votada acima seja relatada como zero.

O desafio:

Dado esses dois números inteiros (votações líquidas e% votadas), qual é o programa mais curto que você pode escrever, que determina o número mais baixo de votações totais totais da postagem recebida, com todas as restrições acima satisfeitas?

As restrições de entrada são garantidas. Se a entrada não atender às restrições acima, o comportamento do programa depende de você. Kudos de bônus se não entrar em um loop infinito ou travar. Considere retornar um número negativo se desejar mais orientação.

Regras gerais:

  • Isso é , então a solução válida mais curta (medida em bytes) vence.
  • Não permita que idiomas com código de golfe o desencorajem a postar respostas com idiomas que não sejam codegolf. Tente encontrar uma resposta o mais curta possível para 'qualquer' linguagem de programação. Parabéns por uma linguagem da Web do lado do cliente, como Javascript.
  • Se você tiver soluções interessantes em vários idiomas, publique-as separadamente .
  • As regras padrão se aplicam à sua resposta, para que você possa usar STDIN / STDOUT, funções / método com os parâmetros e tipo de retorno adequados ou programas completos. Sua chamada.
  • As brechas padrão são proibidas.
  • Se possível, adicione um link com um teste para o seu código.
  • Além disso, adicione uma explicação de como o código funciona.
  • Lembre-se de que se você estiver executando uma operação de divisão inteira que trunca (por exemplo, 20/3 = 6) em vez de arredondamentos , isso pode não estar totalmente correto.
  • Casos de teste adicionais que exploram os casos extremos nas restrições acima são bem-vindos.
  • Enquanto o tipo de retorno esperado é numérico, booleano "false" pode ser usado no lugar de 0 .

Exemplos de casos de teste:

A primeira coluna é apenas um número de referência incluído para facilitar a discussão.

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
fonte
Esse caso especial com total de zero votos é bastante exigente. Se houver um número igual de votos positivos e negativos, a porcentagem de votos positivos é de 50%, exceto que é 0% quando não há votos, quebrando a simetria de votos positivos e negativos.
Xnor
2
@xnor 0/0 geralmente é indefinido, portanto, uma suposição deve ser feita. Com esta escolha, você recebe uma "resposta = segunda entrada" automática se a segunda entrada é 0, e um automático "resposta = primeira entrada" se a segunda entrada é 100.
WBT
1
Caso de teste sugeriu emprestado de @nwellnhof: 1000, 100. Você pode confirmar que a resposta esperada é 1000?
Arnauld
1
Downvoted, porque odeiam tem que odeio :)
Hosch250
@ Arnauld e nwellnhof: conforme observado no comentário antes da sua, se a segunda entrada = 100, a resposta = primeira entrada. Se os 100 eram realmente uma porcentagem arredondada um pouco menor, seria necessário mais do que o primeiro número de votos para obter votos líquidos = primeira entrada, e esse desafio busca o menor número de votos totais.
WBT

Respostas:

10

JavaScript (ES6), 47 bytes

Recebe entrada na sintaxe de currying (n)(p), em que n é o número de votos líquidos e ep é a porcentagem de votos positivos. Pode retornar falsepara0 .

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

Experimente online!

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 borda

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

  • Se u = 0 e n = 0 , então F n (u) = NaN e F n (L) XOR p = p . Portanto, retornamos u = 0 se n = p = 0 (primeira iteração do primeiro caso de teste) ou continuamos com a recursão se p! = 0 (primeira iteração do sétimo caso de teste).

  • Se u> 0 e u = n / 2 , então F n (u) = + Infinito e - novamente - F n (u) XOR p = p . A menos que p = 0 , continuemos com a próxima iteração. (Isso acontece nos casos 9 e 11 de teste.)

Arnauld
fonte
Agradável! Você recebe elogios de bônus pela escolha do idioma e por incluir um link + explicação para uma demonstração ao vivo!
WBT
6

Stax , 17 bytes

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

Execute e depure

Isso é força bruta. Começa com 0 para votos positivos do candidato e é incrementado até satisfazer a fórmula.

Descompactado, não jogado e comentado, parece com isso.

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

Execute este

recursivo
fonte
2

Limpo , 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

Experimente online!

Define a função $ :: Int Int -> Real, na qual os argumentos são números inteiros assinados e o valor de retorno é um número flutuante de precisão dupla exatamente representável por um número inteiro assinado de 32 bits.

Ele verifica todos os valores da cequação b=-cd/(d+1)para encontrar uma bsatisfatória a+c=be b/(b+c)=d, já que os menores cresultados são os menores b, assume o primeiro elemento do conjunto de todas as soluções.

Furioso
fonte
2

05AB1E , 13 bytes [levemente quebrado]

*²·т-/ò²т;Qi1

Experimente online!

Explicação:

Para resolver isso, assumi as entradas a, be o resultado esperado x. Dadas as informações na configuração, isso me deu a equação:

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

Reorganizar para x dá

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

O único caso de teste para o qual não funciona é 0, 50 - simplesmente codifiquei para verificar isso.

*²·т-/ò²т;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
fonte
Isso não funciona corretamente para algumas entradas. 90% com 800 votos líquidos pode ser feito com 894 votos positivos.
recursivo
@ recursivo Eu sei o que é. Assume 90% exatamente, não 89,5%.
Geno Racklin Asher
Bem, mais perto de 90,5% neste caso, mas sim.
recursivo
1
Agora eu percebo que é mais complicado do que eu pensava. Vou pensar, mas por enquanto vou marcar como quebrado.
Geno Racklin Asher
@GenoRacklinAsher Agora eu percebo que é mais complicado do que eu pensava. Vou pensar nisso ... Esses são os tipos de comentários que gosto de ler, vendo-os como a marca registrada de um bom quebra-cabeça :-).
WBT
0

Go 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}

Experimente no Go Playground! (O TIO executa o Go 1.9, que não possui matemática.

Versão ungolfed

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
}

No interesse de adicionar uma explicação, a fórmula acima para r pode ser derivada resolvendo simultaneamente n=v-de u = 100 * v/(v + d)para v, em que v e d são o número de votos positivos e negativos, respectivamente. A fórmula derivada é indefinida para v = 50, portanto, temos que lidar com esse caso (o que fazemos com a primeira instrução if).

ollien
fonte