Desafio simples de golfe com códigos: padrões de caracteres!


22

Neste desafio, você recebe uma string como entrada contendo uma string de X, Y e Z, por exemplo. "XYZZ". X, Y e Z representam um caractere específico. Esse padrão é então comparado com uma segunda entrada de string. Se o padrão existir como uma substring na segunda entrada, retorne True, caso contrário, retorne False. Depois que um padrão é encontrado na palavra, o programa para de pesquisar e retorna True.

Exemplos

Padrão: "XXYY"

succeed ---> True (pattern found: ccee)
success ---> False (pattern not matched)
balloon ---> True (pattern found: lloo)

Padrão: "XYXYZ"

bananas ---> True (pattern found: nanas)
banana  ---> False (pattern not found)
  • Nota: Esta não é a entrada real. Este é um exemplo de como o programa deve funcionar. Seu programa deve produzir Trueou False, ou outros valores de Truthy / Falsy.

Outras informações importantes / úteis

  • O padrão não precisa conter um X, Y e um Z, pode conter X e Y ou mesmo (embora um pouco inútil) apenas X.
  • O padrão não pode estar vazio, mas isso não será usado como um caso de teste.
  • A cadeia de pesquisa não estará vazia e será minúscula.
  • A ordem alfabética de X, Y e Z no padrão não importa.
  • X, Y e Z devem ser caracteres únicos.
  • Você pode usar qualquer biblioteca que desejar.
  • A pontuação é determinada pelo tamanho do código , em bytes. Menor pontuação ganha.

Boa sorte!


O padrão pode ser qualquer coisa. Eu provavelmente deveria ter mencionado que o padrão não precisa ter um X, Y e um Z, poderia ter apenas um X e um Y. Esses padrões são apenas exemplos, portanto, fique à vontade para criar o seu próprio exemplos com esses padrões.
notHalfBad

O que você quer dizer com "o padrão existe"? Como um pedaço contíguo? Como uma substring? Por exemplo, X e Y podem representar a mesma coisa?
Xnor

@xnor X e Y devem ser independentes um do outro, e o que quero dizer com o padrão existente é que em qualquer lugar da string existe uma substring que corresponde ao padrão. Vou adicioná-los à descrição do meu desafio para esclarecer.
notHalfBad

3
Relacionado. (Mesma coisa, mas pede correspondências exatas do padrão, não para substrings.)
Martin Ender

4
Mais detalhes: O padrão pode estar vazio? A cadeia de pesquisa? A string de pesquisa usará apenas letras minúsculas? O padrão será o primeiro em ordem alfabética entre os padrões equivalentes, ou seja, use X primeiro, depois Y e Z?
Xnor

Respostas:


12

Perl 5 , 85 bytes

Economizou 40 bytes graças à sugestão de Peter Taylor! (veja minha versão mais antiga abaixo para ver as diferenças)

83 bytes de código + -plsinalizador.

s/./$h{$&}?"\\$h{$&}":($h{$&}=$.,join("",map"(?!\\$_)",1..$.++)."(.)")/ge;$_=<>=~$_

Experimente online!

O XYXYZ é transformado em ((?!\1).)((?!\1)(?!\2).)\1\2((?!\1)(?!\2)(?!\3).)(sim, alguns dos testes não podem ser verdadeiros, mas são mais curtos), e a segunda entrada é então verificada nesse regex. (veja as explicações da minha versão mais antiga para obter mais intuição de como ela funciona)


Minha versão mais antiga:
Obrigado a Arnauld por apontar um erro que cometi na minha primeira versão.
113 bytes de código + -plsinalizadores e -Mre=eval.

s/./$h{$&}?"\\$h{$&}":($h{$&}=++$i,"(.)")/ge;$_.='(?{++$c;$\=1if!grep$v{$c}{${$_}}++,1..'.(keys%h).'})^';<>=~$_}{

Experimente online!

Por exemplo XYXYZ: (.) (.) (.) A primeira regex irá converter o padrão de \ 1 \ 2, e adicionar no final de um teste para verificar se $1, $2e $3são diferentes: em caso afirmativo, $\é definido como um. Em seguida, a segunda entrada é testada contra esse regex e $\é implicitamente impressa no final.
O regex gerado para XYXYZ é (.)(.)\1\2(.)(?{++$c;$\=1if!grep{$v{$c}{${$_}}++}1..3})^.
(Vou acrescentar mais detalhes às explicações quando tiver um momento)


Então, usando regex para transformar não-regex em regex? coolio
Matthew Roh

@ Arnauld De fato, obrigado. (Eu devo ter lido o desafio muito rápido, meu mal). Teve que dobrar o número de bytes para corrigi-lo, mas funciona agora!
Dada

Não seria mais golfista gerar um regex como (.)((?!\1).)\1\2((?!\1)(?!\2).)?
Peter Taylor

@ Peter Taylor, talvez .. Eu pensei vagamente, mas parecia mais difícil (leia mais) gerar .. Vou dar outra olhada quando tiver um momento.
Dada

@ Peter Taylor deixa pra lá, vai ser 30 bytes mais curto; Vou atualizar isso em breve, graças :)
Dada

10

Geléia , 9 bytes

=þ
ẆÇ€ċÇ}

Retorna o número de vezes que o padrão foi encontrado, sendo diferente de zero e zero sendo falso.

Experimente online!

Como funciona

ẆÇ€ċÇ}  Main link. Left argument: s (string). Right argument: p (pattern)

Ẇ       Window; generate all substrings of s.
 ǀ     Map the helper link over the substrings.
    Ç}  Apply the helper link to p.
   ċ    Count the number of times the right result appears in the left result.


=þ      Helper link. Argument: t (string)

=þ      Compare all characters of t for equality with all characters of t, yielding
        a square matrix of Booleans.

8

JavaScript (ES6), 94 bytes

f=
(p,s)=>s.match(p.replace(/./g,c=>m[c]||(t=r,r=`(?!\\${++g})`+r,m[c]=`\\`+g,t),g=m=[],r=`(.)`))
<div oninput=o.textContent=!!f(p.value,s.value)><input id=p placeholder=Pattern><input id=s placeholder=String><span id=o>

Funciona transformando o padrão em uma regexp, por exemplo, para XYXYZgerar /(.)(?!\1)(.)\1\2(?!\2)(?!\1)(.)/.

Percebo uma distinção interessante entre PCRE e JavaScript regexp: no PCRE, \<n>falha (e, portanto, (?!\<n>)é bem - sucedido) antes que o grupo de captura seja definido, enquanto o JavaScript corresponde com êxito à string vazia (e, portanto, (?!\<n>)falha).


7

Python 2 , 70 bytes

f=lambda p,s:s>''and(map(s.find,s[:len(p)])==map(p.find,p))|f(p,s[1:])

Experimente online!

Verifica se uma sequência corresponde a um padrão usando o método nesta resposta . Usa um prefixo da sequência de pesquisa cujo comprimento é igual ao padrão. Retira o primeiro caractere da string até encontrar uma correspondência ou Falsese ela ficar vazia


73 bytes:

f=lambda p,s:s>''and(map(s.find,s)==map(p.find,p))|f(p,s[1:])|f(p,s[:-1])

Experimente online

Verifica se uma sequência corresponde a um padrão usando o método nesta resposta . Verifica recursivamente todas as substrings, ramificando para remover o primeiro ou o último caractere até que a sequência esteja vazia.



4

05AB1E , 19 16 bytes

ÙœJv¹y…XYZ‡²åi1q

Experimente online!


ÙœJ              # Get powerset of all unique characters in string.
   v             # Loop through each...
    ¹            # Push input word.
     y           # Push current set of letters in powerset.
      …XYZ‡      # Replace each of the 3 letters in the original word with XYZ.
           ²å    # Check if second input is in this string, push 1 if it is.
             i1q # If 1, push 1 and quit.

Retornará 1 se verdadeiro, nulo se não for verdadeiro.


Isso pode ter 14 bytes se o retorno dos possíveis valores de XYZ for permitido:

05AB1E , 14 bytes

ÙœJv¹y…XYZ‡²å—

Experimente online 2!


Supondo que uma sequência não vazia seja verdadeira em 05AB1E e que uma sequência vazia seja falsa, sua segunda versão deve estar em conformidade com as especificações.
217 Dennis

1
Resultado incorreto na entrada "abcd" e "XYZZ". Você precisa adicionar uma quarta letra como uma substituição padrão.
GB

@Dennis: Se formos pelo meta post, os únicos valores de verdade em 05AB1E são 1e True(o que geralmente é uma desvantagem para esse tipo de desafio), mas se a especificação de desafio puder ser interpretada como permitindo definir verdade / falsidade para o desafio a segunda versão funciona como você diz.
Emigna

@ Emigna Oh, eu não sabia disso.
Dennis

4

Java 7, 177 176 173 bytes

Object c(String p,String s){int i=p.length();if(s.length()<i)return 0>1;for(;i-->0;)if(p.indexOf(p.charAt(i))!=s.indexOf(s.charAt(i)))return c(p,s.substring(1));return 1>0;}

Explicação:

Object c(String p, String s){                             // Method with two String parameters and Object return-type
  int i = p.length();                                     //  Index that starts at the length of the pattern
  if(s.length() < i)                                      //  If the length of the input is smaller than the length of the pattern
    return 0>1;//false                                    //   Simply return false
  for(;i-->0;)                                            //  Loop from 0 to length_of_pattern
    if(p.indexOf(p.charAt(i)) != s.indexOf(s.charAt(i)))  //   If the index of the characters of the pattern and input aren't matching
     return c(p, s.substring(1));                         //    Return the recursive-call of pattern and input minus the first character
                                                          //  End of loop (implicit / single-line body)
  return 1>0;//true                                       //  If every index of the characters are matching: return true
}                                                         // End of method

Código do teste:

Experimente aqui.

class M{
  static Object c(String p,String s){int i=p.length();if(s.length()<i)return 0>1;for(;i-->0;)if(p.indexOf(p.charAt(i))!=s.indexOf(s.charAt(i)))return c(p,s.substring(1));return 1>0;}

  public static void main(String[] a){
    System.out.println(c("XXYY", "succeed"));
    System.out.println(c("XXYY", "success"));
    System.out.println(c("XXYY", "balloon"));

    System.out.println(c("XYXYZ", "bananas"));
    System.out.println(c("XYXYZ", "banana"));
  }
}

Saída:

true
false
true
true
false

4

PHP, 89 bytes

Um presente de @Christoph e @Titus

for(;$v=$argv[1][$i++];)$r.=$$v?"\\".$$v:"(.)".!$$v=++$j;echo preg_match("#$r#",$argv[2]);

PHP, 105 bytes

Um presente de @Christoph

foreach(str_split($argv[1])as$v)$r.=$x[$v]?"\\$x[$v]":"(.)".!$x[$v]=++$y;echo preg_match("#$r#",$argv[2]);

PHP, 167 bytes

[,$a,$b]=$argv;foreach($s=str_split($a)as$v)$r[]=$k++>strpos($a,$v)?"\\".(1+array_search($v,array_keys(array_count_values($s)))):"(.)";echo preg_match(_.join($r)._,$b);

1
Você poderá salvar 2 bytes usando em ++$pvez de ($p+1), embora eu não o tenha testado.
user59178

1
Não funciona para mim: Sandbox . Enfim uma versão do código golfed: [,$a,$b]=$argv;foreach(str_split($a)as$k=>$v)$r.=$k==($p=strpos($a,$v))?"(.)":"\\".++$p;echo preg_match("#$r#",$b);.
Christoph

1
Leve isso como um presente: [,$a,$b]=$argv;foreach(str_split($a)as$v)$r.=$x[$v]?"\\$x[$v]":'(.)'.!$x[$v]=++$y;echo preg_match("#$r#",$b);(Note que você deve manter suas velhas usando <strike>)
Christoph

1
@Christoph A Gift foi o esforço de aprendizado da !. Vale mais a pena os pontos que eu poderia alcançar com sua boa solução.
Jörg Hülsermann 14/03

1
Conto 109, não 108. -3 bytes se você não copiar $argvpara $ae $b; -6 bytes com for(;a&$v=$argv[1][$i++];); -1 byte com nomes de variáveis mais longos ( de fato! : Use $vvem vez de $v, $iiem vez de $i, $rrem vez de $r, $yyem vez de $ye você pode usar $$vvem vez de $x[$v])
Tito

4

C #, 184 165 155 bytes

obrigado aloisdg!

bool c(string p,string n){for(int l=p.Length,i=0,j;i<l;i++)for(j=i;j>=0;)if(p[i]==p[j]==(n[i]!=n[j--]))return l!=n.Length&&c(p,n.Substring(1));return 2>1;}

solução de retorno, como bônus, funciona com um padrão com qualquer personagem!

    public static bool c(string p,string n)
    {
        for (int l = p.Length, i = 0, j; i < l; i++)
            for (j = i; j >= 0;)
                if (p[i]==p[j]==(n[i]!=n[j--]))
                    return l != n.Length && c(p,n.Substring(1));
        return 2>1;
    }

Eu notei golfe expôs lógica i didnt uso, será atualizado em breve
downrep_nation

2
Primeiro de tudo, por que o var s=l==n.Length;? Você o usa apenas em return s?!s:(onde !sé sempre false), para que possa ser alterado para return l==n.Length?0>1:. Além disso, o que é esta: (n[i]!=n[j]||n[i]!=n[j]). Você verifica n[i]!=n[j]duas vezes .. Isso sempre será true or true/ false or false..: S
Kevin Cruijssen 14/03

O cheque duplo realmente sobrou de um sistema maior que desapareceu no golfe, então o s foi usado muito, eu o melhorarei ainda mais. Obrigado!
downrep_nation

Você pode decalcar todas as suas variáveis ​​em uma linhaint l = p.Length,i = 0, j;
aloisdg diz Reinstate Monica 15/17

Pode mover o seu i++e o seu j--dentro do loop for. por exemplo:for(j=i;j>=0;)if(p[i]==p[j]==(n[i]!=n[j--]))
aloisdg diz Reinstate Monica 15/03

3

Ruby, 63 61 bytes

->a,b{a.chars.permutation.any?{|w|a.tr((w|[])*'','XYZW')[b]}}

Em vez de procurar um padrão regex, tente substituir 'X', 'Y' e 'Z' de todas as maneiras possíveis e encontre uma correspondência literal.

(Na verdade, o mesmo conceito da resposta 05AB1E da carusocomputing)


2

JavaScript (ES6), 92 89 87 86 bytes

Pega entrada p(padrão) e s(string) na sintaxe de currying (p)(s). Retorna 0/ 1.

p=>g=s=>s&&g(s.slice(1))|[...p].every((C,i,x)=>C==(x[c=s[i]]=x[c]||'XYZ'[c&&j++]),j=0)

Formatado e comentado

p =>                             // main function: takes pattern p as input, returns g
  g = s =>                       // g = recursive function: takes string s as input
    s &&                         // if s is not empty:
      g(s.slice(1))              //   do a recursive call, starting at the next character
    |                            // merge the result with this iteration
    [...p].every((C, i, x) =>    // for each character C at position i in p:
      C ==                       //   check whether C is matching the next expected
      (                          //   character, which is either:
        x[c = s[i]] = x[c] ||    //   - a substitution character already associated to s[i]
        'XYZ'[c && j++]          //   - the next substitution character ('X', 'Y' or 'Z')
      ),                         //   - undefined if c = s[i] doesn't exist or j > 2
      j = 0                      //   initialize j = pointer in 'XYZ'
    )                            //

Casos de teste

let f =

p=>g=s=>s&&g(s.slice(1))|[...p].every((C,i,x)=>C==(x[c=s[i]]=x[c]||'XYZ'[c&&j++]),j=0)

console.log(f("XXYY")("succeed"))   // 1
console.log(f("XXYY")("success"))   // 0
console.log(f("XXYY")("balloon"))   // 1
console.log(f("XYXYZ")("bananas"))  // 1
console.log(f("XYXYZ")("banana"))   // 0


0

Mathematica 18 caracteres (sem contar a sequência e o padrão)

StringContainsQ[string,pattern]

Exemplos:

StringContainsQ["succeed", x_ ~~ x_ ~~ y_ ~~ y_]

True

StringContainsQ["bananas", x_ ~~ y_ ~~ x_ ~~ y_ ~~ z_]

True


Isso é inválido porque não aceita a sequência e o padrão como entradas de sequência, conforme necessário.
lirtosiast 12/07
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.