Gương ma thuật điên rồ


22

Giới thiệu

Tôi có một căn phòng đầy những tấm gương ma thuật . Chúng là những cổ vật bí ẩn có thể nhân đôi bất kỳ vật phẩm nào, ngoại trừ một chiếc gương ma thuật khác. Rõ ràng hơn, một phiên bản trùng lặp của vật phẩm sẽ xuất hiện ở phía bên kia của gương, ở cùng một khoảng cách. Tuy nhiên, nếu có một gương ma thuật khác ở hai bên, giữa gương nhân đôi và một trong hai vật phẩm (nguyên bản hoặc trùng lặp), bản sao sẽ không được hình thành. Mục ban đầu có thể là bên trái hoặc bên phải của gương và bản sao sẽ xuất hiện ở phía bên kia. Ngoài ra, các mục trùng lặp có thể được nhân đôi bởi một gương khác. Các mục không bao giờ chặn sự trùng lặp của các mục khác (ngoại trừ bằng cách trực tiếp vào vị trí của mục trùng lặp).

Đầu vào

Đầu vào của bạn là một chuỗi bao gồm các ký tự .#|, đại diện cho không gian trống, vật phẩm và gương ma thuật. Sẽ luôn có ít nhất một chiếc gương ma thuật trong đầu vào.

Đầu ra

Đầu ra của bạn sẽ là một chuỗi khác trong đó mỗi gương ma thuật đã nhân đôi mọi vật phẩm có thể, theo các quy tắc ở trên. Bạn có thể giả định rằng sẽ luôn có một khoảng trống tại chỗ xuất hiện một mục trùng lặp (vì vậy chúng sẽ không đi ra khỏi giới hạn).

Ví dụ

Hãy xem xét chuỗi đầu vào

.#.|.....|......#
 A B     C      D

nơi chúng tôi đã đánh dấu một số vị trí cho rõ ràng. Gương nhân Bđôi mục A, kết thúc ở bên phải của nó:

.#.|.#...|......#
 A B     C      D

Gương Csau đó nhân đôi mục mới:

.#.|.#...|...#..#
 A B     C      D

Gương Ckhông thể nhân đôi vật phẩm A, vì gương Bđang cản đường. Nó cũng không thể sao chép mục D, vì gương Bnằm ở phía bên kia. Tương tự như vậy, gương Bkhông thể sao chép mục Dhoặc trùng lặp bên cạnh nó, vì gương Cđang cản trở, vì vậy đây là đầu ra chính xác.

Đối với một ví dụ khác, hãy xem xét đầu vào

.##..#...|#..##...|..##....#.
 AB  C   DE  FG   H  IJ    K

Gương Dcó thể nhân đôi ABsang phải, EGsang trái. CFđã là bản sao của nhau. Chuỗi trở thành

.##.##..#|#..##.##|..##....#.
 AB  C   DE  FG   H  IJ    K

Gương Hcó thể nhân đôi E, Fvà các bản sao của ABbên phải và Ibên trái. GJđã là bản sao của nhau, và gương Dlà theo cách của K. Bây giờ chúng tôi có

.##.##..#|#..#####|#####..##.
 AB  C   DE  FG   H  IJ    K

Cuối cùng, gương Dcó thể nhân đôi bản sao Ibên trái. Chúng tôi kết thúc với

.#####..#|#..#####|#####..##.
 AB  C   DE  FG   H  IJ    K

Quy tắc và tính điểm

Bạn có thể viết một chương trình đầy đủ hoặc một chức năng. Số byte thấp nhất sẽ thắng. Các bài nộp không sử dụng công cụ regex cạnh tranh tách biệt với các công cụ thực hiện và có thể được đánh dấu bằng (không có regex) .

Các trường hợp thử nghiệm

"|" -> "|"
"..|.." -> "..|.."
".#.|..." -> ".#.|.#."
"..#|.#." -> ".##|##."
".#..|....|.." -> ".#..|..#.|.#"
".|..|.#....." -> "#|#.|.#....."
"...|.#...|....#" -> ".##|##...|...##"
"......#|......." -> "......#|#......"
".#.|.....|......#" -> ".#.|.#...|...#..#"
".......|...#.##|...." -> "##.#...|...#.##|##.#"
"...#..||.......#..#...#" -> "...#..||.......#..#...#"
".##|.#....||#||......#|.#" -> ".##|##....||#||.....##|##"
".##..#...|#..##...|..##....#." -> ".#####..#|#..#####|#####..##."
".#|...||...|#...|..##...|#...." -> ".#|#..||.##|##..|..##..#|#..##"
"....#.|...#.|..|.|.....|..#......" -> "..#.#.|.#.#.|.#|#|#.#..|..#.#...."
"..|....|.....#.|.....|...|.#.|..|.|...#......" -> ".#|#...|...#.#.|.#.#.|.#.|.#.|.#|#|#..#......"

Chúng ta có thể lấy một mảng các ký tự làm đầu vào và / hoặc đầu ra không?
Conor O'Brien

@ ConorO'Brien Không, trừ khi đó là đại diện tự nhiên của một chuỗi trong ngôn ngữ của bạn.
Zgarb

Câu trả lời:


10

Võng mạc , 50 byte

+`([#.])(([#.])*\|(?>(?<-3>[#.])*))(?!\1)[#.]
#$2#

Hãy thử trực tuyến! (Dòng đầu tiên cho phép bộ kiểm tra được phân tách bằng nguồn cấp.)

Tôi đoán điều này ngược lại với một đệ trình (không có biểu thức chính quy).

Giải trình

Đây chỉ đơn giản là một sự thay thế regex, được áp dụng nhiều lần ( +) cho đến khi chuỗi ngừng thay đổi. Tôi đang sử dụng các nhóm cân bằng để đảm bảo rằng hai vị trí được nhân đôi có cùng khoảng cách với gương đã cho (phản hồi sẽ không được thực hiện, vì chuỗi chính xác ở cả hai bên |có thể khác nhau).

([#.])            # Match and capture a non-mirror cell.
(                 # This will match and capture everything up to its corresponding
                  # cell so that we can write it back in the substitution.
  ([#.])*         #   Match zero or more non-mirror cells and push each one onto
                  #   group 3. This counts the distance from our first match to
                  #   the mirror.
  \|              #   Match the mirror.
  (?>             #   Atomic group to prevent backtracking.
    (?<-3>[#.])*  #     Match non-mirror while popping from group 3.
  )               #   There are three reasons why the previous repetition
                  #   might stop:
                  #   - Group 3 was exhausted. That's good, the next position
                  #     corresponds to the first character we matched.
                  #   - We've reached the end of the string. That's fine,
                  #     the last part of the regex will cause the match to fail.
                  #   - We've hit another mirror. That's also fine, because
                  #     the last part of the regex will still fail.
)
(?!\1)            # Make sure that the next character isn't the same as the first
                  # one. We're looking for .|# or #|., not for #|# or .|.
[#.]              # Match the last non-mirror character.

Điều này được thay thế bằng #$2#cách đơn giản thay thế cả ký tự đầu tiên và cuối cùng của trận đấu bằng a #.


9

Perl, 49 byte

Tín dụng đầy đủ cho @Martin Ender cho người này đã đề xuất regex này ngắn hơn 15 byte so với của tôi.

47 byte mã + -plcờ

s/([.#])(\||[^|](?2)[^|])(?!\1)[^|]/#$2#/&&redo

Để chạy nó:

perl -plE 's/([.#])(\||[^|](?2)[^|])(?!\1)[^|]/#$2#/&&redo' <<< ".##..#...|#..##...|..##....#."

Các phần đầu tiên ( ([.#])) và cuối cùng ( (?!\1)[^|]) giống như trong câu trả lời của Retina (xem phần giải thích ở đó).
Phần giữa ( (\||[^|](?2)[^|])) sử dụng đệ quy perl ( (?2)) để khớp với một nhân bản ( \|) hoặc ( |) hai nhân vật không phải là nhân vật ( [^|]) được phân tách bằng cùng một mẫu ( (?2)).


Phiên bản cũ hơn (và xấu hơn) của tôi: s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo


4

Haskell (không có biểu thức chính quy), 117 byte

r=reverse
s=span(<'|')
m=zipWith min
g a|(b,l:c)<-s a,(d,e)<-s c=b++l:g(m(r b++[l,l..])d++e)|0<1=a
f x=m(g x)$r.g.r$x

2

PHP, 123 117 100 byte

for($t=$argv[1];$t!=$s;)$t=preg_replace("%([.#])(\||[.#](?2)[.#])(?!\g1)[.#]%","#$2#",$s=$t);echo$t;

chương trình lấy đối số dòng lệnh, regex lấy từ @Martin Ender / Dada. Chạy với -r.


@Zgarb đã sửa, cảm ơn
Titus

2

C, 176 byte

void t(char*a){int x=0;for(int i=0;a[i];i++)if(a[i]=='|'){for(int j=x;a[j]&&j<=i*2-x;j++){if((a[j]==35)&&(a[2*i-j]==46)){a[2*i-j]=35;i=-1;}if((i-j)&&(a[j]=='|'))break;}x=i+1;}}

Bị đánh cắp

void t(char*a)
{
    int x=0;
    for(int i=0;a[i];i++)
        if(a[i]=='|')
        {
            for(int j=x;a[j]&&j<=i*2-x;j++)
            {
                if((a[j]=='#')&&(a[2*i-j]=='.'))
                {
                    a[2*i-j]='#';
                    i=-1;
                    break;
                }
                if((i!=j)&&(a[j]=='|'))
                    break;
            }
            x=i+1;
        }
}

1
Tôi nghĩ bạn có thể lưu một vài byte bằng cách thay thế '#''.'bằng 3546tương ứng.
nhân tạo

Mã này có thể được đánh golf..a rất nhiều.
Mukul Kumar

cảm ơn nhân tạo, đã lưu 3 byes. '|' là 124, do đó không tiết kiệm được gì (nhưng có lẽ tôi nên thay đổi điều đó, vì vậy nó sẽ nhất quán; chưa chắc chắn). và @Mukul, tôi thực sự không thấy bằng cách nào, mà không thay đổi đáng kể dòng logic của nó.
Mắt Lev

kiểm tra xem mã này có chạy tốt không x,i,j;void t(char*a){while(a[i]++)if(a[i]=='|'){for(j=x;a[j++]&&j<=i*2-x;j++){if((a[j]==35)&&(a[2*i-j]==46)){a[2*i-j]=35;i=-1;break;}if((i-j)&&(a[j]=='|'))break;}x=i+1;}}- 170 byte
Mukul Kumar

1
Thay thế 1 byte (i! = J) bằng (ij) và nếu bạn sẽ gắn bó với c ++ thì ít nhất hãy xác định tất cả int tại một nơi ...
Mukul Kumar

1

JavaScript (ES6), 170 byte

s=>s.replace(/#/g,(c,i)=>(g(i,-1),g(i,1)),g=(i,d,j=h(i,d))=>j-h(j=j+j-i,-d)|s[j]!='.'||(s=s.slice(0,j)+'#'+s.slice(j+1),g(j,d)),h=(i,d)=>s[i+=d]=='|'?i:s[i]?h(i,d):-1)&&s

Ung dung:

function mirror(s) {
    for (var i = 0; i < s.length; i++) {
        // Reflect each # in both directions
        if (s[i] == '#') s = reflect(reflect(s, i, true), i, false);
    }
    return s;
}
function reflect(s, i, d) {
    // Find a mirror
    var j = d ? s.indexOf('|', i) : s.lastIndexOf('|', i);
    if (j < 0) return s;
    // Check that the destination is empty
    var k = j + (j - i);
    if (s[k] != '.') return s;
    // Check for an intervening mirror
    var l = d ? s.lastIndexOf('|', k) : s.indexOf('|', k);
    if (l != j) return s;
    // Magically duplicate the #
    s = s.slice(0, k) + '#' + s.slice(k + 1);
    // Recursively apply to the new #
    return reflect(s, k, d);
}
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.