İkili bir sözcükle eşleşen en kısa basit normal ifade


20

Görev

Basit bir normal ifadeyi yalnızca aşağıdakilerden oluşan boş olmayan bir normal ifade olarak tanımlayın

  • karakterler 0ve 1,
  • parantez gruplama (ve ),
  • bir veya daha fazla tekrar nicelik belirteci +.

Boş olmayan bir 0s ve 1s dizesi verildiğinde , programınız tam giriş dizesiyle eşleşen en kısa basit normal ifadeyi bulmalıdır . (Yani, basit bir normal ifadeyle eşleştiğinde, ^ ve ile  işaretlenmiş gibi davranın $.) Birden çok kısa normal ifade varsa, bunların herhangi birini veya tümünü yazdırın.)

, böylece (bayt cinsinden) en kısa gönderme kazanır.

Test senaryoları

1 -> 1
00 -> 00 or 0+
010 -> 010
1110 -> 1+0
01010 -> 01010
0101010 -> 0(10)+ or (01)+0
011111 -> 01+
10110110 -> (1+0)+
01100110 -> (0110)+ or (01+0)+
010010010 -> (010)+
111100111 -> 1+001+ or 1+0+1+
00000101010 -> 0+(10)+ or (0+1)+0
1010110001 -> 1(0+1+)+ or (1+0+)+1

3
Normal ifadeyi kendimiz yazmak yerine normal ifadeyi yazan bir program yazmamızı istediğinizi açıklığa kavuşturmalısınız. Ama bu ilginç görünüyor.
gcampbell

1
Testlerimde 01100110ilginç bir durum var ... saf bir algoritma yazacaktı 01+0+1+0ya (0+1+)+0da optimal olmayan.
Neil

Yanıtlar:


2

Pyth, 20 bayt

hf.x}z:zT1Zy*4"()01+

Bu işlemin çalışması yaklaşık 30 saniye sürer, bu nedenle çevrimdışı çalıştırılması gerekir.

Açıklama:

hf.x}z:zT1Zy*4"()01+
                        Implicit: z is the input string.
              "()01+    "()01+"
            *4          Repeated 4 times
           y            All subsequences in length order
hf                      Output the first one such that
      :zT1              Form all regex matches of z with the candidate string
    }z                  Check if the input is one of the strings
  .x      Z             Discard errors

Her kısa dizenin "() 01+" * 4 dizisi olduğundan tam olarak emin değilim, ancak 4 gerekirse bayt maliyetiyle 9'a yükseltilebilir.


9

JavaScript (ES6), 488 341 bayt

s=>[s.replace(/(.)\1+/g,'$1+'),...[...Array(60)].map((_,i)=>`(${(i+4).toString(2).slice(1)})+`),...[...Array(1536)].map((_,i)=>`${i>>10?(i>>8&1)+(i&2?'+':''):''}(${i&1}${i&4?i>>4&1:i&16?'+':''}${i&8?''+(i>>7&1)+(i&64?i>>5&1:i&32?'+':''):''})+${i&512?(i>>8&1)+(i&2?'+':''):''}`)].filter(r=>s.match(`^${r}$`)).sort((a,b)=>a.length-b.length)[0]

Açıklama: Altı normal ifade tüm olası ikili kelimeleri ifade edebildiğinden ve en uzun ikisi dokuz karakter uzunluğunda olduğundan, bunları ve daha kısa normal ifadeleri kontrol etmek yeterlidir. Bir aday açık bir şekilde "çalışma uzunluğu kodlaması" olan bir dizedir (yani, tüm basamak çalışmaları uygun +s ile değiştirilir ), fakat aynı zamanda bir takım ()s içeren dizelerin de kontrol edilmesi gerekir. 1596 gibi regex'ler üretiyorum (bu kopyalar ve işe yaramaz regex'ler içerir, ancak bunlar ortadan kaldırılacaktır) ve 1597'nin tümünü hangisinin en kısa eşleşme olduğunu görmek için test edin. Oluşturulan regexes iki türe ayrılır: \(\d{2,5}\)\+(60 regexes) ve (\d\+?)?\(\d[\d+]?(\d[\d+]?)?\)(\d\+?)?(1536 regexes, hem önde gelen hem de takip eden basamağa sahip regexes üretmekten kaçınırım).


@LeakyNun Başlangıçta 9 uzunluk 4 regexes olduğunu düşündüm ama bu açıkçası yanlış yani açıklamam açıkladı.
Neil

2

Pyth - 31 30 29 bayt

Kaba kuvvet! Muhtemelen biraz yineleyici golf olabilir.

 f=+Yf.x:zjY"^$")Z^"10+()"T1Y

Test Takımı .


1

Yakut, 109 bayt

Sıkıcı kaba kuvvet yaklaşımı. Hiçbir regex hiç 9 karakterden daha uzun (Neil notları gibi) ve bireysel karakter 4 defadan fazla tekrarlanması gerekmez çünkü çalışır (ile '01()+'.chars*9benim CPU mutsuz yaptı).

10.times{|i|('01()+'.chars*4).combination(i).map{|s|begin
/^#{s*''}$/=~$*[0]&&[puts(s*''),exit]
rescue
end}}
$ for word in `grep -Po '^\S+' test_cases.txt`; do nice -n20 ruby sre.rb $word; done
1
0+
010
1+0
01010
0(10)+
01+
(1+0)+
(01+0)+
(010)+
1+0+1+
0+(10)+
1(0+1+)+

1

Python 3, 186 bayt

Bu soruna kaba-zorlama dışında bir yaklaşım olup olmadığını araştırıyorum, ama şimdilik bir Python kaba-kuvvet çözümü.

import re,itertools
def a(b):
 for z in range(10):
  for i in itertools.combinations("01()+"*4,z):
   j=''.join(i)
   try:
    if re.fullmatch(j,b)and len(j)<=len(b):return j
   except:1
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.