Lazer hedeflerine uygun ayna yapılandırması bulun


13

GÜNCELLEME PUANLAMA : Bu zorluk tahmin ettiğimden daha zor olduğu için puanlamayı ayarladım. Tek bir ayna girişini çözebilen bir program geçerli bir cevaptır. Daha sofistike programlar puanlarına bir bonus kazanırlar.

Ayna kutusunda bir lazer yolu bulmak için PPCG'de birkaç bulmaca var. Bu bulmacada, bir dizi lazer varış noktasına uyacak bir ayna kutusu oluşturmanız gerekir .

Size bir kutu ve lazerlerin girip çıkacağı özellikler verilir. Programınızın spesifikasyonu karşılamak için kutuya tam olarak N çift taraflı ayna yerleştirmesi gerekir. Aynalar 45 derecede açılı olmalı, ancak öne eğimli veya arka eğimli olabilir.

Giriş

Programınız, aşağıdaki biçim örneklerinde STDIN, komut satırı bağımsız değişkeni veya dosya aracılığıyla bir kutu ızgarası kabul etmelidir:

+--G--+     +abcde+
G     |     f/////d
|    /|     a//   c
+-----+     f     |
            +-b-e-+

Harf çiftleri ([a-zA-Z] kullanılabilir) 52 lazerin giriş / çıkışını gösterir. Kutunun içinde N /ayna olacak . Kutu boyutları 3 <= W, H <= 200 olacaktır. Kutu +|-karakterlerden oluşur. Kutuda sıfır dahil olmak üzere herhangi bir sayıda ayna olabilir.

Çıktı

/Karakterler taşınabileceği ve / veya \karakterlere dönüştürülebileceği dışında, çıktı girdiyle eşleşmelidir . Programınız STDOUT'a veya isteğe bağlı yeni satırın sonuna gelen bir dosyaya doğru bir ayna kutusu dizesi göndermelidir. Aynaların yerleştirilmesi giriş özelliklerini karşılayamıyorsa, çıktı Impossible\n. Olası çözümlere örnekler:

+--G--+     +abcde+
G  /  |     f \ \ d
|     |     a/ \  c
+-----+     f / //|
            +-b-e-+

Test örneği

Giriş:

+abcdefghijklmnopqrstuvwxyA-+
|///////////////            |
|///////////////            |
|                           |
+-Abcdefghijklmnopqrstuvwxya+

Örnek çıktı:

+abcdefghijklmnopqrstuvwxyA-+
|\                         \|
|/                        / |
|\\\\\\\\\\\\\\\\\\\\\\\\\\ |
+-Abcdefghijklmnopqrstuvwxya+

Puanlama (GÜNCELLENDİ)

Bu bonuslar ile kod golf. Cevabınızı, programınızın kaç aynayı çözebileceğini (N) aday göstermelisiniz. Puanınız, bayt cinsinden programınızın uzunluğunun N'ye bölünmesiyle elde edilir. Bu, insanların basit bir programla girmesine izin verir, ancak daha fazla hırs programcısını bonus ile ödüllendirir.

Standart boşluklara izin verilmedi.


3
Bu, golf oynamaktan bağımsız olarak zor bir sorun gibi görünüyor.
orlp

2
İpucu: kaba kuvvet bir seçenek değildir ; daha büyük örnek için saniyede 10 bin seçenekte 3 evren yaşınızı alacaktır.
Sanchises

@ sanchises Herhangi bir ayna çevrilebilir gibi çok daha uzun süreceğini düşünüyorum, bu yüzden * 2^30orada da bir bileşene ihtiyacınız olduğunu düşünüyorum
VisualMelon

Ek ipucu: Arama alanınızı budamak için bulmacanın özelliklerinden yararlanmanız gerekir. Ayrıca, kısmi çözeltilerin kombinasyonlarını veya tam bir çözüme yakın kısmi çözeltilerden tepe tırmanma da kullanabilirsiniz. Artık daha basit çözümlerle cevap vermek geçerli, bu nedenle bir veya iki ayna bulmacasını çözen programlar da kabul edilebilir.
Mantık Şövalyesi

Yanıtlar:


2

C # - 897 862 bayt

Aynalar olamayacakları yerlere koyarak ciddi bir hata buldular. Şimdi çalışıyor, umarım! Ayrıca bazı hafif golf yaptım, süre döngü orada bırakamadı ... utanç verici.

Komple program STDIN'den girdi alır, STDOUT'a çıktılar.

Bu çok eğlenceliydi, 7 x 5 problemiyle iyi başa çıkıyor (ve aynalardan birini kaldırdığınızda, imkansız hale getirdiğinizde), 30 5'i çözmek için yaklaşık 1 saat sürdü.

using Q=System.Console;class P{static int w,L;static string S(char[]M,int t,int r,int i,int d,int[]B){var s="";if(r<0)return s;M=(char[])M.Clone();B=(int[])B.Clone();B[i]=1;for(i+=d;M[t]<48|t==i;i=t+(d=t<w?w:t>L-w?-w:t%w<1?1:-1))if(++t>=L){for(i=0;++i<L&r>0;)if(B[i]<1&M[i]<33){M[i]='.';r--;}return r<1?new string(M):s;}int c=M[i];if(c>32)s=c>47|c<46?s=c==M[t]?S(M,t,r,t,0,B):s:S(M,t,r,i,c<47?w/d:-w/d,B);else if((s=S(M,t,r,i,d,B))==""&B[i]<1){M[i]='.';s=S(M,t,r-1,i,w/d,B);if(s==""){M[i]='/';s=S(M,t,r-1,i,-w/d,B);}}return s;}static void Main(){string a,A="",R=A;for(;(a=Q.ReadLine())!=null;A+=a)L+=(w=a.Length);var G=A.ToCharArray();int r=0,i=L;for(;i>0;G[i]=G[i]=='|'?',':G[i])if(G[--i]==47|G[i]==92){r++;G[i]=' ';}a=S(G,0,r,1,w,new int[L]);if(a=="")R="Impossible\n";else for(;i<L;i+=w)R+=a.Substring(i,w)+"\n";Q.Write(R.Replace(".","\\").Replace(",","|"));}}

7 5 Örnek:

+abcde+
f/////d
a//   c
f     |
+-b-e-+

+abcde+
f   \ d
a/  //c
f/ \ /|
+-b-e-+

İmkansız sürüm:

+abcde+
f ////d
a//   c
f     |
+-b-e-+

Impossible

Farklı bir şey (program orijinal ayna düzenine bakmaz):

+a----+
|//// |
|/////|
|/////|
+----a+

+a----+
| /\\\|
|\\\\\|
|\\/\\|
+----a+

30'a 5 çözelti:

+abcdefghijklmnopqrstuvwxyA-+
| \\\\\\\\\\\\\\\\\\\\\\\\ \|
| /                       //|
|\                         \|
+-Abcdefghijklmnopqrstuvwxya+

Her bir lazer kaynağına sırayla bakar ve bunun için geçerli bir rota oluşturur (mümkünse) ve sonra bir sonrakine geçer. Hangi lazer kaynağına (hedefe) baktığını, yerleştirilmesi için kaç tane ayna kaldığını, mevcut hücrenin "bulunduğu yer", hareket ettiği yönü ve her bir hücrenin ne olduğunu bilmesi gereken oldukça basit bir derinlik-öncesi aramadır. zaten ziyaret edildi (böylece zaten bir yere ayna koymaz). Son 3, geçerli hedefin yolunu birleştirmek ve hedef değiştiğinde sıfırlamak için kullanılır. Tüm lazerler bağlandıktan sonra, devam eder ve boş bırakılması gerekmeyen boşlukları doldurur (ziyaret edilen her yeri bilmesi gereken başka bir neden).

Güzergâhlar inşa ederken, bir ayna yerleştirmek için "ileri" gitmeyi tercih eder ve bunu yapıldığında, bir "\" aynayı tercih eder - bu en iyi yukarıdaki "farklı bir şey" örneğinde görülür; en çok 'a', sonra bir "\" ile bir çözüm bulabilirse sürekli olarak "\" doldurur, aksi takdirde "/" (doğal olarak, ilk hücreyi atlamak bir çözüm bulamamasına neden olursa, o zaman geri izlemek ve orada bir ayna koymak deneyin).

using Q=System.Console;

class P
{
    static int w,L;

    // M is cur grid
    // t is target edge thing (0->L)
    // r is mirrors remaining
    // i is pos
    // d is dir
    static string S(char[]M,int t,int r,int i,int d,int[]B)
    {
        var s="";

        if(r<0) // no mirrors left
            return s;

        // clone everything
        M=(char[])M.Clone();
        B=(int[])B.Clone();

        B[i]=1; // can't write to this

        for(i+=d; // move i
            M[t]<48|t==i; // only if target is something sensible (increment if i==t)
            i=t+(d=t<w?w:t>L-w?-w:t%w<1?1:-1)) // reflect, should be fine for w=3
            if(++t>=L) // run off the end
            {
                for(i=0;++i<L&r>0;) // don't need I any more (count through everything)
                    if(B[i]<1&M[i]<33) // not been here & it's open space
                    {
                        M[i]='.'; // doesn't matter
                        r--;
                    }
                return r<1?new string(M):s; // none remaining ? victory : defeat
            }

        int c=M[i];
        if(c>32) // not boring
            s=c>47|c<46? // hit edge
                s=c==M[t]? // hit the correct thing
                    S(M,t,r,t,0,B): // i+0=t, tells it to increment t
                    s
            :S(M,t,r,i,c<47?w/d:-w/d,B); // mirror
        else // boring
            if((s=S(M,t,r,i,d,B))==""&B[i]<1) // fwd
            {
                M[i]='.'; // use . instead of \
                s=S(M,t,r-1,i,w/d,B); // \
                if(s=="")
                {
                    M[i]='/';
                    s=S(M,t,r-1,i,-w/d,B); // /
                }
            }

        return s;
    }

    static void Main()
    {
        string a,A="",R=A; // R is free
        for(;(a=Q.ReadLine())!=null;A+=a) // read input
            L+=(w=a.Length); // note width, accumulate length

        var G=A.ToCharArray();

        int r=0,i=L; // count mirrors (I refuse to make these static)
        for(;i>0; // end on i=0
            G[i]=G[i]=='|'?',':G[i]) // replace | with ,
            if(G[--i]==47|G[i]==92) // remove and count mirrors
            {
                r++;
                G[i]=' '; // storing G[i] doesn't seem to save anything
            }

        // search
        a=S(G,0,r,1,w,new int[L]);

        if(a=="") // defeat
            R="Impossible\n";
        else // victory
            for(;i<L;i+=w) // for each line
                R+=a.Substring(i,w)+"\n";

        Q.Write(R.Replace(".","\\").Replace(",","|")); // swap back | and \
    }
}

Güzel çözüm. Yeni puanlama sistemine göre en az 917/7 = 131 puan alırsınız.
Mantık Şövalyesi

2

Python, 671 654 bayt

Bir çözüm değil, bir girişim, aşağıda okuyun.

import random as R
def V(F):
 for S,_x,_y in (F[0],0,1),(F[-1],0,-1),([L[0] for L in F],1,0),([L[-1] for L in F],-1,0):
  for i,C in enumerate(S):
   if not C in '+-|':
    x=_x;y=_y
    if not x: X=i;Y=y
    elif not y: Y=i;X=x
    while F[Y][X] != C:
     if F[Y][X]=='\\':x,y=y,x
     if F[Y][X]=='/':a=x+y;x,y=x-a,y-a
     X+=x;Y+=y
     try:
      if F[Y][X] in '+-|':return False
     except:
      return False
 return True
F=open(input()).read().split('\n')
while 1:
 _=[F[0]]+['\n'.join([L[0]+''.join([R.choice(' \\/')for i in range(len(F[0])-2)])+L[-1] for L in F[1:-1]])]+[F[-1]]
 if V(_):
  for l in _: print l
  break

Çözümden memnun olmadığım için bunu maksimuma çıkarmadım. kenar çizgisinde bulduğu her karakter Viçin alanı yürüterek verilen bir çözümü doğrular . Çözeltiler rastgele üretilir. Çirkin, giriş1 için çalışıyor, ancak diğer girişler için çok zaman alıyor. Rastgele çözümleri denediğinden, bunun verilen sorun için gerçek bir çözüm olduğunu düşünmüyorum; ama başkalarına yardımcı olabilir.FC

Çalıştırmak: echo "entry1.txt" | python script.py


1
Yeni puanlama sistemi ile bu geçerli bir çözümdür ancak bir bölen ikramiye puanı almaz (2 veya daha fazla ayna ile sorunları çözemezse). Ben daha önce geçersiz yapılandırmalar budama ile bunu optimize edebilirsiniz düşünüyorum (örneğin: her sütun veya satır kenarındaki bir harf ile en az bir ayna olmalıdır - eşleşen harfler birbirinin tersi sürece).
Mantık Şövalyesi
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.