15
\$\begingroup\$

Mayan pyramids were (and are) an important part of ancient architecture, that were generally used for religious purposes.

They were usually step pyramids, but the steps on each were too steep to climb. Priests would climb to the tops of them via alternative staircases to perform ceremonies. The pyramids were also used as landmarks because of their height, and sometimes even used as burial sites for high ranking officials.


The Challenge

Write a program that can print out a pyramid schematic based on user specifications (see below).


Requirements

  • Take an input of two space-separated variables.

  • Input must be accepted through STDIN (or closest alternative).

  • Output must be through STDOUT (or closest alternative).


Input

  • Height as any positive integer. This is used as the base level's width (in blocks). Each succeeding level of the pyramid has the width n - 1 where n is the previous floor's width (in blocks).

  • Block size which will be 1 or any odd, positive integer ≤ (less than) 10.


Blocks

The given block size determines the width (and height) of each individual piece. Essentially, there are i^2 spaces inside the visible box where i is the block size.

A 1x1 block would look like this:

+++
| |
+++

While a 5x5 block would look like this:

+++++++
|     |
|     |
|     |
|     |
|     |
+++++++

Horizontally Adjacent Blocks

Horizontally side-by-side blocks must have their middle walls merged into one.

You must have this:

+++++
| | |
+++++

Instead of something like this:

++++++
| || |
++++++

Vertically Adjacent Blocks (-5% bonus)

Vertically side-by-side blocks have a special exception: the middle wall can be merged into one.

So, instead of 1x1 blocks looking like this:

 +++
 | |
 +++
+++++
| | |
+++++

They could look like this:

 +++
 | |
+++++
| | |
+++++

Examples

Input: 3 1

Output:

  +++
  | |
  +++
 +++++
 | | |
 +++++
+++++++
| | | |
+++++++

OR

  +++
  | |
 +++++
 | | |
+++++++
| | | |
+++++++

Input: 2 3

Output:

  +++++
  |   |
  |   |
  |   |
  +++++
+++++++++
|   |   |
|   |   |
|   |   |
+++++++++

OR

  +++++
  |   |
  |   |
  |   |
+++++++++
|   |   |
|   |   |
|   |   |
+++++++++

Scoreboard

To be ranked on the scoreboard, put your answer in this format:

# Language, Score

Or if you get the bonus -5%:

# Language, Score (Bytes - 5%)

function getURL(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){$.ajax({url:getURL(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),useData(answers)}})}function getOwnerName(e){return e.owner.display_name}function useData(e){var s=[];e.forEach(function(e){var a=e.body.replace(/<s>.*<\/s>/,"").replace(/<strike>.*<\/strike>/,"");console.log(a),VALID_HEAD.test(a)&&s.push({user:getOwnerName(e),language:a.match(VALID_HEAD)[1],score:+a.match(VALID_HEAD)[2],link:e.share_link})}),s.sort(function(e,s){var a=e.score,r=s.score;return a-r}),s.forEach(function(e,s){var a=$("#score-template").html();a=a.replace("{{RANK}}",s+1+"").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SCORE}}",e.score),a=$(a),$("#scores").append(a)})}var QUESTION_ID=57939,ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",answers=[],answer_ids,answers_hash,answer_page=1;getAnswers();var VALID_HEAD=/<h\d>([^\n,]*)[, ]*(\d+).*<\/h\d>/;
body{text-align:left!important}table thead{font-weight:700}table td{padding:10px 0 0 30px}#scores-cont{padding:10px;width:600px}#scores tr td:first-of-type{padding-left:0}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id="scores-cont"><h2>Scores</h2> <table class="score-table"> <thead><tr><td></td><td>User</td><td>Language</td><td>Score</td></tr></thead><tbody id="scores"></tbody> </table></div><table style="display: none"> <tbody id="score-template"><tr><td>{{RANK}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SCORE}}</td></tr></tbody></table>

\$\endgroup\$
7
  • \$\begingroup\$ What's the minimum input? 1 1? \$\endgroup\$
    – user42643
    Sep 14, 2015 at 20:25
  • \$\begingroup\$ Yes, which would be a single block. @minxomat It's explained under the "Input" section. \$\endgroup\$
    – Zach Gates
    Sep 14, 2015 at 20:26
  • \$\begingroup\$ What would the input 3 2 produce? \$\endgroup\$ Sep 14, 2015 at 23:08
  • \$\begingroup\$ According to the second bullet under the "Input" section, the second input integer must be odd. @Hand-E-Food If you meant to ask what would happen for an input like 2 3, it would exit when n - 1 = 0 where n is the previous floor's width in blocks. \$\endgroup\$
    – Zach Gates
    Sep 14, 2015 at 23:09
  • \$\begingroup\$ @ZachGates, thanks! Don't mind me. Clearly the coffee has failed me. \$\endgroup\$ Sep 14, 2015 at 23:27

7 Answers 7

11
\$\begingroup\$

JavaScript (ES6), 161 (169-5%) 166 (174-5%)

Using template strings, the 2 newlines are significant and counted.

Test running the snippet below in an EcmaScript 6 browser. Firefox ok, not Chrome because it lacks support for destructuring assignment.

Code explained after the snippet.

/*Test: redefine console.log*/ console.log=x=>O.innerHTML+=x+'\n';

for([h,b]=prompt().split` `,g='+'[R='repeat'](-~b),f=' '[R](b),n=o='';h--;o+=e+(d=g[R](++n)+`+
`)+f.replace(/./g,e+('|'+f)[R](n)+`|
`))e=' '[R](h*-~b/2);console.log(o+d)
<pre id=O></pre>

Less Golfed

[h, b] = prompt().split` `; // get the space separated input values
c = -~b; // Add 1 to b. As b is of string type b+1 would be a string concatenation
g = '+'.repeat(c); // top border
f = ' '.repeat(b); // inner blank row
o = ''; // initialize output string
for(n = 0; h > 0; --h) // loop on height
{
   ++n;
   e = ' '.repeat(h*c/2); // blanks for offset from left margins
   d = g.repeat(n) + `+\n`; // top border repeated, then right end and newline
   // the block body is squared, there are as many rows as columns inside
   // so I can build the right number of rows replacing the chars in a single row
   o += e + d + f.replace(/./g, e + ('|'+f).repeat(n)+`|\n`)
}
o += d // add last top border as bottom
console.log(o)    
\$\endgroup\$
9
\$\begingroup\$

Ruby, 124 (130 - 5%)

n=(g=gets).to_i
b=g[-2].to_i+1
a=(0..n*b-1).map{|i|[?+*(i/b*b+b+1),(?|+' '*(b-1))*(i/b+1)+?|][i%b<=>0].center(n*b+1)}
puts a,a[-b]

With comments

n=(g=gets).to_i                                  #get input and interpret as a number for pyramid height (everything after the space is ignored)
b=g[-2].to_i+1                                   #the single-character block size is the second last character (just before the newline.) Add 1 to give the pitch between squares.
a=(0..n*b-1).map{|i|                             #run through all lines except the last one
[?+*(i/b*b+b+1),                                 #calculate number of + symbols
(?|+' '*(b-1))*(i/b+1)+?|]                       #or alternatively, pattern '|    |'
     [i%b<=>0]                                   #check if i%b is zero or positive to decide which to print
     .center(n*b+1)}                             #centre the text. It will be mapped to the array a.
puts a,a[-b]                                     #a contains the pyramid, minus its last line. Print it, and add the last line
\$\endgroup\$
1
  • \$\begingroup\$ Don't forget about your bonus -5% (bringing your score to 124). Good work! \$\endgroup\$
    – Zach Gates
    Sep 14, 2015 at 23:38
2
\$\begingroup\$

Python 2, 117 (123 bytes)

h,n=map(int,raw_input().split())
p,v='+|'
while h:p+='+'*-~n;v+=' '*n+'|';h-=1;l=~n/-2*h*' ';print l+p+('\n'+l+v)*n
print p

The idea is to build up the bricks' top p as +++++++++ and side v as | | |. The top starts as + and is augmented by n+1 +'s each layer. The side starts as | and is augmented by n spaces and a |. Each layer, we augment the tops and sides, then print one top and n sides.

To center them, we first print an indent l. It consists of a number of spaces that scales with the current height h. To update it, we decrementing the height variable h until it hits 0, after which the current layer is flush against the left edge of the screen. We print the top once more to make the bottom layer, and we're done.

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

Pyth, 45 (47 bytes - 5%)

AmvdczdVGjm.[Jh*GhHj*H?d\ \+*+2N?d\|\+\ hH;*J\+

Try it out here.

                                                   Implicit: z=input(), d=' '
    czd                                            Split input on spaces
 mvd                                               Evaluate each part of the above (convert to int)
A                                                  Store the pair in G,H
             Jh*GhH                                J = 1+(G*(H+1))
       VG                                          For N in [0 to G-1]:
          m                             hH;          Map d in [0 to H] to:
                                ?d\|\+                 Get '|' or '+' (vertical edges or corners)
                            *+2N                       Repeat the above (N+2) times
                      ?d\ \+                           Get ' ' or '+' (block centre or horizontal edge)
                    *H                                 Repeat the above H times
                   j                                   Join (|/+) by (   /+++)
           .[J                        \                Centrally pad the above to width J using spaces
         j                                           Join on newlines, implicit print
                                           *J\+    Get J '+'s, implicit print
\$\endgroup\$
1
  • 1
    \$\begingroup\$ +1. Better late than never. :P \$\endgroup\$
    – Zach Gates
    Sep 21, 2015 at 22:27
0
\$\begingroup\$

Python 2, 200 (210 - 5%)

a,b=map(int,raw_input().split());c=0;a+=1;i=a*b+a-b;e=[i*'+']
while a-1:
 v=(('|'+' '*b)*a).rstrip();p=' '*((i-len(v))/2);a-=1;c+=1
 for u in range(b):e.insert(0,p+v)
 e.insert(0,p+'+'*len(v))
print'\n'.join(e)

I used string multiplication and stripped extra spaces.

\$\endgroup\$
0
\$\begingroup\$

Vyxal o, 44 bytes (46 - 5%)

(n£¹n-‹⁰½⌈*ð*:\+⁰›n›*›*+:→x,⁰(:₴\|:⁰꘍¥›*p,))←x

Try it Online!

\$\endgroup\$
0
\$\begingroup\$

05AB1E, 27 26 bytes

Takes the height and then block size on seperate lines. 30 bytes if the input format is strict.

Lε'|²úRy²>*>©∍²и®'+×.ø}˜.c

Try it online!

L                         # push range [1 .. h]
 ε                     }  # for y in [1 .. h]:
  '|                     '# push "|"
    ²úR                   # pad with w spaces in the back
       ²>*>               # line length: (w+1)*y+1
           ©              # store the line length in the register
            ∍             # extend the string to this length
             ²и           # push a list with w copies of the string
               ®'+×      '# push a string of "+"*line length
                   .ø     # surround the list with this string

˜                         # flatten into a list of strings
 .c                       # centralize
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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