¡Felicitaciones por obtener 10,000 reputación!

19

¡Después de que @ MartinBüttner logró exactamente 10,000 reputación , ahora tenemos tres filas completas de 10k usuarios en la página de usuarios ! Ahora, dado que todos somos programadores aquí, nos gusta automatizar las cosas en lugar de hacerlo manualmente. Su desafío es escribir un programa para felicitar automáticamente a los nuevos usuarios de 10k.

Especificación

Entrada

La entrada será nlíneas de números separados por espacios. (Si lo desea, también puede tomar una sola lista separada por comas de números separados por espacios, si eso acorta su código). Por ejemplo:

10 20 30 40 50
15 25 35 45 55
20 30 40 50 60

O:

10 20 30 40 50,15 25 35 45 55,20 30 40 50 60

Cada lista de números representa una lista de valores de reputación de los usuarios en un solo día.

Salida

El resultado será la misma cantidad de nlíneas (o una lista separada por comas de la misma longitud). Cada elemento de línea / lista será:

  • :D si hubo un usuario cuya reputación se convirtió en> = 10,000
    • Múltiples correos separados por espacios :Dsi hubo varios usuarios que cumplieron o pasaron el conteo de 10,000 repeticiones. Por ejemplo, :D :D :Dpara 3 nuevos usuarios de 10k.
  • :( y luego detener la salida adicional si la entrada es ambigua o imposible (más sobre esto en la siguiente sección).
  • nada si ninguna de estas condiciones es cierta.

Ambigüedad

Es posible que la entrada sea ambigua. Para los propósitos de este desafío, asumimos que:

  • El límite de reputación es de 200 por día, ignorando aceptaciones y recompensas y similares por el bien del desafío.
  • Los usuarios no pueden perder reputación (nuevamente por simplicidad y por el desafío).

La entrada se considera ambigua cuando es imposible determinar qué valores de reputación corresponden a qué usuario. Por ejemplo, en la entrada 10 20,30 40, no puede saber si el usuario de 10 repeticiones se convirtió en el usuario de 30 repeticiones o en el usuario de 40 repeticiones.

La entrada se considera imposible cuando los usuarios de un día no podrían haberse convertido en usuarios del día siguiente. Por ejemplo, en la entrada 10 20,310 320, esta situación es claramente imposible porque los usuarios no podrían haber ganado 300 reputación en un día. Los usuarios que pierden reputación también son imposibles.

Casos de borde

  • Los valores iniciales de reputación pueden comenzar en cualquier cosa (es decir, un usuario puede comenzar con 1337 reputación).
  • No hay salida para el primer elemento de línea / lista.
  • La entrada siempre será sintácticamente válida, lo que significa que los valores de reputación siempre serán enteros positivos, siempre habrá la misma cantidad de valores de reputación por elemento de línea / lista, etc.
  • Los valores de reputación no están ordenados; Pueden estar en cualquier orden.

Casos de prueba

Entrada: 9900,10000
Salida::D

Entrada: 9900 9950 9910,10100 9950 9910,10300 10150 10110
Salida::D,:D :D

Entrada: 10 20 30,42 10 20,10 242 20,442 42 10,0 0 0,442 42 10
Salida:,,,:(

Entrada: 10 20,15 25,15 25
Salida:,,

Entrada: 9999 9998 9997,10000 9998 9997,10000 10000 9997,10300 10000 10000
Salida::D,:D,:(

Entrada: 100,90,80,70
Salida::(

Entrada: 10000 10000 10000 9999,10000 10000 10000 10000,10010 10020 10030 10040
Salida::D,:(

Entrada: 9999 9998 9997 9996,10196 10197 10198 10199,10399 10199 10197 10196
Salida::D :D :D :D,

Pomo de la puerta
fuente
@ MartinBüttner Ah, no me di cuenta de eso. Corregido
Pomo de la puerta
El primer paso en ese ejemplo también es ambiguo.
Martin Ender
1
Mientras que el ejemplo 4 no es ambiguo.
Martin Ender
(i.e. a user can start with 1337 reputation).Me gustó este porque era mi representante ... hace 5 minutos hasta que alguien votó por una de mis respuestas xD
Teun Pronk
Ejemplo 5, el paso 2 también es ambiguo (¿qué usuario de 10k es cuál?). Lo mismo ocurre con el ejemplo 7 (a menos que agregue alguna regla que indique que los usuarios con igualdad de repeticiones son irrelevantes, pero entonces, ¿cómo sabe qué usuario era cuál el primer día, si se relacionó con otra persona más tarde?)
Martin Ender

Respuestas:

12

Rubí, 209 bytes

Editar: cambié a Ruby, que acortó esto en aproximadamente un 30%. Vea el historial de edición para la versión original de Mathematica. Supongo que los ahorros principales provienen de que Ruby permutationno ignora las posiciones cambiadas de elementos idénticos (en lo que tuve que engañar a Mathematica).

Esto utiliza el formato separado por nueva línea.

gets.split('
').map{|s|s.split.map &:to_i}.each_cons(2){|a,b|a.permutation.map{|q|q.zip(b).map{|x,y|y-x}}.reject{|d|d.any?{|x|x<0||x>200}}.size!=1?abort(':('):(puts':D '*(a.count{|d|d<1e4}-b.count{|d|d<1e4}))}

La esencia es esta:

  • Obtenga todos los pares de días consecutivos.
  • Obtenga todas las permutaciones del día anterior y reste cada una de ellas del día actual.
  • Elimine todos los resultados que contengan diferencias que sean negativas o mayores 200.
  • Si el número de permutaciones restantes no es 1, salida :(.
  • De lo contrario, genere tantos :Dcomo haya nuevos usuarios de 10k.
  • Al final, deja caer todos los días después del primero :(.

Menos golf:

gets.split("\n").map{|s|
  s.split.map &:to_i
}.each_cons(2){|a,b|
  a.permutation.map{|q|
    q.zip(b).map{|x,y|
      y-x
    }
  }.reject{|d|
    d.any?{|x|
      x<0||x>200
    }
  }.size!=1 ? abort(':(') : (puts ':D '*(a.count{|d|d<1e4}-b.count{|d|d<1e4}))
}

Creo que esa es una hermosa cadena de enumeradores. :)

PS: ¿Es raro que yo era el primero en presentar una respuesta a esto?

Martin Ender
fuente
8
No creo que sea raro. Algo me dice que tienes la ventaja de jugar en casa;)
Calvin's Hobbies
Entonces esto fallará algunos de los ejemplos en la pregunta, ¿verdad?
Cruncher el
@Cruncher Fallará aquellos que creo que están mal de acuerdo con las especificaciones (como he mencionado en los comentarios). Si Doorknob decide cambiar la especificación en lugar de arreglar los ejemplos, supongo que tendré que modificar esto.
Martin Ender
@ MartinBüttner Eso es lo que pensé. Solo confirmando :)
Cruncher
6

Haskell, 254 249 244 232 228

import Data.List
t=m(9999<)
p(a:b:r)=(a,b,r)%(filter(all(`elem`[0..200]))$nub$m(zipWith(-)b)$permutations a)
p _=""
(a,b,r)%(_:[])=(concat$m(const":D ")$t b\\t a)++'\n':p(b:r)
_%_=":("
m=map
main=interact$p.m(m read.words).lines

Una pequeña explicación: el algoritmo es muy similar al utilizado por MartinBüttner, excepto en el nubque pensé un poco. Tenga en cuenta que una diferencia de lista se utiliza para la elaboración de la cantidad de reputación más valores son 10.000 o mayor en el día n + 1 en comparación con el día n: t b\\t a.

También estoy de acuerdo con MartinBüttner en la interpretación de las especificaciones y en que algunos de los ejemplos anteriores son incorrectos, incluso hasta el punto de que el ejemplo # 2 es incorrecto (debería ser :().

La Inquisición Española
fuente
¿No deberías alias map?
orgulloso Haskeller
1
Es correcto (guardar 2 bytes), pero se pueden guardar otros 10 bytes haciendo zinfijo y reemplazándolo replicate (length l) xpor map (const x) l. ¿Haskell no es fantástico?
TheSpanishInquisition
Seguro que lo es. Buen golf! En esa nota, debido a que la aplicación de función tiene la mayor precedencia, debería poder acortar (t b)\\(t a)a t b\\t a4 campos más.
orgulloso Haskeller
Sería bueno si hubiera algún código para encontrar estos lugares donde el código se puede acortar automáticamente ... Sin embargo, parece un proyecto un poco grande.
orgulloso Haskeller
Tienes razón @proudhaskeller, esos paréntesis no eran necesarios. Gracias.
TheSpanishInquisition