Tránh sông


48

Lý lịch

Trong kiểu chữ, các dòng sông là những khoảng trống trực quan trong một khối văn bản, xảy ra do sự liên kết ngẫu nhiên của các không gian. Điều này đặc biệt khó chịu vì não của bạn dường như dễ dàng lấy chúng hơn trong tầm nhìn ngoại vi, khiến mắt bạn liên tục bị phân tâm.

Ví dụ: lấy khối văn bản sau, các dòng bị hỏng sao cho độ rộng của dòng không vượt quá 82 ký tự :

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.

Có một dòng sông trải dài sáu dòng ở phần dưới cùng bên phải, mà tôi đã nhấn mạnh trong khối sau:

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.

Chúng ta có thể giảm thiểu điều này bằng cách chọn chiều rộng cột hơi khác nhau. Ví dụ: nếu chúng ta bố trí cùng một văn bản bằng các dòng không dài hơn 78 ký tự , thì không có dòng sông nào dài hơn hai dòng:

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.

Lưu ý rằng với mục đích của câu hỏi này, chúng tôi chỉ xem xét các phông chữ đơn cách, sao cho các dòng sông chỉ đơn giản là các cột không gian thẳng đứng. Độ dài của một con sông là số dòng nó kéo dài.

Ngoài ra: Nếu bạn thú vị trong việc phát hiện dòng sông theo phông chữ tỷ lệ, có một số bài viết thú vị trên mạng.

Các thách thức

Bạn được cung cấp một chuỗi các ký tự ASCII có thể in (điểm mã 0x20 đến 0x7E) - tức là một dòng đơn. In văn bản này, với độ rộng dòng từ 70 đến 90 ký tự (đã bao gồm), sao cho độ dài tối đa của bất kỳ dòng sông nào trong văn bản được giảm thiểu. Nếu có nhiều chiều rộng văn bản có cùng chiều dài sông tối thiểu (tối thiểu), hãy chọn chiều rộng hẹp hơn. Ví dụ trên với 78 ký tự là đầu ra chính xác cho văn bản đó.

Để ngắt dòng, bạn nên thay thế các ký tự khoảng trắng (0x20) bằng các ngắt dòng, sao cho các dòng kết quả có càng nhiều ký tự càng tốt, nhưng không lớn hơn chiều rộng văn bản đã chọn. Lưu ý rằng chính kết quả ngắt dòng không phải là một phần của số đó. Ví dụ, trong khối cuối cùng ở trên, Lorem[...]temporchứa 78 ký tự, cũng là chiều rộng của văn bản.

Bạn có thể cho rằng đầu vào sẽ không chứa các khoảng trắng liên tiếp và sẽ không có khoảng trắng ở đầu hoặc cuối. Bạn cũng có thể cho rằng không có từ nào (chuỗi con liên tiếp không dấu cách) sẽ chứa hơn 70 ký tự.

Bạn có thể viết chương trình hoặc hàm, lấy đầu vào qua STDIN, đối số dòng lệnh hoặc đối số hàm và in kết quả sang STDOUT.

Đây là mã golf, vì vậy câu trả lời ngắn nhất (tính bằng byte) sẽ thắng.


Tôi nghĩ trong các ví dụ bọc cột 78 và 82 của bạn, các dòng cuối cùng và thứ hai đến cuối cùng là không chính xác. Trong ví dụ 82, khoảng nghỉ cuối cùng phải nằm giữa idest , và trong ví dụ 78, nó phải nằm giữa inculpa . Hay tôi đang làm gì đó sai?
Cristian Lupascu

@Optimizer Dấu ngắt là chiều dài văn bản, không phải chiều dài sông.
FryAmTheEggman

Tôi đoán nó không được tính là một dòng sông chính thức, nhưng trong ví dụ có độ dài tối đa 78 ký tự, dường như có một dòng sông chéo khá dài ở khu vực phía trên bên trái
markasoftware 6/11/2016

Chúng ta có coi những trường hợp như thế này là những dòng sông tiếp tục không?
Trình tối ưu hóa

Thử thách lớn! Hừm, cái tiếp theo có thể là về việc có những dòng sông (không hoàn toàn thẳng đứng) định hình những chữ cái thăng hoa;)
Tobias Kienzler

Câu trả lời:


7

CJam, 116 106 99 84 77 72 byte

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

Lấy đầu vào dòng đơn và in đầu ra chính xác sang STDOUT.

CẬP NHẬT : Cải thiện rất nhiều và loại bỏ các vòng lặp dư thừa bằng cách thực hiện tất cả các tính toán trong chính vòng lặp sắp xếp. Cũng sửa một lỗi trong tính toán chiều dài sông.

Giải thích sớm (sau khi tôi chơi gôn hơn nữa)

Hãy thử nó ở đây


@Optimizer Bạn có thể sử dụng đầu vào từ ARGV, sau đó bạn có thể làm ea~thay vì Xmỗi lần. Lưu hai byte.
Martin Ender

12

Ruby 162 160 158 152 160 157 ( bản demo )

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

Phiên bản không chơi gôn:

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{...}cho phép tôi sử dụng phép nội suy chuỗi. Tôi mới thử 21.times, nhưng nó có một số ý nghĩa nữa và tôi đã không thể đạt được một giải pháp ngắn hơn.
Cristian Lupascu

@ MartinBüttner Bạn là đúng, nó không làm việc! Tôi đã chỉnh sửa câu trả lời của mình. Cảm ơn!
Cristian Lupascu

Điều này không hoạt động với pastebin.com/vN2iAzNd
Joshpbarron

@Joshpbarron Phát hiện rất tốt! Tôi đã sửa nó bây giờ.
Cristian Lupascu

8

APL (105)

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

Giải trình:

  • (K⊂⍨' '=K←' ',⍵): Thêm một khoảng trắng ở phía trước , sau đó phân chia trên các khoảng trắng. Mỗi từ giữ lại không gian nó bắt đầu.
  • ∘{... }¨70+⍳21: với giá trị đó, cho mỗi số trong phạm vi [71, 91]: (Do cách phân chia các từ, mỗi 'dòng' kết thúc với một khoảng trắng thừa ở đầu, sẽ bị xóa sau. Phạm vi được thay đổi bởi một để bù cho không gian thừa.)
    • ×⍴⍺:: nếu vẫn còn từ,
      • z←⍵>+\≢¨⍺: lấy độ dài cho mỗi từ và tính tổng thời lượng chạy cho mỗi từ. Đánh dấu bằng 1tất cả các từ có thể được thực hiện để điền vào dòng tiếp theo và lưu trữ này vào z.
      • (⊂z/⍺),⍵∇⍨⍺⍨~z: lấy những từ đó, và sau đó xử lý những gì còn lại của danh sách.
    • ⋄⍺: nếu không, trả về (hiện đang trống).
  • G←: lưu trữ danh sách các danh sách các dòng trong G(một cho mỗi chiều dài dòng có thể).
  • V←{... }¨G: cho mỗi khả năng, tính chiều dài của con sông dài nhất và lưu trữ vào V:
    • +\↑≢¨¨⍵: lấy độ dài của mỗi từ (một lần nữa) và tạo một ma trận trong số các độ dài. Tính tổng chạy cho mỗi dòng trên các hàng của ma trận. (Do đó, không gian thừa ở đầu mỗi dòng bị bỏ qua.)
    • 2≠⌿: cho mỗi cột của ma trận, xem độ dài hiện tại của dòng tại điểm đó không khớp với dòng sau nó. Nếu vậy, có không một con sông ở đó.
    • ⊂⍨¨↓⍉: tự tách từng cột của ma trận (trên 1s). Điều này đưa ra một danh sách các danh sách, trong đó đối với mỗi dòng sông sẽ có một danh sách [1, 0, 0, ...], tùy thuộc vào độ dài của dòng sông. Nếu không có sông, danh sách sẽ có [1].
    • ⌈/≢¨: lấy chiều dài của mỗi con sông và lấy giá trị tối đa của nó.
  • ⊃G/⍨V=⌊/V: từ G, chọn mục đầu tiên có chiều dài của con sông dài nhất bằng với mức tối thiểu cho tất cả các mục.
  • {1↓∊⍵,3⊃⎕TC}¨: cho mỗi dòng, nối tất cả các từ lại với nhau, xóa mục nắm tay (khoảng trắng thừa từ đầu) và thêm một dòng mới vào cuối.
  • : nối tất cả các dòng với nhau.

Đó là 200 byte, không phải 105.
user11153

3
@ user11153 Tôi chưa chỉ định UTF-8 làm mã hóa. Bộ ký tự APL phù hợp với một codepage duy nhất (và codepage đó tồn tại ), tức là có một mã hóa hiện có mà mỗi ký tự đó khớp với một byte và do đó 105 là hoàn toàn tốt.
Martin Ender

Tốt để biết! :)
dùng11153

8

Bash + coreutils, 236 157 byte

Được chỉnh sửa với một cách tiếp cận khác - ngắn hơn một chút so với trước đây:

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

Đọc chuỗi đầu vào từ dòng lệnh.

Với 3 loại lồng nhau, tôi rùng mình khi nghĩ độ phức tạp thời gian lớn của nó là gì, nhưng nó hoàn thành ví dụ dưới 10 giây trên máy của tôi.


3

Python, 314 byte

Rất cám ơn SP3000, grc và 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')

2
Giống như Pi-thon
Trình tối ưu hóa

3

JavaScript (ES6) 194 202

Giải pháp lặp lại, có thể ngắn hơn nếu thực hiện đệ quy

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

Giải thích

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

Thử nghiệm trong bảng điều khiển 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.')

Đầu ra

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 byte

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

Phiên bản bị đánh cắp:

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