Pizza fair teilen

13

Die Schwierigkeit, Pizza mit Freunden zu teilen, besteht darin, dass es schwierig ist, sicherzustellen, dass jeder die gleiche Menge Peperoni auf seinem Stück bekommt. Ihre Aufgabe ist es also, zu entscheiden, wie Sie eine Pizza fair in Scheiben schneiden, damit alle glücklich sind.

Richtungen

Schreiben Sie ein Programm, das anhand einer Liste der Positionen von Pepperonis auf einer runden Pizza und der Anzahl der zu schneidenden Scheiben eine Liste der Winkel ausgibt, unter denen die Pizza geschnitten werden sollte, sodass auf jeder Scheibe die gleiche Menge von Pepperonis liegt es.

  • Die Pizza hat nur einen Belag: Peperoni.
  • Ihre Freunde kümmern sich nicht um die Größe ihrer Scheibe, nur dass sie nicht um irgendwelche Peperoni betrogen werden.
  • Die Pizza ist ein auf den Ursprung zentrierter Kreis (0, 0)mit einem Radius von1 .
  • Die Pepperonis sind Kreise, die dort zentriert sind, wo die Eingabe angibt, dass sie zentriert sind und einen Radius von haben0.1
  • Nehmen Sie die Eingabe als Ganzzahl , die die Anzahl der zu erstellenden Schnitte und eine Liste der geordneten Paare darstellt , die die Positionen der Pepperonis auf einem kartesischen Koordinatensystem darstellen. (In jedem vernünftigen Format)
  • Die Ausgabe sollte eine Liste von Winkeln im Bogenmaß sein , die die Positionen der "Schnitte" zur Pizza (im Bereich0 <= a < 2pi ) darstellen. (In jedem vernünftigen Format) (Präzision sollte mindestens sein +/- 1e-5.)
  • Sie können teilweise Stücke einer Peperoni auf einer Scheibe haben (z. B. wenn eine Pizza eine Peperoni hat und diese von 10 Personen geteilt werden muss, schneiden Sie die Pizza zehnmal durch, wobei alle Schnitte durch die Peperoni schneiden. Aber stellen Sie sicher, dass sie fair sind !)
  • Eine geschnittene Dose kann (muss) mehrere Pepperonis in Scheiben schneiden.
  • Pepperonis kann sich überlappen.

Beispiele

Eingang:

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

Mögliche gültige Ausgabe:

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

Hier ist eine Visualisierung dieses Beispiels (jeder bekommt eine halbe Peperoni):

Bildbeschreibung hier eingeben

Mehr Beispiele:

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

Bildbeschreibung hier eingeben

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

Bildbeschreibung hier eingeben

Wertung

Das ist , also gewinnt die geringste Anzahl von Bytes.

kukac67
quelle
Mit welcher Genauigkeit müssen Einsendungen eingehalten werden, um als gültig zu gelten?
Rainbolt
@Rainbolt Ich würde sagen, dass 4 oder 5 Nachkommastellen ausreichen sollten. Was schlagen Sie vor? Ich sollte es der Frage hinzufügen.
Kukac67
Ich bin mir nicht sicher, ob jedes Problem lösbar ist. Was ist, wenn 7 Scheiben und 3 Peperoni gleichmäßig verteilt sind?
Nathan Merrill
1
@ NathanMerrill Dann würde jeder 3/7 einer Peperoni bekommen. :) (Größe der Scheiben spielt keine Rolle.)
Kukac67
1
Pizzahutversuch fehlgeschlagen. Fragen Sie beim nächsten Mal einen einfacheren. ;)
Ilmari Karonen

Antworten:

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]])&

Ungolfed:

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]
   ]
) &

Dies definiert eine Funktion, die als Parameter die Anzahl der Schnitte und eine Liste von Paaren für die Peperoni-Koordinaten verwendet, wie z

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

Die Slices werden auf der Konsole gedruckt, während sie die Pizza durchlaufen.

Bei den meisten Pizzas ist dies ziemlich langsam, da ich (um die erforderliche Präzision zu erreichen) den Pepperoni-Bereich von 0 bis 2π in Schritten von 1e-5 integriere. Um in angemessener Zeit ein etwas ungenaueres Ergebnis zu erhalten, können Sie das 1.*^-5am Ende auf ändern 1.*^-3.

Wie es funktioniert

Die Idee ist, die Pizzastücke auszuräumen und dabei über die Fläche der bedeckten Peperoni-Stücke zu integrieren. Immer wenn dieser Bereich die erforderliche Menge an Peperoni pro Person erreicht, melden wir den aktuellen Winkel und setzen den Bereichszähler zurück.

Um die überstrichene Peperoni-Fläche zu erhalten, schneiden wir die Linie mit der Peperoni und geben die beiden Abstände vom Ursprung an, in denen sich die Linie mit der Peperoni schneidet. Da eine Linie in beiden Richtungen unendlich verläuft, müssen diese Abstände auf nicht negative Werte geklemmt werden. Dies löst zwei Probleme:

  • Zweimaliges Zählen der Schnittpunkte mit jedem Peperoni, einmal positiv und einmal negativ (was tatsächlich zu einer Gesamtfläche von 0 führen würde).
  • Zählen Sie nur Keile von Peperoni-Stücken, die im Ursprung enthalten sind.

Ich werde später einige Diagramme hinzufügen.

Martin Ender
quelle
Ja. Das war mein Angriffsplan. Zumindest kann ich jetzt leichter Beispiele machen! : D
kukac67
Mir ist aufgefallen, dass Ihre Implementierung manchmal einen zusätzlichen Winkel ausgibt, der ein zusätzliches Segment ohne Pepperoni erzeugt. (zB mit Eingabe: [8, {{0.4, 0.2}, {-0.3, 0.1}, {-0.022, -0.5}, {0.3, -0.32}}])
kukac67
@ kukac67 behoben.
Martin Ender