Sottostringa unica più corta


14

Dato (su STDIN, come argomenti della riga di comando o come argomenti della funzione) due stringhe non vuote distinte, trova e restituisce la sottostringa più corta della prima stringa che non è una sottostringa della seconda. Se tale sottostringa non esiste, è possibile restituire la stringa vuota, restituire qualsiasi stringa che non sia una sottostringa della stringa originale o generare un'eccezione. Se si ritorna da una funzione, in questo caso è anche possibile restituire null (o indefinito, Nessuno, ecc.). Se più di tali sottostringhe sono legate per il più corto, è possibile restituire una qualsiasi di esse.

Le stringhe possono essere costituite da qualsiasi carattere ASCII stampabile.

L'input dato su STDIN verrà dato con una stringa su ogni riga. Su richiesta, è possibile aggiungere una sola riga vuota alla fine dell'input.

Questo è il codice golf, quindi vince il programma valido più breve.

ALCUNI CASI DI PROVA

INGRESSO:

STRING ONE
STRING TWO

PRODUZIONE:

E

INGRESSO:

A&&C
A&$C

USCITE VALIDE:

&&
&C

INGRESSO:

(Due stringhe di 80 lettere generate casualmente)

QIJYXPYWIWESWBRFWUHEERVQFJROYIXNKPKVDDFFZBUNBRZVUEYKLURBJCZJYMINCZNQEYKRADRYSWMH
HAXUDFLYFSLABUCXUWNHPSGQUXMQUIQYRWVIXGNKJGYUTWMLLPRIZDRLFXWKXOBOOEFESKNCUIFHNLFE

TUTTE LE USCITE VALIDE:

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
più corto o più lungo?
Leaky Nun,

@FryAmTheEggman Quindi dovrei ancora pubblicare la mia soluzione ...
Leaky Nun

"Una stringa su ogni riga" con o senza virgolette?
Leaky Nun,

1
Possiamo prendere una serie di stringhe?
Dennis,

"B" è una sottostringa di "aBc"?
downrep_nation

Risposte:


4

Brachylog , 23 byte

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

Funziona sul vecchio transpiler Java. Prevede le due stringhe in un elenco come input, unifica l'output con la sottostringa. Se non viene rilevata alcuna sottostringa, restituisce false.

Purtroppo non ho ancora codificato il sottoinsieme incorporato nel nuovo transpiler Prolog.

Spiegazione

: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

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]

Casi test:

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

Sto lavorando per renderlo più breve, ma questo è il mio istinto cerebrale. Non è ancora un gran giocatore di golf.

Grazie a @ user81655 e @NonlinearFruit per i byte extra.

Modifica :

Dang. Ho provato questo codice:

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

Ho pensato che fosse più corto di qualche byte. Si è scoperto che era 1 byte più lungo di quello che avevo prima della modifica.


Non conosco molto Python, ma forse puoi farlo (r=range)(1,len(a)+1)quindi usare r?
Conor O'Brien,

@ CᴏɴᴏʀO'Bʀɪᴇɴ Non posso farlo in questo modo. Se assegno rangealla rnella riga sopra, si aggiunge in realtà un byte. Buona idea, comunque. C'è probabilmente un modo più breve per scorrere le sottostringhe.
Taylor Lopez,

range(1,len(a))e range(len(a)-1)dovrebbe funzionare non dovrebbe? Inoltre penso che l'uso di un carattere di tabulazione per il rientro dei due spazi salverebbe un byte.
user81655

No, con range(1,len(a)), il 4 ° cast di test fallisce perché non proverà l'intera stringa; andrà solo alla lunghezza della stringa - 1. E con range(len(a)-1), il primo caso di test non ritorna 'cd'invece di solo 'd'. Potrebbe esserci qualcosa lì, però.
Taylor Lopez,

Spiacenti, non ho familiarità con Python e ho ipotizzato che le gamme fossero inclusive. In tal caso, prova range(1,len(a)+1)e range(len(a)).
user81655

3

Python, 87 86 byte

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]

Se esiste, questo restituirà la sottostringa unica più corta a sinistra.

Se non è presente alcuna sottostringa univoca, viene generato un IndexError .

Provalo su Ideone .


Eccolo. Stavo aspettando che qualcuno uccidesse la mia implementazione non-lambda. bello lol
Taylor Lopez

Penso che si possa fare questa breve fornendo il secondo argomento opzionale per enumerateper iniziare ja i+1.
user2357112 supporta Monica il

@ user2357112 Questo sfortunatamente genera un NameError . Il codice definisce jprima, quindi i.
Dennis,

@Dennis: Sì, ma non è necessario. È possibile cambiare l'ordine dei loop.
user2357112 supporta Monica il

1
@ user2357112 Se cambio l'ordine del loop, la prima sottostringa unica che trova potrebbe non essere la più breve. Semplicemente scambiando i ritorni dell'ordine 'ab'per l'input 'abc','aaa'.
Dennis,

2

Python, 82 byte

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

Utilizzo: f('A&&C', 'A&$C')-> ritorna'&&'

Aumenta ValueError se non esiste una sottostringa adatta.

Spiegazione:

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}crea in modo ricorsivo un insieme di sottostringhe di u f=lambda s,t:min(g(s)-g(t),key=len)prende la sottostringa più corta dalla differenza di insieme


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>

Se la restituzione falseè accettabile, salvare 2 byte utilizzando &&sinvece di ?s:''.



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

Il test funziona solo in Firefox. Restituisce undefinedse non è presente alcuna sottostringa.


Le stringhe potrebbero contenere caratteri ASCII stampabili come \ o altri metacaratteri RegExp, ma se ti stai limitando a Firefox, perché non utilizzare b.includesinvece?
Neil,

@Neil La domanda non ha detto che le stringhe potrebbero essere qualsiasi personaggio prima, ma grazie per avermelo fatto notare! Aggiornato per l'uso includes.
user81655

1
Lo snippet di test genera unSyntaxError: unexpected token 'for'
NoOneIsHere

@NoOneIsHere Questo è l'errore che otterrai se non stai utilizzando Firefox ...
user81655

1

Retina , 37 byte

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

L'output è vuoto se non viene trovata alcuna sottostringa valida A .

Provalo online!(Leggermente modificato per eseguire diversi casi di test contemporaneamente. Il formato di input è in realtà separato dall'alimentazione di riga, ma le suite di test sono più facili da scrivere con un caso di test per riga. Il framework di test trasforma lo spazio in un avanzamento di riga prima dell'inizio del codice effettivo.)

Spiegazione

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

Per ogni possibile posizione iniziale in A, abbinare la sottostringa più corta in cui non appare B. Il &è per sovrapposizione di partite, in modo tale che abbiamo effettivamente provare ogni posizione di partenza, anche se una partita è più lungo di un carattere. Le \Gassicura che non saltare nessuna posizione - in particolare, in questo modo dobbiamo fermata al avanzamento, in modo tale che non otteniamo corrispondenze aggiuntive da Bsé. Il motivo per cui questo non rovina le cose è in realtà abbastanza sottile: perché se c'è una posizione di partenza in Acui non possiamo trovare alcuna sottostringa valida, anche questo è un errore che causerà \Gl'interruzione del controllo di ulteriori posizioni. Tuttavia, se (dalla posizione iniziale corrente) compaiono tutte le sottostringheB, così anche tutte le sottostringhe che iniziano più a destra della posizione corrente, quindi scartarle non è un problema (e migliora effettivamente le prestazioni).

A causa della M!configurazione, tutte queste partite verranno restituite dal palco, unite con avanzamenti di riga.

O$#`.+
$.&

Questo ordina le linee del risultato precedente per lunghezza. Questo viene fatto abbinando la linea con .+. Quindi $attiva una forma di "ordinamento", in modo che la corrispondenza venga sostituita $.&per determinare l'ordinamento. Lo $.&stesso sostituisce la partita con la sua lunghezza. Infine, l' #opzione dice a Retina di ordinare numericamente (altrimenti, tratterà i numeri risultanti come stringhe e li ordinerebbe lessicograficamente).

G1`

Infine, manteniamo semplicemente solo la prima riga, usando uno stage grep con una regex vuota (che corrisponde sempre) e un limite di 1.


1

Perl, 87 85

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

Questa è una funzione anonima che restituisce la prima (per posizione) delle sottostringhe più corte in $_[0]cui non si verificano $_[1]o undefse non esiste tale sottostringa.

Programma di test con stringhe tratte dalla risposta di @ iAmMortos, testato con 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 byte

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

Esempio di utilizzo: "abcd" # "dabc"-> "cd".

Un'implementazione semplice: costruisci tutte le sottostringhe ae mantieni quelle che non appaiono b. argminrestituisce un elemento di una lista che minimizza la funzione dato un 2 ° argomento, qui: length.


Non lo sapevo argmin! Sembra estremamente utile.
Zgarb,

0

Pyth - 9 6 byte

h-Fm.:

Provalo online qui .


Crossed 9 è ancora 9
cat

Mi piacerebbe sapere come funziona.
mroman,

@mroman the.: con un arg sono tutti i substr. Quindi lo mappa su entrambe le stringhe, quindi piega tra diff, quindi ho tutti i substrati del primo che non sono del secondo, quindi scelgo il primo, che è il più piccolo perché: è ordinato.
Maltysen,

0

C #, 152 byte

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

Rubino, 70 byte

Raccoglie tutte le sottostringhe di una certa lunghezza dalla prima stringa e, se ce n'è una che non si trova nella seconda stringa, restituirla.

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

0

Burlesque - 26 byte

In questo momento il modo più breve che posso trovare è:

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

0

Japt , 14 byte

Êõ!ãU c k!èV g

Provalo online!

Restituisce undefinedse non esiste una sottostringa valida . Ciò è distinto dal ritorno della stringa "non definita" , sebbene la differenza sia visibile solo a causa del flag -Q.

Spiegazione:

Ê                 :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 byte

à f@øX «VøX

Provalo

                :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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.