Tất cả các cách có thể để xen kẽ hai chuỗi


21

Gần đây tôi đã thấy câu hỏi này trên stackoverflow. Đó là một câu hỏi hay, nhưng có một vấn đề nghiêm trọng với câu hỏi. Họ đang yêu cầu cách tốt nhất để làm điều đó. Ví dụ, dễ đọc nhất, thành ngữ nhất, gọn gàng nhất v.v ... Họ không biết đó không phải là vấn đề? Bạn phải hỏi về cách thực hiện với ít byte mã nhất!

Vì tôi nghi ngờ câu hỏi đó sẽ được đánh giá cao trên stackoverflow, tôi quyết định hỏi nó ở đây.

Các thách thức

Bạn phải viết chương trình hoặc hàm ngắn nhất có thể tạo ra tất cả các cách có thể để xen kẽ bất kỳ hai chuỗi tùy ý. Ví dụ: nếu hai chuỗi là 'ab''cd', đầu ra là:

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

Như bạn có thể thấy, aluôn luôn là trước bcluôn luôn là trước d.

IO có thể ở bất kỳ định dạng hợp lý. Sử dụng mã python này để xác minh để kiểm tra đầu ra của bạn. (tín dụng: 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

Mẫu 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']

Như thường lệ, các sơ hở tiêu chuẩn được áp dụng và câu trả lời ngắn nhất tính theo byte sẽ thắng. Vì câu hỏi ban đầu là về con trăn, tôi rất muốn xem câu trả lời ngắn nhất về con trăn. (Và không, pyth không phải là trăn). Tuy nhiên, câu trả lời trong bất kỳ ngôn ngữ được khuyến khích.


5
Ít byte mã nhất cách tốt nhất để làm điều đó, mọi người đều biết điều đó! * (Từ chối trách nhiệm: không phải CR).
R

1
Có phải tất cả các nhân vật đều khác biệt? Hay không nhất thiết?
aditsu

4
Trên thực tế ... trong ví dụ "mã", "golf" của bạn, bạn cũng có một "o" trùng lặp và kết quả trùng lặp, ví dụ: 'gcoodelf'. Tôi sẽ cho rằng đó là những gì bạn muốn.
aditsu

1
"Tôi vừa tìm thấy câu hỏi tuyệt vời này. Tuy nhiên, có một lỗ hổng chết người: họ muốn nó được thực hiện tốt!"
Cyoce 30/03/2016

1
Bạn nên cung cấp IO mẫu cho "aabb", "bc".
Taemyr 30/03/2016

Câu trả lời:


1

Bình thường, 26

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

Hãy thử nó ở đây

Đây là một triển khai rất cơ bản của công thức đệ quy đã cho. Nó định nghĩa một chức năng gthực hiện các nhiệm vụ cần thiết. Liên kết là một chương trình được sửa đổi để đọc các chuỗi từ dòng mới STDIN được phân tách, để thuận tiện hơn. Để gọi hàm làm g<string1><string2>.

Sự bành trướng:

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

Hai cuộc gọi đệ quy rất giống nhau, nhưng tôi không thể tìm ra cách nào để đánh gôn chúng nữa.


10

Haskell, 53 48 byte

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

Xác định một hàm %a%bvới các chuỗi a,bcung cấp một danh sách các chuỗi.

Cho hai chuỗi, chúng tôi chọn một trong hai để lấy ký tự đầu tiên. Sau đó, chúng tôi lặp lại phần còn lại của hai chuỗi, thêm ký tự đó vào từng kết quả.

Khi một trong các chuỗi trống, kết quả duy nhất có thể là chuỗi khác. ""%""=[""]cũng sẽ đủ, nhưng nó dài hơn.


53 byte:

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

Xác định một hàm %a%dvới các chuỗi a,dcung cấp một danh sách các chuỗi.

Hàm được định nghĩa đệ quy. Nếu chúng ta lấy một ký tự từ chuỗi thứ nhất, thì nó phải được thêm vào mỗi kết quả của lệnh gọi đệ quy trên phần còn lại của chuỗi thứ nhất với chuỗi thứ hai. Đối xứng cho chuỗi khác.

Đối với trường hợp cơ sở, nếu một trong các chuỗi trống, kết quả là một danh sách thành phần đơn của phép nối của chúng. Điều này ngắn hơn hai trường hợp cho mỗi chuỗi trống.


@aditsu Rất tiếc, ý tôi là ""%""=[""].
xnor

Thật kỳ lạ khi có một câu trả lời chiến thắng bạn bằng chính xác một byte trong cùng một ngôn ngữ
tự hào

10

Haskell, 47

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

% là nhà điều hành giải quyết thách thức này.

#là một toán tử có hai danh sách và tìm tất cả các cách để xen kẽ chúng sao cho ký tự đầu tiên là từ chuỗi đầu tiên (với trường hợp cạnh - nếu danh sách đầu tiên trống, thì kết quả là một danh sách trống) bằng cách đệ quy %.

Sau đó, %hoạt động bằng cách chỉ cần áp dụng #hai lần.

Chỉnh sửa: Phiên bản trước có lỗi trong đó đã ""%""trả về ["",""], vì vậy tôi đã sửa nó. Nó đã được sửa bằng cách thêm trường hợp cơ sở vào %, sau đó cho phép loại bỏ trường hợp cơ sở có cùng độ dài từ #(điều này thực sự không có ý nghĩa nhiều).


@nimi Nhưng các loại không phù hợp - (#) :: [a]->[a]->[[a]], a::[a]và vì vậy , kết quả phải là loại[[a]]
tự hào

Rất tiếc, bạn đã đúng. Lấy làm tiếc.
nimi

8

Python 2, 71 byte

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

Chạy ví dụ:

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

Cho hai chuỗi, x,ychúng ta có thể lấy ký tự đầu tiên xvà thêm nó vào từng kết quả của cuộc gọi đệ quy bị thiếu f(x[1:],y). Hoặc, chúng ta có thể làm tương tự với xychuyển đổi. Bằng cách lấy x,yđầu vào phoặc đảo ngược `p [:: - 1], chúng ta có được cả hai khả năng.

Để tránh lấy từ một chuỗi trống x, chúng tôi logic ngắn mạch với x and. Nếu cả hai chuỗi đều trống, không có chuỗi nào có thể xvà chúng ta có được và danh sách các khả năng trống, mà chúng ta sửa với ortrường hợp cơ sở chính xác [''].

Một chiến lược tổng quát tương tự trong Python 3 (73 byte):

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

Những loại ma thuật này là?! (+1)
aditsu

3

Con trăn, 80

Theo yêu cầu, đây là một câu trả lời python:

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

Cảm ơn Sp3000 vì đã ăn 4 byte :)


2

CJam, 38

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

Dùng thử trực tuyến

Lập trình động (sử dụng đệ quy ghi nhớ).

Giải trình:

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 byte

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

Kiểm tra nó ở đây.

Cảm giác này thực sự có thể chơi được, nhưng cho đến nay tôi chỉ tìm thấy 4 giải pháp thay thế mà tất cả đều có cùng số byte:

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)

Ý tưởng cơ bản là tạo ra tất cả các hoán vị của 0s và 1s tương ứng với chuỗi nào sẽ lấy mỗi ký tự trong kết quả từ đó. Đó là tất cả mọi thứ lên đến và bao gồm cả e!. Phần còn lại chỉ đơn giản là kéo ra các ký tự theo thứ tự đó từ hai chuỗi sau đó.


Thật tuyệt, tôi đã nghĩ về ý tưởng đó nhưng không nghĩ rằng nó có thể chơi golf tốt như vậy.
aditsu

@aditsu Điều chúng ta thực sự cần là sự pha trộn giữa e*.*lặp lại mỗi yếu tố theo một lượng khác nhau. ;) (Tức là một nhà điều hành phải làm :a.*:~. Tôi cho rằng e*có thể được sử dụng cho việc đó vì hiện tại nó có lỗi nếu được đưa ra hai danh sách.)
Martin Ender

2

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

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

Chỉnh sửa: Đã lưu 4 byte bằng cách cải thiện điều kiện chấm dứt của tôi. Đã lưu 3 byte nhờ @ edc65.


Quá gần để xuất bản, nhưng hãy xem - nó ngắn hơn: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 Rất đẹp; Tôi đã thử và không sử dụng vnhư điều kiện, nhưng nó không bao giờ xảy ra với tôi để sử dụng v[1].
Neil

2

Brachylog , 8 byte

p~cᵐz₁cc

Hãy thử trực tuyến!

Lấy đầu vào dưới dạng danh sách hai chuỗi thông qua biến đầu vào và tạo ra tất cả các xen kẽ có thể thông qua biến đầu ra. Vì các trường hợp thử nghiệm dường như cho phép xen kẽ trùng lặp ở những nơi có thư chung, tôi không cẩn thận tránh chúng, nhưng điều này tạo ra nhiều bản sao hơn và không chỉ với các thư được chia sẻ. (Nếu điều này không được phép, nhưng trùng lặp chữ cái chung là không cần thiết, chỉ cần thêm ba byte để bọc {}ᵘcho đầu ra dưới dạng danh sách không có bản sao.)

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.

Về cơ bản, điều này tạo ra mọi phân vùng của cả hai chuỗi, sau đó xen kẽ chúng theo kiểu xác định thông thường theo một trong hai thứ tự. Sự xen kẽ trùng lặp bổ sung là do các cặp phân vùng trong đó sự khác biệt giữa chiều dài của cái thứ nhất và chiều dài của cái thứ hai có một số giá trị khác 0 hoặc 1, do đó, một trong số chúng có các đoạn được nối với nhau ở cuối. Vì vậy, để tạo ra đầu ra có cùng bội số với đầu ra mẫu:

Brachylog , 17 byte

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

Hãy thử trực tuyến!

Mã bổ sung {lᵐ-ℕ<2&}, không thành công bất kỳ cặp phân vùng nào trong đó bất kỳ phân chia ngoại lai nào được thực hiện. (Tôi đã thay đổi tiêu đề trên TIO để in bằng dấu ngoặc kép để kiểm tra đầu ra dễ dàng hơn trong trình bao Python.)


1

MATL , 34 30 byte

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

Điều này sử dụng một ý tưởng từ câu trả lời này : nếu chiều dài của các chuỗi là mn, liệt kê tất cả m+ncác mẫu mbit với các bit được đặt. Một cách làm điều đó liệt kê đó là: tạo ra tất cả các hoán vị của một vector với mnhững người thân và nsố không và sau đó loại bỏ các bản sao.

Hãy thử trực tuyến!

Giải trình

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 byte

Hàm đệ quy trả về [a+b]nếu một trong hai chuỗi đó trống. Mặt khác, nó trả về một danh sách các chuỗi a[0] + every string in v[a[1..-1],b]được thêm vào danh sách các chuỗib[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

Hàng loạt, 154 152 byte

@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%
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.