Скоротіть масив


26

Мета:

Давши масив рядків, створіть скорочені версії кожного рядка.

Специфікація:

Для цього завдання абревіатура - це перші N символів рядка. Для рядка abc: a, abі abcвсі дійсні скорочення, в той час bc, і acнемає.

Враховуючи масив рядків, ми хочемо знайти найкоротший набір скорочень, такий, що з огляду на введення та будь-яку абревіатуру, ви могли б визначити, до якого елемента введення йдеться абревіатура.

Приклад:

Вхід: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]

Ми працюємо по струнах, починаючи з першої.

  • Понеділок - це лише рядок з символом M, тому найкоротший можливий абревіатура M.

  • Вівторок починається з T, але так чинить і четвер. Це означає, що ми пробуємо рядок TU. Оскільки жоден інший рядок не починається з цього, ми використовуємо TU.

  • Середа є W, четвер є Th, а п’ятниця - F.

Більше прикладів:

Input: "one,two,three,four,five,six,seven"
Output: "o,tw,th,fo,fi,si,se"

Input: "red,orange,yellow,green,blue,purple"
Output: "r,o,y,g,b,p"

Input: "a,ab,abc"
Output: Not valid! No abbreviation for `a` that doesn't apply to the other items.

Примітки:

  • Ви робите введення та вихід будь-яким розумним способом.

  • Можна припустити, що вхід завжди буде дійсним масивом рядків.

  • Можна припустити, що рішення завжди знайдеться, на відміну від останнього тестового випадку.

  • Рядки будуть складатися лише з ASCII для друку (або символи для друку у кодуванні)

  • Це кодовий гольф, тому виграє найменше байтів!


Пов’язано: 1 , 2 , 3
Sp3000

5
Можливий дублікат Golf Down the PPCG Імена користувачів
Okx

2
Я не думаю, що це дублікат жодного з них (хоча вони всі досить схожі). Власне, я думаю, що це, мабуть, найкращий виклик серед чотирьох; всі інші мають варіанти, які ускладнюють їх.

2
Чи важлива справа? Зокрема, у вашому прикладі будня використовується столиця Uна вівторок, а в нижній регістр - hу четвер.
Брайан Дж

1
@Mego Не редагуйте мою публікацію, якщо модератор не позначить її як дублікат
Julian Lachniet

Відповіді:


10

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

!ms`^(.+?)(?!.+^\1)(?<!^\1.+)

Введення та вихід - це рядки рядків, розділені між стрічковими каналами.

Спробуйте в Інтернеті! (Для зручності тестуйте набір з розділенням коми.)

Пояснення

Це просто узгоджує всі префікси з одним регулярним виразом і друкує їх ( !). mі sє звичайними модифікаторами регулярних вирівнювань для створення ^початкових рядків .матчу та підведення каналів.

^(.+?)      # Match the shortest possible prefix of a line and capture
            # it in group 1.
(?!.+^\1)   # Make sure that this prefix does not show up in a line after
            # the current one.
(?<!^\1.+)  # Make sure that this prefix does not show up in a line before
            # the current one.

10

Python 2 , 87 86 байт

lambda a:[b[:min(i for i in range(len(b))if sum(s[:i]==b[:i]for s in a)<2)]for b in a]

Спробуйте в Інтернеті!


lambda a:[[b[:i]for i in range(len(b))if sum(s[:i]==b[:i]for s in a)<2][0]for b in a]за 85 байт
Кертіс Бехтел

заміна len(b)з 4**8економить ще 2 байта, виходячи з припущення , що рядки будуть не більше 65536 символів
Curtis Bechtel

8

JavaScript (ES6), 81 78 74 70 байт

Приймає введення як масив рядків.

a=>a.map(s=>[...s].reduce((y,c)=>a.some(x=>x!=s&!x.indexOf(y))?y+c:y))

Відформатовано та прокоментовано

a =>                          // given an array of strings 'a'
  a.map(s =>                  // for each string 's' in 'a':
    [...s].reduce((y, c) =>   //   starting with 'y' = first character of 's',
                              //   for each subsequent character 'c' of 's':
      a.some(x =>             //     if we find a string 'x' in 'a' such that:
        x != s &              //       - 'x' is different from 's'
        !x.indexOf(y)         //       - and 'y' appears at the beginning of 'x'
      ) ?                     //     then:
        y + c                 //       append 'c' to 'y'
      :                       //     else:
        y                     //       keep 'y' unchanged
    )                         //   end of reduce(): returns the correct prefix
  )                           // end of map()

Тестові справи


1
70 теж, але абсолютно інше: codegolf.stackexchange.com/a/113270/32091
Qwertiy

+1 для reduce.
Ніл

6

Желе , 14 байт

;\w@þ=1Si1⁸ḣð€

Спробуйте в Інтернеті!

Як це працює

;\w@þ=1Si1⁸ḣð€  Monadic link. Argument: A (string array)

            ð   Collect all links to the left into a chain (arity unknown) and
                begin a dyadic chain.
             €  Map the previous chain over A. The current chain is dyadic and the
                mapped one inherits its arity. Thus, the right will be A for all
                invocations, while the left argument will iterate over A.
                For each string s in A, the following happens.
;\                Cumulative reduce by concatenation; yield all prefixes of s.
  w@þ             Window index swapped table; for each string t in A and each
                  prefix p of s, find the index of the substring t in p.
                  The first index is 1; 0 means not found.
     =1           Compare the indices with 1, returning 1 iff t begins with p.
       S          Sum the Booleans across columns, counting the number of strings
                  in A that begin with a given prefix.
        i1        Find the first index of 1, the shortest prefix that is unique
                  across all strings in A.
          ⁸       Head; truncate s to the computed length.

6

Haskell , 48 байт

[_]#x=""
a#(c:y)=c:[z|d:z<-a,c==d]#y
f=map=<<(#)

Спробуйте в Інтернеті!

  • f- це основна функція, складання списку Strings та повернення a String. Його визначення - це монадичний ярлик для f a=map (a#) a.
  • a#xрозглядає рядок xі список aі намагається знайти найкоротший префікс, xякий є унікальним a. Якщо aє один елемент, просто використовуйте порожній рядок. Якщо aце ще не один елемент, відріжте перший символ x, відфільтруйте та рубайте елементи, aпочинаючи з того самого символу, а потім повторіть повтор.


3

Желе , 14 12 байт

ḣ€JṙLḶ$ḟ/€Ḣ€

Спробуйте в Інтернеті!

Як це працює

ḣ€JṙLḶ$ḟ/€Ḣ€  Main link. Argument: A (string array)

  J           Yield the 1-based indices of A, i.e., [1, ..., len(A)].
ḣ€            Head each; for each string s in A, take the first 1, ..., and len(A) 
              characters. This builds the 2D array of prefixes of all strings in A.
    LḶ$       Length-unlength; yield [0, ..., len(A)-1].
   ṙ          Rotate the 2D array 0, ..., and len(A)-1 units to the left.
       ḟ/€    Reduce filterfalse each; for each rotation, remove all prefixes from
              the first set that also occur in later sets.
          Ḣ€  Head each; for each rotation, keep only the shortest unique prefix.

Просто цікаво, чому у вас тут 2 відповіді? Мені вони обоє подобаються, але мені просто цікаво, чому у вас тут є два відповіді «Желе». :)
HyperNeutrino

Якщо у мене є два аналогічні конкурентні підходи, але досить різні підходи, я зазвичай розміщую їх окремими відповідями.
Денніс

Влучне зауваження. Так, мені просто було цікаво. :) Це хороша ідея; У мене зазвичай не один підхід: P
HyperNeutrino

2

C ++ 11 (MinGW), 198 байт

#import<list>
#import<iostream>
f(std::list<std::string>l){int i,m;for(auto s:l){for(i=0,m=1;++i<s.length();)for(auto t:l)if(t!=s&&t.substr(0,i)==s.substr(0,i))m=i+1;std::cout<<s.substr(0,m)<<" ";}}

Телефонуйте за допомогою:

int main()
{
    f({"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"});
}

Додавання voidідентифікатора перед функцією повинно змусити його компілювати і інші компілятори, тим самим додавши до довжини 5 байт.


Це повинно бути void f..., інакше не працює ... + 5 байт, на жаль. Наскільки мені відомі функції, потрібні специфікатори типу в C ++
Містер Xcoder

Крім того, видатний підхід! Гольф в C / C ++ може бути болючим
Містер Xcoder

@ Mr.Xcoder Хоча це компілюється на компіляторі MinGW, який я використовую. Отже, це або розширення компілятора, або невизначена поведінка.
Steadybox

Я думаю, що це стосується розширення компілятора, на GCC це не працює ...
Містер Xcoder

1
Поки існує середовище, в якому працює код, він дійсний
підземний

2

Javascript ES6, 70 символів

s=>(s+'#'+s).replace(/(\w+?)(\w*)(?=(\W(?!\1(?!\2))\w+)+$)|#.+/g,"$1")

f=s=>(s+'#'+s).replace(/(\w+?)(\w*)(?=(\W(?!\1(?!\2))\w+)+$)|#.+/g,"$1")

console.log(f("one,two,three,four,five,six,seven")==="o,tw,th,fo,fi,si,se")
console.log(f("red,orange,yellow,green,blue,purple")==="r,o,y,g,b,p")
console.log(f("one,two,three,four,five,six,seven".split`,`)==="o,tw,th,fo,fi,si,se")
console.log(f("red,orange,yellow,green,blue,purple".split`,`)==="r,o,y,g,b,p")


2

PHP, 131 120 119 118 байт

Дякуємо @ Jörg за preg_grep.

for(;a&$s=$argv[++$k];$i=+$t=!print"$t
")for(;a&$s[$i]&&1<count(preg_grep("(^".preg_quote($t.=$s[$i++]).")",$argv)););

приймає дані з аргументів командного рядка; друкує результати по одному рядку кожен.
Запустіть -nrабо спробуйте в Інтернеті .

  • може вийти з ладу, якщо вхід містить щось, що починається з -.
    +15 байт для виправлення: замініть другий $argvна array_slice($argv,1).
  • отримує попередження в PHP 7.1; замінити a&з ""<(+1 байт) , щоб виправити.
  • -12 байт, якщо введення не містить спеціальних символів для регулярних виразів:
    Вставити &($t.=$c)раніше &&і замінити ". preg_quote($t.=$c)."на $t.

зламатися

for(;a&$s=$argv[++$k];      # loop $s through arguments
    $i=+$t=!                # 3. reset $i and $t to empty
    print"$t\n")            # 2. print abbreviation
    for(;a&($c=$s[$i++])    # 1. loop $c through characters
        &&1<count(              # 3. if count==1, break loop
            preg_grep("(^"      # 2. find matching arguments
                . preg_quote(
                $t.=$c          # 1. append $c to abbreviation
            ).")",$argv)
        );
    );

не-регулярна версія, 131 130 байт

for($a=$argv;a&$s=$a[++$k];$i=+$t=!print"$t
")for($n=1;$n&&a&$c=$s[$i++];)for($n=$m=1,$t.=$c;a&$u=$a[$m++];)$n-=0===strpos($u,$t);

Замінити перший і останній a&з ""<(+2 байта) , щоб виправити для PHP 7.1.

зламатися

for($a=$argv;a&$s=$a[++$k];     # loop through arguments
    $i=+$t=!print"$t\n")            # 2. print abbreviation, reset $i and $t to empty
    for($n=1;$n&&a&$c=$s[$i++];)    # 1. loop through characters while $n<>0
        for($n=$m=1,                    # reset $n and $m to 1
            $t.=$c;                     # append current character to prefix
            a&$u=$a[$m++];              # loop through arguments:
        )$n-=0===strpos($u,$t);         # -$n = number of matching strings -1

абсолютно нецікава примітка:
strstr($u,$t)==$uі 0===strpos($u,$t)мають однакову довжину і однаковий результат.


Використовуйте справжній символ нового рядка ( 0x0A) замість \n, це збереже один байт;).
Blackhole

@Blackhole Спасибі; Цього разу я забув про це.
Тит

1

PHP, 127 байт

працює не з недійсними масивами

<?foreach($a=$_GET as$k=>$v)for($i=0,$c=2,$s="";$c>1;$r[$k]=$s)$c=count(preg_grep("_^".($s.=$v[$i++])._,$a));echo join(",",$r);

PHP, 132 байт

<?foreach($a=$_GET as$v)for($i=0,$s="";a&$v[$i];)if(count(preg_grep("_^".($s.=$v[$i++])._,$a))==1){$r[]=$s;break;}echo join(",",$r);

Інтернет-версія

151 Байт підтримує спеціальні символи

<?foreach($a=$_GET as$v)for($i=0,$s="";a&$v[$i];)if(count(preg_grep("_^".preg_quote($s=substr($v,0,++$i),_)._,$a))==1){$r[]=$s;break;}echo join(",",$r);

PHP, 140 байт

<?foreach($a=$_GET as$k=>$v)for($i=0;a&$v[$i];)if(count(preg_grep("#^".($s=substr($v,0,++$i))."#",$a))==1){$r[]=$s;break;}echo join(",",$r);

Це не вдасться, якщо вхід містить спеціальні символи регулярного вираження. У мене було б 113 байт замість 131, якщо ні.
Тит

@Titus У цьому випадку я можу додати preg_quoteлише 10 байт
Jörg Hülsermann

Він також вийде з ладу, якщо вхід містить 0. Але ви можете зберегти один байт за допомогою $i=+$s="".
Тит

і ви можете видалити count()-count()матеріал: введення гарантовано є дійсним (-21 байт). Я думаю, я міг би виправити та переграти це до 120 байт. $_GETбула гарна ідея!
Тит

@Titus Я не зрозумів, що дозволені лише допустимі масиви. Так, це не вдасться, якщо рядок містить нуль, але це народило ідею
Йорг Гюльсерманн

0

Clojure, 118 байт

#(reduce(partial map(fn[a b](or a b)))(for[i(range 1e2)S[(for[c %](take i c))]](for[s S](if(=((frequencies S)s)1)s))))

Це працює над префіксами довжиною, 1e2але той самий підрахунок байтів може підтримувати до 1e9. iпетлі довжини префіксів S- це послідовність підрядків довжини i. Останній forзамінює ті підрядки, з nilякими трапляються частіше, ніж один раз. Зниження зберігає перше ненульове значення для кожного рядка, занадто погано orне є функцією, тому мені довелося завершити його.

Це фактично повертає списки подібних символів ((\M) (\T \u) (\W) (\T \h) (\F)), але я думаю, що це прийнятно. Clojure досить багатослівний з рядками, і subsкидав би StringIndexOutOfBoundsExceptionна відміну take.

Повні приклади:

(def f #(reduce(partial map(fn[a b](or a b)))(for[i(range 1e2)S[(for[c %](take i c))]](for[s S](if(=((frequencies S)s)1)s)))))

(f ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"])
(f (re-seq #"[^,]+" "one,two,three,four,five,six,seven"))
(f (re-seq #"[^,]+" "red,orange,yellow,green,blue,purple"))

0

SQL (аромат PostgreSQL 9.4), 219 байт

Тепер для найдовшої відповіді :) Я не думаю, що це навіть може перемогти Java. Я спробую поголити ще кілька від цього. Сподіваючись позбутися одного з вкладених запитів, але мені не подобаються мої шанси.
Це передбачає, що існує таблиця, яка містить рядки, над якими буде працювати. Оскільки це SQL, порядок повернення не гарантується таким, як порядок таблиці, і в цьому випадку малоймовірний. Якщо це проблема, я видалю.

SELECT R FROM(SELECT*,RANK()OVER(PARTITION BY A ORDER BY C,N)Z FROM(SELECT*,SUM(1)OVER(PARTITION BY R)C FROM(SELECT*FROM A JOIN LATERAL(select left(A,n)R,N FROM generate_series(1,length(A))S(n))L ON 1=1)X)Y)Z WHERE Z=1


Пояснення SQL Fiddle

  SELECT *
  FROM A 
    JOIN LATERAL(SELECT LEFT(A,n)R,N 
    FROM generate_series(1,length(A))S(n))L ON 1=1

Найпотаємніший запит використовує generate_seriesі LATERALоб'єднує для створення рядків для рядка, розділеного на збільшуючу довжину, так що "один" стає "о", "на", "один". Кількість символів у звороті також зберігається.

SELECT 
  *,
  SUM(1)OVER(PARTITION BY R)C
FROM ( ... )X

Потім додаємо кількість записів, які мають однаковий результат. Наприклад, 'f' від чотирьох і п'яти має 2, але 'fo' і 'fi' мають по одному. OVERЗаява в SQL може бути досить потужним. COUNT(*)було б звичайним способом, але SUM(1)дає той же результат.

SELECT 
  *,
  RANK()OVER(PARTITION BY A ORDER BY C,N)Z
FROM ( ... )Y

Потім ми класифікуємо результати для кожного введення на основі найменших повторів та символів. ROW_NUMBERТут би також працювали, але це довше.

SELECT R FROM ( ... )Z WHERE Z=1;

Нарешті ми вибираємо найнижчий номер для кожного слова.



0

APL (Dyalog) , 27 байт

{⍵↑¨⍨1⍳⍨¨↓+/(↑,⍵)∘.(⊃⍷)⍵}

Спробуйте в Інтернеті!

{ анонімна функція, де ⍵ являє собою аргумент ...

∘.( таблиця функцій, де функція

   перший елемент

   булівський список "лівий аргумент починається тут з правого аргументу?"

) де правильні аргументи

 аргуемти

( а лівий аргумент -

   таблиця з рядками, що складається з

  ,/ префікси

  ¨ кожен з

   аргументи

+/ сума впоперек (підраховує кількість аргументів, що відповідають цьому префіксу)

 розділити таблицю на список рядків

⍳⍨¨ у кожному з них знайдіть місце розташування першого

1 один (тобто перший префікс, який очолює лише один аргумент)

↑¨⍨ для кожного місця займає стільки символів із відповідного елемента

 аргумент

} кінець анонімної функції


0

PowerShell, 151 139 байт

$x,$w=@(),$args[0];$w|%{$k=$_;$a='';foreach($l in [char[]]$k){$a+=$l;if($a-notin$x-and!($w|?{$_-ne$k-and$_-like"$a*"})){$x+=$a;break;}}};$x

Цікавить, чи є кращий спосіб це зробити. Довелося використовувати a foreach(over a |%), щоб мати можливість виконувати a breakвкладений цикл, не позначаючи його.

Редагувати: 2 гольфи від AdmBorkBork


1
Я не переглядав код безпосередньо, але напевно, ви можете використовувати -notinзамість цього, -not$x.contains($a)а не !($w...замість цього, -not($w...щоб зберегти кілька байтів, так?
AdmBorkBork

0

APL, 26 байт

{⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}

Пояснення:

  • ↓↑⍵: прокладіть кожен рядок, щоб відповідати довжині найдовшого рядка
  • ∘.(... )⍨: для кожної можливої ​​пари рядків знайдіть спільний префікс:
    • : нерівність масиву
    • : і
    • =: предметна рівність
    • ∧\: та сканувати (зберігати лише провідні матчі)
  • +/¨: підсумовуйте кожен вектор у таблиці, даючи довжину спільних префіксів
  • ⌈/: знайти максимальне значення у кожному стовпчику
  • 1+: додайте один, даючи кількість символів, необхідних для збереження унікальної строки
  • ⍵↑¨⍨: взяти стільки символів з кожного рядка

Тест:

      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday'
┌─┬──┬─┬──┬─┐
│M│Tu│W│Th│F│
└─┴──┴─┴──┴─┘
      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'one' 'two' 'three' 'four' 'five' 'six' 'seven'
┌─┬──┬──┬──┬──┬──┬──┐
│o│tw│th│fo│fi│si│se│
└─┴──┴──┴──┴──┴──┴──┘
      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'red' 'orange' 'yellow' 'green' 'blue' 'purple'
┌─┬─┬─┬─┬─┬─┐
│r│o│y│g│b│p│
└─┴─┴─┴─┴─┴─┘

0

Q, 93 байти

{n:1;{$[any e:(,/)1<{(+/)i like x}each i:z#'x;[z+:1;y:?[e;z#'x;i];.z.s[x;y;z]];y]}[x;n#'x;n]}

Вирішується рекурсивно, приймає рядок як вхідний, отримує перші n елементів кожного рядка з кожною рекурсією. Якщо будь-який із цих елементів не є унікальним, він замінює їх першими n + 1 елементами.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.