Sous-chaînes à identification unique les plus courtes

23

Étant donné une liste de chaînes, remplacez chaque chaîne par l'une de ses sous-chaînes non vides qui n'est une sous-chaîne d'aucune des autres chaînes de la liste et aussi courte que possible.

Exemple

Étant donné la liste ["hello","hallo","hola"], "hello"devrait être remplacée par juste "e"comme cette sous-chaîne n'est pas contenue dans "hallo"et "hola"est aussi courte que possible. "hallo"pourrait être remplacé soit par "ha"ou "al"et "hola"par l' une "ho", "ol"ou "la".

Règles

  • Vous pouvez supposer que les chaînes ne seront pas vides et ne contiendront que des caractères alphabétiques du même cas.
  • Vous pouvez supposer qu'une telle sous-chaîne existe pour chaque chaîne de la liste, c'est-à-dire qu'aucune chaîne de la liste ne sera une sous-chaîne de l'une des autres chaînes.
  • L'entrée et la sortie peuvent être dans n'importe quel format raisonnable.
  • Il s'agit de , essayez donc d'utiliser le moins d'octets possible dans la langue de votre choix.

Cas de test

Une seule sortie possible est donnée pour la plupart des cas.

["ppcg"] -> ["p"] (or ["c"] or ["g"])
["hello","hallo","hola"] -> ["e","ha","ho"]
["abc","bca","bac"] -> ["ab","ca","ba"]
["abc","abd","dbc"] -> ["abc","bd","db"]
["lorem","ipsum","dolor","sit","amet"] -> ["re","p","d","si","a"]
["abc","acb","bac","bca","cab","cba"] -> ["abc","acb","bac","bca","cab","cba"]

En relation: Sous - chaîne d'identification la plus courte - idée similaire, mais règles plus impliquées et format encombrant.

Laikoni
la source
Pourquoi est-ce que ""(chaîne vide) ne s'identifie pas uniquement pour le "ppcg"cas unique ?
MooseBoys
2
@MooseBoys Étant donné une liste de chaînes, remplacez chaque chaîne par l'une de ses sous- chaînes non vides
M. Xcoder

Réponses:

4

Python 2 , 116 octets

def f(a):g=lambda s,S:s not in`set(a)-{S}`[3:]and min(s,g(s[1:],S),g(s[:-1],S),key=len)or S;return[g(s,s)for s in a]

Essayez-le en ligne!

Chas Brown
la source
4

Pyth , 12 octets

mhf!ts}LTQ.:

Essayez-le ici!

Comment ça marche

Fondamentalement, filtre les sous-chaînes de chacune qui n'apparaissent que dans l'une des chaînes de la liste (c'est-à-dire qu'elle est unique à cette chaîne) et obtient la première.

mhf!ts}LTQ.:     Full program, Q=eval(stdin_input())
m         .:     Map over Q and obtain all the substrings of each.
  f              And filter-keep those that satisfy (var: T)...
      }LTQ       ... For each string in Q, yield 1 if it contains T, else 0.
   !ts           ... Sum the list, decrement and negate. 
 h               Head. Yields the first valid substring, which is always the shortest.
M. Xcoder
la source
4

Prolog (SWI) , 175 163 bytes

S/L/R:-sub_string(S,_,L,_,R).
[H|T]+[I|R]:-string_length(H,L),between(1,L,X),H/X/I,T+R.
R+R.
L-R:-L+R,forall(member(E,L),findall(_,(member(F,R),\+ \+ E/_/F),[_])).

Essayez-le en ligne!

La plupart des choses ici devraient être assez évidentes, mais:

Explication

Signatures: ( += entrée, ?= facultatif, -= sortie, := expression)

  • sub_string(+String, ?Before, ?Length, ?After, ?SubString)
  • string_length(+String, -Length)
  • member(?Elem, ?List)
  • between(+Low, +High, ?Value)
  • findall(+Template, :Goal, -Bag)
  • forall(:Cond, :Action)

\+ \+est juste not not(c.-à-d. convertit une correspondance en booléen (dans ce cas, l'empêche de faire correspondre les deux ps ppcgséparément))

ASCII uniquement
la source
Le bon outil pour le travail: P à l'exception du fait qu'il est incroyablement verbeux
ASCII uniquement
4

J , 30 29 25 octets

1(|:(0{-.&,)"_1]\.)<\\.&>

Essayez-le en ligne!

                   <\\.&>        a 3-dimensional array of substrings
1 |:                             transpose each matrix to sort the substrings by length
1              ]\.               all choices where one word is missing
    (0{-.&,)"_1                  for every matrix, flatten, remove substrings
                                  that are present in the corresponding complement,
                                  pick first
FrownyFrog
la source
3

JavaScript (ES6), 93 octets

a=>a.map(s=>(L=s.length,g=n=>a.every(S=>S==s|!~S.search(u=s.substr(n%L,n/L+1)))?u:g(n+1))(0))

Essayez-le en ligne!

Comment?

Pour chaque chaîne s de longueur L dans le tableau d'entrée a [] et en commençant par n = 0 , nous utilisons la fonction récursive g () pour générer toutes les sous-chaînes u de s avec:

u = s.substr(n % L, n / L + 1)

Par exemple, avec s = "abc" et L = 3 :

 n | n%L | floor(n/L+1) | u
---+-----+--------------+-------
 0 |  0  |       1      | "a"
 1 |  1  |       1      | "b"
 2 |  2  |       1      | "c"
 3 |  0  |       2      | "ab"
 4 |  1  |       2      | "bc"
 5 |  2  |       2      | "c"
 6 |  0  |       3      | "abc"
 7 |  1  |       3      | "bc"
 8 |  2  |       3      | "c"

Certaines sous-chaînes sont générées plusieurs fois, mais cela n'a pas d'importance. Ce qui est important, c'est que toutes les sous-chaînes de longueur N ont été générées avant toute sous-chaîne de longueur N + 1 .

Nous arrêtons le processus dès que u ne peut être trouvé dans aucune autre chaîne S dans un [] , ce qui est garanti de se produire lorsque u == s dans le pire des cas, conformément à la règle de défi n ° 2:

aucune chaîne dans la liste ne sera une sous-chaîne de l'une des autres chaînes

Par conséquent, dans l'exemple ci-dessus, les étapes 7 et 8 ne seront en fait jamais traitées.

Arnauld
la source
2

PowerShell , 107 octets

($a=$args)|%{$(for($i=0;$i++-lt($g=($s=$_)|% Le*)){0..($g-$i)|%{$s|% s*g $_ $i}|?{!($a-match$_-ne$s)}})[0]}

Essayez-le en ligne!

Explication

Pour chaque chaîne fournie (et affectez l'ensemble du tableau à $a):

  • Faire une forboucle sur chaque longueur de sous-chaîne (basée sur 1) de la chaîne (en affectant la chaîne elle-même $set la longueur à $g)
  • Pour chaque longueur ( $i):
    • Faites une boucle d'index, de 0 à la longueur - $i, puis pour chaque index:
      • Récupère la sous-chaîne de la chaîne courante ( $s) en position $_(index) et de longueur$i
      • Passez cette sous-chaîne à Where-Object( ?) et retournez-la si:
        • Le sous-ensemble de array ( $a) qui ne contient pas la chaîne actuelle $s, n'a pas de correspondance avec la sous-chaîne actuelle$_

De retour au niveau de la chaîne, nous avons toutes les sous-chaînes de cette chaîne qui n'ont pas été trouvées dans les autres, alors prenez la première [0]car nous n'en avons besoin que d'une, puis passez à la chaîne suivante.

briantiste
la source
0

C # (Visual C # Interactive Compiler) , 149 octets

a=>a.Select(s=>{var t=s;for(int j=0,k,l=s.Length;j++<l;)for(k=-1;j+k++<l;)if(!a.Where(u=>s!=u&u.Contains(t=s.Substring(k,j))).Any())j=k=l;return t;})

Essayez-le en ligne!

Moins golfé ...

// a is an input array of strings
a=>
  // iterate over input array   
  a.Select(s=>{
    // t is the result string
    var t=s;
    // j is the substring length
    for(int j=0,k,l=s.Length;j++<l;)
      // k is the start index
      for(k=-1;j+k++<l;)
        // LINQ query to check if substring is valid
        // the tested string is collected in t
        if(!a.Where(u=>s!=u&u.Contains(t=s.Substring(k,j))).Any())
          // break loops
          j=k=l;
    // return result
    return t;
  })
dana
la source