右揃えのテキスト


27

あなたの仕事は、文字列の入力と数字を受け取り、文字列を右に揃えて、テキストの幅を数字にすることです。行が長すぎる場合は、その行を分割して残りを次の行に置き、不要になるまで繰り返します。行が幅より短い場合は、スペースで埋めます。複数の改行が発生する可能性があり、他の単一文字と同様に処理する必要があります。

たとえば、文字列

Programming
Puzzles
&
Code
Golf

そしてその数5は以下を生成します:

Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf

一方、同じ文字列と数値で10は次のようになります。

Programmin
         g
   Puzzles
         &
      Code
      Golf

文字列

a

b

そして、5という数字は以下を生成します:

    a
      <-- note the 5 spaces
    b

最短のコードが勝ちます!


1
テキストには「必要に応じて行を分割してください[...]」と書かれていますが、例では、単語が収まる場合でも、すべての単語の後改行することを提案しています。明確にしてください:各単語を新しい行に配置するのですか、それとも実際の単語ラッピングアルゴリズムを実装するのですか?
ティムウィ

入力行の途中にスペースを入れることはできますProgramming Puzzles\n&\nCode Golfか?
Sp3000

@ sp3000スペースを含む任意の文字を使用できます。
トレブシェット

@Timwi:この例には、1行に1つの単語があります。行内のスペースが特別なものではないことを明確にするために、複数の単語の行を含める方が良いでしょう。(つまり、改行のみと非改行のみがあります。)
ピーターコーデス

回答:



10

Python 2、84

s,n=input()
for w in s.split('\n'):
 w=w or' '
 while w:print w[:n].rjust(n);w=w[n:]

改行と数字を含む文字列を入力として受け取り、結果を出力します。入力の各行に対して、n文字を一度に取得してrjust印刷します。組み込みを使用して、印刷前にスペースを左側に埋め込みます。

ハックで空の行ケースを修正しましたw=w or' '。おそらくもっと良い方法がありますが、私はそれについてあまり考えません。


8

CJam、21バイト

li_qN/Sfe|f/ff{\Se[N}

@ Sp3000に1バイトのゴルフをし、さらに3バイトの道を開いてくれてありがとう

CJamインタープリターでオンラインで試してください。

使い方

li                     Read an integer L from the first line of input.
  _                    Push a copy.
   qN/                 Split the remaining input at linefeeds.
      Sfe|             Map `OR " "'; the replaces empty lines with a space.
          f/           Split each line into chunks of length L.
            ff{     }  For each chunk, push L and the chunk; then:
               \         Swap L with the chunk.
                Se[      Left-pad the chunk to length L by prepending " ".
                   N     Push a linefeed.

5

Pyth、16

jm>Q+*\ QdscRQ.z

こちらからオンラインでお試しください

説明

jm>Q+*\ QdscRQ.z             : Q is the number on the first line, .z takes the rest
           cRQ.z             : chop each line of .z into chunks of Q characters
 m        s                  : remove nested lists and map over the result
    +*\ Qd                   : add Q spaces to each line d
  >Q                         : take the last Q characters of that result
j                            : join results on newlines

4

Perl、39バイト

perl -ni5 -e 's!^$|.{1,$^I}!printf"%${^I}s
",$&!ge'

36バイト+ 3バイト-ni。ラップの幅は、引数としてに渡されます-i

空白行にスペースを埋めることにより、空白行を適切に処理します。

$ echo -e "Programming\nPuzzles\n\n&\n\nCode\nGolf" | perl -ni5 -e 's!^$|.{1,$^I}!printf"%${^I}s
",$&!ge'
Progr
ammin
    g
Puzzl
   es

    &

 Code
 Golf

使い方

このソリューションでは、置換演算子を使用して入力をループし、同等のforループでバイトを節約します。しかし、本当のトリックは、置換のLHSの正規表現にあります。

^$|.{1,$^I}

グローバル修飾子を使用すると$^I、一度に文字と一致します。$^I文字列に残っている文字数が少ない場合、最後まですべて一致します。^$空白行を処理するには、with が必要です。例えば:

$ echo -e "foo\n\nbar" | perl -ni2 -E 'say "<$_>" for /^$|.{1,$^I}/g'
<fo>
<o>
<>
<ba>
<r>

置換のRHSは、printf一致したチャンクをスペースで左詰めするために使用します。


私はいつも忘れ$^Iます!
ドムヘイスティングス

@DomHastingsそのトリックをchilemagicから学びました。彼は別のチャレンジのコメントでそれを言及しました。
-ThisSuitIsBlackNot

3

Javascript(ES6)、107

JSに組み込みのパッド機能があればいいのにと思います。しかたがない。

(a,b)=>a.replace(eval(`/(.{${b}})(?!\\n)/g`),`$1
`).split`
`.map(c=>(Array(b).join` `+c).slice(-b)).join`
`

説明:

(a, b)=>

  // searches for sequences of characters longer than b without a newline after them and
  // adds a newline after every b characters of the sequence
  a.replace(eval(`/(.{${b}})(?!\\n)/g`), '$1\n')
    .split('\n')
    .map(c=>

      // prepends b spaces to each string then slices it from the right down to length b
      ( Array(b).join(' ') + c ).slice(-b)

    ).join('\n')

3

ジュリア、126バイト

f(s,n)=for i=split(s,"\n") while length(i)>0 println(lpad(i[1:min(n,end)],n));length(i)<n?break:(i=i[min(n+1,end):end])end;end

ゴルフをしていない:

function f(s::String, n::Int)
    for i in split(s, "\n")
        while length(i) > 0
            println(lpad(i[1:min(n,end)], n))
            length(i) < n ? break : (i = i[min(n+1,end):end])
        end
    end
end

2

バッシュ、6261 +機能、59

N入力の最初の行として読み込む代わりに、呼び出し側が設定できる場合は短い。

# width as a function arg: 59 chars
f()while read -rn$1 r;do [[ $r ]]&&printf %$1s\\n "$r";done
# width on stdin: 64 chars  (not updated with later suggestions&ideas)
read N;while read -rn$N r;do [[ $r ]]&&printf %$N's\n' "$r";done

これは、入力の空行の処理に失敗します。それ以外の場合、これは入力データを単語分割、パス名展開、またはその他の方法で生データ以上のものとして扱うことはありません。

read -n$N1文字を保存しますが、readむしゃむしゃさせます\

次の文字が改行で[[ $r ]]&&あるread -n4ことを先読みできないので、これが必要です。したがってr、4文字の文字列に設定され、次の読み取りではゼロ文字の空の文字列が生成されます。実際の改行をフィルタリングせずにこれらの偽の改行をフィルタリングするには、前の行が最大長であったかどうかの追跡状態が必要です。コードを増やすか、まったく異なるアプローチが必要になります。

[[ $r ]]より短い[ -n "$r" ]行で始まる場合にはエラーを回避するために必要とされる-z foo、またはである*あなたが使用している場合、または何か[ $r ]

正当化は、標準のprintf "%4s"形式文字列で発生します。

でテスト

f()(while read -rn$1 r;do [[ $r ]]&&printf %$1s\\n "$r";done); (echo 4; echo -e "*\n\\"; cat /tmp/lines) | f 4

1. -rバイトカウントに含めます。2. f()(while ... done)少し短いです。
デニス

@Dennis:なし[[ $r ]]&&で、N = 4の場合、長さ4の入力行は、前になかった場所に空白の出力行を生成します。のでread戻って4文字の文字列が、その後、すぐに次の呼び出しとリターンに改行を見ています。また、()ヒントをありがとう。fnsをそのように定義できるとは知りませんでした。
ピーターコーデス

Bashでのゴルフのヒントを読むことをお勧めします。これは素晴らしいリソースです。
デニス

実際、whileすでに複合されているため、括弧も必要ありませんf()while ... done
デニス

@デニス:すごい。リンクをありがとう。それらのいくつかは私にとって新しいものであり、別の答えでいくつかの問題を修正しました:)私は通常ゴルフをしませんが、コマンドライン中毒者である15年以上は私に1つまたは2つのことを教えてくれました:)
ピーターCordes

2

Haskell、108バイト

import Data.List.Split
k[]=[""]
k x=x
f n=unlines.(map(\l->([1..n-length l]>>" ")++l).k.chunksOf n=<<).lines

使用例:

*Main> putStr $ f 5 "a\n\nb\ncd\nMatamorphosis"
    a

    b
   cd
Matam
orpho
  sis

使い方

                              .lines   -- split input string at newlines
                           =<<         -- for every line
                  chunksOf n           --    split into chunks of length n
                k                      --    fix empty lines
    map                                --    for every chunk
        \l->([1..n-length l]>>" "      --      make a string of missing spaces
                        ++l            --      and append the chunk
unlines                                -- join padded chunks with newlines in-between

1

GNU awk + ​​bash、70

f()(awk -vFPAT=.\{,$1} '{for(i=0;i++<NF;){printf "%'$1's\n",$i}}/^$/')

bashを使用してカウントをawkプログラムにスロットするのは問題です。NR==1{N=$0}ブロックで読むよりも小さい。

一度に1行ずつ読み取ります。FPATを使用して、最大4文字のチャンクに分割します。(区切り文字ではなく、フィールドに一致します。GNU拡張。)各フィールドを個別にprintfします。(デフォルトORS = \ n)。

/^$/NF = 0の空行を印刷するためのルールがあり、他のブロックではまったく印刷されません。私の純粋なbashソリューションとは異なり、これは実際に一般的なケースで機能します。

半無関係ですが、perlの私の考えは、perlコードだけで112文字です:

(echo 4; echo -e 'foo\nbar'; echo -e "*\n\\"; echo '~$(true)'; cat /tmp/lines) |  # test input
perl -e '$N=<>;$/=\1;print "$N\n"; while(<>){if(/\n/ or length($l)>=$N){printf("%$4s\n",$l);$l=/\n/?"":$_;}else{$l.=$_;}}'

これは改行の1つを食べ、長すぎます。 $/=\1一度に1バイトを読み取ります。$ lに追加します。おそらく、固定幅の分割アプローチを使用した1行ずつのアプローチはより短くなるでしょう。


1

Bash + GNU utils、41

fold -$1|sed ":;s/^.\{,$[$1-1]\}\$/ &/;t"

文字列はSTDINを介して入力され、幅はコマンドライン引数によって入力されます:

ubuntu@ubuntu:~$ echo 'Programming
Puzzles
&
Code
Golf'|./ralign.sh 10
Programmin
         g
   Puzzles
         &
      Code
      Golf
ubuntu@ubuntu:~$

1

Python 2、151バイト

s,n=input();N='\n'
for w in[i.lstrip()if i.replace(' ','').isalpha()else i for i in s.replace(N,'\n ').split(N)]:
 while w:print w[:n].rjust(n);w=w[n:]

これは、@ xnorが改行を適切に処理しないため、上記の@xnorの回答の適応です。


forループはから変更されました:

for w in s.split('\n'):

に:

for w in[i.lstrip()if i.replace(' ','').isalpha()else i for i in s.replace(N,'\n ').split(N)]:

$ python main.py
"Programming\n\n\nPuzzles\n\n&\n\nCode\nGolf", 5
Progr
ammin
    g


Puzzl
   es

    &

 Code
 Golf

1

C#、143バイト

(s,n)=>Join("\n",s.Split('\n').SelectMany(l=>(l.Any()?l:" ").Select((c,i)=>new{c,i}).GroupBy(o=>o.i/n,o=>o.c).Select(g=>Concat(g).PadLeft(n))))

Linqを使用すると、非常に厄介な表現を作成できます。GroupByここでは便利ですが、インデックスを取得する関数のオーバーロードを作成できなかったのは残念です。

にラムダを割り当てFunc<string, int, string>て実行する

少ないゴルフ:

Func<string, int, string> Align = (s, n) => Join("\n", 
    s.Split('\n')
     .SelectMany(l => (l.Any() ? l : " ")
         .Select((c, i) => new { c, i })
         .GroupBy(o => o.i / n, o => o.c)
         .Select(g => Concat(g).PadLeft(n))));

1

Groovy、63バイト

正しく関連付けられた文字列を返します。これまでpadLeft(およびpadRight、padCenter)関数があることを知りませんでした。

f={s,n->s.split("(?<=\\G.{$n})|\n")*.padLeft(n," ").join("\n")}

1

JavaScript 174 136

function R(s,x){return s.replace(new RegExp(".{"+x+"}","g"),"$&\n").replace(/[^\n]*/g,function(m){
while(m.length<x)m=" "+m;return m;})}


1

Matlab、99バイト

6バイトを削除してくれた@beakerに感謝します!

匿名関数の使用:

@(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0))) 

関数を定義し、ansそれを使用して呼び出します:

>> @(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0)))

ans =

@(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0)))

>> ans(['Programming' 10 'Puzzles' 10 '&' 10 'Code' 10 'Golf'], 5) %% 10 is line feed

ans =

Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf

1

バーレスク、28バイト

以下のバージョンと同じですが、行1を数字として、他の行を文字列として扱います。

lng_riPpun{pPco{pP' lp}mu}Wl

使用方法:

$ cat input.txt | blsq --stdin "lng_riPpun{pPco{pP' lp}mu}Wl"
Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf

旧バージョン(16バイト):

{5co{5' lp}mu}Wl

例:

blsq ) "Programming\nPuzzles\n&\nCode\nGolf"{5co{5' lp}mu}Wl
Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.