두 줄을 인터리빙하는 모든 가능한 방법


21

최근 에 stackoverflow 에서이 질문을 보았습니다 . 좋은 질문이지만 그 질문에는 한 가지 치명적인 문제가 있습니다. 그들은 최선의 방법을 요구하고 있습니다. 예를 들어, 가장 읽기 쉽고, 가장 관용적이며, 가장 까다 롭지 않습니다. 가장 적은 바이트의 코드로 어떻게해야하는지 물어봐야합니다!

stackoverflow에 대한 질문에 감사 할 것이므로 여기에서 질문하기로 결정했습니다.

도전

임의의 두 문자열을 인터리브하는 가능한 모든 방법을 생성하는 가능한 가장 짧은 프로그램 또는 함수를 작성해야합니다. 예를 들어 두 문자열이 'ab'and 'cd'인 경우 출력은 다음과 같습니다.

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

당신이 볼 수 있듯이, a항상 이전이다 b, 그리고 c항상 전에이다 d.

IO는 합리적인 형식 일 수 있습니다. 이 파이썬 코드를 사용하여 출력을 확인하십시오. (신용 : 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

샘플 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']

평소와 같이 표준 허점이 적용되고 바이트 단위의 최단 답변이 이깁니다. 질문은 원래 파이썬에 관한 것이기 때문에 가장 짧은 파이썬 답변을보고 싶습니다. (아니요, pyth는 파이썬이 아닙니다). 그러나 모든 언어로 답변을 권장합니다.


5
코드의 가장 적은 바이트 가 그것을 수행하는 가장 좋은 방법 이며 , 누구나 알고 있습니다! * (면책 조항 : CR 아님).
Rɪᴋᴇʀ

1
모든 문자가 고유합니까? 아니면 꼭 그렇지 않습니까?
aditsu

4
실제로 "code", "golf"예제에서 중복 "o"와 중복 결과도 있습니다 (예 : 'gcoodelf'). 나는 그것이 당신이 원하는 것이라고 가정합니다.
aditsu

1
"방금이 위대한 질문을 찾았습니다. 그러나 한 가지 치명적인 결함이 있습니다.
Cyoce

1
"aabb", "bc"에 대한 샘플 IO를 제공해야합니다.
Taemyr

답변:


1

피스, 26

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

여기 사용해보십시오

이것은 주어진 재귀 공식의 매우 기본적인 구현입니다. g필요한 작업을 수행 하는 기능 을 정의합니다 . 링크는 STDIN 줄 바꿈에서 분리 된 문자열을보다 편리하게 읽는 수정 된 프로그램입니다. 함수를 호출하려면을 수행하십시오 g<string1><string2>.

확장:

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

두 재귀 호출은 매우 비슷하지만 더 이상 골프를 칠 수있는 방법을 찾지 못했습니다.


10

하스켈, 53 48 바이트

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

문자열을 사용하여 문자열 목록을 제공 하는 함수 %를 정의합니다 .a%ba,b

두 개의 문자열이 주어지면 첫 번째 문자를 가져올 두 문자열 중 하나를 선택합니다. 그런 다음 나머지 두 문자열을 반복하여 해당 문자를 각 결과 앞에 붙입니다.

문자열 중 하나가 비어 있으면 가능한 유일한 결과는 다른 문자열입니다. ""%""=[""]충분하지만 더 길다.


53 바이트 :

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

문자열을 사용하여 문자열 목록을 제공 하는 함수 %를 정의합니다 .a%da,d

이 함수는 재귀 적으로 정의됩니다. 첫 번째 문자열에서 문자를 가져 오면 나머지 첫 번째 문자열에서 두 번째 문자열로 재귀 호출의 각 결과 앞에 추가해야합니다. 다른 문자열에 대해 대칭 적으로.

기본 경우, 문자열 중 하나가 비어 있으면 결과는 단일 요소의 연결 목록입니다. 이것은 각 문자열이 비어있는 경우보다 두 경우보다 짧습니다.


@aditsu 죄송합니다 ""%""=[""].
xnor

그것은 동일한 언어로 정확히 1 바이트 너희를이기는 답변 가지고 이상해
자랑 haskeller

10

하스켈, 47

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

% 이 도전을 해결하는 연산자입니다.

#는 두 개의 목록을 가져 와서 첫 번째 문자가 첫 번째 문자열 (가장자리 경우-첫 번째 목록이 비어 있으면 결과는 빈 목록 임)에서 오는 것처럼 인터리브하는 모든 방법을 찾는 연산자입니다. %.

그런 다음 두 번 %적용하면 #됩니다.

편집 : 이전 버전에는 버그가 ""%""반환 ["",""]되어 수정했습니다. 에 기본 사례를 추가하여 수정 한 %다음 동일한 길이의 기본 사례를 제거 할 수있었습니다 #(실제로 의미가 없었습니다).


@nimi 그러나 유형 mismach - (#) :: [a]->[a]->[[a]], 그래서 a::[a]그 결과는 유형을 사용해야합니다[[a]]
자랑 haskeller

죄송합니다. 죄송합니다.
nimi

8

파이썬 2, 71 바이트

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

예제 실행 :

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

두 개의 문자열이 주어지면 x,y첫 번째 문자를 가져 와서 x재귀 호출의 각 결과 앞에 누락 할 수 f(x[1:],y)있습니다. 또는 동일한 작업을 수행 x하고 y전환 할 수 있습니다 . x,y입력 p또는 반전`p [::-1] 을 취함으로써 , 우리는 두 가지 가능성을 얻습니다.

빈 문자열을 사용하지 않으려면로 x논리적 인 단락을 x and합니다. 두 문자열이 모두 비어 있으면 문자열이 될 수 없으며 x가능성의 목록을 가져 와서 or올바른 기본 사례로 수정합니다 [''].

Python 3의 유사한 생성 전략 (73 바이트) :

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

어떤 종류의 마법입니까?! (+1)
aditsu

3

파이썬, 80

요청에 따라 다음은 파이썬 답변입니다.

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 바이트를 먹어 주셔서 감사합니다 Sp3000 :)


2

CJam, 38

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

온라인으로 사용해보십시오

동적 프로그래밍 (메모 화 된 재귀 사용)

설명:

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 바이트

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

여기에서 테스트하십시오.

이것은 정말 골프처럼 느껴지지만 지금까지는 모두 동일한 바이트 수를 갖는 4 가지 대안 솔루션을 찾았습니다.

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)

기본 아이디어는 결과에서 각 문자를 가져올 문자열에 해당하는 0s 및 1s 의 모든 순열을 생성 하는 것입니다. 를 포함하여 모든 것을 포함합니다 e!. 나머지는 단순히 두 문자열에서 순서대로 문자를 가져옵니다.


좋아, 나는 그 아이디어에 대해 생각했지만 그것이 골프를 잘 할 수 있다고 생각하지 않았다.
aditsu

@aditsu 실제로 필요한 것은 각 요소를 다른 양으로 반복하는 요소 e*.*요소를 혼합하는 것 입니다. ;) (즉, 운영자 :a.*:~입니다. e*두 개의 목록이 주어지면 현재 오류가 있기 때문에 사용할 수 있다고 생각 합니다.)
Martin Ender

2

자바 스크립트 (Firefox 30-57), 88 84 81 바이트

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

편집 : 종료 조건을 개선하여 4 바이트를 절약했습니다. @ edc65 덕분에 3 바이트가 절약되었습니다.


출판하기에는 너무 가까워 보이지만 짧습니다.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 아주 좋은; v조건 으로 사용하지 못했지만 사용하지 못했습니다 v[1].
Neil

2

Brachylog , 8 바이트

p~cᵐz₁cc

온라인으로 사용해보십시오!

입력 변수를 통해 입력을 두 문자열의 목록으로 취하고 출력 변수를 통해 가능한 모든 인터리빙을 생성 합니다. 테스트 케이스는 문자가 공유되는 중복 interleavings을 허용하는 것 때문에, 내가 그들을 피하기 위해 어떤 처리되지 않은, 그러나 이것은 생성 훨씬 더 중복뿐 아니라 공유 문자로합니다. (허용되지 않지만 공유 문자 복제본이 필요하지 않은 경우, 중복되지 않은 {}ᵘ목록으로 출력 할 수 있도록 3 바이트 만 추가 하면됩니다.)

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.

본질적으로 이것은 두 문자열의 모든 파티션을 생성 한 다음 정상적인 순서 결정 방식으로 인터리브합니다. 여분의 중복 인터리빙은 첫 번째 길이와 두 번째 길이 사이의 차이가 0 또는 1 이외의 값을 갖는 파티션 쌍으로 인해 발생하므로 그중 하나는 청크가 서로 끝에 연결됩니다. 따라서 샘플 출력과 동일한 다중성을 갖는 출력을 생성하려면 다음을 수행하십시오.

Brachylog , 17 바이트

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

온라인으로 사용해보십시오!

추가 코드 () {lᵐ-ℕ<2&}는 불필요한 분할이 이루어진 파티션 쌍에 실패합니다. (파이썬 쉘에서 더 쉬운 출력 확인을 위해 따옴표로 인쇄하도록 TIO의 헤더를 변경했습니다.)


1

MATL , 34 30 바이트

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

이것은에서 아이디어 사용 이 답변 : 문자열의 거리에서는 쉴드가있는 경우 mn, 모든 열거 m+n와 비트 패턴을 m설정 비트. 이 열거를 수행하는 한 가지 방법은 m1과 n0 으로 벡터의 모든 순열을 생성 한 다음 중복을 제거 하는 것 입니다.

온라인으로 사용해보십시오!

설명

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

루비, 83 바이트

[a+b]해당 문자열 중 하나가 비어 있으면 반환하는 재귀 함수입니다 . 그렇지 않으면 문자열 목록에 a[0] + every string in v[a[1..-1],b]추가 된 문자열 목록을 반환 합니다.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

배치, 154152 바이트

@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%
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.