# The Ever Amplifying Zigzag

Write a program or function that takes in a positive integer N and outputs the first N numbers of this amplifying zigzag pattern, using only the lines needed:

                                         26
25  27                                      .
10                          24      28                                  .
9  11                      23          29                              .
2     8     12                  22              30                          44
1 3   7        13              21                  31                      43
4 6           14          20                      32                  42
5              15      19                          33              41
16  18                              34          40
17                                  35      39
36  38
37


So, if N is 1 the output is

1


If N is 2, the output is

 2
1


If N is 3 the output is

 2
1 3


If N is 4 the output is

 2
1 3
4


If N is 10 the output is

         10
9
2     8
1 3   7
4 6
5


If N is 19 the output is

         10
9  11
2     8     12
1 3   7        13
4 6           14
5              15      19
16  18
17


and so on.

# Notes

• Each peak or trough of the zigzag reaches its point one more line away from the line with the 1 on it than the previous peak or trough.

• N is not limited to 44. The zigzag grows in the same pattern and larger N should be supported.

• Numbers with multiple digits should only "touch" at their corners, as depicted. Make sure this works when N is 100 and above.

• There should be no empty (or space only) lines in the output except one optional trailing newline.

• Any line may have any amount of trailing spaces.

# Scoring

The shortest code in bytes wins. Tiebreaker is earlier answer.

• What's the maximum possible N? – Julie Pelletier Jun 14 '16 at 2:24
• @JuliePelletier In theory there is none, but you can assume it will be less than 2^16. – Calvin's Hobbies Jun 14 '16 at 2:27
• Is using control characters allowed or are we limited to digits spaces and linefeeds? – Dennis Jun 14 '16 at 3:31
• @Dennis Let's say no. Just digits/spaces/newlines. – Calvin's Hobbies Jun 14 '16 at 3:52
• Somebody should submit that to the OEIS in that format as a joke. – DanTheMan Jun 16 '16 at 20:03

# Jelly, 4137 29 bytes

RDµḌ’½Ċ-*_\x©L€Ṣ.ị®ạ€⁶ẋj"FZj⁷


Try it online!

### How it works

RDµḌ’½Ċ-*_\x©L€Ṣ.ị®ạ€⁶ẋj"FZj⁷  Main link. Argument: n (integer)

R                              Range; yield [1, ..., n].
D                             Decimal; yield A =: [[1], ..., [1, 0], ...].
µ                            Begin a new, monadic chain. Argument: A
Ḍ                           Undecimal; convert back to falt range.
’                          Decrement to yield [0, ..., n-1].
½Ċ                        Take the square root and round up (ceil).
-*                      Elevate -1 to each rounded square root.
_\                    Cumulatively reduce by subtraction.
This yields [1, 2, 1, 0, -1, 0, ...], i.e., the
vertical positions of the digits in A.
L€                Compute the length of each list in A.
x                   Repeat the nth position l times, where l is the
nth length.
©                  Copy the result to the register.
Ṣ               Sort.
.ị             At-index 0.5; yield the last and first element,
which correspond to the highest and lowest position.
ạ€®          Take the absolute difference of each position in the
register and the extrema.
This yields the number of spaces above and below
the integers in r as a list of pairs.
⁶ẋ        Replace each difference with that many spaces.
F     Flatten the list A.
j"      Join the nth pair of strings of spacing, separating
by the nth digit in flat A.
Z    Zip/transpose the result.
j⁷  Join, separating by linefeeds.

• Why not make a function in your language (Jelly) that can do that in a few chars while you're at it? – Julie Pelletier Jun 14 '16 at 7:00
• @JuliePelletier The art of writing a good golfing language is about coming up with a set of instructions (and syntax/language semantics) which allow you to write short solutions for as many different tasks as possible, not about being able to solve one very specific and contrived challenge in a single byte. A good golfing language tends to be actually very powerful and expressive, as opposed to just being a collection of built-ins which are useless for anything but the specific function they compute. – Martin Ender Jun 14 '16 at 7:50
• @JuliePelletier And it would also go against the rules of PPCG SE – Bálint Jun 16 '16 at 14:12

# PHP, 211177164 163 bytes

Predict the peaks with $n and increase the array dynamically in either direction, using ($x, y) output cursor. Numbers are aligned with str_pad() and the final output is the implode() of that array of strings (g).

for($x=0,$d=-1,$h=$n=2,$y=$a=1;$a<=$argv[1];$y+=$d){$g[$y]=str_pad($g[$y],$x).$a;$x+=strlen($a);if($a++==$n){$h+=2;$n+=$h-1;$d*=-1;}}ksort($g);echo implode(~õ,$g);


## Test it online!

Update: removed 34 bytes by getting rid of the unneeded array_pad(). Update2: followed @insertusernamehere's advice to shorten it a bit more. Update3: followed @Lynn's advice to save one more byte with ~õ which imposes the use of LATIN-1 charset. (not available in online PHP emulator so not included there)

• Just a question about this code.. Don't you have to initialize the array $g before you access a specific element? I mean, giving it a length or inserting the rows? I'm not very experienced with PHP, so it just looks weird to me... Thanks. – Yotam Salmon Jun 14 '16 at 5:17 • No. Once you define $arr = [];, you can refer to $arr[anything]. Some cases will output notices but those are ignored here. Note that reading stuff like this probably won't help you much to learn a language. Your comment made me realize I could make it shorter though as I initially thought I'd need to pad my array but I don't. :) – Julie Pelletier Jun 14 '16 at 5:26 • Haha glad for helping ;) Just realized that in PHP an array and a dictionary are initialized in the same way and are completely the same when looking at the syntax (Why, PHP?!) – Yotam Salmon Jun 14 '16 at 5:28 • Some minor improvements – 164 bytes: for($x=0,$d=-1,$h=$n=2,$y=$a=1;$a<=$argv[1];$y+=$d){$g[$y]=str_pad($g[$y],$x).$a;$x+=strlen($a);if($a++==$n){$h+=2;$n+=$h-1;$d*=-1;}}ksort($g);echo implode("⏎",$g); (Replace ⏎ with an actual newline.) – insertusernamehere Jun 14 '16 at 6:56 • I believe if you set up your encoding right (Latin-1, not UTF-8), ~õ is a two-byte alternative to "⏎". – Lynn Jun 16 '16 at 18:32 # Pyth, 60535246423938363432 31 bytes 39: It is now on par with the bug-fixed version of Jelly, and I have out-golfed Dennis' competing version! 38: I have out-golfed Dennis! 36: I have out-golfed Dennis again! 34: Even lower than his bug-fixed version! 31: 32 -> 31 thanks to Dennis. J1K.u+N=J_WsI@Y2JtQZjsM.t.e++*]*dlhkabhSKhk*]*dlhkabeSKKd J1K.u+N=J_WsI@Y2JtQZjsM.t.eX*]*dlhkhaeSKhSKabhSKhkKd J1K.u+N=J_WsI@Y2JtQZ=-RhSKKjsM.t.eX*]*dlhkheSKbhkKd J1K.u+N=J_WsI@Y2JtQQj-#dsMC.eX*]*dlhkheSKbhkK J1j-#dsMC.eX*]*dlhkyQ+Qbhkm=+Z=J_WsI@td2J J1j-#dsMCmX*]*;lhdyQ+Q=+Z=J_WsI@td2Jhd J1j-#dsMCmX*]*;lhdyQ+Q=+Z=J_WsI@td2Jh J1j-#dsMCmX*]*;lhdyQ+Q=+Z=@_BJsI@td2h j-#dsMCmX*]*;lhdyQ+Q=+Zsty%s@td2 2h j-#dsMCmX*]*;lhdyQ+Q=+Z@_B1.E@d2h JQj-#dsMCmX*]*;lhdyQ=+J@_B1.E@d2h JyQj-#dsMCmX*]*;lhdJ=+Q@_B1.E@d2h j-#dsMCmX*]*;lhdyQ=+Q@_B1.E@d2h j-#dsMCmX*]*;lhdyQ=+Q^_1.E@d2h  Try it online! ## How it works j-#dsMCmX*]*;lhdyQ=+Q^_1.E@d2h input: Q j-#dsMCmX*]*;lhdyQ=+Q^_1.E@d2hdQ implicit filling arguments m Q for each number d from 0 to Q-1: @d2 yield the square root of d. .E yield its ceiling. ^_1 raise -1 to that power. this yields the desired direction. =+Q increment Q by this amount. hd yield d+1.  yield its string representation. l yield its length. *; repeat " " for that number of times ] yield a list containing the string above. * yQ repeat the list for Q*2 times. the Q has changed, but Q*2 is an overshoot that is high enough, so we don't have to worry about it. X in that list, replace the element with index being the number generated above hd with d+1. C transpose the resulting array. sM flatten each element. -#d remove lines containing only spaces. (filter on truthiness of set difference with space) j join by newlines.  • "39: On par with Jelly"; "38: I have out-golfed Dennis!" For a few hours you did, but it looks like @Dennis doesn't like to get beaten at code-golfing: Jelly 37 bytes ;) – Kevin Cruijssen Jun 16 '16 at 7:24 • @KevinCruijssen Done. – Leaky Nun Jun 16 '16 at 13:50 • Nice! xD M̶a̶y̶b̶e̶ I have a wild imagination, but now I imagine you've looked and looked in frustration for hours until you finally found this shorter solution, and now @Dennis will casually wake up and shorten his code again. (Jk, I hope you stay below Dennis!) – Kevin Cruijssen Jun 16 '16 at 14:05 • @KevinCruijssen Tada! It's now lower than the bug-fixed version. – Leaky Nun Jun 16 '16 at 14:31 # MATLAB, 148 bytes n=input('');k=fix(n^.5);m=0;w=1;d=-1;for l=1:n;s=num2str(l);m(k+1,w:w+nnz(s)-1)=s;w=w+nnz(s);k=k+d;d=d*(-1)^(l^.5==fix(l^.5));end;[m(any(m,2),:),'']  Note that the spaces are missing in Octave, as MATLAB prints the the character indexed with 0 as a space, while octave does just omit that character. Explanation: n=input(''); k=fix(n^.5); %caculate starting height m=0;w=1;d=-1; %initialize counters and output matrix for l=1:n; s=num2str(l); m(k+1,w:w+nnz(s)-1)=s; %insert current index as a string w=w+nnz(s); %current horizontal position k=k+d; %current vertical position d=d*(-1)^(l^.5==fix(l^.5)); %if we reached a square number, change direction end [m(any(m,2),:),''] %delete all zero rows  ## Haskell, 144 142 bytes g n|k<-take n$scanl(+)0$[1..]>>= \x->(-1)^x<$[2..2*x]=unlines[[1..n]>>= \x->show x#(k!!(x-1)==y)|y<-[minimum k..maximum k]]
s#g|g=s|1<2=' '<$s  Usage example: *Main> putStr$ g 19
10
9  11
2     8     12
1 3   7        13
4 6           14
5              15      19
16  18
17


How it works:

s#g|g=s|1<2=' '<$s -- # is a helper function that expects a string s -- and a boolean g. It returns s if g is True, else -- as many spaces as there a characters in s k<-take n$                      -- bind k to the first n elements of
[1..]>>= \x->(-1)^x<\$[2..2*x]  -- 2*x-1 copies of (-1)^x for each x in [1,2,3,...]
-- i.e. [-1, 1,1,1, -1,-1,-1,-1,-1, 1,1,1,1,1,1,1..]
scanl(+)0                      -- build partial sums, starting with 0
-- i.e. [0,-1,0,1,2,1,0,-1,-2,-3,-2,-1...]
-- -> k is the list of y coordinates for the
--    numbers 1,2,3,...

[  |y<-[minimum k..maximum k]] -- for all y coordinates in k
\x->show x#(k!!(x-1)==y)  -- map the # function
[1..n]>>=                     -- over [1..n] (the x coordinates)
-- where # is called with
--  s -> a string representation of x
--  g -> True if k at index x equals the current y
unlines                         -- join with newlines


Edit: Thanks @Lynn for two bytes!

## JavaScript (ES6), 213 bytes

with(Math)n=>(a=[...Array(n)].map((_,i)=>n-=1+sqrt(--i)&1||-1).map((e,_,a)=>e-min(...a))).map((e,i)=>r[e][i]=++i,r=[...Array(1+max(...a))].map(_=>a.map((_,i)=> .repeat(1+log10(++i)))))&&r.map(a=>a.join).join\n


Where \n represents a literal newline character. Explanation:

with(Math)                          Bring functions into scope
n=>                                Accepts one parameter
(a=                               Intermediate result variable
[...Array(n)].map(               For each number 0..n-1
(_,i)=>n-=                      Accumulate index for each number
1+sqrt(--i)&1||-1              Calculate the direction
).map((e,_,a)=>e-min(...a))     Scale the smallest index to zero
).map((e,i)=>r[e][i]=++i,         Overwrite the padding with 1..n
r=[...Array(1+max(...a))].map(   Calculate number of lines
_=>a.map((_,i)=>                For each number 1..n
.repeat(1+log10(++i)))))    Calculate the padding needed
&&r.map(a=>a.join).join\n     Join everything together


To shorten pow(-1,ceil(sqrt(i))) I rewrite it as sqrt(i-1)&1||-1 however this doesn't work for i=0 so to fix that I add 1 but this then flips the sign of the result which is why I end up with n-=.

• heyyy you got a gold badge! nice job! and holy smokes you almost have as much rep as I do. keep it going! – Conor O'Brien Jun 20 '16 at 0:14
• @CᴏɴᴏʀO'Bʀɪᴇɴ That's "merely" the Fanatic badge. Apparently I'm really close to getting the gold code-golf tag badge! – Neil Jun 20 '16 at 0:16
• double holy smokes. I need to get moving XD – Conor O'Brien Jun 20 '16 at 0:17

# Python 2, 137 bytes

l={}
i=x=y=n=v=0
exec"v+=1;l[y]=l.get(y,'').ljust(x)+v;x+=len(v);i=-~i%-~n;y+=n%4-1;n+=2>>i*2;"*input()
for k in sorted(l):print l[k]
`

View the output on ideone.

• Hm... It doesn't go on and on and on and on. – Zizouz212 Jun 20 '16 at 0:30
• @Zizouz212 It does, ideone just has a fixed output with and automatically breaks lines that are too long. – flawr Jun 25 '16 at 13:43