Текст праворуч вирівняйте


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 Тут може бути будь-який символ, включаючи пробіли.
Trebuchette

@Timwi: У прикладі є одне слово на рядок. Краще було б включити кілька багатослівних рядків, щоб зрозуміти, що простір у рядку не особливий. (тобто є лише нові, і не нові.)
Пітер Кордес,

Відповіді:



10

Пітон 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

Піта, 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 Я дізнався цю хитрість від чилімагіків, які згадували її у коментарі до іншого виклику .
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

Безголівки:

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зберігає один персонаж, але дозволяє readоб'єднуватись \.

[[ $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
Денніс,

@Dennis: вау, хакс. Дякуємо за посилання Пару цих речей були для мене новими, і я зафіксував пару речей в іншій відповіді :) Я зазвичай не гольф, але> 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 і , отже , не друкують взагалі в іншому блоці. Тож на відміну від мого чисто-баш-рішення, насправді це працює в загальному випадку.

Напівпов'язане, але моя ідея для 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, ширина вводиться аргументом командного рядка:

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Тут корисно, але шкода, що вони не могли створити перевантаження функцій, приймаючи індекс.

Призначте лямбда а, 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

Матлаб, 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.