İngiliz İstihbaratını yenebilir misin? (Program Dışı Çözücü)


20

İngiliz İstihbaratını yenmek için tehlikeli bir arayışa çıkma zamanı. Bu zorluğun amacı, bir Nonogram'ı çözecek en kısa kodu yazmaktır.

Nonogram nedir?

Nonogram Yapboz

Kurallar basit. Siyahla doldurulması veya boş bırakılması gereken bir kareler ızgarasına sahipsiniz. Izgaranın her satırının yanında, o satırdaki siyah karelerin çalışma uzunlukları listelenir. Her sütunun üstünde, o sütundaki siyah karelerin çalışma uzunlukları listelenir. Amacınız tüm siyah kareleri bulmak. Bu bulmaca türünde, sayılar, herhangi bir satır veya sütunda kaç tane kesintisiz doldurulmuş kare çizgisinin olduğunu ölçen ayrı bir tomografi biçimidir. Örneğin, "4 8 3" ipucu, birbirini izleyen gruplar arasında en az bir boş kare olacak şekilde dört, sekiz ve üç dolu kareden oluşan setler olduğu anlamına gelir. [ 1 ] [ 2 ]

Dolayısıyla yukarıdaki Nonogram'ın çözümü şöyle olacaktır:

Çözülmüş nongram

Uygulama ayrıntıları

Nonogram'ı temsil etmeyi seçebilir, ancak dilinize uygun gördüğünüz şekilde bir girdi olarak alabilirsiniz. Aynı şey çıktı için de geçerli. Bu zorluğun amacı kelimenin tam anlamıyla işi bitirmektir; nonogram'ı programınızın verdiği çıktı ile çözebilirseniz, bu geçerlidir. Bir uyarı, çevrimiçi bir çözücü kullanamazsınız :)

Bu problem çok etkili bir çözüm olmadığı için (np-complete) çok zordur ve bu nedenle, daha büyük olanları çözemediğiniz için cezalandırılmayacaksınız, ancak cevabınız ağırsa ödüllendirilecektir. büyük davaları halledebilir (bonusa bakınız). Bir ölçüt olarak, çözümüm 5-10 saniye içinde yaklaşık 25x25'e kadar çalışır. Farklı diller arasında esneklik sağlamak için 25x25 nonogram için 5 dakikadan daha az süren çözümler yeterince iyidir.

Her zaman kare NxN nonogramda bir bulmaca olduğunu varsayabilirsiniz.

Çözümlerinizi test etmek için bu çevrimiçi nonogram bulmacayı kullanabilirsiniz .

puanlama

Tabii ki, istediğiniz herhangi bir dili kullanmakta özgürsünüz ve bu kod golf olduğundan, girişler sırayla sıralanacaktır: accuracy -> length of code -> speed.Ancak, kod golf dilleri ile cesaret kırmayın, golf oynama girişimlerini gösteren tüm dillerde cevaplar ilginç bir şekilde kaldırılacak!

Bonus

Aslında Nonograms'ı, burada İngiliz İstihbaratı tarafından yayınlanan kriptografik bir Noel kartından öğrendim . İlk bölüm 25x25 büyüklüğünde devasa bir programdı. Çözümünüz bunu çözebiliyorsa, kudos alacaksınız :)

Veri girişi açısından hayatınızı kolaylaştırmak için, bu özel bulmacanın verilerini ücretsiz kullanımınız için nasıl temsil ettiğimi sağladım. İlk 25 satır, satır ipuçlarını, ardından bir '-' ayırıcı çizgisini, ardından 25 satır col ipucunu, ardından bir '#' ayırıcı çizgisini ve daha sonra ızgaranın kare ipuçları doldurulmuş olarak temsil edilmesidir.

7 3 1 1 7
1 1 2 2 1 1
1 3 1 3 1 1 3 1
1 3 1 1 6 1 3 1
1 3 1 5 2 1 3 1
1 1 2 1 1
7 1 1 1 1 1 7
3 3
1 2 3 1 1 3 1 1 2
1 1 3 2 1 1
4 1 4 2 1 2
1 1 1 1 1 4 1 3
2 1 1 1 2 5
3 2 2 6 3 1
1 9 1 1 2 1
2 1 2 2 3 1
3 1 1 1 1 5 1
1 2 2 5
7 1 2 1 1 1 3
1 1 2 1 2 2 1
1 3 1 4 5 1
1 3 1 3 10 2
1 3 1 1 6 6
1 1 2 1 1 2
7 2 1 2 5
-
7 2 1 1 7
1 1 2 2 1 1
1 3 1 3 1 3 1 3 1
1 3 1 1 5 1 3 1
1 3 1 1 4 1 3 1
1 1 1 2 1 1
7 1 1 1 1 1 7
1 1 3
2 1 2 1 8 2 1
2 2 1 2 1 1 1 2
1 7 3 2 1
1 2 3 1 1 1 1 1
4 1 1 2 6
3 3 1 1 1 3 1
1 2 5 2 2
2 2 1 1 1 1 1 2 1
1 3 3 2 1 8 1
6 2 1
7 1 4 1 1 3
1 1 1 1 4
1 3 1 3 7 1
1 3 1 1 1 2 1 1 4
1 3 1 4 3 3
1 1 2 2 2 6 1
7 1 3 2 1 1
#
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Ve işte size kolaylık sağlamak için biraz farklı bir sürüm; her öğenin liste listesi olduğu virgülle ayrılmış bir demet (satır, sütun).

([[7, 3, 1, 1, 7],
  [1, 1, 2, 2, 1, 1],
  [1, 3, 1, 3, 1, 1, 3, 1],
  [1, 3, 1, 1, 6, 1, 3, 1],
  [1, 3, 1, 5, 2, 1, 3, 1],
  [1, 1, 2, 1, 1],
  [7, 1, 1, 1, 1, 1, 7],
  [3, 3],
  [1, 2, 3, 1, 1, 3, 1, 1, 2],
  [1, 1, 3, 2, 1, 1],
  [4, 1, 4, 2, 1, 2],
  [1, 1, 1, 1, 1, 4, 1, 3],
  [2, 1, 1, 1, 2, 5],
  [3, 2, 2, 6, 3, 1],
  [1, 9, 1, 1, 2, 1],
  [2, 1, 2, 2, 3, 1],
  [3, 1, 1, 1, 1, 5, 1],
  [1, 2, 2, 5],
  [7, 1, 2, 1, 1, 1, 3],
  [1, 1, 2, 1, 2, 2, 1],
  [1, 3, 1, 4, 5, 1],
  [1, 3, 1, 3, 10, 2],
  [1, 3, 1, 1, 6, 6],
  [1, 1, 2, 1, 1, 2],
  [7, 2, 1, 2, 5]],
 [[7, 2, 1, 1, 7],
  [1, 1, 2, 2, 1, 1],
  [1, 3, 1, 3, 1, 3, 1, 3, 1],
  [1, 3, 1, 1, 5, 1, 3, 1],
  [1, 3, 1, 1, 4, 1, 3, 1],
  [1, 1, 1, 2, 1, 1],
  [7, 1, 1, 1, 1, 1, 7],
  [1, 1, 3],
  [2, 1, 2, 1, 8, 2, 1],
  [2, 2, 1, 2, 1, 1, 1, 2],
  [1, 7, 3, 2, 1],
  [1, 2, 3, 1, 1, 1, 1, 1],
  [4, 1, 1, 2, 6],
  [3, 3, 1, 1, 1, 3, 1],
  [1, 2, 5, 2, 2],
  [2, 2, 1, 1, 1, 1, 1, 2, 1],
  [1, 3, 3, 2, 1, 8, 1],
  [6, 2, 1],
  [7, 1, 4, 1, 1, 3],
  [1, 1, 1, 1, 4],
  [1, 3, 1, 3, 7, 1],
  [1, 3, 1, 1, 1, 2, 1, 1, 4],
  [1, 3, 1, 4, 3, 3],
  [1, 1, 2, 2, 2, 6, 1],
  [7, 1, 3, 2, 1, 1]])

Ne yazık ki benim web sitesi kapalı ama oldukça hızlı bir Nonogram çözücü vardı; 5-10 dakika aşırı geliyor.
Neil


1
@dwana Çözülemeyen durumlar için endişelenmenize gerek yok. Rastgele cevaba gelince, 25x25 nonogramda 2 ^ 625 olası konfigürasyonunuz var. Bağlamda, bu bilinen evrendeki atom sayısının iki katından fazladır (yani evrendeki her bir atomu biraz kullanırsanız, olasılıkları saklamak için hala yeterli alanınız olmaz). Zaman açısından, her bir yapılandırmanın geçerliliğini kontrol etmeniz size bir nano saniye (cömert)
sürdüyse

1
Çözülemeyen davaları netleştirmek için Ty. (+ büyülü bir bilgisayarım var ~ 2.1546362E-186 saniyede bir cevabı doğrular)
dwana

1
CSV'nizde kare ipucu yok. İşte bunları oluşturmak için bazı JS:s=[].fill([].fill(0,0,25),0,25);s[3][3]=s[3][4]=s3[3][12]=s3[3][13]=s3[3][21]=s[8][6]=s[8][7]=s[8][10]=s[8][14]=s[8][15]=s[8][18]=s[16][6]=s[16][11]=s[16][16]=s[16][20]=s[21][3]=s[21][4]=s[21][9]=s[21][10]=s[21][15]=s[21][20]=s[21][21]=1;
Titus

Yanıtlar:


5

Brachylog , 70 69 bayt

[R:C]hlL~l:L:1f=.:3aR,.z:3aC,
tL,?he##ElL,E:2a
.<2,_1<
@b:4f:la
e.h1,

Bu, iki listenin bir listesini alır (önce satır göstergeleri, ardından sütun olanlar). Her göstergenin kendisi bir listedir ( [3,1]bir satırdaki gibi durumlar için).

Bu sürüm, 5'e 5 örneğini çözmek için yaklaşık 3 dakika sürer.

Çok daha verimli versiyon, 91 bayt

[R:C]hlL~l:L:1f:Cz:3az:Rz:3a=.:4aR,.z:4aC,
tL,?he##ElL,E:2a
.<2,_1<
:+a#=,?h
@b:5f:la
e.h1,

Çevrimiçi deneyin!

Bu tam bir kaba kuvvet değildir: tek fark, bunun, her bir satır ve sütundaki 1s sayısının girişte göstergeler olarak verilen sayılarla eşleşeceği şekilde hücre değerleri üzerinde kısıtlamalar getirmesidir. Bu durumda tek kaba kuvvet kısmı, 1'lerin "bloklarının" gösterge olarak verilenle eşleştiği kısıtlamalara sahip tek bir ızgara bulmaktır.

Bu, mücadelenin 5'e 5 örneğinde yaklaşık 0.05 saniye sürer. Bu, bonus durumu için hala çok yavaş, çünkü kısıtlama açısından bir veya daha fazla sıfırla ayrılmış blokların nasıl ifade edileceği hakkında hiçbir fikrim yok.

açıklama

Aşağıda 93 baytlık versiyonu açıklayacağım. İkisi arasındaki tek fark, 70 baytlık versiyonda bulunmayan 3 yüklemine çağrı ve tahminlerin numaralandırılmasıdır (bir tane daha az olduğu için).

  • Ana yüklem:

    [R:C]     Input = [R, C]
    hlL       The length of R is L
    ~l        Create a list of length L
    :L:1f     Each element of that list is a sublist of length L with cells 0 or 1 (Pred 1)
              %%% Part unique to the 93 bytes version
    :Cz       Zip the rows of the list of lists with C
    :3a       The sum of 1s in each row is equal to the sum of the indicators (Pred 3)
    z         Transpose
    :Rz       Zip the columns of the list of lists with R
    :3a       The sum of 1s in each column is equal to the sum of the indicators (Pred 3)
              %%%
    =.        Assign values to the cells of the list of lists which satisfy the constraints
    :4aR,     The blocks of 1s must match the indicators on rows
    .z        Transpose
    :4aC,     The blocks of 1s must match the indicators on columns
    
  • Tahmin 1: Satırları belirli bir uzunluğa sahip olmaya zorlar ve her hücrenin 0 veya 1 olmasını sağlar.

    tL,       L is the length given as second element of the input
    ?he       Take an element from the list
    ##ElL,    That element E is itself a list of length L
    E:2a      The elements of E are 0s and 1s (Pred 2)
    
  • Tahmin 2: Bir değişkeni 0 veya 1 olarak sınırla

    .<2,      Input = Output < 2
    _1<       Output > -1
    
  • Tahmin 3: Bir listedeki 1'lerin toplamı göstergelerin toplamına eşit olmalıdır (örneğin gösterge [3: 1] ise listenin toplamı 4 olmalıdır)

    :+a       Sum the elements of the list and sum the indicator
    #=,       Both sums must be equal
    ?h        Output is the list
    
  • Tahmin 4: 1'li blokların göstergeyle eşleşip eşleşmediğini kontrol edin

    @b        Split the list in blocks of the same value
    :5f       Find all blocks of 1s (Pred 5)
    :la       The list of lengths of the blocks results in the indicator (given as output)
    
  • Tahmin 5: 1s bloklar için doğru, aksi takdirde yanlış

    e.        Output is an element of the input
      h1,     Its first value is 1
    

İş için mükemmel bir araç gibi geliyor. Açıklamayı dört gözle bekliyorum.
Emigna

@Fatalize Bu harika, birinin bunu yapmak için prolog esque bir dil kullanmasını bekliyordum. 25x25 kasa ile denediniz mi? Verileri zaten
girdim

@gowrath Bunu bu öğleden sonra bilgisayarımda çalıştıracağım, ne olacağını göreceğiz.
9'da ölümcül

@Fatalize Zaman aşımı gibi görünüyor ama yanlış yapıyor olabilirim. Veri girişi becerilerime de tamamen güvenmezdim: D
gowrath

@gowrath TIO'da zaman aşımına uğradı, ancak doğrudan bilgisayarımda çevrimdışı yorumlayıcıda çalıştıracağım.
9'da ölümcül

9

Haskell, 2422302019191771616160149131 bayt

import Data.Lists
m=map
a#b=[x|x<-m(chunk$length b).mapM id$[0,1]<$(a>>b),g x==a,g(transpose x)==b]
g=m$list[0]id.m sum.wordsBy(<1)

Sonunda 200 baytın altında @Bergi'ye kredi verin. Boyutu neredeyse yarıya indirmeye yardımcı olduğu için @ nimi'ye çok teşekkürler.

Vay. Hemen hemen yarı boyutta, kısmen benim yüzümden, ama esas olarak @nimi yüzünden.

Sihirli işlev (#). Belirli bir nonogramın tüm çözümlerini bulur .

Bu, tüm durumları çözebilir, ancak karmaşıklığı hakkında olduğu için süper yavaş olabilir O(2^(len a * len b)). Hızlı bir kıyaslama 5x5 nongram için tahsis edilen 86GB'ı ortaya çıkardı.

Eğlenceli gerçek: Sadece kare olanlar için değil, tüm nonogramlar için çalışır.


Nasıl çalışır:

  • a#b: Karelerin sayısını temsil eden tamsayı listelerinin listesi verildiğinde, tüm ızgaraları ( map(chunk$length b).mapM id$a>>b>>[[0,1]]) oluşturun ve sonuçları yalnızca geçerli olanları tutmak için filtreleyin.
  • g: Potansiyel bir nonogram verildiğinde 1'lerin çalışmalarını yatay olarak toplar.

O (2 len (len a * len b)) değil, O ((len a * len b) ^ 2) demek istediniz.
Anders Kaseorg

@AndersKaseorg Doğru. Yanlışlıkla ima ettiğim milyonu orada tut. : D
ThreeFx

1
Başka bir kaç bayt: m(chunk$l b)vereplicate(l$a>>b)
Bergi

@ThreeFx 86GB: O ... Btw bunu nasıl derleyeceğinizi kısaca açıklar mısınız? Sadece haskell öğrenmeye başladım ve bu ghc ile hata veriyor. Test etmek istiyorum :)
gowrath

1
import Data.Listsçünkü yeniden ihracat hem yeterli Data.Listve Data.List.Split.
nimi

4

Pyth, 91 72 71 bayt

D:GHdRq@@QdG.nCf.)TrH8V^,01^hQ2=TcNhQ=Y1VhQ=*Y*:H@TH1:H@CTH2)IYjbmjkdTb

[size, [horizontal clues], [vertical clues]]Her ipucunun bir tamsayı listesi olduğu (boş ipuçları boş listedir []) form listesinin girdisini alan ve satır sonunu 1gölgeli ve 0gölgesiz bir ikili ızgara şeklinde her satırdaki her çözümü yazdırır. .

Bu kaba bir kuvvettir, kabaca öyledir O(2^n^2). Daha büyük bulmacalar için çok uzun zaman almaya başlar, ancak yeterli zaman verilen herhangi bir aritmetik boyutu çözecektir.

Çevrimiçi deneyin

Nasıl çalışır

Program [0, 1], uzunluğu eşit olan tekrarlanan Kartezyen ürününü alarak mümkün olan her düzeni oluşturur size^2. Bu daha sonra her bir yatay çizgi için bir liste vererek parçalara ayrılır. Her satır çalışma uzunluğu kodlanır, varlığı ile filtrelenir 1ve düzleştirilir, bu hat için ipucu kalır. Bu daha sonra girişe göre kontrol edilir. Yukarıdaki işlem, dikey çizgileri kontrol ederek, parçaların aktarılması için tekrarlanır. İsabet varsa, her bir yığın birleştirilir ve birleştirilmiş satırlar yeni satırlarda birleştirilir ve sondaki satırsonu ile örtülü olarak yazdırılır.

D:GHdRq@@QdG.nCf.)TrH8V^,01^hQ2=TcNhQ=Y1VhQ=*Y*:H@TH1:H@CTH2)IYjbmjkdTb  Program. Input: Q
                            hQ                                           Q[0], size
                           ^  2                                          Square
                        ,01                                              [0, 1]
                       ^                                                 Cartesian product
                      V                                     )            For N in the Cartesian product:
                                 cNhQ                                    Split N into Q[0] chunks
                               =T                                        Assign that to T
                                     =Y1                                 Y=1
                                        VhQ                              For H in range [0, Q[0]-1]:
D:GHd                                                                     def :(G, H, d)
                   rH8                                                     Run-length-encode(H)
               f.)T                                                        Filter by presence of 1 in character part
            .nC                                                            Transpose and flatten, giving the clue
       @@QdG                                                               Q[d][G], the relevant input clue
     Rq                                                                    Return clue==input clue
                                               :H@TH1                     :(H, T, 1)
                                                     :H@CTH2              :(H, transpose(T), 2)
                                           =*Y*                           Y=Y*product of above two
                                                             IY           If Y:
                                                                 mjkdT     Conacatenate each element of T
                                                               jb          Join on newlines
                                                                      b    Add a newline and implicitly print

Bazı ipuçları için @ Pietu1998'e teşekkürler


Bu şimdiye kadar gördüğüm en uzun Pyth programı olabilir
Business Cat

=ZhZeşittir =hZve FNeşittir V.
PurkkaKoodari

@TheBikingViking Yeterli zaman verildiğinde tam olarak ne demek istiyorsun? Eğer evren anlayışından başlamış olsaydınız, bunun 25x25'i çözmeyeceğinden eminim.
gowrath

1
@gowrath Ben de bundan oldukça eminim! Pyth için yeniyim ve bu uzun sürdü sonra, daha iyi bir algoritma uygulamaya çalışmayı düşünmek bile istemiyorum
TheBikingViking

2

JavaScript (ES6), 401 386 333 bayt

Bu erken bir girişim. Çok verimli değil ama satır ve sütunların ikili gösterimi üzerinde düzenli ifadeler kullanarak bir çözümü test etmeyi merak ettim.

Örneğin, ipucunu [3,1]aşağıdaki normal ifadeye çevirir :

/^0*1{3}0+1{1}0*$/

Şu anda, bu sürüm kare ipuçlarını dikkate almıyor. Muhtemelen daha sonra ekleyeceğim.

kod

(c,r)=>{W=c.length;w=[];S=0;M=(n,p)=>eval(`/^0*${p.map(v=>`1{${v}}`).join`0+`}0*$/`).exec(n);R=(y,i=0)=>S||(w[y]=r[y][i],y+1<W?R(y+1):c.every((c,y)=>(n=0,w.map((_,x)=>n+=w[W-1-x][y]),M(n,c)))&&(S=w.join`
`),r[y][i+1]&&R(y,i+1));r=r.map(r=>[...Array(1<<W)].map((_,n)=>((1<<30)|n).toString(2).slice(-W)).filter(n=>M(n,r)));return R(0)}

Çıktı

Çözüm ikili biçimde görüntülenir. Gibi:

00110
01110
11100
11101
00001

Ölçek

Bu örnek ızgara üzerinde basit bir testtir.

let f =
(c,r)=>{W=c.length;w=[];S=0;M=(n,p)=>eval(`/^0*${p.map(v=>`1{${v}}`).join`0+`}0*$/`).exec(n);R=(y,i=0)=>S||(w[y]=r[y][i],y+1<W?R(y+1):c.every((c,y)=>(n=0,w.map((_,x)=>n+=w[W-1-x][y]),M(n,c)))&&(S=w.join`
`),r[y][i+1]&&R(y,i+1));r=r.map(r=>[...Array(1<<W)].map((_,n)=>((1<<30)|n).toString(2).slice(-W)).filter(n=>M(n,r)));return R(0)}

console.log(f(
  [[2],[3],[4],[2],[2]],
  [[2],[3],[3],[3,1],[1]]
));


iyi fikir. Yine de tarayıcılarımı yılbaşı bulmacasında öldürüyor.
Titus

2

Haskell, 109 bayt

Feragatname: Bu @ ThreeFx'in cevabından türetilmiştir . Cevabını golf oynamasına yardım ettim, ancak son önemli iyileştirmelerimi dahil etmek için ilgisini kaybetmiş görünüyor, bu yüzden onları yeni cevap olarak gönderiyorum.

import Data.List
n=mapM id
a#b=[x|x<-n$(n$" #"<$a)<$b,g x==a,g(transpose x)==b]
g=map$max[0].map length.words

Kullanım örneği: [[2],[3],[3],[3,1],[1]] # [[2],[3],[4],[2],[2]]-> [[" ## "," ### ","### ","### #"," #"]].

Kaba kuvvet. Uzunlukları saymak ve giriş ile karşılaştırmak için tüm kombinasyonları ve #bölünmüş int parçalarını deneyin #.


1

PHP 751 833 (720) 753 724 726 710 691 680 682 bayt

Özel bir dizi artışı oluşturmak ve kartezyen jeneratörümü bir kez daha denemek için istekliydim;
ancak kartezyeni büyük bulmacayı daha hızlı çözmek için geri izleme lehine düşürdü.

$p=[];foreach($r as$y=>$h){for($d=[2-($n=count($h)+1)+$u=-array_sum($h)+$w=count($r)]+array_fill($i=0,$n,1),$d[$n-1]=0;$i<1;$d[0]+=$u-array_sum($d)){$o=$x=0;foreach($d as$i=>$v)for($x+=$v,$k=$h[$i];$k--;)$o+=1<<$x++;if(($s[$y]|$o)==$o){$p[$y][]=$o;$q[$y]++;}for($i=0;$i<$n-1&$d[$i]==($i?1:0);$i++);if(++$i<$n)for($d[$i]++;$i--;)$d[$i]=1;}}
function s($i,$m){global$c,$w,$p;for(;!$k&&$i[$m]--;$k=$k&$m<$w-1?s($i,$m+1):$k){for($k=1,$x=$w;$k&&$x--;){$h=$c[$x];for($v=$n=$z=$y=0;$k&&$y<=$m;$y++)$n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];if($k&$v)$k=$n<=$h[$z];}}return$k?is_array($k)?$k:$i:0;}
foreach(s($q,0)as$y=>$o)echo strrev(sprintf("\n%0{$w}b",$p[$y][$o]));
  • dizilerdeki $rsatır ipuçlarını, $csütun ipuçlarını ve $skare ipuçlarını bekler .
  • invalid argument supplied for foreachçözüm bulamazsa atar .
  • doğru bayt sayısını elde etmek için bir fiziksel kullanın \nve diğer iki satır sonunu kaldırın.

açıklama

1) satır ipuçlarından
, kare ipuçlarını tatmin eden
ve her satır dizini için sayılarını hatırlayan olası satırlar oluşturur .

2) satır kombinasyonları üzerinde geriye doğru izleme:
Kombinasyon sütun ipuçlarını karşılıyorsa, daha derine inin veya başarılı kombinasyonu döndürün,
aksi takdirde bu satır için bir sonraki olasılığı deneyin

3) baskı çözümü


Son golfün performans üzerinde ciddi etkisi oldu;
ancak son karşılaştırmalar için profil oluşturma görevlerini kaldırdım.

Son golf adımını geri almak için $n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];
ile değiştirin if(($p[$y][$i[$y]]>>$x&1)-$v){$k=($v=!$v)||$n==$h[$z++];$n=1;}else$n++;
.

örnekler

Küçük örnek için ( 17 ila 21 civarında 12 8 7 6.7 5.3 ms),

$r=[[2],[3],[3],[3,1],[1]];$c=[[2],[3],[4],[2],[2]];$s=[0,0,0,0,0];

noel için bulmaca:

  • küçük ev sunucumu eski çözümle öldürdü
  • tarayıcıyı test çıktılarıyla öldürdü
  • Şimdi 50 37,8 45,5 36 saniye içinde çözüldü

sorudan bir dosyaya veri koyun christmas.nonogramve içe aktarmak için bu kodu kullanın:

$t=r;foreach(file('christmas.nonogram')as$h)if('-'==$h=trim($h))$t=c;elseif('#'==$h){$t=s;$f=count($h).b;}else
{$v=explode(' ',$h);if(s==$t)for($h=$v,$v=0,$b=1;count($h);$b*=2)$v+=$b*array_shift($h);${$t}[]=$v;}

Yıkmak

$p=[];  // must init $p to array or `$p[$y][]=$o;` will fail
foreach($r as$y=>$h)
{
    // walk $d through all combinations of $n=`hint count+1` numbers that sum up to $u=`width-hint sum`
    // (possible `0` hints for $h) - first and last number can be 0, all others are >0
    for(
        $d=[2-
            ($n=count($h)+1)+               // count(0 hint)=count(1 hint)+1
            $u=-array_sum($h)+$w=count($r)  // sum(0 hint) = width-sum(1 hint)
        ]                           // index 0 to max value $u-$n+2
        +array_fill($i=0,$n,1)      // other indexes to 1
        ,$d[$n-1]=0;                // last index to 0
                                    // --> first combination (little endian)
        $i<1;   // $i:0 before loop; -1 after increment; >=$n after the last combination
        $d[0]+=$u-array_sum($d) // (see below)
    )
    {
        // A: create row (binary value) from 1-hints $h and 0-hints $d
        $o=$x=0;
        foreach($d as$i=>$v)
            for($x+=$v,$k=$h[$i];$k--;)
                $o+=1<<$x++;
        // B: if $o satisfies the square hints
        if(($s[$y]|$o)==$o)
        {
            $p[$y][]=$o;    // add to possible combinations
            $q[$y]++;       // increase possibility counter
        }
        // C: increase $d
            // find lowest index with a value>min
                // this loop doesn´t need to go to the last index:
                // if all previous values are min, there is nothing left to increase
        for($i=0;$i<$n-1&$d[$i]==($i?1:0);$i++);
        if(++$i<$n)             // index one up; increase $d if possible
            for($d[$i]++        // increase this value
            ;$i--;)$d[$i]=1;    // reset everything below to 1
            // adjust $d[0] to have the correct sum (loop post condition)
    }
}

// search solution: with backtracking on the row combinations ...
function s($i,$m)
{
    global $c,$w,$p;
    for(;
        !$k // solution not yet found
        &&$i[$m]    // if $i[$m]==0, the previous iteration was the last one on this row: no solution
            --;     // decrease possibility index for row $m
        $k=$k&$m<$w-1? s($i,$m+1) : $k      // if ok, seek deeper while last row not reached ($m<$w-1)
    )
    {
        // test if the field so far satisfies the column hints: loop $x through columns
        for($k=1,$x=$w;$k&&$x--;)   // ok while $k is true
        {
            $h=$c[$x];
            // test column hints on the current combination: loop $y through rows up to $m
            for($v=$n=$z=   // $v=temporary value, $n=temporary hint, $z=hint index
                $y=0;$k&&$y<=$m;$y++)
                // if value has not changed, increase $n. if not, reset $n to 1
                // (or 0 for $k=false; in that case $n is irrelevant)
                $n=$n*  
                    // $f=false (int 0) when value has changed, true (1) if not
                    ($f=($p[$y][$i[$y]]>>$x&1)==$v)
                    +$k=$f?:    // ok if value has NOT changed, else
                        ($v=!$v)        // invert value. ok if value was 0
                        || $n==$h[$z    // value was 1: ok if temp hint equals current sub-hint
                        ++]             // next sub-hint
                ;
            // if there is a possibly incomplete hint ($v==1)
            // the incomplete hint ($n) must be <= the next sub-hint ($c[x][$z])
            // if $n was <$h[$z] in the last row, the previous column hints would not have matched
            if($k&$v)$k=$n<=$h[$z];
        }
        // ok: seek deeper (loop post condition)
        // not ok: try next possibility (loop pre condition)
    }
    return$k?is_array($k)?$k:$i:0;  // return solution if solved, 0 if not
}

// print solution
foreach(s($q,0)as$y=>$o)echo strrev(sprintf("\n%0{$w}b",$p[$y][$o]));

1
Büyük örnek, küçük ev sunucumu öldürür (500 - Dahili Sunucu Hatası). Kombinasyonlar 15 saniye sonra hazırdır, ancak kartezyen ürünün 1.823E + 61 üyesi vardır. (7. ve 22. sıra sadece bir çözüm btw'ye sahiptir.) Algoritma geliştirilmelidir.
Titus

Ben tekrarlı geri izleme kullandıysanız bu hızlandırılmış olabilir düşünüyorum. Yine de, harika bir iş!
gowrath

@gowrath: backtracking biraz verir ve hatta bayt kazandırır ... bit aritmetiği ile tamsayı yaklaşık% 50 hız verir, ancak boyutu arttırır (tam olarak ne kadar olduğunu öğrenmeliyim) ... Hala varım.
Titus

@gowrath: Böceğimi kovaladım; artımdaydı (başka nerede?): $ddoğru sırada olmalıforeach
Titus
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.