Subcadena única más corta

14

Dado (en STDIN, como argumentos de línea de comando o como argumentos de función) dos cadenas distintas no vacías, encuentre y devuelva la subcadena más corta de la primera cadena que no es una subcadena de la segunda. Si no existe tal subcadena, puede devolver la cadena vacía, devolver cualquier cadena que no sea una subcadena de la cadena original o lanzar una excepción. Si regresa de una función, también puede devolver nulo (o indefinido, Ninguno, etc.) en este caso. Si varias de estas subcadenas están vinculadas por la más corta, puede devolver cualquiera de ellas.

Las cadenas pueden consistir en cualquier carácter ascii imprimible.

La entrada dada en STDIN se dará con una cadena en cada línea. A petición suya, se puede agregar una sola línea vacía al final de la entrada.

Este es el código de golf, por lo que gana el programa válido más corto.

ALGUNOS CASOS DE PRUEBA

ENTRADA:

STRING ONE
STRING TWO

SALIDA:

E

ENTRADA:

A&&C
A&$C

SALIDAS VÁLIDAS:

&&
&C

ENTRADA:

(Dos cadenas de 80 letras generadas al azar)

QIJYXPYWIWESWBRFWUHEERVQFJROYIXNKPKVDDFFZBUNBRZVUEYKLURBJCZJYMINCZNQEYKRADRYSWMH
HAXUDFLYFSLABUCXUWNHPSGQUXMQUIQYRWVIXGNKJGYUTWMLLPRIZDRLFXWKXOBOOEFESKNCUIFHNLFE

TODAS LAS SALIDAS VÁLIDAS:

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
fuente
1
más corto o más largo?
Leaky Nun
@FryAmTheEggman Entonces aún debería publicar mi solución ...
Leaky Nun
¿"Una cadena en cada línea" con o sin comillas?
Leaky Nun
1
¿Podemos tomar una serie de cadenas?
Dennis
¿Es "B" una subcadena de "aBc"?
downrep_nation

Respuestas:

4

Brachylog , 23 bytes

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

Funciona en el antiguo transpiler de Java. Espera las dos cadenas en una lista como entrada, unifica la salida con la subcadena. Si no se encuentra ninguna subcadena, devuelve falso.

Lamentablemente, todavía no he codificado el subconjunto integrado en el nuevo transpiler de Prolog.

Explicación

: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
               }
Fatalizar
fuente
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]

Casos de prueba:

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

Trabajando para hacerlo más corto, pero este es mi instinto cerebral. Realmente no soy un gran golfista todavía.

Gracias a @ user81655 y @NonlinearFruit por los bytes adicionales.

Editar :

Dang Probé este código:

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

Pensé que era unos pocos bytes más cortos. Resulta que fue 1 byte más de lo que tenía antes de la edición.

Taylor Lopez
fuente
No sé mucho de Python, pero ¿tal vez puedas (r=range)(1,len(a)+1)usarlo r?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ No puedo hacerlo de esa manera. Si asigno rangea ren la línea anterior, en realidad agrega un byte. Buena idea, sin embargo. Probablemente haya una forma más corta de recorrer las subcadenas.
Taylor Lopez
range(1,len(a))y range(len(a)-1)debería funcionar, ¿no? También creo que usar un carácter de tabulación para la sangría de dos espacios ahorraría un byte.
user81655
No, con range(1,len(a)), el 4to elenco de prueba falla porque no intentará la cadena completa; solo irá a la longitud de la cadena: 1. Y con range(len(a)-1), el primer caso de prueba no regresa en 'cd'lugar de solo 'd'. Sin embargo, puede haber algo allí.
Taylor Lopez
Lo siento, no estoy familiarizado con Python y supuse que los rangos eran inclusivos. En ese caso intente range(1,len(a)+1)y 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]

Si existe, devolverá la subcadena más corta más a la izquierda de todas.

Si no hay una subcadena única, se genera un IndexError .

Pruébelo en Ideone .

Dennis
fuente
Ahí está. Estaba esperando que alguien matara mi implementación no lambda. nice lol
Taylor Lopez
Creo que se puede hacer de este corto suministrando el segundo argumento opcional que enumeratepara empezar ja i+1.
user2357112 es compatible con Monica el
@ user2357112 Eso arroja un NameError , desafortunadamente. El código define jprimero, luego i.
Dennis
@ Dennis: Sí, pero no es necesario. Podrías cambiar el orden del bucle.
user2357112 es compatible con Monica el
1
@ user2357112 Si cambio el orden del bucle, la primera subcadena única que encuentre puede no ser la más corta. Simplemente intercambiando el pedido devuelve 'ab'por entrada '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)

Uso: f('A&&C', 'A&$C')-> devoluciones'&&'

Aumenta ValueError si no hay una subcadena adecuada.

Explicación:

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}crea recursivamente un conjunto de las subcadenas de u f=lambda s,t:min(g(s)-g(t),key=len)toma la subcadena más corta de la diferencia del conjunto

RootTwo
fuente
2

JavaScript (ES6), 79 bytes

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>

Si la devolución falsees aceptable, guarde 2 bytes utilizando en &&slugar de ?s:''.

Neil
fuente
1

JavaScript (Firefox), 80 bytes

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

La prueba solo funciona en Firefox. Devuelve undefinedsi no hay una subcadena.

usuario81655
fuente
Las cadenas pueden contener caracteres ASCII imprimibles como \ u otros metacaracteres RegExp, pero si se limita a Firefox, ¿por qué no usarlo b.includes?
Neil
@Neil La pregunta no decía que las cadenas podrían ser de cualquier carácter antes, pero gracias por hacérmelo saber. Actualizado para usar includes.
user81655
1
El fragmento de prueba arroja unSyntaxError: unexpected token 'for'
NoOneIsHere
@NoOneIsHere Ese es el error que obtendrá si no está usando Firefox ...
user81655
1

Retina , 37 bytes

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

La salida está vacía si no se encuentra una subcadena válida A.

Pruébalo en línea! (Ligeramente modificado para ejecutar varios casos de prueba a la vez. El formato de entrada en realidad está separado por salto de línea, pero las suites de prueba son más fáciles de escribir con un caso de prueba por línea. El marco de prueba convierte el espacio en un salto de línea antes de que comience el código real).

Explicación

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

Para cada posible posición inicial en A, coincida con la subcadena más corta que no aparece en B. El &es para coincidencias superpuestas, de modo que en realidad probamos todas las posiciones iniciales, incluso si una coincidencia es más larga que un personaje. Esto \Ggarantiza que no omitimos ninguna posición, en particular, de esta manera tenemos que parar en el salto de línea, de modo que no obtengamos coincidencias adicionales de Bsí mismo. La razón por la que esto no arruina las cosas es bastante sutil: porque si hay una posición inicial en la Aque no podemos encontrar ninguna subcadena válida, entonces también es una falla que hará \Gque deje de verificar otras posiciones. Sin embargo, si (desde la posición inicial actual) todas las subcadenas aparecen enB, también lo harán todas las subcadenas que comienzan más a la derecha de la posición actual, por lo que descartarlas no es un problema (y en realidad mejora el rendimiento).

Debido a la M!configuración, todos estos partidos serán devueltos desde el escenario, unidos con saltos de línea.

O$#`.+
$.&

Esto ordena las líneas del resultado anterior por longitud. Esto se hace haciendo coincidir la línea con .+. Luego $activa una forma de "ordenar por", de modo que la coincidencia se sustituye $.&por la determinación del orden de clasificación. El $.&mismo reemplaza el partido con su longitud. Finalmente, la #opción le dice a Retina que ordene numéricamente (de lo contrario, trataría los números resultantes como cadenas y los ordenaría lexicográficamente).

G1`

Finalmente, simplemente mantenemos solo la primera línea, usando una etapa grep con una expresión regular vacía (que siempre coincide) y un límite de 1.

Martin Ender
fuente
1

Perl 87 85

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

Esta es una función anónima que devuelve la primera (por posición) de las subcadenas más cortas de las $_[0]que no se producen $_[1], o undefsi no existe dicha subcadena.

Programa de prueba con cadenas tomadas de la respuesta de @ iAmMortos, probado 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');
hvd
fuente
1

Haskell, 72 bytes

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

Ejemplo de uso: "abcd" # "dabc"-> "cd".

Una implementación sencilla: compila todas las subcadenas ay conserva las que no aparecen b. argmindevuelve un elemento de una lista que minimiza la función dada a El segundo argumento, aquí: length.

nimi
fuente
¡No lo sabía argmin! Parece extremadamente útil.
Zgarb
0

Pyth - 9 6 bytes

h-Fm.:

Pruébelo en línea aquí .

Maltysen
fuente
Tachado 9 sigue siendo 9
gato
Me encantaría saber cómo funciona esto.
mroman
@mroman the.: con un argumento es todo substrs. Así que mapeo eso sobre ambas cadenas, luego doblo setwise diff, por lo que tengo todos los substrs de primero ese arnt del segundo, luego elijo el primero, que es el más pequeño porque: está ordenado.
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
fuente
0

Ruby, 70 bytes

Recopila todas las subcadenas de una cierta longitud de la primera cadena, y si hay una que no está en la segunda cadena, devuélvala.

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

Burlesque - 26 bytes

En este momento, la forma más corta que puedo encontrar es:

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

Japt , 14 bytes

Êõ!ãU c k!èV g

Pruébalo en línea!

Devuelve undefinedsi no hay una subcadena válida . Esto es distinto de devolver la cadena "indefinida" , aunque la diferencia solo es visible debido al indicador -Q.

Explicación:

Ê                 :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
fuente
0

Japt -h, 11 bytes

à f@øX «VøX

Intentalo

                :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
Lanudo
fuente