13
\$\begingroup\$

In mountaineering terminology, a "14er" is any mountain with an elevation of 14 000 feet or more. However, there is another distinction. For a peak to count as a 14er, it must also have a "geographic prominence" of 300 or more feet. This means that to move from one 14er to another, you must first descend at least 300 feet before rising again. Take this example. Line 1 counts as 14 000 feet, and each line counts as 100 feet.

  /\__/\  
 /      \ 
/        \

Now, both of these peaks have enough elevation to count, but there isn't enough drop in elevation between them to count as two separate peaks. Therefore, one of these counts as a 14er, and the other one is just a "partial peak". Here is an example where the two peaks count as two separate 14er:

   /\    /\   
  /  \  /  \  
 /    \/    \ 
/            \

There can also be a partial peak on the decline between two 14ers. Here's a slightly modified version of the last mountain range:

   /\      /\   
  /  \/\  /  \  
 /      \/    \ 
/              \

This mountain range also counts as two 14ers.

You must write a program or function that takes an ascii-art representation of a mountain range, and return how many 14ers are in the range. You can take input in whatever format is most convenient for you, be it 2D array of characters, a string with newline, or a string with some other delimiter. You can assume that all inputs will only contain the characters /\_, and that the length of each line will be the same (including trailing spaces). You can also assume that the mountain range starts on the bottom left corner with either a / or a _.

If the last section of a mountain is not on the bottom line, you can assume that the mountain only decreases after that, e.g.

  /
 /
/

Counts as a single 14er.

You do not have to handle invalid mountain ranges.

Here is some sample I/O:

         /\___/\_             
        /        \    /\      
       /          \  /  \     
   _/\/            \/    \    
  /                       \   
 /                         \  
/                           \_

2

                  /\    /\
         /\      /  \  /  
  /\    /  \    /    \/   
 /  \  /    \  /          
/    \/      \/           

4

       /\                 
 _/\__/  \                
/         \               

1

      /\                  
     /  \   /\            
    /    \_/  \           
   /           \          
  /             \         
 /               \        
/                 \       

1

              /\          
    /\_/\    /  \_        
   /     \  /     \     /\
  /       \/       \   /  
 /                  \_/   
/                         

3
\$\endgroup\$
  • \$\begingroup\$ So the starting line counts as 14,000 feet? \$\endgroup\$ – R. Kap Apr 23 '16 at 6:42
  • \$\begingroup\$ @R.Kap Yes, I believe that's correct, assuming you mean the bottom line when you say starting line. \$\endgroup\$ – Alex A. Apr 23 '16 at 6:43
  • 1
    \$\begingroup\$ I think you should mention somewhere that a _ counts as 100 feet lower than a slash on the same line. At least that's what your last test case suggests. \$\endgroup\$ – Martin Ender Apr 23 '16 at 9:50
  • 3
    \$\begingroup\$ The spec seems thin... can we have a flat peat like / / / _ \ \ \ ? Also, I suppose that the highest point in the input should always be counted as a peak but this is not explicitly specified; one could start at a lower peak and end up with a different count. \$\endgroup\$ – feersum Apr 23 '16 at 11:06
  • 2
    \$\begingroup\$ Will it always be continous? Will it have at most one nonspace character for each column? \$\endgroup\$ – Leaky Nun Apr 23 '16 at 11:22
2
\$\begingroup\$

JavaScript (ES6), 133 bytes

s=>[...s].map((_,i)=>(c=s[i%h*w+i/h|0])=="/"?++a>2&&(p+=!d,d=a=3):c=="\\"&&--a<1&&(d=a=0),w=s.search`
`+1,h=-~s.length/w,a=3,d=p=1)|p

Explanation

Since the specifications are not stated clearly, this makes a couple of assumptions:

  • The bottom line is the 14,000ft mark (so all positions on the grid are high enough to count as a peak).
  • The grid starts at (or ascending) the first peak (since it's at least 14,000ft high already as per previous assumption).
  • A separate peak counts only after descending 300ft then ascending 300ft.

Iterates over the character c of each column (specifically, it iterates down each column until it finds a character). The current altitude is stored in a. It is clamped to a minimum of 0 and a maximum of 3. The direction needed to move to count the next peak is stored in d (false = up, true = down). If a reaches 3 and d is false, the number of peaks p is incremented and d is set to true (down). Once a reaches 0, d is set back to false (up).

var solution =

s=>
  [...s].map((_,i)=>   // loop
    (c=s[i%h*w+i/h|0]) // c = current character (moves down columns)
    =="/"?             // if c is '/'
      ++a>2&&          // increment a, if a equals 3 and d is true:
        (p+=!d,d=a=3)  // increment p, set d to true, clamp a to 3
    :c=="\\"&&         // if c is '\':
      --a<1&&          // decrement a, if a equals 0:
        (d=a=0),       // set d to false, clamp a to 0
    
    // Initialisation (happens BEFORE the above code)
    w=s.search`\n`+1,  // w = grid width
    h=-~s.length/w,    // h = grid height
    a=3,               // a = current altitude (min = 0, max = 3)
    d=                 // d = required direction (false = up, true = down)
    p=1                // p = number of found peaks
  )|p                  // output the number of peaks

var testCases = [`
/\\
`,`
/\\          
  \\         
   \\    /\\  
    \\  /  \\ 
     \\/    \\
`,`
\\    /
 \\  / 
  \\/  
`,`
            /\\            
         /\\/  \\/\\         
      /\\/        \\/\\      
   /\\/              \\/\\   
/\\/                    \\/\\
`,`
  /\\__/\\
 /      \\
/        \\
`,`
   /\\    /\\   
  /  \\  /  \\  
 /    \\/    \\ 
/            \\
`,`
   /\\      /\\   
  /  \\/\\  /  \\  
 /      \\/    \\ 
/              \\
`,`
         /\\___/\\_             
        /        \\    /\\      
       /          \\  /  \\     
   _/\\/            \\/    \\    
  /                       \\   
 /                         \\  
/                           \\_
`,`
                  /\\    /\\
         /\\      /  \\  /  
  /\\    /  \\    /    \\/   
 /  \\  /    \\  /          
/    \\/      \\/           
`,`
       /\\                 
 _/\\__/  \\                
/         \\               
`,`
      /\\                  
     /  \\   /\\            
    /    \\_/  \\           
   /           \\          
  /             \\         
 /               \\        
/                 \\       
`,`
              /\\          
    /\\_/\\    /  \\_        
   /     \\  /     \\     /\\
  /       \\/       \\   /  
 /                  \\_/   
/                         
`];
result.textContent = testCases.map(c=>c+"\n"+solution(c.slice(1,-1))).join`\n\n`;
<textarea id="input" rows="6" cols="40"></textarea><br /><button onclick="result.textContent=solution(input.value)">Go</button><pre id="result"></pre>

\$\endgroup\$
2
\$\begingroup\$

C, 174 bytes

a[99],c,p,j,M,m;main(i){for(i=j=1;c=getchar(),~c;i++)c<11?a[i]=j++,i=0:c&4?a[i]=j:0;for(m=j;c=a[i++];c>a[i-2]?M-m>1&&c-m>1?M=c,m=j,p++:M<c?M=m=c:M:m>c?m=c:0);printf("%d",p);}

Requires a trailing newline in the input, otherwise +4 bytes.

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

JavaScript (ES6), 154 bytes

s=>s.split`\n`.map((s,i)=>s.replace(/\S/g,(c,j)=>{e[j]=i+(c!='\\');e[j+1]=i+(c>'/')}),e=[])&&e.map(n=>h-n+d?h-n-d*3?0:(c++,d=-d,h=n):h=n,h=e[0],c=d=1)|c>>1

Where \n represents the literal newline character. Ungolfed:

function climb(string) {
    var heights = [];
    // Split the array into lines so that we know the offset of each char
    var array = string.split("\n");
    // Calculate the height (actually depth) before and after each char
    for (var i = 0; i < array.length; i++) {
        for (var j = 0; j < string.length; j++) {
            switch (array[i][j]) {
            case '\':
                heights[j] = i;
                heights[j+1] = i + 1;
                break;
            case '_':
                heights[j] = i + 1;
                heights[j+1] = i + 1;
                break;
            case '/':
                heights[j] = i + 1;
                heights[j+1] = i;
                break;
        }
    }
    var count = 1;
    // Start by looking for an upward direction
    var direction = 1;
    var height = heights[0];
    for (var k = 1; k < heights.length; k++) {
        if (heights[i] == height - direction * 3) { // peak or trough
            direction *= -1;
            count++; // we're counting changes of direction = peaks * 2
            height = heights[i];
        } else if (heights[i] == height + direction) {
            // Track the current peak or trough to the tip or base
            height = heights[i];
        }
    }
    return count >> 1;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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