En Kötü Durum Manhattan Dışlama


20

Toroidal olarak sarılı bir W by H kareler ızgarası düşünün . Öğeler ızgaraya aşağıdaki gibi yerleştirilir.

İlk öğe herhangi bir kareye yerleştirilebilir, ancak sonraki öğeler önceki herhangi bir öğenin ( R aralığı Von Neumann mahallesi olarak da bilinir) Manhattan mesafesi R içinde olmamalıdır . Konumları dikkatlice seçmek, geçerli konumlar olmadan çok sayıda öğenin ızgaraya yerleştirilmesine izin verir. Ancak bunun yerine tam tersi düşünün: Yerleştirilebilecek ve başka geçerli pozisyon bırakmayacak en az öğe sayısı nedir?

İşte bir yarıçap 5 hariç tutma bölgesi:

Yarıçap 5 hariç tutma bölgesi

İşte bir başka yarıçap 5 hariç tutma bölgesi, bu sefer kenarlara yakın, böylece sarma davranışı belirgindir:

Sarma yarıçapı 5 hariç tutma bölgesi

Giriş

Üç tamsayı:

  • W : ızgaranın genişliği (pozitif tamsayı)
  • H : ızgara yüksekliği (pozitif tamsayı)
  • R : hariç tutma bölgesinin yarıçapı (negatif olmayan tam sayı)

Çıktı

Geçerli yerleşimleri engellemek için yerleştirilebilecek en az sayıda öğe olan bir tamsayı N.

ayrıntılar

  • Sıfır yarıçapı 1 kare (öğenin yerleştirildiği alan) hariç tutma bölgesi verir.
  • N yarıçapı N dikey adımda ulaşılabilen bölgeyi hariç tutar (kenarların toroidal olarak sarıldığını unutmayın).

Kodunuzun önemsiz R = 0 durumunda çalışması gerekir , ancak W = 0 veya H = 0 için çalışması gerekmez .

Kodunuz ayrıca R > W veya R > H'nin bulunduğu durumla da ilgili olmalıdır .

Zaman sınırı ve test senaryoları

Kodunuz tüm test senaryolarıyla ilgilenebilmeli ve her test senaryosu 5 dakika içinde tamamlanmalıdır. Bu kolay olmalıdır (örnek JavaScript çözümünün her test vakası için birkaç saniye sürmesi gerekir). Zaman sınırı esas olarak aşırı kaba kuvvet yaklaşımını dışlamaktır. Örnek yaklaşım hala oldukça kaba kuvvettir.

Kodunuz bir makinede 5 dakika içinde tamamlanır ancak başka bir makinede tamamlanmazsa, yeterince yakın olacaktır.

Form girişlerindeki test senaryoları: 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

Fikirlerle görselleştirmeye ve oynamaya yardımcı olan snippet

Örnek (çözülmemiş) çözelti

Küçük çıktılar için sadece bir örnek (genişlik ve yükseklikten çok daha küçük olmayan yarıçaptan kaynaklanır). Herhangi bir test vakasını halledebilir, ancak zaman aşımına uğrar ve daha büyük vakalardan vazgeçer.


4
Harika kod snippet'i!
Stretch Maniac

@StretchManiac thanks :) JavaScript öğrenmeye çalışıyorum böylece herhangi bir geri bildirim hoş geldiniz
trichoplax

1
Bu çok hoş bir pasaj. Ben de o renk düzenini seviyorum. Bir paletten mi?
mil

@miles teşekkür ederim - renkler sadece tahmin edilir ve sonra biraz ince ayarlanır (ancak çok fazla değil - hala 6 yerine 3 karakter renk kodudur). Parçacık kodunda üçüncü satır bloğunda kullanılan renkleri görebilirsiniz.
trichoplax

Yanıtlar:


5

Python 2, 216 182 bayt

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)

Gibi girin f(16,16,8). @ Trichoplax'ın örneğiyle hemen hemen aynı algoritmayı kullanır , ancak setlerle birlikte. Başlangıçta ilk öğeyi yerleştirmedim (0, 0), ancak bu son birkaç durumda boğulmasını sağladı.

Yukarıdaki tüm durumlar 10 saniye içinde, limitin çok altında. Aslında, vakalar daha az verimli olması için küçük bir oda vardı yeterince küçük, yinelenen durumlar için kontrol bir çek kaldırmak için izin.

(Golf yardımı için @ trichoplax'a teşekkürler)

Expanded:

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

Piton 3, 270 262 260 251 246 226

(Sp3000 için teşekkürler:

  • -~ yerine +1 , hangi beni sonra boşluk kaybetmek sağlayan return son satırında.
  • gereksiz parantezleri kaybetmek W*H .
  • lambda'lar ...
  • her şeyi tek bir satıra koyarak.
  • python modulo %, 20 byte daha tasarruf etmek için negatif sayılar için olumlu sonuç verir)

Bu, Python 3'e taşınan sorunun JavaScript örnek cevabıdır.

Çok sayıda işlev bağımsız değişkenini iletmek zorunda kalmamak için, hesaplama işlevinin içindeki iki destekleyici işlevi, kapsamını paylaşacak şekilde taşıdım. Ayrıca girinti maliyetini önlemek için bu işlevlerin her birini tek bir satırda yoğunlaştırdım.

açıklama

Bu oldukça kaba kuvvet yaklaşımı ilk öğeyi (0, 0) 'a yerleştirir ve sonra hariç tutulan tüm kareleri işaretler. Daha sonra, tüm kareler hariç tutulana kadar bir öğeyi yinelenen tüm geçerli karelere yerleştirir ve gereken minimum öğe sayısını döndürür.

Golf kodu:

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

Kod çözülmemiş kod:

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

Çözülmemiş kod bir işlevi tanımlar ve komut satırından çağrılmasına izin vermek için kod içerir. Golf kodu sadece standart kod golf soruları için yeterli olan fonksiyonu tanımlar .

Golf kodunu komut satırından test etmek isterseniz, burada komut satırı işleme dahil (ancak golf değil):

Komut satırı test edilebilir golf kodu

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])))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.