Prefijo común más largo de 2 cadenas


30

Escriba un programa que tome 2 cadenas como entrada y devuelva el prefijo común más largo. Este es el , por lo que gana la respuesta con la menor cantidad de bytes.

Test Case 1:

"global" , "glossary"
"glo"


Test Case 2:

"department" , "depart"
"depart"

Test Case 3:

"glove", "dove"
""

1
Otro buen caso de prueba es "aca", "aba".
Morgan Thrapp

2
¿Desea un programa completo que ingrese desde STDIN e imprima en STDOUT, o las funciones son correctas?
xnor

2
¿Podemos suponer que la entrada no tendrá nuevas líneas? ¿Qué caracteres tendrá la entrada?
Downgoat

55
Nota general: las personas que usan una solución basada en expresiones regulares no deben copiar las respuestas de expresiones regulares de otras personas sin probarlas usted mismo; Esto no funciona en todos los motores regex. En particular, proporciona respuestas diferentes (ambas incorrectas) en nvi y vim.
Random832

1
Todos los ejemplos dados están en minúsculas, pero ¿debemos preocuparnos por la sensibilidad a mayúsculas y minúsculas? Por ejemplo, debería globaly GLOSSARYvolver gloo ''?
AdmBorkBork

Respuestas:


22

Python 3, 54 bytes

¡Gracias Python por tener una función integrada para esta tarea! :RE

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

Toma entrada como dos palabras separadas por un espacio como glossary global.


21

Haskell, 29 bytes

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

Uso:

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

Define recursivamente la función binaria %por coincidencia de patrones. En dos cadenas con las primeras letras iguales, toma esas primeras letras y las antepone a la función del resto de las cadenas. En cualquier otra cosa, da la cadena vacía.


11

Pyth, 8 7 bytes

e@F._MQ

Gracias @isaacg por 1 byte de descuento

Toma la entrada entre comillas y separadas por comas, como "abc", "acc". Esto sale por un error (pero deja stdout vacío) cuando el resultado es la cadena vacía. Si eso es inaceptable, agregue 2 bytes para#e@F._MQq

Banco de pruebas

Explicación

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 que el resultado sea una cadena vacía sin error: e|@F._M.z]k.
kirbyfan64sos

@ kirbyfan64sos Creo que lo que puse sobre rodearlo #...qes un byte menos que eso, lo
editaré

1
Tome la entrada en el formulario "abc", "def"y puede usar en Qlugar 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++]);}

Lee dos cadenas de stdin, imprime el carácter en la posición actual de una de las cadenas, mientras que el carácter en la posición actual es igual al carácter en la misma posición en la otra cadena.

Gracias a Zereges por guardar un byte.


44
Ese es un uso hermoso y aterrador de la fordeclaración ...
Joshpbarron

El ciclo no podría terminar si las cadenas fueran iguales.
Jon Trauntvein

2
No funcionará para cadenas que contengan espacios en blanco. Puede guardar un byte haciendo int ien el espacio global (para que sea 0 inicializado)
Zereges

@ JonTrauntvein Creo que ese caso es UB (?). Sin embargo, funciona ™ para mí. (gcc-5.1)
sweerpotato

9

Haskell, 38 bytes

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

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

Comprime ambas cadenas de entrada en una lista de pares de caracteres. Haga dos listas: la primera con todos los pares desde el principio siempre que ambos personajes sean iguales, la segunda con todos los restos. Suelte la segunda lista y extraiga todos los caracteres de la primera lista.


9

CJam, 12 11 9 bytes

l_q.-{}#<

Esto lee las cuerdas de dos líneas separadas con terminación de línea de estilo Unix, es decir, <string>\n<string>\n.

¡Gracias a @ MartinBüttner por -1 byte y a @ jimmy23013 por -2 bytes!

Pruébelo en línea en el intérprete de CJam .

Cómo 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.

¡Maldición, no puedo creer que mi primera respuesta haya sido tan cercana!
geokavel

1
Puede hacer trampa un poco asumiendo una nueva línea final y su uso l_q.-.
jimmy23013

@ jimmy23013 Eso es estándar para la entrada en sistemas operativos tipo Unix, entonces, ¿por qué no? ¡Gracias!
Dennis

8

APL, 13

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

Esta es una función que toma una matriz de dos cadenas y devuelve el prefijo:

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

¿Es realmente justo decir que el alfabeto APL es un alfabeto de caracteres de tamaño de byte? ¿O es esa práctica estándar por aquí?
Filipq

99
Las respuestas de @Filipq aquí usan la codificación más natural del lenguaje. APL tiene su propia página de códigos en la que cada carácter es un solo byte.
Alex A.

7

AppleScript, 215 bytes

Y lo intenté mucho ...; (

establezca x en el texto de "diálogo de visualización" "respuesta predeterminada" ") devuelto
establezca el texto devuelto a (mostrar diálogo "" respuesta predeterminada "")
establecer n a 1
establecer o en ""
repetir mientras el elemento n de x = el elemento n de a
establecer o en el elemento n de o & x
establecer n en n + 1
fin
o

Quería ver qué tan bien AppleScript podría lograr esto, y hombre , no está diseñado para comparaciones de cadenas.


12
AppleScript no fue creado para nada .
kirbyfan64sos

Lo único para lo que lo uso además de los terribles campos de golf es tell app "System Events" to <something>. Sin embargo, es interesante ver cómo se trata este tipo de cosas. @ kirbyfan64sos
Addison Crump


6

sed, 18

Tenía algo mucho más largo y más complicado en mente, así que el crédito por esta idea va a @ kirbyfan64sos .

s/(.*).* \1.*/\1/

Incluye +1 para la -ropción de sed.


¿Cuál fue tu idea original?
kirbyfan64sos

@ kirbyfan64sos Básicamente implicaba recorrer los personajes uno por uno y detenerse en una falta de coincidencia. Era solo una idea, sin código detrás.
Trauma digital el

6

CJam, 12 8 26

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

Pruébalo en línea.

(Tengo idea de usar. = En lugar de .- después de ver la respuesta de Dennis).

Con todos los casos límite, se hizo difícil para un principiante de CJam como yo mantenerlo corto. Con suerte, esto al menos funciona para todos los 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);}}

Sé que no es terriblemente competitivo. Solo quería ver cómo se vería.

EDITAR: Gracias Ash Burlakzenko, Berend y Dennis_E


2
Solo obtener una respuesta de C # por debajo de 250 bytes es competitivo. Además, ¿no puedes simplemente using System.*?
aplaude el

1
.ForEach(x=>Console.Write(x))podría reducirse a.ForEach(Console.Write)
Ash Burlaczenko

1
using System.Collections.Generic;es innecesario Afeite un byte más quitando el espacio de string[] a.
Berend

2
1-El Containses innecesario. 2-Puede guardar algunos bytes quitando using System;y diciendo System.Console.Write;3-Este código devuelve el resultado incorrecto ("a") para la entrada "aab", "aaab", debido a IndexOf. La solución más corta que se me ocurre es usar a[0].Take(a[1].Length)Esto tiene 147 bytes de longitud: "usando System.Linq; clase a {Main void Main (string [] a) {a [0] .Take (a [1] .Length) .TakeWhile ((c, i) => a [1] [i] == c) .ToList (). ForEach (System.Console.Write);}} "
Dennis_E

Gracias por los comentarios cuando tenga un descanso, los echaré un buen vistazo, especialmente el comentario de Dennis_E.
Jakotheshadows

5

Lisp común, 39

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

Toma dos argumentos de cadena, determina el índice i donde difieren y devuelve una subcadena de 0 a i .


5

Perl 5, 20 19 18 bytes

19 bytes, más 1 para la -Ebandera en lugar de -e:

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

Esto es copiado descaradamente de Digital Trauma 's respuesta SED . Se supone que la entrada es un par de palabras sin espacios en ellas (o antes de la primera) y con un espacio entre ellas.


Actualizar:

ThisSuitIsBlackNot sugirió usar -pelo siguiente para guardar un byte (¡gracias!):

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

Y luego Luk Storms sugirió usar -nElo siguiente para guardar otro byte (¡gracias!):

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

(Estoy contando -Ecomo un byte en lugar de la norma -e, pero -no -pcomo dos. Mi impresión es que eso es SOP por aquí.)


1
" -M5.010, cuando es necesario, es gratis" . Por la misma meta publicación, -peo -nesería 1 byte adicional, no 2. Entonces perl -nE 'say/^(.*).* \1/'obtendría 16 bytes.
ThisSuitIsBlackNot

4

Pitón 3, 72

31 bytes guardados gracias a FryAmTheEggman. 8 guardados gracias a DSM.

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

¿Sin qué harían los programadores de Python zip? : D
Beta Decay

77
@BetaDecay Nuestra mosca estaría abierta todo el tiempo.
Morgan Thrapp

Puede poner la input()s en el zipy guardar el ay el benlace.
DSM

@DSM Ooo, buen punto. ¡Gracias!
Morgan Thrapp

4

Pitón 3, 47

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

Una función que toma una lista wde dos palabras e imprime el prefijo común antes de terminar con un error.

La printfunción de Python 3 le permite imprimir cadenas alineadas entre sí print(end=c)(gracias a Sp3000 por guardar 3 bytes con esta sintaxis más corta). Esto repetidamente toma dos letras de las palabras e imprime la primera de las letras. La indexación c[c!=d]da un error fuera de límites donde c!=d, terminando la ejecución cuando se encuentran dos letras desiguales.

Un bucle for explícito es un carácter más largo que la comprensión de la lista:

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

¡Guauu! ¡Ni siquiera había pensado en usar una función! Buena esa. +1
Zach Gates

Solo vi esto ahora, pero ¿qué tal print(end=c[c!=d])?
Sp3000

1
@ Sp3000 Wow, nunca conecté que el argumento principal de printser opcional significaba que podía llamarse solo con el argumento final, y que podría contener la cadena. Ese es un truco realmente útil en general. Deberías hacer una propina.
xnor

3

Javascript ES6, 52 bytes

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

Uso:

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

No funciona con ada,aca...
flawr 03 de

Vaya, arreglado. Olvidé matar el filtrado después de que las cadenas ya no coinciden.
Dendrobium el

1
No necesita nombrar la función, por lo que puede omitir elf=
Ypnypn

1
puedes hacerlo más pequeño con el mapa(a,b)=>[...a].map((e,i)=>e==b[i]?e:b='').join``
Shaun H

2

Retina , 14 bytes

Utiliza la misma idea que kirbyfan64sos . Desafortunadamente, a pesar de la afirmación de Martin de que eventualmente el modo Match contará con una forma de imprimir grupos de captura, aún no se ha implementado. De lo contrario, (.*).* \1podría usarse junto con 2 bytes más o menos para alguna opción de cadena de configuración aún no existente.

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

Cada línea iría en su propio archivo, con 1 byte agregado por archivo adicional. Alternativamente, ejecute en un solo archivo con la -sbandera.


La expresión regular equivalente no coincide en vim debido a la codicia (y una expresión regular no codiciosa coincidirá con la subcadena más corta , es decir, en blanco), ¿está seguro de que funciona?
Random832

@ Random832 Intente usar este probador de reemplazo de expresiones regulares , con la opción .NET marcada. Establezca la operación para "reemplazar" y coloque los patrones en los cuadros correctos. No deja de coincidir si debería haber uno. ¿Cómo podría fallar debido a la codicia? Esa es la única razón por la que funciona. \1asegura que ambas palabras comiencen con el mismo prefijo. Entonces, no importa cuán codicioso (.*)sea, \1es lo mismo.
mbomb007

En vim, se niega a coincidir en absoluto: creo que está encontrando una cadena más larga para la primera (. *), Luego no coincide con \ 1, luego no retrocede correctamente a cadenas más cortas.
Random832

@ Random832 Entonces necesitas encontrar algo más para probar tus expresiones regulares.
mbomb007

2

K, 24 bytes

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

Encuentra el mínimo de la longitud de cada cadena. ( (&/#:'x)) Recorte cada cuerda a esa longitud ( #'x). Luego compara, difumina y suma la secuencia resultante:

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

Finalmente, tome tantos caracteres de la primera de las cadenas proporcionadas ( #*x).

En acción:

 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 las cadenas, reduciendo la primera hasta que coincida (imprimir y salir) o la cadena sea nula y el ciclo termine.

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)

Sin golf:

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

Se solucionó un problema (con un costo considerable de 14 bytes) gracias a xnor!


2

C99, 73 bytes

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

Similar a esta respuesta , pero más corta y cumple con las especificaciones (toma la entrada de stdin).


Las especificaciones no dicen que la entrada tiene que venir de stdin. Esto es realmente más largo que la otra respuesta si agrega #include<stdio.h>, que es necesario para que el programa compile.
musaritmia

@AndrewCashner: no es necesario que esté en stdin, pero sí necesita recibir información. La otra respuesta está codificada. Además, gcc se queja del uso implícito, pero se compila bien sin incluir.
Comintern

Mucho más corto sin los temporales: main(int c,char**a){for(;*a[1]==*a[2]++;putchar(*a[1]++));}(59 bytes).
Toby Speight

2

MATLAB, 50 40 bytes

Define una función que acepta 2 cadenas como entrada, salidas a la ventana de comando

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

Esta solución funcionará para cualquier cadena, salidas

ans =

   Empty string: 1-by-0

si no se da coincidencia

Se puede jugar golf usando un script en lugar de una función (usando variables locales a, b) (-16 bytes).

entonces obteniendo 34 Bytes

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

El estilo de función (que parece ser el estilo aceptado), produce

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

(Gracias @Stewie Griffin)


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

2

Perl 6 , 28 bytes

Se me ocurrieron dos que toman sus valores de STDIN que se basan en la respuesta de Perl 5.

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

El primero requiere exactamente un espacio entre las entradas, mientras que el otro requiere al menos un espacio en blanco entre las entradas.


Eso es bastante más corto que lo primero que probé, que toma los valores de la línea de comando.

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

o incluso la versión lambda de la misma:

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

Aunque esto es mucho más fácil de ajustar para que acepte cualquier número de cadenas de entrada, a costa de un solo trazo.

{[~] 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

Japt, 27 bytes

Japt es una versión abreviada de Ja vaScri pt . Interprete

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

(Las cuerdas van en la caja de entrada, así: "global" "glossary")

Este código es exactamente equivalente al siguiente JS:

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

Todavía no he implementado funciones anónimas, que es para lo que $...$sirve: cualquier cosa entre los signos de dólar se deja intacta en el cambio a JS. Después de agregar funciones, este código de 21 bytes será suficiente:

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

Y después de implementar algunas características más, idealmente será de 18 bytes:

UmXY{AxX=VgY ?X:AP

Sugerencias bienvenidas!


Entonces resulta que este programa tiene solo 15 bytes en el Japt moderno:

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

Pruébalo en línea!


2

MATL , 11 9 bytes

y!=XdYpf)

Pruébalo en línea!

(-2 bytes gracias 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

¡Gracias! losy idea es bastante buena, había intentado cosas como una inicial en itilugar de la 1Gw, pero no pensé en usar el ypara eso.
sundar - Restablecer Monica

1

Clojure / ClojureScript, 51

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

Muy claro. Desafortunadamente, los espacios alrededor de la desestructuración de parámetros son necesarios (eso es [a & b]todo). No es el más corto, pero supero algunas otras respuestas en idiomas a los que les gusta alardear de su brevedad, así que lo publicaré.


1

Python 2, 50 bytes

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

Entrada

La entrada se toma como dos cadenas:

"global", "glossary"

Salida

La salida es cada carácter seguido de un espacio; lo cual, con suerte, no es un problema. Sin embargo, si es así, editaré mi respuesta.

g l o 

Estoy bastante seguro de que esto no es válido; la especificación claramente dio el formato de salida como una cadena sin espacios.
lirtosiast el

Bueno, sí, pero la entrada también se dio en el formato "global" , "glossary"(dos cadenas separadas). ¿Cuántas otras respuestas siguen a la carta? @ThomasKwa
Zach Gates

"toma dos cadenas" es el lenguaje utilizado por OP; por lo general, cuando se menciona algo así sin ningún calificador, se refiere a una de nuestras E / S predeterminadas , lo que significa que podemos tomar una cadena de la línea de comando y una de STDIN, o una matriz de dos cadenas, o lo que sea que siga a esas reglas.
lirtosiast el

Creo que te estás tomando mi respuesta demasiado en serio. Esta es solo una presentación divertida y mi mejor intento de vencer a un incorporado. Si a OP no le gusta el formato de salida, que así sea; Eliminaré mi respuesta. @ThomasKwa
Zach Gates

¿Qué tal print(exit()if a!=b else a,end='')? No sé si eso funcionará o no, pero podría
Beta Decay

1

TeaScript, 16 bytes 20

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

Toma cada entrada separada por un espacio.


1

PHP, 52 bytes

No es espectacular pero hace el trabajo:

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

Toma dos argumentos de línea de comando:

php prefix.php department depart

PHP7 le permite guardar otro byte while(($a=$argv)[1][$i]==$a[2][$i])echo$a[1][$i++];: otra solución única de PHP7 (y lo mejor que puedo encontrar con @ 50 bytes) <?=substr(($a=$argv)[1],0,strspn($a[1]^$a[2],~ÿ));. Asegúrese de que su editor esté en modo ASCII, es importante ~ÿque no se convierta a Unicode.
Leigh
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.