Самая короткая уникальная подстрока


14

Учитывая (в STDIN, как аргументы командной строки или как аргументы функции) две разные непустые строки, найдите и верните самую короткую подстроку первой строки, которая не является подстрокой второй. Если такой подстроки не существует, вы можете вернуть пустую строку, вернуть любую строку, которая не является подстрокой исходной строки, или выдать исключение. Если вы возвращаетесь из функции, вы также можете вернуть null (или undefined, None и т. Д.) В этом случае. Если несколько таких подстрок связаны с самыми короткими, вы можете вернуть любую из них.

Строки могут состоять из любых печатных символов ascii.

Ввод данных в STDIN будет дан с одной строкой в ​​каждой строке. По вашему запросу в конце ввода может быть добавлена ​​одна пустая строка.

Это код гольф, поэтому выигрывает самая короткая действительная программа.

НЕКОТОРЫЕ ИСПЫТАТЕЛЬНЫЕ СЛУЧАИ

ВХОД:

STRING ONE
STRING TWO

ВЫХОД:

E

ВХОД:

A&&C
A&$C

ДЕЙСТВИТЕЛЬНЫЕ ВЫХОДЫ:

&&
&C

ВХОД:

(Две случайно сгенерированные 80-буквенные строки)

QIJYXPYWIWESWBRFWUHEERVQFJROYIXNKPKVDDFFZBUNBRZVUEYKLURBJCZJYMINCZNQEYKRADRYSWMH
HAXUDFLYFSLABUCXUWNHPSGQUXMQUIQYRWVIXGNKJGYUTWMLLPRIZDRLFXWKXOBOOEFESKNCUIFHNLFE

ВСЕ ДЕЙСТВИТЕЛЬНЫЕ ВЫХОДЫ:

AD
BJ
BR
CZ
DD
EE
ER
EY
EY
FF
FJ
FW
FZ
HE
IJ
IN
IW
JC
JR
JY
KL
KP
KR
KV
LU
MH
MI
NB
NQ
OY
PK
PY
QE
QF
QI
RA
RB
RF
RO
RV
RY
RZ
SW
UE
UH
UN
UR
VD
VQ
VU
WB
WE
WI
WU
XN
XP
YI
YK
YK
YM
YS
YW
YX
ZB
ZJ
ZN
ZV

1
короткий или длинный?
Утренняя монахиня

@FryAmTheEggman Тогда я должен еще опубликовать свое решение ...
Дырявый Nun

«Одна строка в каждой строке» с или без кавычек?
Утренняя монахиня,

1
Можем ли мы взять массив строк?
Деннис

такое "B" подстрока "aBc"?
downrep_nation

Ответы:


4

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

:1foh.,{,.[A:B]hs?'~sB}

Работает на старом транспортере Java. Ожидает две строки в списке в качестве входных данных, объединяет выходные данные с подстрокой. Если подстрока не найдена, возвращает false.

К сожалению, я еще не кодировал подмножество, встроенное в новый транспортер Prolog.

объяснение

:1f               Find all bindings which satisfy predicate 1 with that binding as input and
                  with the Input of the main predicate as output.
   oh.,           Order that list of bindings, and unify the output with the first one.

{
 ,.[A:B]          Unify the output with the list [A,B]
        hs?       Unify the input with a subset of A
           '~sB   Check that no subset of B can be unified with the input
               }

4

Питон, 119 115 91

lambda a,b:[a[m:m+n]for n in range(1,len(a)+1)for m in range(len(a))if a[m:m+n]not in b][0]

Тестовые случаи:

| Input 1  | Input 2     | Output        |
|----------+-------------+---------------|
| 'abcd'   | 'abc'       |  'd'          |
| 'abcd'   | 'dabc'      |  'cd'         |
| 'abcd'   | 'dcbabbccd' |  'abc'        |
| 'abcdf'  | 'abcdebcdf' |  'abcdf'      |
| 'abc'    | 'abc'       |  (IndexError) |

Работаю над тем, чтобы сделать его короче, но это мой мозговой инстинкт. Не очень большой игрок в гольф еще.

Спасибо @ user81655 и @NonlinearFruit за дополнительные байты.

Редактировать :

Dang. Пробовал этот код:

def z(a,b):
 for s in [a[m:m+n]for n in range(1,len(a)+1)for m in range(len(a)-n+1)]:
  if s not in b:return s
 return''

Думал, что это было на несколько байтов короче. Оказывается, это было на 1 байт длиннее, чем было до редактирования.


Я не знаю много Python, но, может быть, вы можете (r=range)(1,len(a)+1)тогда использовать r?
Конор О'Брайен,

@ CᴏɴᴏʀO'Bʀɪᴇɴ Не могу так поступить. Если я задаю , rangeчтобы rв строке выше, он фактически добавляет байт. Хорошая идея, хотя. Вероятно, существует более короткий способ перебора подстрок.
Тейлор Лопес

range(1,len(a))и range(len(a)-1)должен работать не так ли? Также я думаю, что использование символа табуляции для отступа в два пробела позволит сохранить байт.
user81655

Нет, с range(1,len(a))4-м тестом приведен сбой, потому что он не будет пробовать полную строку; это будет идти только до длины строки - 1. И с range(len(a)-1), 1-й контрольный пример не возвращается, 'cd'а просто 'd'. Там может быть что-то, хотя.
Тейлор Лопес

Извините, я не знаком с Python, и я предположил, что диапазоны были включены. В этом случае попробуйте range(1,len(a)+1)и range(len(a)).
user81655

3

Python, 87 86 байт

lambda s,t,e=enumerate:[s[i:i-~j]for j,_ in e(s)for i,_ in e(s)if(s[i:i-~j]in t)<1][0]

Если он существует, он вернет самую левую из всех самых коротких уникальных подстрок.

Если нет уникальной подстроки, возникает ошибка IndexError .

Проверьте это на Ideone .


Вот оно Я ждал, чтобы кто-нибудь убил мою не-лямбда-реализацию. хороший лол
Тейлор Лопес

Я думаю , что вы можете сделать это короче, снабжая необязательный второй аргумент , enumerateчтобы начать jв i+1.
user2357112 поддерживает Monica

@ user2357112 Это , к сожалению, вызывает ошибку NameError . Код определяет jсначала, потом i.
Деннис

@ Денис: Да, но это не нужно. Вы можете изменить порядок петель.
user2357112 поддерживает Monica

1
@ user2357112 Если я переключу порядок цикла, первая найденная уникальная подстрока может быть не самой короткой. Простое изменение порядка возвращает 'ab'для ввода 'abc','aaa'.
Деннис

2

Python, 82 байта

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}
f=lambda s,t:min(g(s)-g(t),key=len)

Использование: f('A&&C', 'A&$C')-> возвращает'&&'

Вызывает ValueError, если подходящей подстроки нет.

Объяснение:

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}рекурсивно создает набор подстрок из u f=lambda s,t:min(g(s)-g(t),key=len)принимает самую короткую подстроку из заданной разности


2

JavaScript (ES6), 79 байт

f=
(a,b)=>[...a].some((_,i,c)=>c.some((_,j)=>b.indexOf(s=a.substr(j,i+1))<0))?s:''
<div oninput=o.textContent=f(a.value,b.value)><input id="a"/><input id="b"/><pre id=o>

Если возврат falseприемлем, сохраните 2 байта, используя &&sвместо ?s:''.



1

JavaScript (Firefox), 80 байт

solution=

a=>b=>[for(_ of(i=0,a))for(_ of(j=!++i,a))if(b.includes(s=a.substr(j++,i)))s][0]

document.write("<pre>"+
[ [ "test", "best" ], [ "wes", "west" ], [ "red", "dress" ] ]
.map(c=>c+": "+solution(c[0])(c[1])).join`\n`)

Тест работает только в Firefox. Возвращает, undefinedесли нет подстроки.


Строки могут содержать печатные символы ASCII, такие как \ или другие метасимволы RegExp, но если вы ограничиваете себя Firefox, почему бы не использовать b.includesвместо этого?
Нил

@Neil Вопрос не говорил, что строки могли быть любым символом прежде, но спасибо, что сообщили мне знать! Обновлено для использования includes.
user81655

1
Тестовый фрагмент SyntaxError: unexpected token 'for'
кода

@NoOneIsHere Это ошибка, которую вы получите, если не используете Firefox ...
user81655

1

Сетчатка , 37 байт

M!&`\G(.+?)(?!.*¶.*\1)
O$#`.+
$.&
G1`

Вывод пуст, если в. Не найдена допустимая подстрока A.

Попробуйте онлайн! (Немного изменен для одновременного запуска нескольких тестовых наборов. Формат ввода фактически разделен переводом строки, но наборы тестов проще всего написать с одним тестовым набором на строку. Среда тестирования превращает пространство в перевод строки до начала реального кода.)

объяснение

M!&`\G(.+?)(?!.*¶.*\1)

Для каждой возможной начальной позиции в A, сопоставьте самую короткую подстроку, которая не появляется в B. Предназначен &для перекрывающихся совпадений, так что мы фактически пробуем каждую начальную позицию, даже если совпадение длиннее одного символа. В \Gгарантирует , что мы не пропустить ни одной позиции - в частности, таким образом , мы должны остановиться на перевод строки, так что мы не получаем дополнительные матчи от Bсебя. Причина, по которой это не мешает, на самом деле довольно неуловима: потому что если есть начальная позиция, в Aкоторой мы не можем найти какую-либо допустимую подстроку, то это также ошибка, которая приведет \Gк прекращению проверки любых дальнейших позиций. Однако, если (из текущей начальной позиции) все подстроки появляются вBто же самое относится и ко всем подстрокам, которые начинаются дальше справа от текущей позиции, поэтому их отбрасывание не является проблемой (и фактически повышает производительность).

Из-за M!конфигурации все эти совпадения будут возвращены со сцены, объединены с переводами строки.

O$#`.+
$.&

Это сортирует строки предыдущего результата по длине. Это делается путем сопоставления строки с .+. потом$ активируется форма «сортировки», так что совпадение заменяется $.&для определения порядка сортировки. $.&Сам заменяет матч с его длиной. Наконец, #опция указывает Retina сортировать численно (в противном случае получающиеся числа будут обрабатываться как строки и сортироваться лексикографически).

G1`

Наконец, мы просто сохраняем только первую строку, используя этап grep с пустым регулярным выражением (которое всегда совпадает) и пределом 1 .


1

Perl, 87 85

sub{(grep{$_[1]!~/\Q$_/}map{$}=$_;map{substr($_[0],$_,$})}@}}(@}=0..length$_[0]))[0]}

Это анонимная функция, которая возвращает первую (по позиции) самую короткую подстроку, $_[0]которая не встречается $_[1], илиundef если такой подстроки не существует.

Тестовая программа со строками, взятыми из ответа @ iAmMortos, протестирована с Perl 5.22.1:

#!/usr/bin/perl -l
use strict;
use warnings;

my $f = <see above>;
print $f->('abcd', 'abc');
print $f->('abcd', 'dabc');
print $f->('abcd', 'dcbabbccd');
print $f->('abcdf', 'abcdebcdf');
print $f->('abc', 'abc');

1

Haskell, 72 байта

import Data.Lists
a#b=argmin length[x|x<-powerslice a,not$isInfixOf x b]

Пример использования: "abcd" # "dabc"-> "cd".

Простая реализация: создайте все подстроки aи сохраните те, которые не отображаются в b. argminвозвращает элемент списка , который сводит к минимуму функции по заданной 2 - й аргументу, здесь: length.


Я не знал о argmin! Это кажется чрезвычайно полезным.
Згарб

0

Вычеркнуто 9 все еще 9
кошка

Я хотел бы знать, как это работает.
mroman

@mroman.: с одним аргументом - все подстроки. Поэтому я сопоставляю это с обеими строками, затем складываю по-разному diff, так что у меня есть все подстроки первого, второго и второго, затем я выбираю первый, который наименьший, потому что: отсортирован.
Maltysen

0

C #, 152 байта

string f(string a,string b){int x=a.Length;for(int i=1;i<=x;i++)for(int j=0;j<=x-i;j++){var y=a.Substring(j,i);if(!b.Contains(y))return y;}return null;}

0

Рубин, 70 байт

Собирает все подстроки определенной длины из первой строки и, если есть такая, которой нет во второй строке, возвращает ее.

->a,b{r=p;(1..l=a.size).map{|i|(0...l).map{|j|b[s=a[j,i]]?0:r||=s}};r}

0

Бурлеск - 26 байтов

Прямо сейчас самый короткий способ, которым я могу придумать, является:

lnp^sujbcjz[{^p~[n!}f[-][~

0

Japt , 14 байт

Êõ!ãU c k!èV g

Попробуйте онлайн!

Возвращает, undefinedесли нет допустимой подстроки . Это отличается от возврата строки "undefined" , хотя разница видна только из-за флага -Q.

Объяснение:

Ê                 :Length of the first input
 õ                :For each number in the range [1...length]:
  !ãU             : Get the substrings of the first input with that length
      c           :Flatten to a single array with shorter substrings first
        k         :Remove ones which return non-zero to:
         !èV      : Number of times that substring appears in second input
             g    :Return the shortest remaining substring

0

Japt -h, 11 байт

à f@øX «VøX

Попытайся

                :Implicit input of strings U & V
à               :All combinations of U
  f@            :Filter each as X
    øX          :  Does U contain X?
       «        :  Logical AND with the negation of
        VøX     :  Does V contain X?
                :Implicit output of last element
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.