Luruskan teks

27

Tugas Anda adalah mengambil input string dan angka serta menyelaraskan string ke kanan, menjadikan lebar teks sebagai nomor. Ketika garis terlalu panjang, pecahkan dan letakkan sisanya di baris berikutnya, ulangi sampai tidak perlu. Jika garis lebih pendek dari lebarnya, maka balut dengan spasi. Beberapa baris baru dapat muncul, dan harus diperlakukan seperti karakter tunggal lainnya.

Misalnya, string

Programming
Puzzles
&
Code
Golf

dan jumlahnya 5akan menghasilkan:

Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf

Sedangkan string dan nomor yang sama 10akan menghasilkan:

Programmin
         g
   Puzzles
         &
      Code
      Golf

String

a

b

dan angka 5 akan menghasilkan:

    a
      <-- note the 5 spaces
    b

Kode terpendek menang!

Trebuchette
sumber
1
Teks mengatakan "Hancurkan garis bila perlu [...]", tetapi contoh Anda menyarankan agar Anda mengingkari setiap kata, bahkan ketika itu cocok. Harap jelaskan: apakah kita menempatkan setiap kata pada baris baru, atau apakah kita menerapkan algoritma pembungkusan kata yang sebenarnya?
Timwi
Bisakah ada spasi di tengah-tengah jalur input, misalnya Programming Puzzles\n&\nCode Golf?
Sp3000
@ sp3000 Bisa ada karakter apa pun, termasuk spasi.
Trebuchette
@Timwi: Contohnya memiliki satu kata per baris. Akan lebih baik untuk memasukkan beberapa baris multi-kata untuk memperjelas bahwa ruang di dalam sebuah baris tidak spesial. (yaitu hanya ada baris baru, dan non-baris baru.)
Peter Cordes

Jawaban:

8

Pyth, 14 byte

jm.[\ QdscRQ.z

Demonstrasi

Menggunakan operator pad Pyth.

isaacg
sumber
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:]

Dibawa sebagai input string dengan baris baru dan angka, dan mencetak hasilnya. Untuk setiap baris dalam input, ambil dan cetak nkarakter sekaligus, menggunakan built-in rjustuntuk melapisi bagian kiri dengan spasi sebelum mencetak.

Saya memperbaiki kasing kosong dengan retas w=w or' '. Mungkin ada metode yang lebih baik, tetapi saya tidak akan terlalu memikirkannya.

Tidak
sumber
8

CJam, 21 byte

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

Terima kasih kepada @ Sp3000 untuk bermain golf 1 byte dan membuka jalan untuk 3 lebih.

Cobalah online di juru bahasa CJam .

Bagaimana itu bekerja

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.
Dennis
sumber
5

Pyth, 16

jm>Q+*\ QdscRQ.z

Cobalah online di sini

Penjelasan

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
FryAmTheEggman
sumber
4

Perl, 39 byte

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

36 byte + 3 byte untuk -ni. Lebar bungkus dilewatkan sebagai argumen untuk -i.

Tangani garis kosong dengan benar dengan melapisinya dengan spasi:

$ 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

Bagaimana itu bekerja

Solusi ini menggunakan operator substitusi untuk mengulang melalui input, menghemat satu byte di atas forloop yang setara . Trik sebenarnya, bagaimanapun, adalah di regex pada LHS substitusi:

^$|.{1,$^I}

Dengan pengubah global, ini akan cocok dengan $^Ikarakter sekaligus; ketika ada kurang dari $^Ikarakter yang tersisa di string, itu akan cocok dengan semuanya hingga akhir. Pergantian dengan ^$diperlukan untuk menangani garis kosong. Sebagai contoh:

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

RHS dari substitusi hanya digunakan printfuntuk pad kiri-chunk yang cocok dengan spasi.

IniSuitIsBlackNot
sumber
Saya selalu lupa $^I!
Dom Hastings
@HomHastings Saya belajar trik itu dari chilemagic, yang menyebutkannya dalam komentar tentang tantangan lain .
ThisSuitIsBlackNot
3

Javascript (ES6), 107

Saya berharap JS memiliki fungsi pad built-in. Baiklah.

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

Penjelasan:

(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')
DankMemes
sumber
3

Julia, 126 byte

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

Tidak Disatukan:

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
Alex A.
sumber
2

Fitur Bash, 62 , 61+ , 59

Lebih pendek jika Ndapat diatur oleh pemanggil, daripada harus membacanya sebagai baris input pertama.

# 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

Ini gagal menangani garis kosong di input. Jika tidak, ini tidak akan memasukkan data input ke pemisahan kata, perluasan nama path, atau memperlakukannya lebih dari sekadar data mentah.

read -n$Nmenyimpan satu karakter, tetapi memungkinkan readmunge \.

Ini [[ $r ]]&&diperlukan karena read -n4tidak dapat melihat ke depan untuk melihat bahwa arang berikutnya adalah baris baru. Jadi set rke string 4-char, dan pembacaan berikutnya menghasilkan string kosong-char. Memfilter baris baru palsu ini tanpa memfilter baris baru nyata akan memerlukan status pelacakan: apakah baris sebelumnya maks-panjang atau tidak. Diperlukan lebih banyak kode atau pendekatan yang sama sekali berbeda.

[[ $r ]]lebih pendek dari [ -n "$r" ]yang diperlukan untuk menghindari kesalahan jika garis dimulai dengan -z foo, atau apakah *atau sesuatu, jika Anda digunakan [ $r ].

Pembenaran terjadi dengan string format printf "% 4s" standar printf.

Tes dengan

f()(while read -rn$1 r;do [[ $r ]]&&printf %$1s\\n "$r";done); (echo 4; echo -e "*\n\\"; cat /tmp/lines) | f 4
Peter Cordes
sumber
1. Saya akan memasukkan -rdalam hitungan byte. 2. f()(while ... done)sedikit lebih pendek.
Dennis
@ Dennis: Tanpa [[ $r ]]&&, jika N = 4, garis input dengan panjang 4 akan menghasilkan garis output kosong di mana sebelumnya tidak ada. Karena readmengembalikan string 4 karakter, kemudian melihat baris baru pada panggilan berikutnya dan segera kembali. Juga, terima kasih atas ()tipnya. Saya tidak tahu Anda bisa mendefinisikan fns seperti itu.
Peter Cordes
Saya sarankan membaca Tips untuk bermain golf di Bash . Ini sumber yang bagus.
Dennis
Sebenarnya, karena whilesudah majemuk, Anda bahkan tidak perlu tanda kurung:f()while ... done
Dennis
@Dennis: wow, haxx. Terima kasih untuk tautannya. Beberapa hal baru bagi saya, dan saya memperbaiki beberapa hal di jawaban lain :) Saya biasanya tidak bermain golf, tetapi> 15 tahun menjadi pecandu baris perintah telah mengajarkan saya satu atau dua hal :)
Peter Cordes
2

Haskell, 108 byte

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

Contoh penggunaan:

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

    b
   cd
Matam
orpho
  sis

Bagaimana itu bekerja

                              .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
nimi
sumber
1

GNU awk + bash, 70

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

Menggunakan bash untuk memasukkan hitungan ke program awk adalah prob. lebih kecil dari membacanya dengan NR==1{N=$0}blok.

Baca satu baris pada satu waktu. Dibagi menjadi potongan karakter paling banyak, menggunakan FPAT. (cocok dengan bidang, bukan pemisah. Ekstensi GNU.) printf masing-masing bidang secara terpisah. (ORS Default = \ n).

The /^$/Aturan yang ada untuk mencetak baris kosong, yang memiliki NF = 0 dan dengan demikian tidak mencetak sama sekali di blok lain. Jadi tidak seperti solusi murni-bash saya, ini benar-benar berfungsi dalam kasus umum.

Semi-tidak terkait, tapi ide saya sejauh ini untuk perl adalah 112 karakter untuk kode perl:

(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.=$_;}}'

Ini memakan salah satu baris baru, dan terlalu lama. $/=\1membaca satu byte pada satu waktu. Kami menambahkan ke $ l. Mungkin garis-pada-saat-dengan pendekatan split-lebar tetap akan lebih pendek.

Peter Cordes
sumber
1

Utilitas Bash + GNU, 41

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

String adalah input melalui STDIN, lebar adalah input oleh baris perintah arg:

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

Python 2, 151 byte

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

Ini adalah adaptasi dari jawaban xnor di atas, karena ia tidak menangani baris baru dengan benar.


The forLoop diubah dari:

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

untuk:

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

Contoh

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


Puzzl
   es

    &

 Code
 Golf
Zach Gates
sumber
1

C #, 143 byte

(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 memungkinkan Anda membuat ekspresi yang cukup rumit. GroupByberguna di sini, tapi sayang sekali mereka tidak bisa membuat fungsi kelebihan mengambil indeks.

Tetapkan lambda ke a Func<string, int, string>untuk menjalankannya

Kurang bermain golf:

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))));
Carl Walsh
sumber
1

Groovy, 63 byte

Mengembalikan string yang disesuaikan dengan benar. Tidak tahu ada fungsi padLeft (dan padRight, padCenter) sampai sekarang.

f={s,n->s.split("(?<=\\G.{$n})|\n")*.padLeft(n," ").join("\n")}
dbramwell
sumber
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;})}
wolfhammer
sumber
1

Ceylon, 107

String w(String s,Integer n)=>"\n".join{for(l in s.lines)for(p in l.partition(n))String(p).padLeading(n)};
Roland Tepp
sumber
1

Matlab, 99 byte

Terima kasih kepada @beaker karena menghapus 6 byte!

Menggunakan dan fungsi anonim:

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

Tentukan fungsi dan gunakan ansuntuk menyebutnya:

>> @(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
Luis Mendo
sumber
1

Burlesque, 28 Bytes

Sama seperti versi di bawah ini, tetapi memperlakukan baris 1 sebagai angka dan garis lainnya sebagai string.

lng_riPpun{pPco{pP' lp}mu}Wl

Penggunaan seperti pada:

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

Versi Lama (16 byte):

{5co{5' lp}mu}Wl

Contoh:

blsq ) "Programming\nPuzzles\n&\nCode\nGolf"{5co{5' lp}mu}Wl
Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf
mroman
sumber