Peggiore caso di esclusione di Manhattan


20

Immagina una W di H griglia di quadrati che si avvolge toroidalmente. Gli articoli vengono posizionati sulla griglia come segue.

Il primo oggetto può essere posizionato su qualsiasi quadrato, ma gli oggetti successivi non devono trovarsi a una distanza R di Manhattan da nessun elemento precedente (noto anche come un quartiere Von Neumann dell'intervallo R ). La scelta accurata delle posizioni consente di adattare un gran numero di elementi alla griglia prima che non vi siano più posizioni valide. Tuttavia, considera invece l'obiettivo opposto: qual è il numero più basso di oggetti che possono essere posizionati e non lasciare ulteriori posizioni valide?

Ecco una zona di esclusione raggio 5:

Zona di esclusione del raggio 5

Ecco un'altra zona di esclusione del raggio 5, questa volta vicino ai bordi, quindi il comportamento di avvolgimento è evidente:

Raggio di avvolgimento 5 zona di esclusione

Ingresso

Tre numeri interi:

  • W : larghezza della griglia (numero intero positivo)
  • H : altezza della griglia (numero intero positivo)
  • R : raggio della zona di esclusione (numero intero non negativo)

Produzione

Un numero intero N , che è il numero più piccolo di elementi che è possibile posizionare evitando ulteriori posizionamenti validi.

Dettagli

  • Un raggio di zero indica una zona di esclusione di 1 quadrato (quella su cui è stato posizionato l'oggetto).
  • Un raggio di N esclude la zona che può essere raggiunta in N passaggi ortogonali (ricordare che i bordi si avvolgono toroidalmente).

Il tuo codice deve funzionare per il banale caso di R = 0, ma non deve funzionare per W = 0 o H = 0.

Il tuo codice deve anche occuparsi del caso in cui R > W o R > H .

Termine e casi di test

Il codice deve essere in grado di gestire tutti i casi di test e ciascun caso di test deve essere completato entro 5 minuti. Questo dovrebbe essere semplice (l'esempio della soluzione JavaScript richiede alcuni secondi per ogni caso di test). Il limite di tempo è principalmente quello di escludere l'approccio della forza bruta estrema. L'approccio di esempio è ancora abbastanza bruto.

Se il codice viene completato entro 5 minuti su un computer ma non su un altro, sarà abbastanza vicino.

Casi di test negli input del modulo: output asW H R : N

5 4 4 : 1
5 4 3 : 2
5 4 2 : 2
5 4 1 : 5

7 5 5 : 1
7 5 4 : 2
7 5 3 : 2
7 5 2 : 4

8 8 8 : 1
8 8 7 : 2
8 8 6 : 2
8 8 5 : 2
8 8 4 : 2
8 8 3 : 4

 7  6  4 : 2
 7  6  2 : 4
11  7  4 : 3
11  9  4 : 4
13 13  6 : 3
11 11  5 : 3
15 14  7 : 2
16 16  8 : 2

Snippet per aiutare a visualizzare e giocare con le idee

Soluzione di esempio (non golfizzata)

Solo un esempio per piccoli output (risultanti da un raggio non molto inferiore alla larghezza e all'altezza). Può gestire uno qualsiasi dei casi di test, ma si interromperà e rinuncerà ai casi più grandi.


4
Frammento di codice fantastico!
Stretch Maniac,

@StretchManiac grazie :) Sto provando a imparare JavaScript quindi qualsiasi feedback è il benvenuto
trichoplax

1
È uno snippet piuttosto carino. Mi piace anche quella combinazione di colori. Viene da una tavolozza?
miglia,

@miles grazie - i colori sono solo indovinati e poi messi a punto un po '(ma non molto - sono ancora tutti e 3 i codici colore dei caratteri piuttosto che 6). Puoi vedere i colori usati nel terzo blocco di linee nel codice dello snippet.
trichoplax,

Risposte:


5

Python 2, 216 182 byte

def f(W,H,R):L={(i%W,i/W)for i in range(W*H)};M={(x,y)for x,y in L if min(x,W-x)+min(y,H-y)>R};g=lambda s:min([1+g(s-{((a+x)%W,(b+y)%H)for x,y in L-M})for a,b in s]or[1]);return g(M)

Inserisci come f(16,16,8). Utilizza praticamente lo stesso algoritmo del campione di @ trichoplax , ma con i set. Inizialmente non ho posizionato il primo oggetto (0, 0), ma questo mi ha fatto soffocare negli ultimi casi.

Tutti i casi sopra completati entro 10 secondi, ben al di sotto del limite. In effetti, i casi sono abbastanza piccoli da avere un po 'di spazio per essere meno efficiente, permettendomi di rimuovere un controllo che controllava gli stati duplicati.

(Grazie a @trichoplax per l'aiuto del golf)

Allargato:

def f(W,H,R):
  # All cells
  L={(i%W,i/W)for i in range(W*H)}                 

  # Mask: Complement of exclusion zone around (0, 0) 
  M={(x,y)for x,y in L if min(x,W-x)+min(y,H-y)>R}

  # Place recursively
  g=lambda s:min([1+g(s-{((a+x)%W,(b+y)%H)for x,y in L-M})for a,b in s]or[1])
  return g(M)

2

Python 3, 270 262 260 251 246 226

(Grazie a Sp3000 per:

  • -~ invece di +1 , che mi fa perdere uno spazio dopo return sull'ultima riga.
  • perdere parentesi superflue in giro W*H .
  • lambda ...
  • mettendo tutto su una linea.
  • python modulo %fornisce risultati positivi per numeri negativi, per salvare altri 20 byte)

Questa è la risposta di esempio JavaScript dalla domanda trasferita in Python 3.

Per evitare di dover passare così tanti argomenti di funzione, ho spostato le due funzioni di supporto all'interno della funzione di calcolo in modo che condividano il suo ambito. Ho anche condensato ciascuna di queste funzioni in un'unica riga per evitare il costo del rientro.

Spiegazione

Questo approccio di forza abbastanza bruta posiziona il primo oggetto su (0, 0), quindi segna tutti i quadrati esclusi. Quindi posiziona ricorsivamente un oggetto in tutti i quadrati validi rimanenti fino a quando tutti i quadrati sono esclusi e restituisce il numero minimo di elementi richiesti.

Codice golfizzato:

def C(W,H,R):r=range;M=lambda g:min([M(G(g,x,y))for x in r(W)for y in r(H)if g[x+W*y]]or[-1])+1;G=lambda g,x,y:[g[a+W*b]if min((x-a)%W,(a-x)%W)+min((y-b)%H,(b-y)%H)>R else 0for b in r(H)for a in r(W)];return-~M(G([1]*W*H,0,0))

Codice non golfato:

def calculate(W, H, R):
    starting_min = W * H + 1
    cells = [0] * (W * H)
    grid_state = grid_with_item_added(cells, 0, 0, W, H, R)
    return min_from_here(grid_state, starting_min, W, H, R) + 1

def min_from_here(grid_state, starting_min, W, H, R):
    no_cells = True
    min = starting_min
    for x in range(W):
        for y in range(H):
            if grid_state[x + W * y] == 0:
                no_cells = False
                new_grid_state = grid_with_item_added(grid_state, x, y, W, H, R)
                m = min_from_here(new_grid_state, starting_min, W, H, R)
                if m < min:
                    min = m

    if no_cells:
        return 0
    else:
        return min + 1

def grid_with_item_added(grid_state, x, y, W, H, R):
    grid = grid_state[:]
    for a in range(W):
        for b in range(H):
            if manhattan_distance(a, b, x, y, W, H) <= R:
                grid[a + W * b] = 1

    return grid

def manhattan_distance(a, b, c, d, W, H):
    horizontal = min(abs(W + c - a) % W, abs(W + a - c) % W)
    vertical = min(abs(H + d - b) % H, abs(H + b - d) % H)
    return horizontal + vertical


if __name__ == '__main__':
    import sys
    arguments = sys.argv[1:]
    if len(arguments) < 3:
        print('3 arguments required: width, height and radius')
    else:
        print(calculate(int(arguments[0]), int(arguments[1]), int(arguments[2])))

Il codice ungolfed definisce una funzione e include anche il codice per consentirne la chiamata dalla riga di comando. Il codice golfed definisce semplicemente la funzione, che è sufficiente per le domande standard sul golf del codice .

Se desideri testare il codice golfed dalla riga di comando, eccolo qui con la gestione della riga di comando inclusa (ma non golfed):

Codice golf testabile dalla riga di comando

def C(W,H,R):r=range;M=lambda g:min([M(G(g,x,y))for x in r(W)for y in r(H)if g[x+W*y]]or[-1])+1;G=lambda g,x,y:[g[a+W*b]if min((x-a)%W,(a-x)%W)+min((y-b)%H,(b-y)%H)>R else 0for b in r(H)for a in r(W)];return-~M(G([1]*W*H,0,0))

if __name__ == '__main__':
    import sys
    arguments = sys.argv[1:]
    if len(arguments) < 3:
        print('3 arguments required: width, height and radius')
    else:
        print(C(int(arguments[0]), int(arguments[1]), int(arguments[2])))
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.