Write a program that takes 2 strings as input, and returns the longest common prefix. This is , so the answer with the shortest amount of bytes wins.

Test Case 1:

"global" , "glossary"

Test Case 2:

"department" , "depart"

Test Case 3:

"glove", "dove"
  • 3
    \$\begingroup\$ Do you want a complete programs that inputs from STDIN and prints to STDOUT, or are functions OK? \$\endgroup\$
    – xnor
    Commented Nov 3, 2015 at 19:35
  • 3
    \$\begingroup\$ Can we assume the input won't have newlines? Which characters will the input have? \$\endgroup\$
    – Downgoat
    Commented Nov 3, 2015 at 23:59
  • 7
    \$\begingroup\$ General note: People using a regex based solution should not copy other people's regex answers without testing them yourself; this does not work in all regex engines. In particular, it gives different (both incorrect) answers in nvi and vim. \$\endgroup\$
    – Random832
    Commented Nov 4, 2015 at 16:38
  • 2
    \$\begingroup\$ All of the examples given are in lowercase, but do we need to worry about case sensitivity? For example, should global and GLOSSARY return glo or ''? \$\endgroup\$ Commented Nov 5, 2015 at 16:08
  • 2
    \$\begingroup\$ Can it return the length? \$\endgroup\$
    – S.S. Anne
    Commented Mar 13, 2020 at 17:45

72 Answers 72


Python 3, 54 bytes

Thanks Python for having a built-in function for this task! :D

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

Takes input as two words separated by a space such as glossary global.


Haskell, 29 bytes



>> "global"%"glossary"

Recursively defines the binary function % by pattern matching. On two strings with equal first letters, takes that first letters, and prepends it to the function of the remainder of the strings. On anything else, gives the empty string.


Pyth, 8 7 bytes


Thanks @isaacg for 1 byte off

Takes input quoted and comma separated, like "abc", "acc". This exits on an error (but leaves stdout empty) when the result is the empty string. If that is unacceptable, add 2 bytes for #e@F._MQq

Test Suite


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
  • \$\begingroup\$ To make the result the empty string without error: e|@F._M.z]k. \$\endgroup\$ Commented Nov 3, 2015 at 18:11
  • \$\begingroup\$ @kirbyfan64sos I believe the thing I put in about surrounding it with #...q is one byte less than that, I'll edit in the full code, I guess that is confusing \$\endgroup\$ Commented Nov 3, 2015 at 18:14
  • 1
    \$\begingroup\$ Take input in the form "abc", "def" and you can use Q instead of .z \$\endgroup\$
    – isaacg
    Commented Nov 3, 2015 at 22:55

Haskell, 38 bytes

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

Usage example: ( ((map fst.fst.span(uncurry(==))).).zip ) "global" "glossary" -> "glo".

Zip both input string into a list of pairs of characters. Make two lists out of it: the first one with all pairs from the beginning as long as both characters are equal, the second one with all the rests. Drop the second list and extract all characters from the first list.


C++, 101 100 99 bytes

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

Reads two strings from stdin, prints the character at the current position from one of the strings while the character at the current position is equal to the character at the same position in the other string.

Thanks to Zereges for saving one byte.

  • 4
    \$\begingroup\$ That is a beautiful and terrifying use of the for statement... \$\endgroup\$
    – Sarima
    Commented Nov 4, 2015 at 13:28
  • \$\begingroup\$ The loop would fail to terminate if the strings were equal. \$\endgroup\$ Commented Nov 5, 2015 at 23:00
  • 2
    \$\begingroup\$ Won't work for strings containing whitespaces. You can save one byte, by making int i in global space (so that it will be 0 initialized) \$\endgroup\$
    – Zereges
    Commented Nov 5, 2015 at 23:01
  • \$\begingroup\$ @JonTrauntvein I think that case is UB(?). It works™ for me though. (gcc-5.1) \$\endgroup\$ Commented Nov 10, 2015 at 17:29

CJam, 12 11 9 bytes


This reads the strings on two separate lines with Unix-style line ending, i.e., <string>\n<string>\n.

Thanks to @MartinBüttner for -1 byte, and to @jimmy23013 for -2 bytes!

Try it online in the CJam interpreter.

How it works

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.
  • \$\begingroup\$ Darn, I can't believe my very first answer was so close! \$\endgroup\$
    – geokavel
    Commented Nov 4, 2015 at 16:46
  • 1
    \$\begingroup\$ You can cheat a bit by assuming a trailing newline and use l_q.-. \$\endgroup\$
    – jimmy23013
    Commented Nov 5, 2015 at 2:18
  • \$\begingroup\$ @jimmy23013 That's standard for input on Unix-like OS's, so why not? Thanks! \$\endgroup\$
    – Dennis
    Commented Nov 5, 2015 at 2:28

APL, 13


This is a function that takes an array of two strings, and returns the prefix:

      {⊃↓K/⍨=⌿K←↑⍵}'glossary' 'global'
      {⊃↓K/⍨=⌿K←↑⍵}'department' 'depart'
  • \$\begingroup\$ Is it really fair to say that the APL alphabet is an alphabet of byte-size characters? Or is that standard practice around here? \$\endgroup\$
    – Moop
    Commented Nov 3, 2015 at 23:43
  • 9
    \$\begingroup\$ @Filipq Answers here use the encoding most natural to the language. APL has its own code page on which each character is a single byte. \$\endgroup\$
    – Alex A.
    Commented Nov 4, 2015 at 3:40
  • \$\begingroup\$ this fails when there are matching letters after the longest common prefix, e.g. "string" "stronger" should give just "str", not "strng" \$\endgroup\$
    – ngn
    Commented Mar 7, 2020 at 8:58

AppleScript, 215 Bytes

And I tried so hard... ;(

set x to(display dialog""default answer"")'s text returned
set a to(display dialog""default answer"")'s text returned
set n to 1
set o to""
repeat while x's item n=a's item n
set o to o&x's item n
set n to n+1

I wanted to see how well AppleScript could pull this off, and man is it not built for string comparisons.

  • 12
    \$\begingroup\$ AppleScript wasn't built for anything. \$\endgroup\$ Commented Nov 3, 2015 at 23:51
  • 1
    \$\begingroup\$ The only thing I use it for besides terrible golfs is tell app "System Events" to <something>. It is interesting to see how it deals with this kind of stuff, though. @kirbyfan64sos \$\endgroup\$ Commented Nov 4, 2015 at 14:30

sed, 18

I had something much longer and more complicated in mind, so credit for this idea goes to @kirbyfan64sos.

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

Includes +1 for the -r option to sed.

  • \$\begingroup\$ What was your original idea? \$\endgroup\$ Commented Nov 3, 2015 at 23:51
  • \$\begingroup\$ @kirbyfan64sos It basically involved looping through characters one by one and stopping at a mismatch. It was just an idea - no code behind it. \$\endgroup\$ Commented Nov 3, 2015 at 23:54

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

I know it isn't terribly competitive. I just wanted to see what it would look like.

EDIT: Thanks Ash Burlakzenko, Berend, and Dennis_E

  • 2
    \$\begingroup\$ Just getting a C# answer under 250 bytes is competitive. Also, can't you just using System.*? \$\endgroup\$
    – clapp
    Commented Nov 3, 2015 at 22:45
  • 1
    \$\begingroup\$ .ForEach(x=>Console.Write(x)) could be shortened to .ForEach(Console.Write) \$\endgroup\$ Commented Nov 4, 2015 at 8:01
  • 1
    \$\begingroup\$ using System.Collections.Generic; is unnecessary. Shave off one more byte by removing the space from string[] a. \$\endgroup\$
    – Berend
    Commented Nov 4, 2015 at 9:16
  • 2
    \$\begingroup\$ 1-The Contains is unnecessary. 2-You can save a few bytes by removing using System; and saying System.Console.Write; 3-This code returns the wrong result ("a") for input "aab","aaab", because of IndexOf. The shortest fix I could think of is using 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);}}" \$\endgroup\$
    – Dennis_E
    Commented Nov 4, 2015 at 12:36
  • \$\begingroup\$ Thanks for the comments when I get a break I'll take a good look at all of them especially Dennis_E's comment. \$\endgroup\$ Commented Nov 4, 2015 at 17:46

rs, 14 bytes

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

Live demo and test cases.

This is pretty simple. It just matches the...longest common prefix and removes the rest of the string. If there is no longest common prefix, it just clears everything.


CJam, 12 8 26


Try it Online.

(Got idea to use .= instead of .- after looking at Dennis's answer.)

With all the edge cases, it became to hard for a CJam beginner like me to keep it short. Hopefully, this at least works for all cases.


Perl 5, 20 19 18 bytes

19 bytes, plus 1 for the -E flag instead of -e:

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

This is copied shamelessly from Digital Trauma's sed answer. It assumes the input is a couple of words without spaces in them (or before the first) and with one space between them.


ThisSuitIsBlackNot suggested using -pe as follows, to save a byte (thanks!):

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

And then Luk Storms suggested using -nE as follows to save another byte (thanks!):

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

(I'm counting -E as one byte instead of the standard -e, but -n or -p as two. My impression is that that's SOP around here.)


Common Lisp, 39

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

Takes two string arguments, determines the index i where they differ, and returns a substring from 0 to i.


Javascript ES6, 52 bytes



>> f("global","glossary")
  • \$\begingroup\$ Does not work with ada,aca... \$\endgroup\$
    – flawr
    Commented Nov 3, 2015 at 22:07
  • \$\begingroup\$ Whoops, fixed. Forgot to kill filtering after the strings no longer match. \$\endgroup\$
    – Dendrobium
    Commented Nov 3, 2015 at 22:17
  • 1
    \$\begingroup\$ You don't need to name the function, so you can leave out the f= \$\endgroup\$
    – Ypnypn
    Commented Nov 3, 2015 at 22:56
  • 1
    \$\begingroup\$ you can do it smaller with map (a,b)=>[...a].map((e,i)=>e==b[i]?e:b='').join`` \$\endgroup\$
    – Shaun H
    Commented May 16, 2016 at 17:44
  • \$\begingroup\$ b can be given 0 rather than "" \$\endgroup\$
    – l4m2
    Commented Apr 9, 2021 at 15:18

Python 3, 72

31 bytes saved thanks to FryAmTheEggman. 8 saved thanks to DSM.

for x,y in zip(input(),input()):
 if x==y:r+=x
  • \$\begingroup\$ What would Python programmers do without zip? :D \$\endgroup\$
    – Beta Decay
    Commented Nov 3, 2015 at 20:58
  • 7
    \$\begingroup\$ @BetaDecay Our fly would be open all the time. \$\endgroup\$ Commented Nov 3, 2015 at 21:00
  • \$\begingroup\$ You could put the input()s in the zip and save the a and b binding. \$\endgroup\$
    – DSM
    Commented Nov 9, 2015 at 22:06
  • \$\begingroup\$ @DSM Ooo, good point. Thanks! \$\endgroup\$ Commented Nov 9, 2015 at 22:07

Python 3, 47

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

A function that takes a list w of two words, and prints the common prefix before terminating with an error.

Python 3's print function lets you prints strings flush against each other with print(end=c) (thanks to Sp3000 for saving 3 bytes with this shorter syntax). This repeatedly take two letters from the words, and prints the first of the letters. The indexing c[c!=d] gives an out-of-bounds error where c!=d, terminating the execution when two unequal letters are encountered.

An explicit for loop is one char longer than the list comprehension:

def f(w):
 for c,d in zip(*w):print(end=c[c!=d])
  • \$\begingroup\$ Wow! I hadn't even thought about using a function! Nice one. +1 \$\endgroup\$
    – Zach Gates
    Commented Nov 4, 2015 at 21:32
  • \$\begingroup\$ Only saw this now, but how about print(end=c[c!=d])? \$\endgroup\$
    – Sp3000
    Commented Nov 10, 2015 at 6:11
  • 1
    \$\begingroup\$ @Sp3000 Wow, I never connected that the main argument to print being optional meant it could be called with only the end argument, and that could contain the string. That's a really useful trick in general. You should make a tip. \$\endgroup\$
    – xnor
    Commented Nov 10, 2015 at 7:49

MATL, 11 9 bytes


Try it online!

(-2 bytes thanks to 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

05AB1E, 6 bytes


Try it online or verify all test cases.

Or alternatively:


Might be invalid, since it outputs -1 instead of an empty string if the strings have no common prefix.

Try it online or verify all test cases.


ø      # Zip the two (implicit) inputs together, creating pairs
       #  i.e. "abc1de98f" and "abc2de87f"
       #   → ["aa","bb","cc","12","dd","ee","98","87","ff"]
 €Ë    # Check for each if all inner items (the two characters in this case) are the same
       #  → [1,1,1,0,1,1,1,0,0,1]
   γ   # Split it into parts, grouping the same subsequent values together
       #  → [[1,1,1],[0],[1,1],[0,0],[1]]
    н  # Pop and only leave the first item
       #  → [1,1,1]
     Ï # Only leave the characters at the truthy indices in the (implicit second) input
       #  i.e. "abc2de87f" and [1,1,1] → "abc"
       # (after which the result is output implicitly)

η      # Get the prefixes of the first (implicit) input
       #  i.e. "abc1de98f"
       #   → ["a","ab","abc","abc1","abc1d","abc1de","abc1de9","abc1de98","abc1de98f"]
 R     # Reverse this list
       #  → ["abc1de98f","abc1de98","abc1de9","abc1de","abc1d","abc1","abc","ab","a"]
  .Δ   # Then find the first item in this list which is truthy for:
       # (which will result in -1 if none are found)
    Å? #  Check if the second (implicit) input starts with the current prefix
       #   i.e. "abc2de87f" and "abc1d" → 0 (falsey)
       #   i.e. "abc2de87f" and "abc" → 1 (truthy)
       # (after which the result is output implicitly)
  • \$\begingroup\$ Alt 6. This one outputs [] instead of -1. \$\endgroup\$
    – Grimmy
    Commented Mar 16, 2020 at 10:46

Retina, 14 bytes

Uses the same idea as kirbyfan64sos. Unfortunately, despite Martin's claim that eventually Match mode will feature a way to print capturing groups, it hasn't been implemented yet. Otherwise, (.*).* \1 could be used along with 2 bytes or so for some not-yet-existing configuration string option.

(.*).* \1.*

Each line would go in its own file, with 1 byte added per additional file. Alternatively, run in a single file with the -s flag.

  • \$\begingroup\$ The equivalent regex fails to match in vim due to greediness (and a non-greedy regex will match the shortest substring, i.e. blank), are you sure it works? \$\endgroup\$
    – Random832
    Commented Nov 4, 2015 at 16:31
  • \$\begingroup\$ @Random832 Try using this regex replace tester, with the .NET option checked. Set the operation to "replace", and put the patterns in the correct boxes. It doesn't fail to match if there should be one. How could it possible fail due to greediness? That's the only reason it works. \1 ensures that both words start with the same prefix. So no matter how greedy (.*) is, \1 is the same. \$\endgroup\$
    – mbomb007
    Commented Nov 4, 2015 at 16:39
  • \$\begingroup\$ In vim it refuses to match at all - I think it is finding a longer string for the first (.*), then failing to match it against \1, then not properly backtracking to shorter strings. \$\endgroup\$
    – Random832
    Commented Nov 4, 2015 at 16:40
  • \$\begingroup\$ @Random832 Then you need to find something else to test your regexes on. \$\endgroup\$
    – mbomb007
    Commented Nov 4, 2015 at 16:41

K, 24 bytes


Find the minimum of the length of each string. ((&/#:'x)). Trim each string to that length (#'x). Then compare, smear and sum the resulting sequence:

1 1 1 0 0 1
1 1 1 0 0 0

Finally, take that many characters from the first of the strings provided (#*x).

In action:

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

Powershell, 65 bytes

Compare the strings, shrinking the first until it either matches (print and exit) or the string is null and the loop terminates.


Julia, 62 bytes

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


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)
            # Otherwise stop everything!

    return c

Fixed an issue (at the hefty cost of 14 bytes) thanks to xnor!


C99, 73 bytes

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

Similar to this answer, but shorter and meets spec (takes input from stdin).

  • \$\begingroup\$ Spec doesn't say input has to come from stdin. This is actually longer than the other answer if you add #include<stdio.h>, which is necessary for the program to compile. \$\endgroup\$ Commented Dec 18, 2015 at 19:18
  • 1
    \$\begingroup\$ @AndrewCashner - It doesn't need to be on stdin, but it does need to take input. The other answer is hard-coded. Also, gcc whines about the implicit usage, but it compiles fine without the include. \$\endgroup\$
    – Comintern
    Commented Dec 18, 2015 at 19:23
  • \$\begingroup\$ Much shorter without the temporaries: main(int c,char**a){for(;*a[1]==*a[2]++;putchar(*a[1]++));} (59 bytes). \$\endgroup\$ Commented Jul 4, 2018 at 12:10

MATLAB, 50 40 bytes

Defines a function that accepts 2 strings as input, outputs to command window

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

This solution will work for any string, outputs

ans =

   Empty string: 1-by-0

if no match is given.

Can be golfed by using a script instead of a function (using local variables a, b) (-16 bytes).

so getting 34 Bytes

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

The function style (which seems to be the accepted style), yields

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

(Thanks @Stewie Griffin)

  • \$\begingroup\$ 40 bytes: @(a,b)a(1:find([diff(char(a,b)) 1],1)-1). =) \$\endgroup\$ Commented Nov 27, 2015 at 10:54

Perl 6, 28 bytes

I came up with two that take their values from STDIN which are based on the Perl 5 answer.

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

The first requires exactly one space between the inputs, while the other requires at least one whitespace character between the inputs.

That is quite a bit shorter than the first thing I tried which takes the values from the command line.

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

or even the lambda version of it:

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

Though this is much easier to adjust so that it accepts any number of input strings, at the cost of only one stroke.

{[~] 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 `(@_,)`

Japt, 27 bytes

Japt is a shortened version of JavaScript. Interpreter

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

(The strings go into the Input box like so: "global" "glossary")

This code is exactly equivalent to the following JS:


I have not yet implemented anonymous functions, which is what the $...$ is for: anything between the dollar signs is left untouched in the switch to JS. After I add functions, this 21-byte code will suffice:

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

And after I implement a few more features, it will ideally be 18 bytes:


Suggestions welcome!

So it turns out that this program is only 15 bytes in modern Japt:

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

Try it online!


Husk, 6 4 bytes


Try it online!

-2 bytes from Dominic Van essen.


Clojure/ClojureScript, 51

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

Pretty straightforward. Unfortunately the spaces around the parameter destructuring are necessary (that's the [a & b] stuff). Not the shortest but I beat some other answers in languages that like to brag about their terseness so I'll post it.


ed, sed, 19 bytes

ex, 18 bytes

vim, 20 bytes

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

This also works with ex/vi (heirloom ex 050325), and the trailing slash is not required.

Oddly, this should work in vim, but mysteriously fails. It works if I add another unused capture group, something which should not change the semantics of the regex at all:

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

It fails and gives garbage answers in nvi and the results are downright mysterious:

global glossary
:s/\(.*\)\(.*\) \1\(.*\)/\1{\2,\3}/

NOTE: This expects the words on the current [last in the file] line [or every line for the sed script] separated by a space, and containing no space. To operate on every line in ex/vim, add % to the beginning. I don't think I'm the only program here to have constraints like these.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.