This is a CC-BY-SA challenge from the CCSC Mid-South Programming Contest 2018.
Author(s): Brent Yorgey
Source: Consortium for Computing Sciences in Colleges Mid-South Programming contest 2018
https://ccsc18.kattis.com/problems/ccsc18.mountainrange
Good news: you have been hired to do all the special effects for a film! One of the scenes will take place outside, on a windswept plain with a towering mountain range in the background. Your job is to turn a description of the mountain range into a rendered image.
The bad news: the film’s producers have an extremely small budget, and so they can’t afford luxuries like rendered 3D graphics made up of pixels. Hence, you will be making your image out of ASCII characters.
Write a function or full program to produce mountain range ASCII art according to the spec below. This is code-golf; tie breaker is earlier submission.
Input
You will receive a list of 5-tuples in any standard input format for PPCG and/or your language. Each 5-tuple is the values (x, h, z, t, s) representing one mountain of the range you will draw.
- x is the x-coordinate of the mountain's peak, with 1≤x≤199.
- h is the height of the mountain, with 1≤h≤100.
- z indicates the relative distance of the mountain from the viewer, with 1≤z≤m. The smaller the value of z, the closer the mountain is to the viewer. Closer mountains hide ones that are farther away.
- t is the height of the treeline. The side of the mountain up to the treeline should be filled with trees, represented by the ASCII character
Y. - s is the height of the snowline. The side of the mountain above the snowline should be filled with snow, represented by the ASCII character
*.
The base of each mountain will not extend beyond 0 or 200 horizontally; you may assume that 0≤x−h and x+h≤200. The height of each mountain is no more than 100, so all mountains will fit within a 100x200 grid. The snow and trees will not overlap or exceed the height of the mountain; you may assume that 0≤t≤s≤h. All numbers are non-negative, and all z-values will be unique.
Output
The output should consist of an ASCII drawing of the specified mountain range. Each mountain is triangular in shape with its sides drawn using / and \ characters. For example, here is a mountain of height 4:
/\
/ \
/ \
/ \
This mountain has x-coordinate 4, since the horizontal distance from the left margin to its peak is 4 units.
Trees and snow should fill the interior of the mountain but not obscure the sides of the mountain. For example, here is a mountain with height 6, treeline height 2, and snowline height 3:
/\
/**\
/****\
/ \
/YYYYYYYY\
/YYYYYYYYYY\
That is, the trees extend from the base of the mountain up to a height of 2 units, and the snow starts at a height of 3 units and extends to the top of the mountain.
Mountains with a smaller z-coordinate may hide all or part of a mountain with a larger z-coordinate; see the third sample input/output below.
Leading whitespace is significant, and should be as specified by the x-position and width of the drawn mountains. Leading/trailing newlines are allowed, and any amount of spaces after each line.
Examples
(8, 5, 1, 2, 3)
/\
/**\
/ \
/YYYYYY\
/YYYYYYYY\
(2, 2, 1, 0, 1)
/\
/ \
(8, 5, 2, 2, 3), (2, 2, 1, 0, 1), (9, 8, 3, 1, 4), (17, 4, 4, 4, 4)
/\
/**\
/****\
/*/\***\
/ /**\ \ /\
/ / \ \/YY\
/\ /YYYYYY\ \YYY\
/ \YYYYYYYY\YYY\YYY\
If you find other interesting examples, please share in your answers!
-
\$\begingroup\$ Sandbox (deleted). Related. \$\endgroup\$CAD97– CAD972018年04月16日 16:11:03 +00:00Commented Apr 16, 2018 at 16:11
5 Answers 5
Python 2, (削除) 194 (削除ここまで) (削除) 191 (削除ここまで) 186 bytes
g=map(list,[' '*200]*100)
for x,h,z,t,s in sorted(input(),key=lambda m:-m[2]):
for i in range(h):g[-h+i][x+~i:x-~i]=['/']+[' *Y'[(i<h-s)-(i>=h-t)]]*2*i+['\\']
for l in g:print''.join(l)
Prints the whole 100x200 grid.
Ruby, 133 bytes
->a{r=[];a.sort_by{|x|-x[2]}.map{|x,h,z,t,s|h.times{|i|(r[i]||=?\s*200)[x-j=h-i,j*2]=?/+" Y*"[i<t ?1:i<s ?0:2]*~-j*2+?\\}};r.reverse}
Anonymous lambda. Takes input as array of parameter arrays for mountains, returns array of strings.
Walkthrough
->a{ #Input array is a
r=[]; #Initialize the output array
a.sort_by{|x|-x[2]} #Sort by decreasing distance
.map{|x,h,z,t,s| #Loop through the mountains
h.times{|i| #For each mountain fill h lines starting from the ground
(r[i]||=?\s*200) #If we haven't yet been so high, initialize with spaces
[x-j=h-i,j*2]= #Take a slice from x-(h-i) for double length of h-i
?/+" Y*"[i<t ?1:i<s ?0:2]*~-j*2+?\\ #Draw the sides of the mountain (/\),
} #with (h-i-1)*2 of the appropriately selected filler symbols in the middle
};r.reverse #Reverse to the top->bottom order suitable for printing
}
Charcoal, 79 bytes
AθWθ«≔⊟Φθ=§κ2⌈Eθ§μ2ι≔Φθ¬=κιθ≔§ι1ηJ§ι0±η≔⟦§ι4−η§ι3η⟧ζFY *«≔⊟ζεG↘ε←⊗ε↗εκ→»P↘η←↙η
Try it online! Link is to verbose version of code. Note: Leading space used to force the required indentation. Explanation:
AθWθ«
Loop while the input array is not empty.
≔⊟Φθ=§κ2⌈Eθ§μ2ι
Find the most distant mountain in the array.
≔Φθ¬=κιθ
Remove it from the array.
≔§ι1η
Get the height of the mountain.
J§ι0±η
Jump to the top of the mountain.
≔⟦§ι4−η§ι3η⟧ζ
Get the snowline, treeline and height.
FY *«
Loop over the trees, bare mountain and snow.
≔⊟ζεG↘ε←⊗ε↗εκ→»
Draw a trapezium of the desired height.
P↘η←↙η
Draw the sides of the mountain.
C (clang), (削除) 284 (削除ここまで) (削除) 261 (削除ここまで) (削除) 257 (削除ここまで) 252 bytes
a,b,*z,i,j,k,o;c(*a,*b){return b[2]-a[2];}f(*m,n){qsort(m,n,5*sizeof *m,c);for(i=101;--i>0;puts(""))for(j=0;++j<200;putchar(o))for(o=32,k=0;k<n;z=&m[5*k++],a=z[0]-z[1]+i,b=z[0]-~z[1]-i,o=z[1]/i&&j/a&&b/j?"/\\*Y "[j==a?0:j==b?1:i>z[4]?2:z[3]/i?3:4]:o);}
Credits:
-3 bytes Thanks Kevin Cruijssen
f() takes these params:
m: array of integers with all mountains' parameters
n: number of mountains
m should be a flat array of specifying x, h, z, t and s for mountains with each mountain's parameters appended to this array.
f() prints full 100x200 grid of ASCII scenery render.
Ungolfed:
a,b,*z,i,j,k,o;
c(*a,*b){return b[2]-a[2];} //comaprison function for sort by z-order
f(*m,n){
qsort(m,n,5*sizeof(*m),c); //sort mountains by z-order
for(i=100;i>0;i--,puts("")) { //for each row
for(j=1;j<200;j++){ // for each pixel in this row
o=' '; //initialize pixel to background pixel value
for(k=0;k<n;k++) { // for each mountain, in z-order distant to close
z=&m[5*k]; //start pointer for mountain's params
a=z[0]-z[1]+i; //min x limit of mountain on this line
b=1+z[0]+z[1]-i; //max x limit of mountain on this line
o=z[1]/i && j/a && b/j ? "/\\*Y "[j==a?0:j==b?1:i>z[4]?2:z[3]/i?3:4]:o;
//calculate pixel value ovrwriting previous mountain if necessary
}
putchar(o); //print pixel value
}
}
}
-
\$\begingroup\$
for(j=1;j<200;putchar(o),j++)can befor(j=0;++j<200;putchar(o))(-2 bytes) andb=1+z[0]+z[1]-ican beb=z[0]-~z[1]-i(-1 byte) \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2018年04月19日 14:02:09 +00:00Commented Apr 19, 2018 at 14:02 -
\$\begingroup\$ Thanks @Kevin. Applied same trick to
itoo, saved 2 more bytes. \$\endgroup\$GPS– GPS2018年04月19日 14:27:43 +00:00Commented Apr 19, 2018 at 14:27 -
\$\begingroup\$ Suggest
40instead of5*sizeof *m,--iinstead of--i>0,b=*z++-~*z-i,o=*z/i&&j/a&&b/j?j-a?j-b?i>z[3]?42:z[2]/i?89:32:92:47:o)a=i-1[z=m+5*k++]+*zinstead ofz=&m[5*k++],a=z[0]-z[1]+i,b=z[0]-~z[1]-i,o=z[1]/i&&j/a&&b/j?"/\\*Y "[j==a?0:j==b?1:i>z[4]?2:z[3]/i?3:4]:o)\$\endgroup\$ceilingcat– ceilingcat2018年07月09日 03:00:24 +00:00Commented Jul 9, 2018 at 3:00
JavaScript (Node.js), (削除) 265 (削除ここまで) (削除) 243 (削除ここまで) (削除) 229 (削除ここまで) (削除) 210 (削除ここまで) (削除) 204 (削除ここまで) 203 bytes
a=>a.sort((x,y)=>y[2]-x[2]).map(([x,h,,t,s])=>{for(y=h;y--;)for(i=h+x-y;i--;)(d=R[y]=R[y]||[])[i]=i<x-h+y?d[i]||" ":"Y *\\/"[i>x-h+y?i<h+~y+x?y<t?0:y<s?1:2:3:4]},R=[])&&R.map(x=>s=x.join``+`
`+s,s="")&&s