Kürzester eindeutiger Teilstring

14

Wenn Sie (in STDIN, als Befehlszeilenargumente oder als Funktionsargumente) zwei unterschiedliche, nicht leere Zeichenfolgen angeben, suchen Sie die kürzeste Teilzeichenfolge der ersten Zeichenfolge, die keine Teilzeichenfolge der zweiten ist, und geben Sie sie zurück. Wenn keine solche Teilzeichenfolge vorhanden ist, können Sie die leere Zeichenfolge zurückgeben, eine beliebige Zeichenfolge zurückgeben, die keine Teilzeichenfolge der ursprünglichen Zeichenfolge ist, oder eine Ausnahme auslösen. Wenn Sie von einer Funktion zurückkehren, können Sie in diesem Fall auch null (oder undefiniert, keine usw.) zurückgeben. Wenn mehrere solcher Teilzeichenfolgen für die kürzeste Zeit gebunden sind, können Sie eine beliebige davon zurückgeben.

Zeichenfolgen können aus beliebigen druckbaren ASCII-Zeichen bestehen.

Auf STDIN angegebene Eingaben werden mit einer Zeichenfolge in jeder Zeile angegeben. Auf Ihren Wunsch kann am Ende der Eingabe eine einzelne Leerzeile eingefügt werden.

Dies ist Codegolf, also gewinnt das kürzeste gültige Programm.

EINIGE TESTFÄLLE

EINGANG:

STRING ONE
STRING TWO

AUSGABE:

E

EINGANG:

A&&C
A&$C

GÜLTIGE AUSGÄNGE:

&&
&C

EINGANG:

(Zwei zufällig generierte Zeichenfolgen mit 80 Buchstaben)

QIJYXPYWIWESWBRFWUHEERVQFJROYIXNKPKVDDFFZBUNBRZVUEYKLURBJCZJYMINCZNQEYKRADRYSWMH
HAXUDFLYFSLABUCXUWNHPSGQUXMQUIQYRWVIXGNKJGYUTWMLLPRIZDRLFXWKXOBOOEFESKNCUIFHNLFE

ALLE GÜLTIGEN AUSGÄNGE:

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
SuperJedi224
quelle
1
kürzeste oder längste?
Undichte Nonne
@FryAmTheEggman Dann sollte ich noch meine Lösung posten ...
Undichte Nonne
"Ein String in jeder Zeile" mit oder ohne Anführungszeichen?
Undichte Nonne
1
Können wir eine Reihe von Zeichenfolgen nehmen?
Dennis
ist "B" eine Teilzeichenfolge von "aBc"?
Downrep_nation

Antworten:

4

Brachylog , 23 Bytes

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

Funktioniert auf dem alten Java-Transpiler. Erwartet die beiden Zeichenfolgen in einer Liste als Eingabe, vereinheitlicht die Ausgabe mit der Teilzeichenfolge. Wenn keine Teilzeichenfolge gefunden wird, wird false zurückgegeben.

Leider habe ich die im neuen Prolog-Transpiler integrierte Teilmenge noch nicht codiert.

Erläuterung

: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
               }
Tödlich
quelle
4

Python, 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]

Testfälle:

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

Ich arbeite daran, es kürzer zu machen, aber das ist mein Gehirninstinkt. Noch kein richtiger Golfer.

Vielen Dank an @ user81655 und @NonlinearFruit für die zusätzlichen Bytes.

Bearbeiten :

Dang. Versuchte diesen Code:

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''

Dachte, es wäre ein paar Bytes kürzer. Es stellte sich heraus, dass es 1 Byte länger war als vor der Bearbeitung.

Taylor Lopez
quelle
Ich kenne nicht viel Python, aber vielleicht kannst du das (r=range)(1,len(a)+1)dann nutzen r?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Ganz so geht es nicht. Wenn ich zuweisen rangezu rin der Zeile darüber, fügt es tatsächlich ein Byte. Gute Idee. Es gibt wahrscheinlich einen kürzeren Weg, um die Teilzeichenfolgen zu durchlaufen.
Taylor Lopez
range(1,len(a))und range(len(a)-1)sollte funktionieren sollte es nicht? Außerdem würde die Verwendung eines Tabulatorzeichens für den Einzug mit zwei Leerzeichen ein Byte sparen.
user81655
Nein, mit range(1,len(a))schlägt die vierte Testbesetzung fehl, da nicht die gesamte Saite ausprobiert wird. es geht nur bis zur Länge der Zeichenkette - 1. Und mit range(len(a)-1)schlägt der erste Testfall fehl, 'cd'anstatt nur zurückzukehren 'd'. Möglicherweise gibt es dort jedoch etwas.
Taylor Lopez
Tut mir leid, ich kenne Python nicht und habe angenommen, dass die Bereiche inklusive sind. In diesem Fall versuchen Sie range(1,len(a)+1)und range(len(a)).
User81655
3

Python, 87 86 Bytes

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]

Ist dies der Fall, wird die am weitesten links stehende aller kürzesten eindeutigen Teilzeichenfolgen zurückgegeben.

Wenn es keine eindeutige Teilzeichenfolge gibt, wird eine Teilzeichenfolge IndexError gibt .

Teste es auf Ideone .

Dennis
quelle
Da ist es. Ich habe darauf gewartet, dass jemand meine Nicht-Lambda-Implementierung tötet. schön lol
Taylor Lopez
Ich denke, Sie können dies verkürzen, indem Sie das optionale zweite Argument angeben enumerate, um jbei zu beginnen i+1.
user2357112 unterstützt Monica
@ user2357112 Das löst leider einen NameError aus . Der Code definiert jdann zuerst i.
Dennis
@ Tennis: Ja, aber es muss nicht. Sie könnten die Schleifenreihenfolge ändern.
user2357112 unterstützt Monica
1
@ user2357112 Wenn ich die Schleifenreihenfolge ändere, ist die erste eindeutige Teilzeichenfolge möglicherweise nicht die kürzeste. Tauschen Sie einfach die Bestellrückgabe 'ab'gegen eine Eingabe aus 'abc','aaa'.
Dennis
2

Python, 82 Bytes

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

Verbrauch: f('A&&C', 'A&$C')-> Rückkehr'&&'

Löst ValueError aus, wenn keine geeignete Teilzeichenfolge vorhanden ist.

Erläuterung:

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}Erstellt rekursiv eine Menge der Teilzeichenfolgen von u f=lambda s,t:min(g(s)-g(t),key=len)entnimmt die kürzeste Teilzeichenfolge der Mengenunterschiede

RootTwo
quelle
2

JavaScript (ES6), 79 Byte

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>

Wenn die Rückgabe falseakzeptabel ist, speichern Sie 2 Bytes mit &&sanstelle von ?s:''.

Neil
quelle
1

JavaScript (Firefox), 80 Byte

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`)

Test funktioniert nur in Firefox. Gibt zurück, undefinedwenn keine Teilzeichenfolge vorhanden ist.

user81655
quelle
Zeichenfolgen können druckbare ASCII-Zeichen enthalten, z. B. \ oder andere RegExp-Metazeichen. Wenn Sie sich jedoch auf Firefox beschränken, warum nicht b.includesstattdessen verwenden?
Neil
@Neil Die Frage besagte nicht, dass die Zeichenfolgen zuvor beliebige Zeichen sein könnten, aber danke, dass du mich darüber informiert hast! Zur Verwendung aktualisiert includes.
user81655
1
Das Test-Snippet wirft eineSyntaxError: unexpected token 'for'
NoOneIsHere
@NoOneIsHere Dies ist der Fehler, den Sie erhalten, wenn Sie Firefox nicht verwenden ...
user81655
1

Retina , 37 Bytes

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

Die Ausgabe ist leer, wenn in keine gültige Teilzeichenfolge gefunden wird A .

Probieren Sie es online!(Leicht modifiziert, um mehrere Testfälle gleichzeitig auszuführen. Das Eingabeformat ist tatsächlich zeilenweise getrennt, aber Testsuiten lassen sich am einfachsten mit einem Testfall pro Zeile schreiben. Das Testframework verwandelt den Raum in einen Zeilenvorschub, bevor der eigentliche Code beginnt.)

Erläuterung

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

ASuchen Sie für jede mögliche Startposition in die kürzeste Unterzeichenfolge, die nicht in angezeigt wird B. Das &ist für überlappende Übereinstimmungen, so dass wir tatsächlich jede Startposition ausprobieren, auch wenn eine Übereinstimmung länger als ein Zeichen ist. Das \Gstellt sicher, dass wir keine Positionen überspringen - insbesondere müssen wir auf diese Weise beim Zeilenvorschub anhalten, damit wir keine zusätzlichen Übereinstimmungen von Bsich bekommen. Der Grund, warum dies die Dinge nicht durcheinander bringt, ist eigentlich ziemlich subtil: Wenn es eine Startposition gibt, Aan der wir keine gültigen Teilzeichenfolgen finden können, ist dies auch ein Fehler, der dazu führt, dass \Gkeine weiteren Positionen mehr überprüft werden. Wenn jedoch (ab der aktuellen Startposition) alle Teilzeichenfolgen in angezeigt werdenB , werden alle Teilzeichenfolgen, die weiter rechts von der aktuellen Position beginnen, so dass das Verwerfen dieser Teilzeichenfolgen kein Problem darstellt (und die Leistung tatsächlich verbessert).

Aufgrund der M!Konfiguration werden alle diese Übereinstimmungen zusammen mit Zeilenvorschüben von der Bühne zurückgegeben.

O$#`.+
$.&

Dadurch werden die Zeilen des vorherigen Ergebnisses nach Länge sortiert. Dies geschieht durch Abgleichen der Zeile mit .+. Dann $aktiviert eine Form von „sort-by“, so dass die Übereinstimmung mit substituierten wird $.&zur Bestimmung Sortierreihenfolge. Der $.&selbst ersetzt das Streichholz durch seine Länge. Schließlich weist die #Option Retina an, numerisch zu sortieren (andernfalls würden die resultierenden Zahlen als Zeichenfolgen behandelt und lexikografisch sortiert).

G1`

Schließlich behalten wir einfach nur die erste Zeile bei, indem wir eine grep-Stufe mit einem leeren regulären Ausdruck (der immer übereinstimmt) und einem Limit von verwenden 1.

Martin Ender
quelle
1

Perl, 87 85

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

Dies ist eine anonyme Funktion, die die erste (nach Position) der kürzesten Teilzeichenfolgen zurückgibt $_[0], die nicht in vorkommen $_[1], oder undefwenn keine solche Teilzeichenfolge vorhanden ist.

Testprogramm mit Strings aus der Antwort von @ iAmMortos, getestet mit 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');
hvd
quelle
1

Haskell, 72 Bytes

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

Anwendungsbeispiel: "abcd" # "dabc"-> "cd".

Eine unkomplizierte Implementierung: Erstellen Sie alle Teilzeichenfolgen von aund behalten Sie diejenigen bei, die nicht in angezeigt werden b. argminGibt ein Element einer Liste zurück, das die Funktion mit dem 2. Argument minimiert length.

nimi
quelle
I didn't know about argmin! It seems extremely useful.
Zgarb
0

Pyth - 9 6 bytes

h-Fm.:

Try it online here.

Maltysen
quelle
Crossed out 9 is still 9
cat
I'd love to know how this works.
mroman
@mroman the .: with one arg is all substrs. So I map that over both strings, then fold setwise diff, so I have all substrs of first that arnt of the second, then I pick the first one, which is smallest cuz .: is sorted.
Maltysen
0

C#, 152 bytes

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;}
downrep_nation
quelle
0

Ruby, 70 bytes

Collects all substrings of a certain length from the first string, and if there is one that isn't in the second string, return it.

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

Burlesque - 26 bytes

Right now the shortest way I can come up with is:

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

Japt, 14 bytes

Êõ!ãU c k!èV g

Try it online!

Returns undefined if there is no valid substring. This is distinct from returning the string "undefined", though the difference is only visible because of the -Q flag.

Explanation:

Ê                 :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
Kamil Drakari
quelle
0

Japt -h, 11 bytes

à f@øX «VøX

Try it

                :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
Shaggy
quelle