48
\$\begingroup\$

This challenge is a simple one. Given two inputs, describing the height and width of a Lego piece, you have print an ASCII art representation of it.

Here is how the Lego pieces are supposed to look:

(4, 2)

___________
| o o o o |
| o o o o |
-----------

(8, 2)

___________________
| o o o o o o o o |
| o o o o o o o o |
-------------------

(4, 4)

___________
| o o o o |
| o o o o |
| o o o o |
| o o o o |
-----------

(3, 2)

_________
| o o o |
| o o o |
---------

(1, 1)

o

If you can't tell from the test-cases, the top and bottom are width*2+3 underscores and dashes, and each row has pipes for the sides, o's for the little things, and everything is separated by spaces.

The only exception for this is (1, 1), which is just a single o.

You will never get 0 for any of the dimensions.

This is , so shortest code in bytes wins!

var QUESTION_ID=84050,OVERRIDE_USER=31343;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"http://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(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){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<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="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

\$\endgroup\$
17
  • 2
    \$\begingroup\$ Is it possible that the width or the height will be greater than 10? What range should we support? \$\endgroup\$
    – DJMcMayhem
    Jun 30, 2016 at 2:37
  • 31
    \$\begingroup\$ The special case is a real bummer. \$\endgroup\$ Jun 30, 2016 at 3:03
  • 49
    \$\begingroup\$ In the next few years, I want to see another "Print a Lego piece" challenge that requires writing the code to tell a 3D printer to produce a Lego. \$\endgroup\$
    – Kevin
    Jun 30, 2016 at 8:47
  • 9
    \$\begingroup\$ Wait, "whatever integer range your language supports"? That ain't how LEGO works. The bricks are only available in a handful of very specific dimensions. Even if you add in plates, you only get a couple more. Any script that does not discard input such as (1,7) or (5,3) is complete garbage. \$\endgroup\$
    – RegDwight
    Jul 1, 2016 at 14:43
  • 3
    \$\begingroup\$ Why doesn't the single piece (1,1) have sides? There is a real Lego piece with a single nipple on top of a cube. \$\endgroup\$
    – tcrosley
    Jul 2, 2016 at 0:00

43 Answers 43

1
2
1
\$\begingroup\$

Octave, 97 95 86 bytes

@(w,h){[a=~(1:w*2+3)+95;repmat(['| ' repmat('o ',1,w) '|'],h,1);~a+45],'o'}{(w*h<2)+1}

I used the @atlasologist's method in Python to test (1, 1): (...,'o')[x<2>y]

Thanks to @Luis Mendo for saving 7 bytes: a=ones(1,w*2+3)*'_' to a=~(1:w*2+3)+95 and a./a*'-' to ~a+45

Thanks to @pajonk for saving 2 bytes: f=

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This is not valid Matlab code. You should label as "Octave" only. Also, instead of a./a*'-' can you use ~~a*'-'? Or even ~a+45? \$\endgroup\$
    – Luis Mendo
    Jun 30, 2016 at 16:51
  • \$\begingroup\$ Also, probably you can leave it as an anonymous function (without f=) \$\endgroup\$
    – pajonk
    Jun 30, 2016 at 17:30
1
\$\begingroup\$

J, 59 bytes.

' o|_='&({~)@:((4,~3,2(,~"1)2 0,"1(1 0&($~)@,+:))^:(0===]))
\$\endgroup\$
1
\$\begingroup\$

Retina, 112 111 bytes

Makes the piece the correct width, then adds rows. Performs a substitution at the end if the result was a 1x1. Takes input like 4,2. Byte count assumes ISO 8859-1 encoding.

\d+
$*
1$
¶___¶| |¶---
+s`1(,.*)(¶.* )(.*)
$1__$2o $3--
+sm`1(.*)(^.*$¶)(.*)
$1$2$2$3
,¶

_____¶\| o \|¶-----
o

Try it online

Fun fact:

You can give multiple inputs on separate lines and it will add them together into a single LEGO!

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

Common Lisp, 286 bytes

(let((columns(read))(rows(read)))(when(and(= columns 1)(= rows 1))(progn(write-char #\o)(exit)))(dotimes(i(+(* columns 2)3))(write-char #\_))(terpri)(dotimes(i rows)(format t "| ")(dotimes(i columns)(format t "o "))(format t "| ")(terpri))(dotimes(i(+(* columns 2)3))(write-char #\-)))
\$\endgroup\$
2
  • \$\begingroup\$ this shows you have 285, not 286 bytes. (let((c(read))(r(read)))(when(and(= c 1)(= r 1))(progn(#1=write-char #\o)(exit)))(#2=dotimes #4=(i(+(* c 2)3))(#1# #\_))(terpri)(#2#(i r)#3=(format t "| ")(#2#(i c)(format t "o "))#3#(terpri))(#2# #4# (#1# #\-))) saves 73 bytes. I used c instead of columns, r instead of rows, also #n# and #n= reader macro where you reuse things. \$\endgroup\$
    – user65167
    Feb 25, 2017 at 10:04
  • \$\begingroup\$ This saves 103 bytes: (lambda(c r)(if(=(* c r)1)(format t"o"(exit)))(#1=dotimes #2=(i(+(* c 2)3))(format t"_"))(terpri)(#1#(i r)#3=(format t"| ")(#1#(i c)(format t"o "))#3#(terpri))(#1# #2#(format t"-"))), I think anonymous function is allowed. What I don't like is fact that for (f 1 1) output is not shown (or it's shown but program exits too quickly to see it) but it was in your solution from the beggining. \$\endgroup\$
    – user65167
    Feb 25, 2017 at 19:04
1
\$\begingroup\$

PHP 4.1, 103 bytes

This is based on my answer on https://codegolf.stackexchange.com/a/57883/14732, which was where all the heavy lifting was done.

<?$R=str_repeat;printf($W+$H<3?o:"_%'_".($Z=1+$W*2)."s_
%s-%1$'-{$Z}s-",'',$R('|'.$R(' o',$W).' |
',$H));

This answer requires that short_open_tags and register_globals are enabled (which it is enabled by default).

You can pass the values using the keys W and H, over POST, GET, SESSION and COOKIE.

This outputs warnings to STDERR, which aren't errors. According to https://codegolf.meta.stackexchange.com/a/1655/14732, this is acceptable as long as it isn't disallowed in the question.
Removing the warnings costs me 2 bytes.

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

Racket 174 bytes

(λ(w h)(let((dl(λ(s)(displayln s)))(d(λ(s)(display s))))(for((x(+ 3(* w 2))))(d"_"))
(dl"")(for((x h))(d"| ")(for((y w))(d"o "))(d"|")(dl""))(for((x(+ 3(* w 2))))(d"-"))))

Ungolfed:

(define (f1 w h)
    (let ((dl (λ (s) (displayln s)))
          (d (λ (s) (display s))))
      (for ((x (+ 3 (* w 2))))
        (d "_"))
      (dl "")
      (for ((x h))
        (d "| ")
        (for ((y w))
          (d "o "))
        (d "|")
        (dl ""))
      (for ((x (+ 3 (* w 2))))
        (d "-"))))

Testing:

(f 5 2)

Output:

_____________
| o o o o o |
| o o o o o |
-------------
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 41 bytes

¿⁼η⁼θ¹o≔⁺³×θ²κURκ⁺²ηP×κ_M⁺η¹↓Pκ↗Fη«P×θ o↑

Draws a box to get the vertical sides, then manually draws the top and bottom.

Then, prints the o's line by line.

Link is to verbose version of code.

Try it online!

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

SpecBAS - 87 bytes

1 INPUT w,h: x=w*2+3: ?IIF$(w=1 AND h=1,"o","_"*x+#13+(("| "+("o "*w)+"|"#13)*h)+"-"*x)

Uses an inline-IF to either print single "o" when width and height are 1, otherwise builds up a string. #13 is the line feed character.

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

Scala, 90 bytes

(w:Int,h:Int)=>{val A=2*w+3;if(w*h==1)"o"else s"${"_"*A}\n${s"| ${"o "*w}|\n"*h}${"-"*A}"}

paste the above function into your Scala REPL, and then invoke the function with the width and height arguments.

\$\endgroup\$
4
  • \$\begingroup\$ Hello, and welcome to PPCG! This is a great first post! There is only one small issue: we commonly use Scala, 170 bytes not Scala - 170 bytes. They both work, but out byte snippet counters look for the first, according to my research. \$\endgroup\$ Jul 1, 2016 at 23:21
  • \$\begingroup\$ @NoOneIsHere thanks. fixed. and also shortened the submission from 170 to 94 bytes. Enjoying this... :-) \$\endgroup\$ Jul 2, 2016 at 9:50
  • \$\begingroup\$ @PeterPerháč You need to use Level 1 headers, so not fixed. Instead of **Scala, 94 bytes**, use #Scala, 94 bytes. \$\endgroup\$ Jul 2, 2016 at 13:18
  • \$\begingroup\$ You can use anonymous functions, i.e. {val A=2*w+3;if(w*h==1)"o"else s"${"_"*A}\n${s"| ${"o "*w}|\n"*h}${"-"*A}"} (not snippets, though). \$\endgroup\$ Jul 2, 2016 at 17:30
0
\$\begingroup\$

JavaScript ES6, 134 124 Bytes

function p(e,n){r='repeat';e*n-1?x="_"[r](2*e+3)+"\n"+("|"+" o"[r](e)+" |\n")[r](n)+"-"[r](2*e+3)+"\n":x="o",console.log(x)}
\$\endgroup\$
9
  • \$\begingroup\$ I can shave off 4 bytes by using [r] instead of .repeat: function p(e,n){r='repeat';1==e&&1==n?x="0":x="_"[r](2*e+3)+"\n"+("|"+" o"[r](e)+" |\n")[r](n)+"-"[r](2*e+3)+"\n",console.log(x)} \$\endgroup\$ Jun 30, 2016 at 9:20
  • \$\begingroup\$ The output for 1,1 should be o, not 0. Also, I don't see any use of ES6 here, so you can change the version. \$\endgroup\$
    – Neil
    Jun 30, 2016 at 12:22
  • 1
    \$\begingroup\$ You can replace function p(e,n) with p=(e,n)=> for 6 bytes. \$\endgroup\$
    – cyberbit
    Jun 30, 2016 at 14:14
  • 1
    \$\begingroup\$ You're assigning x= twice. The second assignation can be removed for an extra 2 bytes, and x can be replaced altogether with a console.log( ? : ), bringing it down to 113 bytes: p=(e,n)=>{r='repeat';console.log(e*n-1?"_"[r](2*e+3)+"\n"+("|"+" o"[r](e)+" |\n")[r](n)+"-"[r](2*e+3)+"\n":"o")} ` \$\endgroup\$ Jun 30, 2016 at 15:10
  • 1
    \$\begingroup\$ Guess what, welcome to PPCG! \$\endgroup\$ Jul 1, 2016 at 8:04
0
\$\begingroup\$

JavaScript ECMAScript6 (92 94 91 87 Bytes)

92 Characters

a=(w,h,r='repeat')=>w-h?"__"[r](w)+"__\n"+("|"+" o"[r](w)+" |\n")[r](h)+"--"[r](w)+"---":"o"

Everything below here is Correct

94 Characters

a=(w,h,r='repeat')=>w*h-1?"__"[r](w)+"__\n"+("|"+" o"[r](w)+" |\n")[r](h)+"--"[r](w)+"---":"o"

91 Characters

a=(w,h)=>w*h-1?`${"__"[r='repeat'](w)}__\n`+('|'+" o"[r](w)+' |\n')[r](h)+"-"[r](w*2+3):"o"

87 Characters (Smallest so Far)

a=(w,h)=>w*h-1?'__'[r='repeat'](w)+`__
`+('|'+' o'[r](w)+` |
`)[r](h)+'-'[r](w*2+3):'o'

I took what I learned from the other JavaScript Submissions and made it a lot smaller by writing mine from scratch and then working my way down, turns out you don't need any console.log or alert as by default it will push it to the console when there is an output

I am still working on it to see if I can make it smaller yet

\$\endgroup\$
1
  • \$\begingroup\$ I think your first line of output is one character short. \$\endgroup\$ Jan 11, 2018 at 23:32
0
\$\begingroup\$

Swift, 182 Bytes

func p(w:Int,h:Int){let i=w*2+3;var s="";if w+h<3{s="o"}else{for _ in 0..<i{s+="_"};for _ in 0..<h{s+="\n|";for _ in 0..<w{s+=" o"};s+=" |"};s+="\n";for _ in 0..<i{s+="-"}};print(s)}

If this was a closure implementation the func p(w:Int,h:Int) could be deleted and w replaced with $0 and h replaced with $1 but then it would be only the implementation not the interface so I felt that was cheating...

2nd attempt 180 Bytes

func q(w:Int,h:Int){let l=w*2+3;var s="",a="";if w+h<3{s="o"}else{for _ in 0..<l{s+="_";a+="-"};for x in 0..<h*w{s+=x%h==0 ? "\n| o":x%h==w-1 ? " o |":" o"};s+="\n";s+=a};print(s)}

Improved using ternaries. Only 2 bytes though...

3rd attempt 263 bytes

func r(w:Int,h:Int){let l=w*2+3;var s="";if w+h<3{s="o"}else{for a in 0..<(h+2)*l{if a<l{s+="_";continue};if a>=(h+2)*l-l{s+=a%l==0 ? "\n-":"-";continue};let v=a%l>0&&a%l<l-2;s+=a%l==0 ? "\n|":v&&(a%l)%2==0 ? "o":v&&(a%l)%2==1 ? " ":a%l==l-1 ? "|":" "}};print(s)}

The reason I include this is because my original thought was to decrease the amount of for loops. Whilst this is more verbose it only has the one iteration (also it took me quite a long time so here it is again in a more friendly format):

func r(w: Int, h: Int) {
    let l = w * 2 + 3
    var str = ""
    if w + h < 3 {
        str = "o"
    } else {
        for a in 0..<(h + 2) * l {
            if a < l {
                str += "_"
                continue
            }
            if a >= (h + 2) * l - l {
                str += a % l == 0 ? "\n-" : "-"
                continue
            }
            let v = a % l > 0 && a % l < l - 2
            str += a % l == 0 ? "\n|" : v && (a % l) % 2==0 ? "0" : v && (a % l) % 2 == 1 ? " " : a % l == l - 1 ? "|" : " "
        }
    }
    print(str)
}

There are a lot of ternary conditions here so I'm sure it can be optimised further.

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to the site! Nice first post. \$\endgroup\$
    – user58826
    May 2, 2017 at 21:04
0
\$\begingroup\$

MAWP, 131 bytes

@1A{1M\}>1M!//~[1A~!~]%~!2W3M[1A95W2W5M;]%~
[1A25W;65W1M4W;~[1A84W;77W2W43W1MM;]%~84W;65W1M4W;]~25W;2W3M[1A95W;]

The special case was a pain, but I managed to 'golf' a solution under 150 bytes here.

Output

4 3
___________
| o o o o |
| o o o o |
| o o o o |
-----------

Try it!

\$\endgroup\$
1
2

Your Answer

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

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