Выравнивание линий!

31

Выравнивание линий!

Учитывая символ и многострочную строку, ваша задача состоит в том, чтобы заполнить каждую строку строки так, чтобы они располагались среди заданного разделителя.

Примеры

Входные данные:

,
Programming, Puzzles
And, Code golf

Выход:

Programming, Puzzles
        And, Code golf

вход

На входе будет многострочная строка и символ (между которыми вы будете выравнивать), вы можете использовать их в любом порядке / формате. Символ появится ровно один раз в строке. Каждая строка ввода может быть разной длины.

Ввод может быть через аргументы функции или STDIN.

Выход

Выходные данные должны быть одинаковыми по центру строки. Вам разрешен один завершающий символ новой строки и нет пробельных пробелов.

Вывод должен быть дополнен минимальным количеством пробелов. Вы не можете удалять любые начальные пробелы во входных данных (если они существуют).

Выход может быть из функции return или STDOUT.

Downgoat
источник
Может ли вход в полную программу исходить из аргументов командной строки, или это запрещено?
DLosc
@DLosc Да, конечно
Downgoat
1. Для аргументов функции / командной строки, должны ли мы читать одну строку или одна строка на аргумент будет допустимой? 2. Нужно ли заполнять строки минимальным количеством пробелов?
Деннис
@ Денис Вы можете взять его в одну строку. Или одна строка на аргумент. «Вы можете взять их в любом порядке» . Да, вам нужно дополнить строки минимальным количеством пробелов. Я отредактирую спецификацию
Downgoat
@vihan Могут ли функции принимать по одной строке на аргумент?
xnor

Ответы:

13

APL (37)

APL просто не очень хорош в обработке струн (или, конечно, я не очень хорош в гольфе).

{⌽∊R,¨' '/⍨¨(⌈/-+)⍺⍳⍨¨⌽¨R←S⊂⍨S=⊃S←⌽⍵}

Принимает символ в качестве левого аргумента, а многострочную строку - в качестве правого аргумента. Предполагается, что многострочная строка оканчивается переводом строки (например, A\nB\nC\nвместо A\nB\nC.) Поскольку я могу использовать «любой формат [я] желаю», и это также обычный формат для текстовых файлов, я думаю, что это разумно.

Объяснение:

  • S←⌽⍵: перевернуть строку и сохранить ее в S.
  • R←S⊂⍨S=⊃S: разделить Sего на первый символ и сохранить массив строк в R.
  • ⍺⍳¨⌽¨R: перевернуть каждую строку R, а затем найти индекс ⍺ (символа) в каждой строке.
  • (⌈/-+): вычтите каждый из индексов из наибольшего индекса, указав необходимое количество пробелов
  • ' '/⍨¨: для каждого из этих значений сгенерируйте столько пробелов
  • R,¨: добавить пробелы к каждой строке в R.
  • : объединить все строки вместе
  • : отменить (вернуть исходный заказ)

Пример:

      NL←⎕UCS 10 ⍝ newline
      test←'Programming, Puzzles',NL,'And, Code golf',NL
      test ⍝ test string
Programming, Puzzles                
And, Code golf                      

      ⍝ run the function
      +X←','{⌽∊R,¨' '/⍨¨(⌈/-+)⍺⍳⍨¨⌽¨R←S⊂⍨S=⊃S←⌽⍵}test
Programming, Puzzles                        
        And, Code golf                      

      ⍴X ⍝ result is really a string with newlines, not a matrix
44
Мэринус
источник
9

CJam, 23 22 20 байт

Спасибо Деннису за сохранение 2 байта.

ea_rf#_:e>\fm.{S*\N}

Это читает строки из аргументов командной строки и символ из STDIN.

Онлайн-интерпретатор не поддерживает аргументы командной строки, но вы можете проверить эквивалентную версию здесь.

объяснение

ea    e# Get the lines from ARGV.
_rf#  e# Duplicate input, read the character and find index of character in each line.
_:e>  e# Duplicate indices and find maximum.
\fm   e# Subtract each index from the maximum index.
.{    e# Apply this block to each pair of line and (max_index - index).
  S*  e#   Get a string with the right amount of spaces.
  \N  e#   Swap spaces with line and push a line feed.
}
Мартин Эндер
источник
9

Пип , 22 20 18 + 1 = 19 байт

Y_@?qMgsX(MXy)-y.g

Принимает строки в качестве аргументов командной строки и разделителя из STDIN ( идея заимствована из ответа Мартина CJam ). Использует -nфлаг для печати выходных значений в отдельных строках.

                    g is list of cmdline args; s is space (implicit)
    q               Read the delimiter from stdin
 _@?                Construct a lambda function that takes a string and returns
                       the index of the delimiter in it
     Mg             Map that function to each remaining item in g
Y                   Yank the resulting list of indices into the variable y

         (MXy)-y    Take the max of y minus each element in y
       sX           Space, repeated that many times...
                .g  ... concatenated to each item in g
                    Print, newline-separated (implicit, -n flag)

И пример запуска:

C:\Users\dlosc> pip.py -ne Y_@?qMgsX(MXy)-y.g "Programming, Puzzles" "And, Code golf"
,
Programming, Puzzles
        And, Code golf
DLosc
источник
7

JavaScript ES 2015, 113 байт

f=(c,s)=>s.split`
`.map((e,_,a)=>' '.repeat(a.map(j=>j.indexOf(c)).reduce((g,h)=>g>h?g:h)-e.indexOf(c))+e).join`
`

Не так коротко, как языки гольфа, опубликованные до сих пор. Принимает ввод как два аргумента функции, например f(',','Programming, Puzzles\nAnd, Code golf'). Ниже приведен фрагмент кода, в котором есть простой способ проверки.

f=function(c,s){
  return s
    .split('\n')
    .map(function(e,_,a){
      return ' '.repeat(
        a.map(function(f){
          return f.indexOf(c)
        }).reduce(function(g,h){
          return g>h?g:h
        })-e.indexOf(c)
      )+e
    })
    .join('\n')
}

run=function(){document.getElementById('output').innerHTML=f(document.getElementById('char').value,document.getElementById('string').value)};document.getElementById('run').onclick=run;run()
<label>Character: <input type="text" id="char" value="," maxlength="1" /></label>
<textarea id="string" rows="4" cols="30" style="display:block">
Programming, Puzzles
And, Code Golf</textarea><button id="run">Run</button><br />
<pre id="output"></pre>

NinjaBearMonkey
источник
5

Юлия, 117 байт

f(c,t)=(s=[split(l,c)for l=split(t,"\n")];join(map(i->lpad(i[1],maximum(map(i->length(i[1]),s))," ")*c*i[2],s),"\n"))

Ungolfed:

function f(c::String, t::String)
    # Create an array of arrays by splitting on newlines and
    # then on the given delimiter
    s = [split(l, c) for l in split(t, "\n")]

    # Find the maximum length on the left side of the delimiter
    m = maximum(map(i -> length(i[1]), s))

    # Rejoin on the delimiter and pad each line with spaces,
    # and rejoin this with newlines
    join(map(i -> lpad(i[1], m, " ") * d * i[2], s), "\n")
end
Алекс А.
источник
5

Python 3, 85 (IDLE 3.2.2, Windows)

c,*s=input().split('\n')
for x in s:print(' '*(max(z.find(c)for z in s)-x.find(c))+x)

Довольно просто. Это находит положение символа в строке дважды: один раз, чтобы найти максимум (ну, один раз на строку), и один раз, чтобы найти смещение. Я пытался объединить их, но это было дольше.

Python 3 используется для распаковки ввода. Мой IDLE, кажется, принимает многострочные строки в качестве входных данных.

XNOR
источник
@DLosc работает для меня в вставке IDLE в многострочную строку.
xnor
Хм. Когда я это делаю (IDLE 3.3.4, Windows 7), cполучает разделитель и sполучает пустой список. Последующие звонки, чтобы input()вернуть оставшиеся строки одну за другой.
DLosc
@DLosc Странно. Я копирую строку прямо из браузера в строку ожидания. Вы делаете то же самое? IDLE 3.2.2, Windows 7, если это имеет значение.
xnor
Одно и тоже. Вот скриншот ...
DLosc
@DLosc все еще работает для меня ( скриншот ). Хотя я не понимаю, что происходит, я скажу, что это поведение компилятора или среды , и я отредактировал, чтобы попытаться указать соответствующую информацию. Версия функции на 3 символа длиннее в Python 2.
xnor
3

Желе , 12 байт

Ỵ©w€µạṀ⁶ẋż®Y

Попробуйте онлайн!

Совершенно и golfed с Caird coinheringaahing в J Elly Н Yper Т дождь (JHT) , наши Желе практик чат.

Как это работает

Третий аргумент командной строки (первый ввод) должен быть многострочной строкой, а символ должен быть четвертым аргументом командной строки (второй ввод).

W © w € µạṀ⁶ẋż®Y ~ Полная программа.

Sp ~ Разделить строку по новым строкам.
 © ~ Скопируйте результат в реестр.
  w € ~ Получить индекс первого вхождения символа в каждой строке.
      Take ~ Возьми максимум.
    и вычесть его из каждого индекса, взяв абсолютное значение.
       Re ~ Повторите пробел, который много раз (векторизация).
         ż® ~ чередовать с тем, что было сохранено в реестре.
           Y ~ Присоединяйтесь к новым строкам и печатайте неявно.

Я не уверен, разрешено ли использование ввода в качестве списка строк, поэтому в качестве ввода используется многострочная строка. Если бы это было разрешено:

10 байт

w€µạṀ⁶ẋż³Y

Попробуйте онлайн!

Мистер Xcoder
источник
1
вот когда вы знаете, что создали успешную комнату
Эрик Outgolfer
2

Matlab / Octave, 106 байт

Функция, которая использует три отдельных аргумента для символа, строки, строки; и дает результат в стандартный вывод:

function f(c,s,t)
p=find(s==c)-find(t==c);disp([repmat(32,1,max(-p,0)) s]),disp([repmat(32,1,max(p,0)) t])

Пример в Matlab:

>> f(',', 'Programming, Puzzles', 'And, Code golf')
Programming, Puzzles
        And, Code golf

Или попробуйте онлайн с переводчиком Octave.

Луис Мендо
источник
2

Юлия, 80 байт

f(c,s)=(t=split(s,'
');u=[search(i,c)for i=t];join([" "].^(maxabs(u)-u).*t,'
'))

Ungolfed:

function f(c,s)
  # converts multiline string to array of single-line strings
  t=split(s,'\n')

  # creates array of positions of delimiter
  u=[search(i,c)for i=t]

  # Appends appropriate number of spaces to each line
  # (uses elementwise operations to achieve this result)
  v=[" "].^(maxabs(u)-u).*t

  # Recombines array of strings to multiline string and returns
  return join(v,'\n')
end
Глен О
источник
2

JavaScript (ES6), 105

Используя строки шаблона, 2 новых строки значимы и подсчитаны.

Тестовый запуск фрагмента в любом браузере, совместимом с EcmaScript 6 (то есть FireFox. Chrome не поддерживает параметры по умолчанию)

f=(s,c,p=(s=s.split`
`).map(r=>m<(v=r.indexOf(c))?m=v:v,m=0))=>s.map((r,i)=>' '.repeat(m-p[i])+r).join`
`

// Ungolfed
f=(s,c)=>{
  s=s.split('\n')
  p=s.map(r=>r.indexOf(c))
  m=Math.max(...p)
  s=s.map((r,i)=>' '.repeat(m-p[i])+r)
  return s.join('\n')
}  

// TEST
out=x=>O.innerHTML+=x+'\n'

out(f(`Programming, Puzzles
And, Code golf`,','))
<pre id=O></pre>

edc65
источник
2

Python 2, 93 байта

def f(x,y,z):
 p=y.index(x)-z.index(x)
 if p<0:y=" "*abs(p)+y
 else:z=" "*p+z
 print y+'\n'+z

Называется так:

f(',','Programming, Puzzles','And, Code Golf')
Альфа распад
источник
2

C # 4.0, 329 320 307 байт

using System;class P{static void Main(){Func<char,dynamic>f=(d)=>Console.ReadLine().Split(d);var c=f(' ')[0][0];var m=0;var l=new string[9999][];var z=0;for (l[z]=f(c);l[z].Length==2;l[z]=f(c)){m=Math.Max(l[z][0].Length,m);z++;}for(var i=0;i<z;i++){Console.WriteLine("{0,"+m+"}"+c+"{1}",l[i][0],l[i][1]);}}}

Безголовая версия:

using System;
class P
{
    static void Main()
    {
        // lamba to to read a line and split on a char, returns an array of 
        Func<char,dynamic>f=(d)=>Console.ReadLine().Split(d); 
        // read the separator char by taking the first char of the first string 
        // in the array
        // use our lambda
        var c=f(' ')[0][0];
        var m=0; // max position where char is found
        var l=new string[9999][]; // hold all input
        var z=0; // count valid entries in l
        // loop until the input doesn't contain an
        // array with 2 elements
        // here we use our lambda agian, twice
        for (l[z]= f(c);l[z].Length==2;l[z] = f(c))
        {
            // calculate max, based on length 
            // of first element from the string array
            m=Math.Max(l[z][0].Length,m);
            z++; // increase valid items
        }
        // loop over all valid items
        for(var i=0;i<z;i++)
        {
        // use composite formatting with the padding option
        // use the max to create a format string, when max =4 
        // and seperator char is , this will give
        // "{0,4},{1}"
            Console.WriteLine("{0,"+ m +"}"+c+"{1}",l[i][0],l[i][1]);
        }
    }
}

Он принимает максимум 9999 строк ...

Rene
источник
2

Дьялог АПЛ , 22 20 16 байт

-4 благодаря нгн.

APL на самом деле не так уж и плох при обработке строк, если ему разрешено работать с массивами. В этой задаче мы можем выбрать наиболее подходящий формат, который для APL означает вектор текстовых векторов в качестве левого аргумента, а разделитель в качестве скалярного правого аргумента. Это даже обрабатывает несколько разделителей на строку и выравнивает первый из каждой строки.

⊣,¨⍨' '⍴¨⍨⌈.⍳-⍳¨

⊣,¨⍨ добавьте каждую строку с

' '⍴¨⍨ столько пробелов, сколько

⌈.⍳ самый правый индекс символа среди строк

- минус

⍳¨ индекс символа в каждой строке

Попробуйте APL онлайн! ( добавлено для вывода на печать по вертикали)

Бонус? Работает для любого количества строк и разделителей (выравнивается по левому краю).

Адам
источник
⊣,¨⍨' '⍴¨⍨⌈.⍳-⍳¨
нгн
Да, конечно.
Адам
1

С #, 191

Как функция. Примерно портирование моего ответа JS.

using System.Linq;string f(string s,char c){var q=s.Split('\n');int m=0,v;Array.ForEach(q,x=>m=m<(v=x.IndexOf(c))?v:m);return String.Join("\n",q.Select(x=>new String(' ',m-x.IndexOf(c))+x));}
edc65
источник
1

Рубин, 74 байта

l=lambda{|d,s|s.each{|e|puts ' '*(s.map{|f|f.index(d)}.max-e.index(d))+e}}

и называть это как

l.call ',',['Programming, Puzzles','And, Code golf']
golgappa
источник
1

R, 68 байт

function(c,x,y,r=regexpr)cat(x,"\n",rep(" ",r(c,x)-r(c,y)),y,sep="")

Безымянная функция, которая принимает 3входные данные; cкоторый является символом для выравнивания, xявляется первой строкой и yвторой строкой.

В R функция regexprвозвращает позицию данного шаблона в строке. Решение работает с применением regexprобеих строк и повторяющихся пробелов, равных разнице, и впоследствии просто печатает оба ввода, разделенные новой строкой.

Billywob
источник
0

Python 2, 67 66 байт

def a(d,l):
 i=l[0].index(d)
 for e in l:print' '*(i-e.index(d))+e

Вызывается с:

a(',', ['Programming, Puzzles', 'And, Code golf'])
Celeo
источник
0

Moonscript, 138 байт

(n)=>
 i=0
 @='
'..@
 l=[b-a for a,b in @gmatch "
().-()"..n]
 m=math.max unpack l
 (@gsub '
',(a)->
  i=i+1
  a..(' ')\rep m-l[i])\sub(2)

Это возвращает функцию, которая принимает 2 аргумента. Первый - это строка, второй - символ, по которому нужно выровнять. Эти аргументы являются неявным аргументом @ и n.

Сначала я добавляю новую строку в строку, чтобы облегчить обработку.

@='
'..@

Теперь я генерирую список позиций каждого символа выравнивания, используя gmatch. Затем я заменяю новую строку перед каждой строкой на правильное количество пробелов, затем обрезаю новую строку, добавленную в начале.

Райан Рассел
источник
0

Луа, 169 байт

function a(d,t)m={}for k,v in pairs(t)do m[#m+1]=string.find(v,d)end o=math.max(unpack(m))for k,v in pairs(t)do print(string.rep(" ",o-(string.find(v,d)or 0))..v)end end

Не так коротко, как другие ответы, но это мой первый: D

Sygmei
источник
0

Сетчатка , 71 байт

+`^((.)(.*¶)*)((.)*\2.*¶)((?<-5>.)*(?(5)\2|(.)\2).*)
$1$#7$* $4$#5$* $6

Попробуйте онлайн! Примечание: это оставляет символ выравнивания в выводе; его можно удалить по стоимости 4 байта. Если нужно выровнять только две строки, то для 52 байтов:

^(.)¶((.)*\1.*¶)((?<-3>.)*(.)*\1.*)
$#5$* $2$#3$* $4

Объяснение:

^(.)¶

Это соответствует символу выравнивания.

((.)*\1.*¶)

Это соответствует первой строке, а также отслеживает, сколько символов было до символа выравнивания. (.NET сохраняет стек совпадений для каждой переменной, в этом случае $3.)

((?<-3>.)*(.)*\1.*)

Это соответствует второй строке, пытаясь учесть столько символов, сколько мы нашли в первой строке. ?<-3>заставляет совпадение вытолкнуть стек для каждого символа, пока он не станет пустым, и в этот момент совпадение завершится неудачно, а (.)*затем сопоставит оставшиеся символы до символа выравнивания. На данный момент у нас есть следующие переменные:

  • $1 содержит символ выравнивания
  • $2 содержит первую строку
  • $3 содержит стек, длина которого - префикс первой строки минус префикс второй строки
  • $4 содержит вторую строку
  • $5 содержит стек, длина которого - префикс второй строки минус префикс первой строки

$#5$*затем ставит префикс необходимого количества пробелов, чтобы первая строка выровнялась со второй, и наоборот для $#3$*.

Аналогичная логика применима к основному ответу, за исключением того, что здесь мы должны найти две линии, которые не выровнены, чтобы мы могли выровнять их (это то, что нужно ?(5)), а затем повторить выравнивание по всем линиям, пока все они не выровняются ,

Нил
источник
0

Common Lisp, 101 байт

(lambda(c l)(dolist(x l)(format t"~,,v@a~%"(-(apply'max(mapcar(lambda(x)#1=(position c x))l))#1#)x)))

Первый параметр - это символ, второй - список строк для выравнивания.

Попробуйте онлайн!

Renzo
источник