Richten Sie den Text rechts aus

27

Ihre Aufgabe ist es, eine Zeichenfolge und eine Zahl einzugeben und die Zeichenfolge nach rechts auszurichten, sodass die Breite des Texts der Zahl entspricht. Wenn eine Zeile zu lang ist, brechen Sie sie und setzen Sie den Rest in die nächste Zeile. Wiederholen Sie dies, bis es nicht mehr erforderlich ist. Wenn eine Linie kürzer als die Breite ist, füllen Sie sie mit Leerzeichen auf. Mehrere Zeilenumbrüche können vorkommen und sollten wie jedes andere einzelne Zeichen behandelt werden.

Zum Beispiel die Zeichenfolge

Programming
Puzzles
&
Code
Golf

und die Zahl 5würde ergeben:

Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf

Während die gleiche Zeichenfolge und die Zahl 10erzeugen würde:

Programmin
         g
   Puzzles
         &
      Code
      Golf

Die Saite

a

b

und die Nummer 5 würde ergeben:

    a
      <-- note the 5 spaces
    b

Kürzester Code gewinnt!

Trebuchette
quelle
1
Der Text sagt "Brechen Sie die Zeilen wenn nötig [...]", aber Ihre Beispiele deuten darauf hin, dass Sie nach jedem Wort brechen , auch wenn es passen würde. Bitte klären Sie: Platzieren wir jedes Wort in einer neuen Zeile oder implementieren wir einen tatsächlichen Zeilenumbruch-Algorithmus?
Timwi
Kann es in der Mitte einer Eingabezeile Leerzeichen geben, z Programming Puzzles\n&\nCode Golf.
Sp3000,
@ sp3000 Es kann ein beliebiges Zeichen einschließlich Leerzeichen eingegeben werden.
Trebuchette,
@ Timwi: Das Beispiel hat ein Wort pro Zeile. Es wäre besser gewesen, einige Mehrwortzeilen einzufügen, um zu verdeutlichen, dass der Abstand innerhalb einer Zeile nicht besonders ist. (dh es gibt nur Zeilenvorschübe und keine Zeilenvorschübe.)
Peter Cordes

Antworten:

8

Pyth, 14 Bytes

jm.[\ QdscRQ.z

Demonstration

Verwendet den Pad-Operator von Pyth.

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

Nimmt als Eingabe eine Zeichenfolge mit Zeilenumbrüchen und einer Zahl und druckt das Ergebnis. nNimmt und druckt für jede Zeile in der Eingabe Zeichen auf einmal. Verwenden Sie dabei die integrierte Funktion rjust, um die linke Seite vor dem Drucken mit Leerzeichen zu füllen.

Ich habe die leere Zeile mit dem Hack behoben w=w or' '. Es gibt wahrscheinlich eine bessere Methode, aber ich werde nicht viel darüber nachdenken.

xnor
quelle
8

CJam, 21 Bytes

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

Vielen Dank an @ Sp3000 für das Abschlagen von 1 Byte und den Weg für 3 weitere.

Probieren Sie es online im CJam-Interpreter aus .

Wie es funktioniert

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
quelle
5

Pyth, 16

jm>Q+*\ QdscRQ.z

Probieren Sie es hier online aus

Erläuterung

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
quelle
4

Perl, 39 Bytes

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

36 Bytes + 3 Bytes für -ni. Die Umbruchbreite wird als Argument an übergeben -i.

Behandelt Leerzeilen ordnungsgemäß, indem Leerzeichen eingefügt werden:

$ 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

Wie es funktioniert

Diese Lösung verwendet den Substitutionsoperator, um die Eingabe zu durchlaufen und ein Byte über der entsprechenden forSchleife zu speichern . Der eigentliche Trick liegt jedoch in der Regex auf der linken Seite der Substitution:

^$|.{1,$^I}

Mit dem globalen Modifikator werden die $^IZeichen gleichzeitig abgeglichen. Wenn weniger als $^IZeichen in der Zeichenfolge verbleiben, wird alles bis zum Ende übereinstimmen. Der Wechsel mit^$ ist erforderlich, um Leerzeilen zu verarbeiten. Beispielsweise:

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

Die RHS der Ersetzung wird einfach verwendet, printfum den übereinstimmenden Block mit Leerzeichen zu füllen.

ThisSuitIsBlackNot
quelle
Ich vergesse immer $^I!
Dom Hastings
@DomHastings Ich habe diesen Trick von chilemagic gelernt, der ihn in einem Kommentar zu einer anderen Herausforderung erwähnt hat .
ThisSuitIsBlackNot
3

Javascript (ES6), 107

Ich wünschte, JS hätte eine eingebaute Pad-Funktion. Naja.

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

Erläuterung:

(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
quelle
3

Julia, 126 Bytes

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

Bash, 62 , 61 + Feature, 59

Kürzere, wenn Nvom Anrufer festgelegt werden kann, anstatt es als erste Eingabezeile lesen zu müssen.

# 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

Dies kann leere Zeilen in der Eingabe nicht verarbeiten. Andernfalls werden die Eingabedaten weder einer Wortteilung noch einer Pfadnamenerweiterung unterzogen, noch werden sie auf andere Weise als mehr als nur Rohdaten behandelt.

read -n$NSpeichert ein Zeichen, lässt aber readmunge\ .

Das [[ $r ]]&&wird benötigt, weil read -n4ich nicht voraussehen kann, ob das nächste Zeichen ein Zeilenumbruch ist. Es wird also reine Zeichenfolge mit 4 Zeichen festgelegt, und beim nächsten Lesevorgang wird eine leere Zeichenfolge mit 0 Zeichen erstellt. Das Filtern dieser falschen Zeilenumbrüche ohne das Filtern von echten Zeilenumbrüchen würde den Verfolgungsstatus erfordern: ob die vorherige Zeile die maximale Länge hatte oder nicht. Es wäre entweder mehr Code oder ein völlig anderer Ansatz erforderlich.

[[ $r ]]ist kürzer als [ -n "$r" ]erforderlich, um Fehler zu vermeiden, wenn die Zeile mit -z foooder *oder etwas beginnt , wenn Sie verwendet haben [ $r ].

Die Ausrichtung erfolgt mit der Standard-Formatzeichenfolge printf "% 4s".

Testen Sie mit

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
quelle
1. Ich würde -rin die Byteanzahl einbeziehen. 2. f()(while ... done)ist etwas kürzer.
Dennis
@Dennis: Ohne [[ $r ]]&&, wenn N = 4, erzeugt eine Eingabezeile der Länge 4 eine leere Ausgabezeile, wo vorher keine war. Da readkehrt eine Kette von 4 Zeichen, dann sieht eine neue Zeile auf den nächsten Anruf und sofort kehrt zurück. Danke auch für den ()Tipp. Ich wusste nicht, dass Sie FNS so definieren können.
Peter Cordes
Ich empfehle Tipps zum Golfen in Bash . Es ist eine großartige Ressource.
Dennis
Da whilees bereits zusammengesetzt ist, brauchen Sie nicht einmal die Klammern:f()while ... done
Dennis
@ Tennis: Wow, haxx. Danke für den Link. Ein paar dieser Dinge waren neu für mich und ich habe ein paar Dinge in einer anderen Antwort korrigiert :) Ich spiele normalerweise nicht Golf, aber> 15 Jahre als Kommandozeilen-Junkie haben mir ein oder zwei Dinge beigebracht :)
Peter Cordes
2

Haskell, 108 Bytes

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

Anwendungsbeispiel:

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

    b
   cd
Matam
orpho
  sis

Wie es funktioniert

                              .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
quelle
1

GNU awk + bash, 70

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

Die Verwendung von bash zum Einfügen der Zählung in das awk-Programm ist wahrscheinlich. kleiner als das Lesen mit einem NR==1{N=$0}Block.

Lesen Sie jeweils eine Zeile. Mit FPAT in maximal 4 Zeichenblöcke aufteilen. (Entspricht den Feldern und nicht den Trennzeichen. GNU-Erweiterung.) printf jedes Feld separat. (Standard ORS = \ n).

Die /^$/Regel besteht darin, leere Zeilen zu drucken, die NF = 0 haben und daher im anderen Block überhaupt nicht gedruckt werden. Im Gegensatz zu meiner reinen Bash-Lösung funktioniert dies also im allgemeinen Fall.

Semi-unabhängig, aber meine Idee für Perl ist 112 Zeichen für nur den Perl-Code:

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

Dies frisst eine der Zeilenumbrüche und ist viel zu lang. $/=\1Liest jeweils ein Byte. Wir hängen an $ l an. Wahrscheinlich wäre eine Zeile zu einer Zeit mit einem Split-Ansatz mit fester Breite kürzer.

Peter Cordes
quelle
1

Bash + GNU-Utils, 41

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

String wird über STDIN eingegeben, width wird über das Kommandozeilenargument eingegeben:

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

Python 2, 151 Bytes

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

Dies ist eine Anpassung von @ xnors Antwort oben, da er mit Zeilenumbrüchen nicht richtig umgeht.


Die forSchleife wurde geändert von:

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

zu:

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

Beispiel

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


Puzzl
   es

    &

 Code
 Golf
Zach Gates
quelle
1

C # 143 Bytes

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

Mit Linq können Sie ziemlich knorrige Ausdrücke machen. GroupByist hier nützlich, aber es ist eine Schande, dass sie keine Funktionsüberladungen erzeugen konnten, die den Index übernehmen.

Weisen Sie das Lambda einem Func<string, int, string>zu, um es auszuführen

Weniger golfen:

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
quelle
1

Groovy, 63 Bytes

Gibt die korrekt zugewiesene Zeichenfolge zurück. Wusste bis jetzt nicht, dass es eine Funktion padLeft (und padRight, padCenter) gibt.

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

Matlab, 99 Bytes

Vielen Dank an @beaker für das Entfernen von 6 Bytes!

Verwendung und anonyme Funktion:

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

Definieren Sie die Funktion und verwenden Sie ans, um sie aufzurufen:

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

Burlesque, 28 Bytes

Entspricht der folgenden Version, behandelt jedoch Zeile 1 als Zahl und die anderen Zeilen als Zeichenfolge.

lng_riPpun{pPco{pP' lp}mu}Wl

Verwendung wie in:

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

Alte Version (16 Bytes):

{5co{5' lp}mu}Wl

Beispiel:

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