Bir Dize Parentezize Etme


25

Girdi olarak düzgün şekilde parantez içine alınmış bir dize verildiğinde, iç içe parantezler çıkarılmış olarak eşleşen parantezler içindeki (veya tüm parantezlerin dışındaki) tüm boş olmayan alt dizgelerin bir listesini çıkarın. Her alt dize, tamamen aynı eşleşen parantez içindeki karakterlerin sırası olmalıdır. Alt dizgiler derinlik sırasına göre sıralanmalı ve aynı derinliğe sahip alt dizgiler dizgede meydana geldikleri sıraya göre listelenmelidir. Girişin her zaman doğru parantez içinde olduğunu varsayalım.

Girişin yalnızca küçük harf ASCII harfleri ve parantez içerdiğini varsayabilirsiniz.

Cevabınız, bir dizge verildiğinde bir dizge listesi döndüren bir işlev olmalıdır.

Örnekler:

                   'a(b)c(d)e' -> ['ace', 'b', 'd']
                   'a(b(c)d)e' -> ['ae', 'bd', 'c']
                  'a((((b))))' -> ['a', 'b']
                        'a()b' -> ['ab']
                            '' -> []
                           'a' -> ['a']
          '(((a(b)c(d)e)f)g)h' -> ['h', 'g', 'f', 'ace', 'b', 'd']
'ab(c(((d)ef()g)h()(i)j)kl)()' -> ['ab', 'ckl', 'hj', 'efg', 'i', 'd']

En az bayt kazanır.


Son test durumunda doğru sırada mı 'i've 'd'doğru sırada mı?
PurkkaKoodari 16:15

@ Pietu1998 i, olduğundan daha az iç içe d.
feersum

@ feersum Ah, doğru.
PurkkaKoodari 16:15

1
Diğer standart gönderim türlerine, özellikle de tam programlara izin verir misiniz? Her dilde bir işlev kavramı yoktur. Varsayılan görüş birliği için bkz. Meta.codegolf.stackexchange.com/a/2422/8478 ve meta.codegolf.stackexchange.com/questions/2447/… .
Martin Ender,

2
@ redstonerodent Kullanmaya meyilli olan ifade "Bir program veya fonksiyon yazabilir, STDIN (veya en yakın alternatif) ile giriş alarak, komut satırı argümanı veya fonksiyon argümanı yazabilir ve sonucu STDOUT (veya en yakın alternatif), fonksiyon dönüş değeri ile çıkartabilirsiniz. veya function (out) parametresi. " ve sizin durumunuzda "Çıktı, herhangi bir uygun, açık, düz liste biçiminde olabilir."
Martin Ender,

Yanıtlar:


11

JavaScript ES6, 91 93 104 133 148

Edit2 2 bayt thx kullanıcı81655 kaydetti

Daha fazla dize ve daha az dizi kullanarak düzenleme

Aşağıdaki pasajı EcmaScript 6 uyumlu bir tarayıcıda çalıştırma testi

f=s=>[...s].map(c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),o=[],l=0)&&(o+'').match(/\w+/g)||[]

// Less golfed

u=s=>{
  o=[]; l=0;
  [...s].map(c=>{
    if (c>'(') // letters or close bracket
      o[l]=(o[l]||'')+c, // add letter or close bracket to current level string
      l-=c<'a' // if close bracket, decrement level
    else
      ++l // open bracket, increment level
  })
  o = o+'' // collapse array to comma separated string
  return o.match(/\w+/g)||[] // fetch non empty strings into an array
}

// TEST
console.log=x=>O.innerHTML+=x+'\n'

;[ 'a(b)c(d)e'                    // ['ace', 'b', 'd']
 , 'a(b(c)d)e'                    // ['ae', 'bd', 'c']
 , 'a((((b))))'                   // ['a', 'b']
 , 'a()b'                         // ['ab']
 , ''                             // []
 , 'a'                            // ['a']
 , '(((a(b)c(d)e)f)g)h'           // ['h', 'g', 'f', 'ace', 'b', 'd']
 , 'ab(c(((d)ef()g)h()(i)j)kl)()' // ['ab', 'ckl', 'hj', 'efg', 'i', 'd']
].forEach(t=>console.log(t +" -> " + f(t)))
<pre id=O></pre>


İle 2 bayt kaydedin c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),.
user81655 16:15

@ user81655 güzel, teşekkürler
edc65 16:15

8

Julia, 117 86 83 bayt

v->(while v!=(v=replace(v,r"(\(((?>\w|(?1))*)\))(.*)",s"\g<3> \g<2>"))end;split(v))

Bu bir regex çözümü.

Ungolfed:

function f(v)
  w=""
  while v!=w
    w=v
    v=replace(v,r"(\(((?>\w|(?1))*)\))(.*)",s"\g<3> \g<2>"))
  end
  split(v)
end

r"(\(((?>\w|(?1))*)\))(.*)"yinelemeli (olup (?1)ihtiva eden üçüncü grup (parantez kendileri hariç) parantez içinde her şeyi ihtiva eden ikinci grup birinci dış dengeli parantez (dengelenmemiş / parantez ters içermeyen) eşleşir Recurses grup 1), normal ifade parantezden sonraki her şey (dizenin sonuna kadar).

replace(v,r"...",s"\g<3> \g<2>")daha sonra ikinci grubu dizgenin sonuna götürür (boşluktan sonra, sınırlayıcı olarak kullanılır), ilgili parantezler kaldırılır. V == w değerine kadar yineleyerek, yerine parantez kalmayıncaya kadar değiştirmenin tekrarlanması sağlanır. Eşleşmeler sonuna taşındığından ve sonraki eşleşme ilk parantez için geçerli olduğundan, sonuç derinlik sırasına göre ayrılmış dize olur.

Sonra splitdizenin tüm boşluklu olmayan bileşenlerini bir dizi dizisi şeklinde (boşluksuz) döndürür.

Not w=""ungolfed kodunda kullanıldığından emin olmak için bu süre döngü çalışır en az bir kez ve golfed formda gerekli değildir (giriş dizesi tabii boşsa hariç).

Martin Büttner'e 3 bayt kaydetme konusunda yardım için teşekkür ederiz.


Güzel, aynı çözüme bağımsız olarak Retina'da geldim. Orada 44 bayt var, ancak tam programlı çözümlere izin verilmez. : /
Martin Ender

Sen kullanarak üç bayt kaydedebilirsiniz \wyerine [^()].
Martin Ender

@ MartinBüttner - teşekkürler. Aslında bunu düşünmüştüm, ama bir şeyi gözden kaçırdığım ve bazı durumlarda başarısız olacağı konusunda endişelendim. Eğer iyi diyorsan, sorun değil.
Glen O

6

Python, 147 bayt

def f(s):
 d=0;r=[['']for c in s]
 for c in s:
  if c=='(':d+=1;r[d]+=['']
  elif c==')':d-=1
  else:r[d][-1]+=c
 return[i for i in sum(r,[])if i]

Birim testleri:

assert f('a(b)c(d)e') == ['ace', 'b', 'd']
assert f('a(b(c)d)e') == ['ae', 'bd', 'c']
assert f('a((((b))))') == ['a', 'b']
assert f('a()b') == ['ab']
assert f('') == []
assert f('a') == ['a']
assert f('(((a(b)c(d)e)f)g)h') == ['h', 'g', 'f', 'ace', 'b', 'd']
assert f('ab(c(((d)ef()g)h()(i)j)kl)()') == ['ab', 'ckl', 'hj', 'efg', 'i', 'd']

Bu bulmacayı sevdim; çok tatlı!


4

Pyth, 32 bayt

fTscR)uX0.<GJ-FqLH`()@[Hdk)Jzmkz

Test odası

Gevşek bir şekilde @ Quuxplusone'un yaklaşımına dayanıyordu. Her derinlikte karakterlerin boşlukla ayrılmış listelerini oluşturur, sonra bunları böler ve boş grupları filtreler. Çalışma listesi mevcut derinlik listesini her zaman önünde tutmak için döndürülür.


4

Retina , 44 41 bayt

+`\(((\w|(\()|(?<-3>.))*).(.*)
$4 $1
S_` 

-sBayrakla koş . Son satırın sonundaki boşluğa dikkat edin.

Glen O'dan bağımsız olarak bu çözümle karşılaştım, ancak aynı olduğu ortaya çıktı. Fikir ilk parantez çiftini eşleştirmek, çıkartmak ve içeriğini çıktının sonuna (tekrar tekrar) eklemek. .NET'in regex'te özyinelememesi nedeniyle, dört bayt uzunluğundaki dengeleme gruplarını kullanmak zorunda kaldım.

İlk regex'i anlamadıysanız, sizi dengeleme grupları hakkındaki SO cevabına yönlendireyim . Girişin parantez içinde olması garanti edildiğinden ), .bunun yerine eşleştirerek iki bayt kaydedebiliriz \). Sonra dizenin geri kalanıyla eşleşiriz (.*). $4 $1ilk önce söz konusu dizginin geri kalan kısmını yazar (hem parantezleri hem de içeriklerini ihmal ederek) ve sonra bir boşluktan sonra parantezlerin içeriğini yazar. +`Dizesi (bütün parantez kaldırıldıktan sonra yalnızca olur) değişen durana kadar bu adımı tekrar etmek Retina söyler.

Boş parantezler iki ardışık boşlukla sonuçlanır, bu nedenle sonunda tüm dizgiyi boşluklara böleriz ( S`bölme modunu etkinleştirir ve regex tek bir boşluktur). _Biz çıktıda boş sonuçlarını içermez böylece seçeneği bölünmenin omit boş kısımlarına Retina söyler.


3

Common Lisp, 160

(lambda(x)(labels((g(l)(cons(#1=format()"~(~{~A~}~)"(#2=remove-if'listp l))(mapcan #'g(#2#'atom l)))))(remove""(g(read-from-string(#1#()"(~A)"x))):test'equal))))

Vaka dönüşümü gerekli değilse bu dört bayt daha az olabilir. Fikir, giriş dizesinin her bir tarafına sol ve sağ parantez eklemek, onu bir liste olarak ele almak, listenin en üst düzey elemanlarını bir dizeye yazmak ve ardından alt listeleri aynı şekilde işlemektir.


2

Haskell, 114 112 111 bayt

')'%(h:i:t)=("":i):t++[h]
'('%l=last l:init l
c%((h:i):t)=((c:h):i):t
g x=[a|a<-id=<<foldr(%)(x>>[[""]])x,a>""]

Kullanım örneği: g "ab(c(((d)ef()g)h()(i)j)kl)()"-> ["ab","ckl","hj","efg","i","d"].

Giriş dizgisinde geriye doğru gidiyorum. Ara veri yapısı, karakter dizilerinin bir listesidir. Dış liste seviye başınadır ve iç liste bir seviye içindeki grup başınadır, örneğin [["ab"],["ckl"],["hj"],["efg","i"],["d"]](not: gerçek listede aralarında çok fazla boş dizeler vardır). Her şey, girişin uzunluğuna eşit sayıda boş dizeyle başlar - fazlasıyla yeterli, ancak boş listeler yine de filtrelenir. Dış listeler ya döner (/ / )veya karakteri ön elemana ekler. )Ayrıca yeni bir grup başlar.

Düzenleme: @Zgarb kaydetmek için bir bayt buldu.


1

Sed, 90 bayt

:
s/^(\w*)\((.*)\n?(.*)/\1\n\3_\2/M
s/(\n\w*_)(\w*)\)(.*)/\3\1\2/M
t
s/[_\n]+/,/g
s/,$//

-r+1 bayt tarafından hesaplanan genişletilmiş regex'leri ( bayrak) kullanır . Ayrıca, bu bir GNU Uzantısı kullanır (komuttaki Mbayrak s).

Örnek Kullanım:

$ echo 'ab(c(((d)ef()g)h()(i)j)kl)()' | sed -r -f deparenthesize.sed
ab,ckl,hj,efg,i,d

Açıklama: sed, özyinelemeli regex'ler gibi şeyleri desteklemediğinden, el işi gerekir. İfade, her biri bir iç içe geçmiş derinlik düzeyini temsil eden birden çok satıra bölünür. Aynı derinlikteki (ve dolayısıyla aynı satırdaki) bireysel ifadeler bir ile ayrılır _. Komut bir seferde bir giriş parantezinde bir parantez içinde çalışır. Kalan giriş daima mevcut yuvalama seviyesine karşılık gelen satırın sonunda tutulur.


0

Python, 161 bayt

İşte tek bir fonksiyonel python çözümü buldum.

p=lambda s:filter(None,sum([''.join([s[i]for i in range(len(s))if s[:i+1].count('(')-s[:i+1].count(')')==d and s[i]!=')']).split('(')for d in range(len(s))],[]))

Bu zorluk, parantez içinde tanımlanmış olan uzun bir dize çıkaran https://github.com/samcoppini/Definition-book kitabından esinlenilmiştir . Bana her cümleyi verecek parantez çıkarılmış olarak kod yazmak istedim. İşlevsel çözüm uzun dizelerde etkili olamayacak kadar yavaş, ancak zorunlu çözümler (@ Quuxplusone'un çözümü gibi) çok daha hızlı.

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.