Tạo một hình chữ nhật từ một đặc điểm kỹ thuật


14

Giới thiệu

Thử thách này được lấy cảm hứng từ Grime , ngôn ngữ phù hợp với mô hình 2D của tôi. Về cơ bản, bạn được cung cấp một "ngữ pháp" mô tả các lưới ký tự hai chiều và công việc của bạn là tạo ra một lưới theo ngữ pháp. Ngoài ra, lưới nên càng nhỏ càng tốt theo một nghĩa yếu nhất định.

Đầu vào

Đầu vào của bạn là một chuỗi chứa các ký tự ASCII chữ thường và các ký hiệu |-. Để đơn giản, đầu vào không chứa các ký tự chữ thường lặp đi lặp lại. Chuỗi là một đặc tả cho một lớp các lưới ký tự hình chữ nhật và nó được phân tích cú pháp từ trái sang phải bằng cách sử dụng một ngăn xếp như sau.

  • Cho một ký tự chữ thường c, đẩy vào ngăn xếp một m×nlưới của ký tự c, cho bất kỳ m, n ≥ 1.
  • Đưa ra một đường ống |, bật hai lưới ABtừ ngăn xếp ( Bở trên cùng) và đẩy lưới ABthu được bằng cách nối Bbên phải A. Điều này đòi hỏi điều đó ABcó chiều cao bằng nhau.
  • Đưa ra một dấu gạch nối -, bật hai lưới ABtừ ngăn xếp ( Bở trên cùng) và đẩy lưới A/Bthu được bằng cách ghép Bvào đáy A. Điều này đòi hỏi điều đó ABcó chiều rộng bằng nhau.

Nó được đảm bảo rằng đối với một số lựa chọn mnđược thực hiện trong quá trình phân tích cú pháp (có thể khác nhau cho mỗi chữ cái), đặc tả đầu vào mô tả chính xác một số hình chữ nhật, còn lại trên ngăn xếp ở cuối.

Đầu ra

Đầu ra của bạn là một lưới hình chữ nhật gồm các ký tự được chỉ định bởi đầu vào. Lưới phải tối thiểu theo nghĩa là loại bỏ bất kỳ hàng hoặc cột nào sẽ làm cho nó không hợp lệ. Bạn có thể trả về một chuỗi phân tách dòng mới (có hoặc không có dòng mới), một mảng ký tự 2D hoặc một chuỗi các chuỗi, tùy theo định dạng nào thuận tiện nhất.

Lưu ý rằng bạn không bắt buộc phải xử lý đầu vào chính xác như được mô tả ở trên; Điều quan trọng duy nhất là đầu ra của bạn là chính xác.

Thí dụ

Xem xét các đặc điểm kỹ thuật

par-s||e-

Đầu tiên, chúng tôi chọn đẩy một 1×2hình chữ nhật p1×1hình chữ nhật của ar(lý do cho điều này sẽ rõ ràng sau). Sau đó, chúng tôi bật các hình chữ nhật arhình chữ nhật, và đẩy nối dọc của chúng

a
r

Tiếp theo, chúng ta đẩy một 1×2hình chữ nhật s, bật nó và hình chữ nhật ở trên, và đẩy nối ngang của chúng

as
rs

Sau đó, chúng tôi bật hình chữ nhật đó và phình chữ nhật, và đẩy nối của chúng

pas
prs

Cuối cùng, chúng ta đẩy một 3×1hình chữ nhật của e, bật nó và hình chữ nhật ở trên, và đẩy nối dọc

pas
prs
eee

Đây là đầu ra của chương trình, hoặc ít nhất một trong các khả năng. Mặc dù vậy

ppas
ppas
pprs
eeee

cũng được tạo bởi đặc tả, nó không phải là đầu ra hợp lệ, vì nhiều hàng và cột có thể bị xóa.

Như một ví dụ tinh tế hơn, hãy xem xét

co|m|p|il|e|r|-

Đặc điểm kỹ thuật này tạo ra hình chữ nhật

comp
iler

đó là một đầu ra hợp lệ. Tuy nhiên, nó cũng tạo ra

commp
iiler

cũng hợp lệ vì không có hàng hoặc cột nào có thể bị xóa mà không làm mất hiệu lực của nó.

Quy tắc

Bạn có thể cung cấp một chương trình đầy đủ hoặc một chức năng. Số byte thấp nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép.

Các trường hợp kiểm tra thêm

Bạn có thể sử dụng chúng để kiểm tra chương trình của bạn.

Input:
a
Output:
a

Input:
co|mp|l|-ex|i|f|-y|
Example output:
cccoy
mplly
exify

Input:
ja-r|g-o|ni-|ze|d-|
Example output:
jronze
arondd
ggoidd

Input:
un|co|p-yr|i|gh-t-ab|-|le-||-
Example output:
unnnnnnn
coyriggl
ppyrihhe
ppyritte
ppyriabe

N và m đến từ đâu?
Seequ 17/03/2015

Có thể là tĩnh hoặc phải là một số hình thức đầu vào?
Seequ 17/03/2015

@Sieg nmđược chọn không xác định. Nó được đảm bảo rằng các giá trị phù hợp cho chúng tồn tại, nhưng công việc của chương trình là tìm ra chúng.
Zgarb

Bạn không thực sự định nghĩa chúng là gì.
seequ

un|co|p-|yr|i|gh--t-ab|-|le-||-là không thể có giá trị. Cái cuối cùng -có 2, trong khi chỉ có 1 phần tử trên ngăn xếp.
orlp

Câu trả lời:


6

K, 123 110 byte

Tôi đã sử dụng một cách tiếp cận tương tự với giải pháp của tông_box.

r:{y,x#,*|y};h:{t:(#x)|#y;r[t-#x;x],'r[t-#y]y};a:{(,x .|2#y),2_ y};*(){(a[{+h[+x;+y]}]x;a[h]x;(,,y),x)"-|"?y}/

Chương trình này là một chuỗi các định nghĩa của trình trợ giúp theo sau là hàm ngầm định lấy một chuỗi làm đối số đúng. Định dạng lại cho dễ đọc và gán chức năng cuối cùng làf :

r: {y,x#,*|y};                           / repeat last row x times
h: {t:(#x)|#y;r[t-#x;x],'r[t-#y;y]};     / append horizontal
v: {+h[+x;+y]};                          / append vertical
a: {(,x[y@1;y@0]),2_ y};                 / pop two values, concat

f: *(){:[y="-";a[v;x]; y="|";a[h;x]; (,,y),x]}/;

Sử dụng ví dụ:

  f "ja-r|g-o|ni-|ze|d-|"
("jronze"
 "aroidd"
 "ggoidd")

Đã thử nghiệm bằng Kona, nhưng nó cũng sẽ hoạt động trong oK nếu bạn thay thế: định nghĩa fbằng a $- k5 đã thay đổi cú pháp của "cond".

Một điểm quan trọng là nhận ra rằng thực hiện một phụ lục dọc là chuyển vị của phần phụ nằm ngang của chuyển vị của cả hai ma trận. (Xem định nghĩa v.) Tôi nghĩ vẫn còn chỗ để vắt kiệt một vài nhân vật ở đây và đó. Nếu bất cứ ai quan tâm đến một lời giải thích chi tiết hơn, tôi có thể cung cấp một.

biên tập:

Cập nhật chương trình ở đầu mục này. Phiên bản bị đánh cắp:

r: {y,x#,*|y};                           / repeat row x times
h: {t:(#x)|#y;r[t-#x;x],'r[t-#y;y]};     / append horizontal
v: {+h[+x;+y]};                          / append vertical
a: {(,x .|2#y),2_ y};                    / apply a concat
f: *(){(a[v]x;a[h]x;(,,y),x)"-|"?y}/;

Tối ưu hóa độ dài đáng chú ý bao gồm việc sử dụng "áp dụng dấu chấm" trong a, thay thế "cond" bằng lập chỉ mục danh sách f(ít hiệu quả hơn, nhưng ngắn hơn) và thay thế các điều khoản của biểu mẫu a[b;c]vào a[b]cnơi được phép bằng cách nhóm. Vì tôi không còn sử dụng "cond" hay bất kỳ nguyên thủy nào khác giữa k3 và k5, phiên bản này hiện hoạt động trong oK mà không cần sửa đổi.


Chúc mừng bạn đã thắng tiền thưởng!
Zgarb

Cảm ơn! Đó là một vấn đề thú vị mang lại kết quả khá tốt cho K. Thật thú vị khi thấy những nỗ lực trong J hoặc APL để so sánh.
JohnE

4

Prolog, 539 byte

:-lib(ic).
:-lib(util).
b(A,B,C):-between(A,B,C).
g(S):-string_list(S,L),p(L,[]).
w(h(L,R):_:_,I,J):-w(L,I,J);L=_:W:_,X is I-W,w(R,X,J).
w(v(U,D):_:_,I,J):-w(U,I,J);U=_:_:H,Y is J-H,w(D,I,Y).
w(f(C):W:H,I,J):-b(1,W,I),b(1,H,J),char_code(S,C),put_char(S).
p([],[S]):-term_variables(S,V),S=_:X:Y,labeling(V),!,b(1,Y,J),(b(1,X,I),w(S,I,J);nl),fail.
p([124|T],[Q,Z|R]):-!,Q=_:WA:H,Z=_:WB:H,W #= WA+WB,p(T,[h(Z,Q):W:H|R]).
p([45|T],[Q,Z|R]):-!,Q=_:W:HA,Z=_:W:HB,H #= HA+HB,p(T,[v(Z,Q):W:H|R]).
p([C|T],R):-!,[H,W] #:: 1..100,p(T,[f(C):W:H|R]).

Giải trình

Chúng tôi bắt đầu với vị ngữ g, lấy một chuỗi, chuyển đổi nó thành một danh sách các ký tự và gọip vị từ (phân tích cú pháp) với một ngăn xếp trống làm đối số thứ hai.

Vị ngữ pgọi chính nó đệ quy với một ngăn xếp được sửa đổi phù hợp (tìm kiếm [H|T]các mẫu phá hủy và các hàm tạo). Khi được gọi trong trường hợp cơ sở, trong đó danh sách đầu vào trống, pin phần tử duy nhất của ngăn xếp. Nếu ngăn xếp có ít hơn hoặc nhiều hơn một phần tử tại thời điểm này, điều đó có nghĩa là chúng ta có chuỗi đầu vào trống, chuỗi đầu vào xấu hoặc lỗi (với chuỗi emtpy, vị ngữ không thành công (Prolog nóiNo ), nhưng không có gì được in, không sao, vì chúng ta không nên in bất cứ thứ gì cho chuỗi trống).

Giải quyết

Ngăn xếp chứa một mô tả về các hình chữ nhật được xây dựng, ký hiệu S:W:H, trong đó Slà một biểu tượng tượng trưng của hình chữ nhật, Wchiều rộng và Hchiều cao của nó (lưu ý, A:Blà đường cú pháp cho :(A,B)bộ dữ liệu có tên là functor :; nó chỉ viết ngắn hơn so với bộ dữ liệu với ký hiệu tiền tố).

Với ABtiểu hình chữ nhật quy cách, Scó thể là:

  • h(A,B) : concat ngang của A và B
  • v(A,B) : concat dọc của A và B
  • f(C) : điền vào C, trong đó C là mã ký tự

Chiều rộng và chiều cao của lưới là các biến lập trình ràng buộc: trong quá trình ghép dọc (tương ứng ngang), chiều rộng (chiều cao tương ứng) của các hình chữ nhật được thao tác là thống nhất, trong khi chiều cao kết quả (chiều rộng tương ứng) bị giới hạn là tổng của chiều cao của mỗi subgrid (chiều rộng tương ứng).

Bước ghi nhãn ở cuối quy trình tạo ra các biến trong khi vẫn tuân thủ các ràng buộc, sử dụng các giá trị tối thiểu có thể (đây là một thuộc tính của thứ tự mà các giải pháp được thử).

Tôi có thể đã có được một câu trả lời ngắn hơn bằng cách sử dụng cùng một lý do được thực hiện trong các câu trả lời khác, không có ràng buộc, nhưng bây giờ đã quá muộn.

Cũng lưu ý rằng vì tên miền mặc định cho các biến được đặt thành 1..100, nên có giới hạn về kích thước lưới có thể có. Giới hạn trên có thể được thay đổi nếu cần thiết. Ý nghĩa về hiệu suất của việc này là có thể mất nhiều thời gian để xác định rằng một giải pháp cụ thể không thừa nhận giải pháp nào. Tôi nói " có thể " bởi vì các ràng buộc có khả năng cắt tỉa mạnh mẽ việc tìm kiếm theo cấp số nhân. Nếu bạn tìm thấy một chuỗi đầu vào khó / tốn kém để từ chối, vui lòng chia sẻ.

In ấn

Phần in rất thú vị vì có một loại thuật toán đúc tia trên cấu trúc: Tôi lặp qua từng ô của lưới kết quả, từ điểm này (1,1)đến điểm khác (W,H)và gọi wvị ngữ để in nội dung của lưới trong cây chính, tại vị trí này (tất nhiên, một dòng mới được in sau khi xử lý từng dòng).

Trong w, các vị trí có liên quan đến lưới hiện tại (lưới gốc xác định tọa độ tuyệt đối).

Khi in một h(A,B)cấu trúc tại điểm (X,Y), tôi in vô điều kiện ở cả hai nhánh:

  • trong lưới Atại điểm (X,Y), và
  • trong lưới Bvào thời điểm (H,Y), nơi HXtrừ đi chiều rộng của A.

Các nhánh lá của cây lưới f(C), cuối cùng hoặc in ký tự C, nếu vị trí tương đối nằm trong lưới hoặc không làm gì cả. Đây là cách tôi có thể in nội dung của lưới sang luồng đầu ra, từ trên xuống dưới, từ trái sang phải. Không có mảng thực tế được sản xuất.

Xét nghiệm

t("ja-r|g-o|ni-|ze|d-|").
t("un|co|p-yr|i|gh-t-ab|-|le-||-").
t("co|mp|l|-ex|i|f|-y|").
t("a").

tt :- t(X),nl,g(X).
tt.

Chạy thử:

[eclipse] tt.

jronze
aronze
ggoidd

uuuuuuun
coyriggl
coyrihhl
coyrittl
ppyriabe

cccoy
mmply
exify

a

Yes (0.00s cpu)

+1 No actual arrays are produced.đó là cách nó nên được thực hiện. Quá mức trong trường hợp này, vì ngữ pháp rất đơn giản và có các phím tắt.
edc65

@ edc65 Vâng, đó là quá mức cần thiết. Nhưng vì nó là codegolf, tôi đã cố gắng giảm thiểu kích thước và thao tác với các mảng sẽ quá dài dòng.
coredump

3

Python 2.7, 259

z=zip
def p(a,b):
 s,l=sorted([a,b],key=len)
 s+=([s[-1]]*(len(l)-len(s)))
 return z(*(z(*a)+z(*b)))
g=lambda s,t=[]:s and(s[0]=='-'and g(s[1:],t[:-2]+[z(*p(z(*t[-2]),z(*t[-1])))])or(s[0]=='|'and g(s[1:],t[:-2]+[p(t[-2],t[-1])])or g(s[1:],t+[[s[0]]])))or t[0]

glà một hàm lấy một đặc tả và đưa ra một mảng các ký tự 2D. Nếu bạn muốn có một phiên bản thân thiện hơn với người dùng, hãy thêm dòng này để làm cho nó có một đặc tả từ stdin và in ra lưới:

print'\n'.join(''.join(s)for s in g(raw_input()))

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

Input:
a
Output:
a
==========
Input:
co|mp|l|-ex|i|f|-y|
Output:
coooy
mplly
exify
==========
Input:
ja-r|g-o|ni-|ze|d-|
Output:
jronze
aroidd
ggoidd
==========
Input:
un|co|p-yr|i|gh-t-ab|-|le-||-
Output:
unnnnnnn
coyriggl
ppyrihhe
ppyritte
ppyriabe

Giải trình

Chiến lược này rất đơn giản: nếu một lưới Gcó giá trị cho một đặc điểm kỹ thuật S, thì việc lặp lại cột ngoài cùng bên phải Gcũng đưa ra một đặc tả hợp lệ cho S, và điều tương tự cũng đúng với việc lặp lại hàng dưới cùng (bằng chứng về điều này là do cảm ứng cấu trúc bật S). Do đó, khi chúng ta muốn ghép hai hình chữ nhật, chúng ta có thể chỉ cần nối thêm cột / hàng cuối cùng của cột nhỏ hơn cho đến khi chúng khớp với kích thước (đây là chức năng của p).


3

Haskell, 388 367 352 byte

data C=L{c::Char}|N{t::Int,w::Int,h::Int,l::C,r::C}
q=replicate
[]#[x]=x
(c:i)#(b:a:s)|c=='-'=i#(N 1(max(w a)$w b)(h a+h b)a b:s)|c=='|'=i#(N 2(w a+w b)(max(h a)$h b)a b:s)
(c:i)#s=i#(N 0 1 1(L c)(L c):s)
p i|t i==0=q(h i)$q(w i)$c$l i|t i==2=zipWith(++)(p(l i){h=h i})$p(r i){h=h i,w=w i-w(l i)}|1<2=p(l i){w=w i}++p(r i){w=w i,h=h i-h(l i)}
f=p.(#[])

Cách sử dụng: f "par-s||e-"->["pas","prs","eee"]

Chạy thử với in ấn đẹp:

> putStr $ unlines $ f "par-s||e-"
pas
prs
eee

> putStr $ unlines $ f "co|m|p|il|e|r|-"
comp
iler

> putStr $ unlines $ f "a"
a

> putStr $ unlines $ f "co|mp|l|-ex|i|f|-y|"
coooy
mplly
exify

> putStr $ unlines $ f "ja-r|g-o|ni-|ze|d-|"
jronze
aroidd
ggoidd

> putStr $ unlines $ f "un|co|p-yr|i|gh-t-ab|-|le-||-"
unnnnnnn
coyriggl
ppyrihhe
ppyritte
ppyriabe

Cách thức hoạt động: hàm #phân tích chuỗi đầu vào thành cấu trúc cây C, đó là một chiếc lá Lgiữ ký tự để in hoặc một nút N. Ncó thể là a) một phép nối cạnh nhau ( t==2), b) phép nối từ trên xuống ( t==1) hoặc c) một hình vuông chữ cái đơn ( t==0). Tất cả các nút có trường chiều rộng và chiều cao và con trái và phải. Sau khi phân tích cú pháp, pin nút gốc còn lại bằng cách điều chỉnh đệ quy kích thước (chiều rộng x chiều cao) của các nút con và nối chúng.

Chỉnh sửa: xuất ra dưới dạng danh sách các dòng thay vì in đẹp


1

JavaScript (ES6), 283 295

Chỉnh sửa Bây giờ giải pháp JS (được đánh gôn nhiều) này ít nhất ngắn hơn giải pháp Python tham chiếu (khá có thể chơi được).

Tương tự như tông_box, chỉ cần lặp lại cột ngoài cùng bên trái hoặc hàng trên cùng.

F=w=>(
s=[t=1,l='length'],
[for(c of w)(
  b=s[t],a=s[--t],
  c>'z'?
    s[t]=(G=(a,b,m=b[l]-a[l])=>m?m>0?G([a[0],...a],b):G(a,[b[0],...b]):a.map((r,i)=>r+b[i]))(a,b)
  :c<'a'?
    s[t]=a.map(r=>r[m=b[0][l]-r[l],0].repeat(m>0&&m)+r).concat(b.map(r=>r[0].repeat(m<0&&-m)+r))
  :s[t+=2]=[c]
)],
s[t].join('\n'))

Ungolfed Đây là giải pháp vô căn cứ đầu tiên của tôi.

F=sp=>{
  s=[]
  for(c of sp){
    a=s.pop(b=s.pop())
    if (c > 'z')
    {
      l = a.length
      m = b.length
      for(; l-m ;)
        l < m ? l = a.unshift(a[0]) : m = b.unshift(b[0])
      s.push(a.map((r,i) => r + b[i]))
    }
    else if (c < 'a')
    {
      l = a[0].length
      m = b[0].length
      s.push(
        a.map(r => r[0].repeat(l < m ? m-l : 0) + r)
        .concat(b.map( r => r[0].repeat( l > m ? l-m : 0) + r))
      )
    }
    else 
    {
      s.push(a,b,[c])
    }
  }
  return s.pop().join('\n')
}

Kiểm tra trong bảng điều khiển Firefox / FireBug

;['par-s||e-','co|m|p|il|e|r|-','co|mp|l|-ex|i|f|-y|',
 'ja-r|g-o|ni-|ze|d-|','un|co|p-yr|i|gh-t-ab|-|le-||-']
.forEach(w=>console.log(F(w)))

Đầu ra

pas
prs
eee

comp
iler

cccoy
mmply
exify

jronze
aronze
ggoidd

uuuuuuun
coyriggl
coyrihhl
coyrittl
ppyriabe

0

Python 3, 251 byte

Đây là câu trả lời tham khảo mà tôi đã hứa, đánh gôn thêm một chút.

T=lambda m:list(map(list,zip(*m)))
E=lambda a,b:a[:1]*(len(b)-len(a))+a
H=lambda a,b:[d+c for c,d in zip(E(a,b),E(b,a))]
s=[]
for k in input():s=k>"z"and[H(*s[:2])]+s[2:]or k<"a"and[T(H(*map(T,s[:2])))]+s[2:]or[[[k]]]+s
for r in s[0]:print("".join(r))

Đây là một chương trình đầy đủ lấy chuỗi từ STDIN và in ra STDOUT. Cách tiếp cận tương tự như của tông_box: đẩy một mảng 1x1 cho một ký tự và các hàng trùng lặp nếu cần để ghép.

$ echo "par-s||e-" | python3 gr.py
pas
prs
eee

Giải thích chi tiết

  • Tchuyển một danh sách nhất định của danh sách. Phần lớn công việc được thực hiện bằng cách zip(*m)hoán đổi các hàng thành các cột, phần còn lại chỉ là chuyển đổi kết quả thành một danh sách các danh sách, vì ziptrả về một bộ tạo các bộ dữ liệu.
  • E(a,b)trả về avới phần tử đầu tiên được lặp lại đủ số lần để khớp với độ dài của b. Lưu ý rằng nhân một danh sách với một số âm sẽ đưa ra danh sách trống, vì vậy nếu bngắn hơn a, điều này sẽ trả về a.
  • H(a,b)trả về phép nối ngang của ab, cái ngắn hơn được kéo dài bằng Enếu cần thiết.
  • s là chồng.
  • Trong forvòng lặp, chúng tôi lặp lại chuỗi đầu vào và thay thế sbằng một giá trị mới: nếu nó |(lớn hơn z), chúng tôi bật hai giá trị và đẩy chúng H, nếu nó -(thấp hơn a), chúng tôi bật hai giá trị, hoán vị, đưa vào H, hoán đổi một lần nữa và đẩy kết quả, và nếu không thì đẩy một mảng 1x1 bằng chữ cái.
  • Cuối cùng, chúng tôi in phần tử đầu tiên của s.
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.