Prefisso comune più lungo di 2 stringhe


30

Scrivi un programma che accetta 2 stringhe come input e restituisce il prefisso comune più lungo. Questo è , quindi vince la risposta con il minor numero di byte.

Test Case 1:

"global" , "glossary"
"glo"


Test Case 2:

"department" , "depart"
"depart"

Test Case 3:

"glove", "dove"
""

1
Un altro buon caso di test è "aca", "aba".
Morgan Thrapp,

2
Desideri programmi completi che immettano da STDIN e stampino su STDOUT, oppure le funzioni sono OK?
xnor

2
Possiamo presumere che l'input non avrà newline? Quali caratteri avrà l'input?
Downgoat,

5
Nota generale: le persone che utilizzano una soluzione basata su regex non devono copiare le risposte regex di altre persone senza testarle personalmente; questo non funziona in tutti i motori regex. In particolare, fornisce risposte diverse (entrambe errate) in nvi e vim.
Casuale 832

1
Tutti gli esempi forniti sono in minuscolo, ma dobbiamo preoccuparci della distinzione tra maiuscole e minuscole? Ad esempio, dovrebbe globale GLOSSARYrestituire gloo ''?
AdmBorkBork,

Risposte:


22

Python 3, 54 byte

Grazie a Python per avere una funzione integrata per questo compito! : D

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

Accetta input come due parole separate da uno spazio come glossary global.


21

Haskell, 29 byte

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

Uso:

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

Definisce in modo ricorsivo la funzione binaria %mediante la corrispondenza del modello. Su due stringhe con uguali prime lettere, prende quelle prime lettere e le antepone alla funzione del resto delle stringhe. Su qualsiasi altra cosa, dà la stringa vuota.


11

Pyth, 8 7 byte

e@F._MQ

Grazie @isaacg per 1 byte di sconto

Accetta input tra virgolette e virgola separati, come "abc", "acc". Questo esce su un errore (ma lascia vuoto stdout) quando il risultato è la stringa vuota. Se ciò è inaccettabile, aggiungere 2 byte per#e@F._MQq

Test Suite

Spiegazione

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

Per rendere il risultato la stringa vuota senza errori: e|@F._M.z]k.
Kirbyfan64sos,

@ kirbyfan64sos Credo che la cosa che ho inserito nel circondarlo #...qsia un byte in meno di quello, lo modificherò nel codice completo, immagino che sia confuso
FryAmTheEggman,

1
Prendi l'input nel modulo "abc", "def"e puoi usare Qinvece di.z
isaacg

10

C ++, 101 100 99 byte

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

Legge due stringhe da stdin, stampa il carattere nella posizione corrente da una delle stringhe mentre il carattere nella posizione corrente è uguale al carattere nella stessa posizione nell'altra stringa.

Grazie a Zereges per aver salvato un byte.


4
Questo è un uso bellissimo e terrificante della fordichiarazione ...
Joshpbarron,

Il loop non terminerebbe se le stringhe fossero uguali.
Jon Trauntvein,

2
Non funziona con stringhe contenenti spazi bianchi. Puoi salvare un byte, creando int inello spazio globale (in modo che sia 0 inizializzato)
Zereges

@JonTrauntvein Penso che il caso sia UB (?). Funziona ™ per me però. (gcc-5.1)
sweerpotato,

9

Haskell, 38 byte

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

Esempio di utilizzo: ( ((map fst.fst.span(uncurry(==))).).zip ) "global" "glossary"-> "glo".

Comprimi entrambe le stringhe di input in un elenco di coppie di caratteri. Crea due elenchi: il primo con tutte le coppie dall'inizio purché entrambi i caratteri siano uguali, il secondo con tutti gli altri. Rilascia il secondo elenco ed estrai tutti i caratteri dal primo elenco.


9

CJam, 12 11 9 byte

l_q.-{}#<

Questo legge le stringhe su due linee separate con un finale di linea in stile Unix, cioè <string>\n<string>\n.

Grazie a @ MartinBüttner per -1 byte e a @ jimmy23013 per -2 byte!

Provalo online nell'interprete CJam .

Come funziona

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.

Accidenti, non posso credere che la mia prima risposta sia stata così vicina!
geokavel,

1
Puoi imbrogliare un po 'assumendo una nuova riga finale e usandola l_q.-.
jimmy23013,

@ jimmy23013 È lo standard per l'input su sistemi operativi simili a Unix, quindi perché no? Grazie!
Dennis,

8

APL, 13

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

Questa è una funzione che accetta una matrice di due stringhe e restituisce il prefisso:

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

È davvero giusto dire che l'alfabeto APL è un alfabeto di caratteri di dimensioni in byte? O è quella pratica standard qui?
Filipq,

9
@Filipq Le risposte qui usano la codifica più naturale per la lingua. APL ha una propria tabella codici in cui ogni carattere è un singolo byte.
Alex A.

7

AppleScript, 215 byte

E ho provato così duramente ...; (

imposta x su (visualizza la finestra di dialogo "" risposta predefinita "") il testo restituito
impostare un testo di (visualizza la finestra di dialogo "" risposta predefinita "") restituito
impostare n su 1
impostare o su ""
ripetere mentre l'articolo di x n = l'articolo di a n
imposta o su o & x's articolo n
imposta n su n + 1
fine
o

Volevo vedere quanto AppleScript potesse farcela, e non è fatto per il confronto delle stringhe.


12
AppleScript non è stato creato per nulla .
kirbyfan64sos,

L'unica cosa per cui lo uso oltre a golf terribili è tell app "System Events" to <something>. Si è interessante vedere come si tratta di questo genere di cose, però. @ kirbyfan64sos
Addison Crump

6

rs , 14 byte

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

Demo live e casi di test.

Questo è abbastanza semplice Corrisponde solo al ... prefisso comune più lungo e rimuove il resto della stringa. Se non esiste un prefisso comune più lungo, cancella tutto.


6

sed, 18

Avevo in mente qualcosa di molto più lungo e complicato, quindi il merito di questa idea va a @ kirbyfan64sos .

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

Include +1 per l' -ropzione di sed.


Qual è stata la tua idea originale?
kirbyfan64sos,

@ kirbyfan64sos Fondamentalmente si trattava di scorrere i personaggi uno alla volta e fermarsi a una discrepanza. Era solo un'idea - nessun codice dietro.
Digital Trauma,

6

CJam, 12 8 26

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

Provalo online.

(Ho avuto l'idea di usare. = Invece di .- dopo aver visto la risposta di Dennis.)

Con tutti i casi limite, è diventato difficile per un principiante CJam come me tenerlo breve. Speriamo che questo funzioni almeno per tutti i casi.


6

C #, 201 147 byte

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

So che non è terribilmente competitivo. Volevo solo vedere come sarebbe stato.

EDIT: Grazie Ash Burlakzenko, Berend e Dennis_E


2
È solo competitivo ottenere una risposta C # inferiore a 250 byte. Inoltre, non puoi using System.*?
applaude il

1
.ForEach(x=>Console.Write(x))potrebbe essere abbreviato in.ForEach(Console.Write)
Ash Burlaczenko il

1
using System.Collections.Generic;non è necessario. Elimina un altro byte rimuovendo lo spazio da string[] a.
Berend,

2
1-The Containsnon è necessario. 2-È possibile salvare alcuni byte rimuovendo using System;e dicendo System.Console.Write;3-Questo codice restituisce il risultato errato ("a") per l'input "aab", "aaab", a causa di IndexOf. La soluzione più breve che mi viene in mente è l'utilizzo di a[0].Take(a[1].Length)Questa lunghezza è di 147 byte: "utilizzo 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

Grazie per i commenti quando avrò una pausa darò una buona occhiata a tutti, in particolare al commento di Dennis_E.
Jakotheshadows il

5

Lisp comune, 39

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

Accetta due argomenti di stringa, determina l'indice i in cui differiscono e restituisce una sottostringa da 0 a i .


5

Perl 5, 20 19 18 byte

19 byte, più 1 per la -Ebandiera anziché -e:

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

Questo è copiato spudoratamente da trauma digitale 's risposta sed . Presuppone che l'input sia composto da un paio di parole senza spazi (o prima del primo) e con uno spazio tra loro.


Aggiornare:

ThisSuitIsBlackNot ha suggerito di utilizzare -pecome segue, per salvare un byte (grazie!):

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

E poi Luk Storms ha suggerito di usare -nEcome segue per salvare un altro byte (grazie!):

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

(Sto contando -Ecome un byte anziché lo standard -e, ma -no -pcome due. La mia impressione è che sia SOP da queste parti.)


1
" -M5.010, quando necessario, è gratuito" . Per lo stesso meta post, -peo -nesarebbe 1 byte aggiuntivo, non 2. Quindi perl -nE 'say/^(.*).* \1/'farebbe segnare 16 byte.
ThisSuitIsBlackNon

4

Python 3, 72

31 byte salvati grazie a FryAmTheEggman. 8 salvati grazie a DSM.

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

Cosa farebbe senza i programmatori Python zip? : D
Decadimento beta

7
@BetaDecay La nostra mosca sarebbe sempre aperta.
Morgan Thrapp,

È possibile inserire la input()s in zipe salvare il ae il bbinding.
DSM,

@DSM Ooo, buon punto. Grazie!
Morgan Thrapp,

4

Python 3, 47

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

Una funzione che accetta un elenco wdi due parole e stampa il prefisso comune prima di terminare con un errore.

La printfunzione di Python 3 ti consente di stampare le stringhe una contro l'altra print(end=c)(grazie a Sp3000 per aver salvato 3 byte con questa sintassi più breve). Questo prende ripetutamente due lettere dalle parole e stampa la prima delle lettere. L'indicizzazione c[c!=d]genera un errore fuori limite in cui c!=d, terminando l'esecuzione quando si incontrano due lettere diverse.

Un ciclo esplicito per è un carattere più lungo della comprensione dell'elenco:

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

Wow! Non avevo nemmeno pensato di usare una funzione! Ben fatto. +1
Zach Gates

L'ho visto solo ora, ma che ne dici print(end=c[c!=d])?
Sp3000,

1
@ Sp3000 Wow, non ho mai collegato che l'argomento principale printfosse facoltativo, significava che poteva essere chiamato solo con l'argomento end e che poteva contenere la stringa. Questo è un trucco davvero utile in generale. Dovresti dare un consiglio.
xnor

3

Javascript ES6, 52 byte

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

Uso:

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

Non funziona con ada,aca...
flawr

Whoops, riparato. Ho dimenticato di eliminare il filtro dopo che le stringhe non corrispondono più.
Dendrobium,

1
Non è necessario f=
assegnare un

1
puoi farlo più piccolo con la mappa(a,b)=>[...a].map((e,i)=>e==b[i]?e:b='').join``
Shaun H,

2

Retina , 14 byte

Utilizza la stessa idea di kirbyfan64sos . Sfortunatamente, nonostante l'affermazione di Martin che alla fine la modalità Match presenterà un modo per stampare gruppi di acquisizione, non è stata ancora implementata. Altrimenti, (.*).* \1potrebbe essere usato insieme a circa 2 byte per qualche opzione di stringa di configurazione non ancora esistente.

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

Ogni riga andrebbe nel suo file, con 1 byte aggiunto per ogni file aggiuntivo. In alternativa, esegui in un singolo file con il -sflag.


Il regex equivalente non riesce a corrispondere in vim a causa dell'avidità (e un regex non avido corrisponderà alla sottostringa più corta , cioè vuota), sei sicuro che funzioni?
Casuale 832

@ Random832 Prova a utilizzare questo tester di sostituzione regex , con l'opzione .NET selezionata. Impostare l'operazione su "sostituisci" e inserire i motivi nelle caselle corrette. Non manca se ci dovrebbe essere uno. Come potrebbe fallire a causa dell'avidità? Questa è l'unica ragione per cui funziona. \1assicura che entrambe le parole inizino con lo stesso prefisso. Quindi, non importa quanto sia avido (.*), \1è lo stesso.
mbomb007,

In definitiva si rifiuta di abbinare affatto - penso che stia trovando una stringa più lunga per la prima (. *), Quindi non riuscendo a farla corrispondere a \ 1, quindi non tornare correttamente a stringhe più brevi.
Casuale 832

@ Random832 Quindi devi trovare qualcos'altro su cui testare le tue regex.
mbomb007,

2

K, 24 byte

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

Trova il minimo della lunghezza di ogni stringa. ( (&/#:'x)). Taglia ogni stringa di quella lunghezza ( #'x). Quindi confrontare, sbavare e sommare la sequenza risultante:

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

Infine, prendi molti caratteri dalla prima delle stringhe fornite ( #*x).

In azione:

 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 byte

Confronta le stringhe, restringendo la prima finché non corrisponde (stampa ed esci) o la stringa è nulla e il ciclo termina.

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

2

Julia, 62 byte

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

Risolto un problema (al costo elevato di 14 byte) grazie a xnor!


2

C99, 73 byte

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

Simile a questa risposta , ma più breve e conforme alle specifiche (accetta input dallo stdin).


La specifica non dice che l'input debba provenire da stdin. Questo in realtà è più lungo dell'altra risposta se si aggiunge #include<stdio.h>, che è necessario per la compilazione del programma.
musaritmia,

@AndrewCashner - Non deve essere su stdin, ma deve ricevere input. L'altra risposta è codificata. Inoltre, gcc si lamenta dell'uso implicito, ma si compila bene senza includere.
Comintern,

Molto più breve senza i provvisori: main(int c,char**a){for(;*a[1]==*a[2]++;putchar(*a[1]++));}(59 byte).
Toby Speight,

2

MATLAB, 50 40 byte

Definisce una funzione che accetta 2 stringhe come input, output nella finestra di comando

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

Questa soluzione funzionerà per qualsiasi stringa, output

ans =

   Empty string: 1-by-0

se non viene fornita alcuna corrispondenza.

Può essere giocato a golf usando uno script anziché una funzione (usando le variabili locali a, b) (-16 byte).

ottenendo così 34 byte

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

Lo stile di funzione (che sembra essere lo stile accettato), cede

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

(Grazie @Stewie Griffin)


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

2

Perl 6 , 28 byte

Ne ho inventati due che prendono i loro valori da STDIN che sono basati sulla risposta Perl 5.

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

Il primo richiede esattamente uno spazio tra gli ingressi, mentre l'altro richiede almeno uno spazio bianco tra gli ingressi.


È un po 'più breve della prima cosa che ho provato che prende i valori dalla riga di comando.

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

o addirittura la versione lambda di esso:

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

Anche se questo è molto più facile da regolare in modo da accettare un numero qualsiasi di stringhe di input, al costo di un solo tratto.

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

Japt è una versione abbreviata di Ja vaScri pt . Interprete

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

(Le corde vanno nella casella di input in questo modo: "global" "glossary")

Questo codice è esattamente equivalente al seguente JS:

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

Non ho ancora implementato funzioni anonime, il che è ciò che $...$serve: qualsiasi cosa tra i segni del dollaro rimane intatta nel passaggio a JS. Dopo aver aggiunto le funzioni, questo codice a 21 byte sarà sufficiente:

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

E dopo aver implementato alcune funzionalità in più, idealmente saranno 18 byte:

UmXY{AxX=VgY ?X:AP

Suggerimenti benvenuti!


Quindi si scopre che questo programma ha solo 15 byte nel moderno Japt:

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

Provalo online!


2

MATL , 11 9 byte

y!=XdYpf)

Provalo online!

(-2 byte grazie 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

Grazie! L' yidea è piuttosto buona, avevo provato cose come un'iniziale itiinvece di quella 1Gw, ma non ho pensato di usarla yper quello.
Sundar - Ripristina Monica il

1

Clojure / ClojureScript, 51

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

Abbastanza diretto. Sfortunatamente gli spazi attorno al parametro destrutturante sono necessari (questa è [a & b]roba). Non il più breve, ma ho battuto alcune altre risposte in lingue a cui piace vantarsi della loro tersezza, quindi la posterò.


1

Python 2, 50 byte

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

Ingresso

L'input è preso come due stringhe:

"global", "glossary"

Produzione

L'output è ogni carattere seguito da uno spazio; che, si spera, non è un problema. Tuttavia, se lo è, modificherò la mia risposta.

g l o 

Sono abbastanza sicuro che questo non sia valido; le specifiche hanno chiaramente fornito il formato di output come una stringa senza spazi.
lirtosiast

Bene sì, ma anche l'input è stato dato nel formato "global" , "glossary"(due stringhe separate). Quante altre risposte seguono la lettera? @ThomasKwa
Zach Gates

"accetta due stringhe" è il linguaggio utilizzato da OP; di solito quando qualcosa del genere viene menzionato senza qualificatori, si riferisce a uno dei nostri I / O predefiniti , il che significa che possiamo prendere una stringa dalla riga di comando e una da STDIN, o una matrice di due stringhe, o qualsiasi altra cosa segua quelle regole.
lirtosiast

Penso che stai prendendo la mia risposta un po 'troppo sul serio. Questa è solo una presentazione divertente e il mio miglior tentativo di battere un built-in. Se a OP non piace il formato di output, così sia; Rimuoverò la mia risposta. @ThomasKwa
Zach Gates

Che ne dici print(exit()if a!=b else a,end='')? Non so se funzionerà o meno, ma potrebbe
Decadimento beta

1

TeaScript, 16 byte 20

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

Prende ogni input separato da uno spazio.


1

PHP, 52 byte

Non spettacolare ma fa il lavoro:

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

Accetta due argomenti della riga di comando:

php prefix.php department depart

PHP7 ti consente di salvare un altro byte while(($a=$argv)[1][$i]==$a[2][$i])echo$a[1][$i++];- Un'altra soluzione unica di PHP7 (e meglio potrei trovare @ 50 byte) <?=substr(($a=$argv)[1],0,strspn($a[1]^$a[2],~ÿ));- Assicurati che il tuo editor sia in modalità ASCII, è importante che ~ÿnon venga convertito in Unicode.
Leigh,
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.