Substring Unik Terpendek


14

Diberikan (pada STDIN, sebagai argumen baris perintah, atau sebagai argumen fungsi) dua string non-kosong yang berbeda, temukan dan kembalikan substring terpendek dari string pertama yang bukan merupakan substring dari string kedua. Jika tidak ada substring seperti itu, Anda dapat mengembalikan string kosong, mengembalikan string apa pun yang bukan substring dari string asli, atau melempar pengecualian. Jika Anda kembali dari suatu fungsi, Anda juga dapat mengembalikan nol (atau tidak ditentukan, Tidak ada, dll.) Dalam kasus ini. Jika beberapa substring terikat untuk yang terpendek, Anda dapat mengembalikan salah satunya.

String dapat terdiri dari karakter ascii yang dapat dicetak.

Input yang diberikan pada STDIN akan diberikan dengan satu string pada setiap baris. Atas permintaan Anda, satu baris kosong dapat ditambahkan di akhir input.

Ini adalah kode golf, sehingga program yang paling singkat yang valid menang.

BEBERAPA KASUS UJI

MEMASUKKAN:

STRING ONE
STRING TWO

KELUARAN:

E

MEMASUKKAN:

A&&C
A&$C

OUTPUT YANG LUAR BIASA:

&&
&C

MEMASUKKAN:

(Dua string 80-huruf yang dihasilkan secara acak)

QIJYXPYWIWESWBRFWUHEERVQFJROYIXNKPKVDDFFZBUNBRZVUEYKLURBJCZJYMINCZNQEYKRADRYSWMH
HAXUDFLYFSLABUCXUWNHPSGQUXMQUIQYRWVIXGNKJGYUTWMLLPRIZDRLFXWKXOBOOEFESKNCUIFHNLFE

SEMUA OUTPUT YANG VALID:

AD
BJ
BR
CZ
DD
EE
ER
EY
EY
FF
FJ
FW
FZ
HE
IJ
IN
IW
JC
JR
JY
KL
KP
KR
KV
LU
MH
MI
NB
NQ
OY
PK
PY
QE
QF
QI
RA
RB
RF
RO
RV
RY
RZ
SW
UE
UH
UN
UR
VD
VQ
VU
WB
WE
WI
WU
XN
XP
YI
YK
YK
YM
YS
YW
YX
ZB
ZJ
ZN
ZV

1
terpendek atau terpanjang?
Leaky Nun

@FryAmTheEggman Maka saya masih harus mengirim solusi saya ...
Leaky Nun

"Satu string di setiap baris" dengan atau tanpa tanda kutip?
Leaky Nun

1
Bisakah kita mengambil serangkaian string?
Dennis

Apakah "B" merupakan substring dari "aBc"?
downrep_nation

Jawaban:


4

Brachylog , 23 byte

:1foh.,{,.[A:B]hs?'~sB}

Bekerja pada transpiler Java lama. Mengharapkan dua string dalam daftar sebagai input, menyatukan output dengan substring. Jika tidak ada substring yang ditemukan, mengembalikan false.

Sayangnya saya belum memberi kode subset built-in di Prolog transpiler baru.

Penjelasan

:1f               Find all bindings which satisfy predicate 1 with that binding as input and
                  with the Input of the main predicate as output.
   oh.,           Order that list of bindings, and unify the output with the first one.

{
 ,.[A:B]          Unify the output with the list [A,B]
        hs?       Unify the input with a subset of A
           '~sB   Check that no subset of B can be unified with the input
               }

4

Python, 119 115 91

lambda a,b:[a[m:m+n]for n in range(1,len(a)+1)for m in range(len(a))if a[m:m+n]not in b][0]

Kasus uji:

| Input 1  | Input 2     | Output        |
|----------+-------------+---------------|
| 'abcd'   | 'abc'       |  'd'          |
| 'abcd'   | 'dabc'      |  'cd'         |
| 'abcd'   | 'dcbabbccd' |  'abc'        |
| 'abcdf'  | 'abcdebcdf' |  'abcdf'      |
| 'abc'    | 'abc'       |  (IndexError) |

Berusaha membuatnya lebih pendek, tapi ini naluri otakku. Belum terlalu pegolf.

Terima kasih kepada @ user81655 dan @NlinlinearFruit untuk byte ekstra.

Edit :

Dang. Mencoba kode ini:

def z(a,b):
 for s in [a[m:m+n]for n in range(1,len(a)+1)for m in range(len(a)-n+1)]:
  if s not in b:return s
 return''

Kupikir itu beberapa byte lebih pendek. Ternyata itu 1 byte lebih lama dari apa yang saya miliki sebelum edit.


Aku tidak tahu banyak python, tapi mungkin Anda dapat lakukan (r=range)(1,len(a)+1)kemudian menggunakan r?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Tidak bisa melakukannya dengan cara seperti itu. Jika saya menetapkan rangeuntuk rdi baris di atas, itu benar-benar menambah byte. Tapi ide bagus. Mungkin ada cara yang lebih pendek untuk beralih melalui substring.
Taylor Lopez

range(1,len(a))dan range(len(a)-1)haruskah bekerja bukan? Saya juga berpikir menggunakan karakter tab untuk dua spasi indent akan menghemat satu byte.
user81655

Tidak, dengan range(1,len(a)), gips uji ke-4 gagal karena tidak akan mencoba string penuh; itu hanya akan pergi ke panjang string - 1. Dan dengan range(len(a)-1), test case 1 gagal mengembalikan 'cd'bukan hanya 'd'. Mungkin ada sesuatu di sana.
Taylor Lopez

Maaf, saya tidak terbiasa dengan Python dan saya menganggap rentangnya inklusif. Dalam hal ini coba range(1,len(a)+1)dan range(len(a)).
user81655

3

Python, 87 86 byte

lambda s,t,e=enumerate:[s[i:i-~j]for j,_ in e(s)for i,_ in e(s)if(s[i:i-~j]in t)<1][0]

Jika ada, ini akan mengembalikan substring unik terpendek ke kiri.

Jika tidak ada substring unik, sebuah IndexError dinaikkan.

Uji di Ideone .


Itu ada. Saya sedang menunggu seseorang untuk membunuh implementasi non-lambda saya. lol yang bagus
Taylor Lopez

Saya pikir Anda dapat membuat ini lebih pendek dengan menyediakan argumen kedua opsional untuk enumeratememulai jdi i+1.
user2357112 mendukung Monica

@ user2357112 Itu melempar NameError , sayangnya. Kode mendefinisikan jpertama, lalu i.
Dennis

@ Dennis: Ya, tapi itu tidak perlu. Anda bisa mengganti urutan loop.
user2357112 mendukung Monica

1
@ user2357112 Jika saya mengganti urutan loop, substring unik pertama yang ditemukannya mungkin bukan yang terpendek. Cukup menukar pengembalian pesanan 'ab'untuk input 'abc','aaa'.
Dennis

2

Python, 82 byte

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}
f=lambda s,t:min(g(s)-g(t),key=len)

Penggunaan: f('A&&C', 'A&$C')-> pengembalian'&&'

Meningkatkan ValueError jika tidak ada substring yang cocok.

Penjelasan:

g=lambda u:{u}|g(u[1:])|g(u[:-1])if u else{''}secara rekursif membuat satu set substring dari u f=lambda s,t:min(g(s)-g(t),key=len)mengambil substring terpendek dari perbedaan set


2

JavaScript (ES6), 79 byte

f=
(a,b)=>[...a].some((_,i,c)=>c.some((_,j)=>b.indexOf(s=a.substr(j,i+1))<0))?s:''
<div oninput=o.textContent=f(a.value,b.value)><input id="a"/><input id="b"/><pre id=o>

Jika pengembalian falsedapat diterima, simpan 2 byte dengan menggunakan &&salih-alih ?s:''.



1

JavaScript (Firefox), 80 byte

solution=

a=>b=>[for(_ of(i=0,a))for(_ of(j=!++i,a))if(b.includes(s=a.substr(j++,i)))s][0]

document.write("<pre>"+
[ [ "test", "best" ], [ "wes", "west" ], [ "red", "dress" ] ]
.map(c=>c+": "+solution(c[0])(c[1])).join`\n`)

Tes hanya berfungsi di Firefox. Kembali undefinedjika tidak ada substring.


String dapat berisi karakter ASCII yang dapat dicetak seperti \ atau metacharacters RegExp lainnya, tetapi jika Anda membatasi diri Anda pada Firefox, mengapa tidak menggunakan b.includessaja?
Neil

@Neil Pertanyaannya tidak mengatakan bahwa string dapat berupa karakter apa pun sebelumnya, tetapi terima kasih telah memberi tahu saya! Diperbarui untuk digunakan includes.
user81655

1
Cuplikan uji melempar aSyntaxError: unexpected token 'for'
NoOneIsHere

@NoOneIsHere Itulah kesalahan yang akan Anda dapatkan jika Anda tidak menggunakan Firefox ...
user81655

1

Retina , 37 byte

M!&`\G(.+?)(?!.*¶.*\1)
O$#`.+
$.&
G1`

Output kosong jika tidak ditemukan substring yang valid di A .

Cobalah online! (Sedikit dimodifikasi untuk menjalankan beberapa test case sekaligus. Format input sebenarnya dipisahkan dengan linefeed, tetapi test suites lebih mudah ditulis dengan satu case test per baris. Kerangka uji mengubah ruang menjadi linefeed sebelum kode aktual dimulai.)

Penjelasan

M!&`\G(.+?)(?!.*¶.*\1)

Untuk setiap posisi awal yang memungkinkan di A, cocokkan substring terpendek yang tidak muncul di B. The &adalah untuk tumpang tindih pertandingan, seperti yang kita benar-benar mencoba setiap posisi awal, bahkan jika pertandingan lebih panjang dari satu karakter. The \Gmemastikan bahwa kami tidak melewati posisi apa pun - khususnya, dengan cara ini kami harus berhenti di umpan baris, sehingga kami tidak mendapatkan kecocokan tambahan dari , sehingga semua substring yang memulai lebih jauh langsung dari posisi saat ini, jadi membuang itu bukan masalah (dan sebenarnya meningkatkan kinerja).B dirinya sendiri. Alasan ini tidak mengacaukan segalanya sebenarnya cukup halus: karena jika ada posisi awal di Amana kita tidak dapat menemukan substring yang valid, maka itu juga merupakan kegagalan yang akan menyebabkan\G berhenti memeriksa setiap posisi lebih lanjut. Namun, jika (dari posisi awal saat ini) semua substring muncul diB

Karena M!konfigurasi, semua pertandingan ini akan dikembalikan dari panggung, bergabung dengan umpan garis.

O$#`.+
$.&

Ini memilah garis dari hasil sebelumnya dengan panjang. Ini dilakukan dengan mencocokkan baris dengan .+. Kemudian $mengaktifkan bentuk "sort-by", sehingga pertandingan diganti dengan $.&untuk menentukan urutan sortir. Itu $.&sendiri menggantikan pertandingan dengan panjangnya. Akhirnya, #opsi memberi tahu Retina untuk mengurutkan secara numerik (jika tidak, itu akan memperlakukan angka yang dihasilkan sebagai string dan mengurutkannya secara leksikografis).

G1`

Akhirnya, kami hanya menyimpan baris pertama, dengan menggunakan tahap grep dengan regex kosong (yang selalu cocok) dan batas 1.


1

Perl, 87 85

sub{(grep{$_[1]!~/\Q$_/}map{$}=$_;map{substr($_[0],$_,$})}@}}(@}=0..length$_[0]))[0]}

Ini adalah fungsi anonim yang mengembalikan pertama (berdasarkan posisi) dari substring terpendek $_[0]yang tidak terjadi di $_[1], atau undefjika tidak ada substring seperti itu ada.

Program pengujian dengan string yang diambil dari jawaban @ iAmMortos, diuji dengan Perl 5.22.1:

#!/usr/bin/perl -l
use strict;
use warnings;

my $f = <see above>;
print $f->('abcd', 'abc');
print $f->('abcd', 'dabc');
print $f->('abcd', 'dcbabbccd');
print $f->('abcdf', 'abcdebcdf');
print $f->('abc', 'abc');

1

Haskell, 72 byte

import Data.Lists
a#b=argmin length[x|x<-powerslice a,not$isInfixOf x b]

Contoh penggunaan: "abcd" # "dabc"-> "cd".

Implementasi langsung: bangun semua substring adan pertahankan yang tidak muncul b. argminmengembalikan elemen daftar yang meminimalkan fungsi mengingat argumen ke-2, di sini:length .


Saya tidak tahu tentang argmin! Tampaknya sangat bermanfaat.
Zgarb

0

Pyth - 9 6 byte

h-Fm.:

Cobalah online di sini .


Dicoret 9 masih 9
kucing

Saya ingin tahu cara kerjanya.
mroman

@mroman.: dengan satu arg adalah semua substr. Jadi saya memetakan itu di kedua string, lalu lipat setwise diff, jadi saya memiliki semua substrs pertama yang bukan yang kedua, kemudian saya memilih yang pertama, yang terkecil cuz.: Diurutkan.
Maltysen

0

C #, 152 byte

string f(string a,string b){int x=a.Length;for(int i=1;i<=x;i++)for(int j=0;j<=x-i;j++){var y=a.Substring(j,i);if(!b.Contains(y))return y;}return null;}

0

Ruby, 70 byte

Mengumpulkan semua substring dengan panjang tertentu dari string pertama, dan jika ada yang tidak ada di string kedua, kembalikan.

->a,b{r=p;(1..l=a.size).map{|i|(0...l).map{|j|b[s=a[j,i]]?0:r||=s}};r}

0

Burlesque - 26 byte

Saat ini cara terpendek yang bisa saya lakukan adalah:

lnp^sujbcjz[{^p~[n!}f[-][~

0

Japt , 14 byte

Êõ!ãU c k!èV g

Cobalah online!

Kembali undefinedjika tidak ada substring yang valid . Ini berbeda dari mengembalikan string "tidak terdefinisi" , meskipun perbedaannya hanya terlihat karena flag -Q.

Penjelasan:

Ê                 :Length of the first input
 õ                :For each number in the range [1...length]:
  !ãU             : Get the substrings of the first input with that length
      c           :Flatten to a single array with shorter substrings first
        k         :Remove ones which return non-zero to:
         !èV      : Number of times that substring appears in second input
             g    :Return the shortest remaining substring

0

Japt -h, 11 byte

à f@øX «VøX

Cobalah

                :Implicit input of strings U & V
à               :All combinations of U
  f@            :Filter each as X
    øX          :  Does U contain X?
       «        :  Logical AND with the negation of
        VøX     :  Does V contain X?
                :Implicit output of last element
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.