Найкоротший простий регулярний вираз, що відповідає двійковому слову


20

Завдання

Визначте простий регулярний вираз як не порожній регулярний вираз, що складається тільки з

  • символів 0і 1,
  • групування дужок (та ),
  • одно-або більше кількісний показник повторення +.

Враховуючи не порожній рядок 0s і 1s, ваша програма повинна знайти найкоротший простий регулярний вираз, що відповідає повній вхідній рядку. (Тобто, при збігу простий регулярних виразів, робити вигляд , що це bookended від ^ і  $.) Якщо існує кілька регулярних виразів найкоротших, виведіть будь-який з них або все.)

, тому найкоротше подання (у байтах) виграє.

Тестові кейси

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
Ви повинні уточнити, що ви хочете, щоб ми писали програму, яка пише регулярний вираз, а не писати регулярно. Але це виглядає цікаво.
gcampbell

1
На моєму тестуванні, 01100110цікавий випадок ... написав би наївний алгоритм 01+0+1+0чи (0+1+)+0не є оптимальним.
Ніл

Відповіді:


2

Pyth, 20 байт

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

Це запустить приблизно 30 секунд, тому його потрібно запустити в автономному режимі.

Пояснення:

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

Я не повністю впевнений, що кожен найкоротший рядок є сукупністю "() 01+" * 4, але 4 можна збільшити до 9 без витрат на байт.


9

JavaScript (ES6), 488 341 байт

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]

Пояснення: Оскільки шість регексів можуть виражати всі можливі бінарні слова, а найдовші два - дев’ять символів, достатньо перевірити ці та всі коротші регулярні вирази. Один із кандидатів - це, очевидно, рядок із "кодуванням довжини запуску" (тобто всі розряди циклів замінені на відповідні +s), але також ()слід перевірити рядки з одним набором s. Я генерую 1596 таких регексів (сюди входять дублікати та непотрібні регулярні виразки, але вони будуть просто усунені) і протестую всі 1597, щоб побачити, який найкоротший збіг. Згенеровані регекси поділяються на два типи: \(\d{2,5}\)\+(60 регексів) та (\d\+?)?\(\d[\d+]?(\d[\d+]?)?\)(\d\+?)?(1536 регексів, оскільки я уникаю генерування регексів як із провідною, так і з наступною цифрою).


@LeakyNun Спочатку я думав, що було 4 регулярні вирази довжиною 9, але це, очевидно, неправильно, тому я уточнив своє пояснення.
Ніл


1

Рубін, 109 байт

Це нудний підхід грубої сили. Працює, тому що жоден регулярний вираз не повинен бути довше 9 символів (як зазначає Ніл), і жоден окремий символ не потрібно повторювати більше 4 разів (спроба з ним '01()+'.chars*9зробила мій процесор нещасним).

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

Пітон 3, 186 байт

Я розслідую, чи існує підхід до цієї проблеми, окрім грубого насильства, але ось вирішення Python грубої сили поки що.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.