6
\$\begingroup\$

The Challenge:

Just as the title says, your challenge is to use the printable ASCII characters to create a program that prints out a random polygon in the terminal based on the number of sides, n provided by the user, where n is an integer in the range 3 -> 10 including 3 and 10, in as few bytes as possible.

For example:

If n = 4 it should print out a 4 sided shape. For instance, it may print out a square, like so:

 ______
|      |
|      |
|______|

However, if the program is called again with the same attribute of n=4, it should print out a different polygon based on the same number of sides. For instance, maybe a plain, old parallelogram this time, like so:

    ______________
   /             / 
  /             /
 /_____________/

As another example, consider n=6. At least once, it should print out a 6-sided polygon, such as the convex hexagon shown below:

    ________
   /        \  
  /          \
 /            \
 \            /
  \          /
   \________/

But another time, it should print out a visually different polygon with 6 sides, for instance, maybe a concave hexagon like the following:

________
\      /
 \    /
  \  /
  /  \
 /    \
/______\

Finally, as a last example, if n=3, it may print out an isosceles triangle:

    / \
   /   \
  /_____\

However, another call with the same attribute should print out another kind of triangle, maybe like the following right triangle:

    /|
   / |
  /__|

EDIT: To fulfill @CatsAreFluffy's request, here is an example of an ASCII nine-sided polygon:

    ___
   /   \
  /     \
 /       \
 \       /
  \     /
   \   /
   /   \
  /     \
 /       \
 \       /
  \     /
   \   /
    \ /
     v

NOTE: These are all just examples. Your polygons can be drawn in any style, as long as they meet the guidelines shown below.

Guidelines:

  • Each number of sides, from 3-10, should have at least 2 different shapes associated with it.

  • The program should print out a random shape from the shapes associated with each number of sides each time the program is executed with a specific number of visually distinguishable sides in the range 3 -> 10 given as an argument.

  • The sides of the each polygon can be any length, such that every shape able to be drawn by the entire program has at least one side with the same length as all the others. For instance, a triangle should have at least one side with the same length as one of the sides of a parallelogram. So should the square, pentagons, rectangles, etc. with the parallelogram, and also with each other. As a reference, in the examples given in the challenge sections, each shape has at least one side with a length of 3 slashes.

  • Standard loopholes apply.

\$\endgroup\$
  • \$\begingroup\$ For your square and hourglass, you have the top overhanging the sides, but for the parallelogram and hexagon the top is "inside" the sides. Is that intentional? Can submissions choose either style, as fits their design? \$\endgroup\$ – AdmBorkBork Mar 25 '16 at 19:37
  • \$\begingroup\$ @TimmyD Those are just examples. Submissions can choose any style they want, as long as the submissions meet the guidelines given. \$\endgroup\$ – R. Kap Mar 25 '16 at 19:38
  • \$\begingroup\$ I think you mean hexagon, not pentagon for your n = 6 example. \$\endgroup\$ – DoctorHeckle Mar 25 '16 at 19:39
  • \$\begingroup\$ @DoctorHeckle Yes, you're right. I meant hexagon. \$\endgroup\$ – R. Kap Mar 25 '16 at 19:39
  • \$\begingroup\$ Can the sides overlap themselves? \$\endgroup\$ – Blue Mar 26 '16 at 2:03
9
\$\begingroup\$

Java, 1887 1866 bytes

Try in on Ideone

Saved 21 bytes due to unneeded "public" headers (Thanks to @Bálint!)

Not exactly a golfing challenge, but hey, why not?

I feel Java might actually be the best language for this challenge because no esolang could handle this, and many others don't have as good list manipulation (although Java's takes way more bytes).

Golfed:

import java.util.*;public class A{public static void main(String[]args){System.out.print((new P()).b(Integer.parseInt((new Scanner(System.in)).next())).s());}}class P{S p;public S b(int w){p=new S(w);int j=-1,k=-1,f=(w%2)*2,t,y,x;for(x=0;x<w/2-2+w%2;x++){t=r();y=r();if(j==t|k==y|t==y){x--;continue;}g(t,true,2);g(y,false,2-f);f=0;j=t;k=y;}while(1>0){t=r();y=r();if(w<4&t<1&y<1)continue;if(j==t|k==y|t==y|j==y){x--;continue;}g(t,true,3);g(y,false,3+(w<4?0:(w%2)*2));break;}return p;}void g(int w,boolean b,int h){if(w<1)p.u(h,b);else if(w<2)p.r(h,b);else p.l(h,b);}int r(){return (int)(Math.random()*3);}}class S{List<List<Character>>q,a;int h,s,u,o,e,r,b,t,g,n,m,x,y;public S(int d){s=d;h=s+s%2-1;u=h;o=h;b=s>3?(int)(Math.random()*3*s)+1:0;q=new ArrayList<List<Character>>();a=new ArrayList<List<Character>>();for(x=0;x<h;x++){q.add(new ArrayList<Character>());a.add(new ArrayList<Character>());}i(0,q);i(0,a);e=1;r=1;t=0;g=0;n=0;m=0;}public String s(){String p="";for(x=0;x<e+b+r;x++)p+=x>t+(s<4?1:0)&x<e+b+g?'_':' ';p+="\n";for(y=0;y<h;y++){for(x=0;x<e;x++)p+=y>h-2&x>n?'_':q.get(y).get(x);for(x=0;x<b;x++)p+=y>h-2?'_':' ';for(x=0;x<r;x++)p+=y>h-2&x<m-1?'_':a.get(y).get(x);p+="\n";}return p;}void i(int i,List<List<Character>>z){for(List<Character>l:z)l.add(i,' ');if(z==q){e++;if(i<=t)t++;if(i<=n)n++;}else{r++;if(i<=g)g++;if(i<=m)m++;}}void u(int v,boolean i){if(i){u-=v;for(y=0;y<v;)q.get(u+y++).set(t,'|');}else{o-=v;for(y=0;y<v;)a.get(o+y++).set(g,'|');}}void l(int v, boolean i){if(i){x=v-t;while(x-->0)i(0,q);t=x>0?0:t-v;u-=v;for(y=0;y<v;)q.get(y+u).set(t+y++,'\\');}else{x=v-g;while(x-->0)i(0,a);g=x>0?0:g-v;o-=v;for(y=0;y<v;)a.get(y+o).set(g+y++,'\\');}}void r(int v,boolean i){if(i){t+=v;y=t;while(e<=y)i(e,q);t=y-1;u-=v;for(y=0;y<v;)q.get(u+y).set(t-y++,'/');}else{g+=v;y=g;while(r<=y)i(r,a);g=v<1?g:y-1;o-=v;for(y=0;y<v;)a.get(o+y).set(g-y++,'/');}}}

Must be in file called A.java (for obvious reasons). To run:

  1. In the terminal, type javac A.java
  2. Then, if it gives you no errors, type java A
  3. Finally, type the number of sides. This program actually supports side lengths up to 65536

As you can see in the example output below, the corners tend to be more open, and the sides not as smooth, as compared to the polygons in the examples. Also, it cannot produce a square, but still follows the official guidelines. If there are any problems I can change the answer to fix them.

Sample output:

3

  / |
 /  |
/___|


4
   ____    
  /    \   
 /      \  
/________\ 


5
   _________ 
  /         |
 /          |
/           |
\           |
 \ _________|


6
  ____________    
 |            \   
 |             \  
 |              \ 
 /               |
/_______________ |


7
 _____________________  
\                     / 
 \                   /  
  \                 /   
   |               /    
   |              /     
   \              \     
    \ _____________\    


8
 _______________  
\               / 
 \             /  
  \           /   
   |          \   
   |           \  
   /            | 
  /____________ | 


9
 __________  
\          / 
 \        /  
  \      /   
   |    /    
   |   /     
   /   \     
  /     \    
  |      |   
  |_____ |   


10
   ____     
  /    \    
 /      \   
/        \  
|         / 
|        /  
\        |  
 \       |  
  /      \  
 /________\ 

EDIT: Finally! the ungolfed code is here! It's a bit long, but you probably already guessed that...

I will get to the explanation soon.

import java.util.*;
public class ASCII_Polygon_Driver
{
   public static void main(String[] args)
   {
      System.out.print(P.b(Integer.parseInt((new Scanner(System.in)).next())));
   }
}
class P
{
   static S p;
   public static S b(int w)
   {
      p = new S(w);
      int l1=-1,l2=-1,f=(w%2)*2,r1,r2,x;
      for(x=0;x<w/2-2+w%2;x++)
      {
         r1=r();
         r2=r();
         if(l1==r1){x--;continue;}
         if(l2==r2){x--;continue;}
         if(r1==r2){x--;continue;}
         g(r1,true,2);
         g(r2,false,2-f);
         f=0;
         l1=r1;
         l2=r2;
      }
      while(true)
      {
         r1=r();
         r2=r();
         if(w<4&r1<1&r2<1)continue;
         if(l1==r1|l2==r2|r1==r2|l1==r2){x--;continue;}
         g(r1,true,3);
         g(r2,false,3+(w<4?0:(w%2)*2));
         break;
      }
      return p;
   }
   static void g(int w,boolean b,int h)
   {
      if(w<1)p.goUp(h,b);
      else if(w<2)p.goRight(h,b);
      else p.goLeft(h,b);
   }
   static int r()
   {
      return (int)(Math.random()*3);
   }
}
class S
{
   public List<List<Character>> area1;
   public List<List<Character>> area2;
   private int wid1;
   private int wid2;
   private int spcb;
   public int hght;
   private int top1;
   private int top2;
   private int bot1;
   private int bot2;
   private int mid1;
   private int mid2;
   public int sides;
   private int x;
   private int y;
   public int y1;
   public int y2;
   public S(int numSides)
   {
      sides = numSides;
      hght = sides+sides%2-1;
      y1=hght;
      y2=hght;
      spcb = sides>3?(int)(Math.random()*3*sides)+1:0;
      area1 = new ArrayList<List<Character>>();
      area2 = new ArrayList<List<Character>>();
      for(x=0;x<hght;x++)
      {
         area1.add(new ArrayList<Character>());
         area2.add(new ArrayList<Character>());
      }
      insertCollum1(0);
      insertCollum2(0);
      wid1 = 1;
      wid2 = 1;
      top1 = 0;
      top2 = 0;
      bot1 = 0;
      bot2 = 0;
   }
   public String toString()
   {
      String out ="";

      for(x=0; x<wid1+spcb+wid2; x++)
      {
         out+=x>top1+1&x<wid1+spcb+top2?'_':' ';
      }
      out+="\n";
      for(y=0; y<hght; y++)
      {
         for(x=0; x<wid1; x++)out+=y>hght-2&x>bot1?'_':area1.get(y).get(x);
         for(x=0; x<spcb; x++)out+=y>hght-2?'_':' ';
         for(x=0; x<wid2; x++)out+=y>hght-2&x<bot2-1?'_':area2.get(y).get(x);
         out+="\n";
      }
      return out;
   }
   private void insertCollum1(int index)
   {
      for(List<Character> line : area1)
      {
         line.add(index,' ');
      }
      wid1++;
      if(index<=top1)top1++;
      if(index<=bot1)bot1++;
   }
   private void insertCollum2(int index)
   {
      for(List<Character> line : area2)
      {
         line.add(index,' ');
      }
      wid2++;
      if(index<=top2)top2++;
      if(index<=bot2)bot2++;
   }
   /*private void setChar1(int x, int y, char character, List<List<Character>> which)
   {
      which.get(y).set(x,character);
   }*/
   public void goUp(int howMany, boolean is1)
   {
      if(is1)
      {
         y1-=howMany;
         for(y=0;y<howMany;)
         {
            area1.get(y1+y++).set(top1,'|');
         }
      }
      else
      {
         y2-=howMany;
         for(y=0;y<howMany;)
         {
            area2.get(y2+y++).set(top2,'|');
         }
      }
   }
   public void goLeft(int howMany, boolean is1)
   {
      if(is1)
      {
         x = howMany-top1;
         while(x-->0)insertCollum1(0);
         top1 = Math.max(0,top1-howMany);
         y1-=howMany;
         for(y=0;y<howMany;)
         {
            area1.get(y+y1).set(top1+y++,'\\');
         }
      }
      else
      {
         x = howMany-top2;
         while(x-->0)insertCollum2(0);
         top2 = Math.max(0,top2-howMany);
         y2-=howMany;
         for(y=0;y<howMany;)
         {
            area2.get(y+y2).set(top2+y++,'\\');
         }
      }
   }
   public void goRight(int howMany,boolean is1)
   {
      if(is1)
      {
         top1+=howMany;
         y=top1;
         while(wid1<=y)insertCollum1(wid1);
         top1=y-1;
         y1-=howMany;
         for(y=0;y<howMany;)
         {
            area1.get(y1+y).set(top1-y++,'/');
         }
      }
      else
      {
         top2+=howMany;
         y=top2;
         while(wid2<=y)insertCollum2(wid2);
         top2=howMany<1?top2:y-1;
         y2-=howMany;
         for(y=0;y<howMany;)
         {
            area2.get(y2+y).set(top2-y++,'/');
         }
      }
   }
}
\$\endgroup\$
  • \$\begingroup\$ And, to be honest, I am actually not experienced in Java whatsoever. I am more a Python person. With that said, when I ran your code in my Mac's Terminal, I got this error: A.java:1: cannot find symbol symbol : class Shetring location: class S. Maybe you can fix it soon as I cannot since I am not experienced in that language. At least not yet. \$\endgroup\$ – R. Kap Mar 27 '16 at 2:16
  • \$\begingroup\$ @R.Kap That's a weird error. When I ran it on my computer (Windows) and on Ideone (online compiler, link on answer), it worked fine. What version of Java are you using? EDIT-- oh, I forgot to tell you how to run it. I'll edit my answer. \$\endgroup\$ – Blue Mar 27 '16 at 11:01
  • \$\begingroup\$ I finally got it to work in my Terminal, and I have to say, amazing job! It does everything according to the guidelines, and still works perfectly! Great job! :) \$\endgroup\$ – R. Kap Mar 27 '16 at 17:47
  • \$\begingroup\$ Do you need the methods to be public? Default isn't enough? \$\endgroup\$ – Bálint May 19 '16 at 20:06
  • \$\begingroup\$ @Bálint good catch; u, r and l don't need to be public \$\endgroup\$ – Blue May 19 '16 at 20:09

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.