จัดแนวเส้น!


31

จัดแนวเส้น!

ให้ตัวละครและสตริงหลายงานของคุณคือการรองแต่ละบรรทัดของสตริงเพื่อให้พวกเขาเข้าแถวท่ามกลางตัวคั่นที่กำหนด

ตัวอย่าง

การป้อนข้อมูล:

,
Programming, Puzzles
And, Code golf

เอาท์พุท:

Programming, Puzzles
        And, Code golf

อินพุต

การป้อนข้อมูลจะเป็นสตริงหลายบรรทัดและตัวละคร (ซึ่งคุณจะจัดชิด) คุณอาจใช้สิ่งเหล่านี้ในลำดับ / รูปแบบที่คุณต้องการ ตัวละครจะปรากฏขึ้นหนึ่งครั้งต่อบรรทัด แต่ละบรรทัดของอินพุตอาจมีความยาวแตกต่างกัน

อินพุตสามารถผ่านอาร์กิวเมนต์ของฟังก์ชันหรือ STDIN

เอาท์พุต

เอาต์พุตควรเป็นสตริงเดียวกันที่อยู่กึ่งกลาง คุณได้รับอนุญาตให้ขึ้นบรรทัดใหม่หนึ่งบรรทัดและไม่มีช่องว่างต่อท้าย

เอาต์พุตควรถูกเสริมด้วยจำนวนช่องว่างขั้นต่ำ คุณไม่สามารถลบช่องว่างนำหน้าในอินพุต (ถ้ามี)

เอาต์พุตอาจมาจากฟังก์ชันส่งคืนหรือ STDOUT


การป้อนข้อมูลให้กับโปรแกรมเต็มรูปแบบนั้นมาจากอาร์กิวเมนต์บรรทัดคำสั่งหรือไม่นั้นถูกห้าม
DLosc

@DLosc ใช่แน่นอน
Downgoat

1. สำหรับอาร์กิวเมนต์ของฟังก์ชัน / บรรทัดคำสั่งเราควรอ่านสตริงเดี่ยวหรือจะยอมรับหนึ่งบรรทัดต่ออาร์กิวเมนต์ได้หรือไม่ 2. เราต้อง pad เส้นด้วยจำนวนช่องว่างขั้นต่ำหรือไม่?
Dennis

@Dennis คุณสามารถใช้มันในสายเดียว หรือหนึ่งบรรทัดต่ออาร์กิวเมนต์ "คุณอาจจะใช้เวลาเหล่านี้ในลำดับใด ๆ ที่คุณต้องการ" ใช่คุณจำเป็นต้องวางบรรทัดด้วยจำนวนช่องว่างขั้นต่ำ ฉันจะแก้ไขสเป็ค
Downgoat

@vihan สามารถใช้ฟังก์ชันหนึ่งบรรทัดต่ออาร์กิวเมนต์ได้หรือไม่
xnor

คำตอบ:



13

APL (37)

APL ไม่ดีเท่าการประมวลผลสตริง (หรือฉันเล่นกอล์ฟไม่เก่ง)

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

นี่ใช้อักขระเป็นอาร์กิวเมนต์ด้านซ้ายและสตริงหลายบรรทัดเป็นอาร์กิวเมนต์ที่ถูกต้อง มีการสันนิษฐานว่าสตริงหลายบรรทัดสิ้นสุดใน linefeed (เช่นA\nB\nC\nแทนที่จะเป็นA\nB\nC) เนื่องจากฉันสามารถใช้ "รูปแบบใด ๆ [I] ปรารถนา" และนี่ก็เป็นรูปแบบดั้งเดิมสำหรับไฟล์ข้อความฉันคิดว่ามันสมเหตุสมผล

คำอธิบาย:

  • S←⌽⍵: reverse Sสตริงและเก็บไว้ใน
  • R←S⊂⍨S=⊃S: แยกบนตัวอักษรตัวแรกของตนและเก็บอาร์เรย์ของสตริงในSR
  • ⍺⍳¨⌽¨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 bytes

ขอบคุณเดนนิสที่ช่วยประหยัด 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

Pip , 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

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>



5

Julia, 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 ใช้สำหรับการเปิดกล่องรับสัญญาณ MY IDLE ดูเหมือนจะใช้สตริงหลายบรรทัดเป็นอินพุต


@DLosc ใช้งานได้สำหรับฉันใน IDLE การวางในสตริงหลายบรรทัด
xnor

อืมมม เมื่อฉันทำเช่นนั้น (IDLE 3.3.4, Windows 7) cจะได้รับตัวคั่นและsรับรายการว่างเปล่า สายที่ตามมาเพื่อinput()กลับสายที่เหลือทีละหนึ่ง
DLosc

@DLosc แปลก ฉันกำลังคัดลอกสตริงโดยตรงจากเบราว์เซอร์ของฉันไปยังพร้อมท์ Idle คุณทำเช่นเดียวกัน? IDLE 3.2.2, Windows 7 ในกรณีที่เป็นเรื่องสำคัญ
xnor

Same. Here's a screenshot...
DLosc

@DLosc Still works for me (screenshot). Though I don't understand what's going on, I'm going to say this is compiler or environment specific behavior, and I edited to try to specify the relevant info. The function version is 3 chars longer in Python 2.
xnor

3

Jelly, 12 bytes

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

Try it online!

Done and golfed with caird coinheringaahing in Jelly Hyper Training (JHT), our Jelly practice chat room.

How it works

The third command line argument (first input) should be the multi-line string, and the character should be the fourth command line argument (second input).

Ỵ©w€µạṀ⁶ẋż®Y  ~ Full program.

Ỵ             ~ Split the string by newlines.
 ©            ~ Copy the result to the register.
  w€          ~ Get the index of the first occurrence of the character on each line.
      Ṁ       ~ Take the maximum.
    µạ        ~ And subtract it from each index, taking the absolute value.
       ⁶ẋ     ~ Repeat a space that many times (vectorizes).
         ż®   ~ Interleave with what was stored in the register.
           Y  ~ Join by newlines and print implicitly.

I am not sure whether taking input as a list of lines is allowed, so this takes a multiline string as input. If it were allowed:

10 bytes

w€µạṀ⁶ẋż³Y

Try it online!


1
that's when you know you have created a successful room
Erik the Outgolfer

2

Matlab / Octave, 106 bytes

Function that uses three separate arguments for character, string, string; and gives result in stdout:

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

Example in Matlab:

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

Or try it online with Octave interpreter.


2

Julia, 80 bytes

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

Using template strings, the 2 newlines are significant and counted.

Test running the snippet in any EcmaScript 6 compatible browser (that is FireFox. Chrome does not support default parameters)

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>


2

Python 2, 93 bytes

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

Called like so:

f(',','Programming, Puzzles','And, Code Golf')

2

C# 4.0, 329 320 307 bytes

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]);}}}

Ungolfed version :

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]);
        }
    }
}

It does accept a maximum of 9999 lines ...


2

Dyalog APL, 22 20 16 bytes

-4 thanks to ngn.

APL is actually not so bad at string processing, if allowed to work with arrays. In this challenge, we may chose the most appropriate format, which for APL means a vector of text vectors as left argument, and the delimiter as a scalar right argument. This even handles multiple delimiters per line, and aligns the first one of each line.

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

⊣,¨⍨ prepend each line with

' '⍴¨⍨ as many spaces as

⌈.⍳ the rightmost index of the character among the lines

- minus

⍳¨ the index of the character in each line

Try APL online! ( added to print output vertically)

Bonus? Works for any number of strings, and delimiters (aligns by left-most).


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

Yes, of course.
Adám

1

C#, 191

As a function. Roughly a porting of my JS answer.

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));}

1

Ruby, 74 bytes

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

and call it like

l.call ',',['Programming, Puzzles','And, Code golf']

1

R, 68 bytes

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

Unnamed function that takes 3 inputs; c which is the character to align, x is the first string and y the second string.

In R, the function regexpr returns the position of a given pattern in a string. The solution works by applying regexpr on both strings and repeating white spaces amounting to the difference and subsequently just print both inputs separated by a newline.


0

Python 2, 67 66 bytes

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

Called with:

a(',', ['Programming, Puzzles', 'And, Code golf'])

0

Moonscript, 138 bytes

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

This returns a function which takes 2 arguments. The first is the string, the second is the character to align on. These arguments are the implicit argument @, and n.

First, I append a new line to the string, to make processing easier.

@='
'..@

Now, I generate a list of the positions of every alignment character, using gmatch. Next, I replace the newline before every line with the correct number of spaces, then trim the newline I added at the beginning.


0

Lua, 169 bytes

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

Not as short as other answers but this is my first one :D


0

Retina, 71 bytes

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

Try it online! Note: This leaves the alignment character in the output; it can be deleted at a cost of 4 bytes. If only two strings need to be aligned, then for 52 bytes:

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

Explanation:

^(.)¶

This matches the alignment character.

((.)*\1.*¶)

This matches the first line and also keeps track of how many characters there were before the alignment character. (.NET keeps a match stack for each variable, in this case, $3.)

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

This matches the second line, trying to account for as many characters as we found on the first line. ?<-3> causes the match to pop the stack for each character, until it is empty, at which point the match fails, and the (.)* then matches the remaining characters before the alignment character. At this point we have the following variables:

  • $1 contains the alignment character
  • $2 contains the first line
  • $3 contains a stack whose length is the first line prefix minus the second line prefix
  • $4 contains the second line
  • $5 contains a stack whose length is the second line prefix minus the first line prefix

$#5$* then prefixes the necessary number of spaces to make the first line align with the second, and vice versa for $#3$*.

Similar logic applies to the main answer, except here we have to find two lines which don't align so that we can align them (this is where the ?(5) comes in) and then repeat the alignment over all the lines until they are all equally aligned.


0

Common Lisp, 101 bytes

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

The first parameter is the character, the second is a list of string to be aligned.

Try it online!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.