ทำให้จูบงูยืด


57

งูยืดมีลักษณะบางอย่างเช่นนี้

<||=|||:)~

แต่ละลำดับของแถบแนวตั้ง ( |) ในงูที่ยืดออกซึ่งรู้จักกันในชื่อส่วนยืดนั้นสามารถขยายความกว้างเป็นสองเท่าแยกจากกันและถูกวาดด้วยเครื่องหมายสแลช ( /, \) เมื่อขยายออก

งูข้างต้นโดยเฉพาะมีสองส่วนที่ยืดได้ทำให้มีสี่ท่าที่เป็นไปได้:

<||=|||:)~

</\/\=|||:)~

<||=/\/\/\:)~

</\/\=/\/\/\:)~

รูปแบบทั่วไปของงูถ่างในท่ายืดน้อยที่สุดถูกกำหนดโดยregex นี้ :

<(\|+=)*\|+:\)~

ซึ่งสามารถระบุไว้ในคำว่า:

<ตามด้วยหมายเลขของลำดับใด ๆ|'s เข้าร่วมกับอาการตามมาด้วย=:)~

ดังนั้น<|:)~และ<||:)~และ<|=|:)~และ<|=|=||=|||||=||:)~เป็นงูยืด แต่<=:)~และ<=|:)~และ<||=:)~และ<|==||:)~ไม่ใช่

~(:|||=||>งูยืดยังสามารถเผชิญซ้ายแทนขวาเช่น แบบฟอร์มเหมือนกันเพียงมิร์เรอร์

ท้าทาย

เขียนโปรแกรมที่ใช้ในสตริงบรรทัดเดียวของงูยืดสองตัวที่หันเข้าหากันโดยมีช่องว่างจำนวนหนึ่งอยู่ระหว่างนั้น งูทั้งสองจะอยู่ในท่ายืดน้อยที่สุด (แถบแนวตั้งทั้งหมดไม่มีสแลช) สตริงจะเริ่มต้นด้วยหางของงูที่หันไปทางขวาและจบลงด้วยหางของงูที่หันไปทางซ้าย

ตัวอย่างเช่นต่อไปนี้เป็นข้อมูลป้อนเข้าที่มีห้าช่องว่างระหว่างงู:

<|=||:)~.....~(:||||>

ฉันกำลังใช้เครื่องหมายจุด ( .) แทนอักขระช่องว่างจริงเพื่อความชัดเจน

ช่องว่างระหว่างงูยังเป็นอินพุตที่ถูกต้อง:

<|=||:)~~(:||||>

เราพูดว่างูกำลังจูบกันเมื่อลิ้นของพวกมันสัมผัสเช่นนี้

โปรแกรมของคุณต้องการที่จะขยายการรวมกันของส่วนขยายของทั้งสองของงูเช่นงูบางอย่างที่มีจำนวนน้อยที่สุดของช่องว่างระหว่างพวกเขาไปได้ (โดยไม่ทับซ้อนกัน) เช่นดังกล่าวว่างูมีความใกล้เคียงกับการจูบที่เป็นไปได้

หางทั้งสองของงูนั้นได้รับการแก้ไข แต่หัวและลำตัวของมันสามารถเคลื่อนที่ได้ - เหมาะสำหรับงูที่หันไปทางขวา, ซ้ายสำหรับงูที่หันไปทางซ้าย - ตามสิ่งที่ยืดออกไป

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


ตัวอย่างเช่นผลลัพธ์สำหรับ<|=||:)~.....~(:||||>(จากด้านบน) จะเป็น:

</\=||:)~~(:/\/\/\/\>

นี่เป็นทางออกเดียวที่นี่เพราะเมื่อรวมกับส่วนที่ยืดออกอื่น ๆ แล้วงูจะทับซ้อนกันหรืออยู่ห่างจากการจูบมากขึ้น


หากมีหลายวิธีที่เป็นไปได้ผลลัพธ์อาจเป็นหนึ่งในนั้น

ตัวอย่างเช่นถ้าอินพุตเป็น

<|=||:)~.....~(:|||=|>

ผลลัพธ์อาจเป็น

<|=/\/\:)~~(:/\/\/\=|>

หรือ

</\=||:)~~(:/\/\/\=/\>

โปรดจำไว้ว่ามันเป็นไปไม่ได้เสมอที่จะทำให้งูจูบ แต่คุณยังคงต้องเข้าใกล้พวกเขาให้มากที่สุด

ตัวอย่างเช่นถ้าอินพุตเป็น

<||=||||:)~...~(:||>

ผลลัพธ์อาจเป็น

</\/\=||||:)~.~(:||>

หรือ

<||=||||:)~.~(:/\/\>

หากงูกำลังจูบกันอยู่เอาต์พุตจะเหมือนกับอินพุต เช่น

<|=||:)~~(:||||>

โดยทั่วไปเอาต์พุตจะเหมือนกับอินพุตหากส่วนขยายของส่วนที่ยืดใด ๆ จะทำให้งูทับซ้อนกัน เช่น

<|||=|||:)~..~(:||||=|||||=||||||>

หมายเหตุ

  • รับอินพุตจาก stdin หรือบรรทัดคำสั่งตามปกติหรือเขียนฟังก์ชันที่รับสตริง พิมพ์หรือส่งคืนผลลัพธ์
  • คุณสามารถใช้.เครื่องหมายมหัพภาค ( ) ในอินพุตและเอาต์พุตแทนช่องว่าง ( ) ได้หากต้องการ
  • เป็นสิ่งสำคัญที่จะทับสลับกันตามลำดับของแถบแนวตั้งที่ถูกแทนที่ คำสั่งของพวกเขาในงูใหญ่หรือว่าการเฉือนไปข้างหน้าหรือข้างหลังมาก่อนไม่สำคัญ
  • ส่วนที่ยืดไม่สามารถขยายออกไปได้ครึ่งทาง - เป็นสองเท่าหรือไม่มีส่วนขยายเลย

เกณฑ์การให้คะแนน

นี่คือรหัสกอล์ฟ การส่งที่สั้นที่สุดในหน่วยไบต์ชนะ Tiebreaker เป็นคำตอบก่อนหน้า


17
Snex Education 101 - วิธีการจูบอย่างถูกต้อง
เครื่องมือเพิ่มประสิทธิภาพ

45
"เราพูดว่างูกำลังจูบกันเมื่อภาษาของพวกเขาสัมผัสเช่นนี้" ฉันกำลังอ่านอะไรอยู่ ...
เสียชีวิต

8
ดังนั้นงูจึงมี แต่ฝรั่งเศสเท่านั้น
เครื่องมือเพิ่มประสิทธิภาพ

3
@ PeterTaylor Well, "mirrored", ไม่ใช่ "reversed" ( >ไม่<เช่นนั้นจะไม่เหมือนกัน, สำหรับ(และ)) แต่เขายังกล่าวว่า "มันสำคัญมากที่เครื่องหมายทับจะสลับกันตามลำดับของแถบแนวตั้งที่แทนที่ งูที่มีขนาดใหญ่หรือว่าไปข้างหน้าหรือข้างหลังเฉือนมาก่อนไม่สำคัญ "
Martin Ender

7
@qwr จินตนาการ
งานอดิเรกของ Calvin

คำตอบ:


9

CJam, 87 71 70 68 ไบต์

l:L"|"f&Qa%_,Y\m*\f{.{_,"/\\"*?}L'|%.\s" /"1$fe=:-\a+}${0a>}=~S%\S**

ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

l:L        e# Read a line from STDIN and save it in L.
"|"f&      e# Intersect each character with the string "|".
           e# This pushes either "|" or "".
Qa%        e# Split the resulting array at runs of "".
_,         e# Compute the length of the resulting array (A).
           e# This yield K, the number of stretchy parts.
Y\m*       e# Push the array of all vectores in {0,1}^K.
\f{        e# For each vector V in {0,1}^K, push V and A; then:
  .{       e#   For each C in V and the corresponding P in A:
    _,     e#     Compute the length of the stretchy part P.
    "/\\"* e#     Repeat "/\" that many times.
    ?      e#     If C, select P; else, select "/\"*length(P).
  }        e#   This modifies A.
  L'|%     e#   Split L at runs of vertical lines.
  .\s      e#   Interleave the chunks of L and the modified A. Sringify.
           e#   In each iteration, this constructs a different modification of L,
           e#   with some stretched out stretchy parts.
  " /"1$   e#   Push " /" and a copy of the modified L.
  fe=      e#   Calculate the number of spaces and slashes in the modifed L.
  :-       e#   Subtract the number of occurrences.
  \a+      e#   Construct the array [difference modified-L].
}          e#
$          e# Sort the array (by final number of spaces).
{0a>}=     e# Find the first element greater than [0].
           e# This skips over too far stretched snakes, where the number of
           e# slashes is less than the number of spaces.
~          e# Dump the difference (D) and modified L on the stack.
S%         e# Split L at runs of spaces.
\S*        e# Construct a string of D spaces.
*          e# Join the split L, delimiting by D spaces.

19

Retina , 209 107 99 97 92 ไบต์

.(?=(.+)(?<=(?=<((\|+|(?<-5>\|(?=\1())?)+)[^|]+)+$(?(5)!)).+( )+\S+))\4
/ \
+` (.*~|~.*) 
$1

สำหรับวัตถุประสงค์ในการนับแต่ละบรรทัดไปในไฟล์แยกต่างหาก แต่คุณสามารถเรียกใช้รหัสจากไฟล์เดียวด้วยการ-sตั้งค่าสถานะ

นำคุณสมบัติที่ดีที่สุดของ. NET regex และ Retina มารวมกัน: ปรับสมดุลกลุ่มค้นหาความยาวตามอำเภอใจและเปลี่ยนทดแทน regex ซ้ำ ๆ

โดยพื้นฐานแล้ว regex แบบยาวจะเข้ารหัสโซลูชันที่ถูกต้องและเครื่องมือแบ็คเกอร์ของ regex จะค้นหาหนึ่งในตัวเลือกที่ดีที่สุดสำหรับฉัน

คำอธิบาย

ก่อนอื่นมาพิจารณาวิธีที่เราสามารถหาวิธีการแก้ปัญหาที่ถูกต้อง (ไม่จำเป็นต้องสร้างผลลัพธ์ที่ถูกต้อง) ด้วย regex เราสามารถใช้กลุ่มที่สมดุลของ. NET เพื่อช่วยให้เรานับส่วนที่ยืดออก พิจารณา regex ที่ง่ายกว่าต่อไปนี้:

\S+( )+.+(?<=(?(1)!)^([^|]+(\|+|(?<-1>\|)*))+>)

เราสามารถกำจัดมันได้

\S+( )+.+

สิ่งนี้ตรงกับสตริงทั้งหมดผลักดันการจับภาพหนึ่งไปยังกลุ่ม1สแต็คสำหรับแต่ละพื้นที่ในการป้อนข้อมูล เราจะใช้สแต็กนั้นเพื่อให้แน่ใจว่าส่วนที่ยืดออกนั้นเติมเต็มพื้นที่ที่จับไว้ในกลุ่มเหล่านั้นอย่างแน่นอน

ถัดไปคือ lookbehind สิ่งที่จับได้คือ lookbehinds ถูกจับคู่จากขวาไปซ้ายใน. NET (ดังนั้นคุณควรอ่านมัน) สิ่งนี้ทำให้เรามีโอกาสสำรวจสายอักขระเป็นครั้งที่สองโดยพิจารณาว่ามีส่วนย่อยของส่วนที่ยืดซึ่งรวมกับจำนวนของช่องว่างที่ตรงกัน การมองผ่านจากขวาไปซ้าย:

>

นี่เป็นเพียงการรับรองว่าเราจริง ๆ เริ่มจากจุดสิ้นสุดของสตริง (หางงู)

(
  [^|]+
  (
    \|+
  |
    (?<-1>\|)+
  )
)+

สำหรับแต่ละส่วนที่ยืดออกนี่ก็แค่จับคู่ส่วนทั้งหมดโดยไม่ทำอะไรเลย ( \|+) หรือตรงกับส่วนทั้งหมดในขณะที่ popping จับภาพออกจากสแต็ก1( (?<-1>\|)*) |/\|มีการสลับกันเพื่อให้แน่ใจว่าเราสามารถเพียงอย่างเต็มที่ขยายส่วนยืดหรือปล่อยให้มันไม่เปลี่ยนแปลงและไม่ได้รับสิ่งที่ชอบ [^|]+จากนั้นเราก็ย้ายไปเป็นส่วนหนึ่งยืดถัดไปด้วย

(?(1)!)^

ในที่สุดเรามั่นใจว่าเราได้สำรวจสตริงทั้งหมด (ทั้งงู) และสแต็ก1นั้นว่างเปล่าอย่างสมบูรณ์ นั่นคือเราได้พบส่วนย่อยของส่วนที่ยืดซึ่งรวมกับจำนวนช่องว่างที่เราจับได้ก่อนหน้านี้

ตัวย้อนรอยจะย้อนกลับไปเรื่อย ๆ ผ่านสายอักขระที่พยายามรวมกันของส่วนที่ไม่เปลี่ยนแปลงและขยายจนกระทั่งแก้ปัญหาผลรวมย่อยได้ หากเซตย่อยดังกล่าวไม่มีอยู่ lookbehind จะล้มเหลว สิ่งนี้จะทำให้ผู้ย้อนรอยกลับไปที่\S+( )+.+ส่วนและลองจับหนึ่งช่องว่างให้น้อยลงด้วย( )+(ซึ่งจะครอบคลุมโดย.+แทนที่) เนื่องจากความโลภของ+เราจึงพยายามเติมช่องว่างให้มากที่สุด

คุณสามารถตรวจสอบความถูกต้องของวิธีการนี้ได้ด้วยการทดแทนที่ถูกแก้ไขเล็กน้อยนี้:

\S+(( )+).+(?<=(?(2)!)^([^|]+(\|+|(?<-2>\|)*))+>)
=$1=

ซึ่งจะทำให้คุณมีสตริงที่=spaces=มีจำนวนช่องว่างที่สามารถเติมเต็มด้วยงูที่กำหนด

ฉันต้องเพิ่มกลอุบายเพิ่มเติมเพื่อขยาย|s ที่ถูกต้อง โดยพื้นฐานแล้วฉันต้องการแทนที่ทั้งหมด|ที่จับคู่โดยใช้(?<-1>\|)+สาขา ความคิดคือการจับคู่ตัวละครแต่ละตัวใส่ตัวแก้ปัญหาในการค้นหาและตั้งค่าสถานะหากการแข่งขันเกิดขึ้นภายในสาขานั้น หากไม่ได้ตั้งค่าสถานะนั้นเราจะยกเลิกการจับคู่ในตอนท้ายเพื่อหลีกเลี่ยงการแทนที่อักขระอื่น ๆ

ในการทำเช่นนี้เราใช้การค้นหาหลายระดับ อีกครั้ง lookbehinds ความยาวผันแปรได้ของ. NET จะถูกจับคู่จากขวาไปซ้ายดังนั้นหากเราซ้อน lookaheads และ lookbehinds เราสามารถปล่อยให้โปรแกรม regex สำรวจสตริงได้หลายครั้ง สำหรับเหตุผลในการเล่นกอล์ฟตัวแก้กลับด้านในโซลูชันจริงของฉัน (เริ่มต้นที่ท้ายยกช่องว่างจากขวาไปซ้ายจากนั้นแก้ไขผลรวมย่อยจากซ้ายไปขวา) แต่ไม่เช่นนั้นโครงสร้างของตัวแก้จะเหมือนกันทุกประการ . เรามาตัด Regex แบบเต็ม:

.(?=(.+)...)

เราจับคู่อักขระเดี่ยวจากนั้นจับส่วนที่เหลือของสตริงและย้ายเคอร์เซอร์ไปที่ส่วนท้ายของสตริง เราจะใช้กลุ่มนี้ใน1ภายหลังเพื่อตรวจสอบตัวแก้ไขว่าเราอยู่ในตำแหน่งการแข่งขันหรือไม่

(?<=....+( )+\S+)

นี่เป็นเหมือนส่วนแรกของตัวแก้ไขอย่างง่ายด้านบนยกเว้นว่าเราจะเลือกช่องว่างจากขวาไปซ้าย การย้อนรอยของจำนวนช่องว่างทำงานเหมือนกับก่อนหน้ายกเว้นว่าเรากำลังใช้กลุ่ม5ตอนนี้

(?=<((\|+|(?<-5>\|(?=\1())?)+)[^|]+)+$(?(5)!))

นี่เป็นเหมือนก่อนหน้ายกเว้นว่าเราจะไปจากซ้ายไปขวาและเมื่อใดก็ตามที่เราจับคู่ a |ในสาขาขยายเราตรวจสอบว่ามันตรงกับที่ถูกต้องหรือไม่

(?=\1())?

นี่คือ lookahead ที่เป็นตัวเลือก มันพยายามที่จะจับคู่กลุ่ม1อีกครั้ง (ซึ่งที่นี่เป็นไปได้ก็ต่อเมื่อเราตรงกับตัวละครที่ถูกจับคู่) และถ้าเราทำเราจับสตริงว่างเข้าไปในกลุ่ม4ซึ่งบ่งชี้ว่าเราพบตัวละครปัจจุบันในหนึ่งเดียว ของบิตที่ขยาย หาก\1ไม่ตรงกัน4จะไม่จับอะไรเลยและ?ให้แน่ใจว่า lookahead ที่ล้มเหลวจะไม่ส่งผลกระทบต่อตัวแก้ปัญหาเลย

ในที่สุดหลังจากแก้ปัญหาทั้งหมดเสร็จแล้วเราเพียงตรวจสอบ\4ว่าใช้ lookahead นี้หรือไม่ /\ถ้าเป็นเช่นนั้นเราต้องการที่จะเข้ามาแทนที่ตัวอักษรในปัจจุบันมี

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

+` (.*~|~.*) 
$1

6

ทับทิม191 187 186 170 162

->t{s=r=t.size
i=m=t[o=/ +/].size
(0...2**t.scan(y=/\|+/).size).map{|n|q=-1
x=t.gsub(y){|r|n[q+=1]<1?r:'\/'*r.size}
d=i+s-x.size
d<0||d<m&&r=x.gsub(o,' '*m=d)}
r}

นี่คือฟังก์ชันที่รับสตริงเป็นพารามิเตอร์และส่งคืนสตริง

การทดสอบออนไลน์: http://ideone.com/uhdfXt

นี่คือรุ่นที่อ่านได้:

# enumerates the possible states for any string containing snakes
COMBINATIONS =-> snake {
  expandable_fragments = snake.scan /(\|+)/

  (0...2**(expandable_fragments.size)).map{ |i|
    x=-1
    snake.gsub(/\|+/){|r| i[x+=1]>0 ? '\/'*r.size : r}
  }
}

# finds the configuration in which snakes are closest to each other
KISS=
-> input {
  result = input
  s = input.size
  initial_distance = min_distance = input[/ +/].size

  COMBINATIONS[input].map{|c|
    distance = initial_distance + s - c.size
    if distance > -1 && distance < min_distance
      min_distance = distance
      result = c.gsub(/ +/,' '*distance)
    end
  }

  result
}

ในเวอร์ชั่น golfed ฟังก์ชั่นหลักจะเทียบเท่ากับKISSฟังก์ชั่นด้านบนและCOMBINATIONSฟังก์ชั่นได้รับการ inlined


ล้มเหลวในอินพุต<|=||:)~~(:||||>ซึ่งข้อมูลจำเพาะระบุว่าเป็นอินพุตที่ถูกต้อง
หมึกมูลค่า

6

Python ขนาด 205 ไบต์

from itertools import*
f=lambda s:min([c.replace(".","",c.count("X"))for c in map("".join,product(*map({"|":"|X"}.get,s,s)))if{c.count("X")>c.count("."),"|X"in c,"X|"in c}=={0}],key=len).replace("X","/\\")

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

นี่คือแรงเดรัจฉานที่เรียบง่ายเหนือการแทนที่ที่เป็นไปได้ทั้งหมด|ด้วยการ/\กรองการกำหนดค่าที่ไม่ถูกต้อง เพียงบิตเรียบร้อยผมคิดว่าคือการที่เราไม่จริงแทนที่|ด้วย/\โดยตรง - ครั้งแรกที่เราเข้ามาแทนที่|ด้วยXและวาง.จากกลางสำหรับทุกการเปลี่ยนใช้สตริงยาวขั้นต่ำมากกว่าสตริงที่ถูกต้องทั้งหมดแล้วแทนที่XS /\กับ

ฉันลองใช้วิธีอื่น ๆ ไม่กี่วิธีรวมถึงวิธีแบบเรียกซ้ำ แต่พวกเขาก็ดูยุ่งเหยิง ฉันยังได้เรียนรู้ว่าre.splitในปัจจุบันไม่ได้แยกสายว่างเปล่าซึ่งเป็นโชคร้ายเพราะหนึ่งในความคิดของฉันเกี่ยวข้องกับการแยก\bขอบเขตของคำ


5

Mathematica, 381 ไบต์

StringReplace[MapAt[StringReplace[#,"|"->"/\\"]&,StringSplit[#<>"="<>#2,"="],#3]~StringRiffle~"=",")="->")~"<>If[#4>0,"."~StringRepeat~#4,""]<>"~"]&[#1,#3,Sequence@@Function[{l,s},{#,#2-Total@Extract[l,#]}&[Flatten[l~Position~#~Take~#2&@@@Tally@#&@@Select[Subsets@l,Total@#<=s&]~MaximalBy~Total,1],s]][StringLength/@StringCases[#1<>#3,"|"..],StringLength@#2]]&@@#~StringSplit~"~"&

ฟังก์ชัน Pure รับสตริงเป็นอาร์กิวเมนต์ คาดหวัง.มากกว่าระหว่างงู

ฉันไม่คิดว่ามันจะแย่ขนาดนี้ ... นี่คือสิ่งที่ฉันมีก่อนที่ฉันจะทุบมันด้วยกันและติดทุกอย่างไว้

f[lhs_, rhs_, 
  spaces_] := {StringLength /@ StringCases[lhs <> rhs, "|" ..], 
  StringLength@spaces}

g[barLens_, 
   spaceLen_] := {#, #2 - Total@Extract[barLens, #]} & @@ {Flatten[
     Take[Position[barLens, #], #2] & @@@ 
      Tally[First[
        MaximalBy[Select[Subsets[barLens], Total@# <= spaceLen &], 
         Total]]], 1], spaceLen};

h[lhs_, rhs_, partspec_, newSpaceLen_] := 
 StringReplace[
  StringRiffle[
   MapAt[StringReplace[#, "|" -> "/\\"] &, 
    StringSplit[lhs <> "=" <> rhs, "="], partspec], "="], 
  ")=" -> ")~" <> 
    If[newSpaceLen > 0, StringRepeat[".", newSpaceLen], ""] <> "~"]

 h[#1, #3, Sequence @@ g @@ f[#1, #3, #2]] & @@ 
     StringSplit[#, "~"] &

นี่คือตัวอย่างการเรียกใช้พร้อมคำอธิบาย:

Input: "<|=||:)~.....~(:||||>"
@Call StringSplit[#, "~"] &, yielding  {"<|=||:)", ".....", "(:||||>"}
@@Apply h[#1, #3, Sequence @@ g @@ f[#1, #3, #2]] &, but first
Set arguments: h["<|=||:)", "(:||||>", Sequence @@ g @@ f["<|=||:)", "(:||||>", "....."]]
@Call f, yielding {{1, 2, 4}, 5} = {# of bars in each segment, # of spaces}
@@Apply g, let's trace from the interior:
Subsets[barLens] = all subsets of {1, 2, 4}
Select those subsets whose sum is less than # of spaces {{},{1},{2},{4},{1,2},{1,4}}
MaximalBy Total, yielding a list of all subsets whose sum is maximal {{1, 4}}
First of these subsets, can be any of them {1, 4}
Tally the subset, yielding frequencies of each {{1, 1}, {4, 1}}
@@@Apply Take[Position[barLens, #], #2] & at the first level, yielding
    {Take[Position[{1, 2, 4}, 1], 1], Take[Position[{1, 2, 4}, 4, 1]]}
    which takes the first 1 positions of 1 and the first 1 positions of 4, yielding
    {{{1}},{{3}}}
Flatten at the first level, yielding {{1}, {3}}
Create a list {{{1}, {3}}, 5}
@@Apply {#, #2 - Total@Extract[barLens, #]} &, inserting arguments:
    {{{1}, {3}}, 5 - Total@Extract[{1, 2, 4}, {{1}, {3}}]} = {{{1}, {3}}, 0}
    where the second element becomes the # of spaces left over.
Done with g, it returned {{{1}, {3}}, 0}
@@Apply Sequence, splicing the return of g into h, yielding the
@Call, h["<|=||:)", "(:||||>", {{1}, {3}}, 0]; let's start from the interior
StringSplit the concatenated "<|=||:)=(:||||>" with delimiter "=", {"<|","||:)","(:||||>"}
MapAt the part specification {{1}, {3}} and StringReplace at those indices any | with /\
    yielding {"</\","||:)","(:/\/\/\/\>"}
StringRiffle together, inserting back the delimiter "=", yielding "</\=||:)=(:/\/\/\/\>"
StringReplace ")=" with ")~", concat the new number of spaces, concat "~"
Yields "</\=||:)~~(:/\/\/\/\>", done.

ลดลงได้อย่างง่ายดายเป็น 355 โดยเริ่มต้นด้วยa=StringReplace;b=StringSplit;c=StringLength;d=Total;แล้วแทนสิ่งที่ต้องการในที่อื่นภายใน:a=StringReplace;b=StringSplit;c=StringLength;d=Total;a[MapAt[a[#,"|"->"/\\"]&,b[#<>"="<>#2,"="],#3]~StringRiffle~"=",")="->")~"<>If[#4>0,"."~StringRepeat~#4,""]<>"~"]&[#1,#3,Sequence@@Function[{l,s},{#,#2-d@Extract[l,#]}&[Flatten[l~Position~#~Take~#2&@@@Tally@#&@@Select[Subsets@l,d@#<=s&]~MaximalBy~d,1],s]][c/@StringCases[#1<>#3,"|"..],c@#2]]&@@#~b~"~"&
Alex Meiburg

3

Prolog (ECLiPSe), 438 ไบต์

คำตอบอื่น ๆ ของฉันคือการแก้ปัญหาที่ผิดพลาด (ขอโทษสำหรับเสียง) นี่คือความพยายามใน Prolog ซึ่งเคารพกฎทั้งหมด

:-lib(fd).
a([],[]).
a([H|T],L):-append(H,X,L),a(T,X).
s(E,Z,X,Y,L):-length(E,L),a([[60],M,[58,41,126],T,[126,40,58],W,[62]],E),checklist(=(32),T),length(T,Z),b(M,X-[]),b(W,Y-[]).
b(I,[K:M|R]-E):-(I:K=[47,92|L]:s;I:K=[124|L]:n),M#=N+1,N#>=0,b(L,[K:N|R]-E).
b([61|L],[_:0|R]-E):-b(L,R-E).
b([],[_:0|E]-E).
d(_:N,Y:N):-Y=s;Y=n.
s(W,P):-string_list(W,E),s(E,_,X,Y,L),minimize((maplist(d,X,U),maplist(d,Y,V),s(K,Q,U,V,L)),Q),string_list(P,K).

การทดสอบ

(รูปแบบ: อินพุต, เอาต์พุต, บรรทัดใหม่)

<===:)~         ~(:>
<===:)~         ~(:>

<|||:)~         ~(:||||=|>
</\/\/\:)~ ~(:/\/\/\/\=/\>

<=|=:)~         ~(:||||=|>
<=/\=:)~   ~(:/\/\/\/\=/\>

<===|:)~         ~(:||=|>
<===/\:)~     ~(:/\/\=/\>

<|=|=|||=|:)~         ~(:=|>
</\=/\=/\/\/\=/\:)~  ~(:=/\>

<||||||:)~         ~(:=|>
</\/\/\/\/\/\:)~  ~(:=/\>

<||||||:)~         ~(:||>
</\/\/\/\/\/\:)~ ~(:/\/\>

<||=||||:)~ ~(:||>
<||=||||:)~ ~(:||>

<||=||||:)~   ~(:||>
</\/\=||||:)~ ~(:||>

<||=||||:)~    ~(:||>
</\/\=||||:)~~(:/\/\>

<||=||||:)~~(:||>
<||=||||:)~~(:||>

คำอธิบาย

  • เพรดิเคตหลักคือs/2ซึ่งรับอินพุตเป็นอาร์กิวเมนต์แรกและแยกผลลัพธ์ด้วยอาร์กิวเมนต์ที่สอง (ทั้งสองสตริง) อินพุตถูกแปลงเป็นรายการของรหัสอักขระ, E.

  • จากนั้นs(E,Z,X,Y,L)ทำลายรายการลงในองค์ประกอบต่อไปนี้:

    • Z จำนวนช่องว่างระหว่างงู
    • XและYตัวแทนนามธรรมของร่างกายด้านซ้ายและขวา

      รูปแบบของเนื้อความคือรายการn:Nหรือs:Nนิพจน์โดยที่Nความยาวเป็นบวก nวิธีการnormalและวิธีการsstretched

    • L ความยาวทั้งหมดของรายการ

สิ่งที่น่าสนใจs/5คือมันไปได้สองทางคือเราสามารถสร้างงูได้หากมีข้อโต้แย้งอื่น ๆ

    s(E,5,[n:3],[s:2,n:7,s:1],_),string_list(S,E).

... unifies `S` with `"<|||:)~     ~(:/\\/\\=|||||||=/\\>"` (backslashes are quoted). This is due to how `b/2` is written, which can parse the character list or generate it.
  • เราสร้างตัววัตถุด้านซ้ายและขวาที่ปรับเปลี่ยนซึ่งแต่ละส่วนเป็นแบบปกติหรือแบบยืดในขณะที่ลดพื้นที่Qที่แยกงูตัวใหม่ ความยาวทั้งหมดของสตริงที่คำนวณถูก จำกัด ขอบเขตเพื่อให้การค้นหาสิ้นสุดลง

1

Python 2.7.3 427 421 400 371 ไบต์

import re,itertools as K
g,o,k='\|+',len,raw_input()
d=k.count(' ')
if d==0:exit(k)
p,x,y,s=re.sub,0,0,map(o,re.findall(g,k))
for e in [A for w in range(o(s)+1)for A in K.combinations(s,w)]:
 v=sum(e)
 if v==d or x<v<d:x,y=v,list(e)
print p(" +",' '*(d-x),p(g,lambda m:('/\\'*o(m.group(0))if y.remove(o(m.group(0)))or True else 1)if o(m.group(0))in y else m.group(0),k))

รหัสที่ไม่ใช่กอล์ฟที่นี่ -

#!/usr/bin/env python
import sys
import re

def find_dist_combo(li, d):
    #Listing all combinations
    from itertools import combinations as c
    max_dist = -1
    max_dist_combo = []
    for p_len in xrange(1,len(li)+1):
        for e in c(li, p_len):
            e_sum = sum(e)
            cond1 = e_sum == d
            cond2 = max_dist < e_sum < d
            if cond1 or cond2:
                max_dist = e_sum
                max_dist_combo = list(e)
                if cond1:
                    return (max_dist, max_dist_combo)
    return (max_dist, max_dist_combo)

def snakes_foreplay(snakes):
    #find distance
    distance = snakes.count(" ")

    #already kissing
    if distance == 0:
        return snakes

    #find num_stretches
    stretch = map(len, re.findall("\|+", snakes))

    #find lowest combination of numbers
    (e_dist, res_stretch) = find_dist_combo(stretch, distance)

    def sub_callback(m):
        s = m.group(0)
        l = len(s) 
        if l in res_stretch:
            res_stretch.remove(l)
            return '/\\'*l
        return s

    #Resultant substitution
    res_snakes = re.sub("\s+", " "*(distance - e_dist), re.sub("\|+", sub_callback, snakes))

    return res_snakes

if __name__ == "__main__":
    for s in [ip.strip() for ip in sys.stdin]:
        print snakes_foreplay(s)

ทดสอบวิธีการเล่นกอล์ฟ -

$ python stretchy_snakes.py
[In]  <=  <|=||:)~     ~(:||||>
[Out] =>  </\=||:)~~(:/\/\/\/\>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~             ~(:||||>
[Out] =>  </\=/\/\:)~      ~(:/\/\/\/\>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~     ~(:|||=|>
[Out] =>  </\=||:)~~(:/\/\/\=/\>

$ python stretchy_snakes.py
[In]  <=  <||=||||:)~   ~(:||>
[Out] =>  </\/\=||||:)~ ~(:||>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~~(:||||>
[Out] =>  <|=||:)~~(:||||>

แน่นอนว่าสิ่งนี้สามารถทำได้ดีกว่า (ฉันไม่สามารถหาวิธี :))
แจ้งให้เราทราบหากฉันพลาดอะไรที่ชัดเจนขณะเล่นกอล์ฟ (มันเป็น codegolf ครั้งแรกของฉันฉันอาจทำอะไรโง่ ๆ : P)


@ Sp3000 นั่นเป็นสิ่งที่ดี แทนที่exitสำหรับsys.exit()( exitมีอยู่แล้วลืม) และคุณมีสิทธิที่__import__สามารถถอดออกได้, ที่ตัดออกเช่น 20 ตัวอักษร :)
Kamehameha

btw rule of thumb: สำหรับ aliasing คุณจำเป็นต้องใช้> 6ตัวอักษรแทนการใช้นามแฝงถ้าคุณใช้สองครั้ง> 3ตัวอักษรถ้าคุณใช้มันสามครั้ง ฉันไม่แน่ใจว่าf=' 'นามแฝงนั้นคุ้มค่า (ฉันนับเป็นสองเท่า)
Sp3000

@ Sp3000 ใช่คุณถูกต้อง ในรุ่นก่อนหน้าฉันใช้ตัวแปรนั้นสามครั้ง ช่วยฉันอีกสองสามไบต์ :) :)
Kamehameha

1

05AB1E , 93 ไบต์

#õKDεγʒ'|å]©ε€gxøDgU`XG‘]`âDε˜ODI„| Ãg>‹*}ZQÏε˜ε®˜NèDgyÊi„/\y∍]н©J'/¢Ið¢αð×ý'|¡õK®.ιJIðå≠iI

นานเกินไป .. >.>

ลองมันออนไลน์หรือตรวจสอบกรณีทดสอบทั้งหมดหรือตรวจสอบผลลัพธ์ที่เป็นไปได้สำหรับกรณีการทดสอบทั้งหมด

คำอธิบาย:

#õK                   # Split the (implicit) input by one or multiple adjacent spaces
                      # (we now have both snakes as separated items
                      #  - if any spaces were in the input-string)
   D                  # Duplicate this list
    ε                 # Map both snakes to:
     γ                #  Split the snake into chunks of the same character-type
      ʒ'|å]          '#  And only leave the chunks of "|" characters
    ©                 #  Store this list in variable `r` (without popping)
     ε                #  Map the "|" chunks of both snakes again:
      g              #  Get the length of each chunk of "|"
        xø            #  Pair each length with double itself
          DgU`XG‘   #  Create all possible combinations for the current snake
     ]`â              # After the map: create all possible combinations for both snakes
        ε             # Map over each possible combination
         ˜O           #  Get the flattened sum
            I„| Ãg    #  Count the amount of "|" and spaces in the input
                  >‹  #  Check if it's smaller than or equal to this sum
                      #  (1 if truthy; 0 if falsey)
           D        * #  And multiply it by the sum
        }ZQ           # After the map, get the positions of the largest flattened sum,
                      # still below (or equal to) the amount of "|" and spaces combined
       D   Ï          # And only keep those combinations
ε                     # Then map over the remaining combinations
 ˜ε                   #  Flatten it, and map over each value `y`
   ®˜Nè               #   Get the `N`'th part of the snakes
                      #   (where `N` is the index of the map for the current combination)
       D              #   Duplicate this "|"-part
        gyÊi          #   If the length of this "|"-part is not equal to the map-value:
            „/\       #    Push the string "/\"
               y     #    Extended to a size equal to the map-value
                      #   (implicit else:
                      #    use the duplicated value)
                    # After the map: only leave the first (since we don't have
                      # to output all possibilities)
 ©                    # Store it in variable `r` (without popping)
  J'/¢               '# Count the amount of "/" in it
      Ið¢             # Count the amount of spaces in the input
         α            # Get the difference between those
          ð×ý         # And join the list of snakes by that many spaces
'|¡õK                '# Then split by one or multiple adjacent "|"
     ®.ι              # Interleave it with the modified parts of variable` r`
        J             # And join everything together to a single string
Iðå≠i                 # If the input didn't contain any spaces:
     I                #  Output the input instead
                      # (implicit else:
                      #  output the top of the stack before this if)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.