# Magrathea 2.0 - Building Mountains

With the big crash of the universal economy also the demand for custom made planets plunged. The Magratheans had to look after more steady revenues also from a broader class of customers. Therefore, they invented the have-your-own chain of mountain (or short havoc-o-mountains) for people with smaller budget who could not afford a complete planet.

The mountains are build according to the customer's plan (a.k.a. strings of digits and dots) and delivered using ascii-art (consisting of , /, \, ^ and v).

Write a complete program which takes input (single string) either from STDIN or as argument and outputs to STDOUT. This puzzle is a code-golf so please show some attempt at golfing.

### Input

A string of dots and digits providing the basis for the mountain chain. Each string is exactly as long as necessary to support the mountains and each peak is given by a digit instead of a dot, indicating the height of the peak.

### Output

An ascii version of the mountain chain.

• Each digit in the input represents exactly one peak (^) at exactly the height indicated by the digit (i.e. 9 is the highest height).
• There must not be additional peaks in the output (i.e. at places where there is a dot in the input).
• Mountains are of triangular shape, i.e. slopes are created using / and \ characters.
• Passes where two mountains overlap are shaped using the character v.
• No superfluous newlines nor blank lines.
• Padding lines with trailing spaces is optional.

You may assume that the input provided is valid, i.e. there always exists a solution according to the rules (e.g. an input of 13.. would not result in a valid configuration and may be ignored). Moreover, on each side there are exactly as many dots such that the mountains must no be cropped.

### Examples

The first line shows the input, all other lines constitute the desired output. (Actually the mountains look much better in my console than here.)

1
^

11
^^

1.2.
^
^/ \

.2.3..
^
^/ \
/    \

.2..3..
^
^ / \
/ v   \

...4...3...3..
^
/ \  ^   ^
/   \/ \ / \
/        v   \

• What a combination of poetry and art! I love it. – devnull Feb 26 '14 at 11:02
• Is printing extra newlines okay? In other words, for an input of 1, is \n\n\n\n\n\n\n\n^ allowed? – durron597 Feb 26 '14 at 11:51
• @durron597 The output should have no superfluous newlines, have a look at the examples. – Howard Feb 26 '14 at 12:15
• What about trailing space characters? Is it OK if all lines are the same length as the original string, padded out with spaces? – Paul Prestidge Feb 27 '14 at 1:37
• @Chron Yes, that's OK. – Howard Feb 27 '14 at 7:40

## Javascript: 272268233232201192189188178 180 characters

Thanks to @Sam for reducing it from 268 to 233 characters, and for @manatwork for another 1 char. @VadimR for pointing out a bug.

p=prompt(r=t='');s=' ';for(d=10;d--;r=s+q+s,t+=q.trim()?q+'\n':'')for(q='',i=0;i<p.length;)q+=' \\/v^'[p[i++]==d?4:(/\^|\\/.test(r[i-1])+2*/\^|\//.test(r[i+1]))*(r[i]==s)];alert(t)


Properly idented and somewhat ungolfed version with comments:

// The output initialization is just a golfing trick suggested by @manatwork.
input = prompt(state = output = '');
space = ' ';

// Repeat for each line, from the top (the highest peak, highest digit) to the floor (digit 1). Start at 10 to avoid a bug.
for (digit = 10; digit--;

// Update the state of our automaton, at the end of the iteration.
// Add a space after and before to simplify the future pattern recognization.
state = space + line + space,

// Add the line to the output if it is not an empty line, at the end of the iteration.
output += line.trim() ? q + '\n' : '')
{ // This curly brace was added for readability, it is not in the golfed source.

// Analyze each character in the current state to produce a new state, like a cellular automaton.
for (line = '', i = 0; i < input.length;)
{ // This curly brace was added for readability, it is not in the golfed source.
line +=

// If the input is the current digit number, evaluate to 4 and put a peak in this character.
// Otherwise evaluate this expression with those rules:
// 1 means that the hill is higher only at right in the previous iteration, we do climb it to the right in this one.
// 2 means that the hill is higher only at left in the previous iteration, we do climb it to the left in this one.
// 3 means that the hill is higher at both sides in the previous iteration, we are in a v-shaped valley.
// 0 means nothing to do here. If the middle is not a space, it will be multiplied by 0 and become 0.
' \\/v^'[input[i++] == digit ? 4 : (/\^|\\/.test(state[i - 1]) + 2 * /\^|\//.test(state[i + 1])) * (r[i] == space)];
} // This curly brace was added for readability, it is not in the golfed source.
} // This curly brace was added for readability, it is not in the golfed source.

// Give the final output.


As you may note from the code, this works as a cellular automaton, where each cells checks for a number in the input, looks to itself and to its two neighbours to decide what the next iteration will be. At each moment a cell may be a ^, /, \, v or . The input provided in the test cases produces the expected output.

Note that using the alert box sucks, since it normally does not have a monospaced font. You may copy & paste the text from the alert box to somewhere else for a better appreciation of the output, or you may replace the last line alert by console.log, but since this is code-golf, alert is shorter.

Further, it does not validates anything in the input. It simply considers unrecognized characters as spaces the same way it does to . (in fact . is an unrecognized character too).

• There is an old golfing trick to reduce 1 character: initialize variables with empty string as prompt()'s parameter. – manatwork Feb 27 '14 at 17:14
• @manatwork Thank you. Done. – Victor Stafusa Feb 27 '14 at 17:18
• Excuse me, maybe I'm missing something, but I'm getting consistent results in both FF and Chromium. I launch a browser, run JS code from revision#14, and get error message. Then I run code from revision#1 - it runs OK. Again I run 14's code - and no error message, it runs OK. So revision#14's code can not be run by itself? – user2846289 Mar 2 '14 at 16:25
• @VadimR Thanks, fixed. That was a side-effect for testing it with a poluted environment. Needed to prefix the code with delete r; delete s; delete q; delete p; delete t; delete i; delete d; to ensure that it was not poluted. – Victor Stafusa Mar 2 '14 at 18:28
• q.trim()?q+'\n':'' could be q.trim()&&q+'\n', saving two. Also, i<p.length could just be p[i]. – Nicholas Pipitone Oct 26 '18 at 18:32

## Ruby, 208201 189

Very fun challenge! Here's an alternative Ruby solution.

gets.size.times{|x|0.upto(h=$_[x].to_i-1){|d|r=$*[h-d]||=' '*~/$/ [x+d,x-d].map{|o|r[o]=r[o]>?!??v:o<x ??/:?\\if r[o]<?w} d<1?r[x]=?^:r[x-d+1,w=2*d-1]=?w*w}} puts$*.reverse.*($/).tr(?w,' ')  As a bonus, here's a Ruby implementation of Victor's very clever "cellular automaton" algorithm, at 162 characters: s=gets 9.downto(1){|h|$0=(-1..s.size).map{|x|$_=$0[x,3]
s[x]=="#{h}"??^:~/  [\^\/]/??/:~/[\^\\]  /??\\:~/[\^\\] [\^\/]/??v:' '}*''
$*<<$0[1..-2]if$0=~/\S/} puts$*


Example output:

....5.....6..6.....
^  ^
^    / \/ \
/ \  /      \
/   \/        \
/               \
/                 \

• I think you may use $/ for newline. – Howard Feb 27 '14 at 7:43 C# - 588 characters - not as good as Ray's 321 though! class P{static void Main(string[] a){char[,] w=new char[a[0].Length+1,10];int x=0;foreach(char c in a[0]){if(c!='.'){int h=int.Parse(c+"");if(w[x,h]=='\0')w[x,h]='^';int s=1;for(int l=h-1;l>0;l--){for(int m=x-s;m<=x+s;m++){if(w[m,l]!='\0'){if(w[m,l]=='^')w[m,l]='/';if(w[m,l]=='\\')w[m,l]='v';}else{if(m==x-s)w[m,l]='/';else if(m==x+s)w[m,l]='\\';else w[m,l]='\0';}bool t=false;for(int f=9;f>0;f--){if(t)w[m,f]='\0';if(w[m,f]!='\0')t=true;}}s++;}}x++;}for(int k=9;k>0;k--){string u="";for(int j=0;j<w.GetLength(0);j++){u+=w[j,k];}if(u.Replace("\0","")!="")System.Console.WriteLine(u);}}}  Example output: F:\>mountains ".2..3..4..." ^ ^ / \ ^ / v \ / v \  Or a longer more complex one... F:\>mountains ".2..3..6.....5...3......1..3..4....2." ^ / \ ^ / \ / \ ^ / \/ \ ^ ^ / \ ^ / v \ / v \ ^ / v \ ^/ \/ \  Brilliant puzzle... not as easy as it seems... loved it! • "Complex one" is ill-formed, there's no peak for "3". – user2846289 Mar 1 '14 at 17:20 • All the 3s are there. If you're talking about the first one, it's part of the slope. – Hein Wessels Oct 26 '18 at 9:30 # APL, 65 bytes ⍉⌽↑⌽¨h↑¨'^/v\'[1+(~×a)×2+×2+/2-/0,0,⍨h←¯1+⊃⌈/a-↓|∘.-⍨⍳⍴a←11|⎕d⍳⍞] ⍞ this symbol returns raw (not evaluated) input as a character array. Solving interactively, in an APL session:  s←'...4...3...3..' ⍝ let's use s instead of ⍞ ⎕d ⍝ the digits 0123456789 ⎕d⍳s ⍝ the indices of s in ⎕d or 11-s if not found 11 11 11 5 11 11 11 4 11 11 11 4 11 11 11|⎕d⍳s ⍝ modulo 11, so '.' is 0 instead of 11 0 0 0 5 0 0 0 4 0 0 0 4 0 0 a←11|⎕d⍳s ⍝ remember it, we'll need it later ⍴a ⍝ length of a 14 ⍳⍴a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ⍝ ∘.- subtraction table ⍝ ∘.-⍨A same as: A ∘.- A ⍝ | absolute value |∘.-⍨⍳⍴a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1 0 1 2 3 4 5 6 7 8 9 10 11 12 2 1 0 1 2 3 4 5 6 7 8 9 10 11 ... 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ⍝ ↓ split the above matrix into rows ⍝ a- elements of "a" minus corresponding rows ⍝ ⊃⌈/ max them together ⊃⌈/a-↓|∘.-⍨⍳⍴a 2 3 4 5 4 3 3 4 3 2 3 4 3 2 ⍝ This describes the desired landscape, ⍝ except that it's a little too high. ⍝ Add -1 to correct it: ¯1+⊃⌈/a-↓|∘.-⍨⍳⍴a 1 2 3 4 3 2 2 3 2 1 2 3 2 1 ⍝ Perfect! Call it "h": h←¯1+⊃⌈/a-↓|∘.-⍨⍳⍴a 0,⍨h ⍝ append a 0 (same as h,0) 1 2 3 4 3 2 2 3 2 1 2 3 2 1 0 0,0,⍨h ⍝ also prepend a 0 0 1 2 3 4 3 2 2 3 2 1 2 3 2 1 0 2-/0,0,⍨h ⍝ differences of pairs of consecutive elements ¯1 ¯1 ¯1 ¯1 1 1 0 ¯1 1 1 ¯1 ¯1 1 1 1 ⍝ this gives us slopes between elements 2+/2-/0,0,⍨h ⍝ sum pairs: left slope + right slope ¯2 ¯2 ¯2 0 2 1 ¯1 0 2 0 ¯2 0 2 2 ×2+/2-/0,0,⍨h ⍝ signum of that ¯1 ¯1 ¯1 0 1 1 ¯1 0 1 0 ¯1 0 1 1 2+×2+/2-/0,0,⍨h ⍝ add 2 to make them suitable for indexing 1 1 1 2 3 3 1 2 3 2 1 2 3 3 ⍝ Almost ready. If at this point we replace ⍝ 1:/ 2:v 3:\, only the peaks will require fixing. ~×a ⍝ not signum of a 1 1 1 0 1 1 1 0 1 1 1 0 1 1 (~×a)×2+×2+/2-/0,0,⍨h ⍝ replace peaks with 0-s 1 1 1 0 3 3 1 0 3 2 1 0 3 3 ⍝ Now replace 0:^ 1:/ 2:v 3:\ ⍝ We can do this by indexing a string with the vector above ⍝ (and adding 1 because of stupid 1-based indexing) '^/v\'[1+(~×a)×2+×2+/2-/0,0,⍨h] ///^\\/^\v/^\\ ⍝ Looks like our mountain, only needs to be raised according to h r←'^/v\'[1+(~×a)×2+×2+/2-/0,0,⍨h] ⍝ name it for convenience h¨↑r ⍝ extend r[i] with spaces to make it h[i] long / / / ^ \ \ / ^ \ v / ^ \ \ ↑⌽¨h¨↑r ⍝ reverse each and mix into a single matrix / / / ^ \ \ / ^ \ v / ^ \ \ ⍉⌽↑⌽¨h¨↑r ⍝ reverse and transpose to the correct orientation ^ / \ ^ ^ / \/ \ / \ / v \  # Ruby, 390 characters Whew, this one was tricky. I ended up having to append to a new string for each character, using a variable s that meant "skip next character" which was needed for processing ^ and \. This output exactly the given sample output for all of the test cases. m=[gets.chomp] a=m[0].scan(/\d/).max.to_i m[0].gsub!(/./){|n|n==?. ? ' ':a-n.to_i} s=nil until a==0 o='' m[-1].chars{|c|o+=case c when ?0;?^ when ' ';t=s;s=nil;t ? '':' ' when /\d/;(c.to_i-1).to_s when ?^;s=1;o.slice! -1;"/ \\" when ?/;t=s;s=nil;t ? "#{o.slice! -1;' '}":o.slice!(-1)=='\\' ? 'v ':"/ " when ?\\;s=1;' \\' when ?v;' ' end} m.push o a-=1 end puts (m[1..-1]*"\n").gsub /\d/,' '  Chart of what the variables mean: m | The mountain array. a | The highest height of a mountain. Used for counting when to stop. s | Whether or not to skip the next character. 1 for yes, nil for no. o | Temp string that will be appended to mountain. t | Temp variable to hold the old value of s.  I'm sure I could golf it down much more, but I have to go now. Shall be improved later! • I'm struggling with the input .2.2. and can't see why it doesn't work. – Howard Feb 27 '14 at 7:46 # Java, 377 407 Edit: @Victor pointed out that this needed to be a complete program, so I added a few dozen characters to make it compilable and runnable. Just pass the "purchase order" as the first param when executing the program, like so: java M ..3.4..6..4.3.. I think this is similar in spirit to other answers, basically just traverses the "mountain order" repeatedly for every possible height, and builds the mountains from the tops down. That way I only have to deal with four conditions if not building a peak -- either an up slope '/', down slope '\, joint 'v', or empty ' '. I can discover that simple by looking at the three spaces centered "above" my current position in my top-down build. Note that like other submissions, I treat anything other than a number as equivalent to '.' in the input, for brevity. Golfed version: class M{public static void main(String[]m){char[]n=m[0].toCharArray();int e=n.length,h=9,x=-1,p;char[][]o=new char[11][e];char l,r,u;boolean a,b,c;for(;h>=0;h--){for(p=0;p<e;p++){if(n[p]-49==h){o[h][p]=94;if(x==-1)x=h;}else{l=(p>0)?o[h+1][p-1]:0;r=(p<e-1)?o[h+1][p+1]:0;u=o[h+1][p];a=l>91&&l<99;b=r==94||r==47;c=u<33;o[h][p]=(char)((a&&b)?'v':(c&&b)?47:(c&&a)?92:32);}}if(x>=h)System.out.println(o[h]);}}}  Human readable form (and without some of the equivalent transmogrifications to achieve golf form): class Magrathea2 { public static void main(String[] mountain) { String out = ""; char[][] output = new char[11][mountain[0].length()]; int height = 9; int maxheight = -1; int position = 0; char left,right,up; char[] mount = mountain[0].toCharArray(); for (; height >= 0; height--) { for (position=0; position < mount.length; position++) { if (mount[position]-49 == height) { output[height][position] = '^'; if (maxheight==-1) { maxheight=height; } } else { // deal with non-numbers as '.' left=(position>0)?output[height+1][position-1]:0; right=(position<mount.length-1)?output[height+1][position+1]:0; up=output[height+1][position]; if ((left=='^'||left=='\\')&&(right=='^'||right=='/')) { output[height][position]='v'; } else if ((up==' '||up==0)&&(right=='/'||right=='^')) { output[height][position]='/'; } else if ((up==' '||up==0)&&(left=='\\'||left=='^')) { output[height][position]='\\'; } else { output[height][position]=' '; } } } if (maxheight >= height) { out+=new String(output[height]); if (height > 0) { out+="\n"; } } } System.out.println(out); } }  Enjoy. Example output: $ java M ..3..4...6...5....1
^
/ \  ^
^ /   \/ \
^ / v        \
/ v            \
/                \^

• The question mentions Write a complete program, so please, add the missing class X{public static void main(String[]z){. – Victor Stafusa Mar 1 '14 at 21:25
• Right on. I got misdirected by the next section of that sentence -- "or as argument" and missed the complete program part. I'll update it shortly. – ProgrammerDan Mar 2 '14 at 1:36

## Perl 6, 264 224 216 206 200 194 124 bytes

$_=get;my$a=10;((s:g/$a/^/;s:g/\s\.\s/ v /;s:g'\.\s'/ ';s:g/\s\./ \\/;$!=say TR/.1..9/ /;tr'^\\/v' ')if .match(--$a)|$!)xx 9


Thanks to @JoKing for showing a s/// solution. This is golfed a bit further after fixing the tr/// bug in Perl 6.

My original solution with subst:

my$t=get;for 9...1 {if$t.match($_)|$! {$t=$t.subst($_,'^',:g).subst(' . ',' v ',:g).subst('. ','/ ',:g).subst(' .',' \\',:g);$!=say $t.subst(/<[\.\d]>/,' ',:g);$t.=subst(/<[^\\/v]>/,' ',:g)};}


Ungolfed:

my $t=slurp; my$s;
for 9...1 {
if $t.match($_)||$s { # match number or latched$t=$t.subst($_,'^',:g)               # peaks
.subst(' . ',' v ',:g)               # troughs
.subst('. ','/ ',:g)                 # up slope
.subst(' .',' \\',:g);               # down slope
$s=say$t.subst(/<[\.\d]>/,' ',:g);  # clean, display, latch
$t=$t.subst(/<[^\\/v]>/,' ',:g)      # wipe for next line
}
}


Output:

...4...3...33..4..4....2.3.22.33.5..22...333.222.3..
^
^           ^  ^             / \
/ \  ^   ^^ / \/ \     ^    ^^   \     ^^^     ^
/   \/ \ /  v      \  ^/ \^^/      ^^  /   \^^^/ \
/        v           \/               \/           \

• I don't think Perl strictly needs a main function, the entry point can just be the first thing outside a function. – Nissa Oct 25 '18 at 23:38
• I used main for parameter handling. Now using stdin. Thanks. – donaldh Oct 26 '18 at 9:24
• A procedural solution. I'm sure someone can do better with regexes and hyperops. – donaldh Oct 26 '18 at 9:43
• 131 bytes using s/// and tr///. I think that last one can use tr instead of s but I can't quite figure out to translate backslashes. Maybe the first one too – Jo King Oct 26 '18 at 11:56
• Nice work @JoKing – I got into a topic mess when I tried to use s/// and TR///. I see that avoiding blocks is the answer. – donaldh Oct 26 '18 at 14:38

## Perl, 254 218 212

$s=<>;sub f{9-$i-$_[0]?$":pop}for$i(0..8){$h=1;$_=$s;s!(\.*)(\d?)!$D=($w=length$1)+$h-($2||1);join'',(map{($x=$_-int$D/2)<0?f--$h,'\\':$x?f++$h,'/':$D%2?f--$h,v:f$h,'/'}0..$w-1),$2?f$h=$2,'^':''!ge;print if/\S/}

$s=<>; sub f{9-$i-$_[0]?$":pop}
for$i(0..8){$h=1;
$_=$s;
s!(\.*)(\d?)!
$D=($w=length$1)+$h-($2||1); join'',(map{ ($x=$_-int$D/2)<0
?f--$h,'\\' :$x
?f++$h,'/' :$D%2
?f--$h,v :f$h,'/'
}0..$w-1),$2
?f$h=$2,'^'
:''
!ge;
print if/\S/
}


Edit: actually it's a bug-fix to work with ProgrammerDan's ..3..4...6...5....1 example, but, in the process, some bytes were off. And online test: https://ideone.com/P4XpMU

# C# - 321 319

using System.Linq;class P{static void Main(string[]p){int h=p[0].Max()-48,i=h,j,n=p[0].Length;char[]A=new char[n+2],B=A;for(;i-->0;){for(j=0;j++<n;){var r=(A[j+1]==47|A[j+1]==94);B[j]=(char)(p[0][j-1]==i+49?94:i+1<h?A[j]==0?(A[j-1]>90&A[j-1]<95)?r?118:92:r?47:0:0:0);}A=(char[])B.Clone();System.Console.WriteLine(B);}}}


Ungolfed and commented:

using System.Linq;

class P
{
static void Main(string[] p)
{
int h = p[0].Max() - 48,    // Getting the height. Codes for 0 to 9 are 48 to 57, so subtract 48 and hope no one will input anything but dots and numbers.
i = h,
j,                      // Declaring some iterators here, saves a few chars in loops.
n = p[0].Length;
char[] A = new char[n+2],   // Creating an array of char with 2 extra members so as not to check for "index out of bounds" exceptions
B = A;               // B is referencing the same array as A at this point. A is previous row, B is the next one.
for (;i-->0;)               // Looping from top to the bottom of the mountain
{
for (j = 0; j++ < n;)   // Looping from left to right.
{
var r = (A[j + 1] == 47 | A[j + 1] == 94);  // This bool is used twice, so it saves a few characters to make it a variable

// Here's the logic
B[j] = (char)(p[0][j - 1] == i + 49 ? 94    // If at this position in the string we have a number, output "^"
: i + 1 < h ?    // And if not, check if we're on the top of the mountain
A[j] == 0 ?    // If we're not at the top, check if the symbol above is a space (0, actually)
(A[j - 1] > 90 & A[j - 1] < 95) ?   // If there's nothing above, we check to see what's to the left ( ^ or \ )
r ?            // And then what's to the right ( ^ or / )
118            // If there are appropriate symbols in both locations, print "v"
: 92             // If there's only a symbol to the left, print "\"
: r              // Otherwise check if there's a symbol to the right, but not to the left
? 47             // And if there is, print "/"
: 0 : 0 : 0);    // Print nothing if there aren't any symbols above, to the left and to the right,
// or there's a "^" right above, or we're at the top of the mountain
}
A=(char[])B.Clone();    // Clone arrays to iterate over the next line
System.Console.WriteLine(B);
}
}
}


Example:

C:\>program .2..3..4...
^
^ / \
^ / v   \
/ v       \


I think it outputs an extra space before each line, though.

# CJam, 128117112106 104 bytes

CJam is a bit younger than this challenge so this answer does not compete. This was a very nice challenge though! From the little I know about J and APL, I think a submission in those would be impressively short.

WlW++"."Waer{_{~U(e>:U}%\W%}2*;W%]z{$W=}%_$W=S*\:L,2-,\f{\_)L=(~"^/ ^^/ \v ^ \\"S/2/@L>3<_$0=f-{=}/t}zN*  Here is a test case, which I think contains all possible possible combinations of slopes, peaks and troughs: ...4...3...33..4..4....2.3.22.33.5..22...333.222.3..  which yields  ^ ^ ^ ^ / \ / \ ^ ^^ / \/ \ ^ ^/ \ ^^^ ^ / \/ \ / v \ ^/ \^^/ \^ / \^^^/ \ / v \/ \/ \  Test it here. I'll add an explanation for the code later. ## Python, 297234 218 -63 bytes thanks to Jo King -16 bytes with r=s.replace instead of lambda s=input() r=s.replace q=0 j=''.join for i in range(9): if9-iin s or q:q=s=r(9-i,'^');s=r(' . ',' v ');s=r('. ','/ ');s=r(' .',' \\');print j([x,' '][x in'0123456789.']for x in s);s=j([x,' '][x in'/\^v']for x in s)  Takes input from STDIN. Ungolfed, simplified: s=input() # Take input r=lambda y,z: s.replace(y,z) # Function for quick s.replace(a, b) j=lambda x: ''.join(x) q=0 # Acts like boolean for i in range(9): # Count to 9 if 9-iin s or q: # When digit has been found or found previously (no newlines at start) q=s=r(9-i,'^') # Digit to ^, set q to non-zero value for always executing from now on s=r(' . ',' v ') # ' . ' to ' v ' s=r('. ','/ ') # '. ' to '/ ' s=r(' .',' k') # ' .' to 'k'. K is a placeholder, since \\ takes two chars and [...][2::5] fails print j([x,' '][x in'0123456789.']for x in s) # Print without '0123456789.' s=j([x,' '][x in'/\^v']for x in s) # Wipe (delete '/^\v)  • 234 bytes – Jo King Oct 26 '18 at 12:43 • Yeah, I tried the s.replace method myself, but it doesn't work. You're just performing replacements on the original string since strings are immutable – Jo King Oct 27 '18 at 0:30 # Powershell, 148 145 bytes It's a nice challenge! param($s)9..1|?{($p+=$s-match$_)}|%{"$_,^; \. , v ;\. ,/ ; \., \;\^|\\|/|v, "-split';'|%{$x=$s-replace'\.|\d',' '
$s=$s-replace($_-split',')}$x}


Less golfed test script:

$f = { param($s)
9..1|?{($p+=$s-match$_)}|%{ # loop digits form 9 downto 1, execute to the end as soon as a suitable digit met$s=$s-replace$_,'^'          # replace current digit with '^'
$s=$s-replace' \. ',' v '    # replace ' . '  with ' v '
$s=$s-replace'\. ','/ '      # replace '. ' with '/ '
$s=$s-replace' \.',' \'      # replace ' .' with ' \'
$s-replace'\.|\d',' ' # replace all dots and digits with ' ' and push to output. Don't store this replacement$s=$s-replace'\^|\\|/|v',' ' # prepeare to the next step: replace ^ \ / and v to space } # Example: #$s="...4...3...3.."
# 4 : $s="...^...3...3.." output: " ^ " # 4 :$s="... ...3...3.."
# 3 : $s="../ \..^...^.." output: " / \ ^ ^ " # 3 :$s="..   .. ... .."
# 2 : $s="./ \/ \./ \." output: " / \/ \ / \ " # 2 :$s=".        .   ."
# 1 : $s="/ v \" output: "/ v \" # 1 :$s="              "

}

@(
,("1",
"^")

,("11",
"^^")

,("1.2.",
"  ^ ",
"^/ \")

,(".2.3..",
"   ^  ",
" ^/ \ ",
"/    \")

,(".2..3..",
"    ^  ",
" ^ / \ ",
"/ v   \")

,("...4...3...3..",
"   ^          ",
"  / \  ^   ^  ",
" /   \/ \ / \ ",
"/        v   \")

,("...4...3...33..4..4....2.3.22.3..5...22...333.222.3..",
"                                 ^                   ",
"   ^           ^  ^             / \                  ",
"  / \  ^   ^^ / \/ \     ^    ^/   \      ^^^     ^  ",
" /   \/ \ /  v      \  ^/ \^^/      \^^  /   \^^^/ \ ",
"/        v           \/                \/           \")

,(".2..3..6.....5...3......1..3..4....2.",
"       ^                             ",
"      / \    ^                       ",
"     /   \  / \               ^      ",
"    ^     \/   \ ^         ^ / \     ",
" ^ /            v \       / v   \  ^ ",
"/ v                \    ^/       \/ \")
) | % {
$s,$expected = $_$result = &$f$s
"$result"-eq"$expected"
$s$result
}


Output:

True
1
^
True
11
^^
True
1.2.
^
^/ \
True
.2.3..
^
^/ \
/    \
True
.2..3..
^
^ / \
/ v   \
True
...4...3...3..
^
/ \  ^   ^
/   \/ \ / \
/        v   \
True
...4...3...33..4..4....2.3.22.3..5...22...333.222.3..
^
^           ^  ^             / \
/ \  ^   ^^ / \/ \     ^    ^/   \      ^^^     ^
/   \/ \ /  v      \  ^/ \^^/      \^^  /   \^^^/ \
/        v           \/                \/           \
True
.2..3..6.....5...3......1..3..4....2.
^
/ \    ^
/   \  / \               ^
^     \/   \ ^         ^ / \
^ /            v \       / v   \  ^
/ v                \    ^/       \/ \


# Pip-l, 100 bytes

Y#aZGMXaFi,#aIh:+a@i{(yi--h):4j:0Wh-j&++(yi-++jh-j)(yi+jh-j):2}RV Z(J*y)R.(?=.*[^0])0R,6;^" /\v^^"
`

(The language is newer than the question, but probably isn't going to beat the APL submission anyway. Although I hope it will get much shorter.)

Takes input via command-line argument. Try it online!