จัดข้อความชิดขวา


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
ข้อความบอกว่า "แบ่งบรรทัดเมื่อจำเป็น [... ]" แต่ตัวอย่างของคุณแนะนำให้คุณแยกตามทุกคำแม้ว่าจะเหมาะสม โปรดอธิบาย: เราวางคำแต่ละคำในบรรทัดใหม่หรือไม่หรือเราใช้อัลกอริทึมการตัดคำจริงหรือไม่?
Timwi

จะมีช่องว่างอยู่ตรงกลางของบรรทัดอินพุตProgramming Puzzles\n&\nCode Golfหรือไม่?
Sp3000

@ sp3000 อาจมีอักขระใด ๆ ก็ได้รวมถึงช่องว่าง
Trebuchette

@Timwi: ตัวอย่างมีหนึ่งคำต่อบรรทัด คงจะเป็นการดีกว่าถ้าจะรวมหลายบรรทัดหลายคำเพื่อให้ชัดเจนว่าพื้นที่ภายในบรรทัดนั้นไม่พิเศษ (กล่าวคือมีการขึ้นบรรทัดใหม่เท่านั้นและไม่ใช่การขึ้นบรรทัดใหม่)
Peter Cordes

คำตอบ:



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.


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ลูปที่เทียบเท่า เคล็ดลับที่แท้จริงแม้ว่าอยู่ใน regex บน LHS ของการทดแทน:

^$|.{1,$^I}

ด้วยตัวแก้ไขส่วนกลางสิ่งนี้จะจับคู่$^Iอักขระในแต่ละครั้ง เมื่อมีจำนวน$^Iอักขระที่เหลืออยู่ในสตริงน้อยกว่าอักขระนั้นจะจับคู่ทุกอย่างจนจบ ^$จำเป็นต้องมีการสลับกับบรรทัดว่าง ตัวอย่างเช่น:

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

RHS ของการทดแทนนั้นใช้เพียงแค่วางprintfซ้ายอันที่จับคู่กับช่องว่าง


ฉันมักจะลืม$^I!
Dom Hastings

@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

Ungolfed:

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

Bash, 62 , 61 + คุณสมบัติ, 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$Nช่วยประหยัดตัวละครตัวหนึ่ง แต่ช่วยให้Mungeread\

[[ $r ]]&&เป็นสิ่งจำเป็นเพราะread -n4ไม่สามารถ Lookahead จะเห็นว่าถ่านต่อไปคือการขึ้นบรรทัดใหม่ ดังนั้นมันจึงตั้งค่า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 ด้วยวิธีนี้ได้
Peter Cordes

ผมขอแนะนำให้อ่านเคล็ดลับสำหรับการเล่นกอล์ฟในทุบตี มันเป็นทรัพยากรที่ยอดเยี่ยม
เดนนิส

ที่จริงแล้วเนื่องจากwhileมีการรวมกันแล้วคุณไม่จำเป็นต้องใช้วงเล็บ:f()while ... done
Dennis

@Dennis: ว้าว, haxx ขอบคุณสำหรับลิงค์ สองสามสิ่งนั้นเป็นสิ่งใหม่สำหรับฉันและฉันได้แก้ไขบางสิ่งในคำตอบอื่น :) โดยปกติฉันไม่ได้เล่นกอล์ฟ แต่> 15 ปีของการเป็นบรรทัดฐานขี้ยาสอนให้ฉันได้สักสองหรือสองอย่าง :)
ปีเตอร์ 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 to slot การนับเข้าในโปรแกรม awk นั้นเป็นปัญหา เล็กกว่าการอ่านด้วยNR==1{N=$0}บล็อก

อ่านทีละบรรทัด แบ่งออกเป็นส่วน ๆ ได้ไม่เกิน 4 ตัวโดยใช้ FPAT (จับคู่ฟิลด์แทนที่จะเป็นตัวคั่นส่วนขยาย GNU) พิมพ์แต่ละฟิลด์แยกกัน (ค่าเริ่มต้น ORS = \ n)

/^$/กฎจะมีการพิมพ์บรรทัดที่ว่างเปล่าที่มี NF = 0 จึงไม่พิมพ์ที่ทุกคนในบล็อกอื่น ๆ ซึ่งแตกต่างจากวิธีการทุบตีบริสุทธิ์ของฉันนี้ใช้งานได้จริงในกรณีทั่วไป

กึ่งไม่เกี่ยวข้อง แต่ความคิดของฉันสำหรับ perl คือ 112 chars เพียงรหัส 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.=$_;}}'

นี่กินหนึ่งบรรทัดใหม่และยาวเกินไป $/=\1อ่านทีละครั้ง เราผนวกกับ $ l อาจเป็นวิธีการแยกบรรทัดความกว้างคงที่จะสั้นกว่า


1

Bash + GNU utils, 41

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

สตริงคือการป้อนข้อมูลผ่าน STDIN ความกว้างคือการป้อนโดย ARG บรรทัดคำสั่ง:

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 ด้านบนเนื่องจากเขาไม่จัดการกับการขึ้นบรรทัดใหม่


การ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มีประโยชน์ที่นี่ แต่มันเป็นความอัปยศที่พวกเขาไม่สามารถสร้างฟังก์ชั่นโอเวอร์โหลดที่รับดัชนี

มอบหมายแลมบ์ดาให้ a 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

Matlab, 99 ไบต์

ขอบคุณ @beaker สำหรับการลบ 6 ไบต์!

ฟังก์ชั่นการใช้และไม่ระบุชื่อ:

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

Burlesque, 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.