Phát hiện các cửa sổ nghệ thuật ASCII được tạo từ các ký tự M và S


28

Cửa sổ là một hình vuông nghệ thuật ASCII có chiều dài cạnh lẻ ít nhất là 3, với một đường viền ký tự duy nhất xung quanh cạnh cũng như các nét dọc và ngang ở giữa:

#######
#  #  #
#  #  #
#######
#  #  #
#  #  #
#######

Cửa sổ MS là một cửa sổ nơi đường viền chỉ được tạo từ các ký tự MS. Nhiệm vụ của bạn là viết một chương trình (hoặc hàm) lấy một chuỗi và xuất ra một giá trị trung thực nếu đầu vào là một Cửa sổ MS hợp lệ và giá trị falsey nếu không.

Thông số kỹ thuật

  • Bạn có thể lấy đầu vào là một chuỗi phân tách dòng mới hoặc một chuỗi các chuỗi đại diện cho mỗi dòng.
  • Đường viền của Cửa sổ MS có thể chứa hỗn hợp các ký tự M và S, nhưng bên trong sẽ luôn bao gồm các khoảng trắng.
  • Bạn có thể chọn chỉ phát hiện các cửa sổ có dòng mới, hoặc chỉ cửa sổ mà không theo dõi dòng mới, nhưng không phải cả hai.

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

Sự thật:

MMM
MMM
MMM

SMSMS
M M S
SMSMM
S S M
SMSMS

MMMMMMM
M  S  M
M  S  M
MSSSSSM
M  S  M
M  S  M
MMMMMMM

Falsey:

Hello, World!

MMMM
MSSM
MS M
MMMM

MMSMM
M S.M
sSSSS
M S M
MMSMM

MMMMMMM
M  M  M
MMMMMMM
M  M  M
MMMMMMM

MMMMMMM
M M M M
MMMMMMM
M M M M
MMMMMMM
M M M M
MMMMMMM

MMSSMSSMM
M   M   M
S   S   S
S   S  S
MMSSMSSMM
S   S   S
S   S   S
M   M   M
MMSSMSSMM

3
Đây là một bước ngoặt lớn về nghệ thuật ASCII, một vấn đề quyết định để phát hiện một cấu trúc nhất định.
xnor

4
@xnor Tôi cảm thấy như chúng ta có thể muốn một thẻ khác cho nghệ thuật ASCII ngược như thế này.
Trái cây Esolanging

2
mặc dù không đặc trưng cho nghệ thuật ascii, khớp mẫu có thể là một lựa chọn tốt cho một thẻ mới
Lemon

Bạn có thể thêm một hoặc hai trường hợp thử nghiệm trong đó chuỗi không tạo thành một mảng hình chữ nhật không?
Greg Martin

1
@Mast, bạn nói khá đúng! Có lẽ thách thức cần làm rõ
Chris M

Câu trả lời:


1

Pyke, 34 31 byte

lei}t\Mcn+it*i\M*+s.XM"QJ\S\M:q

Hãy thử nó ở đây!

lei                              -         i = len(input)//2
   }t                            -        (^ * 2) - 1
     \Mc                         -       "M".center(^)
        n+                       -      ^ + "\n"
          it*                    -     ^ * (i-1)
                 +               -    ^ + V
             i\M*                -     "M"*i
                  s              -   palindromise(^)
                   .XM"          -  surround(^, "M")
                               q - ^ == V
                       QJ        -   "\n".join(input)
                         \S\M:   -  ^.replace("S", "M")


7

Grime , 39 38 byte

Cảm ơn Zgarb vì đã tiết kiệm 1 byte.

e`BB/BB/W+ W/+
B=W|B/W\ * W/\ /*
W=[MS

Hãy thử trực tuyến!

Tôi không chắc liệu có cách nào đơn giản hơn để thực thi tỷ lệ khung hình vuông của các thành phần cửa sổ riêng lẻ hay không bằng cách sử dụng một nonterminal đệ quy, nhưng điều này dường như đang hoạt động khá tốt.

Giải trình

Tốt nhất là đọc chương trình từ dưới lên.

W=[MS

Điều này chỉ đơn giản là định nghĩa một nonterminal (mà bạn có thể nghĩ là chương trình con khớp với hình chữ nhật) Wkhớp với một Mhoặc một S(có một ẩn ]ở cuối dòng).

B=W|B/W\ * W/\ /*

Điều này xác định một thiết bị đầu cuối Bkhông khớp với khoảng một phần tư đầu ra, tức là một bảng điều khiển cửa sổ với đường viền bên trái và trên cùng. Một cái gì đó như thế này:

MSM
S  
M  

Để đảm bảo rằng bảng điều khiển cửa sổ này là hình vuông, chúng tôi xác định Bđệ quy. Đó là một nhân vật cửa sổ W, hoặc nó B/W\ * W/\ /*thêm một lớp ở bên phải và ở dưới cùng. Để xem làm thế nào nó làm điều này, hãy loại bỏ một số đường cú pháp:

(B/W[ ]*)(W/[ ]/*)

Điều này là giống nhau, bởi vì ghép nối ngang có thể được viết ABhoặc A B, nhưng cái sau có độ ưu tiên thấp hơn so với nối dọc /trong khi đối với cái trước có giá trị cao hơn. Vì vậy, B/W[ ]*một Bvới một nhân vật cửa sổ và một hàng không gian bên dưới. Và sau đó chúng tôi nối thêm vào W/[ ]/*đó là một ký tự cửa sổ với một cột khoảng trắng.

Cuối cùng, chúng tôi lắp ráp các nonterminals này thành hình dạng cửa sổ cuối cùng:

BB/BB/W+ W/+

Đó là bốn ô cửa sổ Btheo sau là một hàng ký tự cửa sổ và một cột ký tự cửa sổ. Lưu ý rằng chúng tôi không khẳng định rõ ràng rằng bốn bảng cửa sổ có cùng kích thước, nhưng nếu chúng không thể ghép chúng thành hình chữ nhật.

Cuối cùng, e`phần đầu chỉ đơn giản là một cấu hình cho Grime kiểm tra xem toàn bộ đầu vào có thể được khớp với mẫu này không (và nó in 0hoặc 1theo đó).


5

JavaScript (ES6), 115 113 byte

a=>(l=a.length)&a.every((b,i)=>b.length==l&b.every((c,j)=>(i&&l+~i-i&&l+~i&&j&&l+~j-j&&l+~j?/ /:/[MS]/).test(c)))

Lấy đầu vào là một mảng các mảng ký tự (thêm 5 byte cho một chuỗi các chuỗi) và trả về 1hoặc 0. Sau khi xác minh rằng chiều cao là số lẻ, mọi hàng được kiểm tra để đảm bảo mảng là hình vuông và mỗi ký tự được xác minh là một trong các ký tự mà chúng tôi mong đợi ở vị trí cụ thể đó. Chỉnh sửa: Đã lưu 2 byte nhờ @PatrickRoberts.


Bạn có thể thay đổi (...).includes(c)để ~(...).search(c)tiết kiệm 1 byte
Patrick Roberts

1
Trên thực tế, thậm chí tốt hơn bạn có thể thay đổi nó để (...?/ /:/[MS]/).test(c)tiết kiệm 2 byte thay vì chỉ 1.
Patrick Roberts

@PatrickRoberts Dễ thương, cảm ơn!
Neil

5

Perl, 124 123 119 95 93 84

Kịch bản Perl sau đây đọc một ứng dụng MS Window từ đầu vào tiêu chuẩn. Sau đó, nó thoát với trạng thái thoát bằng 0 nếu ứng viên là Cửa sổ MS và với trạng thái thoát khác không nếu không.

Nó hoạt động bằng cách tạo hai biểu thức chính quy, một cho dòng trên cùng, giữa và dưới cùng và một cho mọi dòng khác và kiểm tra đầu vào đối với chúng.

Cảm ơn, @Dada. Và một lần nữa.

map{$s=$"x(($.-3)/2);$m="[MS]";($c++%($#a/2)?/^$m$s$m$s$m$/:/^${m}{$.}$/)||die}@a=<>

Tôi không chắc chắn đưa ra kết quả vì trạng thái thoát được cho phép (mặc dù tôi không có thời gian để tìm kiếm bài đăng meta có liên quan). Bất kể, bạn có thể lưu một vài byte:@a=<>;$s=$"x(($.-3)/2);$m="[MS]";map{$a[$_]!~($_%($./2)?"$m$s$m$s$m":"$m${m}{$.}")&&die}0..--$.
Dada

@Dada: Cảm ơn! Đó là một cải tiến ấn tượng: 24 ký tự. (Có mã "$ m" đi lạc trong mã của bạn, do đó, nó thậm chí còn ngắn hơn so với lần đầu tiên.) Tôi không chắc chắn nếu báo cáo kết quả với mã thoát được cho phép nói chung nhưng tôi đã lấy "viết chương trình ( hoặc chức năng) "như cho phép một người linh hoạt với cách trả về kết quả trong trường hợp cụ thể này; mã thoát thực tế là các giá trị trả về hàm của môi trường * nix. :-)
nwk

Tạo 26 ký tự đó.
nwk

1
Thực ra, tôi đang decrementing $.ở cuối để tránh sử dụng hai lần $.-1(đặc biệt là kể từ khi lần đầu tiên nó được ($.-1)/2nên nó cần thêm một số ngoặc đơn), do đó $mtrong $m${m}{$.}không phải là một sai lầm. Ngoài ra, bây giờ tôi mới nhận ra, nhưng các regex nên được bao quanh ^...$(vì vậy ký tự phụ ở cuối hoặc đầu làm cho chúng thất bại), hoặc ngắn hơn: sử dụng nethay vì !~.
Dada

Mặc dù vậy, rõ ràng bạn không thể sử dụng nethay vì !~(Tôi không nên viết tin nhắn khi tôi thức dậy chỉ trong 15 phút!). Vì vậy, bạn sẽ phải sử dụng ^...$trong cả regex tôi sợ.
Dada

2

Toán học, 166 byte

Union[(l=Length)/@data]=={d=l@#}&&{"M","S"}~(s=SubsetQ)~(u=Union@*Flatten)@{#&@@(p={#,(t=#~TakeDrop~{1,-1,d/2-.5}&)/@#2}&@@t@#),p[[2,All,1]]}&&{" "}~s~u@p[[2,All,2]]&

Hàm không tên lấy danh sách các danh sách các ký tự làm đầu vào và trả về Truehoặc False. Đây là một phiên bản ít chơi gôn hơn:

(t = TakeDrop[#1, {1, -1, d/2 - 0.5}] &; 
Union[Length /@ data] == {d = Length[#1]}
  &&
(p = ({#1, t /@ #2} &) @@ t[#1];
SubsetQ[{"M", "S"}, Union[Flatten[{p[[1]], p[[2, All, 1]]}]]]
  && 
SubsetQ[{" "}, Union[Flatten[p[[2, All, 2]]]]])) &

Dòng đầu tiên xác định hàm t, phân tách một danh sách độ dài dthành hai phần, phần đầu tiên là mục đầu tiên, giữa và cuối cùng của danh sách và phần thứ hai là tất cả phần còn lại. Dòng thứ hai kiểm tra xem đầu vào là một mảng vuông ở vị trí đầu tiên. Dòng thứ tư sử dụng thai lần, một lần cho chính đầu vào và một lần trên tất cả * các chuỗi trong đầu vào, để phân tách các ký tự được cho là "M"hoặc "S"từ các ký tự được coi là khoảng trắng; sau đó các dòng thứ năm và thứ bảy kiểm tra xem chúng có thực sự là những gì chúng được cho là không.


2

JavaScript (ES6), 108 106 byte

Đầu vào: mảng chuỗi / Đầu ra: 0hoặc1

s=>s.reduce((p,r,y)=>p&&r.length==w&(y==w>>1|++y%w<2?/^[MS]+$/:/^[MS]( *)[MS]\1[MS]$/).test(r),w=s.length)

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


2

JavaScript (ES6), 140 138 141 140 byte

Tôi biết đây không phải là số byte chiến thắng (mặc dù nhờ Patrick Roberts cho -3 và tôi nhận ra rằng nó đã ném dương tính giả cho 1 thay vì M / S: +3), nhưng tôi đã làm theo cách hơi khác, tôi ' Tôi mới làm điều này, và nó rất vui ...

Chấp nhận một chuỗi các chuỗi, một chuỗi cho mỗi dòng và trả về true hoặc false. Dòng mới được thêm vào cho rõ ràng (không bao gồm trong số byte).

f=t=>t.every((e,i)=>e.split`S`.join`M`==[...p=[b='M'.repeat(s=t.length),
...Array(z=-1+s/2|0).fill([...'MMM'].join(' '.repeat(z)))],...p,b][i])

Thay vì kiểm tra đầu vào theo mẫu tổng quát, tôi xây dựng cửa sổ 'M' có cùng kích thước, thay S bằng M trên đầu vào và so sánh hai cửa sổ.

Bị đánh cắp

f = t => t.every( // function returns true iff every entry in t
                  // returns true below
  (e, i) => e.split`S`.join`M` // replace all S with M
                                 // to compare to mask
  == [ // construct a window of the same size made of Ms and
       // spaces, compare each row 
      ...p = [ // p = repeated vertical panel (bar above pane)
               // which will be repeated
              b = 'M'.repeat(s = t.length),
                  // b = bar of Ms as long as the input array
              ...Array(z = -1 + s/2|0).fill([...'MMM'].join(' '.repeat(z)))],
              // z = pane size; create enough pane rows with
              // Ms and enough spaces
      ...p, // repeat the panel once more
      b][i] // finish with a bar
)

console.log(f(["111","111","111"]))

console.log(f(["MMMMM","M S M","MSSSM","M S M","MSSSM"]))

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

f=t=>t.every((e,i)=>e.split`S`.join`M`==[...p=[b='M'.repeat(s=t.length),
...Array(z=-1+s/2|0).fill([...'MMM'].join(' '.repeat(z)))],...p,b][i])


truthy=`MMM
MMM
MMM

SMSMS
M M M
SMSMS
M M M
SMSMS

MMMMMMM
M  S  M
M  S  M
MSSSSSM
M  S  M
M  S  M
MMMMMMM`.split('\n\n')

falsey=`Hello, World!

MMMM
MSSM
MS M
MMMM

MMSMM
M S.M
sSSSS
M S M
MMSMM

MMMMMMM
M  M  M
MMMMMMM
M  M  M
MMMMMMM

MMMMMMM
M M M M
MMMMMMM
M M M M
MMMMMMM
M M M M
MMMMMMM`.split('\n\n')

truthy.forEach(test=>{
  console.log(test,f(test.split('\n')))
})

falsey.forEach(test=>{
  console.log(test,f(test.split('\n')))
})


1
Để tham khảo trong tương lai, trừ khi hàm đệ quy, f=không cần đưa vào số byte, vì vậy đây thực sự là một đệ trình 138 byte.
Patrick Roberts

Bạn có thể thay thế z=-1+s/2|0bằng z=(s-3)/2để tiết kiệm 1 byte
Patrick Roberts

Bạn cũng có thể thay thế e.replace(/S/g,'M')==...bằng e.split`S`.join`M`==...để lưu một byte khác
Patrick Roberts

Cảm ơn! z=-1+s/2|0có để trả về một số nguyên dương cho s == 1 và thậm chí s, tức là hàm trả về false mà không có Array () làm hỏng nó. Nếu không thì logic cần thiết làm cho nó dài hơn. Mẹo hay về chia tách / tham gia, cảm ơn
Chris M

Bắt tốt, tôi đã không xem xét s=1trường hợp này, vì regex không hợp lệ của tôi chỉ âm thầm thất bại.
Patrick Roberts

1

JavaScript (ES6), 109 107 106 105 99 byte

s=>!s.split`S`.join`M`.search(`^((M{${r=s.search`
`}})(
(M( {${w=(r-3)/2}})M\\5M
){${w}}))\\1\\2$`)

Chỉnh sửa : Whoa, Arnauld đã lưu cho tôi 6 byte bằng cách thay đổi s.split`\n`.lengththành s.search`\n`! Cảm ơn!

Điều này cần một chuỗi đa dòng đơn và xây dựng RegExpxác nhận dựa trên cơ sở bằng cách sử dụng độ dài của chuỗi đầu vào. Trả về truehoặc false. Giả định một cửa sổ hợp lệ không có một ký tự dòng mới.

Bản giới thiệu

f=s=>!s.split`S`.join`M`.search(`^((M{${r=s.search`
`}})(
(M( {${w=(r-3)/2}})M\\5M
){${w}}))\\1\\2$`);
`MMM
MMM
MMM

SMSMS
M M M
SMSMS
M M M
SMSMS

MMMMMMM
M  S  M
M  S  M
MSSSSSM
M  S  M
M  S  M
MMMMMMM

Hello, World!

MMMM
MSSM
MS M
MMMM

MMSMM
M S.M
sSSSS
M S M
MMSMM

MMMMMMM
M  M  M
MMMMMMM
M  M  M
MMMMMMM

MMMMMMM
M M M M
MMMMMMM
M M M M
MMMMMMM
M M M M
MMMMMMM`.split`

`.forEach(test=>{console.log(test,f(test));});


Cách tiếp cận tốt đẹp! Bạn có thể sử dụng r=s.search('\n')thay vì split / length?
Arnauld

@Arnauld đề nghị tuyệt vời, cảm ơn!
Patrick Roberts

Các dấu ngoặc đơn trên s=>!s.split`S`.join`M`.search([...])có thể được loại bỏ, mà không gây ra lỗi cú pháp.
Ismael Miguel

@IsmaelMiguel đúng, nhưng sau đó chuỗi được truyền dưới dạng mẫu, làm mất hiệu lực ẩnRegExp
Patrick Roberts

Thật tệ ... Tôi thực sự không ngờ rằng ...
Ismael Miguel
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.