ASCII Art Mayan Numerals

Python 3.5, 404 400 392 312 311 308 290 281 285 281 bytes:

(Thanks to Adnan for a tip on saving 9 bytes(290->281) and Neil for a tip on saving 4 bytes(285->281)!)

def u(z):
 p=[];P=print;S,N,M,X=' -|\n'
 while not p or z:p+=[z%20];z=z//20
 E=lambda i:(S+N*4+S)*i+X+((M+S*4+M)*i+X)*2+(S+N*4+S)*i+X;F=N*32+X+M+S*30+M+X+N*32+X;[P(S+N*19+S+X+M+((S*4+M)*4+X+M)*2+N*19+M+X+(M+S*19+M+X)*2+S+N*19+S+X*3)if y<1else P(E(y%5)+F*(y//5)+X*3)for y in p[::-1]]

Try it online! (Ideone)

Analysis

For the purposes of this analysis, we will use the character set 0123456789ABCDEFGHIJ to represent each digit in base 20.

So, I could have gone and converted base 10 into base 20 using one of two algorithms I have. The first algorithm I thought of using is what I call the powers algorithm. This is not the one that I used in the code though as it would have made it way longer than it should have been, so I'm not going to talk about this one. However, I did create a python script that converts any integer in base 10 into any other base provided using this method, which you can use here on repl.it. The one I used instead for this challenge is what I call the division algorithm, which I think is explained pretty good here. But basically what happens is that it takes the base 10 number provided and divides it by the base it needs to convert the number to, which in this case is 20, until the remainder is either 0 or 1. It then takes the quotiant and remainder, in that order, from the last division operation, and then all the other remainders from the other division operations in the order from last to first. All these digits are then joined together, and that joined sequence reversed is your base 10 number in base 20! To illustrate this, assume you want to convert the base 10 number 431 to base 20. So, what we would do is this:

[]=list we will put all remainders and the last quotient in
R = Remainder

1. 431/20 = 21 R11 [B (B=11 in base 20)]
2. 21/20 = 1 R1 [Add the remainder and quotient: B11]

Then, finally we would take the list we have, which in this case contains B11, and reverse it so that we now have 11B. In doing this, we have finally got our final answer! 431 in base 10 converted to base 20 is 11B, which can be confirmed using my Python script that uses the powers algorithm which I already shared a link to above, but I will do it again here. Here is one that also uses the division algorithm described in this answer and returns the same answer as the powers one.

This entire process is essentially what happens in my script in this while loop: while not p or z:p+=[z%20];z=z//20. The only difference is that numbers >9 are not represented as letters but instead as themselves.

Moving on, after the base 10 number has been converted to base 20, for each digit in the base 20 integer, which we will call g, g mod 5 dots are printed out and then g//5 bars are printed out. Then the program prints 3 blank lines and moves on to the next digit. However, if the digit is 0, then a single "loaf" is printed out followed by 3 new lines, and then the program moves onto the next digit. So, taking the base 20 number 11B, we go to the first digit. The first digit is 1, and therefore it would print 0 bars since 1//5=0, and 1 dot since 1%5=1. So, we would first get this:

 ---- 
|    |
|    |
 ---- 

and then 3 new lines. Moving onto the the second digit, we also see that it is 1, so it would output the same thing:

 ---- 
|    |
|    |
 ---- 

and also 3 new lines. Finally, moving onto the last digit, we see that it's a B. Since B=11 in base 20, the program would output 1 dot since 11%5=1 and 2 bars since 11//5=2. So now, we get this:

 ---- 
|    |
|    |
 ---- 
--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------

Finally, putting all this together, we get this:

 ---- 
|    |
|    |
 ---- 




 ---- 
|    |
|    |
 ---- 




 ---- 
|    |
|    |
 ---- 
--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------

And, that's the mayan numeral for 431! You finally have your base 10 number represented in base 20 Mayan numerals.

Note: You may or may not have noticed that lambda function in my code. Regardless, this function is used for the creation of the dots since multiple dots must be output next to each other.


Ruby, 223 180 177 179 bytes

Anonymous function, returns a multiline string.

Forgot to add some extra spacing that was needed, and also the recursion. Also golfed a bit more by shifting things around.

f=->n{s=?|;e=' ';n<20?(n<1?[t=e+d=?-*19,a=s+(e*4+s)*4,a,s+d+s,b=s+e*19+s,b,t]:((r=n%5)>0?[t=" ----  "*r,m="|    | "*r,m,t]:[])+[a=?-*32,s+e*30+s,a]*(n/5))*$/:f[n/20]+$/*5+f[n%20]}

Python 3, 243 bytes

s,v,h,x=' |-\n';P=print
t=s+h*19+s+x
def m(n):
 n//20and m(n//20);r=n%20
 if r:
  for a,b,f in[(r%5*' ----  ',r%5*'|    | ',1),('-'*32,'|'+' '*30+'|',r//5)]:P(*((a,b,b,a)*f),sep=x)
 else:P(t+2*(v+(4*s+v)*4+x)+v+h*19+v+x+2*(v+s*19+v+x)+t)
 P(x)

Discussion

n//20and m(n//20) calls m() recursively if there are higher powers of 20 to be handled. The recursion is done before printing the current place value, so that higher powers get printed first.

If the current place value is non-zero (r!=0), the for a,b,f-loop prints the units and then the fives. a is the first/forth row and b is the second/third row. The trick is in the print(*((a,b,b,a)*f),sep=x). For the units, f = 1 resulting in print(*(a,b,b,a),sep=x), which prints the 4 rows that make up the units symbols (x is a '\n'). For the fives, f = the number of fives to print (r//5), so the tuple (a,b,b,a) gets multiplied (i.e., repeated) by the number of fives to print. If f = 2, we get print(*(a,b,b,a,a,b,b,a),sep=x), which prints two symbols for five.

If the current place value is 0, then the zero symbol is printed.