Bir Özellikten Dikdörtgen Oluşturma


14

Giriş

Bu meydan okuma, 2B kalıp eşleştirme dilim olan Grime'dan ilham alıyor . Temel olarak, iki boyutlu karakter ızgaralarını tanımlayan bir "dilbilgisi" verilir ve işiniz dilbilgisine göre bir ızgara oluşturmaktır. Ek olarak, ızgara belirli bir zayıf anlamda mümkün olduğunca küçük olmalıdır.

Giriş

Girişiniz küçük ASCII karakterleri ve sembolleri içeren bir dizedir |ve -. Kolaylık olması açısından, girdi tekrarlanan küçük harfler içermez. Dize, bir dikdörtgen karakter ızgaraları sınıfı için bir belirtimdir ve aşağıdaki gibi bir yığın kullanılarak soldan sağa ayrıştırılır.

  • Küçük bir karakter verildiğinde c, yığına herhangi bir m×nkarakterin ızgarasını itin .cm, n ≥ 1
  • Bir boru verildiğinde |, iki ızgarayı Ave Byığıntan ( Büstte) pop ve sağa ABbirleştirerek elde edilen ızgarayı itin . Bu gerektirir ve eşit yüksekliğe sahiptir.BAAB
  • Bir kısa çizgi verildiğinde -, iki ızgarayı Ave Byığıntan ( Büstte idi) açın ve altını A/Bbirleştirerek elde edilen ızgarayı itin . Bu gerektirir ve eşit genişliğe sahiptir.BAAB

Bunun için bu garanti bazı seçimler mve n(her bir harfi için farklı olabilir) ayrıştırma işlemi sırasında yapılan, giriş özelliği doğru sonunda yığın üzerinde kalan bir dikdörtgen, tarif etmektedir.

Çıktı

Çıktınız, girdi tarafından belirtilen dikdörtgen bir karakter ızgarasıdır. Izgara, herhangi bir satırı veya sütunu kaldırmanın geçersiz kılması anlamında minimum olmalıdır. En uygun biçim hangisi olursa olsun, satırsonu ile ayrılmış bir dize (sondaki satırsonu olsun veya olmasın), 2B bir karakter dizisi veya bir dize dizisi döndürebilirsiniz.

Girişi tam olarak yukarıda açıklandığı gibi işlemeniz gerekmediğini unutmayın; önemli olan tek şey çıktınızın doğru olmasıdır.

Misal

Şartnameyi düşünün

par-s||e-

Önce bir itmek tercih 1×2ait dikdörtgen pve 1×1bir dikdörtgenler ave r(bu nedeni ilerleyen saatlerde açık olacaktır). Sonra ave rdikdörtgenleri patlatıyoruz ve dikey birleşimlerini itiyoruz

a
r

Ardından, bir 1×2dikdörtgeni itiyoruz s, pop ve yukarıdaki dikdörtgeni patlatıyoruz ve yatay birleştirmelerini

as
rs

Sonra o dikdörtgeni ve pdikdörtgeni patlatıp bir araya getirdik

pas
prs

Son olarak, bir 3×1dikdörtgeni itiyoruz e, pop ve yukarıdaki dikdörtgeni açıyoruz ve dikey birleştirme

pas
prs
eee

Bu, programın çıktısıdır veya olasılıklardan en az biridir. Yine de

ppas
ppas
pprs
eeee

aynı zamanda şartname tarafından üretilir, birçok satır ve sütun kaldırılabileceğinden geçerli bir çıktı değildir.

Daha ince bir örnek olarak,

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

Bu özellik dikdörtgeni oluşturur

comp
iler

ki bu geçerli bir çıktıdır. Ancak, aynı zamanda

commp
iiler

bu da geçerlidir, çünkü hiçbir satır veya sütun geçersiz kılmadan kaldırılamaz.

kurallar

Tam bir program veya işlev verebilirsiniz. En düşük bayt sayısı kazanır ve standart boşluklara izin verilmez.

Ekstra Test Durumları

Bunları programınızı test etmek için kullanabilirsiniz.

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 ve m nereden geliyor?
seequ

Statik olabilir mi veya bir çeşit girdi mi olmalı?
seequ

@Sieg nve mdeterminist olarak seçilir. Onlar için uygun değerlerin olması garanti edilir, ancak bunları bulmak programınızın görevidir.
15'te Zgarb

Aslında ne olduklarını tanımlamıyorsunuz.
seequ

un|co|p-|yr|i|gh--t-ab|-|le-||-geçerli olmak imkansız. Sonuncusu -2'lik bir düzene sahipken, yığın üzerinde sadece 1 öğe var.
orlp

Yanıtlar:


6

K, 123110 bayt

Ben karton_box'ın çözümüne benzer bir yaklaşım kullandım.

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

Bu program bir dizi yardımcı tanımdan sonra bir dizeyi doğru bir argüman olarak alan bir tacit fonksiyonudur. Okunabilirlik için yeniden biçimlendirme ve son işlevi şu şekilde atama 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]}/;

Örnek kullanın:

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

Kona kullanılarak test edilmiştir, ama aynı zamanda çalışacak OK değiştirmek eğer :tanımında fbir ile $- k5 "koşul" sözdizimini değiştirdi.

Önemli bir nokta, dikey bir ekleme yapmanın, her iki matrisin geçişinin yatay ekinin devri olduğunu kabul etmektir. (Tanıma bakın v.) Sanırım burada birkaç karakter sıkmak için yer var. Eğer kimse daha ayrıntılı bir açıklama ile ilgileniyorsa ben bir tane sağlayabilirim.

Düzenle:

Bu girişin üstündeki program güncellendi. Ungolfed sürümü:

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

Kayda değer uzunlukta en iyi duruma içinde "geçerli nokta" kullanılmasını içerir aliste indeksleme ile "kon" yerine, f(daha az verimli ama daha kısa) ve form değiştirme terimleri a[b;c]içine a[b]cgruplayarak izin verdiği yerlerde. Artık "cond" veya k3 ile k5 arasında farklı olan herhangi bir temel öğe kullanmadığımdan, bu sürüm artık değiştirilmeden OK'de çalışmaktadır.


Ödülünü kazandığın için tebrikler!
Zgarb

Teşekkürler! K'ye oldukça iyi gelen ilginç bir sorundu. Karşılaştırma için J veya APL'deki girişimleri görmek ilginç olurdu.
JohnE

4

Prolog, 539 bayt

:-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]).

açıklama

gBir dize alan yüklemi karakter dizileri listesi olarak dönüştürür ve pboş bir yığınla (ayrıştırma) yüklemini ikinci bir argüman olarak çağırırız .

Predicate p, kendisini uygun şekilde değiştirilmiş bir yığınla özyinelemeli olarak çağırır ( [H|T]yıkım ve yapıcı desenleri arayın ). Giriş listesinin boş olduğu temel durum çağrıldığında p, yığının benzersiz öğesini yazdırır. Yığın bu noktada daha az veya daha fazla öğeye sahipse, boş bir giriş dizesi, bozuk bir giriş dizesi veya bir hata (boş bir dizeyle, yüklem başarısız olur (Prolog diyor No)), ancak hiçbir şey yazdırılmadığı, boş dizeler için hiçbir şey yazdırmamamız gerektiğinden, sorun yok).

Çözme

Yığın inşa dikdörtgen bir açıklama, gösterilen içerir S:W:H, Sdikdörtgen sembolik bir gösterimidir, Wgenişliği ve Hyüksekliği (not, A:Bsözdizimsel şeker :(A,B)adlı bir functor ile başlığın :, bir başlığın olan daha yazma sadece kısa ön ek gösterimi ile).

AVe Balt dikdörtgen özellikleri ile şunlardan biri Solabilir:

  • h(A,B) : yatay A ve B concat
  • v(A,B) : A ve B'nin dikey kesişimi
  • f(C) : C ile doldurun, burada C bir karakter kodudur

Izgaraların genişlikleri ve yükseklikleri kısıt programlama değişkenleridir: dikey (yatay olarak yatay) birleştirme sırasında, manipüle edilmiş dikdörtgenlerin genişliği (ayrı ayrı yükseklik) birleştirilirken, elde edilen yükseklik (genişlik genişliği) toplamı olarak sınırlandırılır her alt ızgaranın yüksekliği (sırasıyla genişlik).

İşlemin sonundaki etiketleme adımı, mümkün olan en düşük değerleri kullanarak, kısıtlamalara saygı gösterirken değişkenleri somutlaştırır (bu, çözümlerin denendiği sıranın bir özelliğidir).

Kısıtlama olmaksızın, diğer cevaplarda yapılan aynı akıl yürütmeyi kullanarak daha kısa bir cevap almış olabilirim, ama şimdi çok geç.

Ayrıca, değişkenler için varsayılan etki alanı olarak ayarlandığından 1..100, olası ızgara boyutlarında bir sınırlama olduğunu unutmayın. Gerekirse üst sınır değiştirilebilir. Bu performans sonuçları bu vardır olabilir , belirli bir çözüm hiçbir çözüm itiraf belirlemek için çok fazla zaman alır. " Yapabilirim " dedim çünkü kısıtlamaların üstel aramayı büyük ölçüde budaması muhtemeldir. Reddedilmesi zor / maliyetli bir giriş dizesi bulursanız lütfen paylaşın.

Baskı

Bir tür olduğu için baskı parçası ilginçtir ışın-döküm yapı üzerinde algoritması: Ben yinelerler noktadan kaynaklanan tablo her hücresinde, üzerinde (1,1)noktaya (W,H)ve çağrı wyüklemi ana ağacında ızgara içeriğini yazdırmak için, en bu konum (elbette, her satır işlendikten sonra yeni satır yazdırılır).

Konumunda w, konumlar geçerli ızgaraya göredir (kök ızgara mutlak koordinatları tanımlar).

Bir h(A,B)yapı noktasını (X,Y)yazdırırken, her iki dalda da koşulsuz olarak yazdırıyorum:

  • Anoktada ızgarada (X,Y)ve
  • Bnoktasında ızgara , eksi genişliği (H,Y)nerede .HXA

Izgara ağacının yaprak dalları , göreli konum ızgaranın içindeyse f(C)karakteri Cbasar veya hiçbir şey yapmaz. Izgara içeriğini çıktı akışına, yukarıdan aşağıya, soldan sağa doğru bu şekilde yazdırabilirim. Gerçek diziler üretilmez.

Testler

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.

Koşu testi:

[eclipse] tt.

jronze
aronze
ggoidd

uuuuuuun
coyriggl
coyrihhl
coyrittl
ppyriabe

cccoy
mmply
exify

a

Yes (0.00s cpu)

+1 No actual arrays are produced.bu şekilde yapılmalı. Dilbilgisi çok basit olduğundan ve kısayollar olduğundan, bu durumda aşırı doldurun.
edc65

@ edc65 Evet, aşırı dolu. Ancak codegolf olduğu için boyutu en aza indirmeye çalıştım ve dizileri manipüle etmek çok ayrıntılı olurdu.
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]

gbir spesifikasyon alan ve 2B karakter dizisi veren bir fonksiyondur. Daha kullanıcı dostu bir sürüm istiyorsanız, stdin'den bir özellik alması ve ızgarayı yazdırması için bu satırı ekleyin:

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

Test Durumları

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

açıklama

Strateji basittir: bir ızgara Gbir spesifikasyon için geçerliyse S, en sağdaki sütunun tekrarlanması Gda geçerli bir spesifikasyon verir Sve aynı alt satırın tekrarlanmasıyla da geçerlidir (bunun kanıtı yapısal indüksiyon açıktır S). Bu nedenle, iki dikdörtgeni birleştirmek istediğimizde, daha küçük olanın son sütununu / satırını boyut olarak eşleşene kadar ekleyebiliriz (p işlevi budur).


3

Haskell'in 388 367 352 bayt

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

Kullanım: f "par-s||e-"->["pas","prs","eee"]

Güzel baskı ile test çalışması:

> 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

Nasıl çalışır: işlev #, giriş dizesini , yazdırılacak karakteri tutan Cbir yaprak Lveya bir düğüm olan ağaç yapısına ayrıştırır N. Na) yan yana birleştirme ( t==2), b) bir üst-alt birleştirme ( t==1) veya c) tek bir harf karesi ( t==0) olabilir. Tüm düğümlerin bir genişlik ve yükseklik alanı ve sol ve sağ alt öğesi vardır. Ayrıştırma işleminden sonra p, kalan kök düğümü alt düğümlerinin boyutunu (genişlik x yükseklik) tekrar tekrar ayarlayıp birleştirerek yazdırır.

Düzenle: güzel yazdırma yerine satır listesi olarak çıktı


1

JavaScript (ES6), 283 295

Düzenle Bu (yoğun golf) JS çözümü referans (oldukça golf edilebilir) Python çözümünden en az daha kısa.

Karton_kutusuna benzer şekilde, en soldaki sütunu veya en üstteki satırı tekrarlar.

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 Bu benim ilk, çözülmemiş çözümüm.

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

Firefox / FireBug konsolunda test et

;['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)))

Çıktı

pas
prs
eee

comp
iler

cccoy
mmply
exify

jronze
aronze
ggoidd

uuuuuuun
coyriggl
coyrihhl
coyrittl
ppyriabe

0

Python 3, 251 bayt

İşte söz verdiğim referans cevap, biraz daha golf.

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

Bu, dizeyi STDIN'den alıp STDOUT'a yazdıran tam bir programdır. Yaklaşım karton_kutu ile aynıdır: bir karakter için 1x1 dizisini itin ve birleştirme için gerekirse satırları çoğaltın.

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

Detaylı açıklama

  • Tverilen bir liste listesini aktarır. İşin çoğunluğu, zip(*m)satırları sütunlara takas ederek yapılır , geri kalanı sonucu bir liste listesine dönüştürür, çünkü ziptuples jeneratörü döndürür.
  • E(a,b)auzunluğunun eşleşmesi için yeterince kez tekrarlanan ilk öğesiyle döner b. Bir listeyi negatif bir sayıyla çarpmanın boş listeyi verdiğini unutmayın, bu yüzden bdaha kısasa abu geri döner a.
  • H(a,b)yatay birleşimini döndürür ave bgerekirse daha kısa olanı uzatılır E.
  • s yığınıdır.
  • Olarak fordöngü, biz yineleme giriş dize üzerinde ve yerine syeni bir değer ile: Örneğin, |(daha büyük z), iki değer pop ve bunların itme H, eğer en -(daha düşük a), biz iki değer, devrik, besleme pop H, tekrar transpoze edin ve sonucu itin, aksi takdirde harfle 1x1 dizisi itin.
  • Son olarak, ilk elemanını yazdırıyoruz s.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.