หลีกเลี่ยงแม่น้ำ


48

พื้นหลัง

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

ยกตัวอย่างเช่นใช้บล็อกข้อความต่อไปนี้บรรทัดที่แตกจนความกว้างบรรทัดไม่เกิน82 อักขระ :

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eismod tempor
incididunt ut labore et dolore maga aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet,
consectetur adipisicing elit, sed do eismod tempor incididunt ut labore et dolore
maga aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.

มีแม่น้ำทอดยาวหกบรรทัดในส่วนล่างขวาซึ่งฉันได้เน้นไว้ในบล็อกต่อไปนี้:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eismod tempor
incididunt ut labore et dolore maga aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum. Lorem█ipsum dolor sit amet,
consectetur adipisicing elit, sed do eismod tempor█incididunt ut labore et dolore
maga aliqua. Ut enim ad minim veniam, quis nostrud█exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute█irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla█pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui█officia deserunt mollit anim id
est laborum.

เราสามารถลดสิ่งนี้ได้โดยเลือกความกว้างคอลัมน์ที่แตกต่างกันเล็กน้อย เช่นถ้าเราจัดวางข้อความเดียวกันโดยใช้บรรทัดไม่เกิน78 ตัวอักษรจะไม่มีแม่น้ำยาวเกินสองบรรทัด:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eismod tempor
incididunt ut labore et dolore maga aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt
in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor
sit amet, consectetur adipisicing elit, sed do eismod tempor incididunt ut
labore et dolore maga aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.

โปรดทราบว่าเพื่อจุดประสงค์ของคำถามนี้เราจะพิจารณาแบบอักษรแบบโมโนสเกลเท่านั้นเช่นแม่น้ำเป็นเพียงคอลัมน์แนวตั้งของช่องว่าง ความยาวของแม่น้ำคือจำนวนบรรทัดที่มีช่วง

นอกเหนือ: หากคุณสนใจการตรวจจับแม่น้ำในแบบอักษรที่มีสัดส่วนมีโพสต์ที่น่าสนใจ รอบ ๆ เครือข่าย

ความท้าทาย

คุณได้รับสตริงอักขระ ASCII ที่พิมพ์ได้ (รหัสจุด 0x20 ถึง 0x7E) - เช่นหนึ่งบรรทัด พิมพ์ข้อความนี้โดยมีความกว้างบรรทัดระหว่าง 70 ถึง 90 ตัวอักษร (รวมแล้ว) เพื่อให้ความยาวสูงสุดของแม่น้ำใด ๆ ในข้อความนั้นลดลง หากมีความกว้างหลายข้อความที่มีความยาวแม่น้ำสูงสุด (ขั้นต่ำ) เดียวกันให้เลือกความกว้างที่แคบกว่า ตัวอย่างด้านบนมีอักขระ 78 ตัวเป็นเอาต์พุตที่ถูกต้องสำหรับข้อความนั้น

ในการแบ่งบรรทัดคุณควรแทนที่อักขระเว้นวรรค (0x20) ด้วยการขึ้นบรรทัดใหม่เพื่อให้บรรทัดผลลัพธ์มีอักขระมากที่สุด แต่ไม่เกินความกว้างข้อความที่เลือก โปรดทราบว่าตัวแบ่งบรรทัดผลลัพธ์ไม่ได้เป็นส่วนหนึ่งของการนับนั้น ตัวอย่างในบล็อกสุดท้ายด้านบนLorem[...]temporมีอักขระทั้งหมด 78 ตัวซึ่งเป็นความกว้างของข้อความด้วย

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

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่นรับอินพุตผ่าน STDIN อาร์กิวเมนต์บรรทัดคำสั่งหรืออาร์กิวเมนต์ฟังก์ชันแล้วพิมพ์ผลลัพธ์ไปที่ STDOUT

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


ฉันคิดว่าในตัวอย่างการตัดคอลัมน์ 78 และ 82 ของคุณบรรทัดสุดท้ายและบรรทัดที่สองไปไม่ถูกต้อง ในตัวอย่าง 82 แบ่งสุดท้ายควรอยู่ระหว่างIDและESTและในตัวอย่างที่ 78 มันควรจะเป็นระหว่างในและบาป หรือฉันกำลังทำอะไรผิดพลาด?
Cristian Lupascu

@Optimizer tie break คือความยาวข้อความไม่ใช่ความยาวของแม่น้ำ
FryAmTheEggman

ฉันคิดว่ามันไม่นับว่าเป็นแม่น้ำอย่างเป็นทางการ แต่ในตัวอย่างความยาวสูงสุด 78 ตัวอักษรดูเหมือนว่าจะมีแม่น้ำเส้นทแยงมุมยาวสวยในพื้นที่ด้านซ้าย
ไอ

เราพิจารณากรณีเช่นนี้ว่าเป็นแม่น้ำต่อไปหรือไม่?
เครื่องมือเพิ่มประสิทธิภาพ

ท้าทายมาก! หืมคนต่อไปอาจเกี่ยวกับการมีแม่น้ำ (ไม่ใช่แนวดิ่งอย่างหมดจด) เพื่อสร้างตัวอักษรอ่อนเกินกำลัง)
Tobias Kienzler

คำตอบ:


7

CJam, 116 106 99 84 77 72 ไบต์

l:X;93,72>{:D;OOXS/{S+_2$+,D<{+}{@@);a+\}?}/a+}%{z'K*S/:!0a/1fb$W=}$0=N*

รับอินพุตบรรทัดเดียวและพิมพ์เอาต์พุตที่ถูกต้องไปที่ STDOUT

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

คำอธิบายในไม่ช้า (หลังจากฉันเล่นกอล์ฟยิ่งขึ้นไปอีก)

ลองที่นี่


@Optimizer คุณสามารถใช้อินพุตจาก ARGV ได้จากนั้นคุณสามารถทำea~แทนXแต่ละครั้งได้ บันทึกสองไบต์
Martin Ender

12

Ruby 162 160 158 152 160 157 ( ตัวอย่าง )

i=gets+' '
(69..s=r=89).map{|c|w=i.scan(/(.{1,#{c}}\S) /).flatten
m=(0..c).map{|i|w.map{|l|l[i]}+[?x]}.join.scan(/ +/).map(&:size).max
m<s&&(s=m;r=w)}
puts r

รุ่นที่ยังไม่ตีกอล์ฟ:

input = gets+' '

result = ''

(69..smallest_max=89).each{|w|
  #split text into words of at most w characters
  wrap = (input+' ').scan(/(.{1,#{w}}\S) /).flatten

  #transpose lines and find biggest "river"
  max_crt_river = (0..99).map{|i| wrap.map{|l|l[i]} }.flatten.join.scan(/ +/).max_by(&:size).size

  if max_crt_river < smallest_max
    smallest_max = max_crt_river
    result = wrap.join ?\n
  end
}
puts result

@ MartinBüttner %r{...}อนุญาตให้ฉันใช้การแก้ไขสตริง ฉันเพิ่งลอง21.timesแต่มันมีความหมายเพิ่มเติมตามท้องถนนและฉันไม่ได้พยายามหาวิธีแก้ปัญหาที่สั้นกว่านี้
Cristian Lupascu

@ MartinBüttnerคุณมีสิทธิที่มันไม่ทำงาน! ฉันแก้ไขคำตอบของฉันแล้ว ขอบคุณ!
Cristian Lupascu

สิ่งนี้ใช้ไม่ได้กับpastebin.com/vN2iAzNd
Joshpbarron

@Joshpbarron ด่างมาก! ฉันแก้ไขมันตอนนี้
Cristian Lupascu

8

APL (105)

{∊{1↓∊⍵,3⊃⎕TC}¨⊃G/⍨V=⌊/V←{⌈/≢¨⊂⍨¨↓⍉2≠⌿+\↑≢¨¨⍵}¨G←(K⊂⍨' '=K←' ',⍵)∘{×⍴⍺:(⊂z/⍺),⍵∇⍨⍺/⍨~z←⍵>+\≢¨⍺⋄⍺}¨70+⍳21}

คำอธิบาย:

  • (K⊂⍨' '=K←' ',⍵): เพิ่มช่องว่างด้านหน้าแล้วแบ่งช่องว่าง แต่ละคำจะรักษาช่องว่างที่เริ่มต้นด้วย
  • ∘{... }¨70+⍳21: ด้วยค่าดังกล่าวสำหรับแต่ละตัวเลขในช่วง[71, 91]: (เนื่องจากวิธีการแบ่งคำแต่ละบรรทัดจะลงท้ายด้วยช่องว่างเพิ่มเติมในจุดเริ่มต้นซึ่งจะถูกลบออกในภายหลังช่วงถูกเลื่อนโดย หนึ่งเพื่อชดเชยพื้นที่พิเศษ)
    • ×⍴⍺:: หากยังมีคำเหลืออยู่
      • z←⍵>+\≢¨⍺: รับความยาวสำหรับแต่ละคำและคำนวณผลรวมของความยาวต่อคำ มาร์คกับทุกคำที่สามารถนำมาเติมให้เต็มบรรทัดถัดไปและจัดเก็บใน1z
      • (⊂z/⍺),⍵∇⍨⍺⍨~z: ใช้คำเหล่านั้นแล้วประมวลผลสิ่งที่เหลืออยู่ของรายการ
    • ⋄⍺: ถ้าไม่กลับ(ซึ่งตอนนี้ว่างเปล่า)
  • G←: เก็บรายการของรายการในG(หนึ่งสำหรับแต่ละความยาวบรรทัดที่เป็นไปได้)
  • V←{... }¨G: สำหรับแต่ละความเป็นไปได้คำนวณความยาวของแม่น้ำที่ยาวที่สุดและเก็บไว้ในV:
    • +\↑≢¨¨⍵: รับความยาวของแต่ละคำ (อีกครั้ง) และสร้างเมทริกซ์จากความยาว คำนวณผลรวมสะสมสำหรับแต่ละบรรทัดบนแถวของเมทริกซ์ (ดังนั้นจะเว้นช่องว่างที่จุดเริ่มต้นของแต่ละบรรทัด)
    • 2≠⌿: สำหรับแต่ละคอลัมน์ของเมทริกซ์ดูว่าความยาวปัจจุบันของบรรทัดที่จุดนั้นไม่ตรงกับบรรทัดหลังจากนั้นหรือไม่ ถ้าเป็นเช่นนั้นไม่มีแม่น้ำที่นั่น
    • ⊂⍨¨↓⍉: แยกแต่ละคอลัมน์ของเมทริกซ์ด้วยตัวเอง (บน1s) สิ่งนี้จะให้รายการของรายการที่แต่ละแม่น้ำจะมีรายการ[1, 0, 0, ...]ขึ้นอยู่กับความยาวของแม่น้ำ [1]ถ้าไม่มีแม่น้ำรายการจะเป็น
    • ⌈/≢¨: รับความยาวของแม่น้ำแต่ละสายและรับค่าสูงสุดของแม่น้ำนั้น ๆ
  • ⊃G/⍨V=⌊/V: จากGเลือกรายการแรกที่ความยาวของแม่น้ำที่ยาวที่สุดเท่ากับค่าต่ำสุดสำหรับทุกรายการ
  • {1↓∊⍵,3⊃⎕TC}¨: สำหรับแต่ละบรรทัดรวมคำทั้งหมดเข้าด้วยกันลบรายการกำปั้น (ช่องว่างพิเศษจากจุดเริ่มต้น) และเพิ่มขึ้นบรรทัดใหม่ไปยังจุดสิ้นสุด
  • : เข้าร่วมทุกบรรทัดด้วยกัน

นั่นคือ 200 ไบต์ไม่ใช่ 105
user11153

3
@ user11153 ฉันไม่ได้ระบุ UTF-8 เป็นการเข้ารหัส ชุดอักขระ APL พอดีกับเพจรหัสเดียว (และเพจเพจนั้นมีอยู่ ) นั่นคือมีการเข้ารหัสที่มีอยู่แล้วโดยที่อักขระแต่ละตัวนั้นพอดีกับไบต์ดังนั้น 105 จึงสมบูรณ์ดี
Martin Ender

ดีแล้วที่รู้! :)
user11153

8

Bash + coreutils, 236 157 ไบต์

แก้ไขด้วยวิธีการอื่น - ค่อนข้างสั้นกว่าก่อนหน้าเล็กน้อย:

a=(`for i in {71..91};{
for((b=1;b++<i;));{
fold -s$i<<<$@|cut -b$b|uniq -c|sort -nr|grep -m1 "[0-9]  "
}|sort -nr|sed q
}|nl -v71|sort -nk2`)
fold -s$a<<<$@

อ่านสตริงอินพุตจากบรรทัดรับคำสั่ง

ด้วย 3 ประเภทซ้อนกันฉันตัวสั่นที่จะคิดว่าอะไรคือความซับซ้อนของเวลาขนาดใหญ่ -O สำหรับสิ่งนี้


3

Python ขนาด 314 ไบต์

ต้องขอบคุณ SP3000, grc และ FryAmTheEggman:

b=range;x=len
def p(i):
 l=[];z=''
 for n in t:
  if x(z)+x(n)<=i:z+=n+' '
  else:l+=[z];z=n+' '
 return l+[z]*(z!=l[x(l)-1])
t=input().split();q=[]
for i in b(70,91):l=p(i);q+=[max(sum(x(l[k+1])>j<x(l[k])and l[k][j]is' '==l[k+1][j]for k in b(x(l)-1))for j in b(i))]
print(*p(q.index(min(q))+70),sep='\n')


3

JavaScript (ES6) 194 202

วิธีแก้ปัญหาซ้ำแล้วซ้ำอีกอาจจะสั้นลงหากทำซ้ำ

F=s=>{
  for(m=1e6,b=' ',n=70;n<91;n++)
    l=b+'x'.repeat(n),x=r=q='',
    (s+l).split(b).map(w=>
      (t=l,l+=b+w)[n]&&(
        l=w,r=r?[...t].map((c,p)=>x<(v=c>b?0:-~r[p])?x=v:v,q+=t+'\n'):[]
      )
    ),x<m&&(o=q,m=x);
  alert(o)
}

อธิบาย

F=s=> {
  m = 1e9; // global max river length, start at high value
  for(n=70; n < 91; n++) // loop on line length
  {
    l=' '+'x'.repeat(n), // a too long first word, to force a split and start
    x=0, // current max river length
    q='', // current line splitted text
    r=0, // current river length for each column (start 0 to mark first loop)
    (s+l) // add a too long word to force a last split. Last and first row will not be managed
    .split(' ').map(w=> // repeat for each word 
      (
        t=l, // current partial row in t (first one will be dropped)
        (l += ' '+w)[n] // add word to partial row and check if too long
        &&
        (
          l = w, // start a new partial row with current word
          r=r? // update array r if not at first loop
          ( 
            q+=t+'\n', // current row + newline added to complete text 
            [...t].map((c,p)=>( // for each char c at position p in row t
              v = c != ' ' 
                ? 0 // if c is not space, reset river length at 0
                : -~r[p], // if c is space, increment river length
              x<v ? x=v : v // if current > max, update max
            ))
          ):[]  
        )  
      )
    )
    x < m && ( // if current max less than global max, save current text and current max
      o = q,
      m = x
    )
  }
  console.log(o,m)
}

ทดสอบในคอนโซล FireFox / FireBug

F('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eismod tempor incididunt ut labore et dolore maga aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eismod tempor incididunt ut labore et dolore maga aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.')

เอาท์พุต

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eismod tempor
incididunt ut labore et dolore maga aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt
in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor
sit amet, consectetur adipisicing elit, sed do eismod tempor incididunt ut
labore et dolore maga aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.

3

Python 3, 329 ไบต์

import re,itertools as s
def b(t,n):
 l=0;o=""
 for i in t.split():
  if l+len(i)>n:o=o[:-1]+'\n';l=0
  l+=len(i)+1;o+=i+' '
 return o
t=input();o={}
for n in range(90,69,-1):o[max([len(max(re.findall('\s+',x),default='')) for x in ["".join(i) for i in s.zip_longest(*b(t,n).split('\n'),fillvalue='')]])]=n
print(b(t,o[min(o)]))

เวอร์ชันที่ไม่ถูกปรับแต่ง:

# Iterates over words until length > n, then replaces ' ' with '\n'
def b(t,n):
    l = 0
    o = ""
    for i in t.split():
        if l + len(i) > n:
            o = o[:-1] + '\n'
            l = 0
        l += len(i) + 1
        o += i + ' '
    return o

t = input()
o = {}
# range from 90 to 70, to add to dict in right order
for n in range(90,69,-1):
    # break text at length n and split text into lines
    temp = b(t,n).split('\n')
    # convert columns into rows
    temp = itertools.zip_longest(*temp, fillvalue='')
    # convert the char tuples to strings
    temp = ["".join(i) for i in temp]
    # findall runs of spaces, get longest run and get length
    temp = [len(max(re.findall('\s+',x),default='')) for x in temp]
    # add max river length as dict key, with line length as value
    o[max(temp)] = n

print(b(t,o[min(o)]))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.