Compartir pizza de manera justa

13

La dificultad de compartir pizza con amigos es que es difícil asegurarse de que todos tengan la misma cantidad de pepperoni en su porción. Por lo tanto, su tarea es decidir cómo cortar una pizza de manera justa para que todos estén felices.

Direcciones

Escriba un programa que, dada una lista de las posiciones de pepperonis en una pizza circular y el número de rebanadas que se deben hacer, emite una lista de los ángulos en los que se debe cortar la pizza para que cada rebanada tenga la misma cantidad de pepperoni eso.

  • La pizza tiene un solo ingrediente: pepperoni.
  • A tus amigos no les importa el tamaño de su rebanada, solo que no están engañados con ningún pepperoni.
  • La pizza es un círculo centrado en el origen (0, 0)y con un radio de1 .
  • Los pepperonis son círculos centrados donde la entrada dice que están centrados y tienen un radio de0.1
  • Tome la entrada como un número entero que representa el número de cortes que se harán y una lista de pares ordenados que representan las posiciones de los pepperonis en un sistema de coordenadas cartesianas. (En cualquier formato razonable)
  • La salida debe ser una lista de ángulos en radianes que represente las posiciones de los "cortes" de la pizza (en el rango0 <= a < 2pi ). (En cualquier formato razonable) (La precisión debe ser al menos +/- 1e-5).
  • Puede tener trozos parciales de un pepperoni en una rebanada (p. Ej., Si una pizza tiene un pepperoni y necesita ser compartida por 10 personas, corte la pizza diez veces, todos los cortes cortando el pepperoni. Pero asegúrese de que sea justo !)
  • Un corte puede (puede ser necesario) cortar múltiples pepperonis.
  • Pepperonis puede superponerse.

Ejemplos

Entrada:

8 people, pepperonis: (0.4, 0.2), (-0.3, 0.1), (-0.022, -0.5), (0.3, -0.32)

Posible salida válida:

slices at:
0, 0.46365, 0.68916, 2.81984, 3.14159, 4.66842, 4.86957, 5.46554

Aquí hay una visualización de este ejemplo (todos obtienen medio pepperoni):

ingrese la descripción de la imagen aquí

Más ejemplos:

Input: 9 people, 1 pepperoni at: (0.03, 0.01)
Output: 0, 0.4065, 0.8222, 1.29988, 1.94749, 3.03869, 4.42503, 5.28428, 5.83985

ingrese la descripción de la imagen aquí

Input: 5, (0.4, 0.3), (0.45, 0.43), (-0.5, -0.04)
Output: 0, 0.64751, 0.73928, 0.84206, 3.18997

ingrese la descripción de la imagen aquí

Puntuación

Este es el , por lo que gana el menor número de bytes.

kukac67
fuente
¿Con qué precisión deben adherirse los envíos para ser considerados válidos?
Rainbolt
@Rainbolt Yo diría que 4 o 5 decimales deberían ser suficientes. ¿Que sugieres? Debería agregarlo a la pregunta.
kukac67
No estoy seguro de que todos los problemas tengan solución. ¿Qué pasa si hay 7 rebanadas y 3 pepperoni espaciados uniformemente?
Nathan Merrill
1
@NathanMerrill Entonces todos obtendrían 3/7 de un pepperoni. :) (El tamaño de las rodajas no importa.)
kukac67
1
Intento de sombrero de pizza falló. Pide una más fácil la próxima vez. ;)
Ilmari Karonen

Respuestas:

7

Mathematica, 221 bytes

f=(A=Pi.01Length@#2/#;l=m/.Solve[Norm[{a,b}-m{Cos@t,Sin@t}]==.1,m];k=(l/.{a->#,b->#2})&@@@#2;d=1.*^-5;For[Print[h=B=0];n=1,n<#,h+=d,(B+=If[Im@#<0,0,d(Max[#2,0]^2-Max[#,0]^2)/2])&@@@(k/.{t->h});If[B>A,n+=1;Print@h;B-=A]])&

Sin golf:

f = (
   A = Pi .01 Length@#2/#;
   l = m /. Solve[Norm[{a, b} - m {Cos@t, Sin@t}] == .1, m];
   k = (l /. {a -> #, b -> #2}) & @@@ #2;
   d = 1.*^-5;
   For[Print[h = B = 0]; n = 1, n < #, h += d,
    (
      B += If[Im@# < 0, 0, d (Max[#2, 0]^2 - Max[#, 0]^2)/2]
    ) & @@@ (k /. {t -> h});
    If[B > A, n += 1; Print@h; B -= A]
   ]
) &

Esto define una función que toma como parámetros el número de cortes y una lista de pares para las coordenadas de peperoni, como

f[8, {{0.4, 0.2}, {-0.3, 0.1}, {-0.022, -0.5}, {0.3, -0.32}}]

Imprimirá las rebanadas en la consola mientras atraviesa la pizza.

En la mayoría de las pizzas, esto es bastante lento, porque (para lograr la precisión requerida) estoy integrando el área de peperoni de 0 a 2π en pasos de 1e-5. Para obtener un resultado un poco menos preciso en un período de tiempo razonable, puede cambiar el 1.*^-5al final a 1.*^-3.

Cómo funciona

La idea es barrer las rebanadas de pizza mientras se integra sobre el área de las piezas de peperoni cubiertas. Cada vez que esa área alcanza la cantidad requerida de salchichón por persona, informamos el ángulo actual y reiniciamos el contador de área.

Para obtener el área de peperoni barrida, intersectamos la línea con el peperoni para dar uso a las dos distancias desde el origen, donde la línea se cruza con el peperoni. Dado que una línea se extiende hasta el infinito en ambas direcciones, necesitamos sujetar estas distancias a valores no negativos. Esto resuelve dos problemas:

  • Contando las intersecciones con cada salchichón dos veces, una vez positiva y otra negativa (lo que en realidad daría como resultado un área general de 0).
  • Contando solo trozos de peperoni que se incluyen en el origen.

Incluiré algunos diagramas más adelante.

Martin Ender
fuente
Sí. Este era mi plan de ataque. ¡Al menos ahora puedo hacer ejemplos más fácilmente! : D
kukac67
Me di cuenta de que su implementación a veces genera un ángulo adicional que crearía una rebanada adicional sin pepperoni. (por ejemplo, con entrada: [8, {{0.4, 0.2}, {-0.3, 0.1}, {-0.022, -0.5}, {0.3, -0.32}}])
kukac67
@ kukac67 arreglado.
Martin Ender