Domino devirme sayısı


9

Pozitif n ve m verilen bir program veya işlev yazın, n x m dikdörtgen içine sığdırabileceğiniz geçerli farklı domino eğim sayısını hesaplar . Bu dizisidir A099390 yılında Tamsayı Dizilerin Çevrimiçi Ansiklopedisi . Girdiyi herhangi bir makul biçimde işlev bağımsız değişkeni, CLA veya stdin olarak alabilirsiniz. Çıktı olarak tek bir tamsayıyı döndürmeli veya yazdırmalısınız.

Her döşeme boşluğu bırakmamalıdır ve döndürmeler, yansımalar vb. Dahil olmak üzere her farklı döşeme sayılır. Örneğin, 2x3 için eğimler şunlardır:

|--    |||    --| 
|--    |||    --|

Örnek girişler / çıkışlar:

1,  9 -> 0
2,  2 -> 2
2,  3 -> 3
4,  4 -> 36
4,  6 -> 281
6,  6 -> 6728
7, 10 -> 53175517

Programınız teorik olarak herhangi bir n ve m için çalışmalıdır , ancak programınız çok fazla bellek gerektiriyorsa veya veri türünüz taşarsa bu mazerettir. Ancak programınız n, m <= 8 için düzgün çalışmalıdır .


Bayt cinsinden en kısa kod kazanır.


Sadece 2n x 2m alanlara izin vermiş olsaydın hayatımızı daha kolay hale getirebilirdin , güzel bir meydan okuma!
flawr

Tıpkı bu soru gibi codegolf.stackexchange.com/q/51067/15599 sadece daha kısa ve yavaş
Level River St

@ edc65 Damnit = / Yeni bir şey düşünemiyorum ... Düşündüğüm hemen hemen her meydan okuma zaten bir şekilde yapıldı. Her iki durumda da, zorluklar tam olarak aynı değil çünkü sorum bir kod golfü ve eğer bulmak zorunda değilsiniz - sadece bunların miktarı. Belki insanlar kaba kuvvetlendirici yazmak yerine hoş formüller kullanabilirler.
orlp

Kabul - diğer yorumu kaldıracak
edc65

Kopyalanan bilbo'nun yorumu (1 rep nedeniyle yanıt olarak gönderdi): "Bu sorun bir SPOJ meydan okuması kısaltmasıdır: spoj.com/problems/MNTILE SPOJ üzerindeki en kısa kod awk olarak 98 bayttır." . İki kat orjinalim gibi görünüyor - farkında değildim.
orlp

Yanıtlar:


3

Pyth, 30 29 bayt

L?bsmy-tb]dfq1.a-VThbb1y*FUMQ

Çevrimiçi deneyin: Gösteri / Test Paketi

Tüm örnek girişler çevrimiçi derleyicide çalışır. Sonuncusu birkaç saniye sürüyor.

Açıklama:

Kodumda özyinelemeli bir işlev tanımlayacağım y. İşlev y2B koordinatların bir listesini alır ve bu koordinatları kullanarak farklı domino eğme sayısını döndürür. Örneğin y([[0,0], [0,1]]) = 1(bir yatay domino), y([[0,0], [1,1]]) = 0(koordinatlar bitişik değildir) ve y([[0,0], [0,1], [1,0], [1,1]]) = 2(iki yatay veya iki dikey domino). Fonksiyonunu tanımladıktan sonra tüm koordinatları ile diyeceğiz [x,y]ile x in [0, 1, m-1], y in [0, 1, n-1].

Özyinelemeli işlev nasıl çalışır? Oldukça basit. Koordinatlar listesi boşsa, tam olarak geçerli bir döşeme ve ygeri dönüş vardır 1.

Aksi takdirde listedeki ilk koordinatı alırım ve b[0]kalan koordinatları bir komşu için ararım. Komşu b[0]yoksa, o zaman hiçbir döşeme mümkün değildir, bu nedenle 0'a dönüyorum. Bir veya daha fazla komşu varsa, o zaman tilning sayısı ( b[0]bir domina aracılığıyla ilk komşuyla bağlandığım tilting sayısı, artı b[0]ikinci komşu ile bağlandığım tilning sayısı , artı ...) Böylece kısaltılmış listeye sahip her komşu için işlevi iki kez çağırıyorum (iki kord b[0]ve komşuyu kaldırarak ). Daha sonra tüm sonuçları toplayıp geri veriyorum.

Koordinelerin düzeni nedeniyle her zaman sadece iki komşu vardır, biri sağ tarafta ve aşağıda. Ama algoritmam bunu umursamıyor.

                          UMQ  convert the input numbers into ranges
                        *F     Cartesian product (coords of each square)
L                              define a function y(b):
 ?b                              if len(b) > 0:
           f         b             filter b for squares T, which satisfy:
              .a-VThb                Euclidean distance between T and b[0]
            q1                       is equal to 1 (direct neighbors)
    m                              map each neighbor d to:
      -tb]d                          remove d from b[1]
     y                               and call recursively y with the rest
   s                               sum all those values and return them
                                 else:
                      1            return 1 (valid domino tiling found)
                       y*FUMQ  Call y with all coords and print the result  

Bize programınızın nasıl çalıştığı hakkında biraz daha bilgi verebilir misiniz? Algoritmanızı yorumlardan anlayamadım.
flawr

@flawr Algoritmamın bir açıklamasını ekledim.
Jakube

@ Jaketube Açıklama için teşekkürler, özyinelemeli yaklaşımı gerçekten seviyorum!
flawr

3

Matlab, 292

Eminim bu sadece başka bir dile taşıyarak kısaltılabilir.

Temel fikir kaba kuvvettir: m*n/2Domino tuğlaları bir m*ntahtaya nasıl yerleştireceğinize dair bir numara buldum . Ancak bu numaralandırma birçok geçersiz yatırma içerir (üst üste binen ya da tahtanın dışına çıkan tuğlalar). Böylece program tüm bu talaşları inşa eder ve sadece geçerli olanları sayar. Çalışma zamanı karmaşıklığı yaklaşık O(2^(m*n/2) * m*n). Bellek, 8x8sadece O(m*n)belleğe ihtiyaç duyduğu için sorun değildir . Ancak gereken süre 8x8yaklaşık 20 gündür.

Burada neler olduğunu açıklayan tamamen yorumlanmış sürüm.

Not: Matlab sözdizimi vurgulamanın nasıl çalıştığını bilen biri varsa, lütfen bu cevaba karşılık gelen etiketi ekleyin!

function C=f(m,n)
d = ceil(m*n/2);%number of dominoes
%enumeration: %the nth bit in the enumeration says whether the nth 
% domino pice is upright or not. we enumerate like this:
% firt piece goes top left:
% next piece goes to the left most column that has an empty spot, in the
% top most empty spot of that column
C=0;%counter of all valid tilings
for e=0:2^d-1 %go throu all enumerations
    %check whether each enumeration is valid
    A = ones(m,n);
    %empty spots are filled with 1
    %filled spots are 0 (or if overlapping <0) 
    v=1;%flag for the validity. hte grid is assumed to be valid until proven otherwise
    for i=1:d %go throu all pieces, place them in A
        %find the column where to place:
        c=find(sum(A)>0,1);
        %find the row where to place:
        r=find(A(:,c)>0,1);
        %find direction of piece:
        b=de2bi(e,d);
        if b(i)
            x=0;y=1;
        else
            x=1;y=0;
        end
        %fill in the piece:
        try
            A(r:r+y,c:c+x)=A(r:r+y,c:c+x)-1;
        catch z
            v=0;break;
        end
        %check whether A has no overlapping pieces
        if any(A(:)<0)
            v=0;break;
        end
    end
    %if valid, count it as valid
    if v && ~norm(A(:))
        disp(A)
        C=C+1;
    end
end

İşte tamamen golf olanı:

function C=f(m,n);m=4;n=6;d=ceil(m*n/2);C=0;for e=0:2^d-1;A=ones(m,n);v=1;for i=1:d;c=find(sum(A)>0,1);r=find(A(:,c)>0,1);b=de2bi(e,d);if b(i);x=0;y=1;else;x=1;y=0;end;try;A(r:r+y,c:c+x)=A(r:r+y,c:c+x)-1;catch z;v=0;break;end;if any(A(:)<0);v=0;break;end;end;if v && ~norm(A(:));C=C+1;end;end

2

C89, 230 bayt

f(n,m,b)int*b;{int s,i;s=i=0;
while(b[i])if(++i==n*m)return 1;
if(i/n<m-1){b[i]=b[i+n]=1;s+=f(n,m,b);b[i]=b[i+n]=0;}
if(i%n<n-1&&!(b[i]|b[i+1])){b[i]=b[i+1]=1;s+=f(n,m,b);b[i]=b[i+1]=0;}
return s;}
g(n,m){int b[99]={};return f(n,m,b);}

Okunabilirlik için bu cevabı elle sildim - 230 bayta ulaşmak için tüm yeni satırlar güvenle kaldırılabilir.

int g(int n, int m)Eğim sayısını döndüren bir işlevi tanımlar . fBir domino yerleştirerek, yinelenen ve daha sonra paylaşılan bir tahtada dominoyu kaldırarak tüm geçerli eğimleri yineleyen bir yardımcı işlevi kullanır .


0

Python 243

Kaba kuvvet yaklaşımını tercih ettim:

  • m * n / 2 yönleri oluşturmak;
  • domino'yu m * n kartına takmayı deneyin.

Hepsi uygunsa ve boşluk kalmazsa, geçerli bir girişimiz vardır.

İşte kod:

import itertools as t
m,n=input()
c,u=0,m*n
for a in t.product([0,1],repeat=u/2):
 l,k,r,h=[' ',]*u,0,'-|',[1,m]
 for t in a:
  l[k]=r[t]
  k+=h[t]   
  if k%m<m and k/m<n and l[k]==' ':l[k]=r[t]
  k=''.join(l).find(' ',1)
 if k<0:c+=1
print c
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.