Выровнять текст по правому краю


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: в примере по одному слову в строке. Было бы лучше включить несколько строк из нескольких слов, чтобы было ясно, что пространство внутри строки не является особенным. (то есть есть только переводы строк и не переводы строк.)
Питер Кордес,

Ответы:



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в строке осталось меньше символов, оно будет соответствовать всему концу. Чередование с ^$требуется для обработки пустых строк. Например:

$ 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

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

Баш, 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сохраняет один символ, но позволяет readmunge \.

[[ $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 таким образом.
Питер Кордес

Я рекомендую прочитать Советы по игре в гольф в Баше . Это отличный ресурс.
Деннис

На самом деле, поскольку whileэто уже соединение, вам даже не нужны круглые скобки:f()while ... done
Деннис

@ Денис: вау, хакс. Спасибо за ссылку. Несколько таких вещей были для меня новыми, и я исправил пару вещей в другом ответе :) Обычно я не играю в гольф, но> 15 лет работы в качестве командира командной строки научили меня одной или двум вещам :)
Питер Кордес

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}блоком.

Читайте строки за раз. Разбить не более чем на 4 символа, используя FPAT. (Соответствует полям, а не разделителям. Расширение GNU.) printf каждое поле отдельно. (По умолчанию ORS = \ n).

/^$/Правило там печатать пустые строки, которые имеют NF = 0 и , следовательно , не печатают вообще в другом блоке. Так что, в отличие от моего решения с чистым bash, в общем случае это работает.

Полуотносительно, но моя идея для perl - 112 символов только для кода 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, 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

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 байт

Спасибо @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

Бурлеск, 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.