Generalisasi singkatan

14

Diberikan masukan dari daftar kata-kata dan singkatan-singkatannya, menampilkan pola pembentukan singkatan-singkatan itu.

Mari kita ambil contoh input

potato ptao
puzzle pzze

sebagai contoh (yaitu, singkatan untuk potatoadalah ptao, dan singkatan untuk puzzleadalah pzze).

Pertimbangkan semua cara yang mungkin untuk mendapatkan ptaodari potato. Satu cara yang mungkin adalah dengan mengambil huruf pertama, ketiga, keempat, dan keenam, yang akan kita sebut sebagai 1346. Tapi karena tdan omuncul beberapa kali dalam kata, ada beberapa cara lain yang mungkin untuk menghasilkan ptaodari potato: 1546, 1342, dan 1542.

Demikian pula, catatan yang pzzedapat dihasilkan dari puzzledengan salah 1336, 1346, 1436, 1446. Satu-satunya pola yang dimiliki oleh kedua singkatan ini adalah 1346; oleh karena itu, itu harus menjadi output untuk input ini. Jika beberapa pola yang memungkinkan dimungkinkan, Anda dapat menampilkan salah satu, beberapa, atau semuanya (setidaknya satu).

Anda dapat berasumsi bahwa:

  • Input kata dan singkatan hanya berisi huruf kecil.

  • Setidaknya ada satu pasangan kata / singkatan dalam input.

  • Dimungkinkan untuk setiap singkatan dibentuk dari kata yang sesuai.

  • Akan selalu ada setidaknya satu pola yang membentuk setiap singkatan.

  • Panjang maksimum setiap kata adalah 9 karakter.

Masukan dapat diambil sebagai berikut:

  • Array 2-dimensi / daftar / array tupel / dll. [[word, abbr], [word, abbr], ...]

  • Daftar / array 1 dimensi yang datar [word, abbr, word, abbr, ...]

  • string tunggal, dibatasi oleh karakter tunggal yang bukan huruf kecil "word abbr word abbr"

  • hash / array asosiatif / dll. {word => abbr, word => abbr, ...}

Di salah satu opsi input ini, Anda juga diizinkan untuk menukar urutan kata / abbr (harap jelaskan format input di pos Anda).

Output dapat diberikan sebagai angka tunggal, string dibatasi oleh non-digit, atau array / daftar / tuple / dll. angka.

Karena ini adalah , kode terpendek dalam byte akan menang.

Uji kasus (ingat bahwa Anda hanya perlu menampilkan ≥1 hasil jika beberapa pola berfungsi):

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
Gagang pintu
sumber
Hanya untuk memastikan saya mengerti, proses singkatan dapat menyusun ulang huruf?
xnor
@ xnor Benar, seperti yang terlihat dalam beberapa kasus uji.
Gagang Pintu
Dapatkah array 2D memiliki orientasi lain? Setiap kolom, bukan setiap baris, akan berisi sepasang kata / singkatan
Luis Mendo
@ DonMuesli Tidak, tidak bisa.
Gagang Pintu
Bisakah kita menggunakan pengindeksan nol, jadi cetak 0235 bukan 1346?
Denker

Jawaban:

3

Pyth, 19 byte

[email protected]

Coba di sini!

Mengambil daftar dalam format berikut:

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

Alternatif 17 byte solusi yang menampilkan hasilnya sebagai daftar indeks berbasis nol yang dibungkus dalam daftar 1-elemen:

[email protected]

Penjelasan

Contoh: [["potato", "ptao"],["puzzle", "pzze"]]

Pertama kita memetakan setiap karakter dalam singkatan ke daftar indeks dari semua kejadian dalam kata yang menghasilkan

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

Lalu kami mengubah daftar ini yang memberi kami

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

Jadi indeks masing-masing karakter dari masing-masing singkatan disatukan dalam satu daftar.

Maka kita hanya perlu menemukan satu indeks umum di semua daftar yang menghasilkan:

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

Ini adalah output dari solusi 17 byte alternatif saya di atas. Ini kemudian ditransformasikan menjadi [1,3,4,6].

Rincian kode

[email protected] # Q = input

m Q # masukan peta dengan d
        m ed # petakan setiap singkatan dengan k
            mbhd # peta kata ke daftar char
         mxk # memetakan setiap singkatan char ke daftar indeks
      .T # Transpose
    Fd # Lipat setiap elemen
   @ # dan saring jika ada
 hh # Ambil elemen pertama dari und undrement dan tambahkan
Denker
sumber
Tidak bisakah Anda juga menghapus dmhak sebelum @?
Gagang Pintu
@ Doorknob saya bisa. Terima kasih telah melihatnya!
Denker
3

MATL , 29 byte

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

Input adalah array 2D dalam format berikut:

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

Cobalah online! ( kode tertaut menyertakan beberapa modifikasi karena perubahan bahasa sejak jawaban ini diposting )

!       % 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

Kode diperlukan beberapa trik yang terlibat (dan panjang!) Untuk

  • Cegah orientasi vektor yang dihasilkan oleh find( f) agar tidak berubah tergantung pada bentuk input. Ini adalah pernyataan X:wX:: paksakan kedua output menjadi vektor kolom.
  • Menangkal perilaku default "bekerja sepanjang dimensi non-singleton" dari fungsi min( X>). Ini adalah pernyataan tv: ambil salinan dirinya sendiri untuk memastikan setidaknya dua baris);
Luis Mendo
sumber
2

Perl, 46 45 42 byte

Termasuk +1 untuk -p

Berikan input sebagai kata berurutan pada STDIN, mis

perl -p abbrev.pl
prgrmming
prgmg
puzzles
pzzlz

Hentikan STDIN dengan ^Datau ^Zatau apa pun yang diperlukan di sistem Anda

abbrev.pl:

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

Penjelasan

Pertimbangkan input ini (tata letak konseptual, bukan cara input nyata untuk program ini):

potatoes     ptao
puzzle       pzze

String pembangun program mewakili kolom vertikal dari string penuh yang diindeks pada id kolom

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

dll. Ia juga melakukan hal yang sama untuk singkatan, tetapi menggunakan id yang berbeda

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

Kata-kata diproses secara implisit satu per satu dengan menggunakan -popsi. String kolom dikonstruksikan menggunakan rangkaian berulang sementara setiap kata berjalan menggunakan s#.# ...code.. #eg, sehingga setiap kolom membutuhkan id berulang. Saya menggunakan minus nomor kolom diikuti oleh modulo nomor 2. Nomor kolom dapat dibangun menggunakan --$_yang dimulai sebagai kata saat ini yang karena penggunaan hanya a-zdijamin untuk mengevaluasi sebagai 0 dalam konteks numerik. Jadi saya mengerti -1, -2, -3, .... Aku benar-benar ingin menggunakan 1, 2, 3, ..., tetapi menggunakan $_++akan memicu pertambahan string magic perl bukan penghitung angka normal. Saya tidak ingin menggunakan$_ dan bukan beberapa variabel lain karena variabel lain saya harus menginisialisasi ke nol di setiap loop yang membutuhkan terlalu banyak byte.

Nomor baris modulo 2 adalah untuk memastikan id untuk kata penuh dan id untuk singkatan tidak berbenturan. Perhatikan bahwa saya tidak dapat menggunakan kata lengkap dan singkatan pada satu string untuk memiliki nomor kolom melewati string gabungan karena kata-kata penuh tidak semua memiliki panjang yang sama, sehingga kolom kata yang diuraikan tidak akan berbaris. Saya juga tidak dapat menempatkan kata singkatan terlebih dahulu (mereka semua memiliki panjang yang sama) karena saya perlu jumlah kolom pertama dari kata-kata penuh menjadi 1.

Saya menyalahgunakan ruang nama perl global melalui referensi yang tidak ketat untuk membuat string kolom sebagai:

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

Selanjutnya saya memetakan setiap string kolom ke nomor kolom pertama yang pernah muncul string (pemetaan sudah ditunjukkan di atas) dengan lagi menyalahgunakan perl namespace global (tetapi perhatikan bahwa nama tidak dapat berbenturan sehingga global tidak saling mengganggu):

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

Saya harus meniadakan $_karena seperti yang saya jelaskan di atas saya menghitung kolom sebagai -1, -2, -3, .... The ||=make yakin hanya penampilan pertama kolom tertentu mendapat sejumlah kolom baru, jika tidak jumlah kolom sebelumnya dipertahankan dan dikembalikan sebagai nilai. Ini akan terjadi khususnya untuk setiap kata yang disingkat karena spesifikasi menjamin bahwa ada kolom dalam kata-kata lengkap yang akan muncul sebelumnya. Jadi dalam kata yang disingkat terakhir setiap huruf akan diganti dengan nomor kolom dalam kata lengkap yang sesuai dengan kolom untuk semua kata yang disingkat. Jadi hasil dari pergantian terakhir adalah hasil akhir yang diinginkan. Jadi cetak jika dan hanya jika kita berada di akhir input:

$_ x=eof

Penugasan indeks kolom juga akan membuat entri untuk kolom tidak lengkap karena kolom belum sepenuhnya dibangun atau beberapa kata lebih pendek dan tidak mencapai panjang kolom penuh. Ini bukan masalah karena kolom yang dibutuhkan dalam setiap kata yang disingkat dijamin memiliki kolom koreksi dari kata-kata lengkap yang memiliki panjang maksimum yang mungkin (jumlah pasangan yang terlihat saat ini) sehingga entri tambahan ini tidak pernah menyebabkan kecocokan yang salah.

Ton Hospel
sumber
1

Haskell, 74 byte

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

Format input adalah daftar pasangan string, misalnya:

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

Cara kerjanya: mapM(sama seperti sequence . map) pertama-tama mengubah setiap pasangan (w,a)menjadi daftar daftar indeks huruf dalam singkatan ( ' ':memperbaiki indeks berbasis 0 asli Haskell menjadi berbasis 1), misalnya ("potato", "ptao") -> [[1],[3,5],[4],[2,6]]dan kemudian ke daftar semua kombinasi daripadanya di mana elemen pada posisi idiambil dari isublist th, mis [[1,3,4,2],[1,3,4,6],[1,5,4,2],[1,5,4,6]].foldl1 intersectmenemukan persimpangan semua daftar daftar tersebut.

nimi
sumber
0

ES6, 92 byte

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

Menerima input sebagai larik kata dan larik singkatan. Mengembalikan array indeks berbasis 1 (yang biayanya 2 byte dammit). Dalam kasus beberapa solusi, indeks tertinggi dikembalikan.

Neil
sumber
0

Python 3, 210 byte

Bukan jawaban yang mengesankan melihat skor teratas di sini, tapi ini benar-benar beberapa pemahaman daftar paling gila yang pernah saya lakukan dengan Python. Pendekatannya cukup maju ke depan.

 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]]

Fungsi mengharapkan input selalu sebagai string 2-D array seperti: [[word, abbr],...]dan mengembalikan daftar bilangan bulat.

Ps: Penjelasan terperinci segera hadir

Ps2: Saran golf lebih lanjut disambut!

Ioannes
sumber