Verifica se è possibile creare una stringa con sottostringhe!


23

Data una stringa se un array / elenco l, determinare se è spossibile creare o meno parti con l.

Ad esempio, se la stringa è "Hello, world!"e l'elenco è [' world!', 'Hello,'], il programma / funzione dovrebbe restituire un valore di verità, poiché è possibile disporre l'elenco per formare la stringa. Il seguente elenco dovrebbe anche restituire un valore truthy: ['l', 'He', 'o, wor', 'd!']. Immagina solo il 'l'riempimento nel punto in cui deve essere inserito. Quindi sì, puoi ripetere elementi dell'elenco per formare la stringa. Se non può formare la stringa, dovrebbe restituire un valore errato. Metodi standard di IO, si applicano scappatoie standard.

Casi test:

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

Importa se l'array contiene più stringhe di quelle necessarie per costruire la stringa principale?
Shaggy,

Quale dovrebbe essere il valore di ritorno in questi casi?
Shaggy,

@Shaggy Truthy. Se è presente un extra, la stringa può essere costruita con tutte le parti non extra. Aggiungerò un caso di prova.
Compagno SparklePony,

3
Consiglio di aggiungere questo test:"ababab", ["a","ba","ab"]
drogato di matematica il

3
Suggerirei di aggiungere un caso di test contenente metacaratteri regex.
Joey,

Risposte:


11

Brachylog , 8 byte

~c¬{∋¬∈}

Provalo online!

Questo è molto lento. Ci sono voluti circa 37 secondi per il "Ciao, mondo!" test case sul mio PC e timeout su TIO.

Questo prende la stringa attraverso la variabile Input e l'elenco attraverso la variabile Output

Spiegazione

             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 .

"la lal al" più di 60 secondi ...
RosLuP,

1
@RosLuP Con questo input e ["la", " l", "al "]come elenco, è terminato sul mio computer e ha risposto correttamente false.dopo 6800 secondi, e "solo" 113 miliardi di inferenze.
Fatalizza il

Sento che scrivere qualcosa in questa lingua comporterebbe un programma non eseguibile su TIO haha.
Magic Octopus Urn,

@carusocomputing Il linguaggio non è così lento per la maggior parte dei programmi, è solo che in alcuni casi a causa della dichiaratività del programma, si ottengono tempi di esecuzione molto lenti (che potrebbero essere migliorati drasticamente a
scapito

@Fatalize errr ... Intendevo dire che il golf non scriveva, sembra che meno istruzioni ci siano, più ampia è la "domanda" e più calcoli ti occorrono. Sembra una lingua eccezionale per problemi matematici teorici.
Magic Octopus Urn

7

Mathematica, 29 byte

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

Spiegazione:

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

Soluzione di frode borderline, 21 byte

StringMatchQ[#,#2..]&

Poiché Mathematica è un linguaggio di programmazione simbolico, non vi è alcuna differenza tra le espressioni List[a,b,...]e il Alternatives[a,b,...]modo in cui interagiscono con altri simboli e il modo in cui vengono visualizzati ( {a,b,...}e a|b|..., rispettivamente). Se usata nel secondo argomento di StringMatchQ, Alternativesun'espressione viene trattata come uno schema di stringhe, e quindi possiamo salvare 8byte sulla mia soluzione precedente prendendo il secondo argomento come Alternativesespressione.

* Tecnicamente Listè anche Locked, il che impedisce agli utenti di Unprotectmodificarlo e modificarne il comportamento.


1
{x,y,z}viene trattato come x|y|zper la corrispondenza del modello di stringa. Penso che puoi sostituire ""|##&@@#2..con solo #2...
Non un albero il

5

Pyth, 23 byte

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

Accetta input come [['string'],['list', 'of', 'parts']]. L'output è un elenco vuoto o un elenco con valori all'interno. In Pyth, un elenco contenente qualsiasi cosa, anche una stringa nulla ([''] ), viene valutato come vero.

Provalo online!

Spiegazione:

                             | 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

Questa soluzione cerca continuamente di rimuovere ogni possibile parte dall'inizio della stringa e tiene traccia dei valori che deve ancora esaminare.

Se osserviamo il valore di Gnel caso di test [['ababab'],['a','ba','ab']]dopo ogni iterazione del ciclo while, questo è ciò che otteniamo:

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

E, nel caso di test [['aaaaa'],['aa']], questo è ciò che otteniamo:

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

Ho creato un altro caso di test [['aaaaaa'],['a','aa','aaa']]e l'output è stato questo:

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

L'elenco di output contiene un mucchio di immondizia al suo interno, ma è ancora un valore veritiero.


5

Perl 5 , 39 byte

38 byte di codice + -pflag.

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

Provalo online!

Per l'input "Hello, world!", ["l", "He", "o, wor", "d!"](separato da una nuova riga in realtà), costruisce il modello l|He|o, wor|d!|(con i metacaratteri sfuggiti, grazie a \Q..\E), quindi cerca se la prima stringa corrisponde a questo modello con/^($v)*$/ .

Su TryItOnline, nota che deve esserci una nuova riga finale.


"Ciao, mondo! L He o, wor d!" questo input con uno spazio dopo la "l" non genera alcun risultato
RosLuP,

@RosLuP Puoi darmi un link TryItOnline per favore? (Non capisco cosa intendi esattamente. Nota che "falso" in realtà non stampa nulla perché questo è Perl)
Dada,

Quindi per la stampa falsa niente? In questo caso mi scusi, ma questo valore di output non mi sembra troppo utile ...
RosLuP

@RosLuP Esatto. In Perl, undefè il valore di falsità restituito dalla maggior parte dei builtin. E quando lo stampa, in realtà non stampa nulla. Ed è esattamente quello che sto facendo. La stampa di "1/0" è naturale per i linguaggi C-like, ma per Perl, "1 / undef" è il modo naturale.
Dada,

Nessun output ha un'ambiguità "è in esecuzione o già il programma termina falso?"
RosLuP,

4

PHP, 69 byte

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

Casi test


Molto intelligente, mi ci è voluto un minuto per capire cosa stai facendo. +1 per pensare fuori dagli schemi
Martijn,

Falso negativo per quel fastidioso caso limite["", ["The string can be constructed with nothing!"]]
Jonathan Allan,

@JonathanAllan done è una stringa vuota una stringa?
Jörg Hülsermann,

Sì, il problema del partizionamento vuoto è un problema in molte soluzioni.
Jonathan Allan,

3

Python 2, 141 byte

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*

Provalo online!

Estremamente inefficiente. Il primo caso di test scade su TIO.


3

JavaScript (ES6), 59 byte

Accetta l'array di sottostringhe ae la stringa snella sintassi del curry (a)(s). Restituisce false/ true.

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

Commentate

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

Casi test


3

Haskell , 35 byte

#prende ae Stringun elenco di Strings e restituisce a Bool.

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

Provalo online!

Non importa il caso di test che ho lasciato fuori perché ha schiacciato il mio magro laptop, anche con -O2. Ho il sospetto che GHC non fonda quell'elenco di elementi intermedi 30517578125, ha troppa condivisione per raccogliere rapidamente la spazzatura, e poiché il test case è falso il programma deve generarlo tutto ... sentiti libero di provare se puoi gestirlo.

mapM("":)(l<$s)è un elenco di tutti i modi per creare un length selenco di elementi che sono stringhe vuote o stringhe da l.


3

Pyth, 17 15 11 14 byte

AQ|!G}Ym-dH./G

Il requisito per la stringa vuota è cambiato, aggiungendo 3 byte.

Spiegazione

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.

Vecchie versioni

AQ}Ym-dH./G

Più corto e corre nella durata della vita dell'universo!

Spiegazione

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

Questo è terribilmente lento, ma funziona per i miei (banalmente piccoli) casi di test.

Spiegazione

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.

3

Gelatina , 14 12 8 byte

;FŒṖḟ€Ạ¬

Provalo online!

Come funziona

;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 sul caso "", ["The string can be constructed with nothing"]grazie a @JonathanAllan


Falso negativo per"", ["The string can be constructed with nothing!"]
Jonathan Allan,

Sarà molto più lento ma ;FŒṖḟ⁹$€Ạ¬lo risolverebbe.
Jonathan Allan,

... e si può utilizzare un argomento implicito giusto per , quindi non avete bisogno della $o : ;FŒṖḟ€Ạ¬.
Jonathan Allan,

Grr, questo è quello che ottengo per non testare ogni singolo testcase. Potrei essere in grado di mantenere 8 byte sostituendo ¬con un'operazione che ritorna sempre vera con l'argomento giusto "".
fireflame241

^ beh, l'ho riportato alle 8 :)
Jonathan Allan,


2

Pyth, 10 8 byte

f!-TQ./+zh

Suite di test

Questo prende l'elenco sulla prima riga di STDIN e la stringa (senza virgolette) sulla seconda.

Per iniziare, l'elenco viene archiviato Qe la stringa viene archiviata z. Successivamente, formiamo tutte le possibili partizioni di z. Ogni partizione verrà filtrata ( f) per verificare se utilizza solo pezzi in Q. Per fare questo, togliamo tutti gli elementi Qda T, la partizione Siamo partizionamento, e logicamente negare il risultato con !, in modo che solo le partizioni in cui ogni elemento è stato inQ sono conservati.

Per risolvere il problema che ''non ha partizioni, aggiungiamo la prima parola del dizionario a z, in modo che non sia una stringa vuota.


La suite di test manca la linea di fondo (una stringa vuota) - Ha bisogno di un preventivo? Con una riga vuota o ""sembra fallire quel caso.
Jonathan Allan,

Una stringa vuota non ha partizioni, quindi in realtà dà solo la risposta sbagliata qui. Accidenti, proverò a risolverlo.
isaacg,

La soluzione che ho suggerito per Jelly era di concatenare la stringa di input con l'array di input appiattito, forse puoi fare lo stesso?
Jonathan Allan,

@JonathanAllan Ho fatto qualcosa di simile, grazie.
isaacg,

I casi di "", [""]e "", []non sono stati coperti - non andiamo lì :)
Jonathan Allan,

2

PowerShell, 61 58 57 byte

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

Provalo online!

Vecchie soluzioni:

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

Questo è quasi illeggibile, quindi consiglio di cambiarlo un po '. Sono abbastanza certo che molte altre persone sarebbero d'accordo.
Rɪᴋᴇʀ

Grazie per la spiegazione del motivo della correzione della mia soluzione.
Andrei Odegov

1

Python 2, 64 byte

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

Prova questo online!


Penso che non funzioni del tutto, provaci ("aaaaaaa",["aa","aaa"]).
xnor

@xnor l'ho aggiornato. Vieni a scoprirlo, regex è perfetto per questo.
Neil,

4
Dovrei fallire ('x', '.'), immagino, ma non lo è.
Joey,

1
@nfnneil L'hai fatto? L'ultima modifica è stata effettuata 10 ore fa.
Dennis,

1
... o "Hello", ["\w"]ecc.
Jonathan Allan,

1

PowerShell, 78

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

Approccio basato su regex piuttosto semplice.


1

CJam (16 byte)

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

Questo è un blocco anonimo (funzione) che accetta la stringa e l'array di stringhe nello stack. Demo online .

Utilizza l'algoritmo ovvio:

{        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
}

Il valore restituito è una matrice / stringa vuota (falsy) se strnon può essere creata o una matrice contenente str(verità, anche se strè essa stessa la stringa vuota) se può essere creata.


@RosLuP, non sono sicuro di cosa intendi. Quel particolare test case viene eseguito così velocemente che non riesco davvero a cronometrarlo. L'esecuzione di altri casi di test richiede molto tempo, ma le specifiche non includono alcun vincolo temporale.
Peter Taylor,

@RosLuP, demo online . Ma non capisco quale sia la tua lamentela.
Peter Taylor,

1

C ++ (Ccn), 287 byte

#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];}

perché non ho scritto o usato troppo il next_permutation () non so se va tutto bene. Non so al 100% se è una soluzione troppo probabilmente questa non è di qualità ... Un elenco di stringhe è qui un array di puntatori a char; NULL terminato L'algo è semplice, esiste un solo algoritmo che la linearità prova se tutta la stringa nell'elenco si adatta all'argomento "a" stringa c'è un altro algoritmo che consente l'indice dell'elenco di stringhe in modo da provare tutte le possibili combinazioni.

deselezionalo, prova codice e risultati qui

#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

questo verrebbe compilato nel compilatore g ++ 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];}

Devi amare il C ++! :)
MEMark

1

Python, 66 byte

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

0

Microsoft SQL Server, 353 byte

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

Provalo online.

Versione leggibile:

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

0

C, 140 byte

Sono sicuro che esiste un modo più breve per farlo in C, ma volevo creare una soluzione che testasse tutte le possibili combinazioni di sottostringhe invece del solito metodo di ricerca / sostituzione.

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;}

Provalo 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));
}
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.