Regex, бумага, ножницы, ящерица, спок

81

Разминка: Regex, бумага, ножницы

Это задача, которую я изначально хотел опубликовать, прежде чем понял, что существует какое-то очень короткое решение. Тем не менее, это может быть интересной проблемой для размышления при подготовке к реальной задаче ниже.

Напишите три регулярных выражения R , P и S так , чтобы они совпадали друг с другом циклическим способом «камень, бумага, ножницы». В частности, R соответствует S , S соответствует Р и Р соответствует R , но R не соответствует P , S не соответствует R и Р не совпадает с S . Вот удобный столик:

Regex   Matches   Doesn't match
R       S         P
P       R         S
S       P         R

Неважно, что R , P и S делают на любых других входах, включая себя.

Здесь match просто означает, что некоторая (возможно, пустая) подстрока ввода совпадает. Совпадение не должно охватывать весь ввод.

Задача: регулярное выражение, бумага, ножницы, ящерица, спок

Для этой задачи вы решите более сложную версию вышеупомянутой проблемы, основанную на варианте RPS «Рок, бумага, ножницы, ящерица, спок» (популяризированный в теории большого взрыва ). В RPSLV есть пять разных символов, которые бьют друг друга в двух циклах:

  • Камень → Ножницы → Ящерица → Бумага → Спок → Камень
  • Камень → Ящерица → Спок → Ножницы → Бумага → Камень

Вы должны написать пять регулярных выражений R , P , S , L и V, которые имитируют эту структуру, когда передаются друг другу в качестве входных данных. Вот соответствующая таблица:

Regex   Matches   Doesn't match
R       L, S      V, P
L       V, P      S, R
V       S, R      P, L
S       P, L      R, V
P       R, V      L, S

Просто чтобы быть ясно, вы должны не соответствовать строке R, Pи т.д., но и другие регулярные выражения. Например , если ваш регулярное выражение R является ^\w$, например, то Р и V должны совпадать со строкой ^\w$, в то время как S и L не должны.

Опять же, совпадение просто означает, что хотя бы одна (возможно, пустая) подстрока ввода совпадает. Совпадение не должно охватывать весь ввод. Например \b(граница слова) соответствует hello(в начале и в конце), но не соответствует (^,^).

Вы можете использовать любой аромат regex, но, пожалуйста, укажите свой выбор в своем ответе и, если возможно, предоставьте ссылку на онлайн-тестер для выбранного вкуса. Вы не можете использовать какие-либо функции регулярных выражений, которые позволяют вам вызывать код на главном языке flavour (например, eмодификатор Perl flavour ).

Разделители (например /regex/) не включаются в регулярное выражение, если они передаются как входные данные для другого, и вы не можете использовать модификаторы, которые находятся за пределами регулярного выражения. Некоторые разновидности все еще позволяют использовать модификаторы со встроенным синтаксисом, например (?s).

Ваша оценка - это сумма длин пяти регулярных выражений в байтах. Ниже - лучше.

Оказывается, что гораздо проще найти в рабочее решение этой проблемы , чем это может показаться на первый, но я надеюсь , что найти оптимальное решение довольно сложно.

Мартин Эндер
источник
Скажем, R должен совпадать со всем регулярным выражением S или подстрокой S, если он не совпадает ни с одной подстрокой P или V?
Okx
@Okx "match просто означает, что сопоставлена ​​хотя бы одна (возможно, пустая) подстрока ввода. Соответствие не обязательно должно охватывать весь ввод. Например, \bсовпадения hello( границы слова) (в начале и в конце), но это не соответствует (^,^). "
Мартин Эндер
1
Предположительно, не имеет значения, соответствует ли регулярное выражение самому себе?
Brilliand
@ Brilliand Правильно.
Мартин Эндер
1
Отличная головоломка. Я создал интерактивную версию здесь, если кому-то интересно: shark.fish/rock-paper-scissors
shark.dp

Ответы:

45

PCRE .NET, 35 32 байта

-3 байта благодаря Мартину Эндеру

Рок:

([*?]$)

Бумага:

[)$]$+

Ножницы:

[+?]$.*

Ящерица:

[+$]$.?

Спок:

[*)]$

Идея здесь состоит в том, чтобы сопоставить символы в конце других регулярных выражений, которые являются зарезервированными символами регулярных выражений, но перестают обрабатываться как таковые, когда они находятся внутри класса символов.

Бизнес Кот
источник
1
Хорошо, вы выиграли: P
ETHproductions
3
Хитрое использование после EOL «$», которое игнорируется при активном использовании и сопоставимо при пассивном использовании
Stilez
44

PCRE, 15 14 байтов

Рок:
B

Бумага:
\b$

Ножницы:
b|B.

Ящерица:
\B.

Спок:
^\w

Андерс Касеорг
источник
4
Очень впечатляюще.
Эрик
Непобедимый! Я возился с Rock = Q(одно решение 14b существует с Lizard = `\ Q \`, а остальные похожи на ваши), но безрезультатно.
Jaytea
40

нет причудливых функций, 35 30 байт

5 байтов, сохраненных идеей Нейла, которая не ]нуждается в этом \.

Это работает, например, с reмодулем Python .

R='[SLR]]'
P='[RVP]]'
S='[PLS]]'
L='[PVL]]'
V='[SRV]]'

Он ищет ]предшествующую букву, которая указывает, какое это правило.

Предыдущая версия использовалась R='\[[RSL]'и т. Д.

Ранее использовалась попытка со счетом 40 R='[SL]x|Rx'и т. Д.

Кристиан Сиверс
источник
1
Сохраните 5 байтов, изменив все на обратное: R='[LSR]]'и т. Д.
Нейл,
@Neil Это большое улучшение, спасибо!
Кристиан Сиверс
This works with python's reну, тогда, вероятно, в заголовке должен быть Python
cat
1
@cat Я также написал «например», целое предложение просто чтобы сказать что-то конкретное, что я на самом деле пытался. Я думаю, я мог бы сказать POSIX, как и некоторые другие, но я думаю, что мой заголовок совершенно правильный.
Кристиан Сиверс
26

PCRE, 20 19

рок

W

Бумага

^\w

Ножницы

^\W

Спок

w?\x57$

ящерица

[w]W?
TwiNight
источник
21

20 байт

R = 'R|VP'
L = 'L|RS'
V = 'V|LP'
S = 'S|RV'
P = 'P|LS'
emulbreh
источник
Ого, это может быть так просто!
Кристиан Сиверс
Это красиво.
Эрик
8

JavaScript, 45 байт

Еще одно тривиальное решение.

R:
^R|^.[SL]
P:
^P|^.[RV]
S:
^S|^.[PL]
L:
^L|^.[PV]
V:
^V|^.[SR]
dzaima
источник
О, только что понял, что мой ответ - более длинная / похожая версия, хотите, чтобы я удалил ее?
TheLethalCoder
4
@TheLethalCoder Все ответы в настоящее время являются только более длинными / короткими версиями друг друга: p
dzaima
1
Я полагаю, ха-ха ...
TheLethalCoder
5

POSIX, 50 45 байт

Rock
.{5}RP?V?
Paper
.{5}PS?L?
Scissors
.{5}SR?V?
Lizard
.{5}LR?S?
Vulcan (Spock)
.{5}VP?L?

Можно сделать короче, но трюк (скрыть совпадения после $) привык, поэтому я ищу другой способ

Первые 5 символов каждой строки игнорируются при сопоставлении. Таким образом, эффективная целевая строка упрощается до X? Y ?. Ни у одного из них нет двойных букв, потому что "?" обычный символ, поэтому последние 4 символа при использовании в качестве регулярного выражения должны совпадать (пустая строка). Таким образом, шаблоны сворачиваются до «содержит 5 символов, за которыми следует целевая буква»: это означает, что символы 6–9 цели должны содержать целевую букву (5-й символ в каждой строке)

Обновление: 35-байтовая версия ниже, сейчас!

Stilez
источник
Я всегда думал, что V на самом деле не для V ulcan, а для представления формы приветствия Вулкана (это жест рукой, который вы используете для представления Спока при личной игре в RPSLV).
Мартин Эндер
В любом случае, добро пожаловать в PPCG! Хороший первый ответ. Мне нравится, что вы перевернули логику по сравнению со всеми существующими ответами (сопоставляя только одну букву и помещая буквы, избивающие текущее регулярное выражение в регулярное выражение).
Мартин Эндер
POSIX автоматически привязывает совпадение к началу строки? В противном случае, вы не могли бы бросить эти запятые?
Мартин Эндер
Я думаю, что это POSIX. Может быть перк. Но да, приятно заметили! 5 символов меньше!
Стилз
4
Там нет необходимости конкурировать с желе. Просто выберите язык, который вам нравится, и наслаждайтесь. :)
Мартин Эндер
3

PCRE, 65 байт

Это действительно тривиальное решение - и не очень умное - но я постараюсь сыграть в него.

В:

(?#V).+[SR]\)

L:

(?#L).+[PV]\)

S:

(?#S).+[PL]\)

П:

(?#P).+[RV]\)

Р:

(?#R).+[SL]\)

По сути, каждое регулярное выражение имеет «идентификатор» в форме комментария, который сообщает другим регулярным выражениям, должно ли оно соответствовать или нет.

Okx
источник
3

.NET, 50 байт

По порядку они есть R, P, S, L, V.

[^R]\^[SL]
[^P]\^[RV]
[^S]\^[PL]
[^L]\^[PV]
[^V]\^[SR]

Работает путем поиска группы идентификаторов (например, [^R]) в каждом из других выражений.

Изменение выражений на ^R|\^[SL](или аналогичное), кажется, работает, но тогда это слишком похоже на ответ @ dzaima, хотя получилось бы до 45 байт.

TheLethalCoder
источник
3

Vanilla RE, 40 символов

Не самое лаконичное или элегантное решение, но имеет приятную квазисемантическую визуальную структуру!

[^r][sl]
[^p][vr]
[^s][lp]
[^l][pv]
[^v][rs]

Камень бьется Ножницы или Ящерица
Бумага бьется Вулкан или Камень
Ножницы бьется Ящерица или Бумажный
Ящерица бьется Бумага или Вулкан
вулканец бьет Камень или Ножницы

Крис д'Амато
источник
2

POSIX, 35 байт

Rock
R?^[LS]
Paper
P?^[RV]
Scissors
S?^[LP]
Lizard
L?^[PV]
Vulcan (Spock)
V?^[RS]

Совершенно другой способ «спрятаться» за начальным / конечным символом, так что я чувствую себя нормально по этому поводу :) Я подхожу к началу, потому что «?» всегда будет идти между буквой и концом / $, если сделать иначе.

На 10 байт меньше, чем мое первое решение, и концептуально просто, что является бонусом, который мне нравится.

Stilez
источник