Wyrównaj tekst do prawej

27

Twoim zadaniem jest pobrać ciąg znaków i liczbę i wyrównać ciąg po prawej stronie, dzięki czemu szerokość tekstu będzie liczbą. Gdy linia jest za długa, przełam ją i umieść resztę w następnej linii, powtarzając, aż nie będzie to konieczne. Jeśli linia jest krótsza niż szerokość, wypełnij ją spacjami. Może wystąpić wiele nowych linii i należy je traktować jak każdy inny pojedynczy znak.

Na przykład ciąg

Programming
Puzzles
&
Code
Golf

a liczba 5wytworzyłaby:

Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf

Podczas gdy ten sam ciąg i liczba 10spowodowałyby:

Programmin
         g
   Puzzles
         &
      Code
      Golf

Ciąg

a

b

a liczba 5 dałaby:

    a
      <-- note the 5 spaces
    b

Najkrótszy kod wygrywa!

Trebuchette
źródło
1
Tekst mówi „Przerwij linie, gdy jest to konieczne [...]”, ale twoje przykłady sugerują, że łamiesz po każdym słowie, nawet jeśli pasowałoby. Wyjaśnij: czy umieszczamy każde słowo w nowym wierszu, czy wdrażamy rzeczywisty algorytm zawijania słów?
Timwi
Czy na środku linii wprowadzania mogą znajdować się spacje, np. Programming Puzzles\n&\nCode Golf?
Sp3000,
@ sp3000 Może być dowolna postać, w tym spacje.
Trebuchette
@Timwi: Przykład zawiera jedno słowo w wierszu. Lepiej byłoby dołączyć kilka wierszy składających się z wielu słów, aby wyjaśnić, że spacja w linii nie jest wyjątkowa. (tzn. są tylko nowe wiersze i nie-nowe wiersze.)
Peter Cordes,

Odpowiedzi:

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

Pobiera na wejściu ciąg znaków z nowymi liniami i liczbą i wypisuje wynik. Dla każdej linii na wejściu pobiera i drukuje nznaki za jednym razem, korzystając z wbudowanej opcji, rjustaby wypełnić lewą spacją przed drukowaniem.

Naprawiłem pustą skrzynkę z linkiem przy użyciu hacka w=w or' '. Prawdopodobnie jest lepsza metoda, ale nie zamierzam o niej dużo myśleć.

xnor
źródło
8

CJam, 21 bajtów

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

Dzięki @ Sp3000 za grę w golfa z 1 bajtem i torowanie drogi dla 3 kolejnych.

Wypróbuj online w interpretatorze CJam .

Jak to działa

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
źródło
5

Pyth, 16 lat

jm>Q+*\ QdscRQ.z

Wypróbuj online tutaj

Wyjaśnienie

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
źródło
4

Perl, 39 bajtów

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

36 bajtów + 3 bajty dla -ni. Szerokość zawijania jest przekazywana jako argument do -i.

Prawidłowo obsługuje puste linie, wypełniając je spacjami:

$ 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

Jak to działa

W tym rozwiązaniu operator zamiany używa pętli do wprowadzania danych, oszczędzając bajt w równoważnej forpętli. Prawdziwa sztuczka polega jednak na wyrażeniu regularnym LHS podstawienia:

^$|.{1,$^I}

W przypadku globalnego modyfikatora dopasuje on $^Iznaki jednocześnie; gdy $^Iw łańcuchu pozostanie mniej niż znaki, dopasuje wszystko do końca. Do ^$obsługi pustych wierszy wymagana jest zmiana z . Na przykład:

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

RHS substytucji po prostu wykorzystuje printflewy pad do dopasowanego fragmentu ze spacjami.

ThisSuitIsBlackNot
źródło
Zawsze o tym zapominam $^I!
Dom Hastings,
@DomHastings Nauczyłem się tej sztuczki od chilemagic, który wspomniał o niej w komentarzu do innego wyzwania .
ThisSuitIsBlackNot
3

JavaScript (ES6), 107

Chciałbym, żeby JS miał wbudowaną funkcję pada. No cóż.

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

Wyjaśnienie:

(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
źródło
3

Julia, 126 bajtów

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

Nie golfowany:

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.
źródło
2

Bash, 62 , 61 + funkcja, 59

Krótszy, jeśli Ndzwoniący może go ustawić, zamiast czytać go jako pierwszy wiersz wprowadzania.

# 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

To nie obsługuje pustych linii na wejściu. W przeciwnym razie nie spowoduje to podziału danych wejściowych na dzielenie słów, rozwijanie nazw ścieżek ani w żaden inny sposób nie potraktuje ich jako więcej niż surowych danych.

read -n$Nratuje jedną postać, ale pozwala readmunge \.

Jest [[ $r ]]&&to potrzebne, ponieważ read -n4nie mogę się doczekać, aby zobaczyć, że następny znak jest nową linią. Więc ustawia rna 4-znakowy ciąg, a następny odczyt tworzy pusty ciąg o zerowym znaku. Filtrowanie tych fałszywych nowych linii bez filtrowania prawdziwych nowych linii wymagałoby stanu śledzenia: czy poprzednia linia miała maksymalną długość, czy nie. Potrzebny byłby więcej kodu lub zupełnie inne podejście.

[[ $r ]]jest krótszy niż [ -n "$r" ]jest to konieczne, aby uniknąć błędów, jeśli linia zaczyna się od -z foo, jest *lub jest czymś, jeśli użyłeś [ $r ].

Występuje uzasadnienie ze standardowym ciągiem formatu „% 4s” printf.

Przetestuj za pomocą

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
źródło
1. Chciałbym uwzględnić -rw liczbie bajtów. 2. f()(while ... done)jest nieco krótszy.
Dennis
@Dennis: Bez [[ $r ]]&&, jeśli N = 4, linia wejściowa o długości 4 wytworzy pustą linię wyjściową, w której wcześniej jej nie było. Ponieważ readzwraca ciąg 4 znaków, następnie widzi nową linię przy następnym wywołaniu i natychmiast wraca. Dziękuję również za ()wskazówkę. Nie wiedziałem, że możesz w ten sposób zdefiniować fns.
Peter Cordes,
Polecam przeczytać Porady dotyczące gry w golfa w Bash . To świetny zasób.
Dennis
W rzeczywistości, ponieważ whilejest już złożony, nie potrzebujesz nawet nawiasów:f()while ... done
Dennis
@Dennis: wow, haxx. Dzięki za link. Kilka z tych rzeczy było dla mnie nowych, a kilka rzeczy naprawiłem w innej odpowiedzi :) Zwykle nie gram w golfa, ale> 15 lat bycia ćpunem z wiersza poleceń nauczyło mnie kilku rzeczy :)
Peter Cordes
2

Haskell, 108 bajtów

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

Przykład użycia:

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

    b
   cd
Matam
orpho
  sis

Jak to działa

                              .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
źródło
1

GNU awk + bash, 70

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

Używanie bash do umieszczania licznika w programie awk to prob. mniejszy niż czytanie za pomocą NR==1{N=$0}bloku.

Czytaj linię na raz. Podziel na maksymalnie 4 części, używając FPAT. (dopasowuje pola, a nie separatory. Rozszerzenie GNU.) printf każde pole osobno. (Domyślne ORS = \ n).

/^$/Reguła ma drukować pustych wierszy, które mają NF = 0, a zatem nie drukuje w ogóle w innym bloku. W przeciwieństwie do mojego rozwiązania typu pure-bash, tak naprawdę działa to w ogólnym przypadku.

Częściowo niepowiązane, ale jak dotąd mój pomysł na perla to 112 znaków tylko dla kodu perla:

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

To zjada jedną z nowych linii i jest zdecydowanie za długie. $/=\1odczytuje bajt na raz. Dołączamy do $ l. Prawdopodobnie linia po linii z podziałem na ustaloną szerokość byłaby krótsza.

Peter Cordes
źródło
1

Narzędzia Bash + GNU, 41

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

Łańcuch jest wprowadzany przez STDIN, szerokość jest wprowadzana przez arg wiersza poleceń:

ubuntu@ubuntu:~$ echo 'Programming
Puzzles
&
Code
Golf'|./ralign.sh 10
Programmin
         g
   Puzzles
         &
      Code
      Golf
ubuntu@ubuntu:~$
Cyfrowa trauma
źródło
1

Python 2, 151 bajtów

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

Jest to adaptacja powyższej odpowiedzi @ xnor, ponieważ jego nie obsługuje poprawnie nowych linii.


forPętla została zmieniona z:

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

do:

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

Przykład

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


Puzzl
   es

    &

 Code
 Golf
Zach Gates
źródło
1

C #, 143 bajty

(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 pozwala tworzyć dość surowe wyrażenia. GroupByprzydaje się tutaj, ale szkoda, że ​​nie mogli stworzyć przeciążenia funkcji biorąc indeks.

Przypisz lambda do a, Func<string, int, string>aby go uruchomić

Mniej golfa:

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
źródło
1

Groovy, 63 bajty

Zwraca poprawnie wyrównany ciąg. Nie wiedziałem, że do tej pory była funkcja padLeft (i padRight, padCenter).

f={s,n->s.split("(?<=\\G.{$n})|\n")*.padLeft(n," ").join("\n")}
dbramwell
źródło
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
źródło
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
źródło
1

Matlab, 99 bajtów

Dzięki @beaker za usunięcie 6 bajtów!

Korzystanie i anonimowa funkcja:

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

Zdefiniuj funkcję i użyj, ansaby ją wywołać:

>> @(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
źródło
1

Burleska, 28 bajtów

Taka sama jak w poniższej wersji, ale traktuje linię 1 jako liczbę, a pozostałe linie jako ciąg.

lng_riPpun{pPco{pP' lp}mu}Wl

Zastosowanie jak w:

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

Stara wersja (16 bajtów):

{5co{5' lp}mu}Wl

Przykład:

blsq ) "Programming\nPuzzles\n&\nCode\nGolf"{5co{5' lp}mu}Wl
Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf
mroman
źródło