Teste se uma string pode ser criada com substrings!

23

Dada uma sequência se uma matriz / lista l, determine se é spossível criar ou não partes com l.

Por exemplo, se a cadeia é "Hello, world!"e a lista é [' world!', 'Hello,'], o programa / função deve retornar um valor verdadeiro, porque você pode organizar a lista para formar a cadeia. A lista a seguir também retornar um valor truthy: ['l', 'He', 'o, wor', 'd!']. Imagine o 'l'preenchimento onde ele precisa. Então, sim, você pode repetir elementos da lista para formar a sequência. Se não conseguir formar a sequência, retornará um valor falso. Métodos padrão de IO, lacunas padrão se aplicam.

Casos de teste:

Input (In the form of s, l)
Output (1 if possible, 0 if impossible)

"Hello, world!", ["l", "He", "o, wor", "d!"]
1

"la lal al ", ["la", " l", "al "]
1

"this is a string", ["this should return falsy"]
0

"thi is a string", ["this", "i i", " a", " string"]
0

"aaaaa", ["aa"]
0

"foo bar foobar", ["foo", "bar", " ", "spam"]
1

"ababab", ["a","ba","ab"]
1

"", ["The string can be constructed with nothing!"]
1
Camarada SparklePony
fonte
Importa se a matriz contém mais seqüências do que o necessário para construir a sequência principal?
Shaggy
Qual deve ser o valor de retorno nesses casos?
Shaggy
@Shaggy Truthy. Se houver mais, a cadeia poderá ser construída com todas as partes não extras. Vou adicionar um caso de teste.
precisa saber é o seguinte
3
Eu recomendo adicionar este caso de teste:"ababab", ["a","ba","ab"]
math junkie
3
Eu sugiro que você adicione um caso de teste contendo metacaracteres regex.
Joey

Respostas:

11

Braquilog , 8 bytes

~c¬{∋¬∈}

Experimente online!

Isso é realmente lento. Demorou cerca de 37 segundos para o "Olá, mundo!" teste no meu PC e o tempo limite expirou no TIO.

Isso leva a string pela variável Input e a lista pela variável Output

Explicação

             String = ?, List = .

             It is possible to find…
~c           …a deconcatenation of ?…
  ¬{   }     …such that it is impossible…
    ∋¬∈      …that an element of that deconcatenation is not an element of .
Fatalizar
fonte
"la lal al" mais de 60 segundos ...
RosLuP 28/04
1
@RosLuP Com esta entrada e ["la", " l", "al "]como lista, ela terminou no meu computador e respondeu corretamente false.após 6800 segundos e "apenas" 113 bilhões de inferências.
Fatalize
Eu sinto que escrever qualquer coisa nesse idioma resultaria em um programa não executável no TIO haha.
Magic Octopus Urn
@carusocomputing A linguagem não é tão lenta para a maioria dos programas, é apenas que, em alguns casos, devido à declaratividade do programa, resulta em tempos de execução muito muito lentos (que podem ser melhorados drasticamente com o custo do tamanho do código)
Fatalize
@ Erro fatalizar ... eu quis dizer que o golfe não está escrevendo, parece que quanto menos instruções, mais ampla a "pergunta" se torna e mais cálculos você precisa. Parece uma linguagem impressionante para problemas de matemática teóricos.
Urna de polvo mágico
7

Mathematica, 29 bytes

StringMatchQ[#,""|##&@@#2..]&

Explicação:

             #,               (* The first argument *)
StringMatchQ[                 (* matches the string pattern *)
               ""|##&         (*   Alternatives *)
                     @@       (*     applied to *)
                       #2     (*     the second argument *)
                         ..   (*   repeated *)
                           ]&

Solução de trapaça nas fronteiras, 21 bytes

StringMatchQ[#,#2..]&

Como o Mathematica é uma linguagem de programação simbólica, não há * diferença entre as expressões List[a,b,...]e Alternatives[a,b,...]outras além de como elas interagem com outros símbolos e como são exibidas ( {a,b,...}e a|b|..., respectivamente). Quando usada no segundo argumento de StringMatchQ, uma Alternativesexpressão é tratada como um padrão de cadeia e, portanto, podemos salvar 8bytes sobre a minha solução acima, usando o segundo argumento como uma Alternativesexpressão.

* Tecnicamente Listé também Locked, o que impede os usuários de Unprotectalterá-lo e alterar seu comportamento.

ngenisis
fonte
1
{x,y,z}é tratado da mesma forma que x|y|zna correspondência de padrões de sequência. Eu acho que você pode substituir ""|##&@@#2..por apenas #2...
Não é uma árvore
5

Pitão, 23 bytes

AQW&GhGJ.(G0Vf!xJTH aG>JlN;G

Toma entrada como [['string'],['list', 'of', 'parts']]. A saída é uma lista vazia ou uma lista com valores internos. No Pyth, uma lista contendo qualquer coisa, mesmo uma string nula ( ['']), é avaliada como verdadeira.

Experimente online!

Explicação:

                             | Implicit: Q = eval(input())
AQ                           | Assign the first value of Q to G and the second to H
  W&GhG                      | While G is not empty and G doesn't contain an empty string:
       J.(G0                 |  Pop the first value of G and store into J
            Vf!xJTH          |  For N in elements in H that match the beginning of J:
                             |   Additional space for suppressing printing 
                    aG>JlN   |   Append to G the elements of J from the length of N to the end
                          ;  | End all loops
                           G | Print G

Essa solução tenta continuamente remover todas as partes possíveis desde o início da string e monitora quais valores ainda precisam ser examinados.

Se observarmos o valor de Gno caso de teste [['ababab'],['a','ba','ab']]após cada iteração do loop while, é isso que obtemos:

['ababab']
['babab', 'abab']
['abab', 'bab']
['bab', 'bab', 'ab']
['bab', 'ab', 'b']
['ab', 'b', 'b']
['b', 'b', '']
['b', '']
['']   <---Remember, this evaluates to True

E, no caso de teste [['aaaaa'],['aa']], é isso que obtemos:

['aaaaa']
['aaa']
['a']
[]   <---And this evaluates to False

Criei outro caso de teste [['aaaaaa'],['a','aa','aaa']]e a saída foi esta:

['', 'aaa', 'aa', 'a', 'aa', 'a', '', 'a', '', 'aa', 'a', '', 'a', '', '', 'a', '', '']

A lista de saída contém um monte de lixo, mas ainda é um valor verdadeiro.

K Zhang
fonte
5

Perl 5 , 39 bytes

38 bytes de código + -psinalizador.

map{chop;$v.="\Q$_\E|"}<>;$_=/^($v)*$/

Experimente online!

Para a entrada "Hello, world!", ["l", "He", "o, wor", "d!"](separada por novas linhas na verdade), ela constrói o padrão l|He|o, wor|d!|(com os metacaracteres escapados, graças a \Q..\E) e, em seguida, verifica se a primeira string corresponde a esse padrão /^($v)*$/.

No TryItOnline, observe que precisa haver uma nova linha à direita.

dada
fonte
"Olá, mundo! Ele está lá!" esta entrada com um espaço após o "l" gerar nenhum resultado
RosLuP
@RosLuP Você pode me dar um link TryItOnline, por favor? (. Eu não entendo o que quer dizer exatamente Note-se que "false" realmente imprime nada como este é Perl)
Dada
Então, para impressão falsa nada? Neste caso, me desculpe, mas esse valor não saída não me parece muito útil ...
RosLuP
@RosLuP Isso mesmo. Em Perl, undefé o valor falsy retornado pela maioria dos embutidos. E ao imprimi-lo, ele realmente imprime nada. E é exatamente isso que estou fazendo. Imprimir "1/0" é natural para idiomas do tipo C, mas para Perl, "1 / undef" é o caminho natural.
Dada
Nenhuma saída possui uma ambiguidade "está em execução ou o programa já está falso?"
RosLuP
4

PHP, 69 bytes

<?=($s=$_GET[0])>""?ctype_digit(strtr($s,array_flip($_GET[1])))?:0:1;

Casos de teste

Jörg Hülsermann
fonte
Muito esperto, demorei um minuto para entender o que você está fazendo. +1 para pensar fora da caixa
Martijn
Falso negativo para esse caso de incômodo["", ["The string can be constructed with nothing!"]]
Jonathan Allan
@JonathanAllan done é uma string vazia uma string?
Jörg Hülsermann
Sim, o problema do particionamento vazio é um problema em muitas soluções.
Jonathan Allan
3

Python 2, 141 bytes

lambda s,l:s in[''.join(i)for r in range(len(s)+1)for j in combinations_with_replacement(l,r)for i in permutations(j)]
from itertools import*

Experimente Online!

Extremamente ineficiente. O primeiro caso de teste atinge o tempo limite no TIO.

viciado em matemática
fonte
3

JavaScript (ES6), 59 bytes

Pega a matriz de substrings ae a string sna sintaxe de curry (a)(s). Retorna false/ true.

a=>g=s=>!s||a.some(e=>s.split(e)[0]?0:g(s.slice(e.length)))

Comentado

a =>                          // main function that takes 'a' as input
  g = s =>                    // g = recursive function that takes 's' as input
    !s ||                     // if 's' is empty, return true (success!)
    a.some(e =>               // else, for each element 'e' in 'a':
      s.split(e)[0] ?         //   if 's' doesn't begin with 'e':
        0                     //     do nothing
      :                       //   else:
        g(s.slice(e.length))  //     remove 'e' at the beginning of 's' and
    )                         //     do a recursive call on the remaining part

Casos de teste

Arnauld
fonte
3

Haskell , 35 bytes

#pega ae uma Stringlista de Strings e retorna a Bool.

s#l=elem s$concat<$>mapM("":)(l<$s)

Experimente online!

Só não se importe com o caso de teste que eu deixei de fora, porque ele esmagou meu laptop escasso, mesmo com -O2. Eu suspeito que o GHC não fundir essa lista intermediária de elementos 30517578125, ele tem muito compartilhamento para obter rapidamente o lixo coletado e, como o caso de teste é falso, o programa precisa gerar tudo isso ... sinta-se à vontade para tentar se puder lidar com isto.

mapM("":)(l<$s)é uma lista de todas as maneiras de criar uma length slista de elementos que são cadeias vazias ou cadeias de caracteres l.

Ørjan Johansen
fonte
3

Pitão, 17 15 11 14 bytes

AQ|!G}Ym-dH./G

O requisito para a sequência vazia foi alterado, adicionando 3 bytes.

Explicação

AQ|!G}Ym-dH./G
AQ                     Save the input into G, H.
           ./G         Get all partitions of G.
       m-dH            Check if the parts are in H.
     }Y                The empty list should be present if and only
                           if the string can be made...
  |!G                  ... or the string might be empty.

Versões antigas

AQ}Ym-dH./G

Mais curta e corre na vida útil do universo!

Explicação

AQ}Ym-dH./G
AQ                  Save the input into G, H.
        ./G         Get all partitions of G.
    m-dH            Check if the parts are in H.
  }Y                The empty list should be present if and only
                        if the string can be made.

AQ&G}GsMs.pMy*HlG

Isso é assustadoramente lento, mas funciona para meus casos de teste (trivialmente pequenos).

Explicação

AQ&G}GsMs.pMy*HlG
AQ                  Save the input into G, H.
             *HlG   Repeat the list of substrings for each character of G.
            y       Take the power set.
         .pM        Take every permutation of each set of substrings.
      sMs           Get a list of all the joined strings.
    }G              Check if G is one of them.
  &G                Make sure G is not empty.

fonte
3

Geléia , 14 12 8 bytes

;FŒṖḟ€Ạ¬

Experimente online!

Como funciona

;FŒṖḟ€Ạ¬   - main function, left argument s, right argument l
;F         - concatenate to the string the list, flattened to deal with "" as string
  ŒṖ       - Get all partitions of s, that is, all ways to make s from substrings
     €     - For each partition...
    ḟ      -   Filter out (exclude) those elements which are not in... 
           -   (implicit right arg) the list l. This leaves the empty set (falsy) if the partition can be made of elements from the list
      Ạ    - If any element is falsy (thus constructable from l), return 0; else return 1
       ¬   - Apply logical not to this, to yield the proper 1 = constructable from list, 0 otherwise.

bugfix no caso "", ["The string can be constructed with nothing"]graças a @JonathanAllan

fireflame241
fonte
Falso negativo para"", ["The string can be constructed with nothing!"]
Jonathan Allan
Vai ser muito mais lento, mas ;FŒṖḟ⁹$€Ạ¬consertaria.
Jonathan Allan
... e você pode usar um argumento direito implícito para , assim você não precisa o $ou : ;FŒṖḟ€Ạ¬.
Jonathan Allan
Grr, é o que recebo por não testar todos os casos de teste. Talvez eu consiga manter 8 bytes substituindo ¬por uma operação que sempre retorna true com o argumento correto "".
precisa saber é o seguinte
^ Bem, eu tenho que voltar a 8 :)
Jonathan Allan
2

R, 49 bytes

function(s,l)gsub(paste(l,collapse='|'),"",s)==""

Experimente online!

Neil
fonte
2
Deve falhar ('x', '.'), mas não falha .
Joey #
2

Pitão, 10 8 bytes

f!-TQ./+zh

Suíte de teste

Isso pega a lista na primeira linha do STDIN e a sequência (sem aspas) na segunda.

Para começar, a lista é armazenada Qe a sequência é armazenada z. Em seguida, formamos todas as partições possíveis dez . Cada partição será filtrada ( f) para verificar se usa apenas partes Q. Para fazer isso, nós removemos todos os elementos Qde T, a partição Estamos particionamento, e logicamente negar o resultado com !, de modo que somente as partições onde cada elemento foi em Qsão mantidos.

Para corrigir o problema que '' não possui partições, adicionamos a primeira palavra do dicionário em z, para que não seja uma sequência vazia.

isaacg
fonte
A suíte de testes perde a linha de fundo (uma sequência vazia) - precisa ser citada? Com uma linha vazia ou ""parece falhar nesse caso.
Jonathan Allan
Uma string vazia não possui partições, portanto, na verdade, apenas fornece a resposta errada aqui. Droga, vou tentar consertar.
Isaacg
A correção que sugeri para o Jelly foi concatenar a string de entrada com a matriz de entrada achatada, talvez você possa fazer o mesmo?
Jonathan Allan
@ JonathanAllan Eu fiz algo parecido, obrigado.
Isaacg
Os casos de "", [""]e "", []não foram cobertos - não vamos ir lá :)
Jonathan Allan
2

PowerShell, 61 58 57 bytes

{$s,$l=$_;$l|sort -d length|%{$s=$s.replace($_,'')};+!$s}

Experimente online!

Soluções antigas:

{$s,$l=$_;$l|sort -d length|%{$s=$s.replace($_,'')};[int]!$s}
{$s,$l=$_;$l|sort -d length|%{$s=$s.replace($_,'')};0+!$s}  
Andrei Odegov
fonte
Este é quase ilegível, então eu recomendo alterá-lo um pouco. Estou bastante certo de que a maioria das outras pessoas concordaria.
Rɪᴋᴇʀ
Obrigado pela explicação do motivo da sua correção da minha solução.
Andrei Odegov
1

Python 2, 64 bytes

lambda s,l:len(re.findall("^("+"|".join(l)+")*$",s))>0
import re

Experimente isso online!

Neil
fonte
Eu acho que isso não funciona totalmente, tente ("aaaaaaa",["aa","aaa"]).
Xnor
@xnor eu atualizei. Venha descobrir, o regex é perfeito para isso.
28417 Neil
4
('x', '.')Acho que deveria falhar , mas não.
Joey
1
@nfnneil Você fez? Sua última edição foi 10 horas atrás.
Dennis
1
... ou "Hello", ["\w"]etc.
Jonathan Allan
1

PowerShell, 78

$s,$l=$args;!($s-creplace(($l|sort -d length|%{[regex]::escape($_)})-join'|'))

Abordagem bastante simples baseada em regex.

Joey
fonte
1

CJam (16 bytes)

{Ma+1$,m*:e_\a&}

Este é um bloco anônimo (função) que pega a string e a matriz de strings na pilha. Demonstração online .

Ele usa o algoritmo óbvio:

{        e# Declare a block. Call the args str and arr
  Ma+    e#   Add the empty string to the array
  1$,m*  e#   Take the Cartesian product of len(str) copies of (arr + [""])
  :e_    e#   Flatten each element of the Cartesian product into a single string
  \a&    e#   Intersect with an array containing only str
}

O valor de retorno é uma matriz / string vazia (falsy) se strnão puder ser criada, ou uma matriz contendo str(verdade, mesmo que strseja a string vazia) se puder ser criada.

Peter Taylor
fonte
@RosLuP, não sei o que você quer dizer. Esse caso de teste em particular é executado tão rápido que não consigo cronometrar. Outros casos de teste levam muito tempo para serem executados, mas a especificação não inclui nenhuma restrição de tempo.
Peter Taylor
@RosLuP, demonstração online . Mas não entendo qual é a sua reclamação.
Peter Taylor
1

C ++ (Cco), 287 bytes

#include<algorithm.h>
f(a,b)char*a,**b;{int i,j,k,v,p[256];if(!a||!b||!*b)return-1;for(v=0;v<256&&b[v];++v)p[v]=v;if(v>=256)return-1;la:for(i=0,j=0;j<v&&a[i];){for(k=0;b[p[j]][k]==a[i]&&a[i];++i,++k);j=b[p[j]][k]?(i-=k),j+1:0;}if(a[i]&&next_permutation(p,p+v)) goto la;return i&&!a[i];}

porque eu não escrevi ou usei muito o next_permutation () eu não sei se está tudo ok. Eu não sei 100% se é uma solução, muito possivelmente isso está fora de qualidade ... Uma lista de cadeias está aqui, uma matriz de ponteiros para char; NULL terminado O algo é fácil, existe um que a linearidade tenta se todas as strings da lista se encaixam no argumento "a" string, existe outro trecho que permite o índice da lista de strings e tenta todas as combinações possíveis.

ungolf it, código de teste e resultados aqui

#include<stdio.h>
g(a,b)char*a,**b;
{int i,j,k,v,p[256];
 if(!a||!b||!*b) return -1;
 for(v=0;v<256&&b[v];++v) p[v]=v;
 if(v>=256)      return -1; // one array of len >256 is too much
la: 
 for(i=0,j=0;j<v&&a[i];)
   {for(k=0;b[p[j]][k]==a[i]&&a[i];++i,++k); 
    j=b[p[j]][k]?(i-=k),j+1:0;
   } 
 if(a[i]&&next_permutation(p,p+v)) goto la;
 return i&&!a[i];  
}

#define F for
#define P printf

test(char* a, char** b)
{int i;
 P("f(\"%s\",[",a);
 F(i=0;b[i];++i) 
       P("\"%s\"%s", b[i], b[i+1]?", ":"");
 P("])=%d\n", f(a,b));
}

main()
{char *a1="Hello, world!",    *b1[]={"l","He", "o, worl", "d!",      0};//1
 char *a2="la lal al ",       *b2[]={"la", " l", "al ",              0};//1
 char *a3="this is a string", *b3[]={"this should return falsy",     0};//0
 char *a4="thi is a string",  *b4[]={"this", "i i", " a", " string", 0};//0
 char *a5="aaaaa",            *b5[]={"aa",                           0};//0
 char *a6="foo bar foobar",   *b6[]={"foo","bar"," ","spam",         0};//1
 char *a7="ababab",           *b7[]={"a","ba","ab",                  0};//1
 char *a8="",                 *b8[]={"This return 0 even if has to return 1", 0};//0
 char *a9="ababc",            *b9[]={"a","abc", "b", 0};//1

  test(a1,b1);test(a2,b2);test(a3,b3);test(a4,b4);test(a5,b5);test(a6,b6);
  test(a7,b7);test(a8,b8);test(a9,b9);
}

f("Hello, world!",["l", "He", "o, worl", "d!"])=1
f("la lal al ",["la", " l", "al "])=1
f("this is a string",["this should return falsy"])=0
f("thi is a string",["this", "i i", " a", " string"])=0
f("aaaaa",["aa"])=0
f("foo bar foobar",["foo", "bar", " ", "spam"])=1
f("ababab",["a", "ba", "ab"])=1
f("",["This return 0 even if has to return 1"])=0
f("ababc",["a", "abc", "b"])=1

isso seria compilado no compilador gcc C ++

#include<algorithm>

int f(char*a,char**b){int i,j,k,v,p[256];if(!a||!b||!*b)return -1;for(v=0;v<256&&b[v];++v)p[v]=v;if(v>=256)return -1;la:;for(i=0,j=0;j<v&&a[i];){for(k=0;b[p[j]][k]==a[i]&&a[i];++i,++k);j=b[p[j]][k]?(i-=k),j+1:0;}if(a[i]&&std::next_permutation(p,p+v))goto la;return i&&!a[i];}
RosLuP
fonte
Conseguiu amar C ++! :)
MEMark 29/04
1

Python, 66 bytes

lambda s,l:s==''or any(x==s[:len(x)]and f(s[len(x):],l)for x in l)

Ungolfed:

def f(s,l):
    if s=='': 
        return 1
    for x in l:
        if s.startswith(x) and f(s[len(x):],l):
            return 1
    return 0
RootTwo
fonte
0

Microsoft Sql Server, 353 bytes

u as(select s.n,s collate Latin1_General_BIN s,l collate Latin1_General_BIN l,
row_number()over(partition by l.n order by len(l)desc)r from s,l where s.n=l.n),
v as(select n,s,l,replace(s,l,'')c,r from u where r=1 union all
select u.n,u.s,u.l,replace(v.c,u.l,''),u.r from v,u where v.n=u.n and v.r+1=u.r)
select s,iif(min(c)='',1,0)u from v group by n,s

Teste online.

Versão legível:

with s as(
  select n,s
  from(values(1,'Hello, world!'),
             (2,'la lal al '),
             (3,'this is a string'),
             (4,'thi is a string'),
             (5,'aaaaa'),
             (6,'foo bar foobar'),
             (7,'ababab'),
             (8,''))s(n,s)),
l as(
  select n,l
  from(values(1,'l'),(1,'He'),(1,'o, wor'),(1,'d!'),
             (2,'la'),(2,' l'),(2,'al '),
             (3,'this should return falsy'),
             (4,'this'),(4,'i i'),(4,' a'),(4,' string'),
             (5,'aa'),
             (6,'foo'),(6,'bar'),(6,' '),(6,'spam'),
             (7,'a'),(7,'ba'),(7,'ab'),
             (8,'The string can be constructed with nothing!'))l(n,l)),
--The solution starts from the next line.
u as(
  select s.n,
    s collate Latin1_General_BIN s,
    l collate Latin1_General_BIN l,
    row_number()over(partition by l.n order by len(l)desc)r
  from s,l
  where s.n=l.n),
v as(
  select n,s,l,replace(s,l,'')c,r from u where r=1
    union all
  select u.n,u.s,u.l,replace(v.c,u.l,''),u.r
  from v,u
  where v.n=u.n and v.r+1=u.r
)
select s,iif(min(c)='',1,0)u from v group by n,s
Andrei Odegov
fonte
0

C, 140 bytes

Tenho certeza de que existe uma maneira mais curta de fazer isso em C, mas eu queria criar uma solução que teste todas as combinações possíveis de substrings em vez do método usual de localizar / substituir.

char p[999];c,o;d(e,g,l,f)int*e,**g,**l;{c=f&&c;for(l=g;*l;)strcpy(p+f,*l++),(o=strlen(p))<strlen(e)?d(e,g,0,o):(c|=!strcmp(e,p));return c;}

Experimente online

Ungolfed:

#include <string.h>
#include <stdio.h>

char buf[999];
int result;
int temp;

int test(char *text, char **ss, char **ptr, int length) 
{
    if (length == 0)
        result = 0;

    for(ptr = ss; *ptr; ptr++)
    {
        strcpy(buf + length, *ptr);
        temp = strlen(buf);
        if (temp < strlen(text))
        {
            // test recursivly
            test(text, ss, 0, temp);
        }
        else
        {
            if (strcmp(buf, text) == 0)
                result = 1;
        }
    }
    return result;
}

int main()
{
    char *text = "Hello,World";
    char *keywords[] = { "World", "Hello", ",", 0 };
    printf("%d", test(text, keywords, 0, 0));
}
Johan du Toit
fonte