Hasilkan Rectangle dari Spesifikasi


14

pengantar

Tantangan ini terinspirasi oleh Grime , bahasa pencocokan pola 2D saya. Pada dasarnya, Anda diberi "tata bahasa" yang menggambarkan kisi-kisi karakter dua dimensi, dan tugas Anda adalah membuat kisi sesuai dengan tata bahasa. Selain itu, grid harus sekecil mungkin dalam arti lemah tertentu.

Memasukkan

Input Anda adalah string yang berisi karakter ASCII huruf kecil dan simbol |dan -. Untuk kesederhanaan, input tidak mengandung karakter huruf kecil berulang. String adalah spesifikasi untuk kelas kotak karakter persegi panjang, dan diurai dari kiri ke kanan menggunakan tumpukan sebagai berikut.

  • Diberikan karakter huruf kecil c, dorong ke tumpukan m×nkisi karakter c, untuk apa saja m, n ≥ 1.
  • Diberikan pipa |, pop dua grid Adan Bdari tumpukan ( Bada di atas), dan dorong grid ABdiperoleh dengan menyatukan Bke kanan A. Ini mengharuskan ituA danB memiliki ketinggian yang sama.
  • Diberi tanda hubung -, letakan dua kisi Adan Bdari tumpukan ( Bada di atas), dan dorong kisi yang A/Bdiperoleh dengan menyatukan Bke bagian bawah A. Ini membutuhkan itu Adan Bmemiliki lebar yang sama.

Dijamin bahwa untuk beberapa pilihan mdan ndibuat selama proses parsing (yang mungkin berbeda untuk setiap huruf), spesifikasi input dengan benar menggambarkan beberapa persegi panjang, yang tersisa di tumpukan di bagian akhir.

Keluaran

Output Anda adalah kotak karakter persegi panjang yang ditentukan oleh input. Kisi harus minimal dalam arti bahwa menghapus baris atau kolom apa pun akan membuatnya tidak valid. Anda dapat mengembalikan string yang dipisahkan baris baru (dengan atau tanpa baris baru), array karakter 2D, atau array string, yang mana adalah format yang paling nyaman.

Perhatikan bahwa Anda tidak perlu memproses input persis seperti yang dijelaskan di atas; satu-satunya hal yang penting adalah bahwa output Anda sudah benar.

Contoh

Pertimbangkan spesifikasinya

par-s||e-

Pertama, kami memilih untuk mendorong 1×2persegi panjang p, dan 1×1persegi panjang adan r(alasan untuk ini akan jelas nanti). Kemudian, kita meletupkan adan rpersegi panjang, dan mendorong concatenation vertikal mereka

a
r

Selanjutnya, kami mendorong 1×2persegi panjang s, pop itu dan persegi panjang di atas, dan mendorong concatenation horizontal mereka

as
rs

Lalu kita letakan kotak itu dan pkotak itu, dan dorong pasangan mereka

pas
prs

Akhirnya, kita dorong 3×1kotak e, pop, dan kotak di atas, dan dorong concatenation vertikal

pas
prs
eee

Ini adalah output dari program, atau paling tidak salah satu kemungkinan. Perhatikan itu meskipun

ppas
ppas
pprs
eeee

juga dihasilkan oleh spesifikasi, ini bukan output yang valid, karena banyak baris dan kolom dapat dihapus.

Sebagai contoh yang lebih halus, pertimbangkan

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

Spesifikasi ini menghasilkan persegi panjang

comp
iler

yang merupakan output yang valid. Namun, itu juga menghasilkan

commp
iiler

yang juga valid, karena tidak ada baris atau kolom tunggal yang dapat dihapus tanpa membatalkannya.

Aturan

Anda dapat memberikan program atau fungsi lengkap. Hitungan byte terendah menang, dan celah standar tidak diizinkan.

Kasus Uji Ekstra

Anda dapat menggunakan ini untuk menguji program Anda.

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

Dari mana n dan m berasal?
seequ

Bisa statis atau harus berupa input?
seequ

@Sieg ndan mdipilih secara non-deterministik. Dijamin bahwa nilai-nilai yang cocok untuk mereka ada, tetapi itu adalah tugas program Anda untuk menemukannya.
Zgarb

Anda sebenarnya tidak mendefinisikan apa itu.
seequ

un|co|p-|yr|i|gh--t-ab|-|le-||-tidak mungkin valid. Yang terakhir -memiliki arity 2, sementara hanya ada 1 elemen di stack.
orlp

Jawaban:


6

K, 123 110 byte

Saya menggunakan pendekatan yang mirip dengan solusi cardboard_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}/

Program ini adalah serangkaian definisi pembantu diikuti oleh fungsi diam-diam yang mengambil string sebagai argumen yang benar. Memformat ulang untuk keterbacaan dan menetapkan fungsi akhir sebagai 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]}/;

Gunakan contoh:

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

Diuji menggunakan Kona, tetapi itu juga akan berfungsi dalam oK jika Anda mengganti :definisi fdengan a $- k5 mengubah sintaks "cond".

Titik kunci adalah mengakui bahwa melakukan penambahan vertikal adalah transpose dari penambahan horizontal dari transpose dari kedua matriks. (Lihat definisi v.) Saya pikir masih ada ruang untuk memeras beberapa karakter di sana-sini. Kalau ada yang tertarik dengan penjelasan yang lebih rinci saya bisa memberikannya.

edit:

Memperbarui program di bagian atas entri ini. Versi tidak disatukan:

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}/;

Optimalisasi panjang yang penting termasuk penggunaan "dot apply" a, mengganti "cond" dengan daftar indeks di f(kurang efisien, tetapi lebih pendek) dan mengganti syarat formulir a[b;c]ke a[b]ctempat diizinkan oleh pengelompokan. Karena saya tidak lagi menggunakan "cond" atau primitif apa pun yang berbeda antara k3 dan k5 versi ini sekarang berfungsi di oK tanpa modifikasi.


Selamat telah memenangkan hadiah!
Zgarb

Terima kasih! Itu adalah masalah yang menarik yang menghasilkan cukup baik untuk K. Akan menarik untuk melihat upaya di J atau APL untuk perbandingan.
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]).

Penjelasan

Kita mulai dengan predikat g, yang mengambil string, mengubahnya sebagai daftar karakter dan memanggil ppredikat (parse) dengan tumpukan kosong sebagai argumen kedua.

Predikat ppanggilan itu sendiri secara rekursif dengan tumpukan yang dimodifikasi secara tepat (mencari [H|T]pola destruktor dan konstruktor). Ketika dipanggil pada kasus dasar, di mana daftar input kosong, pmencetak elemen unik dari tumpukan. Jika tumpukan memiliki kurang atau lebih dari satu elemen pada titik ini, itu berarti bahwa kita memiliki string input kosong, string input buruk atau bug (dengan string emtpy, predikat gagal) (kata PrologNo ), tetapi tidak ada yang dicetak, yang ok, karena kita seharusnya tidak mencetak apa pun untuk string kosong).

Memecahkan

Tumpukan berisi deskripsi persegi panjang yang dibangun, dilambangkan S:W:H, di mana Sadalah representasi simbolis dari persegi panjang, Wlebar dan Htingginya (catatan, A:Badalah gula sintaksis untuk :(A,B)tupel dengan functor bernama :; hanya lebih pendek untuk menulis daripada memiliki tupel dengan notasi awalan).

Dengan Adan Bspesifikasi sub-persegi panjang, Sdapat berupa:

  • h(A,B) : concat horizontal A dan B
  • v(A,B) : concat vertikal A dan B
  • f(C) : isi dengan C, di mana C adalah kode karakter

Lebar dan tinggi kisi-kisi adalah variabel pemrograman kendala: selama penggabungan vertikal (resp. Horizontal), lebar (resp. Tinggi) dari persegi yang dimanipulasi disatukan, sedangkan tinggi yang dihasilkan (lebar resp) dibatasi menjadi jumlah dari tinggi setiap subgrid (lebar resp.).

Langkah pelabelan di akhir proses akan memunculkan variabel sambil menghormati batasan, menggunakan nilai minimal yang mungkin (ini adalah properti dari urutan di mana solusi dicoba).

Saya mungkin telah memperoleh jawaban yang lebih pendek menggunakan penalaran yang sama yang dilakukan dalam jawaban lain, tanpa kendala, tetapi ini sudah terlambat sekarang.

Perhatikan juga bahwa karena domain default untuk variabel diatur ke 1..100, ada batasan atas ukuran grid yang mungkin. Batas atas dapat diubah jika perlu. Implikasi kinerja dari hal ini adalah bahwa mungkin perlu banyak waktu untuk menentukan bahwa solusi tertentu tidak mengakui solusi. Saya berkata " bisa " karena kendala kemungkinan akan secara drastis memangkas pencarian eksponensial. Jika Anda menemukan string input yang sulit / mahal untuk ditolak, silakan bagikan.

Pencetakan

Bagian pencetakannya menarik karena ada semacam ray-casting algoritma atas struktur: Saya beralih ke setiap sel dari grid yang dihasilkan, dari titik (1,1)ke titik (W,H)dan memanggil wpredikat untuk mencetak konten grid di pohon utama, di lokasi ini (tentu saja, baris baru dicetak setelah memproses setiap baris).

Dalam w, posisi relatif terhadap kisi saat ini (kisi akar mendefinisikan koordinat absolut).

Saat mencetak h(A,B)struktur pada titik(X,Y) , saya mencetak tanpa syarat di kedua cabang:

  • dalam kotak A pada titik (X,Y), dan
  • dalam grid Bpada titik (H,Y), di mana Hadalah Xminus lebarA .

Cabang-cabang daun dari grid-tree, f(C)akhirnya mencetak karakter C, jika lokasi relatif berada di dalam grid, atau tidak melakukan apa-apa. Ini adalah bagaimana saya dapat mencetak konten grid ke aliran output, dari atas ke bawah, dari kiri ke kanan. Tidak ada array aktual yang diproduksi.

Tes

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.

Tes lari:

[eclipse] tt.

jronze
aronze
ggoidd

uuuuuuun
coyriggl
coyrihhl
coyrittl
ppyriabe

cccoy
mmply
exify

a

Yes (0.00s cpu)

+1 No actual arrays are produced.itulah yang harus dilakukan. Berlebihan dalam hal ini, karena tata bahasanya sangat sederhana dan ada jalan pintas.
edc65

@ edc65 Ya, ini berlebihan. Tapi karena itu codegolf, saya mencoba meminimalkan ukuran, dan memanipulasi array akan terlalu bertele-tele.
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]

gadalah fungsi yang mengambil spesifikasi dan memberikan array karakter 2D. Jika Anda menginginkan versi yang lebih ramah pengguna, tambahkan baris ini untuk membuatnya mengambil spesifikasi dari stdin dan cetak kisi:

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

Uji Kasus

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

Penjelasan

Strateginya sederhana: jika kisi Gvalid untuk spesifikasi S, maka pengulangan kolom paling kanan Gjuga memberikan spesifikasi yang valid untukS , dan hal yang sama berlaku dengan pengulangan baris bawah (buktinya adalah dengan induksi struktural aktif S). Oleh karena itu, ketika kita ingin menggabungkan dua persegi panjang, kita cukup menambahkan kolom / baris terakhir dari yang lebih kecil sampai mereka cocok dalam ukuran (ini adalah apa fungsi p tidak).


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.(#[])

Pemakaian: f "par-s||e-" ->["pas","prs","eee"]

Uji coba dengan pencetakan cantik:

> 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

Cara kerjanya: fungsi #mem-parsing string input ke dalam struktur pohon Cyang bisa berupa daun yang Lmenahan karakter untuk dicetak atau simpul N. Ndapat berupa a) gabungan berdampingan ( t==2), b) gabungan atas-bawah (t==1 ) atau c) satu huruf persegi ( t==0). Semua node memiliki bidang lebar dan tinggi dan anak kiri dan kanan. Setelah parsing, pcetak simpul akar yang tersisa dengan secara rekursif menyesuaikan ukuran (lebar x tinggi) dari simpul anak itu dan bergabung dengan mereka.

Sunting: keluaran sebagai daftar baris alih-alih pencetakan yang cantik


1

JavaScript (ES6), 283 295

Edit Sekarang, solusi JS (sangat golf) ini setidaknya lebih pendek daripada referensi (cukup golf) solusi Python.

Mirip dengan cardboard_box, cukup ulangi kolom paling kiri atau baris paling atas.

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 Ini adalah solusi pertama saya, ungolfed.

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')
}

Uji di Firefox / konsol 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)))

Keluaran

pas
prs
eee

comp
iler

cccoy
mmply
exify

jronze
aronze
ggoidd

uuuuuuun
coyriggl
coyrihhl
coyrittl
ppyriabe

0

Python 3, 251 byte

Inilah jawaban referensi yang saya janjikan, bermain golf sedikit lebih jauh.

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))

Ini adalah program lengkap yang mengambil string dari STDIN dan mencetak ke STDOUT. Pendekatannya sama dengan cardboard_box: tekan array 1x1 untuk sebuah karakter, dan duplikat baris jika diperlukan untuk penggabungan.

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

Penjelasan detail

  • Ttranspos daftar daftar yang diberikan. Sebagian besar pekerjaan dilakukan dengan zip(*m)menukar baris ke kolom, sisanya hanya mengubah hasilnya menjadi daftar daftar, karenazip mengembalikan generator tupel.
  • E(a,b)kembali adengan elemen pertama yang diulang cukup kali untuk mencocokkan panjang b. Perhatikan bahwa mengalikan daftar dengan angka negatif memberikan daftar kosong, jadi jika blebih pendek dari a, ini kembali a.
  • H(a,b)mengembalikan rangkaian horizontal adan b, yang lebih pendek diperpanjang olehE jika perlu.
  • s adalah tumpukan.
  • Dalam forloop, kami beralih pada string input, dan ganti sdengan nilai baru: jika itu |(lebih besar dari z), kami memunculkan dua nilai dan mendorongnya H, jika itu -(lebih rendah dari a), kami memunculkan dua nilai, transpos, diumpankan ke H, transpos lagi dan tekan hasilnya, dan sebaliknya dorong array 1x1 dengan huruf.
  • Akhirnya, kami mencetak elemen pertama s.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.