15
\$\begingroup\$

Write a program or function that takes in a positive integer N, and prints or returns an N×N ASCII art string whose top half is a semicircle made of ('s and whose bottom half is a downward-pointing triangle made of V's, with spaces used as padding.

In other words, make an ASCII ice cream cone: (output for N = 17)

 ((((( ((((((((( ((((((((((((( ((((((((((((( ((((((((((((((( ((((((((((((((( ((((((((((((((((( ((((((((((((((((( VVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVV VVVVVVVVVVVVV VVVVVVVVVVV VVVVVVVVV VVVVVVV VVVVV VVV V 

Examples

Here are the outputs for N = 1 to 5. Note that for odd N, the triangle always must be the larger half.

V (( VV ((( VVV V (( (((( VVVV VV ((( ((((( VVVVV VVV V 

Here's an N = 101 pastebin.

And here's an ungolfed Python 3 reference implementation:

N = int(input()) ic = [[' '] * N for _ in range(N)] for y in range(N//2): for x in range(N): if (x - (N - 1) / 2)**2 + (y - (N - 1) / 2)**2 < (N / 2)**2: ic[y][x] = '(' for y in range(N//2, N): for x in range(y - N//2, N - (y - N//2)): ic[y][x] = 'V' for line in ic: print(''.join(line)) 

Details

  • Take input from stdin, command line, or as function argument. Output to stdout or similar, or you may return the string if you write a function.
  • The cone portion should exactly match the reference implementation for all N.
  • The ice cream portion does not need to exactly match the reference implementation as long as it is clearly in the shape of a semicircle for all N. (This is so you don't have to worry about slight differences in the semicircle due to roundoff errors.)
  • There should not be any unnecessary leading spaces but there may be superfluous trailing spaces.
  • The output may optionally contain a trailing newline.
  • You may optionally use any 3 other distinct printable ASCII characters in place of (, V, and space.

Scoring

The shortest submission in bytes wins. Tiebreaker goes to the oldest submission.

\$\endgroup\$
2
  • 6
    \$\begingroup\$ Am I the only one who thought "IceCII ASCream" when I read the title? \$\endgroup\$ Commented Mar 2, 2015 at 17:19
  • 15
    \$\begingroup\$ @Sp3000 Jeez, I hope so... \$\endgroup\$ Commented Mar 2, 2015 at 17:21

4 Answers 4

7
\$\begingroup\$

CJam, 46 bytes

Try it online.

{:Z{Z{Z(2./:R-zYR<):P#YR-zP#+Z2./P#>SP?}/N}fY} 

I believe this currently mimics the original specification exactly, which was required when I started producing this answer. There may be potential to save a few bytes by making the math less accurate to the original specification, but until I see a way to save more than one or two bytes doing so, I'll leave it as-is.

Explanation

{ "Begin block"; :Z{ "For each y from 0 to input-1"; Z{ "For each x from 0 to input-1"; Z(2./:R "Calculate the radius as (input-1)/2.0"; -z "Calculate the horizontal distance from the center"; YR<):P "Calculate the power to raise distances to: (y<radius)+1 (This results in Euclidean distance being calculated for the ice cream and Manhattan distance being calculated for the cone)"; # "Raise the horizontal distance to the determined power"; YR-zP# "Calculate the vertical distance from the center and raise it to the determined power"; + "Add the horizontal and vertical distances"; Z2./P# "Calculate the solid distance threshold and raise it to the determined power"; >SP? "If the solid threshold is exceeded, produce a space; otherwise, produce the determined power digit (This results in ice cream being represented by the digit '2' and the cone by the digit '1')"; }/ "End x loop"; N "Produce a new line"; }fY "End y loop"; } "End block"; 
\$\endgroup\$
2
  • \$\begingroup\$ This appears to use 2's and 1's instead of ('s and V's ? \$\endgroup\$ Commented Mar 2, 2015 at 22:54
  • \$\begingroup\$ @MarkReed This is allowed. Last line in the details section. \$\endgroup\$ Commented Mar 2, 2015 at 23:01
3
\$\begingroup\$

inca2 129 123 121 111 107

This mostly uses the formulas from the python example, but using jot-dots and iotas instead of double-looping. The i function performs the circular test for the j function which invokes jot-dot upon it. And the k function performs the triangle test for the l function. The c function catenates the results of j and l and reshapes it to N×N.

edit: -6 combine 2 maps into 1.
edit: -2 remove useless ravels.
edit: nicer typescript.
edit: -10 apply repeated expression array-wise.
edit: -4 factor out repeated expression as a function.
edit: line-by-line commentary.

q:y-(n-1)%2 i:[((n%2)^2)>+/(qx y)^2 j:(~[y%2)i.(~y) k:2*[x>[|qy l:(@1+~]y%2)k.(~y) c:y y#((jn<y),ly){' (V' 

In more detail, the entry-point is the c function which takes one argument implicitly named y.

c:y y#((jn<y),ly){' (V' n<y } assign y to 'n' jn<y } call j(y) ly } call l(y) (( ), ) } catenate the results ( ){' (V' } map 0 1 2 to ' ' '(' 'V' y y# } reshape to NxN 

The j function receives the same input value as its y parameter.

j:(~[y%2)i.(~y) y%2 } y divided by 2 [ } floor ~ } iota. this generates the row indices 0..y/2 ~y } iota y. this generates the column indices 0..y ( )i.( ) } jot-dot with the function i 

The jot-dot here does the double-loop. It calls the i function with every combination of elements from the left and right arrays (0..n/2 and 0..n). So the i function receives as x the y index of the table, and it receives as y the x index. The names got a little backwards here :).

i:[((n%2)^2)>+/(qx y)^2 n%2 } n divided by 2 (n%2)^2 } squared x y } make a 2-element array (x,y) qx y } call q on this array 

where q does

q:y-(n-1)%2 n-1 } n minus 1 %2 } divided by 2 y- } y minus that 

back to i

i:[((n%2)^2)>+/(qx y)^2 ( )^2 } square the result from q(x,y) +/ } sum the two numbers > } compare the left side (above) with the right (=> 0/1) [ } floor 

The floor should not be necessary. But apparently there's a bug in the interpreter.

The l function works similarly to the j function, using a jot-dot.

l:(@1+~]y%2)k.(~y) y%2 } y divided by 2 ] } ceiling ~ } iota 0..ceil(y/2)-1 1+ } add 1 => 1..ceil(y/2) @ } reverse => ceil(y/2)..1 ~y } iota y 0..y-1 ( )k.( ) } jot-dot using k 

The k function yields a boolean scaled by 2 so the values can be distinguished from the ice cream values later on, in the mapping.

k:2*[x>[|qy x } k's left arg qy } y-(n-1)%2 | } abs [ } floor x } left-hand-side again > } compare [ } floor (should be unnecessary) 2* } scale by 2 

In action (piping through tr to remove tab chars which are the REPL's prompt):

josh@Z1 ~/inca $ ./inca2 <icecream | tr -d '\t' c1 V c2 (( VV c3 ((( VVV V c4 (( (((( VVVV VV c5 ((( ((((( VVVVV VVV V josh@Z1 ~/inca $ 
\$\endgroup\$
0
2
\$\begingroup\$

Python 2, 193 192

Does not use strings, only math

N=input() R=(N+1)/2;r=range(R) s=lambda L,U:(10**U-10**L)/9 f=lambda N,m:s(0,N)+s(m,N-m) g=lambda N,m:s(0,N)+s(m,N-m)*6 for i in r[1:]:print f(N,int(R-(2*R*i-i*i)**.5)) for i in r:print g(N,i) 

s(L,U) returns a number of the form "U-digits with the rightmost L zeros and the rest ones"
f(N,m) returns an N-digit number with the inner section of 2 and an m-wide border of 1on each side
g(N,m) does the same, but using 7 for the 'colour' of the inner section since it matches the texture of the cone more closely

Output

N=8 N=9 11122111 112222211 12222221 122222221 22222222 222222222 22222222 222222222 77777777 777777777 17777771 177777771 11777711 117777711 11177111 111777111 111171111 
\$\endgroup\$
2
  • \$\begingroup\$ Very unique way to do it :) \$\endgroup\$ Commented Mar 4, 2015 at 14:13
  • \$\begingroup\$ If only we can see the ice cream too :P \$\endgroup\$ Commented Mar 4, 2015 at 14:22
2
\$\begingroup\$

Perl 6, 175

Pretty straightforward implementation without much golfing, just extraneous whitespace/punctuation elimination:

sub MAIN($d){my$r=($d/2).Int;for 1..$r ->$n {my$y=$n-$r;my$h=sqrt($r*$r-$y*$y).Int;my$w=2*$h+$d%2;say ' 'x($r-$h)~'('x$w};for 1..($d-$r) ->$y {say ' 'x($y-1)~'V'x($d-2*$y+2)}} 
\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.