Prefixo comum mais longo de 2 strings


30

Escreva um programa que use 2 strings como entrada e retorne o prefixo comum mais longo. Isso é , então a resposta com a menor quantidade de bytes vence.

Test Case 1:

"global" , "glossary"
"glo"


Test Case 2:

"department" , "depart"
"depart"

Test Case 3:

"glove", "dove"
""

1
Outro bom caso de teste é "aca", "aba".
Morgan Thrapp

2
Deseja um programa completo que insira STDIN e imprima em STDOUT, ou as funções estão OK?
Xnor

2
Podemos assumir que a entrada não terá novas linhas? Quais caracteres a entrada terá?
Downgoat 03/11/2015

5
Nota geral: as pessoas que usam uma solução baseada em regex não devem copiar as respostas regex de outras pessoas sem testá-las; isso não funciona em todos os mecanismos regex. Em particular, fornece respostas diferentes (ambas incorretas) no nvi e no vim.
Random832

1
Todos os exemplos apresentados estão em letras minúsculas, mas precisamos nos preocupar com a distinção entre maiúsculas e minúsculas? Por exemplo, deve globale deve GLOSSARYretornar gloou ''?
AdmBorkBork #

Respostas:


22

Python 3, 54 bytes

Obrigado Python por ter uma função interna para esta tarefa! : D

import os;print(os.path.commonprefix(input().split()))

Recebe a entrada como duas palavras separadas por um espaço como glossary global.


21

Haskell, 29 bytes

(c:x)%(d:y)|c==d=c:x%y;_%_=""

Uso:

>> "global"%"glossary"
"glo"

Define recursivamente a função binária %por correspondência de padrões. Em duas cadeias com primeiras letras iguais, pega essas primeiras letras e o anexa à função do restante das cadeias. Em qualquer outra coisa, fornece a string vazia.


11

Pitão, 8 7 bytes

e@F._MQ

Obrigado @isaacg por 1 byte de desconto

Pega a entrada entre aspas e vírgula, como "abc", "acc". Isso ocorre com um erro (mas deixa o stdout vazio) quando o resultado é a sequência vazia. Se isso for inaceitável, adicione 2 bytes para#e@F._MQq

Suíte de teste

Explicação

e@F._MQ        : implicit Q = eval(input)
   ._MQ        : Map the prefix operator onto both inputs
 @F            : Fold the setwise intersection operator over those lists
e              : Take the last such element, the prefixes are always made from shortest
               : to longest, so this always gives the longest matching prefix

Para fazer o resultado a cadeia vazia, sem erro: e|@F._M.z]k.
Kirbyfan64sos #

@ kirbyfan64sos Eu acredito que a coisa que eu coloquei em cerca em torno dela com #...qum byte menos do que isso, eu vou editar no código completo, eu acho que é confuso
FryAmTheEggman

1
Tome entrada na forma "abc", "def"e você pode usar Qem vez de.z
isaacg

10

C ++, 101 100 99 bytes

#include<iostream>
int i;main(){std::string s,t;std::cin>>s>>t;for(;s[i]==t[i];std::cout<<s[i++]);}

Lê duas strings de stdin, imprime o caractere na posição atual a partir de uma das strings, enquanto o caractere na posição atual é igual ao caractere na mesma posição na outra string.

Agradecemos a Zereges por salvar um byte.


4
Esse é um uso bonito e aterrorizante da fordeclaração ... #
317 Joshpbarron

O loop falharia ao terminar se as strings fossem iguais.
Jon Trauntvein

2
Não funcionará para cadeias que contenham espaços em branco. Você pode salvar um byte, fazendo int ino espaço global (de modo que ele será 0 inicializado)
Zereges

@ JonTrauntvein Acho que esse caso é UB (?). Mas funciona para mim. (gcc-5.1)
sweerpotato

9

Haskell, 38 bytes

((map fst.fst.span(uncurry(==))).).zip

Exemplo de uso: ( ((map fst.fst.span(uncurry(==))).).zip ) "global" "glossary"-> "glo".

Compacte ambas as seqüências de entrada em uma lista de pares de caracteres. Faça duas listas: a primeira com todos os pares desde o início, desde que os dois caracteres sejam iguais, a segunda com todos os demais. Solte a segunda lista e extraia todos os caracteres da primeira lista.


9

CJam, 12 11 9 bytes

l_q.-{}#<

Isso lê as strings em duas linhas separadas com final de linha no estilo Unix, ou seja <string>\n<string>\n,.

Obrigado a @ MartinBüttner por -1 byte e a @ jimmy23013 por -2 bytes!

Experimente online no intérprete CJam .

Como funciona

l_         e# Read a line (w/o trailing LF) from STDIN and push a copy.
  q        e# Read another line from STDIN (with trailing LF).
           e# The trailing linefeed makes sure that the lines are not equal.
   .-      e# Perform vectorized character subtraction. This yields 0 for equal
           e# characters, a non-zero value for two different characters, and the
           e# characters themselves (truthy) for the tail of the longer string.
     {}#   e# Find the index of the first truthy element.
        <  e# Keep that many characters from the first string.

Droga, não acredito que minha primeira resposta foi tão próxima!
geokavel

1
Você pode trapacear um pouco assumindo uma nova linha e uso à direita l_q.-.
precisa saber é o seguinte

@ jimmy23013 Isso é padrão para entrada em sistemas operacionais semelhantes ao Unix, então por que não? Obrigado!
Dennis

8

APL, 13

{⊃↓K/⍨=⌿K←↑⍵}

Esta é uma função que pega uma matriz de duas seqüências e retorna o prefixo:

      {⊃↓K/⍨=⌿K←↑⍵}'glossary' 'global'
glo
      {⊃↓K/⍨=⌿K←↑⍵}'department' 'depart'
depart

É realmente justo dizer que o alfabeto da APL é um alfabeto de caracteres do tamanho de bytes? Ou isso é prática padrão por aqui?
Filipq

9
As respostas do @Filipq aqui usam a codificação mais natural para o idioma. O APL possui sua própria página de código na qual cada caractere é um único byte.
Alex A.

7

AppleScript, 215 bytes

E eu tentei tanto ...; (

defina x como (texto da caixa de diálogo "" resposta padrão "") retornado
defina o texto de a para (exibir "" resposta padrão "") retornado
defina n como 1
defina o como ""
repita enquanto o item x de n = item n de a
defina o como o & x's item n
defina n para n + 1
fim
o

Eu queria ver o quão bem o AppleScript poderia fazer isso, e o homem não é construído para comparações de strings.


12
AppleScript não foi construído para nada .
precisa saber é o seguinte

A única coisa que eu uso para além de terríveis campos de golfe é tell app "System Events" to <something>. Ele é interessante ver como ele lida com esse tipo de coisa, no entanto. @ kirbyfan64sos
Addison Crump



6

CJam, 12 8 26

r:AAr:B.=0#_W={;;ABe<}{<}?

Experimente online.

(Tenho idéia de usar. = Em vez de .- depois de olhar para a resposta de Dennis.)

Com todos os casos extremos, tornou-se difícil para um iniciante do CJam como eu mantê-lo curto. Felizmente, isso pelo menos funciona para todos os casos.


6

C #, 201 147 bytes

using System.Linq;class a{static void Main(string[]a){a[0].Take(a[1].Length).TakeWhile((t,i)=>a[1][i]==t).ToList().ForEach(System.Console.Write);}}

Eu sei que não é terrivelmente competitivo. Eu só queria ver como seria.

EDIT: Obrigado Ash Burlakzenko, Berend e Dennis_E


2
Obter uma resposta em C # abaixo de 250 bytes é competitivo. Além disso, você não pode apenas using System.*?
clap

1
.ForEach(x=>Console.Write(x))poderia ser reduzido para.ForEach(Console.Write)
Ash Burlaczenko

1
using System.Collections.Generic;é desnecessário. Raspe mais um byte removendo o espaço de string[] a.
Berend

2
1-O Containsé desnecessário. 2-Você pode salvar alguns bytes removendo using System;e dizendo System.Console.Write;3-Este código retorna o resultado errado ("a") para a entrada "aab", "aaab", por causa de IndexOf. A correção mais curta que eu pude pensar é usar a[0].Take(a[1].Length)This is 147 bytes long: "using System.Linq; class a {static void Main (string [] a) {a [0] .Take (a [1] .Length) .TakeWhile ((c, i) => a [1] [i] == c) .ToList (). ForEach (System.Console.Write);}} "
Dennis_E 4/15/15

Obrigado pelos comentários quando tiver uma pausa. Vou dar uma boa olhada em todos eles, especialmente no comentário de Dennis_E.
Jakotheshadows 4/11/15

5

Lisp comum, 39

(lambda(a b)(subseq a 0(mismatch a b)))

Pega dois argumentos de string, determina o índice i onde eles diferem e retorna uma substring de 0 a i .


5

Perl 5, 20 19 18 bytes

19 bytes, mais 1 para o -Esinalizador em vez de -e:

say<>=~/^(.*).* \1/

Isto é copiado descaradamente de Trauma Digital 's resposta sed . Ele pressupõe que a entrada seja um par de palavras sem espaços (ou antes da primeira) e com um espaço entre elas.


Atualizar:

ThisSuitIsBlackNot sugeriu o uso da -peseguinte maneira, para salvar um byte (obrigado!):

($_)=/^(.*).* \1/

E então Luk Storms sugeriu o uso da -nEseguinte maneira para salvar outro byte (obrigado!):

say/^(.*).* \1/

(Eu estou contando -Ecomo um byte em vez do padrão -e, mas -nou -pcomo dois. Minha impressão é que isso é SOP por aqui.)


1
" -M5.010, quando necessário, é gratuito" . Pela mesma meta postagem, -peou -nehaveria 1 byte adicional, não 2. Portanto, perl -nE 'say/^(.*).* \1/'seria 16 bytes.
precisa saber é o seguinte

4

Python 3, 72

31 bytes salvos graças ao FryAmTheEggman. 8 salvos graças ao DSM.

r=''
for x,y in zip(input(),input()):
 if x==y:r+=x
 else:break
print(r)

O que os programadores Python prescindiriam zip? : D
Decay Beta

7
@BetaDecay Nossa mosca estaria aberta o tempo todo.
Morgan Thrapp

Você poderia colocar os input()s no zipe salvar o ae bvinculativo.
DSM

@DSM Ooo, bom ponto. Obrigado!
Morgan Thrapp

4

Python 3, 47

def f(w):[print(end=c[c!=d])for c,d in zip(*w)]

Uma função que pega uma lista wde duas palavras e imprime o prefixo comum antes de terminar com um erro.

A printfunção do Python 3 permite imprimir seqüências de caracteres alinhadas umas com as outras print(end=c)(obrigado ao Sp3000 por salvar 3 bytes com esta sintaxe mais curta). Isso pega repetidamente duas letras das palavras e imprime a primeira das letras. A indexação c[c!=d]gera um erro fora dos limites em que c!=d, finalizando a execução quando duas letras desiguais são encontradas.

Um loop for explícito é um caractere mais longo que a compreensão da lista:

def f(w):
 for c,d in zip(*w):print(end=c[c!=d])

Uau! Eu nem tinha pensado em usar uma função! Agradável. 1
Zach Gates

Só vi isso agora, mas e quanto print(end=c[c!=d])?
Sp3000 10/11/2015

1
@ Sp3000 Uau, nunca conectei que o argumento principal de printser opcional significava que poderia ser chamado apenas com o argumento final e que poderia conter a string. Esse é um truque realmente útil em geral. Você deveria dar uma dica.
Xnor

3

Javascript ES6, 52 bytes

f=(a,b)=>[...a].filter((e,i)=>e==b[i]?1:b='').join``

Uso:

>> f("global","glossary")
"glo"

Não funciona com ada,aca...
flawr

Opa, fixo. Esqueceu-se de matar a filtragem depois que as strings não coincidem mais.
Dendrobium

1
Você não precisa nomear a função, para que você possa deixar de fora of=
Ypnypn 3/15

1
você pode fazê-lo menor com mapa #(a,b)=>[...a].map((e,i)=>e==b[i]?e:b='').join``
Shaun H

2

Retina , 14 bytes

Usa a mesma idéia que kirbyfan64sos . Infelizmente, apesar da afirmação de Martin de que, eventualmente, o modo Match apresentará uma maneira de imprimir grupos de captura, ele ainda não foi implementado. Caso contrário, (.*).* \1poderia ser usado junto com 2 bytes ou mais para alguma opção de cadeia de configuração ainda não existente.

(.*).* \1.*
$1

Cada linha iria em seu próprio arquivo, com 1 byte adicionado por arquivo adicional. Como alternativa, execute em um único arquivo com o -ssinalizador.


A regex equivalente falha em corresponder no vim devido à cobiça (e uma regex não gananciosa corresponderá à menor substring, ou seja, em branco), tem certeza de que funciona?
precisa saber é o seguinte

@ Random832 Tente usar este regex replace tester , com a opção .NET marcada. Defina a operação para "substituir" e coloque os padrões nas caixas corretas. Não deixa de corresponder se houver um. Como isso poderia falhar devido à ganância? Essa é a única razão pela qual funciona. \1garante que ambas as palavras comecem com o mesmo prefixo. Portanto, não importa quão ganancioso (.*)seja, \1é o mesmo.
mbomb007

No vim, ele se recusa a corresponder - acho que ele está encontrando uma string mais longa para o primeiro (. *), Falhando em correspondê-la com \ 1 e depois não retornando adequadamente a strings mais curtas.
precisa saber é o seguinte

@ Random832 Então você precisa encontrar outra coisa para testar suas expressões regulares.
mbomb007

2

K, 24 bytes

{(+/&\=/(&/#:'x)#'x)#*x}

Encontre o mínimo do comprimento de cada string. ( (&/#:'x)) Apare cada corda com esse comprimento ( #'x). Em seguida, compare, espalhe e some a sequência resultante:

  =/("globaa";"glossa")
1 1 1 0 0 1
  &\=/("globaa";"glossa")
1 1 1 0 0 0
  +/&\=/("globaa";"glossa")
3

Por fim, considere muitos caracteres da primeira das strings fornecidas (#*x ).

Em ação:

 f: {(+/&\=/(&/#:'x)#'x)#*x};
 f'(("global";"glossary")
    ("department";"depart")
    ("glove";"dove")
    ("aaa";"aaaaa")
    ("identical";"identical")
    ("aca";"aba"))
("glo"
 "depart"
 ()
 "aaa"
 "identical"
 ,"a")

2

Powershell, 65 bytes

Compare as cadeias, diminuindo a primeira até corresponder (imprimir e sair) ou a cadeia é nula e o loop termina.

param($a,$b)while($a){if($b-like"$a*"){$a;exit}$a=$a-replace".$"}

2

Julia, 62 bytes

f(a,b)=(c="";for(i,j)=zip(a,b) i!=j?break:(c*=string(i))end;c)

Ungolfed:

function f(a::AbstractString, b::AbstractString)
    # Initialize an output string
    c = ""

    # Iterate over the pairs of characters in a and b,
    # truncated to the shorter of the two lengths
    for (i, j) in zip(a, b)
        if i == j
            # If they match, append to the output string
            c *= string(i)
        else
            # Otherwise stop everything!
            break
        end
    end

    return c
end

Corrigido um problema (com um custo elevado de 14 bytes) graças ao xnor!


2

C99, 73 bytes

main(int c,char *a[]){for(char *x=a[1],*y=a[2];*x==*y++;putchar(*x++));}

Semelhante a esta resposta , mas mais curto e atende às especificações (recebe entrada de stdin).


Spec não diz que a entrada precisa vir de stdin. Na verdade, isso é mais longo que a outra resposta, se você adicionar #include<stdio.h>, o que é necessário para a compilação do programa.
Musarithmia

@AndrewCashner - Ele não precisa estar no stdin, mas precisa receber informações. A outra resposta é codificada. Além disso, o gcc reclama sobre o uso implícito, mas compila bem sem o include.
Comintern

Muito mais curto sem os temporários: main(int c,char**a){for(;*a[1]==*a[2]++;putchar(*a[1]++));}(59 bytes).
precisa

2

MATLAB, 50 40 bytes

Define uma função que aceita 2 seqüências de caracteres como entrada, sai na janela de comando

function t(a,b);a(1:find([diff(char(a,b)) 1],1)-1)

Esta solução funcionará para qualquer string, saídas

ans =

   Empty string: 1-by-0

se nenhuma correspondência for dada.

Pode ser jogado golfe usando um script em vez de uma função (usando variáveis ​​locais a, b) (-16 bytes).

obtendo 34 bytes

a(1:find([diff(char(a,b)) 1],1)-1)

O estilo da função (que parece ser o estilo aceito) gera

@(a,b)a(1:find([diff(char(a,b)) 1],1)-1)

(Obrigado @Stewie Griffin)


40 bytes: @(a,b)a(1:find([diff(char(a,b)) 1],1)-1). =)
Stewie Griffin

2

Perl 6 , 28 bytes

Eu vim com dois que levam seus valores de STDIN, que são baseados na resposta do Perl 5.

lines~~/(.*).*' '$0/;say ~$0
lines~~/:s(.*).* $0/;say ~$0

O primeiro requer exatamente um espaço entre as entradas, enquanto o outro requer pelo menos um caractere de espaço em branco entre as entradas.


Isso é um pouco menor do que a primeira coisa que tentei, que utiliza os valores da linha de comando.

say [~] map ->($a,$b){$a eq$b&&$a||last},[Z] @*ARGS».comb # 58 bytes

ou mesmo a versão lambda:

{[~] map ->($a,$b){$a eq$b&&$a||last},[Z] @_».comb} # 52 bytes

Embora isso seja muito mais fácil de ajustar para aceitar qualquer número de strings de entrada, ao custo de apenas um toque.

{[~] map ->@b {([eq] @b)&&@b[0]||last},[Z] @_».comb} # 53 bytes
#          ┗━┛ ┗━━━━━━━┛  ┗━━━┛
my &common-prefix = {[~] map ->@b {([eq] @b)&&@b[0]||last},[Z] @_».comb}

say common-prefix <department depart>; # "depart"
say common-prefix; # ""
say common-prefix <department depart depot deprecated dependant>; # "dep"

# This code does not work directly with a single argument, so you have
# to give it an itemized List or Array, containing a single element.

say common-prefix $('department',); # "department"

# another option would be to replace `@_` with `(@_,)`

2

Japonês, 27 bytes

Japt é uma versão abreviada do Ja vaScri pt .Intérprete

Um$(X,Y)=>$A&&X==VgY ?X:A=P

(As seqüências de caracteres entram na caixa de entrada da seguinte maneira: "global" "glossary" )

Este código é exatamente equivalente ao seguinte JS:

A=10;(U,V)=>U.split``.map((X,Y)=>A&&X==V[Y]?X:A="").join``

Ainda não implementei funções anônimas, para que serve $...$: qualquer coisa entre os cifrões é deixada intocada na mudança para JS. Depois de adicionar funções, este código de 21 bytes será suficiente:

UmXY{A&&X==VgY ?X:A=P

E depois de implementar mais alguns recursos, o ideal é ter 18 bytes:

UmXY{AxX=VgY ?X:AP

Sugestões são bem-vindas!


Portanto, esse programa tem apenas 15 bytes no Japt moderno:

¡A©X¥VgY ?X:A=P

Experimente online!


2

MATL , 11 9 bytes

y!=XdYpf)

Experimente online!

(-2 bytes graças a Giuseppe)

 y  % implicitly input the two strings, then duplicate the
    %  first one into the stack again
    %  stack: ['department' 'deported' 'department']
 !  % transpose the last string into a column vector
 =  % broadcast equality check - gives back a matrix comparing
    %  every letter in first input with the letters in the second
 Xd % diagonal of the matrix - comparison result of each letter with
    %  only corresponding letter in the other string
    %  stack: ['department' [1; 1; 1; 0; 1; 1; 0; 0;]]
 Yp % cumulative product (so only initial sequence of 1s remains
    %  1s, others become 0)
    %  stack: ['department' [1; 1; 1; 0; 0; 0; 0; 0;]]
 f  %  find the indices of the 1s
 )  % index at those elements so we get those letters out
    % (implicit) convert to string and display

Obrigado! A yidéia é muito boa, eu tentei coisas como uma inicial em itivez de 1Gw, mas não pensei em usar yisso para isso.
Sundar - Restabelece Monica

1

Clojure / ClojureScript, 51

(defn f[[a & b][c & d]](if(= a c)(str a(f b d))""))

Bem direto. Infelizmente, os espaços ao redor do parâmetro de desestruturação são necessários (esse é o problema [a & b]). Não é o mais curto, mas eu bati algumas outras respostas em idiomas que gostam de se gabar de sua discrepância, então eu a publicarei.


1

Python 2, 50 bytes

for a,b in zip(*input()):print(1/0if a!=b else a),

Entrada

A entrada é tomada como duas cadeias:

"global", "glossary"

Saída

A saída é cada caractere seguido por um espaço; o que, espero, não seja um problema. No entanto, se for, editarei minha resposta.

g l o 

Tenho certeza de que isso é inválido; a especificação deu claramente o formato de saída como uma sequência sem espaços.
lirtosiast

Bem, sim, mas a entrada também foi dada no formato "global" , "glossary"(duas seqüências de caracteres separadas) .. Quantas outras respostas seguem essa letra? @ThomasKwa
Zach Gates

"takes two strings" é o idioma usado pelo OP; geralmente quando algo assim é mencionado sem nenhum qualificador, refere-se a um de nossos E / S padrão , o que significa que podemos pegar uma string da linha de comando e uma do STDIN, ou uma matriz de duas strings, ou qualquer outra coisa que as siga. regras.
Lirtosiast

Acho que você está levando a minha resposta um pouco a sério. Esta é apenas uma apresentação divertida e minha melhor tentativa de derrotar uma incorporada. Se o OP não gostar do formato de saída, que assim seja; Vou remover minha resposta. @ThomasKwa
Zach Gates

Que tal print(exit()if a!=b else a,end='')? Eu não sei se isso vai funcionar ou não, mas pode ser
Beta Decay

1

TeaScript, 16 bytes 20

xf»l¦y[i]?1:b=0)

Separa cada entrada por um espaço.


1

PHP, 52 bytes

Não é espetacular, mas faz o trabalho:

$a=$argv;while($a[1][$i]==$a[2][$i])echo$a[1][$i++];

Leva dois argumentos de linha de comando:

php prefix.php department depart

O PHP7 permite que você salve outro byte while(($a=$argv)[1][$i]==$a[2][$i])echo$a[1][$i++];- Outra solução apenas para o PHP7 (e o melhor que eu poderia criar com @ 50 bytes) <?=substr(($a=$argv)[1],0,strspn($a[1]^$a[2],~ÿ));- Verifique se o editor está no modo ascii, é importante~ÿ que não seja convertido em unicode.
Leigh
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.