Kasayı kır!


10

Esinlenerek /puzzling/24334/to-catch-a-thief

Size s ve s (veya seçtiğiniz herhangi bir karakterle ) dolu bir nby n( nkendisi isteğe bağlı giriş) ızgarası verilir . Amacınız her hücreyi aynı ( veya ) yapmaktır . Aşağıda tanımlandığı gibi bir dizi hamle yapabilirsiniz (Şaşırtıcı SE bağlantısıyla farklılığı not edin):0101

  • Bir hücre seçin.
  • Aynı satır ve sütundaki her hücre (hücrenin kendisi hariç) tersine çevrilir. 0to 1ve 1to 0.

Görevi tamamlamak için gereken minimum hamle sayısını girin. Çözülemezse, negatif olmayan bir tam sayı dışında herhangi bir çıktı alın. En kısa kod kazanır.

Örnek veri

1 0 0
0 0 0
0 0 0

-1

1 1 1
1 1 1
1 1 1

0

1 0 1
0 1 0
1 0 1

1

1 1 1 1
0 0 0 0
0 0 0 0
1 1 1 1

2

0 1 0 1
1 0 1 0
1 0 1 0
0 1 0 1

2


3
Bulmacanın çözülemez olması durumunda ne yapmalı? Örneğin 1000(kare olarak yeniden düzenlenmiş, nasıl olduğu önemli değil).
orlp


@orlp Sayı olmayan herhangi bir çıktı yapılır.
ghosts_in_the_code

Girdiyi ayrıştırmamız mı gerekiyor yoksa önceden doldurulmuş dizi veri türü olabilir mi?
coredump

1
İlk test senaryosunun çözümü nedir? Bunun için çözüm bulmuyorum.
cardboard_box

Yanıtlar:


4

Matlab 171 bayt

Giriş 2d bir matris olmalıdır, bu yüzden şöyle adlandırırsınız c([1,1,1,1;0,0,0,0;0,0,0,0;1,1,1,1])(noktalı virgüller yeni bir satır başlatır). Bu işlev tüm olası hareketleri kaba kuvvetlendirir, böylece bir çalışma zamanı elde ederiz O(2^(n^2)).

Nasıl yapılır

Bu, aynı boyuttaki başka bir matrisi bir ve sıfırla doldurmak için mümkün olan tüm yolları seçerek yapılır, bu temel olarak, matrisin her girişinin belirli bir 2 gücünü temsil ettiği ikili wich sayılır.

Daha sonra 1 olan hücreler üzerinde hareketler gerçekleştiriyoruz , bu iki boyutlu evrişim toplamı (mod 2) ile 1xn ve nx1 boyutlarında bir vektörle yapılır.

Son olarak, tüm girdiler üzerinde standart sapmayı hesaplayarak bu hareketlerin gerçekten istenen sonucu üretip üretmediğine karar veriyoruz. Standart sapma yalnızca tüm girişler aynı olduğunda sıfırdır. İstediğimiz sonucu her bulduğumuzda, önceki çözümlerin hamle sayısı ile karşılaştırıyoruz. infVerilen sorun çözülemezse işlev geri döner .

Matematik?

Aslında tüm bu hareketlerin bir abelya grubu oluşturduğunu belirtmek gerekir ! Eğer birisi bu grupların kalsifikasyonunu gerçekten başarırsa, lütfen bana bildirin.

Golf versiyonu:

function M=c(a);n=numel(a);p=a;M=inf;o=ones(1,n);for k=0:2^n-1;p(:)=dec2bin(k,n)-'0';b=mod(conv2(p,o,'s')+conv2(p,o','s'),2);m=sum(p(:));if ~std(b(:)-a(:))&m<M;M=m;end;end

Tam sürüm (gerçek hamlelerin çıkışı ile.)

function M = c(a)
n=numel(a);
p=a;
M=inf;                                               %current minimum of number of moves
o=ones(1,n);
for k=0:2^n-1;
    p(:) = dec2bin(k,n)-'0';                         %logical array with 1 where we perform moves
    b=mod(conv2(p,o,'same')+conv2(p,o','same'),2);   %perform the actual moves
    m=sum(p(:));                                     %number of moves;
    if ~std(b(:)-a(:))&m<M                           %check if the result of the moves is valid, and better
        M=m;
        disp('found new minimum:')
        disp(M)                                      %display number of moves of the new best solution (not in the golfed version)
        disp(p)                                      %display the moves of the new best solution                               (not in the golfed version)
    end
end

1

Perl 5, 498 bayt

Bu, 'n' ve istenen sonucu kabul eder ve sayıyı, yoksa 'X' değerini verir.

Örneğin:

perl ./crack.golf.pl 3 000111111

verir 2. Sadece n ^ 2 <= 64 olduğunda çalışır, bu yüzdenn <= 8 . 5 gibi düşük n ile bile oldukça yavaş olmasına rağmen, bir ^ 3 bit dizisi oluşturur ve önceden bir 2 ^ (n ^ 2) dizisi sıralar, çünkü neden olmasın ?

Okunabilirlik için burada birkaç satır besleme harcadım :

$n=shift;$y=shift;$p=$n*$n;@m=(0..$n-1);@q=(0..$p-1);@v=(0..2**$p-1);@d=map{0}(@q);@b=map{$r=$_;map{$c=$_;$d[$r*$n+$_]^=1 for(@m);$d[$_*$n+$c]^=1 for(@m);$j=0;$k=1;
map{$j|=$k*$d[$_];$k<<=1;}@q;@d=map{0}(@q);$j;}@m}@m;for$k(sort{$a->[0]<=>$b->[0]}map{$z=0;map{$z+=$_}split(//,sprintf"%b",$_);[$z,$_]}@v){$l=sprintf"%0${p}b",$k->[1];
@m=map{$_}split(//,$l);$s=0;for(@q){$s^=$b[$_]if$m[$_];}$z=0;map{$z+=$_}split(//,sprintf"%b",$_);if($y eq sprintf"%0${p}b",$s){print"$k->[0]\n";exit 0;}}print"X\n";
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.