49
\$\begingroup\$

Given an input of a list of words, output the words with their letters arranged diagonally:

p
 r
  o
p  g
 u  r
  z  a
a  z  m
 n  l  m
  d  e  i
c     s  n
 o        g
  d
g  e
 o
  l
   f

(The above should be the output for the input programming puzzles and code golf.)

To be precise, each word starts on the first column and three rows below the previous word, and each successive letter moves one column to the right and one row down.

The input may be provided as either a single string of words, separated by exactly one space, or a list/array of words. The words will only be composed of lowercase letters, a-z, and will always be at least one character long.

The output may be a single string, an array of lines, or an array of arrays of characters. Leading or trailing whitespace is not allowed, except for a single trailing newline.

Further test cases:

a bcd efgh i j

a


b
 c
  d
e
 f
  g
i  h


j

x

x

verylongword short

v
 e
  r
s  y
 h  l
  o  o
   r  n
    t  g
        w
         o
          r
           d

Since this is , the shortest code in bytes will win!

\$\endgroup\$
3
  • \$\begingroup\$ I feel like I should be able to make a Python program for this in 5 minutes, but it always seems to be failing... ;_; \$\endgroup\$
    – hyper-neutrino
    Nov 14, 2016 at 3:58
  • \$\begingroup\$ Wow, it seems like there are a lot of challenges seemingly designed for Turtlèd \$\endgroup\$ Nov 15, 2016 at 1:01
  • \$\begingroup\$ Are terminal escape codes allowed? :) \$\endgroup\$
    – Chromium
    Jun 28, 2018 at 9:30

19 Answers 19

18
\$\begingroup\$

Vim, 85, 76, 66, 52 keystrokes/bytes

When I first looked at this challenge, I thought "This is perfect for vim!" And then when I tried it everything went wrong. Here it is, in all of it's messy hacky glory:

:se ve=all|s/ /\r\r\r/g
qqGo<esc>?\<.\S
lDjP@qq@qG?.
jdG

Try it online, thanks to the (mostly) backwards compatible V interpreter.

Explanation:

At first I thought I could do this beautifully simple 37 byte version:

:se ve=all
qq:g/\S\S/norm ^lDjP
@qq@q

Unfortunately, it's not that simple. Let's take it line by line:

:se ve=all

This enables a feature called 'virtual editing'. It allows the cursor to move to columns that don't exist yet. This answer would be basically impossible without it.

Now we need to separate out the words onto different lines. So we'll replace each space with 3 newlines. Since this is an ex command we can run it simultaneously with our last ex command :se ve=all by seperating the two with a bar.

|s/ /\r\r\r/g

Now the buffer looks like this:

Programming


Puzzles


and


code-golf

Here's where the fun begins. We set up the traditional recursive macro with: qq, and then call this:

G               " Move to the last line
 o<esc>         " Append an extra newline

?               " Search backwards for
 \<.            " Any character at the beginning of a word
    \S          " Followed by a non-space character
l               " Move one character to the right
 D              " Delete eveything until the end of this line
  j             " Move down one line
   P            " Paste what we just deleted

Then we finish the recursive macro with @qq@q. At this point, we have all of the diagonals, we just need to do a little clean up.

G                   " Move to the last line
 ?.                 " Search backwards for any character
j                   " Move down one line
 dG                 " Delete until the end of the buffer
\$\endgroup\$
2
  • \$\begingroup\$ Wow, JavaScript is (currently) shorter than Vim. That's quite a rare occurence these days... \$\endgroup\$ Nov 14, 2016 at 2:30
  • \$\begingroup\$ @ETHproductions Not any more. :) \$\endgroup\$
    – DJMcMayhem
    Nov 14, 2016 at 3:04
7
\$\begingroup\$

Turtlèd, 28 26 bytes

Oh my, I appear to be beating a language specifically designed for golfing. this is a great day.

!_4[*.[ rd+.]ul[ ul]r;_+]_

Try it online!

Explanation

(write means writing to the cell on the grid, pointed char means char in input the string pointer points to)

!                         Take string input into variable
 _                        Normally conditional, with >1 input (there will be), write ' '
  4                       set register to 4
   [*                   ] until the current cell is *
     .                    Write pointed char, initially first char
      [     ]             Until space is written on cell
        rd+.              move right, down, string pointer++, write pointed char
             ul[ ul]      Move back up to the top of the word
                    r;    Move right, down 4 (because this is register value)
                      _+  write * if end of input, else ' ', increment string pointer
                        _ will always write ' ', since it will always point at start char

note trailing space.

Input also needs trailing space. seeing as python can take a list, this is a lot like taking a list in Turtlèd

\$\endgroup\$
6
\$\begingroup\$

MATL, 28 bytes

c!t&n:q3_*ts_b+5M4$XdZ!cZ{Zv

Input is a cell array of strings, with commas as optional separators:

{'programming' 'puzzles' 'and' 'code' 'golf'}

or

{'programming', 'puzzles', 'and', 'code', 'golf'}

Try it online! Or verify all test cases: 1, 2, 3, 4.

Explanation

Consider the following input as an example:

{'aaaa' 'bb' 'ccc'}

You can view the partial results (stack contents) inserting the comment symbol % at any point in the code. For example, view the stack contents after the fourth function (&n).

c        % Input cell array of strings implicitly. Convert to 2D char array,
         % right-padding with spaces
         % STACK: ['aaaa'; 'bb  '; 'ccc']
!        % Transpose
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  ']
t        % Duplicate
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  '],
                  ['abc'
                   'abc'
                   'a c'
                   'a  '],
&n       % Number of rows and of columns
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  '], 4, 3
:q       % Range, subtract 1
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  '], 4, [0 1 2]
3_*      % Multiply by -3
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  '], 4, [0 -3 -6]
ts_      % Duplicate, sum, negate
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  '], 4, [0 -3 -6], 9
b        % Bubble up in stack
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  '], [0 -3 -6], 9, 4
+        % Add
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  '], [0 -3 -6], 13
5M       % Push second input of last function again
         % STACK: ['abc'
                   'abc'
                   'a c'
                   'a  '], [0 -3 -6], 13, 4
4$Xd     % Buld numerical sparse matrix from the above four arguments. The
         % columns of the first input argument will be the diagonals of the
         % result, with indices given bu the second input (negative is below
         % main diagonal). The matrix size is the third and fourth arguments
         % STACK: [97  0  0  0
                    0 97  0  0
                    0  0 97  0
                   98  0  0 97
                    0 98  0  0
                    0  0 32  0
                   99  0  0 32
                    0 99  0  0
                    0  0 99  0
                    0  0  0 32
                    0  0  0  0
                    0  0  0  0
                    0  0  0  0]
Z!c      % Convert from sparse to full, and then to char. Character 0 is
         % displayed as space
         % STACK: ['a   '
                   ' a  '
                   '  a '
                   'b  a'
                   ' b  '
                   '    '
                   'c   '
                   ' c  '
                   '  c '
                   '    '
                   '    '
                   '    '
                   '    ']
Z{       % Split into cell array, with each row in a cell
         % STACK: {'a   ', ' a  ', '  a ', 'b  a', ' b  ', '    ', 'c   ', ' c  ', '  c ', '   ', '   ', '   ', '   '}
Zv       % Deblank: remove trailing space from each string. Implicitly display,
         % each string on a different line. Empty strings do not generate
         % a newline
         % STACK: {'a   ', ' a', '  a', 'b  a', ' b', '', 'c', ' c', '  c', '', '', '', ''}
\$\endgroup\$
0
5
\$\begingroup\$

JavaScript (ES6), 118 109 84 bytes

Takes input as an array of words. Returns an array of arrays of characters.

s=>s.map((w,y)=>[...w].map((c,x)=>(a[p=y*3+x]=a[p]||Array(x).fill(' '))[x]=c),a=[])&&a

Alternative version, 109 bytes

Returns a string.

let f =

s=>s.map((w,y)=>[...w].map((c,x)=>(a[p=y*3+x]=a[p]||Array(x).fill` `)[x]=c),a=[])&&a.map(s=>s.join``).join`
`

console.log(f(["programming", "puzzles", "and", "code", "golf"]))

\$\endgroup\$
0
4
\$\begingroup\$

Japt -Rx, 17 16 13 bytes

Takes input as an array of words. If trailing whitespace on each line were allowed then the last 4 characters could be removed to tie with the Charcoal solution.

yÈmú3)iYçÃmx1

Try it or run all test cases


Explanation

y                 :Transpose
 È                :Map each word at 0-based index Y
  m               :  Map each character
   ú3             :    Right pad with spaces to length 3
     )            :  End mapping
      i           :  Prepend
       Yç         :   Space repeated Y times
         Ã        :End mapping and transpose
          m       :Map
           x1     :  Trim right
                  :Implicitly join with newlines, trim and output
\$\endgroup\$
3
\$\begingroup\$

Common Lisp, 673 668 597 bytes

Terrible solution, I know. I'll probably edit this more after some sleep.

(defun f(&rest z)(let((l)(a 0)(s)(o)(b)(c 0))(loop(setf b(length l))(setf l"")(loop for w in z for i from 0 do(if(>(+(length w)(* i 3))c)(setf c(+(length w)(* i 3))))(setf s(+(* i -3)a))(when(and(>= s 0)(< s(length w)))(setf o(format nil"~v@{~a~:*~}"s" "))(if(and(>=(- s 3)0)(not(equal i(-(length z)1))))(setf o(subseq o(- s 2))))(setf l(concatenate'string o(string(char w s))l)))(when(>= s(length w))(setf l(concatenate'string"   "l))))(if(<=(length l)b)(setf l(concatenate'string(format nil"~v@{~a~:*~}"(- b(length l)-1)" ")l)))(print(string-right-trim" "l))(if(>= b c)(return))(setf a(1+ a)))))

Usage:

* (f "ppcg" "is" "pretty" "ok")

"p" 
" p" 
"  c" 
"i  g" 
" s" 
"" 
"p" 
" r" 
"  e" 
"o  t" 
" k  t" 
"     y" 
""
NIL

This loops over every word in the provided list and adds appropriate characters to the current line. Appropriate padding is provided by my subpar usage of format.

Note: I'm new to Common Lisp, but I know enough to realize that this could use a lot of improvement.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ >:( "ppcg ... ok"!? \$\endgroup\$ Dec 3, 2016 at 13:47
3
\$\begingroup\$

C#, 336 Bytes:

Golfed:

string D(string[]s){int x=0,y=0,r=0,q=2*(s.Max().Length+s.Length)+1;var a=new char[q, q];for(int i=0;i<s.Length;i++){y=r;for(int j=0;j<s[i].Length;j++){a[y,x]=s[i][j];x+=1;y+=1;}x=0;r+=3;}var o="";for(x=0;x<q;x++){var t="";for(y=0;y<q;y++)t+=a[x,y];o+=t==string.Join("",Enumerable.Repeat('\0',q))?"":(t.TrimEnd('\0')+"\r\n");}return o;}

Ungolfed:

public string D(string[] s)
{
  int x = 0, y = 0, r = 0, q = 2 * (s.Max().Length + s.Length) + 1;
  var a = new char[q, q];
  for (int i = 0; i < s.Length; i++)
  {
    y = r;
    for (int j = 0; j < s[i].Length; j++)
    {
      a[y, x] = s[i][j];
      x += 1;
      y += 1;
    }
    x = 0;
    r +=3;
  }
  var o = "";
  for (x = 0; x < q; x++)
  {
    var t = "";
    for (y = 0; y < q; y++)
      t += a[x, y];
    o += t == string.Join("", Enumerable.Repeat('\0', q)) ? "" : (t.TrimEnd('\0') + "\r\n");
  }
  return o;
}

Testing:

  var codeGolf = new DrawDiagonalLinesOfText();
  Console.WriteLine(codeGolf.E(new string[] { "programming", "puzzles", "and", "code", "golf" }));
  Console.WriteLine(codeGolf.E(new string[] { "a", "bcd", "efgh", "i", "j" }));
  Console.WriteLine(codeGolf.E(new string[] { "verylongword", "short" }));

p
 r
  o
p  g
 u  r
  z  a
a  z  m
 n  l  m
  d  e  i
c     s  n
 o        g
  d
g  e
 o
  l
   f


a
b
 c
  d
e
 f
  g
i  h
j


v
 e
  r
s  y
 h  l
  o  o
   r  n
    t  g
        w
         o
          r
           d
\$\endgroup\$
5
  • \$\begingroup\$ This appears to output trailing whitespace at the ends of lines, which is not allowed by the challenge specification. Also, requiring strings of spaces to separate the words in the input array is not an allowed input format. \$\endgroup\$
    – Doorknob
    Nov 15, 2016 at 1:12
  • \$\begingroup\$ @Doorknob Oops, sorry... Fixed, only cost me 2 Bytes :) \$\endgroup\$
    – Pete Arden
    Nov 15, 2016 at 8:36
  • 1
    \$\begingroup\$ Compile to a Func<string[], string> and make various other changes for 297 bytes s=>{int i=0,x=0,y=0,r=0,l=s.Length,q=2*(s.Max().Length+l)+1,j;var a=new char[q,q];for(;i<l;i++){y=r;for(j=0;j<s[i].Length;)a[y++,x++]=s[i][j++];x=0;r+=3;}var o="";for(;x<q;x++){var t="";for(y=0;y<q;)t+=a[x,y++];o+=t==string.Join("",Enumerable.Repeat('\0',q))?"":(t.TrimEnd('\0')+"\n");}return o;}; however you need to add 18 bytes for using System.Linq; \$\endgroup\$ Nov 15, 2016 at 11:06
  • \$\begingroup\$ @TheLethalCoder Thanks, but I don't really want to take your entire solution :) \$\endgroup\$
    – Pete Arden
    Nov 15, 2016 at 11:49
  • \$\begingroup\$ It's not mine its yours I just golfed some of the stuff away i.e. moving thwe i and j to the int declaration at the top and moving some of the ++ so they are used on the last use of the variable \$\endgroup\$ Nov 15, 2016 at 11:53
3
\$\begingroup\$

Python 2, 146 bytes

s=input()
k=max(map(len,s))
a=[k*[' ']for x in range(k+len(s)*3+3)]
for x in range(len(s)):
 for y in range(len(s[x])):a[x*3+y][y]=s[x][y]
print a

Note: the indentations for the last two lines are <space> and <tab>, which saves one byte since I don't need to double-indent.

Input is to be entered as an array of strings like so: ["hello", "world"] or ['hello', 'world']. Output is an array of arrays of characters.

There's probably a better way to do this...

EDIT Thanks to Doorknob for pointing out a missing close square bracket. I placed it before the *k... in the third line.

\$\endgroup\$
4
  • \$\begingroup\$ There's a syntax error in your code on the third line; there's two open brackets but only one close bracket. However I fix it (either by adding an extra closing bracket or removing the extra opening bracket), the program gives an error when run. \$\endgroup\$
    – Doorknob
    Nov 15, 2016 at 1:10
  • \$\begingroup\$ This now appears to output trailing whitespace at the ends of lines and at the end of the output, which is not allowed by the challenge specification. \$\endgroup\$
    – Doorknob
    Nov 16, 2016 at 3:57
  • \$\begingroup\$ trivial golfs \$\endgroup\$
    – Leaky Nun
    Jun 23, 2017 at 16:58
  • \$\begingroup\$ @LeakyNun Thanks. Are you just going through and golfing all of my answers? :P \$\endgroup\$
    – hyper-neutrino
    Jun 23, 2017 at 17:04
3
\$\begingroup\$

Charcoal, 18 11 bytes

16 9 bytes if trailing whitespaces were allowed: try it online.

UTWS«P↘ιM³↓

My first Charcoal answer. Thanks to @DLosc for suggestion and instead of using and (Jump) to go back to the start of the line (and three down).

Try it online (verbose) or Try it online (pure).

Explanation:

Disable trailing spaces in the output:

ToggleTrim();
UT

Loop while there is still a next input-string:

While(InputString()){ ... }
WS« ...

Print this string without moving the cursor in a down-right direction:

Multiprint(:DownRight, i);
P↘ι

And then move three positions down for the next iteration:

Move(3, :Down);
M³↓
\$\endgroup\$
5
  • \$\begingroup\$ When the challenge needs a single input consisting of an array, Charcoal fails as it splits the input string taking every single word as a separate input. But in Charcoal the θ variable represents the first input, so I just assign the test input to that variable in the header and then write the rest of the code, so you can get rid of the α variable and iterate over the splitted items of θ. Try it online! (Non-competing due to leading spaces.) \$\endgroup\$
    – Charlie
    Jun 30, 2017 at 10:30
  • \$\begingroup\$ At least, nobody complained when I used that trick here. :-) \$\endgroup\$
    – Charlie
    Jun 30, 2017 at 10:34
  • \$\begingroup\$ @CarlosAlejo I indeed came across your answer when I was looking for inspiration on existing Charcoal answers. :) \$\endgroup\$ Jun 30, 2017 at 10:41
  • \$\begingroup\$ IDK, the method I usually use is just strings + empty string at the end, if any are multiline then input as a python array \$\endgroup\$
    – ASCII-only
    Jul 27, 2017 at 2:36
  • \$\begingroup\$ @CarlosAlejo It's been a while, but I've just used multiple lines now with an empty line to break the while (and golfed 7 bytes at the same time). Saw it being used in one of Neil's answers, and I now see ASCII-only suggested the same thing (somehow missed that comment). \$\endgroup\$ Aug 14, 2017 at 14:47
3
\$\begingroup\$

Vyxal, 21 bytes

ʁ2꘍∑374f?vLz4jø^↵vøR⁋

Try it Online!

              ø^      # Using the canvas, draw...
ʁ                     # Text: Palindromise each
 2꘍                   # Append two spaces to each
   ∑                  # Concatenate into a single string
    374f              # Directions: [3, 7, 4] - down-left, up-right, down
        ?vL           # Lengths: Lengths of each word in input
           z          # Zip with self
            4j        # Join with 4s
                ↵vøR⁋ # Strip trailing whitespace (ugh)
\$\endgroup\$
1
  • \$\begingroup\$ "Leading or trailing whitespace is not allowed, except for a single trailing newline." \$\endgroup\$ Nov 30, 2022 at 11:41
2
\$\begingroup\$

q/kdb+, 130 109 94 90 86 84 bytes

Solution:

f:{-1(+)a rtrim(til(#)E){raze(x#" "),y,\:"  "}'E:(+)(a:{(max(#:)each x)$x})" "vs x;}

Examples:

q)f "programming puzzles and code golf"
p          
 r         
  o        
p  g       
 u  r      
  z  a     
a  z  m    
 n  l  m   
  d  e  i  
c     s  n 
 o        g
  d        
g  e       
 o         
  l        
   f 
q)f "a bcd efgh i j"
a   


b   
 c  
  d 
e   
 f  
  g 
i  h


j  
q)f (),"x"
x
q)f "verylongword short"
v           
 e          
  r         
s  y        
 h  l       
  o  o      
   r  n     
    t  g    
        w   
         o  
          r 
           d

Explanation (ungolfed):

The basic gist is to create a bunch of equal length strings from the input string, flip (rotate) them, then add appropriate whitespace to get something that looks like this:

"p  p  a  c  g   "
" r  u  n  o  o  "
"  o  z  d  d  l "
"   g  z     e  f"
"    r  l        "
"     a  e       "
"      m  s      "
"       m        "
"        i       "
"         n      "
"          g     "

which is flipped again, and printed to stdout.

Here's a line-by-line breakdown of the concept:

A:"programming puzzles and code golf"; // original input
B:" " vs A;                            // split on " "
C:max count each B;                    // find length of the longest string
D:C$B;                                 // pad each string to this length
E:flip D;                              // flip (rotate) string
F:{raze(x#" "),y,\:"  "};              // appends each char with "  " and prepends an increasing number of " "
G:(til count E)F'E;                    // execute function F with each pair of 0..n and item in list E
H:max count each rtrim G;              // find longest string (ignoring right whitespace)
I:H$G;                                 // pad each of the strings to this length
J:flip I;                              // flip to get result
-1 J;                                  // print to stdout, swallow return value

Notes:

A few ways to shave off some (11) easy bytes if we really wanted to:

  • Could save 2 bytes by dropping the f: and leaving as an anonymous function
  • Could save 3 bytes by dropping the -1 and ; and returning a list of strings rather than printing to stdout
  • Could save 6 bytes if we passed in a list of strings rather than space-separated string

Edits:

  • -11 bytes, use rtrim to find max length to pad, removed need for storing C variable
  • -15 bytes, switching out the max count each for a lambda function a which is created once and used twice
  • -4 bytes, moving the raze into the lambda function to save a raze each
  • -4 bytes, simplified the core lambda function that adds the whitespace
  • -2 bytes, use (+) as shorthand for flip
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 146 bytes

P=PadRight;T=Transpose;R=Riffle;Select[Rest@T@P@MapIndexed[""~Table~#2~Join~#1&,T@P@R[Characters/@#~R~{},{},3]]//.{0->"",{x__,""}->{x}},#!={""}&]&

I'm disappointed by this bytecount, but oh well.

Defines an anonymous function that takes a list of words (e.g. {"this","that","these"}) and returns a two-dimensional array of characters. To view in grid form, add a //Grid at the end.

Converts the strings to an array, adds extra lines, transposes the array, prepends the necessary shifts, then transposes again.

Example result (formatted as grid): Example result

\$\endgroup\$
0
1
\$\begingroup\$

Jelly, 24 bytes

z⁶j€⁾  µJ’⁶ẋ;"z⁶œr€⁶Yœr⁷

Try it online!

How?

z⁶j€⁾  µJ’⁶ẋ;"z⁶œr€⁶Yœr⁷ - Main link: a list of strings
z                        - transpose with filler...
 ⁶                       -     space character
  j€                     - join €ach with
    ⁾                    -     two spaces
       µ                 - monadic chain separation, call the result x
        J                - range(length(x)) [1,2,...,x]
         ’               - decrement (vectorises) [0,1,...x-1]
           ẋ             - repeat (vectorises)
          ⁶              - a space ['', ' ',...,'x spaces']
             "           - zip with
            ;            - concatenation (prefixes with the space strings)
              z          - transpose with filler...
               ⁶         -     space character
                œr€⁶     - trim spaces from the right of €ach
                    Y    - join with line feeds
                     œr⁷ - trim line feeds from the right
                         - implicit print
\$\endgroup\$
1
\$\begingroup\$

Python 2, 182 bytes

def f(s):
 M=max(map(len,s));p=' '*M;L=[p]+s+M*[p];r='';k=0
 while k/M<len(s)*3+M:
  i=k%M;w=k/M-i+1;r+=(L[(w/3+1)*(w%3==1)]+p)[i];k+=1
  if i==M-1:r=r.rstrip()+'\n'
 return r.strip()

A bit long, but on the positive side, it returns a string with no trailing white space on each line, and no trailing white space or returns at the end; constraints that some other entries don't obey.

A list of words is passed into the function; some 'blanks' are aded to this list and then the algorithm maps a row,column pair to a wordNumber, characterNumber in the expanded list. (This is a bit of the inverse of the usual strategy seen in other solutions).

If we allow trailing white space on all lines except the last, we can do a bit better (163 bytes):

def f(s):
 M=max(map(len,s));p=' '*M;L=[p]+s+M*[p];r='';k=0
 while k/M<len(s)*3+M:i=k%M;w=k/M-i+1;r+=(L[(w/3+1)*(w%3==1)]+p)[i]+'\n'*(i==M-1);k+=1
 return r.strip()
\$\endgroup\$
1
\$\begingroup\$

K4, 58 bytes

Solution:

+(|/{0+/|\|~^x}@'x)$x:(2-(!c)+3*#x)$"  "/:'$+(c:|/#:'x)$x:

Examples:

q)k)+(|/{0+/|\|~^x}@'x)$x:(2-(!c)+3*#x)$"  "/:'$+(c:|/#:'x)$x:("programming";"puzzles";"and";"code";"golf")
"p          "
" r         "
"  o        "
"p  g       "
" u  r      "
"  z  a     "
"a  z  m    "
" n  l  m   "
"  d  e  i  "
"c     s  n "
" o        g"
"  d        "
"g  e       "
" o         "
"  l        "
"   f       "
q)k)+(|/{0+/|\|~^x}@'x)$x:(2-(!c)+3*#x)$"  "/:'$+(c:|/#:'x)$x:(,"a";"bcd";"efgh";,"i";,"j")
"a   "
"    "
"    "
"b   "
" c  "
"  d "
"e   "
" f  "
"  g "
"i  h"
"    "
"    "
"j   "
q)k)+(|/{0+/|\|~^x}@'x)$x:(2-(!c)+3*#x)$"  "/:'$+(c:|/#:'x)$x:("verylongword";"short")
"v           "
" e          "
"  r         "
"s  y        "
" h  l       "
"  o  o      "
"   r  n     "
"    t  g    "
"        w   "
"         o  "
"          r "
"           d"

Explanation:

Right-pad strings so they are the same length, transpose, join with " ", left-pad to generate diagonals, then right-pad to correct lengths and transpose back. Takes a list of strings and returns a list of strings. Probably golfable but still shorter than my q/kdb+ solution.

+(|/{0+/|\|~^x}@'x)$x:(2-(!c)+3*#x)$"  "/:'$+(c:|/#:'x)$x:
                                                        x:      / save as variable x
                                                       $        / pad
                                             (        )         / do this together
                                                  #:'x          / count (#:) each (') x
                                                |/              / max
                                              c:                / save as variable c
                                            +                   / flip / transpose
                                           $                    / string ($)
                                    "  "/:'                     / join each with "  "
                                   $                            / pad
                      (           )                             / do this together
                                #x                              / count (#) x
                              3*                                / multiply by 3
                             +                                  / add to
                         (  )                                   / do this together
                          !c                                    / range 0..c
                       2-                                       / subtract from 2
                    x:                                          / save as x:
                   $                                            / pad
 (                )                                             / do all this together
    {         }@'x                                              / apply (@) lambda {} to each x
            ^x                                                  / null (^) x (" " is considered null)
           ~                                                    / not
          |                                                     / reverse
        |\                                                      / max (|) scan (\), maxs
     0+/                                                        / sum (+) over (/) starting with 0
  |/                                                            / max (|) over (/), max
+                                                               / transpose
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 17 bytes

12 bytes if trailing whitespaces were allowed: try it online.

ζε2úíJNúS}ζJðδÜõÜ

Port of @Shaggy's Japt answer.

Input as a list of list of characters; output as a list of lines.

Try it online.

More interesting answer using the Canvas builtin (27 25 bytes):
20 19 bytes if trailing whitespaces were allowed: try it online.

€gDø4.ý˜I€ûðºý374S.Λ¶¡ðδÜ

-2 bytes thanks to @emanresuA.

Input as a list of words; output as a list of lines.

Try it online.

Explanation:

ζ         # Zip/transpose; swapping rows/columns of the (implicit) input-list of lists
          # of characters, with a space " " as filler for shorter lists
 ε        # Map over each inner lists of characters:
  2ú      #  Pad each inner character with 2 leading spaces
    í     #  Reverse each inner string, so the spaces are trailing
     J    #  Join this list together to a single string
      Nú  #  Pad the 0-based map-index amount of leading spaces
        S #  Convert the string back to a list of characters
 }ζ       # After the map: Zip/transpose back again with " " filler
   J      # Join each inner list together to a single string
     δ    # Map over each inner line:
    ð Ü   #  Trim trailing spaces
       õÜ # Trim trailing empty strings from the list
          # (after which the list of lines is output implicitly)
€gDø4.ý˜I€ûðºý374S.Λ¶¡ðδÜ

€g        # Get the length of each word of the (implicit) input-list
  Dø      # Convert each value to a pair of this value with a Duplicate + Zip/transpose
    4.ý   # Intersperse this list of pairs with 4 as delimiter
       ˜  # Flatten it to a single list
I         # Push the input-list of words again
 €û       # Palindromize each word
   ðºý    # Join this list with "  " (2 spaces) delimiter
ŽDā       # Push 374
   S      # Convert it to a list of digits: [3,7,4]
.Λ        # Use the modifiable Canvas builtin with these three arguments
  ¶¡      # Split it on newlines
     δ    # Map over each inner line:
    ð Ü   #  Trim trailing spaces
          # (after which the list of lines is output implicitly)

Additional information about the Canvas builtin Λ/:

It takes 3 arguments to draw an ASCII shape:

  1. Length of the lines we want to draw
  2. Character/string to draw
  3. The direction to draw in, where each digit represents a certain direction:
7   0   1
  ↖ ↑ ↗
6 ← X → 2
  ↙ ↓ ↘
5   4   3

€gDø4.ý˜I€ûðºý374S creates the following Canvas arguments:

  • Lengths (€gDø4.ý˜): e.g. [11,11,4,7,7,4,3,3,4,4,4,4,4,4] for input ["programming","puzzles","and","code","golf"]
  • Characters (I€ûðºý): e.g. "programmingnimmargorp puzzleselzzup andna codedoc golflog" for input ["programming","puzzles","and","code","golf"]
  • Directions (374S): [3,7,4], which translates to \$[↘,↖,↓]\$

Because we have a list of lengths, those are leading here.

Step 1: Draw 11 characters ("programming") in direction 3 (\$↘\$):

p
 r
  o
   g
    r
     a
      m
       m
        i
         n
          g

Step 2: Draw 11-1 characters ("nimmargorp") in direction 7 (\$↖\$):

p
 r
  o
   g
    r
     a
      m
       m
        i
         n
          g

Step 3: Draw 4-1 characters (" p") in direction 4 (\$↓\$):

p
 r
p o
   g
    r
     a
      m
       m
        i
         n
          g

Step 4: Draw 7-1 characters ("uzzles") in direction 3 (\$↘\$):

p
 r
p o
 u g
  z r
   z a
    l m
     e m
      s i
         n
          g

etc.

See this 05AB1E tip of mine for an in-depth explanation of the Canvas builtin.

€gDø4.ý˜ could alternatively be εgD4)}˜¨ or €gDø€4¦˜, but I've been unable to find anything shorter.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Porting my vyxal answer for the canvas one might help (I use [3, 7, 4], palindromise every word and join by double spaces) \$\endgroup\$
    – emanresu A
    Nov 30, 2022 at 18:57
  • \$\begingroup\$ @emanresuA Thanks, that indeed saves 2 bytes for the Canvas program. :) (PS: You might be able to save some bytes yourself by also porting Shaggy's Japt answer.) \$\endgroup\$ Nov 30, 2022 at 20:54
0
\$\begingroup\$

Perl 6, 73 bytes

{my@t;for .kv ->\i,\w{for w.comb.kv {@t[3*i+$^a][$^a]=$^b}};@t »||»" "}

Try it online!

The input argument is a list of words. The output is an array of array of characters.

\$\endgroup\$
0
\$\begingroup\$

PHP, 100 bytes

<?foreach($_GET as$k=>$v)for($x=0;$y=$v[$x];$t[$x++]=$y)($t=&$s[$k*3+$x])?:$t=" ";echo join("
",$s);

Try it online!

\$\endgroup\$
0
\$\begingroup\$

J, 54 bytes

[:+/@,:&.(_32+3&u:)&.>/]({.-@#\<@{."0])&>~#&>-@+3*i.@#

Try it online!

This was a surprisingly good challenge -- deceptively simple but with a lot of depth, and many paths to a solution. Normally I dislike "no trailing whitespace" constraints, but here it was key to the problem's complexity.

After many different approaches, I finally found one which feels like it works with J rather than against it. I will add a detailed explanation another time.

Note: This returns a boxed list of lines, but in the TIO I open and echo each box so that correctness is easier to see.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.