Sous-chaîne unique la plus courte


14

Étant donné (sur STDIN, en tant qu'arguments de ligne de commande ou arguments de fonction) deux chaînes distinctes non vides, recherchez et renvoyez la sous-chaîne la plus courte de la première chaîne qui n'est pas une sous-chaîne de la seconde. Si une telle sous-chaîne n'existe pas, vous pouvez renvoyer la chaîne vide, renvoyer toute chaîne qui n'est pas une sous-chaîne de la chaîne d'origine ou lever une exception. Si vous revenez d'une fonction, vous pouvez également retourner null (ou non défini, Aucun, etc.) dans ce cas. Si plusieurs de ces sous-chaînes sont liées pour la plus courte, vous pouvez renvoyer l'une d'entre elles.

Les chaînes peuvent être constituées de n'importe quel caractère ascii imprimable.

L'entrée donnée sur STDIN sera donnée avec une chaîne sur chaque ligne. À votre demande, une seule ligne vide peut être ajoutée à la fin de la saisie.

C'est le golf de code, donc le programme valide le plus court gagne.

QUELQUES CAS D'ESSAI

CONTRIBUTION:

STRING ONE
STRING TWO

PRODUCTION:

E

CONTRIBUTION:

A&&C
A&$C

SORTIES VALIDES:

&&
&C

CONTRIBUTION:

(Deux chaînes de 80 lettres générées aléatoirement)

QIJYXPYWIWESWBRFWUHEERVQFJROYIXNKPKVDDFFZBUNBRZVUEYKLURBJCZJYMINCZNQEYKRADRYSWMH
HAXUDFLYFSLABUCXUWNHPSGQUXMQUIQYRWVIXGNKJGYUTWMLLPRIZDRLFXWKXOBOOEFESKNCUIFHNLFE

TOUTES LES SORTIES VALIDES:

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
le plus court ou le plus long?
Leaky Nun

@FryAmTheEggman Alors dois-je quand même poster ma solution ...
Leaky Nun

"Une chaîne sur chaque ligne" avec ou sans guillemets?
Leaky Nun

1
Pouvons-nous prendre un tableau de chaînes?
Dennis

"B" est-il une sous-chaîne de "aBc"?
downrep_nation

Réponses:


4

Brachylog , 23 octets

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

Fonctionne sur l'ancien transpilateur Java. Attend les deux chaînes d'une liste en entrée, unifie la sortie avec la sous-chaîne. Si aucune sous-chaîne n'est trouvée, renvoie false.

Malheureusement, je n'ai pas encore codé le sous-ensemble intégré dans le nouveau transpilateur Prolog.

Explication

: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]

Cas de test:

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

Travailler à le raccourcir, mais c'est mon instinct cérébral. Pas encore vraiment un golfeur.

Merci à @ user81655 et @NonlinearFruit pour les octets supplémentaires.

Modifier :

Dang. J'ai essayé ce 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''

Je pensais que c'était plus court de quelques octets. Il s'avère que c'était 1 octet de plus que ce que j'avais avant l'édition.


Je ne connais pas beaucoup de python, mais peut-être pouvez-vous (r=range)(1,len(a)+1)alors utiliser r?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Je ne peux pas faire ça de cette façon. Si j'assigne rangeà rdans la ligne ci-dessus, cela ajoute en fait un octet. Bonne idée cependant. Il existe probablement un moyen plus court pour parcourir les sous-chaînes.
Taylor Lopez

range(1,len(a))et range(len(a)-1)devrait fonctionner non? Je pense également que l'utilisation d'un caractère de tabulation pour le retrait de deux espaces permettrait d'économiser un octet.
user81655

Non, avec range(1,len(a)), le 4ème cast de test échoue car il n'essaiera pas la chaîne complète; cela ira seulement à la longueur de la chaîne - 1. Et avec range(len(a)-1), le 1er cas de test ne retourne pas 'cd'au lieu de juste 'd'. Mais il y a peut-être quelque chose là-dedans.
Taylor Lopez

Désolé, je ne connais pas Python et j'ai supposé que les plages étaient inclusives. Dans ce cas , essayez range(1,len(a)+1)et range(len(a)).
user81655

3

Python, 87 86 octets

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]

S'il existe, cela renverra la plus à gauche de toutes les sous-chaînes uniques les plus courtes.

S'il n'y a pas de sous-chaîne unique, une IndexError est déclenchée .

Testez-le sur Ideone .


Le voilà. J'attendais que quelqu'un tue mon implémentation non lambda. nice lol
Taylor Lopez

Je pense que vous pouvez faire ce court en fournissant le second argument optionnel pour enumeratecommencer jà i+1.
user2357112 prend en charge Monica

@ user2357112 Cela jette malheureusement une NameError . Le code définit d' jabord, ensuite i.
Dennis

@ Dennis: Oui, mais ce n'est pas nécessaire. Vous pouvez changer l'ordre des boucles.
user2357112 prend en charge Monica

1
@ user2357112 Si je change l'ordre des boucles, la première sous-chaîne unique qu'il trouve peut ne pas être la plus courte. Échangez simplement les retours de commande 'ab'pour entrée 'abc','aaa'.
Dennis

2

Python, 82 octets

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

Utilisation: f('A&&C', 'A&$C')-> retourne'&&'

Déclenche ValueError s'il n'y a pas de sous-chaîne appropriée.

Explication:

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}crée récursivement un ensemble de sous-chaînes de u f=lambda s,t:min(g(s)-g(t),key=len)prend la sous-chaîne la plus courte de la différence d'ensemble


2

JavaScript (ES6), 79 octets

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 le retour falseest acceptable, enregistrez 2 octets en utilisant &&sau lieu de ?s:''.



1

JavaScript (Firefox), 80 octets

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

Le test ne fonctionne que dans Firefox. Renvoie undefineds'il n'y a pas de sous-chaîne.


Les chaînes peuvent contenir des caractères ASCII imprimables tels que \ ou d'autres métacaractères RegExp, mais si vous vous limitez à Firefox, pourquoi ne pas les utiliser à la b.includesplace?
Neil

@Neil La question ne disait pas que les cordes pouvaient être n'importe quel personnage auparavant mais merci de me le faire savoir! Mis à jour à utiliser includes.
user81655

1
L'extrait de test jette unSyntaxError: unexpected token 'for'
NoOneIsHere

@NoOneIsHere C'est l'erreur que vous obtiendrez si vous n'utilisez pas Firefox ...
user81655

1

Rétine , 37 octets

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

La sortie est vide si aucune sous-chaîne valide n'est trouvée dans A .

Essayez-le en ligne!(Légèrement modifié pour exécuter plusieurs cas de test à la fois. Le format d'entrée est en fait séparé par saut de ligne, mais les suites de tests sont plus faciles à écrire avec un cas de test par ligne. Le cadre de test transforme l'espace en saut de ligne avant le début du code réel.)

Explication

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

Pour chaque position de départ possible A , faites correspondre la sous-chaîne la plus courte qui n'apparaît pas dans B. C'est &pour les correspondances qui se chevauchent, de sorte que nous essayons en fait chaque position de départ, même si une correspondance est plus longue qu'un caractère. Les \Gassure que nous ne sautez pas de positions - cette façon , nous avons notamment l' arrêt au saut de ligne, de sorte que nous ne recevons pas les matchs supplémentaires de Blui - même. La raison pour laquelle cela ne gâche pas les choses est en fait assez subtile: car s'il y a une position de départ dans Alaquelle nous ne pouvons pas trouver de sous-chaîne valide, c'est également un échec qui entraînera l' \Garrêt de la vérification de toute autre position. Cependant, si (à partir de la position de départ actuelle) toutes les sous-chaînes apparaissent dansB, il en sera de même pour toutes les sous-chaînes qui commencent plus à droite de la position actuelle, donc leur suppression n'est pas un problème (et améliore en fait les performances).

En raison de M! configuration, tous ces matchs seront renvoyés de la scène, joints à des sauts de ligne.

O$#`.+
$.&

Cela trie les lignes du résultat précédent par longueur. Cela se fait en faisant correspondre la ligne avec .+. $Active ensuite une forme de "tri par", de telle sorte que la correspondance soit remplacée par $.&pour déterminer l'ordre de tri. Le $.&lui-même remplace le match par sa longueur. Enfin, l' #option indique à Retina de trier numériquement (sinon, elle traiterait les nombres résultants comme des chaînes et les trierait lexicographiquement).

G1`

Enfin, nous ne gardons que la première ligne, en utilisant une étape grep avec une expression rationnelle vide (qui correspond toujours) et une limite de 1 .


1

Perl, 87 85

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

Il s'agit d'une fonction anonyme qui renvoie la première (par position) des sous-chaînes les plus courtes $_[0]qui ne se produisent pas dans $_[1], ou undefsi aucune sous-chaîne n'existe.

Programme de test avec des chaînes tirées de la réponse de @ iAmMortos, testé avec 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 octets

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

Exemple d'utilisation: "abcd" # "dabc"-> "cd".

Une implémentation simple: créez toutes les sous-chaînes de aet conservez celles qui n'apparaissent pas dans b. argminretourne un élément d'une liste qui minimise la fonction donnée un 2ème argument ici: length.


Je ne savais rien argmin! Cela semble extrêmement utile.
Zgarb

0

Pyth - 9 6 octets

h-Fm.:

Essayez-le en ligne ici .


Barré 9 est toujours 9
chat

J'adorerais savoir comment cela fonctionne.
mroman

@mroman the.: avec un arg est tous les substrs. Donc, je mappe cela sur les deux chaînes, puis plie le diff setwise, donc j'ai tous les substrs du premier qui ne sont pas du second, puis je choisis le premier, qui est le plus petit cuz.: Est trié.
Maltysen

0

C #, 152 octets

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

Rubis, 70 octets

Collecte toutes les sous-chaînes d'une certaine longueur de la première chaîne, et s'il y en a une qui n'est pas dans la deuxième chaîne, renvoyez-la.

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

En ce moment, le moyen le plus court que je peux trouver est:

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

0

Japt , 14 octets

Êõ!ãU c k!èV g

Essayez-le en ligne!

Renvoie undefineds'il n'y a pas de sous-chaîne valide . Ceci est différent du renvoi de la chaîne "non définie" , bien que la différence ne soit visible qu'en raison de l'indicateur -Q.

Explication:

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

à f@øX «VøX

Essayez-le

                :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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.