川を避ける


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.

右下の部分に6本の線にまたがる川があります。これは次のブロックで強調表示しています。

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文字以下の行を使用して同じテキストをレイアウトする場合、2行より長い川はありません。

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)-つまり1行が与えられます。テキスト内の川の最大長が最小になるように、70〜90文字(両端を含む)の行幅でこのテキストを印刷します。同じ(最小の)最大河川長を持つ複数のテキスト幅がある場合は、狭い幅を選択します。上記の78文字の例は、そのテキストの正しい出力です。

改行するには、スペース文字(0x20)を改行で置き換えて、結果の行にできるだけ多くの文字が含まれるようにしますが、選択したテキスト幅以下にします。結果の改行自体は、そのカウントの一部ではないことに注意してください。例として、上の最後のブロックにLorem[...]temporは、78文字が含まれていますが、これはテキストの幅でもあります。

入力に連続したスペースが含まれておらず、先頭または末尾のスペースがないと想定できます。また、単語(非スペースの連続部分文字列)に70文字を超える文字は含まれないと想定することもできます。

プログラムまたは関数を作成し、STDIN、コマンドライン引数または関数引数を介して入力を取得し、結果をSTDOUTに出力できます。

これはコードゴルフなので、最短の回答(バイト単位)が勝ちです。


78および82列の折り返しの例では、最後の行と最後から2番目の行が間違っていると思います。82の例では、最後のブレークはidestの間にある必要があり、78の例ではinculpaのにある必要があります。それとも私は何か間違ったことをしていますか?
クリスチャンルパスク14年

@Optimizerタイブレークはテキストの長さであり、川の長さではありません。
FryAmTheEggman 14年

私はそれが公式の川としてカウントされませんと思いますが、例えば、78文字以内の長さで、トップっぽい左っぽいエリアではかなり長い対角線川があるように思われる
markasoftware

川が続くので、このようなケースを考慮しますか?
オプティマイザー14年

素晴らしい挑戦です!フム、次のものが(純粋に垂直ではない)サブリミナル文字を形作る川を持っていることについてである可能性があります。)
トビアスKienzler

回答:


7

CJam、116106 99 84 77 72バイト

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

1行の入力を受け取り、正しい出力をSTDOUTに出力します。

更新:ソートループ自体ですべての計算を行うことにより、大幅に改善され、冗長なループが削除されました。また、川の長さの計算のバグを修正しました。

すぐに説明(さらにゴルフをした後)

ここで試してみてください


@Optimizer ARGVからの入力を使用することもできますが、そのたびにea~代わりに使用できますX。2バイト節約します。
マーティンエンダー14年

12

ルビー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、今後さらに多くの影響があり、短いソリューションに到達することができませんでした。
クリスチャンルパスク14年

@MartinBüttnerあなたは正しい、それ動作します!回答を編集しました。ありがとう!
クリスティアンルパスク14年

これは動作しませんpastebin.com/vN2iAzNd
Joshpbarron

@Joshpbarron非常によく見つけました!今すぐ修正しました。
クリスチャンルパスク14年

8

APL(105)

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

説明:

  • (K⊂⍨' '=K←' ',⍵):の前にスペースを追加し、スペースで分割します。各単語は、それが始まるスペースを保持します。
  • ∘{... }¨70+⍳21:その値を使用して、範囲内の各番号に対して[71, 91]:(単語が分割される方法のため、各「行」は先頭に余分なスペースがあり、後で削除されます。範囲は次のようにシフトされます。余分なスペースを補うためのもの。)
    • ×⍴⍺::まだ単語が残っている場合、
      • z←⍵>+\≢¨⍺:各単語の長さを取得し、単語ごとの長さの合計を計算します。1次の行を埋めるために使用できるすべての単語でマークし、これをに保存しzます。
      • (⊂z/⍺),⍵∇⍨⍺⍨~z:それらの単語を取り、リストの残りを処理します。
    • ⋄⍺:そうでない場合は、戻ります(現在は空です)。
  • G←:行のリストのリストを格納しますG(可能な行の長さごとに1つ)。
  • V←{... }¨G:可能性ごとに、最長の川の長さを計算して保存しVます:
    • +\↑≢¨¨⍵:各単語の長さを(再び)取得し、長さからマトリックスを作成します。行列の行の各行の現在までの合計を計算します。(したがって、各行の先頭にある余分なスペースは無視されます。)
    • 2≠⌿:マトリックスの各について、そのポイントの行の現在の長さがその後の行と一致しないかどうかを確認します。もしそうなら、そこに川はありません
    • ⊂⍨¨↓⍉:マトリックスの各列を単独で(1sで)分割します。これにより、リストのリストが表示されます。各川には[1, 0, 0, ...]、川の長さに応じてlist があります。川がない場合、リストはになります[1]
    • ⌈/≢¨:各川の長さを取得し、その最大値を取得します。
  • ⊃G/⍨V=⌊/V:fromからG、最も長い川の長さがすべてのアイテムの最小値に等しい最初のアイテムを選択します。
  • {1↓∊⍵,3⊃⎕TC}¨:各行について、すべての単語を結合し、最初の項目(先頭から余分なスペース)を削除し、末尾に改行を追加します。
  • :すべての行を結合します。

200のバイトではなく、105だこと
user11153

3
@ user11153エンコーディングとしてUTF-8を指定していません。APL文字セットは単一のコードページに収まります(そのコードページが存在します)。つまり、これらの各文字が1バイトに収まる既存のエンコーディングが存在するため、105は完全に問題ありません。
マーティンエンダー14年

知っておきたい!:)
user11153 14年

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の時間の複雑さを考えるのに身震いしますが、私のマシンでは10秒以内に例を完了します。


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

2
Pi-thon
Optimizerの

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.