Чи рядок X є підрядком рядка Y?


23

Подавши рядки X і Y, визначте, чи X є підрядкою Y. Порожній рядок розглядається як послідовність кожного рядка. (Напр., ''І 'anna'є підрядками 'banana'.)

Вхідні дані

  • X - буквено-цифровий рядок, що залежить від регістру
  • Y, буквено-цифровий рядок, чутливий до регістру

Вихід

  • Істинне чи помилкове (або його еквіваленти), правильно вказуючи, чи є X послідовністю Y.

Приклади вводу / виводу

X      Y        output

''     'z00'    True
'z00'  'z00'    True 
'z00'  '00z0'   False
'aa'   'anna'   True
'anna' 'banana' True
'Anna' 'banana' False

Критерії

  • Виграє найкоротша програма, що визначається кількістю байтів вихідного коду.

Приклад програм


1
Чому 'anna' субстр 'банан'?
якDo

4
@kaoD - annaце підпослідовності (але НЕ подстрока) з banana. Рядок X - це підряд рядок Y, просто якщо X можна отримати з Y, видаливши нуль або більше елементів Y; наприклад, видалення bі другого aз bananaдає anna.
res

2
Це стосується єдиного рішення на кожній мові сценаріїв, що пропонує регулярний вираз, який є тривіальним для бачення і неможливий для гольфу далі.
Джої

Відповіді:


18

Perl 5 , 17 байт (+1?), Повна програма

s//.*/g;$_=<>=~$_

Спробуйте в Інтернеті!

Викликати pпрапор до перекладача perl, як у perl -pe 's//.*/g;$_=<>=~$_'. Відповідно до встановлених правил підрахунку, коли цей виклик був опублікований , цей прапор коштує один додатковий байт. За більш новими правилами , AFAICT, це може бути безкоштовно.

У будь-якому випадку вхідні рядки повинні подаватися в окремих строках, що закінчуються новою лінією на stdin. Вихід (для stdout) буде, 1якщо перший рядок введення є підрядком другого, або взагалі нічого, якщо його немає.

Зверніть увагу, що обидва рядки введення повинні мати нову лінію в кінці, інакше програма не працює належним чином. Крім того, ви можете додати lпрапор командного рядка до виклику, щоб зробити perl смугою нові рядки; Залежно від діючих правил підрахунку, це може або не коштувати додаткового байта. Зауважте, що використання цього прапора також додасть новий рядок до виводу.

Оригінальна версія (фрагмент, 18 байт / символів)

$x=~s//.*/g,$y=~$x

Введення подається у змінних, $xа $yрезультат - значення виразу (у скалярному контексті). Зауважте, що $xце змінюється в процесі. (Так, я знаю, що використання $_замість цього $xдозволило б мені зберегти чотири символи, але робити це в фрагменті, який здається мені занадто ситним.)

Як це працює?

Перша частина, $x=~s//.*/gвставляє рядок .*між кожним символом у $x. Друга частина, $y=~$xтрактує $xяк зворотній зв'язок і відповідає $yпроти нього. У регулярних виразах Perl .*відповідає нулю або більше довільних символів, в той час як усі буквено-цифрові символи зручно співпадають між собою.


Відповідно до (нового?) Консенсусу, подання має бути програмним чи функціональним, а не фрагментарним. Якщо ваше повідомлення це не задовольняє, спробуйте його відредагувати.
користувач202729

@ user202729: Цей виклик набагато старіший, ніж консенсус, тому, якщо не передбачається застосовувати заднім числом, відповіді в цій темі, мабуть, повинні бути "зібраними". З цього приводу я просто додав версію, яка відповідає чинним правилам, і може навіть бути на один байт / char коротше (зауважте, що базування на байті також новіше, ніж ця проблема, AFAIK) залежно від того, як ви рахуєте комутатори командного рядка.
Ільмарі Каронен

9

Рубі, 32 символи

s=->x,y{y=~/#{[*x.chars]*".*"}/}

Це рішення повертається, nilякщо xне є підпорядкою yі числом в іншому випадку (тобто рубінові еквіваленти до falseта true). Приклади:

p s['','z00']        # => 0   (i.e. true)
p s['z00','z00']     # => 0   (i.e. true)
p s['z00','00z0']    # => nil (i.e. false)
p s['anna','banana'] # => 1   (i.e. true)
p s['Anna','banana'] # => nil (i.e. false)

1
Я в основному робив те саме, але це занадто схоже, щоб я його не публікував. Я думаю, що прийнятно залишити лямбду, яка б залишила вас y=~/#{[*x.chars]*".*"}/(23 символи). ура!
Патрік Осіті

1
або навіть y=~/#{x.split("")*".*"}/(21
годин

@padde Розділений - це фактично 24 символи.
Говард

1
Вибачте, я гадаю, що я випадково пішов з цього y=~часу, переймаючись цим в Ірб ...
Патрік Oscity

Моя версія на 2 часи коротша.
Hauleth

7

Haskell, 51 37

h@(f:l)%(g:m)=f==g&&l%m||h%m;x%y=x<=y

Завдяки Хаммару за суттєве покращення. Зараз це функція інфіксації, але, здається, немає причин, чому вона не повинна.

Демонстрація:

GHCi> :{
GHCi| zipWith (%) [""   , "z00", "z00" , "anna"  , "Anna"]
GHCi|             ["z00", "z00", "00z0", "banana", "banana"]
GHCi| :}
[True,True,False,True,False]

Оскільки порожній список менший, ніж будь-який інший список, ви можете спростити базові випадки до s x y=x<=y. Крім того, ви можете зберегти ще кілька, зробивши його оператором і використовуючи @-pattern замість (f:l). Це скорочує його до 37 символів:h@(f:l)%(g:m)=f==g&&l%m||h%m;x%y=x<=y
hammar

6

Пітон (48 символів)

import re;s=lambda x,y:re.search('.*'.join(x),y)

Той самий підхід, що і у відповіді Говарда Рубі. Шкода, що Python потребує імпорту пакету регулярних виразів та його "багатослівної" lambda. :-)


1
Я згоден, лямбда - багатослівна.
CalculatorFeline

4

Пітон, 59 символів

def s(x,y):
 for c in y:
  if x:x=x[c==x[0]:]
 return x==""

Я вважав, що моя відповідь буде краще виражена в Python.

Редагувати: додано пропозиції щодо res.


Безперечно, x="a"і y="ab"ви вийдете з циклу y=="b"і повернетесь false?
Пітер Тейлор

@PeterTaylor Так, я помітив, коли я запускав приклади в якості тестів після публікації, що я перемішав xі збіг y. У моїх функціях yповинно бути послідовність x. Думаю, я б краще змінити їх, щоб уникнути плутанини.
Гарет

Ви можете отримати це вниз до 59 символів: def s(x,y): for c in y: if x:x=x[c==x[0]:] return x=="". Це не відображається правильно в коментарі, але я думаю, ви можете зрозуміти, що я маю на увазі. (Крім того, одного додаткового простору достатньо, щоб підвищити рівень відступу.)
Res

@res Спасибі, Python не є мовою, якою я багато використовую, як ви, напевно, можете сказати. Приємний гольф. (63 символи відповідно до сценарію користувача Codegolf - він повинен рахувати нові рядки).
Гарет

1
Ви можете використовувати розширення нарізки, щоб захистити від буття х ''і зберегти кілька символів, написавшиx=x[c==x[0:1]:]
Nolen Royalty

4

GolfScript (22 символи)

X[0]+Y{1$(@={\}*;}/0=!

Передбачається, що введення приймається як дві заздалегідь визначені змінні Xі Y, хоча це досить незвично в GolfScript. Залишає 1справжнє або 0неправдиве на стеці.



4

Бурлеск (6 символів)

6 символів у бурлескному: R@\/~[ (якщо припустити, що х і у знаходяться на стеці. Дивіться тут у дії.)



3

PHP, 90 символів

<?function s($x,$y){while($a<strlen($y))if($y[$a++]==$x[0])$x=substr($x,1);return $x=="";}

Ви можете видалити ifзаяву та спростити її на $x=substr($x,$y[$a++]==$x[0]): ideone.com/Ch9vK
mellamokb

Також ось трохи коротше 82-символьне рішення з використанням рекурсії: ideone.com/IeBns
mellamokb


3

CoffeeScript 112 100 95 89

Моя перша спроба кодового гольфу ... сподіваюся, я не соромлюся своєї сім'ї!

z=(x,y)->a=x.length;return 1if!a;b=y.indexOf x[0];return 0if!++b;z x[1..a],y[b..y.length]

Редагувати : виявляється, Coffeescript пробачає більше, ніж я думав із пробілом.

Дякуємо Res та Пітеру Тейлору за кілька порад, щоб зробити його трохи витонченішим


Ще кілька символів можуть бути усунені наступним чином (це не буде доступний широкому прямо в коментарях, але я думаю , що ви можете побачити , що я маю в виду) z=(x,y)-> a=x.length return 1if a==0 b=y.indexOf x[0] return 0if b<0 z x[1..a],y[b+1..y.length]. (В деяких браузерах, наприклад Chrome, ви можете побачити коментар код відображається правильно , клацнувши правою кнопкою миші, а потім оглянете елемент.)
рес

a.lengthніколи не буде негативним, тому ви можете зберегти один символ більше, замінивши if a==0на if a<1. Я не знаю, як працює токенізація CoffeeScript, але якщо вона використовується if0як два лексеми, ви можете зберегти ще два, змінивши обидві умови (тобто if1>a).
Пітер Тейлор

Хороші бали. if1>aне вірно, але if!aє і є символом коротшим! Я також зрозумів, що можу поголити зайвий символ, який перетворюється b+1на нього bта збільшується на попередньому рядку, також роблячи той самий ifтрюк, оскільки він мав справу зі ситуацією 0 / non-0.
Джонно

3

C #, 70 113 107 90 символів

static bool S(string x,string y){return y.Any(c=>x==""||(x=x.Remove(0,c==x[0]?1:0))=="");}

6
Це не пошук підстроки, а не підряд?
Гарет

так, я перечитав Слід виправити зараз.
мізер

1
Настільки весело, як і Linq, я думаю, що ви можете зекономити 10%, скориставшись замість цього рекурсію.
Пітер Тейлор

Ось моя найкраща спроба. Ще довше. static bool S(string x,string y){if(x!=""&&y=="")return false;return x==""||S(y[0]==x[0]?x.Remove(0,1):x,y.Remove(0,1));}
мізер

Ви можете зменшити рекурсивну x==""||y!=""&&S(...)версію до , але вона все ще довша, ніж оновлена ​​версія Linq. Приємного використання Any!
Пітер Тейлор

3

Математика 19 17 27

LongestCommonSequenceповертає найдовшу безперервну послідовність двох рядків. (Не плутати з цим LongestCommonSubsequence, що повертає найдовше суміжне підпорядкування.

Далі перевіряється, чи є найдовше суміжне подання першим із двох рядків. (Отже, ви повинні ввести коротший рядок, за яким слід більший рядок.)

LongestCommonSequence@##==#& 

Приклади

LongestCommonSequence@## == # &["", "z00"]
LongestCommonSequence@## == # &["z00", "z00"]
LongestCommonSequence@## == # &["anna", "banana"]
LongestCommonSequence@## == # &["Anna", "banana"]

Справжнє Справжнє Істинне Неправдиве

Критичний тест - третій, оскільки "анна" міститься безперервно в "банані".


3

Python 3.8 (передвипуск) , 42 байти

lambda a,b:''in[a:=a[a[:1]==c:]for c in b]

Спробуйте в Інтернеті!

Python 3.8 (передвипуск) , 48 байт

lambda a,b,j=0:all((j:=1+b.find(c,j))for c in a)

Спробуйте в Інтернеті!

Python 2 , 48 байт

lambda a,b:re.search('.*'.join(a),b)>0
import re

Спробуйте в Інтернеті!

Скопійовано з цієї відповіді Лінн . >0Може бути опущена , якщо тільки truthy / falsey вихід OK.

Python 2 , 50 байт

f=lambda a,b:b and f(a[a[:1]==b[0]:],b[1:])or''==a

Спробуйте в Інтернеті!

Python 2 , 50 байт

lambda a,b:reduce(lambda s,c:s[c==s[:1]:],b,a)==''

Спробуйте в Інтернеті!


Прекрасне використання моржів.
Джонатан Аллан

2

С - 74 71 64

Це не перемагає рішення Пітера Тейлора, але я думаю, що це досить весело (плюс, це повноцінна робоча програма, а не лише функція)

main(int c,char**v){for(;*v[1]!=0;++v[1])v[2]+=*v[1]==*v[2];return*v[2];}

main(int c,char**v){for(;*v[1];++v[1])v[2]+=*v[1]==*v[2];return*v[2];}


main(c,v)char**v;{while(*v[1])v[2]+=*v[1]++==*v[2];return*v[2];}

І неозорені:

main(int argc, char** argv){
   char * input = argv[1];
   char * test  = argv[2];

   // advance through the input string. Each time the current input
   // character is equal to the current test character, increment
   // the position in the test string.

   for(; *input!='\0'; ++input) test += *input == *test;

   // return the character that we got to in the test string.
   // if it is '\0' then we got to the end of the test string which
   // means that it is a subsequence, and the 0 (EXIT_SUCCESS) value is returned
   // otherwise something non-zero is returned, indicating failure.
   return *test;
}

Щоб перевірити це, ви можете зробити щось на кшталт:

./is_subsequence banana anna && echo "yes" || echo "nope"    
# yes
./is_subsequence banana foobar && echo "yes" || echo "nope"    
# nope

!=0в умові дещо багатослівний ... Програма проти функції - це те, що питання потрібно чітко вказати, а тут цього немає, тому відповіді мають різні варіанти.
Пітер Тейлор

Чорт, !='\0'це погана (гарна?) Звичка писати код не для гольфу, я дозволив це проскочити в останні два раунди гольфу, мені доведеться бути обережнішими в майбутньому. Що стосується програми проти функції, так, ви абсолютно праві.
Гордон Бейлі

@GordonBailey вибачте за шишку, але я вніс кілька змін у більш коротку версію.
oldrinb

2

Пітон, 66 62 59 58 символів

Вид веселого рішення, безумовно, акуратна проблема.

def f(n,h,r=0):
 for c in h:r+=n[r:r+1]==c
 return r==len(n)

2

Рубін 32 30 28

f=->a,b{b.match a.tr'','.*'}

Це повернеться MatchData екземпляр, якщо aце підпорядкування bчи nilіншим чином.

Стара версія, що знаходить підрядку замість підрядки

Рубін 15

f=->a,b{!!b[a]}

Використання String#[](str)методу, який повертає, strякщо strє підрядком selfта !!повертається, Booleanякщо повернене значення може використовуватися як булеве (і не потрібно бути trueабоfalse ), то воно може становити лише 13 символів:

f=->a,b{b[a]}

Він повернеться, nilякщо aне є підрядком b.


2
Приємно, але питання задає підпорядкування, а не підрядку.
Гарет

2

SWI-Prolog, SICStus

Вбудований підказок предикатів / 2 підлік підказок SICStus перевіряє, чи всі елементи першого списку також відображаються у другому списку. Цей предикат також доступний у SWI-Prolog через бібліотеку сумісності, яка може бути завантажена запитом [library(dialect/sicstus/lists)]..

Проба зразка:

25 ?- sublist("","z00").
true.

26 ?- sublist("z00","z00").
true .

27 ?- sublist("z00","00z0").
false.

28 ?- sublist("aa","anna").
true .

29 ?- sublist("anna","banana").
true .

30 ?- sublist("Anna","banana").
false.

Технічна кількість байтів технічно може бути 0, оскільки все, що ми тут робимо, - це запити, як і те, як ми запускаємо програму і подаємо в неї введення.


2

PHP, 41 байт

друкує 1 для справжнього і нічого неправдивого

<?=!levenshtein($argv[1],$argv[2],0,1,1);

Якщо тільки вставки з слова 1 в слово 2 зроблено, для справжніх випадків підрахунок дорівнює нулю

Левенштейн

Спробуйте в Інтернеті!

PHP, 57 байт

друкує 1 для істинного та 0 для хибного

Створює Regex

<?=preg_match(_.chunk_split($argv[1],1,".*")._,$argv[2]);

Спробуйте в Інтернеті!


1
-2 байти: вести .*непотрібно. -2 байт: do not правонаступник $argvв $a. +24 байти: потреби array_map(preg_quote())у спеціальних символах (використовуйте круглі дужки як роздільники, щоб уникнути другого preg_quoteпараметра)
Тит

2
@ Титус ведучий. * Необхідний для введення порожнього рядка, а для введення я повинен обробляти лише можливо порожній буквено-цифровий рядок, чутливий до регістру. Ви маєте рацію з цитатою, якщо є спеціальні символи. Дякуємо, що порахували присвоєння. Скопіюйте та вставте попереднє рішення, а не думайте про це
Jörg Hülsermann

1
preg_matchне поскаржиться на порожній регулярний вираз, поки там розміщувачі. Це просто відповідатиме чому завгодно. Але preg_quote все +22 байт, а НЕ +24: array_map(preg_quote,str_split(...)).
Тит

1
Але тоді вхід гарантовано буквено-цифровий :) Але все одно вам не потрібні ведучі .*.
Тит

2

Брахілог , 2 байти

⊆ᵈ

Спробуйте в Інтернеті!

Як і у цій відповіді, це вбудований предикат, який оголошує взаємозв'язок між вхідною та вихідною змінними, і є мета-предикатом, який модифікує його, щоб оголосити те саме співвідношення між першим та другим елементами вхідної змінної замість (та об'єднати вихідна змінна з другим елементом, але оскільки це проблема рішення, яка не закінчується тут важливою). X⊆Yє твердженням, що X - це підряд Y, тому так і є [X,Y]⊆ᵈ.

Цей предикат (який, звичайно, виводиться через успіх або невдачу, який друкує true.або false.коли він працює як програма) приймає введення як список двох рядків. Якщо введення трохи гнучкіше ...

Брахілог , 1 байт

Спробуйте в Інтернеті!

Приймає рядок X як вхідну змінну, а рядок Y - як вихідну змінну. Результати через успіх чи невдачу, як і раніше. Якщо запустити як повну програму, X подається як вхід, а Y подається як перший аргумент командного рядка.


1

CoffeeScript 73

Ось альтернативна відповідь CoffeeScript, використовуючи регулярні вирази замість рекурсії:

z=(x,y)->a='.*';a+=c+'.*'for c in x;b=eval('/'+a+'/');(y.replace b,'')<y

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

Повертає помилку, коли xіy є порожніми рядками. Подумайте, нам потрібен філософ, щоб сказати нам, чи порожня рядок є сукупністю себе!

(Опубліковано як окрема відповідь від моєї попередньої, оскільки вона відчуває себе досить різною, щоб виправдати це).


1

PowerShell, 38

$args[1]-clike($args[0]-replace'','*')

Звичайно, будь-яке таке рішення, що базується на регулярному вираженні чи узорі, має серйозні проблеми з продуктивністю з довшими рядками. Але оскільки нестача - це критерій ...


1

Різновид анти-розчину, що генерує всі підряди Y:

Пітон 93

l=len(y)
print x in[''.join(c for i,c in zip(bin(n)[2:].rjust(l,'0'),y)if i=='1')for n in range(2**l)]

1

APL (31)

Обробку рядків трохи не вистачає в APL.

{(⊂'')∊N←⍵↓⍨¨1,⍨=/⊃¨⍵:~×⍴⊃N⋄∇N}

використання:

      {(⊂ '') ∊N ← ⍵ ↓ ⍨¨1, ⍨ = / ⊃¨⍵: ~ × ⍴⊃N⋄∇N} 'anna' 'банан'
1
      {(⊂ '') ∊N ← ⍵ ↓ ⍨¨1, ⍨ = / ⊃¨⍵: ~ × ⍴⊃N⋄∇N} 'Анна' 'банан'
0
      {(⊂ '') ∊N ← ⍵ ↓ ⍨¨1, ⍨ = / ⊃¨⍵: ~ × ⍴⊃N⋄∇N} '' 'банан'
1

1

Пітон 132

Схожий на Данієро. Не найпростіше рішення, але спробувати було весело. Я новачок у Python, тому я впевнений, що міг би скоротити його, якби знав трохи більше.

def f(i):
    s=x;j=0
    while j<len(s):t=~i%2;s=[s[:j]+s[j+1:],s][t];j+=t;i>>=1
    return s==y
print True in map(f,range(1,2**len(x)))


1

Пітон ( 75 52)

s=lambda a,b:a==''or b>''and s(a[a[0]==b[0]:],b[1:])

Просте рекурсивне рішення. Перший раз гольф, тому будь-які поради щодо вибивання цього вдячної оцінки дуже вдячні :)

Тестується з наступним:

assert s('anna', 'banana') == True
assert s('oo0', 'oFopp0') == True
assert s 'this', 'this is a string') == True
assert s('that', 'this hat is large') == True
assert s('cba', 'abcdefg') == False

Завдяки @lirtosiast за кілька хитромудрих булевих хитрощів.


1
Ви можете s=lambda a,b:a==''or b>''and s(a[a[0]==b[0]:],b[1:])
звести

Дякую, це розумно, використовуючи булевий як індекс 0/1 в зрощення :)
foslock

1

PHP, 75 65 64 байт

for(;$p=@strpos(_.$argv[2],$c=$argv[1][$i++],$p+1););echo""==$c;

приймає дані з аргументів командного рядка; друкує 1для true, порожній рядок для false. Бігайте з-r .

пояснення:

  • strposповертається, falseякщо голка $cне знаходиться в стозі сіна $argv[2](після положення $p), що
    спричиняє розрив петлі.
  • strposтакож повертається falseза порожньою голкою, розриваючи петлю в кінці $argv[1].
  • Якщо $argv[1]це підряд $argv[2], $cбуде порожнім, коли цикл перерветься.
  • strposпотрібно @придушити Empty needleпопередження.

+$pзамість цього $p+1після цього немає необхідності підкреслювати
Jörg Hülsermann

@ JörgHülsermann +1потрібен для просування в ланцюзі сіна; і підкреслення уникає $p=-1ініціалізації. Але ... я можу уникнути false!==.
Тит

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