Найдовший загальний префікс з 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
Чи можемо ми припустити, що вхід не матиме нових рядків? Які символи будуть мати вхід?
Вниз

5
Загальна примітка: Люди, які використовують рішення на основі регулярних виразів, не повинні копіювати відповіді регексу інших людей, не перевіряючи їх самостійно; це працює не у всіх двигунах регулярного випромінювання. Зокрема, він дає різні (як неправильні) відповіді у nvi та vim.
Випадково832

1
Усі наведені приклади знаходяться в малих літерах, але чи потрібно турбуватися про чутливість регістру? Наприклад, слід globalі GLOSSARYповернути gloабо ''?
AdmBorkBork

Відповіді:


22

Python 3, 54 байти

Дякую Python за вбудовану функцію для цього завдання! : D

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

Вводиться як два слова, розділені пробілом, таким як glossary global.


21

Хаскелл, 29 байт

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

Використання:

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

Рекурсивно визначає бінарну функцію %шляхом узгодження зразка. На двох рядках з рівними першими літерами бере цю першу літеру і додає її до функції решти рядків. Що-небудь ще, дає порожню рядок.


11

Pyth, 8 7 байт

e@F._MQ

Дякуємо @isaacg за 1 байт

Бере вхід з цитатами і комами, відокремленими "abc", "acc". Це виходить з помилки (але залишає stdout порожнім), коли результатом є порожній рядок. Якщо це неприпустимо, додайте 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)
прикорм

9

Haskell, 38 байт

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

Приклад використання: ( ((map fst.fst.span(uncurry(==))).).zip ) "global" "glossary"-> "glo".

Зафіксуйте обидва вхідні рядки до списку пар символів. Складіть із нього два списки: перший з усіма парами від початку, доки обидва символи рівні, другий з усіма залишками. Відкиньте другий список і вийміть усі символи з першого списку.


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.

Дарн, я не можу повірити, що моя перша відповідь була такою близькою!
geokavel

1
Ви можете трохи обдурити, взявши при собі прорив нової лінії та використовувати l_q.-.
jimmy23013

@ 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 на (відобразити діалогове вікно "" відповідь за замовчуванням "") повернено
встановіть (діалогове вікно відображення "" відповідь за замовчуванням "") повертається текст
встановити n до 1
встановити o на ""
повторіть при цьому пункт x n = a пункт n
встановіть o на пункт & n
встановити n до n + 1
кінець
о

Я хотів побачити, наскільки AppleScript може це зняти, і людина це не побудовано для порівняння рядків.


12
AppleScript не будувався ні для чого .
kirbyfan64sos

Єдине, для чого я користуюся, окрім страшних гольфів, - це tell app "System Events" to <something>. Це є цікаво подивитися , як це має справу з такого роду речі, хоча. @ kirbyfan64sos
Addison Crump


6

sed, 18

У мене було щось набагато довше і складніше на увазі, тому заслуга цієї ідеї належить @ kirbyfan64sos .

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

Включає +1 для -rопції для сід.


Якою була ваша оригінальна ідея?
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);}}

Я знаю, що це не дуже конкурентоспроможно. Я просто хотів подивитися, як це буде виглядати.

EDIT: Дякую Ешу Бурлаценко, Беренду та Dennis_E


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 {статичний недійсний 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

Загальна Лісп, 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як два. Моє враження, що тут є SOP.)


1
" -M5.010, коли потрібно, безкоштовно" . На ту саму мета-посаду, -peабо -neце буде 1 додатковий байт, а не 2. Так perl -nE 'say/^(.*).* \1/'би набрали 16 байт.
ThisSuitIsBlackNot

4

Пітон 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 Ooo, хороший момент. Спасибі!
Морган Трапп

4

Пітон 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, припиняючи виконання, коли зустрічаються дві нерівні літери.

Явний цикл для циклу на один знак довший за розуміння списку:

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=
Ypnypn

1
ви можете зробити це менше за допомогою карти(a,b)=>[...a].map((e,i)=>e==b[i]?e:b='').join``
Shaun H

2

Сітківка , 14 байт

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

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

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


Еквівалентний регулярний вираз не збігається з vim через жадібність (а не жадібний регулярний вираз буде відповідати найкоротшому підрядку, тобто порожньому). Ви впевнені, що він працює?
Випадково832

@ Random832 Спробуйте скористатися цим тестером заміни регулярних виразів , встановивши прапорець .NET. Встановіть операцію на «заміну», а візерунки поставте у правильні поля. Це не збігається, якщо має бути такий. Як це могло провалитися через жадібність? Це єдина причина, що це працює. \1гарантує, що обидва слова починаються з одного префікса. Тож як би не було жадібним (.*), \1те саме.
mbomb007

У vim він взагалі відмовляється збігатися - я думаю, що він знаходить довший рядок для першого (. *), Потім не в змозі його зіставити з \ 1, а потім не належним чином повернути до коротших рядків.
Випадково832

@ 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)

Безголовки:

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).


Spec не каже, що вхід повинен надходити від stdin. Це насправді довше, ніж інша відповідь, якщо ви додасте #include<stdio.h>, що необхідно для складання програми.
musarithmia

@AndrewCashner - Це не потрібно, щоб бути на stdin, але він повинен брати вклад. Інша відповідь є жорсткою. Крім того, gcc висловлюється про неявне використання, але він складається добре без включення.
Комінтерн

Набагато коротше без темпоралів: main(int c,char**a){for(;*a[1]==*a[2]++;putchar(*a[1]++));}(59 байт).
Toby Speight

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)

(Дякую @Stewie Griffin)


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

2

Перл 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
Zach Gates

"бере два рядки" - це мова, якою користується ОП; зазвичай, коли щось подібне згадується без будь-яких класифікаторів, воно посилається на один з наших стандартних вводу-виводу , а це означає, що ми можемо взяти один рядок з командного рядка і один із STDIN, або масив з двох рядків, або все, що слід за цим правила.
lirtosiast

Думаю, ти занадто серйозно сприймаєш мою відповідь. Це просто веселе подання і моя найкраща спроба побити вбудований. Якщо OP не подобається вихідний формат, так і нехай; Я видалю свою відповідь. @ThomasKwa
Zach Gates

Як щодо print(exit()if a!=b else a,end='')? Я не знаю, чи спрацює це чи ні, але це може бути
Beta Decay

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, важливо, щоб ~ÿвін не перетворювався на unicode.
Лі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.