Mantıksal Nokta Şekilleri


12

Oyun

Son zamanlarda, zamanımın çoğu, telefonumdaki Logic Dots adlı bir bağımlılık yapıcı oyun tarafından ele geçirildi ve bu bana bu zorluğu yazmam için ilham verdi. Size oyun ekranını gösterirsem kuralları açıklamak daha kolaydır, bu yüzden çözülmemiş ve çözülmüş bir bulmacanın ekran görüntüsü:

Şimdi burada dikkat edilmesi gereken üç ana şey var.

  1. Oyun tahtası (merkezdeki 4x4 kareler ızgarası)
  2. Tüm çizgiler veya a1 dikdörtgenle gerekli şekiller (üstten ikinci çubukta, puan ve menü altında vb.) Bağlantılı noktalar
  3. Bir çözüm için sütunlarda kaç noktanın olması gerektiğini gösteren satır ve sütunların üzerindeki sayılar

Oyunun amacı gerekli şekilleri ızgaraya sığdırmaktır. Şekilleri döndürebilirsiniz, ancak çapraz olarak giremezler.

Çözümde, tüm şekillerin tam olarak bir kez oluşturulduğuna dikkat edin (çünkü sadece bir kez gerekli şekillerde bulunurlar) ve bu durumda hepsi yataydır, ancak dikey olabilirler. Karelerle doldurulmuş pembe, kullanılmayan kareleri gösterir.

İşte daha büyük ve biraz daha karmaşık bir tablo:

Çözülmemiş yapboz, zaten silik meydanlarda dolu birkaç kare var olduğunu Bildirimi o kareler bloke delalet CAN NOT üstünde bir nokta koyun. Kuyruklu noktalar size bir noktanın o noktada olduğunu söyler ve kuyruk yönünde en az bir noktaya bağlanır, ancak başka bir yönde değil (zıt yön dahil).

Gösterim

Bu yazının geri kalanı için, aşağıdaki sembolleri kullanarak panoya başvuracağım:

  • <,>, ^, v - Kuyruk noktası yönünde uzanan önceden yerleştirilmiş bir noktayı belirtir
  • * - Bir noktayı belirtir. Çözülmemiş bir ızgarada (giriş) verilirse, ayrı bir şekildir. Çıkışta ise, etrafındaki noktalara bağlanır.
  • # - Engellenen ızgara karesini belirtir (nokta yerleştiremeyeceğiniz yer)
  • -, | (kısa çizgi ve çubuk) - Sağ ve sol kuyruklu bir noktayı ve sırasıyla yukarı ve aşağı kuyruklu bir noktayı belirtin
  • ** (boşluk karakteri) - ** Boş bir alanı belirtir

Bu sembolleri kullanarak, ikinci örnek olay (çözülmemiş) aşağıdaki gibi temsil edilebilir:

 <    



    # 
 ^ #

Ve çözüm şu şekilde temsil edilebilir:

*< * *
   *  
     *
 *   *
 * *#*
 ^ # *

Hiçbir şeklin yatay, dikey veya çapraz olarak dokunamayacağını unutmayın , bu nedenle aşağıdaki durum geçerli değildir:

 *** 
**   
  ** 

Meydan okuma

Senin meydan okuma 4x4 9x9 dahil, herhangi bir mantık nokta bulmaca çözmek için. Dört giriş satırı, daha sonra oyun tahtası alacaksınız. Çizgiler aşağıdaki gibi olacaktır:

  • 1. satır, Şekiller - Her biri formda verilen sizexquantity(örneğin 3x2, üç uzunluklu iki şekil için) bulunan ve bir boşlukla ayrılmış bulunan şekiller. Örnek çizgi:3x1 2x1 1x1
  • 2. satır, Sütunlar - Her sütun için gereken nokta sayısının boşlukla ayrılmış bir listesi. Örnek çizgi:1 1 2 2
  • 3. satır, Satırlar - Her satır için gereken nokta sayısının boşlukla ayrılmış bir listesi. Örnek çizgi:3 0 3 0
  • 4. satır, Kart boyutu - Tek bir tam sayı, kart boyutu, B

Daha sonra tahta verilir ve Byukarıda belirtilen notasyonu kullanarak tahtayı temsil eden girdi hatlarıdır. Örneğin, ikinci örnek vaka için tam girdi aşağıdaki gibidir:

4x1 3x1 2x2 1x2
1 4 0 3 0 5
4 1 1 2 3 2
6
 <    



    # 
 ^ #  

Programınız daha sonra aynı gösterimde çözülmüş anakartı çıkarır. Yukarıdaki giriş için eşleşen çıkış aşağıdaki gibidir:

** * *
   *  
     *
 *   *
 * *#*
 * # *

Bir oyun tahtasının birden fazla çözümü olabileceğini unutmayın. Bu durumda, sadece geçerli bir çözüm üretin. Ayrıca, programınızın karmaşık bir 10x10 ızgarası için makul bir masaüstü bilgisayarda 10 saniye içinde doğru bir çözüm üretmesi gerekir.

Bu kod golf, yani en az bayt kazanır.


Test Durumları

Giriş 1

3x2 1x4
2 2 3 1 2
4 0 3 0 3
5


    #
  #  
    *

Çıktı 1

*** *

 ***#
  #  
* * *

Giriş 2

3x1 1x6
2 0 4 0 3
3 1 2 1 2
5
*    


   # 

Çıktı 2

* * *
  *  
  * *
*  # 
  * *

Giriş 3

5x1 4x1 2x1 1x2
1 2 3 3 2 2
0 5 0 4 0 4
6
#     
  -   


 #    
   <  

Çıkış 3

#     
 *****

 **** 
 #    
* ** *

Evet, bu doğru @flawr
globby

@flawr t no two shapes can touch horizontally, vertically or diagonally(bu başlangıçta olmalı, neredeyse sonuna kadar kaybetmemeli, ama yine de ...)
edc65

@globby Her boş alan # ile değiştirilmez mi, sanırım #, oyunda boş bir alana tek bir kez dokunduğunuzda. Bir seviyeyi bitirdiğinizde tüm boş hücreleri doldurur.
Teun Pronk

@ #TeunPronk No. #, ikinci örnekteki gri kareler gibi, seviyeye bir nokta yerleştiremeyeceğiniz önceden belirlenmiş boşluklardır.
globby

2
Ödül teklif etmekten daha iyi, daha ilginç test örnekleri eklemeli ve sorunuzdaki hataları düzeltmelisiniz. Örneğin, mevcut test
senaryolarından

Yanıtlar:


3

Python 2: 766 739 696 663 633 bayt

def f(B,S,o=0):
 if[]==S:print'\n'.join(B);exit()
 s=S[0]
 for i in r:
  for j in R(Z-s+1):
   if(B[i][j]in' '+'>v'[o])*(B[i][j+s-1]in' '+'<^'[o])*({' ','-|'[o]}>=set(B[i][j+1:j+s-1]))*all(B[x][y]in'# 'for x,y in [(x,y)for y in R(j-1,j+s+1)for x in i-1,i+1]+[(i,j-1),(i,j+s)]if 0<=x<Z>y>=0):q=B[:];q[i]=q[i][:j]+'*'*s+q[i][j+s:];q=(q,t(q))[o];any((t(q)+q)[k].count('*')>m[k]for k in R(Z+Z))or f(q,S[1:])
 o or f(t(B),S,1)
y=raw_input;S=[];s=str.split
for i in s(y()):u,v=map(int,s(i,'x'));S+=[u]*v
m=map(int,s(y())+s(y()));Z=input();R=range;r=R(Z);B=[y()for _ in r];J=''.join;t=lambda x:map(J,zip(*x))
f(B,S[:len(S)-J(B).count('*')])

Çevrimiçi çalıştığını görün: Ideone.com (Çevrimiçi sürüm, büyük ve zor ızgaralar için çok yavaş olabilir, çevrimdışı olması iyi olmalıdır)

Giriş stdin üzerinden yapılır, sadece OP'den satırları kopyalayıp geçebilirsiniz (ancak dikkatli olun, stackexchange bazen boşlukları veya satırları siler).

Bu kodun bazı temel fikirleri: Özyinelemeli bir işlev kullanır f. ftahtaya bir şekil koymaya çalışır. Olası her konum için kendisini değiştirilmiş kartla çağırır. İçinde 3 döngü var. oyönü belirler (2 - yatay, 3 - dikey). Her zaman şekli yatay olarak yerleştirir, bu nedenle sonunda o=2tahta işleviyle yer değiştirir t. isatırdır ve jtümü olası başlangıç ​​sütunlarıdır. Ardından, şeklin uçlarının geçerli karakterleri varsa, şeklin ortasında geçerli karakterleri varsa ve çevresi boşsa, çok fazla kontrol gerçekleşir.


Son düzenlemenizi (-30) gördüğümde ve vazgeçtiğimde son 6 baytı kesmek için uğraşıyordum ... Ne kadar değerli
olduğuna dair oyum

3

JavaScript (ES6) 661 667 695 702 745 755 786 790 784 798

Devam eden çalışmalar kısaltılabilir. Muhtemelen karmaşık bir ızgarada çok yavaş. Belki de değil.

Düzenle Biraz daha uzun, çok daha hızlı.
Düzenle 2 Hata düzeltme, sütun / satır kontrolü. Bu arada, şimdi daha hızlı

M işlevi ana işlevdir. W parametresi, tüm girişleri içeren çok satırlı bir dizedir. Fonksiyon girişi ayrıştırır ve bir başlangıç ​​kartı hazırlar. Karakterler <>^v|-*başlangıç panosunda ile değiştirildiği ,her biri ,ile değiştirilmesi gerekir *doğru çözelti içinde.

R işlevi, tüm şekilleri tahtaya yerleştirmek için özyinelemeli olarak çalışır. Bir şekil yerleştirildiğinde, kendisini daha kısa bir şekiller listesinden ve değiştirilmiş anakarttan geçirmeye çağırır. Tüm şekiller yerleştirildiğinde, ,değiştirilmediği takdirde bir çözüm yine de geçersiz olabilir *.

Bir şeklin yerleştirilip yerleştirilemeyeceği P fonksiyon testi aa verilen bir konum ve yönelim. Tüm maliyetleri kontrol eder (kartın içinde, çakışma yok, dokunma yok, geçerli satır ve sütun sayısı)

M=w=>(
  [x,c,r,z]=w=w[S='split'](n='\n'),
  (b=[...w.slice(4).join(n)])
  .map((c,p)=>~(k='*<>-*^v|'.indexOf(c))&&[(q=k>3?z:1,0),k&1&&-q,k&2&&q].map(o=>b[p+o]=0),
    c=c[S](e=' '),r=r[S](e),w=z++,f='*',s='',x[S](e).map(v=>s+=v[0].repeat(v[2]))),
  R=(s,b,x=0,y=0,n=s[0],V=i=>b[i]>'#',
    P=(p,o,q,t,g,l,d=[...b])=>{
        if(l<z-n&!V(p+o*l-o)&!V(p+o*l+o*n))
        {
          for(i=-1;v=d[p],++i<w;p+=o,t-=v==f)
            if(i>=l&i-n<l)
              for(v!=e&v!=0|[q,w,~z].some(w=>V(p+w)|V(p-w))?t=0:d[p]=f,j=o*i,u=k=0;
                  ++k<z;(u+=d[j]==f)>g[i]?t=0:j+=q);
          return t>=n&&d.join('')
        }
    })=>{
    if(b){
      if(!n)return~b.search(0)?0:b;
      for(s=s.slice(1);y<w||(y=0,++x<w);++y)
        if(h=R(s,P(y*z,1,z,r[y],c,x))||n>1&&R(s,P(x,z,1,c[x],r,y)))return h
    }
  })(s,b)

FireFox / FireBug konsolunda test et

;['3x2 1x4\n2 2 3 1 2\n4 0 3 0 3\n5\n     \n     \n    #\n  #  \n    *\n'
,'3x1 1x6\n2 0 4 0 3\n3 1 2 1 2\n5\n*    \n     \n     \n   # \n     \n'
,'5x1 4x1 2x1 1x2\n1 2 3 3 2 2\n0 5 0 4 0 4\n6\n#     \n  -   \n      \n      \n #    \n   <  \n'
,'4x1 3x1 2x2 1x2\n1 4 0 3 0 5\n4 1 1 2 3 2\n6\n <    \n      \n      \n      \n    # \n ^ #  \n']
.forEach(x=>console.log(x,M(x).replace(/ /g,'`'))) // space replaced with ` for clarity

Çıktı (toplam yürütme süresi <1sn)

3x2 1x4
2 2 3 1 2
4 0 3 0 3
5


    #
  #  
    *

***`*
`````
`***#
``#``
*`*`*

3x1 1x6
2 0 4 0 3
3 1 2 1 2
5
*    


   # 


*`*`*
``*``
``*`*
*``#`
``*`*

5x1 4x1 2x1 1x2
1 2 3 3 2 2
0 5 0 4 0 4
6
#     
  -   


 #    
   <  

#`````
`*****
``````
`****`
`#````
*`**`*

4x1 3x1 2x2 1x2
1 4 0 3 0 5
4 1 1 2 3 2
6
 <    



    # 
 ^ #  

**`*`*
```*``
`````*
`*```*
`*`*#*
`*`#`*

Görünüşe göre @globby bu ödülü unutmuş. Her neyse, bu yarışta çok eğlendim.
Jakube
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.