g | x | w | all
Bytes Lang Time Link
065Ruby181018T094058ZAsone Tu
015Uiua241008T023651Znoodle p
010Japt181016T225943ZShaggy
147Red181017T110546ZGalen Iv
058Perl 5 lF241003T172219ZXcali
00805AB1E legacy181016T151647ZKevin Cr
134C181018T193957ZJ. Knobl
084Ruby181018T092848ZG B
095Powershell181017T205750Zmazzy
068R181016T151015ZdigEmAll
nanI have two solutions to the problem. The first solution I did first then I thought of another way to do it that I thought would save bytes but it didn't so I included it anyway.181016T201334ZMic1780
023K Kona181017T152317ZAlex Shr
026J181016T132902ZGalen Iv
021Pyth181017T090255ZSok
090Python 2181016T133832ZTFeld
023APL Dyalog Classic181017T071630ZGalen Iv
075JavaScript ES6181016T155717ZArnauld
024J181017T041238ZBubbler
049Perl 6181017T031307ZJo King
083JavaScript Node.js181017T025054Ztsh
084Clean181016T231716ZΟurous
191SNOBOL4 CSNOBOL4181016T205851ZGiuseppe
021Charcoal181016T203322ZNeil
016MATL181016T133746ZLuis Men
006Husk181016T184245ZZgarb
008Jelly181016T172029ZJonathan
064Haskell181016T162601ZDelfad0r
155MBASIC181016T134231Zwooshiny
016Japt181016T150659ZETHprodu

Ruby, 75 65 bytes

->s,h{a=['']*h;x=-k=1;s.map{|c|a[x+=k=h-x<2?-1:x<1?1:k]+=c};a*''}

Try it online!

Takes input as an array of chars, returns string

How it works:

Uiua, 15 bytes

⊕⊂↯△,⊂:⇌+1∩⇡-2.

Try it: Uiua pad

For the input 5, this makes the array:

[0 1 2 3 4 3 2 1]

The array is then repeated to the length of the string, and used to group the string.

Japt, 12 11 10 bytes

Dunno why I deleted this! It was a long time ago.

ñÏgVo ê ÅÔ

Try it (includes all test cases)

ñÏgVo ê ÅÔ     :Implicit input of string U & integer V
ñ              :Sort U by
 Ï             :Passing each 0-based index through the following function
  g            :  Modularly index into
   Vo          :    Range [0,V)
      ê        :    Palindromise
        Å      :    Remove first element
         Ô     :    Reverse

Note: If V=1 then Vo will produce an empty array and the sorting function will return undefined for each character, preserving the original order of the string.

Red, 147 bytes

func[s n][i: v: m: 1 foreach k sort collect[forall s[keep/only reduce[v i s/1]v: v + m
if all[n > 1(i: i + 1)%(n - 1)= 1][m: 0 - m]]][prin last k]]

Try it online!

Red, 153 bytes

func[s n][i: v: m: 1 b: collect[foreach c s[keep/only reduce[v i c]v: v + m
if all[n > 1(i: i + 1)%(n - 1)= 1][m: -1 * m]]]foreach k sort b[prin last k]]

Try it online!

Explanation:

f: func [ s n ] [                      ; s is the string, n is the height
    i: 1                               ; index of the current character in the string
    v: 1                               ; value of the "ladder"
    m: 1                               ; step (1 or -1)
    b: collect [                       ; collect the values in a block b
        foreach c s [                  ; foreach character in the string 
            keep/only reduce [ v i c ] ; keep a block of the evaluated [value index char] 
            i: i + 1                   ; increase the index
            v: v + m                   ; calculate the value 
            if all [ n > 1             ; if height is greater than 1 and
                    i % (n - 1) = 1    ; we are at a pick/bottom of the ladder
                   ]
                [ m: -1 * m ]          ; reverse the step
        ]
    ]
    foreach k sort b [ prin last k ]   ; print the characters in the sorted block of blocks
]

Perl 5 -lF, 58 bytes

$#a=<>-1;map$_.=shift@F,@a,reverse@a[1..@a-2]while@F;say@a

Try it online!

05AB1E (legacy), 11 8 bytes

Σ²Lû¨¾è¼

Inspired by @LuisMendo's MATL answer.
-3 bytes thanks to @Adnan

Try it online. (No test suite, because the legacy version of 05AB1E didn't had a reset for the counter_variable.)

Explanation:

Σ           # Sort the (implicit) input-string by:
 ²L         #  Create a list in the range [1, second input-integer]
            #   i.e. 5 → [1,2,3,4,5]
   û        #  Palindromize it
            #   i.e. [1,2,3,4,5] → [1,2,3,4,5,4,3,2,1]
    ¨       #  Remove the last item
            #   i.e. [1,2,3,4,5,4,3,2,1] → [1,2,3,4,5,4,3,2]
     ¾è     #  Index into it (with wraparound) using the counter_variable (default 0)
            #   i.e. counter_variable = 0 → 1
            #   i.e. counter_variable = 13 → 4
       ¼    #  And after every iteration, increase the counter_variable by 1

NOTE: The counter_variable is used, because in the Python Legacy version of 05AB1E, the Σ didn't had an index N, which it does have in the new Elixir rewrite version of 05AB1E. So why do I still use the Legacy version? Because in the Elixir rewrite it has a bug and doesn't sort for \$n=1\$, which would all result in an empty list [] after the indexing. All other test cases work as intended with Σ²Lû¨Nè: try it online, but the test case with \$n=1\$ times out without result, even with --no-lazy argument flag: try it online.

C, 142 134 bytes

8 bytes saved thanks to Jonathan Frech

Code:

t;i;j;d;f(s,n)char*s;{for(t=strlen(s),i=0;i<n;i++)for(j=0;j+i<t;j=d+i+(n<2))d=j-i+2*~-n,putchar(s[i+j]),i>0&i<n-1&d<t&&putchar(s[d]);}

Explanation:

// C variable and function declaration magic
t;i;j;d;f(s,n)char*s;{
    // Iterate through each "row" of the string
    for(t=strlen(s),i=0;i<n;i++)
        // Iterate through each element on the row
        // Original index iterator here was j+=2*(n-1), which is a full "zig-zag" forward
        // The (n<2) is for the edge case of n==1, which will break the existing logic.
        for(j=0; j+i<t; j=d+i+(n<2))
            // If j+i is the "zig", d is the "zag": Original index was d=j+i+2*(n-i-1)
            // Two's complement swag here courtesy of Jonathan Frech
            d=j-i+2*~-n,
            putchar(s[i+j]),
            // Short circuit logic to write the "zag" character for the middle rows
            i>0 & i<n-1 & d<t && putchar(s[d]);
}

Try it online!

Ruby, 84 bytes

->s,n{r=['']*n;[*0...n,*(2-n)..-1].map{|x|r[x.abs]+=s.slice!(0)||''}while s[0];r*''}

Try it online!

Powershell, 99 95 bytes

param($s,$n)$r=,''*$n
$s|% t*y|%{$r[((1..$n+$n..1)*$s.Length|gu)[$i++*($n-gt1)]-1]+=$_}
-join$r

Test script:

$f = {

param($s,$n)$r=,''*$n
$s|% t*y|%{$r[((1..$n+$n..1)*$s.Length|gu)[$i++*($n-gt1)]-1]+=$_}
-join$r

}

@(
    ,("1234567", 3            ,     "1524637")
    ,("qwertyuiop", 1         ,     "qwertyuiop")
    ,("codegolf", 3           ,     "cgoeofdl")
    ,("elephant", 4           ,     "enlatehp")
    ,("programmingpuzzles", 5 ,     "piermnlsomgzgapzru")
) | % {
    $s,$n,$e = $_
    $r = &$f $s $n
    "$($r-eq$e): $r"
}

Output:

True: 1524637
True: qwertyuiop
True: cgoeofdl
True: enlatehp
True: piermnlsomgzgapzru

Explanation

The script:

The expression ((1..$n+$n..1)*$s.Length|gu generates a sequence like 1,2,3,3,2,1,1,2,3,3,2,1... and removes adjacent duplicates. gu is alias for Get-Unique.

The expression $i++*($n-gt1) returns an index in the deduplicated sequence. =$i++ if $n>1, otherwise =0

R, 68 bytes

function(s,n)intToUtf8(unlist(split(utf8ToInt(s),-(n:(2.9-n)-1)^2)))

Try it online!

I have two solutions to the problem. The first solution I did first then I thought of another way to do it that I thought would save bytes but it didn't so I included it anyway.


Solution 1

PHP, 152 144 116 bytes

<?php
for($i=0;$i<$n=$argv[2];$i++)
    for($j=$i;$s=$argv[1][$j];$j+=$n<2|(($f=!$f|!$i)?$i<$n-1?$n+~$i:$i:$i)*2)
        echo $s;

Try it online!


Solution 2

PHP, 162 bytes

<?php
$s=$argv[0];
$n=$argv[1];
$l=strlen($s);
for($i=0;$i<$l;){
    for($j=0;$j<$n&&$i<$l;)
        $a[$j++].=$s[$i++];
    for($j=$n-2;$j>0&&$i<$l;)
        $a[$j--].=$s[$i++];
}
echo join($a);

Try it online!

K ( Kona ), 23 bytes

A translation of the J answer by Galen

{y@<(#y)#-1_(!x),|!x-1}

J, 54, 29, 27 26 bytes

-1 byte thanks to hoosierEE

([\:#@[$[:}:|@i:@<:@]) ::[

Try it online!

Pyth, 22 21 bytes

|seMhD,V*lz+PUQP_UQzz

Takes input as n followed by s on separate lines. Try it online here, or verify all the test cases at once here.

|seMhD,V*lz+PUQP_UQzz   Implicit: Q=eval(input()), z=remaining input
                        
             UQ         Range [0-Q)
            P           All but last from the above
                         e.g. for Q=3, yields [0,1]
               P_UQ     All but last of reversed range
                         e.g. for Q=3, yields [2,1]
           +            Concatenate the previous two results
                          e.g. for Q=3, yields [0,1,2,1]
        *lz              Repeat len(z) times
      ,V           z    Vectorised pair the above with z, truncating longer to length of shorter
                          e.g. for Q=3, z=WATERMELON, yields:
                          [[0,'W'],[1,'A'],[2,'T'],[1,'E'],[0,'R'],[1,'M'],[2,'E'],[1,'L'],[0,'O'],[1,'N']]
    hD                  Sort the above by the first element
                          Note this is a stable sort, so relative ordering between equal keys is preserved
  eM                    Take the last element of each
 s                      Concatenate into string
                          Note that if n=1, the result of the above will be 0 (sum of empty array)
|                   z   If result of above is falsey, yield z instead

Edit: saved a byte by moving the empty check to the end of processing. Previous version: seMhD,V*lz|+PUQP_UQ]0z

Python 2, 119 108 98 92 91 97 93 91 90 bytes

lambda s,n:''.join(c*(j%(2*n-2or 1)in(i,2*n-i-2))for i in range(n)for j,c in enumerate(s))

Try it online!

-1 byte, thanks to Jonathan Frech

APL (Dyalog Classic), 23 bytes

{⍺[⍋(≢⍺)⍴(¯1↓⊢,1↓⌽)⍳⍵]}

Try it online!

JavaScript (ES6), 75 bytes

Shorter formula suggested by @MattH (-3 bytes)

Takes input as (string)(n).

s=>n=>--n?[...s].map((c,x)=>o[x=x/n&1?n-x%n:x%n]=[o[x]]+c,o=[])&&o.join``:s

Try it online!


JavaScript (ES7), 78 bytes

Saved 4 bytes thanks to @ETHproductions

Takes input as (string)(n).

s=>n=>--n?[...s].map((c,x)=>o[x=n*n-(x%(n*2)-n)**2]=[o[x]]+c,o=[])&&o.join``:s

Try it online!

J, 24 bytes

4 :'x\:(#x)$}:|i:<:y'::[

Try it online!

Explicit dyadic verb. Run it like 'codegolf' f 3.

How it works

4 :'x\:(#x)$}:|i:<:y'::[    x: string, y: height
4 :                         Define a dyadic verb:
               i:<:y        Generate a range of -(y-1) .. y-1
            }:|             Take absolute value and remove last
       (#x)$             1) Repeat to match the string's length
    x\:                     Sort x by the decreasing order of above
                     ::[    If 1) causes `Length Error`, return the input string instead

Normally, explicit function takes additional 5 bytes in the form of n :'...'. But if error handling is added, the difference goes down to 2 bytes due to the parens and space in (tacit)<space>::.

Perl 6, 49 bytes

->\n{*.comb.sort({-abs n-1-$++%(2*n-2||1)}).join}

Try it online!

Takes input as a curried function.

Explanation:

->\n{*.comb.sort({-abs n-1-$++%(2*n-2||1)}).join}
->\n{                                           }  # Take an number
     *.comb        # Turn the string into a list of chars
           .sort({                       })   # And sort them by
                           $++    # The index of the char
                              %(2*n-2||1)  # Moduloed by 2*(n-1) or 1 if n is 0
                       n-1-       # Subtract that from n-1
                   abs            # get the absolute value
                  -               # And negate to reverse the list
                                          .join  # and join the characters

The sequence that it is sorted by looks like this (for n=5):

(-4 -3 -2 -1 0 -1 -2 -3 -4 -3 -2 -1 0 -1 -2 -3 -4 -3 -2 -1)

JavaScript (Node.js), 83 bytes

c=>g=(s,d=c*2-2,r=d,n=o='')=>s&&([...s].map((c,i)=>i%d%r?n+=c:o+=c),o)+g(n,r-1,r-2)

Try it online!

Clean, 105 84 bytes

import StdEnv,Data.List
$s n=[c\\l<-[1..n],c<-s&m<-cycle([1..n]++[n-1,n-2..2])|m==l]

Try it online!

SNOBOL4 (CSNOBOL4), 191 bytes

	S =INPUT
	N =INPUT
	A =ARRAY(N)
	A<1> =EQ(N,1) S	:S(O)
I	I =I + -1 ^ D
	S LEN(1) . X REM . S	:F(O)
	A<I> =A<I> X
	D =EQ(I,N) 1
	D =EQ(I * D,1)	:(I)
O	Y =Y + 1
	O =O A<Y>	:S(O)
	OUTPUT =O
END

Try it online!

Takes S then N on separate lines.

Explanation:

	S =INPUT			;* read S
	N =INPUT			;* read N
	A =ARRAY(N)			;* create array of size N
	A<1> =EQ(N,1) S	:S(O)		;* if N = 1, set A<1> to S and jump to O
I	I =I + -1 ^ D			;* index into I by I + (-1)^D (D starts as '' == 0)
	S LEN(1) . X REM . S	:F(O)	;* extract the first character as X and set S to the
					;* remaining characters, jumping to O when S is empty
	A<I> =A<I> X			;* set A<I> to A<I> concatenated with X
	D =EQ(I,N) 1			;* if I == N, D=1
	D =EQ(I * D,1)	:(I)		;* if I == D == 1, D = 0. Goto I
O	Y =Y + 1			;* increment the counter
	O =O A<Y>	:S(O)		;* concatenate the array contents until last cell
	OUTPUT =O			;* and print
END

Charcoal, 21 bytes

⭆NΦη¬⌊E²﹪⁺μ⎇νι±ι∨⊗⊖θ¹

Try it online! Link is to verbose version of code. Works by noting that indices \$ m \$ of the characters on line \$ i \$ satisfy the relation \$ m \pm i = 0 \pmod {2n - 2} \$. Explanation:

 N                      First input as a number
⭆                       Map over implicit range and join
   η                    Second input
  Φ                     Filter over characters
       ²                Literal 2
      E                 Map over implicit range
          μ             Character index
             ι ι        Outer index
              ±         Negate
            ν           Inner index
           ⎇            Ternary
         ⁺              Plus
                   θ    First input
                  ⊖     Decremented
                 ⊗      Doubled
                    ¹   Literal 1
                ∨       Logical Or
        ﹪               Modulo
     ⌊                  Minimum
    ¬                   Logical Not
                        Implicitly print

MATL, 16 bytes

Zv3L)t?yn:)2$S}i

Try it online! Or verify all test cases.

Explanation

Consider inputs 5, 'programmingpuzzles'.

Zv     % Input, implicit: number n. Symmetric range
       % STACK: [1 2 3 4 5 4 3 2 1]
3L     % Push [1 -1+1j]. When used as an index, this means 1:end-1
       % STACK: [1 2 3 4 5 4 3 2 1], [1 -1+1j]
)      % Index. Removes last element
       % STACK: [1 2 3 4 5 4 3 2]
t      % Duplicate
       % STACK: [1 2 3 4 5 4 3 2], [1 2 3 4 5 4 3 2]
?      %   If non-empty and non-zero
       %   STACK: [1 2 3 4 5 4 3 2]
  y    %   Implict input: string s. Duplicate from below
       %   STACK: 'programmingpuzzles', [1 2 3 4 5 4 3 2], 'programmingpuzzles'
  n    %   Number of elements
       %   STACK: 'programmingpuzzles', [1 2 3 4 5 4 3 2], 18
  :    %   Range
       %   STACK: 'programmingpuzzles', [1 2 3 4 5 4 3 2], [1 2 3 ··· 17 18]
  )    %   Index modularly
       %   STACK: 'programmingpuzzles', [1 2 3 4 5 4 3 2 1 2 3 4 5 4 3 2 1 2]
  2$S  %   Two-input sort: stably sorts first input as given by the second
       %   STACK: 'piermnlsomgzgapzru'
}      % Else. This branch is entered when n=1. The stack contains an empty array
       %   STACK: []
  i    %   Take input
       %   STACK: [], [], 'programmingpuzzles'
       % End, implicit
       % Display stack, implicit. Empty arrays are not displayed

Husk, 6 bytes

δÖK…¢ḣ

Try it online!

Works for n = 1 as well.

Explanation

δÖK…¢ḣ  Implicit inputs, say n=4 and s="WATERMELON"
     ḣ  Range: [1,2,3,4]
    ¢   Cycle: [1,2,3,4,1,2,3,4,1,2,3,4..
   …    Rangify: [1,2,3,4,3,2,1,2,3,4,3,2..
δÖK     Sort s by this list: "WEAMLTROEN"
        Print implicitly.

The higher order function δ works like this under the hood. Suppose you have a higher order function that takes a unary function and a list, and returns a new list. For example, Ö takes a function and sorts a list using it as key. Then δÖ takes a binary function and two lists, zips the lists together, applies Ö to sort the pairs using the binary function as key, and finally projects the pairs to the second coordinate. We use K as the key function, which simply returns its first argument and ignores the second.

Jelly, 8 bytes

6 byter fails for height 1; two bytes used to address it ...maybe a 7 can be found?

ŒḄṖȯ1ṁỤị

A dyadic link accepting a positive integer and a list of characters which yields a list of characters.

Try it online!

How?

ŒḄṖȯ1ṁỤị - Link: positive integer N; list of characters, T
ŒḄ       - bounce (implicit range of) N -> [1,2,3,...,N-1,N,N-1,...,3,2,1]
  Ṗ      - pop off the final entry         [1,2,3,...,N-1,N,N-1,...,3,2]
   ȯ1    - OR one                          if this is [] get 1 instead
     ṁ   - mould like T (trim or repeat to make this list the same length as T)
      Ụ  - grade-up (get indices ordered by value - e.g. [1,2,3,2,1,2] -> [1,5,2,4,6,3])
       ị - index into T

Haskell, 64 bytes

s#n=[c|m<-[0..n],(c,i)<-zip s.cycle$[0..n-1]++[n-2,n-3..1],i==m]

Try it online!

MBASIC, 146 159 155 bytes

1 INPUT S$,N:DIM C$(N):P=1:D=1:FOR I=1 TO LEN(S$):C$(P)=C$(P)+MID$(S$,I,1)
2 IF N>1 THEN P=P+D
3 IF P=N OR P=1 THEN D=-D
4 NEXT:FOR I=1 TO N:PRINT C$(I);:NEXT

Updated to handle n=1

Output:

? programmingpuzzles, 5
piermnlsomgzgapzru

? codegolf, 3
cgoeofdl

? elephant, 4
enlatehp

? 1234567, 3
1524637

? WATERMELON, 4
WEAMLTROEN

? qwertyuiop, 1
qwertyuiop

Japt, 16 bytes

¬üÏu´VÑ aV°ÃÔc q

Test it online!

Explanation

 ¬ üÏ   u´ VÑ  aV° Ã Ô c q
Uq üXY{Yu--V*2 aV++} w c q    Ungolfed
                               Implicit: U = input string, V = size of wave
Uq                             Split U into chars.
   üXY{            }           Group the items in U by the following key function:
       Y                         Take the index of the item.
        u--V*2                   Find its value modulo (V-1) * 2.
               aV++              Take the absolute difference between this and (V-1).
                                 This maps e.g. indices [0,1,2,3,4,5,6,7,...] with V=3 to
                                                        [2,1,0,1,2,1,0,1,...]
                                 The items are then grouped by these values, leading to
                                 [[2,6,...],[1,3,5,7,...],[0,4,...]].
                     w         Reverse the result, giving [[0,4,...],[1,3,5,7,...],[2,6,...]].
                       c       Flatten.
                         q     Join back into a single string.