Condividere la pizza in modo equo


13

La difficoltà nel condividere la pizza con gli amici è che è difficile assicurarsi che tutti ricevano la stessa quantità di peperoni sulla loro fetta. Quindi, il tuo compito è decidere come tagliare una pizza in modo equo in modo che tutti siano felici.

Indicazioni

Scrivi un programma che, dato un elenco delle posizioni dei peperoni su una pizza circolare e il numero di fette da fare, produce un elenco degli angoli in cui la pizza dovrebbe essere tagliata in modo che ogni fetta abbia la stessa quantità di peperoni su esso.

  • La pizza ha un solo condimento: peperoni.
  • Ai tuoi amici non importa delle dimensioni della loro fetta, solo che non sono imbrogliati da nessun peperone.
  • La pizza è un cerchio centrato sull'origine (0, 0)e con un raggio di1 .
  • I peperoni sono cerchi che sono centrati ovunque l'input dica che sono centrati e hanno un raggio di0.1
  • Prendi l'input come un numero intero che rappresenta il numero di sezioni da creare e un elenco di coppie ordinate che rappresentano le posizioni dei peperoni su un sistema di coordinate cartesiane. (In qualsiasi formato ragionevole)
  • L'output dovrebbe essere un elenco di angoli forniti in radianti che rappresentano le posizioni dei "tagli" rispetto alla pizza ( nell'intervallo0 <= a < 2pi ). (In qualsiasi formato ragionevole) (La precisione dovrebbe essere almeno +/- 1e-5.)
  • Puoi avere una porzione parziale di peperoni su una fetta (ad es. Se una pizza ha un peperone e deve essere condivisa da 10 persone, taglia la pizza dieci volte, taglia tutti i peperoni. Ma assicurati che sia giusto !)
  • Un taglio può (potrebbe essere necessario) tagliare più peperoni.
  • I peperoni possono sovrapporsi.

Esempi

Ingresso:

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

Possibile output valido:

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

Ecco una visualizzazione di questo esempio (ognuno ottiene mezzo peperone):

inserisci qui la descrizione dell'immagine

Altri esempi:

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

inserisci qui la descrizione dell'immagine

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

inserisci qui la descrizione dell'immagine

punteggio

Questo è , quindi vince il numero minimo di byte.


Con quale precisione devono essere considerati validi gli invii?
Rainbolt,

@Rainbolt Direi che 4 o 5 decimali dovrebbero essere sufficienti. Cosa suggerisci? Dovrei aggiungerlo alla domanda.
Kukac67,

Non sono sicuro che ogni problema sia risolvibile. E se ci fossero 7 fette e 3 peperoni uniformemente distanziati?
Nathan Merrill

1
@NathanMerrill Quindi tutti otterrebbero 3/7 di peperoni. :) (Le dimensioni delle fette non contano.)
kukac67,

1
Tentativo di cappello da pizza fallito. Chiedi una volta più facile una volta. ;)
Ilmari Karonen il

Risposte:


7

Mathematica, 221 byte

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

Questo definisce una funzione che prende come parametri il numero di sezioni e un elenco di coppie per le coordinate peperoni, come

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

Stampa le fette sulla console mentre attraversa la pizza.

Sulla maggior parte delle pizze, questo è abbastanza lento, perché (per ottenere la precisione richiesta) sto integrando l'area peperoni da 0 a 2π con incrementi di 1e-5. Per ottenere un risultato leggermente meno preciso in un ragionevole lasso di tempo, è possibile modificare il1.*^-5 alla fine in 1.*^-3.

Come funziona

L'idea è di spazzare via le fette di pizza mentre si integra sull'area dei pezzi di peperoni coperti. Ogni volta che quell'area colpisce la quantità richiesta di peperoni per persona, riportiamo l'angolo corrente e azzeriamo il contatore dell'area.

Per ottenere l'area dei peperoni spazzata via, interseciamo la linea con i peperoni per utilizzare le due distanze dall'origine, dove la linea si interseca con i peperoni. Poiché una linea si estende all'infinito in entrambe le direzioni, è necessario fissare queste distanze a valori non negativi. Questo risolve due problemi:

  • Contando le intersezioni con ogni peperoni due volte, una volta positivo e una volta negativo (che in realtà porterebbe a un'area complessiva di 0).
  • Contando solo zeppe di pezzi di peperoni che includono nell'origine.

Includerò alcuni schemi in seguito.


Sì. Questo era il mio piano di attacco. Almeno ora posso fare più facilmente esempi! : D
kukac67,

Ho notato che la tua implementazione a volte genera un angolo in più che creerebbe una fetta extra senza peperoni su di essa. (ad esempio con l'ingresso: [8, {{0.4, 0.2}, {-0.3, 0.1}, {-0.022, -0.5}, {0.3, -0.32}}])
kukac67

@ kukac67 riparato.
Martin Ender,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.