Узагальнення скорочень


14

Давши введення списку слів та їх скорочень, виведіть шаблон, за яким можна утворити абревіатури.

Візьмемо для прикладу введення

potato ptao
puzzle pzze

як приклад (тобто абревіатура для potatoє ptao, а абревіатура для puzzleє pzze).

Розглянемо всі можливі способи отримання ptaoз potato. Один з можливих способів - взяти першу, третю, четверту та шосту букви, про які ми будемо називати 1346. Але так як tі oз'являтися кілька разів на слові, є кілька інших можливих способів отримання ptaoз potato: 1546, 1342і 1542.

Крім того , зауважимо , що pzzeможуть бути отримані з puzzleз будь-яким з 1336, 1346, 1436, 1446. Єдина закономірність, яку мають ці дві абревіатури, - це 1346; отже, це повинен бути вихід для цього вводу. Якщо можливе кілька можливих шаблонів, ви можете вивести будь-яку, якусь або всі (хоча б одну).

Ви можете припустити, що:

  • Введені слова та скорочення містять лише малі літери.

  • У вході є принаймні одна пара слів / абревіатур.

  • З кожного відповідного слова можна утворити кожну абревіатуру.

  • Завжди буде принаймні один візерунок, який утворює кожну абревіатуру.

  • Максимальна довжина кожного слова - 9 символів.

Введення даних може бути прийнято як будь-яке з наведених нижче:

  • 2-мірний масив / список / масив кортежів тощо. [[word, abbr], [word, abbr], ...]

  • плоский одновимірний масив / список [word, abbr, word, abbr, ...]

  • одна рядок, обмежена будь-яким одним символом, який не є малим літером "word abbr word abbr"

  • хеш / асоціативний масив / тощо. {word => abbr, word => abbr, ...}

У будь-якому з цих варіантів введення вам також дозволяється поміняти порядок слова / abbr (будь ласка, повністю опишіть формат введення у вашій публікації).

Вихід може бути заданий як одне число, рядок, розділений нецифровими знаками, або масив / список / кортеж / тощо. чисел.

Оскільки це , найкоротший код у байтах виграє.

Тестові випадки (пам’ятайте, що потрібно вивести ≥1 результати лише у тому випадку, якщо працює декілька шаблонів):

In                                Out
--------------------------------------------------------
potato ptao puzzle pzze         | 1346
aabbcc abc fddeef def           | 246
prgrmming prgmg puzzles pzzlz   | 14353
aaaaa a bbbb b ccc c dd d e e   | 1
aaaaa a bbbb b ccc c            | 1, 2, 3
abcxyz zbcyax                   | 623514
abcxyz acbbacbcbacbbac          | 132213232132213
potato ptao                     | 1346, 1546, 1342, 1542
a aaaaa                         | 11111

Просто щоб переконатися, що я розумію, процес абревіатури може впорядкувати літери?
xnor

@xnor Правильно, як це спостерігається у кількох тестових випадках.
Дверна ручка

Чи може 2D масив мати іншу орієнтацію? Кожен стовпець, а не кожен рядок, міститиме пару слів / абревіатур
Луїс Мендо

@DonMuesli Ні, не може.
Дверна ручка

Чи можемо ми використовувати нульову індексацію, тому надрукуйте 0235 замість 1346?
Денкер

Відповіді:


3

Pyth, 19 байт

mhh@Fd.TmmxkmbhdedQ

Спробуйте тут!

Знімає список у такому форматі:

[["word","abbr"],["word","abbr"],...]

Альтернативно 17-байтне рішення, яке виводить результат у вигляді списку нульових індексів, які загорнуті в 1-елементний список:

m@Fd.TmmxkmbhdedQ

Пояснення

Приклад: [["potato", "ptao"],["puzzle", "pzze"]]

По-перше, ми відображаємо кожен знак у скороченні до списку індексів усіх випадків слова, яке дає

[[[0], [2, 4], [3], [1, 5]], [[0], [2, 3], [2, 3], [5]]]

Потім ми переносимо цей список, який нам дає

[[[0], [0]], [[2, 4], [2, 3]], [[3], [2, 3]], [[1, 5], [5]]]

Таким чином, індекси кожної таблиці кожної абревіатури є разом в одному списку.

Тоді нам просто потрібно знайти один загальний індекс у всіх тих списках, який дає:

[[0], [2], [3], [5]]

Це результат мого альтернативного 17-байтного рішення вище. Потім це перетворюється на[1,3,4,6] .

Розбивка коду

mhh@Fd.TmmxkmbhdedQ # Q = вхід

m Q # введення карти з d
        m ed # карта кожного скорочення за допомогою k
            mbhd # карта зі словом до списку char
         mxk # відобразити кожну скорочувальну таблицю до списку індексів
      .T # Перенести
    Fd # Складіть кожен елемент
   @ # і фільтруйте за наявністю
 hh # Візьміть перший елемент результату і збільште його

Не могли ви також видалити dmправо перед @?
Дверна ручка

@Doorknob я можу. Дякуємо, що помітили це!
Денкер

3

MATL , 29 байт

!"@Y:!=2#fX:wX:h]N$v1XQtv4#X>

Вхід - це двовимірний масив у такому форматі:

{'potato' 'ptao'; 'puzzle' 'pzze'}

Спробуйте в Інтернеті! ( зв'язаний код включає деякі зміни внаслідок зміни мови з моменту опублікування цієї відповіді )

!       % take input. Transpose
"       % for each column
  @Y:   %   push column. Unpack the two strings and push them onto the stack
  !     %   transpose second string
  =     %   matrix with all pairwise matchings of characters in word and abbreviation
  2#f   %   find row and col indices of those matchings
  X:    %   transform into column vector
  wX:   %   swap, transform into column vector
  h     %   concat into a two-col matrix
]       % end for
N$v     % concatenate all matrices containing the indices
1       % push 1
XQ      % build matrix adding 1 for each (row,col) index
tv      % concat vertically with itself, so that it has at least two rows.
        % This forces the following function to work on each col.
4#X>    % arg max of each col: position that produces a match in all pairs.
        % If there are several maximizers in each col this gives the first

Код вимагав деяких причетних (і тривалих!) Хитрощів

  • Запобігайте зміні орієнтації векторів, вироблених find( f), залежно від форми введення. Це заяви X:wX:: примушуйте обидва виходи бути векторами стовпців.
  • Протидіяти «роботу уздовж Перший не Сінглтон розмірності» поведінка за умовчанням min( X>функції). Це твердження tv: складіть копію себе, щоб забезпечити принаймні два ряди);

2

Perl, 46 45 42 байт

Включає +1 для -p

Дайте введення як послідовні слова на STDIN, наприклад

perl -p abbrev.pl
prgrmming
prgmg
puzzles
pzzlz

Скасуйте STDIN з допомогою ^Dабо ^Zщо потрібно для вашої системи

abbrev.pl:

s#.#${${--$_.$.%2}.=$&}||=-$_#eg;$_ x=eof

Пояснення

Розглянемо цей вхід (концептуальна схема, а не реальний спосіб введення для цієї програми):

potatoes     ptao
puzzle       pzze

Програма будує рядки, що представляють вертикальні стовпці повних рядків, індексованих на ідентифікатор стовпця

id1    pp     -> 1
id2    ou     -> 2
id3    tz     -> 3
id4    az     -> 4
...

і т.д. Це також робить те ж саме для абревіатур, але використовуючи інший ідентифікатор

ID1    pp     -> 1
ID2    tz     -> 3
ID3    az     -> 4
ID4    oe     -> 6

Слова неявно обробляються по одному за допомогою -pпараметра. Рядки стовпців побудовані за допомогою повторних конкатенацій під час використання кожного слова s#.# ...code.. #eg, тому кожен стовпець потребує повторюваного ідентифікатора. Я використовую мінус номер стовпця з подальшим модулем номера рядка 2. Номер стовпця може бути побудований, використовуючи --$_яке починається як поточне слово, яке завдяки використанню лише a-zгарантовано оцінювати як 0 у числовому контексті. Так я отримую -1, -2, -3, .... Мені б дуже хотілося б користуватися 1, 2, 3, ..., але використання $_++викликає прирост магічної струни perl замість звичайного числового лічильника. Я є, хочу , щоб використовувати$_ а не якась інша змінна, тому що будь-яку іншу змінну мені доведеться ініціалізувати до нуля у кожному циклі, який займає занадто багато байтів.

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

Я зловживаю простором простого імені Perl через не суворе посилання для побудови рядків стовпців як:

${--$_.$.%2}.=$&

Далі я зіставляю кожну рядок стовпця на номер першого стовпця, у якому рядок коли-небудь з'являється (відображення вже вказано вище), знову зловживаючи глобальним простором імен perl (але зауважте, що імена не можуть зіткнутися, щоб глобалі не заважали один одному):

${${--$_.$.%2}.=$&} ||= -$_

Я повинен заперечувати, $_тому що, як я пояснював вище, я вважаю стовпці як -1, -2, -3, .... ||=ПЕРЕКОНАЙТЕСЯ тільки перша поява даної колонки отримує новий номер стовпчика, в іншому випадку попередній номер стовпця зберігається і повертається в якості значення. Це відбудеться, зокрема, для кожного скороченого слова, оскільки специфікація гарантує, що стовпець у повному обсязі слів буде раніше. Отже, в останньому скороченому слові кожна літера буде замінена номером стовпця у повному слові, яке відповідає стовпцю для всіх скорочених слів. Таким чином, результат останньої заміни є кінцевим результатом, який потрібно шукати. Тож друкуйте, якщо і лише тоді, коли ми в кінці вводу:

$_ x=eof

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


1

Haskell, 74 байти

import Data.List
foldl1 intersect.map(\(w,a)->mapM(`elemIndices`(' ':w))a)

Формат введення - це список пар рядків, наприклад:

*Main > foldl1 intersect.map(\(w,a)->mapM(`elemIndices`(' ':w))a)  $ [("potato","ptao"),("puzzle","pzze")]
[[1,3,4,6]]

Принцип роботи: mapM(так само, як sequence . map) спочатку перетворює кожну пару (w,a)на список списків індексів букв у абревіатурі ( ' ':фіксує власний індекс, заснований на Haskell на 0 на 1), наприклад, ("potato", "ptao") -> [[1],[3,5],[4],[2,6]]а потім у список усіх їх комбінацій, де елемент, який знаходиться в положенні i, виведений із iдругого підпису, наприклад [[1,3,4,2],[1,3,4,6],[1,5,4,2],[1,5,4,6]]. foldl1 intersectзнаходить перетин усіх таких списків списків.


0

ES6, 92 байти

(w,a)=>[...a[0]].map((_,i)=>[...w[0]].reduce((r,_,j)=>w.some((s,k)=>s[j]!=a[k][i])?r:++j,0))

Приймає введення як масив слів та масив скорочень. Повертає масив індексів на основі 1 (що коштує мені 2 байти dammit). У випадку декількох рішень повертаються найвищі показники.


0

Python 3, 210 байт

Не вражаюча відповідь, що простежує тут топи, але це справді одне із найсумніших розумінь списку, що я коли-небудь робив з Python. Підхід досить простий.

 def r(p):
    z=[[[1+t[0]for t in i[0]if l==t[1]]for l in i[1]]for i in[[list(enumerate(w[0])),w[1]]for w in p]]
    return[list(set.intersection(set(e),*[set(i[z[0].index(e)])for i in z[1:]]))[0]for e in z[0]]

Функція очікує введення завжди у вигляді рядкового 2-D масиву типу: [[word, abbr],...]і повертає список цілих чисел.

Пс: детальне пояснення найближчим часом

Ps2: Наступні пропозиції щодо гольфу вітаються!

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