İki diziyi araya sokmanın tüm olası yolları


21

Geçenlerde stackoverflow'ta bu soruyu gördüm . Bu harika bir soru, ancak soruda ölümcül bir sorun var. Bunu yapmanın en iyi yolunu istiyorlar. Örneğin, okunması en kolay, en salak, en temiz vb. Önemli değil ki bilmiyorlar mı? En az baytlık kodla nasıl yapacağınızı sormanız gerekiyor!

Bu sorunun stackoverflow'ta beğenileceğinden şüphelendiğimden, burada sormaya karar verdim.

Meydan okuma

İki rastgele dizgiyi bir araya getirmek için mümkün olan tüm yolları oluşturan en kısa programı veya işlevi yazmalısınız. Örneğin, iki dize 'ab've 'cd'çıktı ise:

['abcd', 'acbd', 'acdb', 'cabd', 'cadb', 'cdab']

Gördüğünüz gibi a, her zaman önce bve cher zaman önce d.

GÇ makul bir biçimde olabilir. Çıktınızı kontrol edip etmediğinizi doğrulamak için bu python kodunu kullanın. (kredi: JeD )

def shuffle(s,t):
    if s=="":
        return [t]
    elif t=="":
        return [s]
    else:
        leftShuffle=[s[0]+val for val in shuffle(s[1:],t)]
        rightShuffle=[t[0]+val for val in shuffle(s,t[1:])]
        leftShuffle.extend(rightShuffle)
        return leftShuffle

Örnek io:

shuffle("$", "1234"):
['$1234', '1$234', '12$34', '123$4', '1234$']

shuffle("az", "by"):
['azby', 'abzy', 'abyz', 'bazy', 'bayz', 'byaz']

shuffle("code", "golf"):
['codegolf', 'codgeolf', 'codgoelf', 'codgolef', 'codgolfe', 'cogdeolf', 'cogdoelf',
'cogdolef', 'cogdolfe', 'cogodelf', 'cogodlef', 'cogodlfe', 'cogoldef', 'cogoldfe',
'cogolfde', 'cgodeolf', 'cgodoelf', 'cgodolef', 'cgodolfe', 'cgoodelf', 'cgoodlef',
'cgoodlfe', 'cgooldef', 'cgooldfe', 'cgoolfde', 'cgoodelf', 'cgoodlef', 'cgoodlfe',
'cgooldef', 'cgooldfe', 'cgoolfde', 'cgolodef', 'cgolodfe', 'cgolofde', 'cgolfode',
'gcodeolf', 'gcodoelf', 'gcodolef', 'gcodolfe', 'gcoodelf', 'gcoodlef', 'gcoodlfe',
'gcooldef', 'gcooldfe', 'gcoolfde', 'gcoodelf', 'gcoodlef', 'gcoodlfe', 'gcooldef',
'gcooldfe', 'gcoolfde', 'gcolodef', 'gcolodfe', 'gcolofde', 'gcolfode', 'gocodelf',
'gocodlef', 'gocodlfe', 'gocoldef', 'gocoldfe', 'gocolfde', 'goclodef', 'goclodfe',
'goclofde', 'goclfode', 'golcodef', 'golcodfe', 'golcofde', 'golcfode', 'golfcode']

Her zaman olduğu gibi standart boşluklar uygulanır ve bayt cinsinden en kısa cevap kazanır. Asıl soru python ile ilgili olduğundan, en kısa python cevabını görmeyi çok isterim. (Ve hayır, pyth python değildir). Ancak, herhangi bir dilde cevaplar teşvik edilmektedir.


5
Kod Fewest bayt olduğunu her biri bilir ki, bunu yapmak için bestest yolu * (uyarı: değil CR)!.
Rɪᴋᴇʀ

1
Tüm karakterler ayrı mı? Ya da mutlaka değil?
aditsu

4
Aslında ... "kod" unuzda, "golf" örneğinizde yinelenen bir "o" ve yinelenen sonuçlar da var, örneğin 'gcoodelf'. Sanırım istediğin bu.
aditsu

1
“Ben sadece bu harika soruyu buldum. Ancak, ölümcül bir kusur var: iyi yapılmasını istiyorlar!”
Cyoce

1
"Aabb", "bc" için IO örneğini sağlamalısınız.
Taemyr

Yanıtlar:


1

Pyth, 26

M?G?H++LhGgtGH+LhHgGtH]G]H

Burada dene

Bu verilen özyinelemeli formülün çok temel bir uygulamasıdır. gGerekli görevi gerçekleştiren bir işlevi tanımlar . Bağlantı, daha uygun olması için dizeleri ayrı ayrı STDIN yeni satırından okuyan değiştirilmiş bir programdır. Fonksiyonu çağırmak için yapın g<string1><string2>.

Genişleme:

M                ##  Define a function g taking two arguments: G and H
 ?G?H ... ]G]H   ##  Two ternaries: if G is empty return a list containing H
                 ##  if H is empty return a list containing G
   +             ##  otherwise return these next two lists joined together
   +LhGgtGH      ##  the first letter of G added to each result of a recursive call to g
                 ##  with G missing its first character and H
   +LhHgGtH      ##  the same as above but with G and H swapped

İki özyinelemeli arama çok benzer, ancak onları daha fazla golf oynamak için bir yol bulamadım.


10

Haskell, 53 48 bayt

a%""=[a]
a%b=[x:t|(x:y,z)<-[(a,b),(b,a)],t<-y%z]

Dizelerin %hangi a%bdizelerin a,blistesini verebileceği bir işlev tanımlar .

İki dize verildiğinde, ilk karakteri almak için ikisinden birini seçiyoruz. Daha sonra iki dizinin geri kalanını tekrarlar ve her karakteri bu karakteri hazırlar.

Dize biri boş olduğunda, olası tek sonuç diğer dizedir. ""%""=[""]ayrıca yeterli olurdu, ama daha uzun.


53 bayt:

a@(b:c)%d@(e:f)=((b:)<$>c%d)++((e:)<$>a%f)
a%d=[a++d]

Dizelerin %hangi a%ddizelerin a,dlistesini verebileceği bir işlev tanımlar .

İşlev özyinelemeli olarak tanımlanmıştır. İlk dizgiden bir karakter alırsak, ikinci dizginin kalan ilk dizgisinde kalan özyinelemeli çağrının her sonucuna hazırlanmalıdır. Diğer dize için simetrik olarak.

Temel durumda, dizelerden biri boşsa, sonuç birleştirmelerinin tek öğeli bir listesidir. Bu, her dize boş olması için iki harften kısadır.


@aditsu Oops, demek istedim ""%""=[""].
xnor

Aynı dilden tam olarak bir byte ile sizi kazanan bir cevabınız olması çok garip
gururlu haskeller

10

Haskell, 47

(x:s)#b=(x:)<$>s%b
a#b=[]
[]%b=[b]
a%b=a#b++b#a

% bu sorunu çözen operatör.

#iki listede yer alan ve ilk karakterin ilk dizgiden (bir kenarlı harfle - ilk liste boşsa, o zaman sonuç boş bir listedir) olduğu şekilde araya sokmanın tüm yollarını bulan bir operatördür. %.

sonra, %sadece #iki kez uygulayarak çalışır .

Düzenleme: Önceki sürümde ""%""geri dönen bir hata vardı ["",""], ben de düzelttim. Bir taban çantasının eklenmesiyle sabitlendi %, daha sonra aynı uzunluktaki bir taban çantasının çıkarılmasını sağladı #(ki bu gerçekten pek anlamlı değildi).


@nimi Ama türler mismach - (#) :: [a]->[a]->[[a]], bu yüzden a::[a]sonuç tür olmalıdır[[a]]
gururlu haskeller

Oops, haklısın. Üzgünüm.
nimi

8

Python 2, 71 bayt

f=lambda*p:[x[0]+t for x,y in p,p[::-1]for t in x and f(x[1:],y)]or['']

Örnek çalışma:

>> f('ab','AB')
['abAB', 'aABb', 'aAbB', 'ABab', 'AabB', 'AaBb']

İki x,ykarakter verildiğinde ilk karakterini alabilir xve özyinelemeli çağrının eksik olduğu her sonucuna hazırlayabiliriz f(x[1:],y). Ya da aynısını xve yanahtarla yapabiliriz. x,yGirdi pveya tersini `p [:: - 1] olarak alarak , her iki olasılığı da elde ederiz.

Boş bir dize almaktan kaçınmak için xmantıksal kısa devre yapıyoruz x and. Her iki dizi de boşsa, ikisi de olamaz xve ordoğru taban durumuna göre belirlediğimiz olasılıkların listesini boşaltırız [''].

Python 3'te (73 bytes) benzer bir üretken strateji:

f=lambda p,s='':[f((x[1:],y),s+x[0])for x,y in[p,p[::-1]]if x]or print(s)

Bu ne tür bir büyü?! (+1)
aditsu

3

Python, 80

İstenildiği gibi, burada bir python cevabı:

f=lambda a,b,c='':[c+x for x in[a+b][a>''<b:]or f(a[1:],b,a[0])+f(a,b[1:],b[0])]

4 bayt yediğiniz için teşekkürler Sp3000 :)


2

CJam, 38

q~L{_2$e&{_2$(\@jf+@@(@@jf++}{+a}?}2jp

Çevrimiçi deneyin

Dinamik programlama (notlu özyineleme kullanarak).

Açıklama:

q~         read and evaluate the input (2 strings)
L{…}2j     calculate with memoized recursion with no initial cache and 2 arguments
  _2$      copy the 2 strings
  e&{…}    if they are both non-empty
    _2$    copy the strings again (they're in reverse order)
    (      take out the first character of the first string
    \@     move the strings after the character
    j      solve recursively
    f+     prepend the character to all results
    @@     bring the other copy of the strings on top (in order)
    (      take out the first character of the second string
    @@     move the strings after the character
    j      solve recursively
    f+     prepend the character to all results
    +      concatenate the 2 sets of results
  {…}      else
    +      concatenate the 2 strings (at least one is empty)
    a      put the result in an array
  ?        end if
p          pretty-print the results for the input strings

2

CJam, 32 bayt

qN/_:,eeWf%e~e!\f{\{_2$=(ot}/No}

Burada test et.

Bu gerçekten golf oynayabiliyor ama şu ana kadar hepsinde aynı byte sayısına sahip 4 alternatif çözüm buldum:

qN/_ee{),*~}%e!\f{\{_2$=(ot}/No}
l_:!l_0f>@+])e!\f{\{_2$=(ot}/No}
ll__3$:!+.=])e!\f{\{_2$=(ot}/No}
qN/[_:,2,]ze~e!\f{\{_2$=(ot}/No} (found by Sp3000)

Temel fikir, sonuçta her karakterin alınacağı dizgeye karşılık gelen 0s ve 1s'nin tüm permütasyonlarını oluşturmaktır . Bu dahil ve dahil her şey e!. Geri kalan kısım, karakterleri iki sıradaki karakterlerden o sırada çeker.


Güzel, bu fikri düşündüm ama o kadar iyi golf oynayabileceğini sanmıyordum.
aditsu

@aditsu Gerçekten ihtiyacımız olan, her bir elemanı farklı miktarlarda tekrarlayan e*ve arasında bir karışım .*. ;) (Yapacak bir operatör var :a.*:~. Sanırım e*şu anda iki liste verildiyse hata yaptığından dolayı kullanılabilir.)
Martin Ender

2

JavaScript (Firefox 30-57), 88 84 81 bayt

(s,t,g=(v,w)=>v[1]?f(v.slice(1),w).map(x=>v[0]+x):[v+w])=>[...g(s,t),...g(t,s)]

Düzenleme: Fesih koşulumu iyileştirerek 4 bayt kurtardı. @ Edc65 sayesinde 3 bayt kurtarıldı.


Yayımlamak için çok yakın, ancak bir göz atın - daha kısa:f=(a,b,z=(v,w)=>v[1]?f(v.slice(1),w).map(x=>v[0]+x):[v+w])=>z(a,b).concat(z(b,a))
edc65

@ edc65 Çok hoş; vDurum olarak kullanmaya çalıştım ve kullanamadım , ama kullanmak için hiçbir zaman aklıma gelmedi v[1].
Neil

2

Brachylog , 8 bayt

p~cᵐz₁cc

Çevrimiçi deneyin!

Girdiyi girdi değişkeni üzerinden iki dizgenin listesi olarak alır ve çıktı değişkeni aracılığıyla olası tüm serpiştirmeleri oluşturur . Test durumları, paylaşılan mektupların olduğu yerde yinelenen birleştirmelere izin veriyor gibi göründüğü için, onlardan kaçınmak için herhangi bir özen göstermedim, ancak bu sadece paylaşılan mektuplarla değil , çok daha fazla sayıda yinelemeye neden oluyor. (Buna izin verilmezse, ancak paylaşılan harf çiftleri gerekli değilse, {}ᵘçıktısını yinelemesiz bir liste olarak eklemek için üç bayt ekleyin .)

p           A permutation of
            the input variable
   ᵐ        with each element
 ~c         arbitrarily partitioned,
    z       zipped
     ₁      without cycling,
      cc    and concatenated twice
            is the output variable.

Temel olarak, bu her iki dizenin her bölümünü oluşturur, daha sonra onları normal deterministik tarzda her iki sırada araya sokar. Ekstra yinelenen harmanlamalar, birincinin uzunluğu ile ikincinin uzunluğu arasındaki farkın, 0 veya 1'den başka bir değere sahip olduğu, böylelikle birinin sonunda birbiriyle birleşen parçalara sahip olduğu bölüm çiftlerinden kaynaklanmaktadır. Bu nedenle, örnek çıktıyla aynı çokluğa sahip çıktı üretmek için:

Brachylog , 17 bayt

p~cᵐ{lᵐ-ℕ<2&}z₁cc

Çevrimiçi deneyin!

Ekstra kod, {lᵐ-ℕ<2&}herhangi bir yabancı bölümün yapıldığı bölüm çiftlerinde başarısız olur. (Python kabuğunda daha kolay çıktı kontrolü için alıntılarla yazdırmak üzere TIO'daki başlığı değiştirdim.)


1

Matl , 34 , 30 bayt

h1Mgw~hY@Xu!ttYs*w~tYs1Gn+*+!)

Bu, bu cevabın bir fikrini kullanır : eğer dizelerin uzunlukları mve ntüm m+nbit desenlerini mbitler ile numaralandırıyorsa . Bunun bir yolu, bu numaralandırmayı yapmaktır: Bir vektörün tüm permütasyonlarını mbirler ve nsıfırlarla oluşturmak ve sonra kopyaları kaldırmak.

Çevrimiçi deneyin!

açıklama

h     % implicitly input the two strings of lengths m and n. Concatenate
1M    % push the two strings again
g     % convert the second strings into ones
w~    % swap. Convert the second string into zeros
h     % concatenate: vector of zeros and ones
Y@    % 2D array with all permutations of that vector, each on a row
Xu    % remove duplicate rows
!     % transpose
ttYs  % duplicate twice. Cumulative sum along each column
*     % element-wise product. Produces, in each column, indices for
      % elements of the first string; 1, 2,...,m. The rest are 0
w~    % swap, negate
tYs   % duplicate. Cumulative sum along each column
1Gn+  % add length of first input
*     % element-wise product. Produces, in each column, indices for
      % elements of the second string: m+1,...,m+n. The rest are 0
+     % add. This gives indices into the concatenated string created initially
!     % transpose back
)     % index into concatenated string. Implicitly display

0

Ruby, 83 bayt

[a+b]Bu dizelerden herhangi biri boşsa döndürülen özyinelemeli bir işlev . Aksi takdirde, a[0] + every string in v[a[1..-1],b]bir dize listesine eklenen dizelerin bir listesini döndürür.b[0] + every string in v[a,b[1..-1]]

v=->a,b{a[0]&&b[0]?v[a[1..-1],b].map{|i|a[0]+i}+v[a,b[1..-1]].map{|i|b[0]+i}:[a+b]}

0

Toplu, 154 152 bayt

@if "%~1%~2"=="" echo %3
@set t=%~1
@if not "%t%"=="" call %0 "%t:~1%" "%~2" %3%t:~,1%
@set t=%~2
@if not "%t%"=="" call %0 "%~1" "%t:~1%" %3%t:~,1%
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.