Самый длинный общий префикс из 2 строк


30

Напишите программу, которая принимает 2 строки в качестве входных данных и возвращает самый длинный общий префикс. Это , поэтому выигрывает ответ с наименьшим количеством байтов.

Test Case 1:

"global" , "glossary"
"glo"


Test Case 2:

"department" , "depart"
"depart"

Test Case 3:

"glove", "dove"
""

1
Еще один хороший тестовый пример "aca", "aba".
— Морган Трепп

2
Вы хотите законченные программы, которые вводят из STDIN и печатают в STDOUT, или функции в порядке?
— xnor

2
Можем ли мы предположить, что на входе не будет новых строк? Какие символы будут вводить?
— Downgoat

5
Общее примечание: люди, использующие решение на основе регулярных выражений, не должны копировать ответы других, не проверяя их самостоятельно; это не работает во всех двигателях регулярных выражений. В частности, он дает разные (оба неправильные) ответы в nvi и vim.
— Random832

1
Все приведенные примеры в нижнем регистре, но нужно ли нам беспокоиться о чувствительности к регистру? Например, должен globalи GLOSSARYвернуть gloили ''?
— AdmBorkBork

Ответы:


22

Python 3, 54 байта

Спасибо Python за наличие встроенной функции для этой задачи! : D

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

Принимает ввод в виде двух слов, разделенных пробелом, например glossary global.


21

Haskell, 29 байт

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

Использование:

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

Рекурсивно определяет двоичную функцию %путем сопоставления с образцом. В двух строках с одинаковыми первыми буквами принимает эти первые буквы и добавляет их к функции остальных строк. На что-нибудь еще выдает пустую строку.


11

Pyth, 8 7 байтов

e@F._MQ

Спасибо @isaacg за 1 байт

Принимает ввод в кавычки и запятую, как "abc", "acc". Это происходит при ошибке (но оставляет стандартный вывод пустым), когда результатом является пустая строка. Если это недопустимо, добавьте 2 байта для#e@F._MQq

Тестирование

объяснение

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

Для того, чтобы результат пустая строка без ошибок: e|@F._M.z]k.
— kirbyfan64sos

@ kirbyfan64sos Я полагаю, что то, что я вкладываю в окружение, на #...qодин байт меньше, я отредактирую в полном коде, думаю, это сбивает с толку
— FryAmTheEggman

1
Возьмите ввод в форме, "abc", "def"и вы можете использовать Qвместо.z
— isaacg

10

C ++, 101 100 99 байт

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

Считывает две строки из stdin, печатает символ в текущей позиции из одной из строк, в то время как символ в текущей позиции равен символу в той же позиции в другой строке.

Спасибо Zereges за сохранение одного байта.


4
Это прекрасное и пугающее использование этого forзаявления ...
— Джошпбаррон,

Цикл не завершится, если строки будут равны.
— Джон Траунтвейн

2
Не будет работать для строк, содержащих пробелы. Вы можете сохранить один байт, сделав int iв глобальном пространстве (чтобы он был инициализирован 0)
— Zereges

@JonTrauntvein Я думаю, что это дело UB (?). Это работает ™ для меня, хотя. (gcc-5.1)
— sweerpotato

9

Haskell, 38 байт

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

Пример использования: ( ((map fst.fst.span(uncurry(==))).).zip ) "global" "glossary"-> "glo".

Zip обе входные строки в список пар символов. Сделайте из него два списка: первый со всеми парами с начала до тех пор, пока оба символа равны, второй со всеми остальными. Удалите второй список и извлеките все символы из первого списка.


9

CJam, 12 11 9 байт

l_q.-{}#<

Это читает строки на две отдельные линии с Unix-стиле конца строки, то есть <string>\n<string>\n.

Спасибо @ MartinBüttner за -1 байт и @ jimmy23013 за -2 байта!

Попробуйте онлайн в интерпретаторе CJam .

Как это работает

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.

Черт, я не могу поверить, что мой самый первый ответ был так близок!
— геокавель

1
Вы можете немного обмануть, предполагая завершающий перевод строки и использование l_q.-.
— Джимми23013

@ jimmy23013 Это стандартно для ввода в Unix-подобных ОС, так почему бы и нет? Благодарность!
— Деннис

8

APL, 13

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

Это функция, которая принимает массив из двух строк и возвращает префикс:

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

Действительно ли справедливо сказать, что алфавит APL - это алфавит байтовых символов? Или это стандартная практика здесь?
— Filipq

9
@Filipq Ответы здесь используют наиболее естественную для языка кодировку. У APL есть собственная кодовая страница, в которой каждый символ представляет собой один байт.
— Алекс А.

7

AppleScript, 215 байт

И я так старался ...; (

установить x в (отображать диалог "" ответ по умолчанию "") возвращаемый текст
установить a (отобразить диалог "" ответ по умолчанию "") возвращаемый текст
установите n в 1
установить "в"
повторить, в то время как пункт x = элемент n
установить o для o & x's item n
установите n в n + 1
конец
о

Я хотел бы видеть , насколько хорошо AppleScript может осуществить это, и человек является не построен для сравнения строк.


12
AppleScript не был создан ни для чего .
— kirbyfan64sos

Единственное, чем я пользуюсь, кроме ужасных гольфов, это tell app "System Events" to <something>. Это является интересно посмотреть , как это имеет дело с такого рода вещи, хотя. @ kirbyfan64sos
— Эддисон Крамп


6

Сед, 18

Я имел в виду что-то гораздо более длинное и сложное, так что заслуга этой идеи принадлежит @ kirbyfan64sos .

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

Включает +1 за -rопцию sed.


Какова была ваша оригинальная идея?
— kirbyfan64sos

@ kirbyfan64sos Это в основном включало циклический переход между символами и остановку при несовпадении. Это была просто идея - без кода.
— Цифровая травма

6

CJam, 12 8 26

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

Попробуйте онлайн.

(Есть идея использовать. = Вместо .- после просмотра ответа Денниса.)

Со всеми крайними случаями начинающему CJam, как я, стало трудно держать это коротким. Надеюсь, это по крайней мере работает для всех случаев.


6

C #, 201 147 байтов

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

Я знаю, что это не очень конкурентоспособно. Я просто хотел посмотреть, как это будет выглядеть.

РЕДАКТИРОВАТЬ: Спасибо Эш Бурлакзенко, Беренд и Деннис_Е


2
Просто получить ответ C # до 250 байт является конкурентоспособным. Кроме того, ты не можешь просто using System.*?
— хлопнуть

1
.ForEach(x=>Console.Write(x))может быть сокращено до.ForEach(Console.Write)
— Эш Бурлаченко

1
using System.Collections.Generic;не нужно Сбрейте еще один байт, удалив пробел из string[] a.
— Беренд

2
1-е Containsненужно. 2-Вы можете сохранить несколько байтов, удалив using System;и сказав System.Console.Write;3-Этот код возвращает неправильный результат ("a") для ввода "aab", "aaab" из-за IndexOf. Самое короткое исправление, о котором я могу подумать, это использование a[0].Take(a[1].Length)Это длиной 147 байт: «использование System.Linq; класс 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

Спасибо за комментарии, когда я получу перерыв, я внимательно посмотрю на все из них, особенно на комментарий Dennis_E.
— Jakotheshadows

5

Common Lisp, 39

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

Принимает два строковых аргумента, определяет индекс i, где они отличаются, и возвращает подстроку от 0 до i .


5

Perl 5, 20 19 18 байт

19 байт плюс 1 за -Eфлаг вместо -e:

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

Это скопировано бесстыдно от Digital Trauma «s SED ответа . Предполагается, что ввод представляет собой пару слов без пробелов в них (или перед первым) и с одним пробелом между ними.


Обновить:

ThisSuitIsBlackNot предложил использовать -peдля сохранения байта следующее (спасибо!):

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

И тогда Luk Storms предложил использовать -nEследующее для сохранения другого байта (спасибо!):

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

(Я считаю -Eкак один байт вместо стандартного -e, но -nили -pкак два. У меня сложилось впечатление, что это СОП здесь.)


1
« -M5.010при необходимости - бесплатно» . За один и тот же мета пост -peили -neбудет 1 дополнительный байт, а не 2. Таким образом, perl -nE 'say/^(.*).* \1/'получится 16 байт.
— ThisSuitIsBlackNot

4

Python 3, 72

31 байт сохранен благодаря FryAmTheEggman. 8 сохранено благодаря DSM.

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

Без чего бы обходились программисты Python zip? : D
— бета-распад

7
@BetaDecay Наша муха будет открыта все время.
— Морган Трепп

Вы можете поместить input()s в zipи сохранить aи bсвязывание.
— DSM

@DSM Ооо, хорошая мысль. Благодарность!
— Морган Трепп

4

Python 3, 47

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

Функция, которая принимает список wиз двух слов и печатает общий префикс перед завершением с ошибкой.

printФункция Python 3 позволяет печатать строки вплотную друг к другу print(end=c)(спасибо Sp3000 за сохранение 3 байтов с этим более коротким синтаксисом). Это многократно берет две буквы из слов и печатает первую из букв. Индексация c[c!=d]выдает ошибку «за пределами», при которой c!=dпрекращается выполнение, когда встречаются две неравные буквы.

Явный цикл for на один символ длиннее, чем понимание списка:

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

Вот Это Да! Я даже не думал об использовании функции! Хороший. +1
— Зак Гейтс

Только видел это сейчас, но как насчет print(end=c[c!=d])?
— Sp3000

1
@ Sp3000 Ничего себе, я никогда не связывал, чтобы основной аргумент printбыл необязательным, означал, что его можно вызывать только с конечным аргументом, и он может содержать строку. Это действительно полезный трюк в целом. Вы должны сделать чаевые.
— xnor

3

Javascript ES6, 52 байта

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

Использование:

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

Не работает с ada,aca...
— flawr

Упс, исправлено. Забыл убить фильтрацию после того, как строки больше не совпадают.
— Дендробиум

1
Вам не нужно называть функцию, так что вы можете f=
— опустить

1
Вы можете сделать это меньше с картой(a,b)=>[...a].map((e,i)=>e==b[i]?e:b='').join``
— Shaun H

2

Сетчатка , 14 байт

Использует ту же идею, что и kirbyfan64sos . К сожалению, несмотря на утверждение Мартина о том, что в конечном итоге режим соответствия будет содержать способ печати групп захвата, он еще не реализован. В противном случае (.*).* \1может использоваться вместе с 2 байтами или около того для некоторой еще не существующей опции строки конфигурации.

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

Каждая строка будет идти в своем собственном файле с добавлением 1 байта на каждый дополнительный файл. В качестве альтернативы, запустите в одном файле с -sфлагом.


Эквивалентное регулярное выражение не соответствует в vim из-за жадности (а не-жадное регулярное выражение будет соответствовать самой короткой подстроке, т.е. пустой), вы уверены, что это работает?
— Random832

@ Random832 Попробуйте использовать этот тестер для замены регулярных выражений, отметив опцию .NET. Установите операцию «заменить» и поместите шаблоны в соответствующие поля. Это не может не совпадать, если он должен быть. Как это могло потерпеть неудачу из-за жадности? Это единственная причина, по которой это работает. \1гарантирует, что оба слова начинаются с одинакового префикса. Поэтому независимо от того , как жадный (.*)это, \1не одно и то же.
— mbomb007

В vim он вообще отказывается совпадать - я думаю, что он находит более длинную строку для первой (. *), Затем не может сопоставить ее с \ 1, а затем неправильно возвращает обратно к более коротким строкам.
— Random832

@ Random832 Тогда вам нужно найти что-то еще, чтобы проверить свои регулярные выражения.
— mbomb007

2

К, 24 байта

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

Найдите минимальную длину каждой строки. ( (&/#:'x)). Обрежьте каждую строку до этой длины ( #'x). Затем сравните, намажьте и суммируйте полученную последовательность:

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

Наконец, возьмите столько символов из первой предоставленной строки ( #*x).

В бою:

 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 байт

Сравнивайте строки, сжимая первую, пока она не совпадет (напечатайте и выйдите) или пока строка не станет нулевой и цикл не завершится.

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

2

Юлия, 62 байта

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

Исправлена ​​проблема (при огромных затратах в 14 байт) благодаря xnor!


2

C99, 73 байта

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

Аналогичен этому ответу , но короче и соответствует спецификации (принимает данные из stdin).


Спец не говорит, что вход должен исходить от стандартного ввода. Это на самом деле длиннее, чем другой ответ, если вы добавите #include<stdio.h>, что необходимо для компиляции программы.
— Мусаритмия

@AndrewCashner - он не обязательно должен быть на stdin, но он должен принимать данные. Другой ответ жестко закодирован. Кроме того, gcc жалуется на неявное использование, но прекрасно компилируется без включения.
— Коминтерн

Гораздо короче без временных: main(int c,char**a){for(;*a[1]==*a[2]++;putchar(*a[1]++));}(59 байт).
— Тоби Спейт

2

MATLAB, 50 40 байт

Определяет функцию, которая принимает 2 строки в качестве входных данных, выводит в командное окно

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

Это решение будет работать для любой строки, выходы

ans =

   Empty string: 1-by-0

если нет совпадения

Можно использовать с помощью скрипта вместо функции (используя локальные переменные a, b) (-16 байт).

так получая 34 байта

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

Стиль функции (который кажется принятым стилем) дает

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

(Спасибо @ Стиви Гриффин)


40 байт: @(a,b)a(1:find([diff(char(a,b)) 1],1)-1). =)
— Стьюи Гриффин

2

Perl 6 , 28 байт

Я придумал два, которые берут свои значения из STDIN, которые основаны на ответе Perl 5.

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

Первый требует ровно один пробел между входами, а другой требует как минимум один символ пробела между входами.


Это немного короче, чем первое, что я попробовал, который берет значения из командной строки.

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

или даже лямбда-версия этого:

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

Хотя это гораздо проще настроить, чтобы он принимал любое количество входных строк, за счет одного удара.

{[~] 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 байт

Japt - это сокращенная версия Ja vaScri pt . переводчик

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

(Строки идут в поле ввода , например , так: "global" "glossary")

Этот код в точности эквивалентен следующему JS:

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

Я еще не реализовал анонимные функции, для чего и $...$существует: все, что находится между знаками доллара, остается нетронутым при переходе на JS. После добавления функций этого 21-байтового кода будет достаточно:

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

И после того, как я реализую еще несколько функций, в идеале это будет 18 байт:

UmXY{AxX=VgY ?X:AP

Предложения приветствуются!


Получается, что эта программа занимает всего 15 байт в современном Japt:

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

Попробуйте онлайн!


2

MATL , 11 9 байт

y!=XdYpf)

Попробуйте онлайн!

(-2 байта благодаря Джузеппе)

 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

Благодарность! yИдея довольно хорошо, я пытался что - то вроде начальной itiвместо 1Gw, но не думать об использовании yдля этого.
— sundar - Восстановить Монику

1

Clojure / ClojureScript, 51

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

Довольно просто. К сожалению, пробелы вокруг параметра разрушения необходимы (вот и [a & b]все). Не самый короткий, но я прибил некоторые другие ответы на языках, которые любят хвастаться их краткостью, поэтому я отправлю это.


1

Python 2, 50 байт

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

вход

Ввод принимается в виде двух строк:

"global", "glossary"

Выход

Вывод - это каждый символ, за которым следует пробел; что, надеюсь, не проблема. Однако, если это так, я отредактирую свой ответ.

g l o 

Я почти уверен, что это неверно; спецификация ясно дала формат вывода в виде строки без пробелов.
— Lirtosiast

Ну да, но входные данные также были даны в формате "global" , "glossary"(две отдельные строки). Сколько других ответов следует за письмом? @ThomasKwa
— Зак Гейтс

«принимает две строки» - язык, используемый OP; обычно, когда что-то подобное упоминается без каких-либо определителей, это относится к одному из наших вводов- выводов по умолчанию , что означает, что мы можем взять одну строку из командной строки и одну из STDIN, или массив из двух строк, или что-либо еще после этих правила.
— lirtosiast

Я думаю, вы слишком серьезно относитесь к моему ответу. Это просто забавная подача и моя лучшая попытка обыграть встроенную. Если OP не нравится формат вывода, пусть будет так; Я удалю свой ответ. @ThomasKwa
— Зак Гейтс

Как насчет print(exit()if a!=b else a,end='')? Я не знаю, сработает ли это или нет, но это может
— произойти

1

TeaScript, 16 байт 20

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

Принимает каждый вход через пробел.


1

PHP, 52 байта

Не впечатляет, но делает работу:

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

Принимает два аргумента командной строки:

php prefix.php department depart

PHP7 позволяет вам сохранить еще один байт. while(($a=$argv)[1][$i]==$a[2][$i])echo$a[1][$i++];- Еще одно решение для PHP7 (и лучше всего, если бы я смог получить @ 50 байт). <?=substr(($a=$argv)[1],0,strspn($a[1]^$a[2],~ÿ));- Убедитесь, что ваш редактор работает в режиме ascii, важно, чтобы ~ÿон не конвертировался в юникод.
— Ли
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.