Zigzagify a String
Pyth, 69 bytes
aY,JhzZVtzaY,@"-\/"K-<NJ>N~JN=+ZKaY,N=+ZK;jbCmX*\ h-e=GSeMYhG-edhGhdY
Demonstration. Longer inputs still work, but they don't look very good in the fixed-width output box.
I start by constructing a list, in Y
, of [character, height] tuples. It is [['P', 0], ['/', -1], ['r', -2], ['\\', -1], ['o', 0], ['\\', 1], ['g', 2]]
early on in the Programming Puzzles & Code Golf
example.
I then make strings of spaces of the appropriate length, insert the character at the appropriate location, transpose, join on newlines and print.
Julia, 297 bytes
s->(l=length;d=sign(diff([i for i=s]));J=join([[string(s[i],d[i]>0?:'/':d[i]<0?:'\\':'-')for i=1:l(d)],s[end]]);D=reshape([d d]',2l(d));L=l(J);E=extrema(cumsum(d));b=2sumabs(E)+1;A=fill(" ",L,b);c=b-2E[2];for (i,v)=enumerate(J) A[i,c]="$v";i<l(D)&&(c-=D[i])end;for k=1:b println(join(A'[k,:]))end)
Ungolfed:
function f(s::String)
# Get the direction for each slash or dash
# +1 : /, -1 : \, 0 : -
d = sign(diff([i for i in s]))
# Interleave the string with the slashes as an array
t = [string(s[i], d[i] > 0 ? '/' : d[i] < 0 ? '\\' : '-') for i = 1:length(d)]
# Join the aforementioned array into a string
J = join([t, s[end]])
# Interleave D with itself to duplicate each element
D = reshape(transpose([d d]), 2*length(d))
# Get the length of the joined string
L = length(J)
# Get the maximum and minimum cumulative sum of the differences
# This determines the upper and lower bounds for the curve
E = extrema(cumsum(d))
# Get the total required vertical size for the output curve
b = 2*sumabs(E) + 1
# Get the beginning vertical position for the curve
c = b - 2*E[2]
# Construct an array of spaces with dimensions corresponding
# to the curve rotated 90 degrees clockwise
A = fill(" ", L, b)
# Fill the array with the curve from top to bottom
for (i,v) = enumerate(J)
A[i,c] = "$v"
i < length(D) && (c -= D[i])
end
# Print out the transposed matrix
for k = 1:b
println(join(transpose(A)[k,:]))
end
end
Javascript (ES6), 360 331 316 302 bytes
Here's my fourth attempt:
s=>{r=[],c=s[m=w=n=0];for(i in s)(i?(d=s[++i])>c?++n:c>d?--n:n:n)<m&&m--,n>w&&w++,c=d;for(i=0,n=w*2;i<(w-m)*2+1;r[i++]=[...' '.repeat(l=s.length*2-1)]);for(i=0;i<l;i++)i%2?(A=s[C=(i-1)/2])<(B=s[C+1])?r[--n,n--][i]='/':A>B?r[++n,n++][i]='\\':r[n][i]='-':r[n][i]=s[i/2];return r.map(x=>x.join``).join`
`}
Not as short as some of the others, but I'm satisfied with it for now.
Oh, so you want to test it? Alright, here you go:
z=s=>{r=[],c=s[m=w=n=0];for(i in s)(i?(d=s[++i])>c?++n:c>d?--n:n:n)<m&&m--,n>w&&w++,c=d;for(i=0,n=w*2;i<(w-m)*2+1;r[i++]=[...' '.repeat(l=s.length*2-1)]);for(i=0;i<l;i++)i%2?(A=s[C=(i-1)/2])<(B=s[C+1])?r[--n,n--][i]='/':A>B?r[++n,n++][i]='\\':r[n][i]='-':r[n][i]=s[i/2];return r.map(x=>x.join``).join('<br>')};
input=document.getElementById("input");
p=document.getElementById("a");
input.addEventListener("keydown", function(){
setTimeout(function(){p.innerHTML = "<pre>"+z(input.value)+"</pre>";},10);
})
<form>Type or paste your text here: <input type="text" id="input"/></form>
<h3>Output:</h3>
<p id="a"></p>
Have fun!
Updates:
Update 1: Golfed off 29 bytes with a variety of typical techniques.
Update 2: Golfed off 15 more bytes by building the string horizontally from the start, as opposed to building an array of the vertical strings and switching them around, which is what it did before.
Update 3: Saved 14 more bytes.
More golfiness coming soon!