text:
Choose from an existing set of weights to make a target sum
When doing weightlifting, I want to make a specific weight by attaching several plates to a bar.
I have the following plates:

6 plates of 1 kg each
6 plates of 2.5 kg each
6 plates of 5 kg each
6 plates of 10 kg each

The bar itself weighs 10 kg.
It's only allowed to attach the plates in pairs - they are attached at each end of the bar, and the arrangement at the two ends must be completely symmetrical (e.g. attaching two 5-kg plates at one end, and one 10-kg plate at the other end is forbidden for reasons of safety).
Make a program or a function that tells me how many plates of each kind I have to use in order to get a given total weight. The input is an integer greater than 11; the output is a list/array/string of 4 numbers. If it's impossible to combine existing plates to get the target weight, output a zero/empty array, an invalid string, throw an exception or some such.
If there are several solutions, the code must output only one (don't make the user choose - he is too busy with other things).
Test cases:
12 -> [2 0 0 0] - 2 plates of 1 kg plus the bar of 10 kg
13 -> [0 0 0 0] - a special-case output that means "impossible"
20 -> [0 0 2 0] - 2 plates of 5 kg + bar
20 -> [0 4 0 0] - a different acceptable solution for the above
21 -> [6 2 0 0] - 6 plates of 1 kg + 2 plates of 2.5 kg + bar
28 -> [0 0 0 0] - impossible
45 -> [0 2 6 0] - a solution for a random number in range
112 -> [2 4 6 6] - a solution for a random number in range
121 -> [6 6 6 6] - maximal weight for which a solution is possible

If your code outputs the numbers in the opposite order (from the heavy plate to the light one), please specify this explicitly to avoid confusion.

Isn't this a dupe of the minimum coin counting question? I don't think the same greedy algorithm fails, except with the restriction of 6 of one kind of plate. I think that might not be sufficient difference, but I'm not sure.

The greedy algorithm doesn't work (not without modification, at least) exactly because the numbers are limited

Related, but that one is ASCII

Yes, the reason I posted was that I was unsure that the modification was significant enough. I posted to try to get community feedback, and I'll remove my comment if it seems like the community disagrees with me.

Can we output all solutions instead of just one?

No, you should choose one. I'll add a clarification.

Can we assume all input to be less than 122?

@busukxuan No - it must work for any number. But in certain languages (e.g. C) you can limit the range at 127, using this guideline. Also, if it fails in a different way for 28 and 122 - it's good enough, as long as it does fail.

I don't think the linked challenge is a duplicate. That one asks to find all subsets with any number of elements, and doesn't have the symmetry restriction. I didn't realized my dupe-hammer worked the way around too, though. I only intented to vote to reopen and gather more opinions @PeterTaylor

@LuisMendo, the symmetry restriction is irrelevant: it just reduces to having 3 pairs of weight 2kg, 3 pairs of 5kg, etc. As for the "all subsets" difference, there are a few other questions which this is a more direct dupe of which have also been closed as a dupe of that one, and I preferred to cut out the middleman.

@PeterTaylor Feel free to mark as dupe again then. I only intended to cast a vote

@LuisMendo, each person only gets one close vote per question.

Jelly, 22 bytes
4ṗạµ×2,5,10,20S€+⁵iƓịḤ

Try it online! or verify all test cases.
How it works
4ṗạµ×2,5,10,20S€+⁵iƓịḤ  Main link. No arguments

4                       Set the left argument and initial return value to 4.
 ṗ                      Take the Cartesian power of [1, 2, 3, 4] and 4, i.e.,
                        generate all 4-tuples of integers between 1 and 4.
  ạ                     Take the absolute difference of all integers in the
                        4-tuples and the integer 4. This maps [1, 2, 3, 4] to
                        [3, 2, 1, 0] and places [0, 0, 0, 0] at index 0.
   µ                    Begin a new, monadic chain. Argument: A (list of 4-tuples)
     2,5,10,20          Yield [2, 5, 10, 20].
    ×                   Perform vectorized multiplication with each 4-tuple in A.
              S€        Sum each resulting 4-tuple.
                +⁵      Add 10 to each sum.
                   Ɠ    Read an integer from STDIN.
                  i     Find its first index in the array of sums (0 if not found).
                     Ḥ  Unhalve; yield the list A, with all integers doubled.
                    ị   Retrieve the 4-tuple at the proper index.

MATL, 29 28 bytes
4t:qEZ^!"[l2.5AX]@Y*10+G=?@.

For inputs that have no solution this produces an empty output (without error).
Try it online!
Explanation
4           % Push 4
t:q         % Duplicate 4 and transform into range [0 1 2 3]
E           % Multiply by 2: transform into [0 2 4 6]
Z^          % Cartesian power. Each row is a "combination" of the four numbers
!           % Transpose
"           % For each column
  [l2.5AX]  %   Push [1 2.5 5 10]
  @         %   Push current column
  Y*        %   Matrix multiply. Gives sum of products
  10+       %   Add 10
  G=        %   Compare with input: are they equal?
  ?         %   If so
    @       %     Push current column, to be displayed
    .       %     Break loop
            %   Implicit end
            % Implicit end
            % Implicit display

Mathematica, 70 bytes
Select[FrobeniusSolve[{2,5,10,20},2#-20],AllTrue[EvenQ@#&&#<7&]][[1]]&

Anonymous function. Takes a number as input, and either outputs a list or errors and returns {}[[1]] if there is no solution.

Jelly, 25 bytes
×2,5,10,20S+⁵⁼³
4ṗ4’ÇÐfḢḤ

Try it here.

2,5,10,20 -> 2,5,⁵,20

really... isn't , a dyad? My whole life is a lie

@LeakyNun , is a dyad, but it can also be used for literals. 2,5,⁵,20 isn't a literal though (2,5 and 20 are, but ,, ⁵ and , are atoms), so you'd need something to combine the links.

Python 3, 112 bytes
lambda n:[i for i in[[i//4**j%4*2for j in range(4)]for i in range(256)]if i[0]+2.5*i[1]+5*i[2]+10*i[3]+10==n][0]

An anonymous function that takes input, via argument, of the target mass and returns the number of each plate as a list. If no solution exists, an error is thrown. This is pure brute force.
How it works
lambda n                                   Anonymous function with input target mass n
...for i in range(256)                     Loop for all possible arrangement indices i
[i//4**j%4*2for j in range(4)]             Create a base-4 representation of the index i,
                                           and multiply each digit by 2 to map from
                                           (0,1,2,3) to (0,2,4,6)
[...]                                      Package all possible arrangements in a list
...for i in...                             Loop for all possible arrangements i
i...if i[0]+2.5*i[1]+5*i[2]+10*i[3]+10==n  Return i if it gives the target mass
[...]                                      Package all solutions in a list
:...[0]                                    Return the first list element. This removes any
                                           multiple solutions, and throws an error if there
                                           being no solutions results in an empty list

Try it on Ideone

Brachylog, 50 bytes
,L##l4,L:{.~e[0:3]}a:[2:5:10:20]*+:10+?,L:{:2*.}a.

Returns false when not possible.

Pyth, 34 31 25 bytes

h+fqQ+;s*VT[1 2.5 5;)yMM^U4 4]*4]0
yMh+fqQ+;s*VT[2 5;y;)^U4 4]*4]0
yMhfqQ+;s*VT[2 5;y;)^U4 4

Test suite.
Errors in impossibility.
This is essentially a brute-force.
This is quite fast, since there are only 256 possible arrangements.

Scala, 202 bytes
Decided Scala doesn't get much love here, so I present a (probably not optimal) solution in Scala.
def w(i:Int){var w=Map(20->0,10->0,5->0,2->0);var x=i-10;while(x>0){
var d=false;for(a<-w.keys)if(a<=x & w(a)<6 & !d){x=x-a;w=w.updated(a,w(a)+2);d=true;}
if(!d){println(0);return;}}
println(w.values);}

The program outputs in reverse order and with extra junk compared to solutions in post. When a solution is not found, prints 0.
Note: I could not remove any of the newlines or spaces because Scala is dumb, so I think to reduce size, the method must be redone unless I missed something obvious.

APL, 40 bytes
{2×(4⍴4)⊤⍵⍳⍨10+2×,⊃∘.+/↓1 2.5 5 10∘.×⍳4}

In ⎕IO←0. In English:

10+2×,∘.+⌿1 2.5 5 10∘.×⍳4: build the array of all the possible weights, by computing the 4D outer sum of the weights per weight type;
⍵⍳⍨: search the index of the given. If not found the index is 1+the tally of the array at step 1;
(4⍴4)⊤: represent the index in base 4, that is, compute the coordinate of the given weigth in the 4D space;
2×: bring the result to problem space, where the coordinates should be interpreted as half the number of the plates.

Example:
              {2×(4⍴4)⊤⍵⍳⍨10+2×,⊃∘.+/↓1 2.5 5 10∘.×⍳4}112
    2 4 6 6
Bonus: since APL is an array language, several weights can be tested at once. In this case the result is transposed:
      {2×(4⍴4)⊤⍵⍳⍨10+2×,⊃∘.+/↓1 2.5 5 10∘.×⍳4}12 13 20 21 28 45 112 121
2 0 0 6 0 0 2 6
0 0 0 2 0 2 4 6
0 0 2 0 0 2 6 6
0 0 0 0 0 2 6 6

JavaScript (ES6), 109 bytes
n=>`000${[...Array(256)].findIndex((_,i)=>i+(i&48)*9+(i&12)*79+(i&3)*639+320==n*32).toString(4)*2}`.slice(-4)

Returns 00-2 on error. Alternative solution that returns undefined on error, also 109 bytes:
n=>[...Array(256)].map((_,i)=>`000${i.toString(4)*2}`.slice(-4)).find(s=>+s[0]+s[1]*2.5+s[2]*5+s[3]*10+10==n)


text:
Print a Lego piece
This challenge is a simple ascii-art 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 code-golf, 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="
"+e.body.replace(OVERRIDE_REG,"")+"
")});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;/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}
 <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">

Leaderboard

	Author	Language	Size

Winners by Language

Language	User	Score

{{PLACE}}	{{NAME}}	{{LANGUAGE}}	{{SIZE}}	Link

{{LANGUAGE}}	{{NAME}}	{{SIZE}}	Link

Is it possible that the width or the height will be greater than 10? What range should we support?

The special case is a real bummer.

@DrGreenEggsandIronMan definitely could be greater than 10. I guess whatever integer range your language supports (bearing in mind the standard loophole about abusing this).

Do (2, 1) and (1, 2) look similar to the bigger ones? Can we have an extra space at the end of each line? Ending newline required or optional?

@aditsu yeah, they do, (1, 1) is the only exception. Trailing whitespace is not allowed, except for a single trailing newline.

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.

- will be better as "

@Kevin such a thing can already be done - see (e.g.) http://www.thingiverse.com/thing:231651 for an example of exactly that.

@Kevin i was hoping for something like this when i clicked on this hot network question

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.

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.

@tcrosley i know, I just wanted a special case, and there also exist (1,1) lego pieces without sides

Really (re ones with no sides).  I don't think the sets our grand-kids play with have any like that, but there's aren't the mega sets with hundreds of pieces.

@RegDwight you are only seeing the top of it. It could be bound underneath.

@tcrosley this kinda thing: http://s.ecrater.com/stores/196820/5355aaa76f14f_196820b.jpg

http://www.thingiverse.com/search/page:1?q=lego

a top down 1x1 lego view

Befunge, 165 227 bytes
&::&*:1` v
v+3*2:\/\_"o",@
v       _$ v<
>"_",1-:^  2
v:,,"| ",*5<
v         _v
>" o",,1-:^$
>*v>\     #\^
5 #|:-1,"|"<
^2$<
v1, *95<
- >2*3+^
>:    #^_@

Not as much whitespace as before, but there are still gaps. The principle is the same as in the previous solution, but the layout is different. This time, to check if both numbers are 1, I'm just taking their product and seeing if the result is greater than 1.

Old solution (227 bytes)
v           v       <
&   >>\:2*3+>"_",1-:|
>&:1`|v ,,"| ",*52:$<   :\<
    #\v         <
     :>" o",,1-:|
     1          >"|",$\1-:|
    \`            @       $
    ^_"o",@>:!    |       2
           ^-1,*95<+3*2,*5<

It might be possible to golf it more. Just look at all that whitespace!
Here's my poor attempt at an explanation in MSPaint picture form:

Code flows in the direction of the arrow.

oh. my. god. Blows my mind

V, 43, 40, 38 36 bytes
One of the longest V answers I've ever written...
Àio ddÀPñóo î½o
u2Pí.«/| °|
Vr-HVr_

Try it online!
Since this contains unicode and unprintable characters, here is a reversible hexdump:
0000000: c069 6f20 1b64 64c0 50f1 f36f 20ee bd6f  .io .dd.P..o ..o
0000010: 0d0a 7532 50ed 2eab 2f7c 20b0 7c0d 0a56  ..u2P.../| .|..V
0000020: 722d 4856 725f                           r-HVr_

This challenge is about manipulating text, so perfect for V! On the other hand, V is terrible at conditionals and math, so the differing output for (1, 1) really screwed it up... :(
Explanation:
À                   "Arg1 times:
 io <esc>           "Insert 'o '
         dd         "Delete this line, and
           À        "Arg2 times:
            P       "Paste it

Now we have 'Height' lines of o's with spaces between them.
ñ                   "Wrap all of the next lines in a macro. This makes it so that if any
                    "Search fails, execution will stop (to handle for the [1, 1] case)
 ó                  "Search and replace
  o î½o             "'o'+space+0 or 1 newlines+another 'o'

u                   "Undo this last search/replace
 2P                 "Paste twice
   í                "Search and replace on every line
    .«/| °|         "A compressed regex. This surrounds every non-empty line with bars.

Vr-                 "Replace the current (last) line with '-'
   H                "Move to line one
    Vr_             "Replace this line with '_'

Non-competing version (31 bytes):
Try it online!
This version uses several features that are newer then this challenge to be 5 bytes shorter!
Second explanation:
ddÀP

which is "Delete line, and paste it n times" is replaced with ÀÄ which is "Repeat this line n times". (-2 bytes)
óo î½o
u

which was "Replace the first match of this regex; Undo" was replaced with
/o î½o

Which is just "Search for a match of this regex" (-1 byte)
And lastly, Ò is just a simple synonym for Vr, which both "Replace every character on this line with 'x'". (-2 bytes)

how come it seems broken at the bottom with this http://v.tryitonline.net/#code=w4BpbyAbZGTDgFDDscOzbyDDrsK9bwp1MlDDrS7Cqy98IMKwfApWci1IVnJf&input=&args=NTA+OTk5

@meepl I really have no idea. It works on 50x959 but if you increase the width or height it stops working. I'm guessing it's most likely a restriction intentionally placed on the website to prevent extremely large programs from being ran.

TIO limits the output to 100 KB, mainly to prevent the frontend from crashing your browser.

32 16-bit little-endian x86 machine code, 57 54 51 bytes
3 bytes less thanks to @ninjalj.
Heavily rewrote the code and have managed to shave off another 3 bytes
In hex
FCBA6F208D48FFE20492AAEB2389D941D1E14151B05FF3AAEB0BB87C20AB89D992F3AB92AAB00AAA4E7DEF59B02DF3AA91AAC3

Input: BX=width, SI=height, DI points to the buffer that receives result as a NULL-terminated string with lines separated by "\n"
Disassembly:
fc            cld
ba 6f 20      mov    dx,0x206f      ;Storing ' o' in DX for later use
8d 48 ff      lea    cx,[bx+si-0x1] ;CX=width+height-1
e2 04         loop   _main0         ;--CX & brahch if not zero
92            xchg   dx,ax          ;(1,1) case, swap DX & AX
aa            stosb                 ;AL == 'o', CX == 0
eb 23         jmp    _end
_main0:
89 d9         mov    cx,bx
41            inc    cx
d1 e1         shl    cx,1
41            inc    cx           ;Calculate (width+1)*2+1
51            push   cx           ;and save it for future use
b0 5f         mov    al,0x5f      ;'_'
f3 aa         rep    stosb        ;Output the whole line of them
eb 0b         jmp    _loopstart   ;Jump into the loop
_loop:
b8 7c 20      mov    ax,0x207c    ;' |'
ab            stosw               ;Output it once (left bar + space)
89 d9         mov    cx,bx        ;Copy width
92            xchg   dx,ax        ;AX == ' o'
f3 ab         rep    stosw        ;Output it CX times
92            xchg   dx,ax        ;Swap values back, AL == '|'
aa            stosb               ;Output only the right bar
_loopstart:
b0 0a         mov    al,0x0a      ;Newline. Can be replaced with mov ax,0x0a0d for windows newline
aa            stosb               ;convention (at the cost of 1 byte), with stosb replaced with stosw
4e            dec    si           ;Height--
7d ef         jge    _loop        ;Continue if si >= 0 (this accounts for the dummy first pass)
59            pop    cx
b0 2d         mov    al,0x2d      ;'-'
f3 aa         rep    stosb        ;Output bottom line
_end:
91            xchg   cx,ax        ;CX == 0, so swap to get zero in AL
aa            stosb               ;NULL-terminate output
c3            retn

Would be shorter as 16-bit: -3 bytes for 3 66h prefixes, +1 byte for "\r\n" line termination.

You should put spaces between the crossed-out numbers and the current numbers in your byte count, for readability.

Python 2, 75 73 72 bytes
lambda x,y:(x*'__'+'___\n'+('| '+'o '*x+'|\n')*y+'-'*(x*2+3),'o')[x<2>y]

Returns a string, with a conditional to handle the 1,1 block.
Thanks to Lynn and Chepner for two bytes

lambda x,y:('_'*x*2+'___\n'+ etc. saves a byte.

Knock off another byte with x*'__' instead of 2*x*'_'.

Just join this Comunity, sorry for asking. How can i see it run? i paste it in the terminal and just prints <function <lambda> at 0x......>. How can i test this?

@Miguel assign it to a variable. It'll return the value of the function: f=lambda x:x+1; print(f(9))

One more question if not to complicated to answer. How can you trace the bits so precisely?

@Miguel, 1 character = 1 byte.

CJam, 34
'_q~'o*"||"\*S*f*f+'-f+zN*_,H='o@?

Try it online
Explanation:
'_        push a '_' character
q~        read and evaluate the input (height and width)
'o*       repeat the 'o' character <width> times
"||"\*    join the "||" string by the string of o's (putting them in between)
S*        join with spaces (inserting a space between every 2 characters)
f*        repeat each character <height> times, making it a separate string
f+        prepend '_' to each string
'-f+      append '-' to each string
z         transpose the array of strings
N*        join with newlines; lego piece is ready, special case to follow
_,        duplicate the string and get its length
H=        compare with H=17
'o        push 'o' for the true case
@         bring the lego piece to the top for the false case
?         if the length was 17, use 'o' else use the lego piece

Ruby, 59 56 bytes
Anonymous function, returns a multiline string. Try it online!
-3 bytes thanks to borrowing a trick from @El'endiaStarman
->w,h{w*h<2??o:?_*(x=2*w+3)+$/+(?|+' o'*w+" |
")*h+?-*x}

Java, 318 312 297 294 260 258 bytes
Saved 15 bytes thanks to cliffroot!
interface a{static void main(String[]A){int b=Byte.valueOf(A[0]),B=Byte.valueOf(A[1]),C=3+b*2;String c="";if(b<2&B<2)c="o";else{for(;C-->0;)c+="_";for(;B-->0;){c+="\n|";for(C=b;C-->0;)c+=" o";c+=" |";}c+="\n";for(C=3+b*2;C-->0;)c+="-";}System.out.print(c);}}

It works with command line arguments.
Ungolfed In a human-readable form:
interface a {
    static void main(String[] A) {
        int b = Byte.valueOf(A[0]),
            B = Byte.valueOf(A[1]),
            C = 3 + b*2;
        String c = "";
        if (b < 2 & B < 2)
            c = "o";
        else {
            for (; C-- > 0;)
                c += "_";
            for (; B-- > 0;) {
                c += "\n|";
                for (C = b; C-- >0;)
                    c += " o";
                c += " |";
            }
            c += "\n";
            for(C = 3 + b*2; C-- >0;)
                c += "-";
        }
        System.out.print(c);
    }
}

Yes, it's still difficult to understand what's going on even when the program is ungolfed. So here goes a step-by-step explanation:
static void main(String[] A)

The first two command line arguments -which we'll use to get dimensions- can be used in the program as A[0] and A[1] (respectively).
int b = Byte.valueOf(A[0]),
    B = Byte.valueOf(A[1]),
    C = 3 + b*2;
String c = "";

b is the number of columns, B is the number of rows and C is a variable dedicated for use in for loops.
c is the Lego piece. We'll append rows to it and then print it at the end.
if (b < 2 & B < 2)
    c = "o";
else {

If the piece to be printed is 1x1, then both b (number of columns) and B (number of rows) should be smaller than 2. So we simply set c to a single o and then skip to the statement that System.out.prints the piece if that's the case.
for (; C-- > 0; C)
    c += "_";

Here, we append (integerValueOfA[0] * 2) + 3 underscores to c. This is the topmost row above all holes.
for (; B > 0; B--) {
    c += "\n|";
    for(C = b; C-- > 0;)
        c+=" o";
    c += " |";
}

This is the loop where we construct the piece one row at a time. What's going on inside is impossible to explain without examples. Let's say that the piece is 4x4:
Before entering the loop, c looks like this:
___________

After the first iteration (\n denotes a line feed):
___________\n
| o o o o |

After the second iteration:
___________\n
| o o o o |\n
| o o o o |

After the third iteration:
___________\n
| o o o o |\n
| o o o o |\n
| o o o o |

.
c += "\n";
for (C = 3 + b*2; C-- > 0;)
    c += "-";

Here, we append (integerValueOfA[0] * 2) + 3 hyphens to the piece. This is the row at the very bottom, below all holes.
The 4x4 piece I used for explaining the for loop where the piece is actually constructed now looks like this:
___________\n
| o o o o |\n
| o o o o |\n
| o o o o |\n
| o o o o |\n
-----------

System.out.print(c);

And finally, we print the piece!

Probably Revision 3 made this the longest post I've ever made on Stack Exchange.

You can move C variable from for loops int b=Byte.valueOf(A[0]),B=Byte.valueOf(A[1]),C. In all your for loops it also seems like you can use C-->0; checks, makes it 298, http://pastebin.com/uj42JueL

some creative usage of for loops for few bytes saved – http://pastebin.com/dhNCpi6n

if you convert your arguments to bytes first, then your check is size of brick is 1x1 will be if(b==1&B==1) which allows you to save over 20 bytes

also for the case 1x1 instead doing this System.out.print('o');return;, you could set c='o' and placed logic for different bricks in else block. then having single print statement and no return allow you to save some additional bytes

What is the \r nonsense? I don't think this produces the required output...

@R.. \r is a carriage return and \n is a linefeed. Because a carriage return followed by a linefeed is interpreted as a single newline on pretty much all modern computers thanks to Microsoft, I decided to make the code shorter by not sticking to one type of line ending.

@dorukayhan: Even if we do accept that claim (which I don't; \r is junk before the newline in my book and in all text editors I use), a lone \r, which you have separating the last 2 "lines", is certainly not a newline.

@R.. I just fixed it.

Turns out I don't need \rs!

I know it's been almost a year, but you can still golf quite a few things for -20 bytes: (238 bytes) interface a{static void main(String[]A){int b=new Byte(A[0]),B=new Byte(A[1]),C=3+b*2,D=C;String c="o";if(b>1|B>1){for(c="";C-->0;c+="_");for(;B-->0;c+=" |")for(c+="\n|",C=b;C-->0;c+=" o");for(c+="\n";D-->0;c+="-");}System.out.print(c);}} Summary of what I've changed: Byte.valueOf(..) to new Byte(..); Removed else; I've put everything inside the for-loops (both at the front and back) to limit brackets and semicolons; Removed the second C=3+b*2 by adding a ,D=C after the first.

Minkolang 0.15, 58 57 56 bytes
Yes, that's right. I golfed off one two stinkin' little bytes...
nn$d*1-5&"o"O.rd2*3+$z1$([" o"]" ||"2Rlkr$Dlz["-_"0G]$O.

Try it here!
Explanation
nn                Take two numbers from input (stack is now [w h])

                  C special case C
  $d              Duplicate stack
    *1-           Multiply and subtract 1
       5&         Jump 5 spaces if truthy
         "o"O.    Top of stack was 1*1-1=0, so output "o" and stop.

                     C precalculates width of top and bottom lines for later use C
         r           Reverse stack (now [h w])
          d          Duplicate top of stack
           2*3+      Multiply top of stack by 2 and add 3
               $z    Pop this and store in register (z = 2*w+3)

                                       C generates the row C
                 1$(                   Open while loop prepopulated with top of stack
                    [" o"]             w times, push "o "
                          " ||"        Push "|| "
                               2R      Rotate twice to the right
                                 l     Push newline (10)
                                  k    Break out of while loop

                                           C duplicates the row h times C
                                   r       Reverse stack
                                    $D     Duplicate whole stack h times
                                      l    Push newline

                     C this is for the top and bottom lines C
        z[           Open for loop that repeats z times
          "-_"       Push "_-"
              0G     Relocate top of stack to bottom of stack
                ]    Close for loop

                 $O.    Output whole stack as characters and stop.

Okay, that's two significant rewrites of the explanation for two bytes saved. I don't think I can or will golf anything more out of this one. :P

The first byte is the hardest step... the beginning of a 1000 bytes begins with a single bit...

brainfuck, 391 bytes
I know this can be golfed down more, but at this point I'm just glad it works. I will continue to work to golf it down.
+++++[-<+++[-<+++<++++++<+++++++<++<++++++++>>>>>]<<+<+<<+<++>>>>>>>]<<<<+<++<->>>>>>,<,>>++++++[<--------<-------->>-]<<->>+<<[>>-<<[>>>+<<<-]]>>>[<<<+>>>-]<[<->>>+<<<[>>>-<<<[>>>>+<<<<-]]>>>>[<<<<+>>>>-]<[<<<<<<<.[-].]<<<+>-]<<+>[->++>+<<]>+++[-<<<<.>>>>]>[-<<+>>]<<<<<<<<<.>>>>>>><[->[->+>+<<]<<<<<<.>>>>>>>[<<<<<<.>.>>>>>-]>[-<<+>>]<<<<<<<.<.<.>>>>>>]>[->++>+<<]>+++[-<<<.>>>]>[-<<+>>]<<

Input needs to be given as just two digits. As in, to do (8, 2) you would just enter 82.
Try it online!
Breakdown:
First put the necessary characters into the tape: (newline)| o_-
+++++[-<+++[-<+++<++++++<+++++++<++<++++++++>>>>>]<<+<+<<+<++>>>>>>>]<<<<+<++<->>>>>

Then collect the input into two cells and subtract 48 from each (to get the numeric value and not the numeral character)
>,<,>>++++++[<--------<-------->>-]<<

Next, check for the special case of (1, 1) (Note that just this check accounts for 109 bytes of the code). As if ifs weren't hard enough to do in brainfuck, we have a nested if:
->>+<<[>>-<<[>>>+<<<-]]>>>[<<<+>>>-]<[<->>>+<<<[>>>-<<<[>>>>+<<<<-]]>>>>[<<<<+>>>>-]<[<<<<<<<.[-].]<<<+>-]<<+

The following is the structure to check if a cell x is zero or nonzero:
temp0[-]+
temp1[-]
x[
 code1
 temp0-
 x[temp1+x-]
]
temp1[x+temp1-]
temp0[
 code2
temp0-]

However in a nested if, we need to have 4 temporary cells.
Now we get to the actual printing of characters:
Print the top bar and a newline:
>[->++>+<<]>+++[-<<<<.>>>>]>[-<<+>>]<<<<<<<<<.>>>>>>>

Print a |, a row of o's, another | and a newline a number of times equal to the height:
<[->[->+>+<<]<<<<<<.>>>>>>>[<<<<<<.>.>>>>>-]>[-<<+>>]<<<<<<<.<.<.>>>>>>]

And print the bottom bar (no newline needed here):
>[->++>+<<]>+++[-<<<.>>>]>[-<<+>>]<<

Jolf, 36 bytes
?w*jJρΡ,a+3ώj+2J'-"-+"d*'_lH"  ' o'o
?w*jJ                             'o   return "o" if j * J - 1
       ,a                              make a box
         +3ώj                           of width +3ώj = 3+2*j
             +2J                        of height +2J = 2+J
                '-                      specifying corners as "-"
      Ρ           "-+"                 replacing the first run of "-"s
                      d*'_lH            with a run of "_"s of equal length
     ρ                      "  '       replacing all "  "
                               ' o      with " o"

Jolf, 24 bytes, noncompeting
Well, I made a better box builtin.
?w*jJ,AhώjJ"_-'_-'|' o'o

Jolf, 38 37 bytes
?w*jJΆ+*'_γ+3ώjS*JΆ'|*j" o' |
"*'-γ'o

Simple stuff, really. Saved a byte by noting that !Ζ (math zeta, or the stand deviance) is only 0 when both arguments are 1, and is falsey otherwise (for our case).

Retina, 52 bytes
Byte count assumes ISO 8859-1 encoding. Note that the sixth line is supposed to contain a single space.
\G1?
$_¶
1*

.+
|$&|
\G.
_
r`.\G
-
s`^.{17}$|1
o

Try it online!
Input is in unary, using 1 as the unary digit, space as a separator and height followed by width.
Explanation
All stages in this program are bare substitutions, occasionally with a regular regex modifier (no repetition or loops, no other types of stages). It doesn't even use Retina-specific substitution features, apart from the usual ¶ alias for linefeeds.
\G1?
$_¶

The purpose of this is to "multiply" the two inputs. Our goal is to create h+2 rows with w 1s each (h+2 so that we can turn the top and bottom into _ and - later). The \G anchor requires the match to start where the last one left off. That is, if we ever fail to match a character in the string, further characters won't match either. We use this to match only the 1s in h, but not in w because the regex doesn't allow the space that separates them to be matched. However, we also make the 1 optional, so that we get an additional empty match at the end of h. That's h+1 matches. Each of those is replaced with the entire input ($_) followed by a linefeed. w itself remains untouched which gives us the h+2nd copy. Say the input was 11 1111, then we've now got:
11 1111
11 1111
11 1111
 1111

That's pretty good. We've got some extra stuff, but the h+2 copies of w are there.
1*

Note that there's a space at the end of the first line. This removes those prefixes from the lines so that we only have the ws afterwards.

Ah well, that doesn't really work with SE's formatting... the first line is empty and the second line is supposed to contain a single space. This inserts spaces into every possible position, i.e. at the beginning and end of each line and between every pair of 1s:
 1 1 1 1
 1 1 1 1
 1 1 1 1
 1 1 1 1

We will turn these into os later
.+
|$&|

This simply wraps every line in a pair of |:
| 1 1 1 1 |
| 1 1 1 1 |
| 1 1 1 1 |
| 1 1 1 1 |

Now we take care of the top and bottom:
\G.
_

Time for \G to shine again. This matches each character on the first line and turns it into a _.
r`.\G
-

Same thing, but due to the r modifier (right-to-left mode), this matches the characters on the last line and turns them into -. So now we've got:
___________
| 1 1 1 1 |
| 1 1 1 1 |
-----------

There's only two things left to do now: turn those 1 into os, and if the input was 1 1 then turn the entire thing into o instead. We can handle both of those with a single stage:
s`^.{17}$|1
o

s is regular singleline mode (i.e. it makes . match linefeeds). If the input was 1 1 the result will have the minimum size of 17 characters so we can match it with ^.{17}$ and replace it with o. Otherwise, if that fails, we'll just match all the 1s and replace those with o instead.

JavaScript (ES6), 89 86 bytes
(x,y,g=c=>c[r=`repeat`](x*2+3))=>x*y-1?g(`_`)+`
`+`| ${`o `[r](x)}|
`[r](y)+g(`-`):`o`

Edit: Saved 3 bytes thanks to @Shaggy.

Save 3 bytes by aliasing repeat.

05AB1E, 33 bytes
Code:
*i'oë¹·3+©'_×¶²F'|„ o¹×„ |¶}®'-×J

Explanation:
*i'o                               # If both input equal 1, push "o"
    ë                              # Else, do...
     ¹·3+                          # Push input_1 × 2 + 3
         ©                         # Copy this number to the register
          '_×                      # Multiply by "_"
             ¶                     # Push a newline character
              ²F           }       # Do the following input_2 times:
                '|                 # Push "|"
                  „ o              # Push " o"
                     ¹×            # Multiply this by input_1
                       „ |         # Push " |"
                          ¶        # Push a newline character
                            ®      # Retrieve the value from the register
                             '-×   # Multiply by "-"
                                J  # Join everything and implicitly print.

Uses the CP-1252 encoding. Try it online!.

Befunge, 144 Bytes
I would have prefered to comment to this post, but I don't have the reputation yet, so I'm putting an answer of my own, which works a similar way, but is slightly more compact
&::&*:1`v
v3*2:\/\_"o",@
>+:  v   >52*," |",, v
>,1-:vLEG O MAKERv::\<
^"_" _$\:|<v "o "_v
v52:+3*2$<,>,,1-:^$
>*,v <    ^"|":-1\<
v-1_@,
>:"-"^

you can test the code here

Python 2, 71 bytes
lambda x,y:('o',x*'__'+'___\n'+'| %s|\n'%('o '*x)*y+'-'*(x*2+3))[x+y>2]

Welcome to PPCG! Nice first post!

Reng v.4, 82 bytes, noncompeting
I pushed a bug fix that fixes functions being overwritten by themselves (please don't ask; my stuff is haunted)
i#wi#hhw+2e1+ø ~*x}o:{"-"ö<
"_"{:o}w2*3+#xx*2ø
"o"o~
ö"|"o"o"{Wo:o}w*"| "ooh1-?^#h

Takes input as space-joined numbers, like 4 2. Try it here!

I pushed a bug fix that fixes functions being overwritten by themselves ... Well, that's an interesting bug to have

Bash, 186,163,156, 148,131, 130 Bytes
 ## Arg1 - Lego width
 ## Arg2 - Lego height
function print_lego() {
(($1+$2>2))&&{
printf _%.0s `seq -1 $1`
echo
for((i=$2;i--;)){
 printf \|
 for((j=$1;j--;)){
  printf o
 }
 echo \|
}
printf =%.0s `seq -1 $1`
echo
}||echo o
}

Note: If you really need the lego to have hyphens for the last line, then change the last printf to
printf -- -%.0s `seq -1 $1`

and add two bytes.

Wouldn't this be quite a bit shorter if it wasn't wrapped in a function? Also, I'm not an expert in bash but it looks like it's got some extra whitespace.

It would be ~170 as a one-liner: (($x+$y==2))&&echo o||{ printf _%.0s $(seq -1 $x);echo;for((i=0;i<$y;i++));do printf \|;for((j=0;j<$x;j++));do printf o;done;echo \|;done;printf =%.0s $(seq -1 $x);echo;}

If you use (), you don't need the keyword function to declare a function. There is an alternate for syntax using braces, e.g: for((j=$1;j--;));{ printf o;}. As shown in the previous example, you can save some characters by decrementing and testing in for's second expression.  You can use backticks instead of $(cmd).

@ninjalj Thanks, I'm new to code golf -- that squeezes another ~17 bytes off, the one-liner is now 152: (($x+$y==2))&&echo o||{ printf _%.0s \seq -1 $x`;echo;for((i=$y;i--;)){ printf |;for((j=$x;j--;)){ printf o;};echo |;};printf =%.0s `seq -1 $x`;echo;}`

Dollar signs are optional in arithmetic context, so you can shave a few more bytes by changing (($something)) to ((something)) throughout. ($1 still needs the dollar sign to disambiguate it from the literal 1.)

PowerShell v2+, 76 bytes
param($x,$y)if($x+$y-2){"_"*($z=$x*2+3);"|$(" o"*$x) |`n"*$y+'-'*$z;exit}"o"

Takes input, then checks an if statement. Since non-zero values are truthy in PowerShell, so long as at least one of $x and $y are not equal to 1, the if will be true.
Inside the if, there's a series of string multiplications. First, we construct our string of underscores, saving $z for later. That gets placed on the pipeline. Next we construct our string of sides and pegs (with the pegs multiplied by $x), done $y times, and concatenate that with our dashes $z times. That string is then placed on the pipeline and we exit. The pipeline is flushed and printing is implicit. Note that we get the newline between the underscores and the first row of pegs for free, since the default .ToString() separator for array output is `n (and we're outputting an array of strings).
If the if is false, we're in the special 1 1 case, so we just put "o" by itself on the pipeline and exit, with printing again implicit.
Examples
PS C:\Tools\Scripts\golfing> .\print-a-lego-piece.ps1 1 1
o

PS C:\Tools\Scripts\golfing> .\print-a-lego-piece.ps1 5 3
_____________
| o o o o o |
| o o o o o |
| o o o o o |
-------------

Perl 5 - 84 77 bytes
84 Bytes
sub l{($x,$y)=@_;$w=3+2*$x;warn$x*$y<2?"o":'_'x$w.$/.('| '.'o 'x$x."|\n")x$y.'-'x$w}

77 Bytes. With some help from Dom Hastings
sub l{($x,$y)=@_;$x*$y<2?o:'_'x($w=3+2*$x).('
| '.'o 'x$x."|")x$y.$/.'-'x$w}

First I was confused as to why someone would go to the effort of using warn in a golf program, but then I realized you're using it because it's shorter than print. Nice!

Yeah, I think in Perl 6 you can take another byte off by using say instead of warn

You can do that in Perl 5 too, just that it's not enabled by default. I think that you can get around that in code-golf by calling your script from the command line with -E instead of -e, enabling all the extensions. I'm new to this place so I don't know exactly where it's specified how to count the scores though.

Oh really, I didn't know that. I'm new here as well so I'm also not sure

I think you can shorten this to 76 bytes... If you're using a function I believe returning the string is acceptable (see the JS answer, saving you 4 bytes for warn), you don't need quotes around the "o" (you can use a bareword for another -2), if you inline the calculation of $w you should save another byte ('_'x($w=3+2*$x) vs. $w=3+2*$x; ... '_'x$w) and lastly, you can change the \n for a literal newline. Hope that helps!

Ah nice, I didn't spot the inline assignment. The literal newline is amazing

@Kaundur Happy to help, I think you can drop the last .$/ as well since there doesn't appear to be a trailing newline requirement... Can't think of any more savings just yet...

@DomHastings Correct again, must have been left over from some earlier version of the code

Cut it down to 70 including a -p: Try it online!

Batch, 172 170 bytes
@echo off
if "%*"=="1 1" echo o&exit/b
set o=
for /l %%i in (1,1,%1)do call set o=%%o%% o
echo ---%o: o=--%
for /l %%i in (1,1,%2)do echo ^|%o% ^|
echo ---%o: o=--%

Edit: Saved 2 bytes thanks to @CᴏɴᴏʀO'Bʀɪᴇɴ @EʀɪᴋᴛʜᴇGᴏʟғᴇʀ.
I can save 7 bytes if I can assume delayed expansion is enabled.

%%o%% instead of %o%?

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ %o% would be replaced with original value of o each time, so that o would only ever equal " o". %%o%% goes through as an argument to call of %o%, which then uses the current value of o.

Why don't you... just do set o=%o% o?

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ %o% gets expanded before the for loop is parsed, so the loop reads for /l %i in (1,1,8) do call set o= o which is obviously pointless.

Why don't you do set o=%%o%% o then (-5)?

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ That would expand to for /l %i in (1,1,8) do set o=%o% o which would set o to %o% o which still isn't right.

If o is o o o  doesn't set o=%o% o set o to o o o o ?

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ It depends on when the statement is parsed. If the set is its own statement, then it parses as set o= o o o o. If it's inside a for loop, then it's parsed as set o= o as I mentioned above.

I think you can do for /l => for/l

Also, if "%*"=="1 1" => if"%*=="1 1

@CᴏɴᴏʀO'Bʀɪᴇɴ Thanks for reminding me that for/l actually has one place where I don't need a space, but I couldn't get your other suggestion to work.

Huh. I thought it would work.

C, 202 191 bytes
#define p printf
i,w,h;t(char*c){for(i=0;p(c),++i<w*2+3;);p("\n");}f(){t("_");for(i=0;i<w*h;)i%w<1?p("| o "):p("o "),i++%w>w-2&&p("|\n");t("-");}main(){scanf("%d %d",&w,&h);w*h<2?p("o"):f();}

Thanks to @Lince Assassino  for saving 11 bytes!
Ungolfed:
#include <stdio.h>
#define p printf

int i, w, h;

void t(char *c)
{
    for(i=0; p(c), ++i<w*2+3;);
    p("\n");
}

void f()
{
    t("_");
    for(i=0; i<w*h;)
    {
        i%w<1 ? p("| o ") : p("o ");
        i++%w>w-2 && p("|\n");
    }
    t("-");
}

int main()
{
    scanf("%d %d", &w, &h);
    w*h<2 ? p("o") : f();
}

You can change your first line for p(char*A){printf(A);}

Really, thank you! But it's possible to make shorter with #define p printf

Cinnamon Gum, 32 bytes
0000000: 6c07 d5f5 7a5d 9cdf 5ae6 52ae 4050 0c35  l...z]..Z.R.@P.5
0000010: 18d9 052f 0082 9b42 e7c8 e422 5fe4 7d9f  .../...B..."_.}.

Non-competing. Try it online. Input must be exactly in the form [width,height] with no space in between the comma and the height.
Explanation
The string decompresses to this:
l[1,1]&o;?&`p___~__~
%| ~o ~|
%---~--~

The first l stage maps [1,1] to o (the special case) and everything else to the string
`p___~__~
%| ~o ~|
%---~--~

The backtick then signals the start of a second stage; instead of outputting that string, CG chops off the backtick and executes the string. The p mode then repeats all the characters inside the tildes first parameter (width) times and then afterwards repeats the characters inside the percent signs second parameter (height) times. So for [4,2] it turns into this:
___________
%| o o o o |
%-----------

and then into:
___________
| o o o o |
| o o o o |
-----------

Vim, 56 keystrokes
This seems like a text editing task, so Vim is the obvious choice! I take input as a text file with two space separated integers and output the answer into the same file. Also, I hate you for having the 1x1 special case... Anyway:
"adt l"bDro:if@a*@b==1|wq|en<cr>Di| |<esc>@aio <esc>yy@bPVr_GpVr-ZZ

and if there hadn't been for the special case, 35 keystrokes
"adt x"bDi| |<esc>@aio <esc>yy@bPVr_GpVr-ZZ

A breakdown for sane people:
"adt l"bD

Delete numbers from buffer into @a and @b (space char kept)
         ro:if@a*@b==1|wq|en<cr>

Replace space with "o" and if special case, save and quit
                                Di| |<esc>

Clear the line and write the edges of the lego block
                                          @aio <esc>

Insert @a lots of "o " to get a finished middle part
                                                    yy@bP

Yank line and make @b extra copies (one too many)
                                                         Vr_

We are at top of buffer, replace extra line with underscores
                                                            Gp

Jump to bottom of buffer, pull line that we yanked earlier
                                                              Vr-ZZ

Replace line with dashes, save and quit

Befunge, 114 113 108 101 bytes
I know there are already a number of Befunge solutions, but I was fairly certain they could be improved upon by taking a different approach to the layout of the code. I suspect this answer can be golfed further as well, but it is already a fair bit smaller than either of the previous entries.
&::&+:2`^|,+55_"_",^
-4:,,"| "<\_|#:+1\,,"|"+55$_2#$-#$" o",#!,#:<
  ,"-"_@#:-1<
 :*2+2\-_"o",@v!:-1<

Try it online!

Can you explain why the string :<| is  needed?

@Zacharý That vertical branch on the first line never actually branches up. The top of the stack is always zero at that point, so it's a shortcut for dropping the stack top and branching down at the same time - essentially this tip.

Pyth, 38 bytes
?t*QJEjb+sm\_K+\|+j\o*dhQ\|+mKJsm\-K\o

Test suite.

Haskell, 76 bytes
1#1="o"
w#h|f<-w*2+3=f!"_"++'\n':h!('|':w!" o"++" |\n")++f!"-"
n!s=[1..n]>>s

Usage example: 3 # 2 gives you a multiline string for a 3-by-2 brick.
Ungolfed:
(#) :: Int -> Int -> String
1     #   1    = "o"
width # height = let longWidth = 2 * width + 3 in -- golfed as 'f'
                      (        longWidth `times` "_"  ++   "\n" )
  ++ height   `times` ( "|" ++     width `times` " o" ++ " |\n" )
  ++                  (        longWidth `times` "-"            )

-- | golfed as (!)
times :: Int -> [a] -> [a]
times n s = concat $ replicate n s

At first glance that looked like it should be shorter with unlines, but it's not.

Groovy, 107, 98, 70, 64
{x,y->t=x*2+3;x<2&&y<2?"o":'_'*t+"\n"+"|${' o'*x} |\n"*y+'-'*t}

Testing:
(2,2)
(1,1)
(8,2)
(1,4)
_______
| o o |
| o o |
-------
o
___________________
| o o o o o o o o |
| o o o o o o o o |
-------------------
_____
| o |
| o |
| o |
| o |
-----

PHP 7, 98 bytes
<?=($P=str_pad)("",$w=3+2*$argv[1],_).$P("",$argv[2]*++$w,$P("
| ",$w-1,"o ")."|").$P("
",$w,"-");

str_pad saves a little from str_repeat.
Juggling with preincrement on $w saves two bytes.
But version 7 is needed for assigning $r while using it at the same time.

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 #\-)))

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.

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.

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.

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=

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?

Also, probably you can leave it as an anonymous function (without f=)

APL, 46 bytes
{⍵≡1 1:'o'⋄'-'⍪⍨'_'⍪'|',' ','|',⍨'o '⍴⍨1 2×⌽⍵}

The guard: ⍵≡1 1:'o' for the special case.
Otherwise 'o '⍴⍨1 2×⌽⍵ builds the content. And the rest is just the boxing.

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!

C#, 198 bytes
void f(int x,int y){int l=x*2+3;Console.Write(y==x&&x==1?"o":s("_",l)+"\n"+s("|"+s(" o",x)+" |\n",y)+s("-",l));}string s(string m,int u){return string.Join("",new string[u].Select(n=>m).ToArray());}

quick and dirty
I had to write a function that multiplies strings
ungolfed (for suggestions)
public static void f(int x,int y)
{
    int l=x*2+3;
    Console.Write(y == x && x == 1 ? "o" : s("_",l)+"\n"+ s("|" + s(" o", x) + " |\n", y) + s("-",l));

}
public static string s(string m,int u)
{
    return string.Join("", new string[u].Select(n => m).ToArray());
}

I noticed your s function can be optimized to string s(string m,int u){return string.Join("",new int[u].Select(n => m));} - the .ToArray() is redundant and the string[] may as well be an int[].  But instead of string.Join you can use aggregate: string s(string m, int u){return new int[u].Aggregate("",(t,i)=>t+m);}

you can shave a few bytes like this...(191) void f(int x,int y){Func<char,int,string>s=(c,i)=>new string(c,i);int l=x*2+3;Console.Write((y&x)==1?"o":s('_',l)+"\n"+s('y',y).Replace("y","| "+s('x', x)+"|\n").Replace("x","o ")+s('-',l));}

J, 59 bytes.
' o|_='&({~)@:((4,~3,2(,~"1)2 0,"1(1 0&($~)@,+:))^:(0===]))

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 |
-------------

Charcoal, 41 bytes
¿⁼η⁼θ¹o≔⁺³×θ²κＵＲκ⁺²ηＰ×κ_Ｍ⁺η¹↓Ｐκ↗Ｆη«Ｐ×θ 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!

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)}

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)}

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.

@Neil AFAIK .repeat was introduced with ES6, fixed the output

Ah, well Firefox had it over a year before ES6.

You can replace function p(e,n) with p=(e,n)=> for 6 bytes.

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")}
`

Guess what, welcome to PPCG!

"JavaScript" it is.

Thanks a lot, learned a bit and will adjust my solution :)

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.

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.

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.

@NoOneIsHere thanks. fixed. and also shortened the submission from 170 to 94 bytes. Enjoying this... :-)

@PeterPerháč You need to use Level 1 headers, so not fixed. Instead of **Scala, 94 bytes**, use #Scala, 94 bytes.

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).

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

I think your first line of output is one character short.

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.

Welcome to the site! Nice first post.

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!

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
From Rgb to Cmyk
Given 3 bytes or RGB as input, calculate the nearest CMYK values, and output them.

create either a function with parameters and return value or a program that operates on stdin/stdout
use the color profile of your choice, but provide a reference
input may be either separate numeric values in range [0;255] or a 6 digit hex string
output should be separate numeric values ranging either [0;1] or [0;100]
standard code golf: no loopholes, shortest code wins
extravagant ideas are welcome

sample data:
input             output
108,174,106       [0.3793103448275862, 0.0, 0.3908045977011494, 0.3176470588235294]
0,0,0             0,0,0,1
170,255,238       33,0,7,0
0x0088ff          1,0.4667,0,0
[250,235,215]     [0,6,14,1.96]
#123456           .7907,.3953,0,.6627

Uncalibrated mapping is fine and probably the easiest
No input validation required; floats are allowed (ranging from 0 to 255), but may also be rounded
Output format should be either clearly commented or obvious; i.e.:

CMYK in that order
does not matter if percentage [0;100] or pure numbers [0;1]

Testing should include the trivial example [0,0,0].

This site has the most digits of online tools that I could find. Does anyone know a tool that gives more than 4 digits?

Can the input be floats between 0 to 1?

Could you give some example inputs/outputs?

Also, welcome to PPCG. :) Usually we put challenges first in the Sandbox for Proposed Challenges for ± 72 hours. That way people can give feedback and your challenge will overall improve before you post it here.

@KevinCruijssen Just a side note, but I don't think that's how you use ±...

@LeakyNun In my understanding it means something like More or less / roughly in the English language see the adverb section here for some examples. I personally prefer it over ≈. Although according to Wikipedia it is mostly used in mathematics and such, in that case the usage is indeed wrong.

@KevinCruijssen Oh, thanks for teaching.

Welcome to the site! This is a decent challenge, but it's a little bit unclear. I'm voting to close as unclear what you're asking, but if you explain the algorithm to convert them and provide some test-cases, I will retract my vote.

@KevinCruijssen In the adverb section, it says South African. It's not used that way in standard English. We use ~.

The close vote message is a bit misleading, because it stems from our Q&A roots, but it was indeed "put on hold as unclear what you're asking". There were a couple of requests for clarification in the comments which weren't addressed: specifically whether inputs and outputs as floats between 0 and 1 are allowed (or whether it has to be integers from 0 to 255), how the conversion actually works, and whether you could include some test cases.

Is it required to always have a 0 in at least one of CMY?

@l4m2 I don´t think so; but I guess that there are RGBs for which the result does not contain a 0.

Dyalog APL, 16 15 bytes
1-⊢(÷,255÷⍨⊢)⌈/

1 minus 1-
 X divided by ÷ Y, followed by , 255 dividing 255÷⍨ Y ⊢, where
  X is itself ⊢ (i.e. the list of RGB values), and
  Y is the max /⌈ (of the RGB values).
$$
\begin{cases}
J = max(R,G,B)\\
C = 1-\frac{R}{J}\\
M = 1-\frac{G}{J}\\
Y = 1-\frac{B}{J}\\
K = 1-\frac{J}{255}\\
\end{cases}
$$
TryAPL!
Credits:
 ∘ -1 byte by ngn.

When is PPCG getting MathJax?

@Neil http://meta.codegolf.stackexchange.com/search?q=MathJax

+1 for ⍨! Nice emoticon

@programmer5000 Thank you. You'll find that one in pretty much all my code-golfs. It swaps the arguments of the function to its left. Other APL emoticons are ⍣ and ⍤. I hope we'll get ⍥ and ⍢ soon.

@Adám ಠ would make me happy!

@programmer5000 J is the master emoticon language though (albeit they face the opposite way of normal smilies). Check the third column here.

@programmer5000 NARS2000 APL has ⊙. Good enough?

C#, 88 86 85 84 bytes
(r,g,b)=>{float[]a={r,g,b,1};var j=a.Max();a[3]=j*j/255;return a.Select(x=>1-x/j);};

output for 108,174,106:
0.3793104
0
0.3908046
0.3176471

Since OP allows function I submitted only the lambda. You can find a running demo on .NetFiddle. I am not a golfer, I post for fun. Also, it is my first answer \o/. Feel free to comment any improvement :)
Kudos to Leaky Nun for the formula.
caveat: it doesn´t work for [0,0,0] (thank you Titus)

1.0-x/j? You surely can't do 1-x/j?

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ yes I can! It was a rest from an experience. The goal was to auto cast to double. I remove it.

You don't need it for subtraction anyways. Also, you don't seem to re-use a[3], and you don't seem to specify a fixed size for a, so you can do {r,g,b} and a[3]=j*j (because, anyways, 1 * a = a).

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ I am reusing a with the select().  If I use a[3] like this I will out of range and throw, wont I?

I mean, assigning it first.

Like this a[3]=j*j/255;? Indeed it works.

Yeah that one, and removing the ,1 in {r,g,b,1}? I don't think assigning first will cause any "out of range" errors.

If I write double[]a={r,g,b};, it throws.

Welcome to PPCG! Nice first post!

Great first answer and welcome to PPCG! If you want to display your language and bytes in a larger font like the other answers (which is usually the standard here), you can add a # in front of the line. :)

@KevinCruijssen Thank you :)

nice approach; though it doesn´t work for [0,0,0]

@Titus Indeed. I forgot it!

Python, 46 bytes
lambda*c:[1-i/max(c)for i in c]+[1-max(c)/255]

Requires input to be floats in Python 2, fairly sure it doesn't in 3.

JavaScript (ES6), 58 51 bytes
a=>[...a.map(e=>1-e/m||1,m=Math.max(...a)),1-m/255]

Accepts an array [R, G, B] (add 7 bytes for separate parameters) and returns an array [C, M, Y, K] using the uncalibrated colour mapping.

Are you sure with the order CYMK on your second answer? looks like CMYK to me.

Do you know why spreading of a mixes up its content? This is weird.  3) Have you tested [0,0,0]? No exception in ES, but looks like a division by zero.

Sorry, they were both CMY, that was my fault. Now also fixed the [0,0,0] cases.

Try [...a,m=Math.max(...a)] in your array solution. 5) Can you golf the other one further using an array as input? Consider using a.0 etc. instead of .map.

@Titus I've come up with a completely new approach now which actually prefers CMYK order and saves 7 bytes too!

Do I get it right that ||1 replaces infinity with 1? ES is wicked! 2) Does m really stay defined outside the map call? 3) I accept the array; but what would it look with separate parameters?

@Titus 1) 0/0 is NaN, which counts as falsy 2) Yes, it sets the global variable m (so invalid in strict mode) 3) ([...a])=> etc.

Mathematica, 36 28 33 bytes
List@@ColorConvert[{##}/255,"CMYK"]&

 After liberalization of I/O formats, golfed further: List@@#~ColorConvert~"CMYK"&
Anonymous function, that does what is asked.
The old function takes three arguments from 0 to 255 (anything beyond this range will be automatically clipped to this range) and returns an array of "CMYK" values between 0. and 1.
Example (for old function):
List @@ ColorConvert[{##}/255, "CMYK"] &[108, 174, 106]

{0.37931, 0., 0.390805, 0.320313}

Since arrays are allowed as input, 33 bytes:
List@@ColorConvert[#/255,"CMYK"]&

Of course the built-in function handles {0, 0, 0} properly and returns {0, 0, 0, 1}.

To clarify: input values must be in [0;255]. will edit the question in a minute, 2) Please test [0,0,0]. 3) Shouldn´t that be /255?

@Titus you're right, its 255, can't address all issues at the moment though, I'll fix things at earliest convenience

@Titus fixed it

Pyth, 24 21 18 24 21 bytes
Life is a round trip, indeed.

=cR255Q+mc--1dK-1JeSQJQK
=cR255Q+mc-JeSQdJQ-1J
+mc-JeSQdJQ-1cJ255
+mc-JeSQd+J^T_15Q-1cJ255
+m-1?JeSQcdJ1Q-1cJ255

Test suite.
Sample input: 108,174,106
Sample output: [0.3793103448275862, 0.0, 0.3908045977011494, 0.3176470588235294]
Sample input: 0,0,0
Sample output: [0, 0, 0, 1.0]
Formula used:
$$
\begin{cases}
J = max(R,G,B)\\
C = 1-\frac{R}{J}\\
M = 1-\frac{G}{J}\\
Y = 1-\frac{B}{J}\\
K = 1-\frac{J}{255}\\
\end{cases}
$$
Old formula: https://i.stack.imgur.com/ZtPD6.gif
Old formula: https://i.stack.imgur.com/Nqi9F.gif

nice golfing. care for a breakdown?

Bash + ImageMagick, 69 bytes
convert "xc:$1[1x1]" -colorspace cmyk txt:-|grep -o '([^)]*)'|head -1

Example:
$ ./rgb2cmyk.sh "#6CAE6A"
(38%,0%,39%,32%)

$ ./rgb2cmyk.sh "#000000"
(0%,0%,0%,100%)

$ ./rgb2cmyk.sh "#AAFFEE"
(33%,0%,7%,0%)

$ ./rgb2cmyk.sh "#0088ff"
(100%,47%,0%,0%)

$ ./rgb2cmyk.sh "#FAEBD7"
(0%,6%,14%,2%)

$ ./rgb2cmyk.sh "#123456"
(79%,40%,0%,66%)

SmileBASIC, 73 72 bytes
INPUT R,G,B
J=MAX(R,G,B)IF!J THEN?0,0,0,1 ELSE?1-R/J,1-G/J,1-B/J,1-J/255

Could be much shorter.

Did you mean to write J=MAX(R,G,B) ?

Lithp, 114 bytes
#R,G,B::((var J(max R G B))(if(!= 0 J)((list(- 1(/ R J))(- 1(/ G J))(- 1(/ B J))(- 1(/ J 255))))((list 0 0 0 1))))

Try it online!

Saved 6 bytes (forgot that max takes any number of arguments)

I'm not quite sure this is right. The first two results with the sample data are correct, but the rest are not (see the Try it online.)
Uses the implementation described nicely as follows:
$$
\begin{cases}
J = max(R,G,B)\\
C = 1-\frac{R}{J}\\
M = 1-\frac{G}{J}\\
Y = 1-\frac{B}{J}\\
K = 1-\frac{J}{255}\\
\end{cases}
$$

PHP 7, 123 110 105 bytes
Input as RGB color 100 240 75
$j=max($h=$argv);echo strtr(@(1-$h[1]/$j).",".@(1-$h[2]/$j).",".@(1-$h[3]/$j).",".(1-$j/255),["NAN"=>0]);

Outputs CMYK values as decimal in 0...1 range.
Saved lots of bytes thanks to Titus.
Sample usage:
php -r '$j=max($h=$argv...' 100 240 75
0.58333333333333,0,0.6875,0.058823529411765

php -r '$j=max($h=$argv...' 255 255 255
0,0,0,0

php -r '$j=max($h=$argv...' 0 255 0
1,0,1,0

php -r '$j=max($h=$argv...' 0 0 0
0,0,0,1

Test online

Input as HEX color #123456, 202 bytes
$h=str_split(substr($argv[1],-6),2);$j=max($r=hexdec($h[0]),$g=hexdec($h[1]),$b=hexdec($h[2]));echo z($r,$j),",",z($g,$j),",",z($b,$j),",",1-$j/255;function z($c,$y){return is_nan(@($c/$y))?0:1-$c/$y;}

54 bytes for function to prevent division by zero, probably golfable or removable.
Gets as input RGB color as HEX #123456 and outputs CMYK as decimal in 0...1 range.
Sample usage:
php -r '$h=str_split...' '#000000'
0,0,0,1

php -r '$h=str_split...' '#ffffff'
0,0,0,0

php -r '$h=str_split...' '#123456'
0.7906976744186,0.3953488372093,0,0.66274509803922

php -r '$h=str_split...' '#ffff00'
0,0,1,0

separate numeric values means you can just take $h=$argv; and use $h[1] instead of $h[0] etc. I like the NAN trick; but doesn´t that yield warnings? strtr is probably shorter than str_replace, and NAN needs no qotation (will yield Notices, but those are not displayed in the default config).

Also, please provide the PHP version this works in. It does not in PHP 7 (where 1/0 results in INF) nor in PHP 5 (1/0 => false).

@Titus Thanks for the very interesting $argv array tip in command line! I added the PHP version. It works with NAN because when you use str_replace it converts implicitly the number to string so it outputs NAN, in fact if you check at this link, you will see that it outputs NAN because of str_replace("INF" instead of str_replace("NAN". I couldn't make it work using strtr. I added the @ to suppress the warnings.

I found my mistake: $n/0 is INF, but 0/0 is NAN (also in PHP 7.0). You can save 4 bytes with str_replace(NAN,0,$s) or 6 bytes with strtr($s,["NAN"=>0).

@Titus great thanks, I couldn't figure out how to properly use strtr();

PHP, not competing
I was just too tempted to post my own.
RGB input, 74 bytes
for(;$i++<4;)echo$i<4?($j=max($argv))?1-$argv[$i]/$j:0:1-$j/255,","[$i>3];

or 68 bytes with a trailing comma in the output: remove [$i>3].
Run with php -r '<code>' <red-value> <green-value> <blue-value>.
HEX input, 100 bytes
foreach($a=array_map(hexdec,str_split($argv[1],2))as$c)echo($j=max($a))?1-$c/$j:0,",";echo 1-$j/255;

Run with php -nr '<code>' RRGGBB.
That approach would take 75 bytes for RGB input:
replace foreach($a=array_map...as$c) with foreach($a=$argv as$c)if($i++).

C, 155 bytes
#define C(x) 1-x/(j>0?j:1)
#define F float
i=0;F j;f(F r,F g,F b){j=(r>g?r:g)>b?(r>g?r:g):b;for(;i++<4;)printf("%f\n",i>1?i>2?i>3?1-j/255:C(b):C(g):C(r));}

I'm trying to figure out how it's possible golf more.
Usage:
#define C(x) 1-x/(j>0?j:1)
#define F float
i=0;F j;f(F r,F g,F b){j=(r>g?r:g)>b?(r>g?r:g):b;for(;i++<4;)printf("%f\n",i>1?i>2?i>3?1-j/255:C(b):C(g):C(r));}
main(){
    f(108,174,106);
}

Output:
0.379310
0.000000
0.390805
0.317647

+3: mistake: function should return the result, not print it. (sorry I just saw that)
+4: error: i is not declared.
+0: error: your ternary operators seem off. shouldn´t that be i>0?i>1?i>2

but there is some golfing potential; I found -25 bytes in ANSI C, and another -19 in C99. 2 bytes are here: j>0?,17 in getting rid of the loop, and 6 in splitting up the j definition.

add another +3 for the function: it returns something else than int, so a return type is required (F *). But I found another byte to golf away in C99.

@Titus If I'm not mistaken, j>0?j:1 can be j+!j to achieve -3 bytes.

And I think the C macro is incorrect: 1-x/1 for j==0? I think that should be 1-(j>0?x/j:1).

Hoon, 110 bytes
=>
rs
|*
a/*
=+
[s=(cury sub .1) j=(roll a max)]
(welp (turn a |*(* (s (min .1 (div +< j))))) (s (div j .255)))

Use the single precision floating-point library.
Create a new generic function that takes a.
Set s to sub curried with .1 for later, and j to folding over a with max.
Map over a by dividing each element with j, finding the minimum of that and 1 to normalize NaN, then subtract 1 with s. Add 1-j/255 to the end of that list.
> =f =>
  rs
  |*
  a/*
  =+
  [s=(cury sub .1) j=(roll a max)]
  (welp (turn a |*(* (s (min .1 (div +< j))))) (s (div j .255)))
> (f (limo ~[.108 .174 .106]))
[i=.3.7931037e-1 t=[i=.0 t=[i=.3.908046e-1 .3.1764704e-1]]]
> (f (limo ~[.0 .0 .0]))
[i=.0 t=[i=.0 t=[i=.0 .1]]]

Can you provide a TiO please.

@Titus: Hoon doesn't have a TiO site, unfortunately.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Starbucks to English
In the classic days of Starbucks before these newfangled sticker-printers and wireless drivethrough headset palmtop scanner dealies, in the heady days of 2000-ish, Starbucks had a concise system for describing beverages with a strict syntax and accompanying encoded form.
Vertically on the cup there are a series of labelled boxes which may contain certain values.:
Decaf
[   ]     -blank-  X  1/2  1/3  2/3
Shots
[   ]     -blank-  0 1 2 3 ... 20    followed by    S T G V
Syrup
[   ]     -blank-  V M C H
Milk
[   ]     -blank-  Wh % N B
Custom
[    ]    -blank- ((-|x)?(F|WC|M|CR) )+
Drink
[   ]     E EM ECP A L C CM

But we will use a horizontal form for easier manipulation. These are the names of the 6 fields of the input which may be any convenient form. Examples here are simple CSV. The Custom field and Syrup fields each may be a concatenation of several values. You may use any convenient subdelimiter. Examples here use space. The Shots field is also a concatenation of a (possible) number and a designation of the cup size (which is implicit in the physical cup but naturally fits in this place in the encoding).
The Decaf field values are translated into words like this
-blank-   -nothing-
X         "decaf"
1/2       "half-caf"
1/3       "one-third-caf"
2/3       "two-thirds-caf"

Logically, the fractional values are only permissible when the number of shots is divisible by the denominator; but for this challenge it is not necessary to detect or diagnose this error.
The Shots field should be broken into its numerical component (if present) and the size identifier. The number should be displayed in latin tuple form: single, double, triple, quadruple, quintuple, beyond 5 just print the number and the suffix "-tuple" ie. 7-tuple, 16-tuple. The size designations are:
S  short
T  tall
G  grande
V  venti

Eg.
2T  double tall
3G  triple grande

The Syrup field may contain one or more of several optional-number/lettercode tokens. The maximum number of a syrup is 20. Even that is too much. LOL.
V  vanilla
C  caramel
M  mocha
H  hazelnut

Eg.
2V 2C     two vanilla two caramel
H         hazelnut
M H 1V    mocha hazelnut one vanilla

The Milk field may contain one of the following.
Wh  whole-milk
%   two-percent
N   skim
B   breve

The Custom field may contain one or more of several modifiers with optional x or - sign.
x  extra     F   foam
-  no        WC  whip
             M   mocha drizzle
             CR  caramel drizzle

The Drink field contains one drink id.
E    espresso
EM   espresso macchiato
ECP  espresso con panna
A    americano
L    latte
C    cappuccino
CM   caramel macchiato

Any field may be blank except for the size designation and the drink id.
Examples.
,3G,V,Wh,,L    =>   triple grande vanilla whole-milk latte
X,2T,,N,,L     =>   decaf double tall skim latte
1/2,V,,,,CM    =>   half-caf venti caramel macchiato
2/3,3V,3V,B,WC,L  => two-thirds-caf triple venti three vanilla breve whip latte
,G,,,xCR,CM    =>   grande extra caramel drizzle caramel macchiato
X,4T,2M 2C,B,xWC -F xM,C  =>
  decaf quadruple tall two mocha two caramel breve extra whip no foam extra mocha drizzle cappuccino

There is no need to diagnose erroneous or illogical concoctions such as a "no foam ... cappuccino*.
Additional Complication
For only the drinks with the word espresso, the number single should be replaced by solo and double should be replaced by doppio. And the size may be unspecified and omitted. Also, just for the bare espresso drink itself, if the only other specification is one of these two specially-replaced numbers-of-shots, then the word espresso itself should be omitted.
,2,1V,B,,EM   =>  doppio one vanilla breve espresso macchiato
,1,,,,E       =>  solo
,2,,,,E       =>  doppio
,3,,,,E       =>  triple espresso

Additional observations on 'reading a cup'
This part is not a requirement for this challenge but may be a useful refinement in applying this sort of verbalized system in other domains.
I mentioned syntax at the very beginning, and by applying the schema to incoming streams of words, orders could be transmitted verbally by several order takers to the barista making beverages. The rough framework SIZE .... DRINK provides demarcation between several orders spoken at once. There is thus a tendency to make all the interior attributes as adjectival phrases so the order also has a valid English noun-phrase structure. So whip is often spoken with whip or whipped and foam is often spoken foamy or with foam.
Thus, for some old-time baristas, they're not "correcting you" when they repeat the order in the proper format (well,... sometimes). They're simply organizing the information for the purpose of remembering all the details exactly. By schematizing the information, an entire beverage order becomes a single unit for the purpose of applying the magic number 7 plus or minus 2. So a barista with this skill can hold 5-9 orders in their head provided other distractions do not consume too much head room. :)

I'm glad you referred to these as beverages, rather than coffee.

What do you mean newfangled. Unless I'm ordering from mobile, all the Starbucks baristas I've ever seen still write it down with a black marker.

@JoeZ. Just my frustration that the simplicity of the old way is continually eroded. The baristas themselves have to translate to a third form in the way of inputting the order to the system. And for a store with a drive-thru, the order is printed in a fourth form on the sticker. Whereas the listing on the heads-up queue has a fifth distinct format (omitting all syrup numbers).

s/frustration/lamentation/

"Venti is large" no, Large is large. In fact, tall is large and grande is Spanish for large. Venti is the only one that doesn't mean large. It's also the only one that's Italian. Congratulations, you're stupid in three languages. :P

Retina 0.8.2, 640 bytes
Performs a series of substitutions to transform the input into the expected output.
-
no
x
extra
Wh
whole-milk
%
2-percent
N
skim
B
breve
X
deJ
1/2
half-J
1/3
1Q-J
2/3
2Qs-J
Q
-third
J
caf
^,
 ,
 ,1(?=\D.*E)
,soloZ
 ,2(?=\D.*E)
,doppioZ
Z,,,,E$
Z
 ,(\d+)
,$1UleZ
,1U
,sing
,2U
,doub
,3U
,trip
\d+(?!\d*U)
$&Y
U
-tup
,4-.
,quadr
,5-
,quin
 ,
Z
S
short
T
tall
G
grande
ZV
 venti
M(?=[^,]*,\w*$)
MR
E
espresso
M$
 macchiato
CP
 con panna
A
americano
L
latte
C$
cappuccino
F
foam
WC
whip
R
 drizzle
4Y
fourY
6Y
sixY
7Y
sevenY
9Y
nineY
10Y
ten
11Y
eleven
12Y
twelve
13Y
thirK
15Y
fifK
18Y
eighK
20Y
twenty
1Y
one
2Y
two
3Y
three
5Y
five
8Y
eight
1(\w*)Y
$1K
K
teen
V
vanilla
C
caramel
M
mocha
H
hazelnut
 -
-
Z,*| ?,+

^ |Y

Try it online!
Most of it is pretty straightforward replacements. A few interesting parts are:
 ,1(?=\D.*E)
,soloZ
 ,2(?=\D.*E)
,doppioZ

Handles the special cases for drinks containing the word "espresso". It transforms the 1 and 2 into "solo" and "doppio" before we get to the stage where we transform those numbers into latin tuple form.
Z,,,,E$
Z

Removes the word "espresso" if "solo" or "doppio" is the only other modifier.
M(?=[^,]*,\w*$)
MR

Appends an R to any M with only one comma between it and the end of the string. This allows us to transform all Rs into "drizzle" later on.
1(\w*)Y
$1K
K
teen

Allows us to transform 14,16,17, and 19 into their word forms all at once, since we replace 4,6,7, and 9 beforehand.

Javascript ES6, 902 900 bytes
s=>(R=(l,r)=>(l.split`.`.map((e,i,l)=>!(i%2)&&(r=r.split(e).join(l[i+1]+" "))),r),R("-.no.!.-tuple.1/2.half-caf.1/3.one-third-caf.2/3.two-thirds-caf.ECP.Econ panna.CM.RY.CR.RZ.EM.EY.WC.whip.Wh.whole-milk.A.americano.B.breve.C.cappuccino.D.extra.E.espresso.F.foam.G.grande.H.hazelnut.I.venti.L.latte.M.OZ.N.skim.O.mocha.R.caramel.S.short.T.tall.V.vanilla.X.decaf.Y.macchiato.Z.drizzle.%.two-percent",R(",1,,,,E.solo.,2,,,,E.doppio",s).split`,`.map((e,i)=>(`1VI.2MO.2CR.4xD`.split`.`.map(k=>k[0]==i&&(e=e.split(k[1]).join(k[2]))),i==1?(e=R("1!.single.2!.double.3!.triple.4!.quadruple.5!.quintuple",e.replace(/(\d+)/,"$1!"))):i==2?(e=R("10.ten.20.twenty.11.eleven.12.twelve.13.thir0.14.four0.15.fif0.16.six0.17.seven0.18.eigh0.19.nine0.0.teen.1.one.2.two.3.three.4.four.5.five.6.six.7.seven.8.eight.9.nine",e)):s.includes`E`&&(e=R("single.solo.double.doppio",e)),e)).join` `).replace(/\s+/g," ").trim())

"Ungolfed":
s=>(
  R=(l,r)=>(l.split`.`.map((e,i,l)=>!(i%2)&&(r=r.split(e).join(l[i+1]+" "))),r),                                   // consecutive string replacement function
  R("-.no.!.-tuple.1/2.half-caf.1/3.one-third-caf.2/3.two-thirds-caf.ECP.Econ panna.CM.RY.CR.RZ.EM.EY.WC.whip.     // replace all symbols with appropriate values
     Wh.whole-milk.A.americano.B.breve.C.cappuccino.D.extra.E.espresso.F.foam.G.grande.H.hazelnut.I.venti.L.latte.
     M.OZ.N.skim.O.mocha.R.caramel.S.short.T.tall.V.vanilla.X.decaf.Y.macchiato.Z.drizzle.%.two-percent",
    R(",1,,,,E.solo.,2,,,,E.doppio",s)                                                                             // if special espresso cases, directly replace entire string
    .split`,`.map((e,i)=>(                                                                                // split input at commas
      `1VI.2MO.2CR.4xD`.split`.`.map(k=>k[0]==i&&(e=e.split(k[1]).join(k[2]))),                                    // substitute duplicate symbols with unique symbols
      i==1?(e=R("1!.single.2!.double.3!.triple.4!.quadruple.5!.quintuple",e.replace(/(\d+)/,"$1!"))):              // if in shots section, expand all numbers
      i==2?(e=R("10.ten.20.twenty.11.eleven.12.twelve.13.thir0.14.four0.15.fif0.16.six0.17.seven0.18.eigh0.        // if in syrup section, expand all numbers
                  19.nine0.0.teen.1.one.2.two.3.three.4.four.5.five.6.six.7.seven.8.eight.9.nine",e)):
      s.includes`E`&&(e=R("single.solo.double.doppio",e)),                                                         // replace single,double with solo,doppio if espresso is in the string
    e)).join` `).replace(/\s+/g," ").trim())                                                                       // join sections, cleanup whitespaces

Example runs:
f(",3G,V,Wh,,L")              -> triple grande vanilla whole-milk latte
f("X,2T,,N,,L")               -> decaf double tall skim latte
f("1/2,V,,,,CM")              -> half-caf venti caramel macchiato
f("2/3,3V,3V,B,WC,L")         -> two-thirds-caf triple venti three vanilla breve whip latte
f(",G,,,xCR,CM")              -> grande extra caramel drizzle caramel macchiato
f("X,4T,2M 2C,B,xWC -F xM,C") -> decaf quadruple tall two mocha two caramel breve extra whip no foam extra mocha drizzle cappuccino
f(",2,1V,B,,EM")              -> doppio one vanilla breve espresso macchiato
f(",1,,,,E")                  -> solo
f(",2,,,,E")                  -> doppio
f(",3,,,,E")                  -> triple espresso

Try this: (R=...)("=-.no.!... (define R inline then use the result as a function)

Python, 824 815 807 805 bytes
f=lambda s,a=0:a==0and" ".join(" ".join(f(" "+s.split(",")[i],(["X,deC,1/2,half-C,1/3,oneT-C,2/3,twoTs-C,C,caf,T,-third","".join(" %i"%i+f(",%i-tupL,"%i,["1","x","2","y"])for i in range(6,21))+"1,solo,2,doppio,"*('E'in s)+"1,singL,2,doubL, 3,tripL, 4,quadrupL, 5,quintupL,x,1,y,2,S,short,T,tall,G,grande,V,Vnti","V, vanilla,H, hazelnut,10,ten,11,eleVn,12,twelV,13,thirT,14,4T,15,fifT,16,6T,17,7T,18,8een,19,9T,20,twenty,1,one,2,two,3,three,4,four,5,fiV,6,six,7,seVn,8,eight,9,nine,T,teen","Wh,whole-milk,%,two-percent,N,skim,B,breV","x,extra ,-,no ,F,foam,WC,whip,M,MR,R, drizzL","CM,xM,E,espresso,M, macchiato,CP, con panna,A,americano,L,latte,C,cappuccino,x,C"][i]+",C, caramel,M, mocha,L,le ,V,ve").split(","))for i in range(6-(s in",1,,,,E,2,,,,E"))).split())or a and f(s.replace(a[0],a[1]),a[2:])or s

Slightly more readable:
def f(s,a=0):
 if a==0:
  a=["X,deC,1/2,half-C,1/3,oneT-C,2/3,twoTs-C,C,caf,T,-third"]
  a+=["".join(" %i"%i+f(",%i-tupL,"%i,["1","x","2","y"])for i in range(6,21))+"1,solo,2,doppio,"*('E'in s)+"1,singL,2,doubL, 3,tripL, 4,quadrupL, 5,quintupL,x,1,y,2,S,short,T,tall,G,grande,V,Vnti"]
  a+=["V, vanilla,H, hazelnut,10,ten,11,eleVn,12,twelV,13,thirT,14,4T,15,fifT,16,6T,17,7T,18,8een,19,9T,20,twenty,1,one,2,two,3,three,4,four,5,fiV,6,six,7,seVn,8,eight,9,nine,T,teen"]
  a+=["Wh,whole-milk,%,two-percent,N,skim,B,breV"]
  a+=["x,extra ,-,no ,F,foam,WC,whip,M,MR,R, drizzL"]
  a+=["CM,xM,E,espresso,M, macchiato,CP, con panna,A,americano,L,latte,C,cappuccino,x,C"]
  return" ".join(" ".join(f(" "+s.split(",")[i],(a[i]+",C, caramel,M, mocha,L,le ,V,ve").split(","))for i in range(6-(s in",1,,,,E,2,,,,E"))).split())
 elif a:
  return f(s.replace(a[0],a[1]),a[2:])
 else:
  return s

Demo at https://repl.it/C8Hz/3

Ruby -plaF,, 975 870 bytes
I got a random upvote on my old, almost-four-year-old answer to this question, and because of my comments on how horribly it went (you can check the post history if you want to see what I wrote before) I was inspired to make it better (aka: rewrite most of it from the ground up) and managed to golf over a hundred bytes off it. Still longer than the Python answer, but I'm much happier with how things turned out now.
About 20 bytes were saved by switching from trying to run regex patterns to affect specific parts of the comma structure to using the -aF, flag to autosplit a line of input on commas and save it to $F, allowing me to modify some elements before stitching it back together and finally modifying the output variable with the last few sub/gsub commands.
Honestly, the number of regex replacements made here means most of this could be a Retina program, but I don't know Retina well enough for that.
g=->n,c{n.grep(/^ ?#{c}/i)[0]}
n=%w"0 one two three four five six seven eight nine ten eleven twelve thir four fif";n+=n[6,4]<<'twenty'
$F[1].sub!(/(\d*)(\w)?/){i=eval$1;"#{i&&(%w"0 sing doub trip quadrup quintup"[i]||$1+"-tup")+"le"} #{g[%w"short tall grande venti",$2]if$2}"}
$F[2].gsub!(/(\d*)(\w)/){i=eval$1;"#{i&&n[i]}#{'teen'if(13..19)===i} #{g[%w"vanilla caramel mocha hazelnut",$2]}"}
$F[3].sub!(/.+/){%w"skim whole-milk breve two-percent"[$&.sum%26%4]}
$F[4].gsub!(/(x|-)?(\w+)/){"#{%w"extra no"[$1.ord%2]if$1} #{g[%w"caramelD mochaD whip foam",$2[0]].sub ?D,' drizzle'}"}
$_=$F*' '
sub(/^\S+/){%w"de - half- one-third- two-thirds-"[$&.sum%8]+"caf"}
sub'CP',' con pana'
sub'CM','caramel'+m=' macchiato'
e='espresso'
gsub(/[A-Z]/){g[%w"americano latte cappuccino"+[m,e],$&]}
gsub(/ +/,' ')
$_.strip!
sub(/[sd]...le/){g[%w"doppio solo",$&[0]]}if$_[e]
sub'o '+e,?o

Try it online!

I'll update acceptance if the status changes!

Maybe? I'm just not very good at info compression like the other two answers; maybe someone else will be the one to beat Python since this is a very naive solution