วิธีที่เป็นไปได้ทั้งหมดในการสอดแทรกสองสตริง


21

ฉันเพิ่งเห็นคำถามนี้ใน stackoverflow มันเป็นคำถามที่ยอดเยี่ยม แต่มีปัญหาหนึ่งที่ทำให้เกิดปัญหาร้ายแรงได้ พวกเขากำลังขอวิธีที่ดีที่สุดที่จะทำ เช่นง่ายที่สุดในการอ่านสำนวนที่ประณีตที่สุด ฯลฯ พวกเขาไม่รู้หรอกว่าเรื่องอะไรสำคัญ คุณควรถามว่าจะทำอย่างไรกับโค้ดที่น้อยที่สุด!

เนื่องจากฉันสงสัยว่าคำถามจะได้รับการชื่นชมใน stackoverflow ฉันจึงตัดสินใจถามที่นี่

ความท้าทาย

คุณต้องเขียนโปรแกรมหรือฟังก์ชั่นที่สั้นที่สุดที่สร้างวิธีที่เป็นไปได้ทั้งหมดเพื่อสอดแทรกสตริงใดก็ได้สองอัน ตัวอย่างเช่นถ้าทั้งสองสตริงเป็น'ab'และ'cd'ผลลัพธ์คือ:

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

ในขณะที่คุณสามารถมองเห็นaอยู่เสมอก่อนbและอยู่เสมอก่อนcd

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 ไม่ใช่ python) อย่างไรก็ตามคำตอบในภาษาใดก็ได้รับการสนับสนุน


5
ไบต์ของรหัสน้อยที่สุดเป็นวิธีที่ดีที่สุดที่จะทำทุกคนรู้ว่า! * (ข้อจำกัดความรับผิดชอบ: ไม่ใช่ CR)
Rɪᴋᴇʀ

1
ตัวละครทุกตัวแตกต่างกันหรือไม่? หรือไม่จำเป็น?
aditsu

4
จริงๆแล้ว ... ในตัวอย่าง "code" ของคุณ "golf" คุณมีซ้ำ "o" และผลลัพธ์ซ้ำซ้อนเช่น 'gcoodelf' ฉันจะถือว่านั่นคือสิ่งที่คุณต้องการ
aditsu

1
"ฉันเพิ่งพบคำถามที่ยอดเยี่ยมนี้อย่างไรก็ตามมีข้อบกพร่องร้ายแรงอย่างหนึ่ง: พวกเขาต้องการให้ทำได้ดี!"
Cyoce

1
คุณควรให้ตัวอย่าง IO สำหรับ "aabb", "bc"
Taemyr

คำตอบ:


1

Pyth, 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

Haskell, 53 48 ไบต์

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

กำหนดฟังก์ชั่น%ที่a%bมีสตริงa,bให้รายการของสตริง

รับสองสายเราเลือกหนึ่งในสองสายเพื่อรับตัวละครตัวแรกจาก จากนั้นเราจะย่อส่วนที่เหลือของสองสตริงโดยเตรียมอักขระนั้นให้กับแต่ละผลลัพธ์

เมื่อสตริงใดสตริงหนึ่งว่างเปล่าผลลัพธ์ที่เป็นไปได้คือสตริงอื่นเท่านั้น ""%""=[""]จะพอเพียง แต่มันอีกต่อไป


53 ไบต์:

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

กำหนดฟังก์ชั่น%ที่a%dมีสตริงa,dให้รายการของสตริง

ฟังก์ชั่นถูกกำหนดซ้ำ หากเราใช้อักขระจากสตริงแรกมันจะต้องมีผลต่อการเรียกซ้ำแบบซ้ำในส่วนที่เหลือของสตริงแรกด้วยสตริงที่สอง สมมาตรสำหรับสตริงอื่น

สำหรับกรณีพื้นฐานหากสตริงใดสตริงหนึ่งว่างเปล่าผลลัพธ์จะเป็นรายการองค์ประกอบเดียวของการต่อข้อมูล นี่คือสั้นกว่าสองกรณีสำหรับแต่ละสายจะว่างเปล่า


@aditsu ""%""=[""]โอ๊ะฉันหมายถึง
xnor

มันแปลกที่จะมีคำตอบที่ชนะคุณโดยหนึ่งไบต์ในภาษาเดียวกันทั้งหมด
ภูมิใจ haskeller

10

Haskell, 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

Python 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และย่อหน้ามันแต่ละผลมาจากการโทร recursive 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

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

ขอบคุณ Sp3000 สำหรับการกิน 4 ไบต์ :)


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

JavaScript (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 ไบต์โดยปรับปรุงเงื่อนไขการยกเลิกของฉัน บันทึกแล้ว 3 ไบต์ขอบคุณ @ edc65


ใกล้เกินไปที่จะเผยแพร่ แต่ให้ดู - สั้นกว่า: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 ซ้ำกันที่มีตัวอักษรที่ใช้ร่วมกันผมยังไม่ได้รับการดูแลใด ๆ เพื่อหลีกเลี่ยงพวกเขา แต่นี้สร้างจำนวนมากที่ซ้ำกันมากขึ้นและไม่ได้เป็นเพียงที่มีตัวอักษรที่ใช้ร่วมกัน (หากไม่ได้รับอนุญาต แต่ไม่จำเป็นต้องใช้ตัวอักษรที่ซ้ำกันเพียงเพิ่มสามไบต์เพื่อตัด{}ᵘเป็นเอาต์พุตโดยไม่มีรายการซ้ำกัน)

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.

โดยพื้นฐานแล้วสิ่งนี้จะสร้างพาร์ติชันของสตริงทั้งสองจากนั้นแทรกอินเทอร์เฟซเหล่านั้นในรูปแบบที่กำหนดขึ้นตามปกติตามลำดับ interleavings ที่ซ้ำกันพิเศษเกิดจากคู่ของพาร์ติชันที่ความแตกต่างระหว่างความยาวของแรกและความยาวของที่สองมีค่าบางอย่างที่นอกเหนือจาก 0 หรือ 1 ดังนั้นหนึ่งในนั้นมีชิ้นที่ได้รับการต่อกันในตอนท้าย ดังนั้นในการผลิตเอาต์พุตที่มีหลายหลากเช่นเดียวกับตัวอย่างผลลัพธ์:

Brachylogขนาด 17 ไบต์

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

ลองออนไลน์!

รหัสพิเศษ{lᵐ-ℕ<2&}, ล้มเหลวคู่พาร์ทิชันใด ๆ ที่มีการแบ่งส่วนภายนอกใด ๆ (ฉันเปลี่ยนส่วนหัวของ TIO เพื่อพิมพ์ด้วยเครื่องหมายคำพูดเพื่อการตรวจสอบผลลัพธ์ที่ง่ายขึ้นใน Python shell)


1

MATL , 34 30 ไบต์

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

สิ่งนี้ใช้แนวคิดจากคำตอบนี้ : หากความยาวของสตริงเป็นmและnระบุm+nรูปแบบบิตทั้งหมดด้วยmชุดบิต วิธีการหนึ่งที่จะทำอย่างนั้นการแจงนับที่: สร้างพีชคณิตทั้งหมดของเวกเตอร์ที่มีmคนและnศูนย์แล้วลบที่ซ้ำกัน

ลองออนไลน์!

คำอธิบาย

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 ไบต์

ฟังก์ชันเรียกซ้ำที่ส่งคืน[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

แบตช์154 152 ไบต์

@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.