Tìm một cấu hình gương để phù hợp với các điểm đến laser


13

CẬP NHẬT SCORING : Vì thử thách này khó khăn hơn tôi dự đoán, tôi đã điều chỉnh cách tính điểm. Một chương trình có thể giải quyết một đầu vào gương duy nhất là một câu trả lời hợp lệ. Các chương trình tinh vi hơn nhận được một phần thưởng cho điểm số của họ.

Đã có một số câu đố trên PPCG để tìm đường đi laser trong hộp gương. Trong câu đố này, bạn cần tạo ra một hộp gương để phù hợp với một số điểm đến laser.

Bạn được cung cấp một hộp và thông số kỹ thuật nơi các tia laser được nhập và thoát. Chương trình của bạn cần đặt chính xác N gương hai mặt trong hộp để đáp ứng thông số kỹ thuật. Các gương phải được đặt ở góc 45 độ nhưng có thể dốc về phía trước hoặc dốc về phía sau.

Đầu vào

Chương trình của bạn sẽ chấp nhận lưới ô vuông thông qua STDIN, đối số dòng lệnh hoặc tệp trong các ví dụ định dạng sau:

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

Các cặp chữ cái ([a-zA-Z] có thể được sử dụng) cho biết đầu vào / đầu ra của tối đa 52 laser. Bên trong hộp sẽ là N/ gương. Kích thước hộp sẽ là 3 <= W, H <= 200. Hộp được làm bằng các +|-ký tự. Có thể có bất kỳ số lượng gương trong hộp bao gồm không.

Đầu ra

Đầu ra phải khớp với đầu vào, ngoại trừ các /ký tự có thể được di chuyển và / hoặc thay đổi thành các \ký tự. Chương trình của bạn sẽ gửi một chuỗi hộp gương chính xác tới STDOUT hoặc một tệp, theo dõi dòng mới tùy chọn. Nếu không có vị trí của gương có thể đáp ứng các đặc điểm kỹ thuật đầu vào, đầu ra Impossible\n. Ví dụ về các giải pháp có thể:

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

Ví dụ kiểm tra

Đầu vào:

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

Ví dụ đầu ra:

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

Ghi điểm (CẬP NHẬT)

Đây là mã golf với tiền thưởng. Bạn nên đề cử với câu trả lời của bạn có bao nhiêu gương mà chương trình của bạn có thể giải quyết (N). Điểm của bạn là độ dài chương trình của bạn tính theo byte chia cho N. Điều này cho phép mọi người tham gia với một chương trình đơn giản, nhưng thưởng cho nhiều lập trình viên tham vọng hơn với phần thưởng.

Sơ hở tiêu chuẩn không được phép.


3
Điều này nghe có vẻ như là một vấn đề khó khăn, bất kể chơi golf.
orlp

2
Gợi ý: lực lượng vũ phu không phải là một lựa chọn ; nó sẽ đưa bạn 3 tuổi vũ trụ với 10k tùy chọn mỗi giây cho ví dụ lớn hơn.
Sanchise

@sanchises Tôi nghĩ rằng nó sẽ mất nhiều thời gian hơn, vì bất kỳ gương nào cũng có thể được lật, vì vậy tôi nghĩ bạn cũng cần một * 2^30thành phần trong đó
VisualMelon

Gợi ý thêm: Bạn sẽ cần khai thác các thuộc tính của câu đố để cắt tỉa không gian tìm kiếm của bạn. Bạn cũng có thể sử dụng kết hợp các giải pháp một phần hoặc hoàn trả từ các giải pháp một phần gần với một giải pháp hoàn chỉnh. Bây giờ có giá trị để trả lời với các giải pháp đơn giản hơn, vì vậy các chương trình giải một hoặc hai câu đố gương cũng được hoan nghênh.
Logic Knight

Câu trả lời:


2

C # - 897 862 byte

Tìm thấy một lỗi nghiêm trọng với việc đặt gương ở những nơi không thể. Bây giờ nó hoạt động, hy vọng! Cũng đã chơi golf nhẹ, không thể rời khỏi vòng lặp trong đó ... đáng xấu hổ.

Hoàn thành chương trình, nhận đầu vào từ STDIN, đầu ra thành STDOUT.

Điều này rất thú vị, nó đối phó tốt với vấn đề 7 x 5 (và khi bạn loại bỏ một trong các gương, làm cho nó không thể), mất khoảng 1 giờ để giải quyết 30 trên 5.

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 trên 5 Ví dụ:

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

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

Phiên bản không thể:

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

Impossible

Một cái gì đó khác nhau (chương trình không nhìn vào bố cục gương ban đầu):

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

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

Giải pháp 30 by 5:

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

Nó lần lượt xem xét từng nguồn laser và xây dựng tuyến đường hợp lệ cho nó (nếu có thể), sau đó chuyển sang nguồn tiếp theo. Đây là một tìm kiếm đầu tiên có độ sâu khá đơn giản, phải biết nguồn laser (mục tiêu) mà nó đang nhìn, bao nhiêu gương để nó đặt, ô hiện tại nó "ở", hướng di chuyển và mỗi ô nó đã được truy cập (để nó không đặt gương ở đâu đó). 3 cái cuối cùng được sử dụng để lắp ráp đường dẫn cho mục tiêu hiện tại và khi thiết lập lại khi mục tiêu thay đổi. Khi nó có tất cả các laser được liên kết, nó sẽ tiếp tục và lấp đầy bất kỳ khoảng trống nào mà nó không cần để trống (một lý do khác mà nó cần biết ở mọi nơi nó được truy cập).

Khi nó xây dựng các tuyến đường, nó thích đi "về phía trước" hơn là chèn gương và khi thực hiện, nó thích một gương "\" - điều này được thấy rõ nhất trong ví dụ "một cái gì đó khác" ở trên, trong đó nó bỏ qua ô đầu tiên bên dưới top-most 'a', sau đó tiếp tục điền "\" nếu nó có thể tìm ra giải pháp với một, nếu không thì "/" (một cách tự nhiên, nếu bỏ qua ô đầu tiên dẫn đến việc nó không thể tìm ra giải pháp, thì nó sẽ thay thế theo dõi và thử đặt một tấm gương ở đó thay thế).

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 \
    }
}

Giải pháp tốt đẹp. Theo hệ thống tính điểm mới, bạn ghi được ít nhất 917/7 = 131.
Logic Knight

2

Python, 671 654 byte

Không phải là một giải pháp, nhưng một nỗ lực, đọc dưới đây.

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

Tôi đã không chơi golf đến mức tối đa, vì tôi không hài lòng với giải pháp. Vxác nhận một giải pháp nhất định bằng cách đi bộ trường Fcho mỗi ký tự Cmà nó tìm thấy bên lề. Các giải pháp được tạo ra một cách ngẫu nhiên. Thật xấu xí, nó hoạt động cho mục 1, nhưng mất nhiều thời gian cho các mục khác. Vì nó ngẫu nhiên thử các giải pháp, tôi không coi đây là một giải pháp thực tế cho vấn đề đã cho; nhưng nó có thể giúp đỡ người khác

Chạy: echo "entry1.txt" | python script.py


1
Với hệ thống tính điểm mới, đây là một giải pháp hợp lệ nhưng không ghi được phần thưởng chia (trừ khi nó có thể giải quyết vấn đề với 2 gương trở lên). Tôi nghĩ rằng bạn có thể tối ưu hóa điều này bằng cách loại bỏ các cấu hình không hợp lệ trước đó (ví dụ: mỗi cột hoặc hàng có một chữ cái trên cạnh phải có ít nhất một gương - trừ khi các chữ cái trùng nhau đối diện nhau).
Logic Knight
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.