N queens, X by Y board karar problemi mülakat sorusu


10

Bugün bir röportajda şu soru soruldu ve o zamandan beri düşünüyorum. Buna cevap veremedim ve çevrimiçi bir çözüm bulamadım.

Y ve N kraliçelerinin X ölçülerine sahip bir satranç tahtası verildiğinde, bu kraliçeleri tahtaya birbirlerine saldıramayacakları şekilde yerleştirmenin mümkün olup olmadığını belirleyin.

2 kraliçeli 2 x 3 kartın bir çözümü var, bu yüzden algoritma doğru dönecekti:

Q . .
. . Q

Bu bulmacanın programlama yaklaşımını arıyorum, sadece kağıt üzerinde çözmenin yolları değil.


En İyi İlk Arama kesinlikle bir seçenektir ve diğer arama buluşsal yöntemleri
Jason

2
şimdiye kadarki en kötü röportaj sorularından birine aday gösterildi - üzerinde çalıştıkları yazılım geri izleme çözümlerine dayanmıyorsa, bu durumda tamamen alakalı
Steven A. Lowe

1
Adil olmak gerekirse, görüşmeci bunun sadece ekstra bir kredi türü olduğunu söyledi. Röportajın geri kalanı oldukça yasal IMO'ydu. Sadece merak ettim.
Röportaj

Belki de cevabında Caleb tarafından belirtilen gerçekleri kullanarak O (1) çözümünü geri izleme veya (bulmayı düşünmek) ile bir simülasyon yapıp yapamayacağı bir testti. Basit şeyleri programlama yeteneği, kişinin işte ihtiyaç duyduğu her şey değildir.
Sopel

ödevler burada açıkça kapsam dışıdır.
jwenting

Yanıtlar:


16

Bu (IMO) programlama açısından çok ilginç bir sorun değil. Her düzenlemeyi deneyen, şöyle bir özyinelemeli algoritma ile gelebilirsiniz:

bool try_queens(Board board, int n)
{
    if (n == 0) {
        // no queens left to place, so we're done
        return true
    }
    // try each open position until we find one that works
    for each position on the board {
        if (is_empty(board, position) and not is_attacked(board, position)) {
            place_queen(board, position)
            if (try_queens(board, n-1)) {
                return true
            }
            remove_queen(board, position)
        }
    }
    // if we get this far, there's no available position
    return false
}

main()
{
    initialize board(X,Y)
    return try_queens(board, N)
}

Sorunu biraz düşünürseniz, X <N veya Y <N olan bir tahtaya N kraliçesi sığdırmanın bir yolu olmadığını anlayacaksınız, çünkü bu en az iki kraliçenin aynı sırada veya dosyada olmasını gerektirecektir, ve bu yüzden birbirlerine saldırırlardı. N-queens problemini okursanız N> N için NxN panosuna N que'leri yerleştirmenin her zaman mümkün olduğunu çabucak öğreneceksiniz. Şimdi cevabın NO (X <N veya Y <N) için olduğunu biliyoruz. ve YES (X> = N ve Y> = N, N> 3) için. Geriye kalan tek şey özel durumlar:

  • N = 1 (EVET)
  • N = 2 (X için EVET = 2 ve Y> 2 veya tam tersi)
  • N = 3 (X için EVET = 3 ve Y> 3 veya tam tersi)

Şimdi güzel özyinelemeli fonksiyonumuz, sadece N ile X ve Y'yi karşılaştıran ve hazır bir sonuç veren basit bir fonksiyon haline gelir. Bu, performans açısından harika, çünkü sabit zamanda cevap alabilirsiniz. Programlama açısından o kadar da iyi değil, çünkü bu noktada sorunun, bulmacaları ne kadar iyi çözebileceğinizle ilgili olduğunu, tekrarlayan bir fonksiyon yazma yeteneğinizden çok daha iyi olduğunu fark ediyorsunuz.

(Ve oğlum ah oğlum, gerçekten benim smarty-pantolon cevabımda aptalca bir hata yapmadığımı umuyorum. ;-)


That's great from a performance point of view, since you can get an answer in constant time. It's not so great from a programming point of view because you realize, at this point, that the question is really more about how well you can solve puzzles than it is about your ability to write a recursive function.Aslında görüşmecinin bu O (1) çözümünü beklediğini düşünüyorum çünkü sonuçta daha iyi ve birçok insan için açık değil. Nxn kraliçesi problemi tüm programlama derslerinde özyineleme için bir alıştırmadır - birçok insan bu sorunu tekrar gördüğünde daha derin düşünmeyecektir.
Sopel

4

Görüşmeci sizden sorunun kodunu yazmanızı istediyse, bunun adil olmadığını düşünüyorum. Algoritma iş gerektirir. Bununla birlikte, fikir, görüşmeciye kullanmanız gereken sınıfları, yöntemleri veya bazı kavramları veya benzer bir şeyi göstermekse, bu adil bir soru olabilir.

Sorun klasik bir Bilgisayar Bilimi problemidir ve bu tür birçok kitapta tartışılmıştır. Animasyon ile mükemmel bir açıklama ve bazı kodlarla birlikte 12 farklı çözüm burada bulunabilir:

http://en.wikipedia.org/wiki/Eight_queens_puzzle

Ayrıca kodu burada bulabilirsiniz: http://www.codeproject.com/KB/java/EightQueen.aspx

Dediğim gibi, bu konuda üzülmeyin, kolay bir şey değil.


0

Bu gerçekten bir yorum daha, ama orada uymuyor ...

Bir satranç tahtasının 8x8 karesi vardır, artık daha az değil (bu sorular her zaman özelleştirilmiş bir satranç tahtasının bu yaklaşımıyla beni rahatsız ediyor).

Ama her neyse, eğer bir x * y satranç tahtanız ve n kraliçeniz varsa ve kraliçenin bu alanları "aldığını"

resim açıklamasını buraya girin

iki boyutlu bir dizi oluşturabilir ve bir kraliçenin saldırdığı tüm alanları "işaretleyebilir". Sonra diğerini (tahtanın ortasından) yerleştirin, kalan alanları işaretleyin, vb. Siz alanlar veya kraliçeler çalışana kadar.

Bu elbette çok basitleştirilmiş bir yaklaşımdır, çünkü kötü bir şekilde yerleştirilirse, maksimum kraliçe sayısının değişebileceğini toplarım.

Hmm, bunu da buldum - 8 kraliçe sorunu.


İlk başta bu tam algoritmayı önerdim, ancak bu yaklaşımı uygularsanız ve son Kraliçenizi gerçekten belirlediğiniz hiçbir yere koymazsanız, bunun imkansız olduğunu garanti edemeyeceğinizi düşünün. Sadece bu düzenlemeyi ortadan kaldırdınız. Bu temel olarak en yakın komşu buluşsal yöntemidir.
Mülakat

@Interviewee - Evet, biliyorum. Bu sadece kafamın üstünde düşündüğüm bir şey. Dediğim gibi, bu ilginç bir sorun ve muhtemelen geliştirilebilir, ama 04:00 (burada) düşünmek için çok tembelim. Btw, röportaj nasıl geçti?
Kale

@ Görüşmeci, bu doğru fikir. Eksik olan kısım, son kraliçe için yer olmadığını fark ederseniz, yedekleyin ve ikinci ila son kraliçe için farklı bir konum deneyin. Eğer o kraliçe için son kraliçenin yerleştirilmesine izin veren bir yer yoksa, başka bir seviyeye geri dönersiniz ve üçüncü ila son kraliçe için farklı bir yer denersiniz, vb.
Caleb

Ben senin avatar bir satranç taş gibi :)
warren

0

Temel olarak, backtrack algoritması şu şekilde çalışır:

  1. Bir X by Y dizisi oluşturun. Tüm kareleri boş olarak ayarlayın.

  2. Kraliçe sayısını sıfıra ayarlayın.

  3. Geçerli konumunuzu (1,1) olarak ayarlayın

  4. Geçerli pozisyonda bir kraliçe yerleştirip yerleştiremeyeceğinize bakın.

  5. Yapabiliyorsanız, Dizi (X, Y) değerini kraliçe olarak ayarlayın, kraliçe sayısını artırın. Eğer tüm kraliçeyi yerleştirirseniz, durun , bir çözümünüz var.

  6. Geçerli konum (X, Y) değilse, geçerli konumu artırın ve 4. adıma gidin.

  7. Son pozisyondaki kraliçeyi bulun (pozisyonları artırdığınız sırada son gelen). Geçerli konumu o kraliçenin konumuna getirin, kaldırın ve kraliçe sayısını azaltın.

  8. Kraliçe sayısı sıfır ise, dur , çözüm yok.

  9. Geçerli konumu artırın.

  10. 4. adıma gidin.


Bu açıklamada algoritma doğru şekilde geri izlemiyor: sadece son yerleştirilebilen kraliçeyi kaldırıyor; başka pozisyonlarda daha önce kraliçeleri denememe riskiyle karşı karşıya kalırsınız.
Kasper van den Berg

@KaspervandenBerg Algoritma doğru şekilde geri döner. Eleştirilerine doğrudan cevap verirdim, ama dürüstçe anlayamıyorum. "Son yerleştirilebilir kraliçe" ile ne demek istediğini bilmiyorum. Sadece son yerleştirilen kraliçeyi kaldıracaktır, ancak herhangi bir kraliçe kaldırıldıktan sonra yerleştirilen kraliçeler son yerleştirilen kraliçe olabilir. Kraliçeleri yerleştirildikleri sıralamanın tersine kaldırarak gerektiğinde geriye doğru takip eder.
David Schwartz

0

Diğer cevaplara ekleme: iki boyutlu bir dizi oluşturmak sadece kodu karmaşıklaştırır.

Normal bir satranç tahtası için sadece 8 boyutunda bir vektöre ihtiyacınız var. Veya C 1 pozisyonu 0 ise 8 + 1, sadece kodu basitleştirmek ve 0-7 ile değil 1-8 ile ilgilenmek için.

X'in dizideki konumunuz ve y konumun içeriği olduğunu düşünüyorsanız. örneğin tahta [1] = 8, ilk kraliçenin [1,8] olduğu anlamına gelir.

Bu şekilde, yalnızca sütun doğrulamasını kontrol etmeniz gerekir.

Fakülte zamanında, Dartmouth BASIC'te uygulanan algoritmalar hakkında, daha az bellek kullanarak (bu eski olmak, mantıklı) 8 kraliçe problemini uygulayan çok eski bir kitapla (60'lar?) Karşılaştım.

Hatırladığım kadarıyla, vektör fikrini kullandı ve esasen kaba tüm pozisyonları iki FOR döngüsü ile zorladı. Konum geçerliliğini kontrol etmek için üçüncü bir döngü kullandı, her pozisyonda bir WHILE döngüsü vektörde geri döndü ve eşit bir sayı olup olmadığını veya diyagonalleri kontrol etmek için teğet bir işlem kullanan bir formül kontrol etti.

Ne yazık ki, bu kitabın kaydını kaybettim ...

Bahsedilen algoritma n-queen probleminin tüm çözümlerini buldu.


0

Böyle bir düzenlemenin var olup olmadığını belirlemek için bir algoritma yazmanız gerekiyorsa, mevcut araştırmaya bakın:
Sekiz kraliçe Wikipedia'da bulmaca .

N> min (X, Y) ise önemsiz olarak false değerini döndürebilirsiniz.
Bu sayfayı okuduktan sonra, N <= min (X, Y) ve 2, 3! = Min (X, Y) ise true değerini döndürmeyi bilirsiniz.

Bu da 2, 3 == dk (X, Y) ve N <= dk (X, Y) bırakır.

N <min (X, Y) ise, bir çözüm bulmak önemsizdir.
N == dak (X, Y) ise, yalnızca maks (X, Y)> N ise bir çözüm vardır.

f(X, Y, N)
    if X < Y => f(Y, X, N)
    if Y > N => false
    => (Y < N) or (Y != 2 and Y != 3) or (X > N)

0

N> min (X, Y) ise hiç bir çözüm yoktur. Aksi takdirde, N = X = Y = 2, N = X = Y = 3 için bir çözüm olmadığını kolayca gösterebilirsiniz. Diğer tüm durumlar için bir çözüm var gibi görünüyor. N büyüdükçe çözümlerin sayısı artıyor gibi görünüyor.

Geri izlemeyle kapsamlı arama yaparak bir çözüm bulabilirsiniz: Birinci sıraya, sütun 1'e bir kraliçe koyun. İkinci sıraya, 1. sıradaki kraliçenin ulaşamayacağı ilk sütuna bir kraliçe koyun. İkinci sıraya bir kraliçe vb. Koyun. Eğer bir kraliçe k sırasına konulamazsa, o zaman onu kaldırır ve kraliçeyi bir sonraki boş pozisyonda k-1 satırına taşırsınız.

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.