[Question]
  [
Piano keys are 3 characters wide, and 7 characters tall. However, if *every* key was 3 charactes wide, there wouldn't be enough room for the black keys. That's why some of the white keys have parts of them cut out. There are 3 types of white keys.
Keys with the right half missing (R):
```
____
|  |
|  |
|  |
|  |
|   |
|   |
|___|
```
Keys with the left half missing (L):
```
 ____
 |  |
 |  |
 |  |
 |  |
|   |
|   |
|___|
```
And keys with the left and right halves missing (M):
```
 ___
 | | 
 | | 
 | | 
 | | 
|   |
|   |
|___|
```
On a real keyboard, the pattern of these goes like this:
```
RMLRMML, RMLRMML, RMLRMML...
```
and repeats for a total of 88 keys. Now you can't see it when the keys are shown individually, but when you shove them together, you can see the black keys.
```
_________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|
```
# Your task
Given a positive integer *N*, print this ASCII-art of a piano with *N* white keys. You should be able to handle any *N* from 1 to 52 inclusive (since real 88-key pianos have 52 white keys). Here is test output from 1 to 8, and after that the pattern increases in a similar fashion.
```
1
____
|  |
|  |
|  |
|  |
|   |
|   |
|___|
2
________
|  | | |
|  | | |
|  | | |
|  | | |
|   |   |
|   |   |
|___|___|
3
_____________
|  | | | |  |
|  | | | |  |
|  | | | |  |
|  | | | |  |
|   |   |   |
|   |   |   |
|___|___|___|
4
________________
|  | | | |  |  | 
|  | | | |  |  | 
|  | | | |  |  | 
|  | | | |  |  | 
|   |   |   |   |
|   |   |   |   |
|___|___|___|___|
5
____________________
|  | | | |  |  | | | 
|  | | | |  |  | | | 
|  | | | |  |  | | | 
|  | | | |  |  | | | 
|   |   |   |   |   |
|   |   |   |   |   |
|___|___|___|___|___|
6
________________________
|  | | | |  |  | | | | | 
|  | | | |  |  | | | | | 
|  | | | |  |  | | | | | 
|  | | | |  |  | | | | | 
|   |   |   |   |   |   |
|   |   |   |   |   |   |
|___|___|___|___|___|___|
7
_____________________________
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|
8
________________________________ 
|  | | | |  |  | | | | | |  |  | 
|  | | | |  |  | | | | | |  |  | 
|  | | | |  |  | | | | | |  |  | 
|  | | | |  |  | | | | | |  |  | 
|   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
```
And last but not least, here is a full 52 key output:
```
_________________________________________________________________________________________________________________________________________________________________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|
```
Standard loopholes are banned, and the shortest answer in bytes wins!
  
[Answer]
## JavaScript (ES6), ~~155~~ ~~149~~ 147 bytes
```
n=>[`_`[r=`repeat`](n*4+(9>>n%7&1)),s=[...Array(n*12/7|0)].map((_,i)=>1998>>i%12&1?` |`:`  |`).join``,s,s,s,s=`   |`[r](n),s,`___|`[r](n)].join`\n|`
```
Where `\n` represents the literal newline character. Leverages the fact that all the lines after the first start with a `|` character. Explanation:
```
f=
n=>[                        // Start by building up a list of rows
 `_`[r=`repeat`](n*4+       // 4 underscores per key
  (9>>n%7&1)),              // Third and seventh keys have one extra
 s=[...Array(n*12/7|0)]     // Calculate total of white and black keys
  .map((_,i)=>              // Process each key in turn
   1998>>i%12&1?` |`:`  |`  // Bitmap of narrow and wide keys
  ).join``,                 // Join the keys together
 s,s,s,                     // Repeated 4 times in total
 s=`   |`[r](n),            // Full width part of the white keys
 s,                         // Repeated twice in total
 `___|`[r](n)               // Base of the white keys
].join`\n|`                 // Join the rows together
```
```
<input type="number" oninput="o.textContent=f(this.value);"><pre id=o>
```
Edit: Saved 2 bytes by fixing my misreading of the spec on the height of the keys.
[Answer]
# Pyth, ~~68~~ ~~65~~ 63 bytes
```
*lJ:+\|s@Lj;*L" |"_j4536 7*4Q" $"k\_jb+*4]J*2]K+\|*Q"   |":Kd\_
```
[Try it online!](http://pyth.herokuapp.com/?code=%2AlJ%3A%2B%5C%7Cs%40Lj%3B%2AL%22%20%7C%22_j4536%207%2A4Q%22%20%24%22k%5C_jb%2B%2A4%5DJ%2A2%5DK%2B%5C%7C%2AQ%22%20%20%20%7C%22%3AKd%5C_&input=8&debug=0)
[Test suite.](http://pyth.herokuapp.com/?code=%2AlJ%3A%2B%5C%7Cs%40Lj%3B%2AL%22%20%7C%22_j4536%207%2A4Q%22%20%24%22k%5C_jb%2B%2A4%5DJ%2A2%5DK%2B%5C%7C%2AQ%22%20%20%20%7C%22%3AKd%5C_&test_suite=1&test_suite_input=1%0A2%0A3%0A4%0A5%0A6%0A7%0A8%0A55&debug=0)
In this version, I just substituted the assignments (J and K) inside to save 2 bytes. Therefore, read the version below.
## Previous 65-byte version with explanation
```
J:+\|s@Lj;*L" |"_j4536 7*4Q" $"kK+\|*Q"   |"*lJ\_jb+*4]J*2]K:Kd\_
```
[Try it online!](http://pyth.herokuapp.com/?code=J%3A%2B%5C%7Cs%40Lj%3B%2AL%22%20%7C%22_j4536%207%2A4Q%22%20%24%22kK%2B%5C%7C%2AQ%22%20%20%20%7C%22%2AlJ%5C_jb%2B%2A4%5DJ%2A2%5DK%3AKd%5C_&input=8&debug=0)
```
J:+\|s@Lj;*L" |"_j4536 7*4Q" $"k    This part generates the most irregular line.
        j;*L" |"_j4536 7            Generate the whole line by black magic
      @L                *4Q         Get the first (4*input) characters of it, with wrapping.
  +\|                               Add "|" in front of it (we took away the first "|")
 :                         " $"k    Replace the ending space by nothing
J                                   Store the line to J.
K+\|*Q"   |"      This part generates the line just below the irregular line.
    *Q"   |"      Repeat "   |" input times
 +\|              Prepend "|"
K                 Store to K
*lJ\_     Now we can actually start printing
*  \_     Repeat "_" ...
 lJ                      [the length of J] times
          (and implicitly print it out)
jb+*4]J*2]K
   *4]J             Repeat J 4 times
       *2]K         Repeat K 2 times
  +                 Concatenate them together
jb                  Join with newlines
                    (and implicitly print it out)
:Kd\_
:K      Replace in K
  d                  " "
   \_                    by "_"
        (and implicitly print it out)
```
### Black magic
```
We find the irregular line from input=7, and cut out the first "|":
"  | | | |  |  | | | | | |  |"
 2  1 1 1 2  2  1 1 1 1 1 2
j;*L" |"_j4536 7    Black magic.
         j4536 7    4536 converted to base 7: [1,6,1,4,0]
        _           Reverse: [0,4,1,6,1]
  *L" |"            Repeat " |" <each element> times:
                    [""," | | | |"," |"," | | | | | |"," |"]
j;                  Join by whitespace:
                    "  | | | |  |  | | | | | |  |"
```
[Answer]
# Ruby, 119 bytes
```
->n{puts ?_*(1+n*4+(0<=>-n%7%4)),(0..6).map{|i|("01"+("%b"%[0xAADAAAD,13][i/4]*99)).tr('10',' |_|'[i/6*2,2])[0,1+n*4]}}
```
**Ungolfed in test program**
```
f=->n{
  puts ?_*(1+n*4+(0<=>-n%7%4)),           #Draw 1+n*4 _'s for top row (one less if -n%7%4>0, black note), then...
  (0..6).map{|i|                          #Cycle through remaining 7 rows
    ("01"+("%b"%[0xAADAAAD,13][i/4]*99)).   #Generate string version of binary number corresponding to pattern, repeat 99 times.
    tr('10',' |_|'[i/6*2,2]                 #Binary 1-> space or underscore. Binary 0 -> | (These choices ensured no leading 0)
    )[0,1+n*4]                              #truncate to the right amount of keys.
  }
}
10.times{|j|f[j]}
```
[Answer]
# ><>, 188 182 bytes
```
&0"_"o011.
.\:7%8g95*-"_"o1-:a1@@?.~~~1+:&:&=1+1$
.v~:7=?;ao"|"o1+:0$0$
.>:7%8g"0"-4*:9go1+:9go1+:9go1+9go1+:&:&=3$-1$
 ^
.>"| _"{:}7=?$~::oooo1+:&:&(3*2+1$
>^
^
0120112
  | | | |  |
```
The number of white keys to display should be present on the stack at program start.
**Edit**: I managed to shave off a few bytes through combining the output for lines 5/6 and 7. Previous version:
```
&0"_"o011.
.\:7%8g95*-"_"o1-:a1@@?.~~~1+:&:&=1+1$
.v~ao"|"o1+:0$0$.
.>:7%8g"0"-4*:9go1+:9go1+:9go1+9go1+:&:&=3$-1$
 ^
.>"|   "oooo1+:&:&(3*2+1$
 ^
 "|___"oooo1+:&:&=?;
0120112
  | | | |  |
```
[Answer]
# PHP, 238 bytes
```
$n=$argv[1];$s=str_repeat;echo'_'.$s($a=$s('_',28),$m=($n-$r=$n%7)/7).substr($a,0,$k=4*$r-($r&&$r!=3))."\n",$g='|'.$s($b='  | | | |  |  | | | | | |  |',$m).substr($b,0,$k)."\n",$g,$g,$g,$h='|'.$s('   |',$n)."\n",$h,'|'.$s('___|',$n)."\n";
```
As usual, prepend the code with `<?php` , put it into a PHP file (let's name it `keyboard.php`) and run it using:
```
$ php -d error_reporting=0 keyboard.php 55
```
Two more bytes can be saved on PHP7 by squeezing the initialization of `$n` and `$s` into their first use:
```
echo'_'.($s=str_repeat)($a=$s('_',28),$m=($n-$r=($n=$argv[1])%7)/7).substr($a,0,$k=4*$r-($r&&$r!=3))."\n",$g='|'.$s($b='  | | | |  |  | | | | | |  |',$m).substr($b,0,$k)."\n",$g,$g,$g,$h='|'.$s('   |',$n)."\n",$h,'|'.$s('___|',$n)."\n";
```
The ungolfed code, a test suite and other goodies can be found [on github](https://github.com/axiac/code-golf/blob/master/ascii-piano-keyboard.php).
[Answer]
# Python ~~3~~ 2, ~~191~~ ~~185~~ ~~180~~ ~~182~~ ~~171~~ ~~145~~ ~~144~~ ~~133~~ 132 bytes
```
def k(n):print"\n|".join(["_"*(4*n+(9>>n%7&1))]+[''.join("   ||"[1998>>j%12&1::2]for j in range(n*12/7))]*4+["   |"*n]*2+["___|"*n])
```
This could use some golfing but I've fiddled with the code so much already that I may not see where the golfable spots are. Any golfing suggestions are welcome.
**Edit:** Misread the spec on the height of the keys. This bug has been fixed.
**Edit:** Borrowed [Neil's 12 key idea](https://codegolf.stackexchange.com/a/79358/47581) from his Javascript answer, removed some parentheses, and switched to Python 2 to save 11 bytes.
**Edit:** Lots of changes to get the function down to one `for` loop.
**Edit:** Now a program instead of a function.
**Edit:** Now using `print"\n|".join()` as suggested by Neil to save 11 bytes. Turned the program back into a function to save a byte.
[Answer]
# C# 1683 bytes
So....after seeing Neil's answer above this is pretty embarrassing, but I'll post it anyway 'cause it took me a while (bless). I used C# to create mine. Inside the "Fncs" class I created an array of the typical order of keys. Then, I created a function which can allow the user to get an appropriate index for this array based on a given integer. In order to edit individual lines, I created a "PianoKeyboard" class which contains a dictionary storing multiple strings representing the individual lines. Finally, I created the "DrawKey" function which appends the appropriate text to the individual lines and the "GetKeys" function which returns the overall string value.
```
namespace ASCIIPiano{public enum WhiteKeyType{Left,Middle,Right}public static class Fncs{public static WhiteKeyType[] Order{get{return new WhiteKeyType[]{WhiteKeyType.Left,WhiteKeyType.Middle,WhiteKeyType.Right,WhiteKeyType.Left,WhiteKeyType.Middle,WhiteKeyType.Middle,WhiteKeyType.Right};}}public static PianoKeyboard DrawKey(this PianoKeyboard keyboard, WhiteKeyType type){keyboard.Append(1,"_____");if (type == WhiteKeyType.Left){keyboard.Append( 2,"|  | ");keyboard.Append( 3,"|  | ");keyboard.Append( 4,"|  | ");keyboard.Append( 5, "|  | ");}else if (type == WhiteKeyType.Middle){keyboard.Append(2, " | | ");keyboard.Append(3," | | ");keyboard.Append( 4," | | ");keyboard.Append(5," | | ");}else{keyboard.Append( 2," |  |");keyboard.Append(3, " |  |");keyboard.Append(4," |  |");keyboard.Append(5, " |  |");}keyboard.Append(6,"|   |");keyboard.Append(7,"|   |");keyboard.Append(8,"|___|");return keyboard;}public static int GetWhiteKeyIndex(this int number){return number % 7;}public static string GetKeys(this int quantityofwhitekeys){PianoKeyboard keyboard = new PianoKeyboard();for (int i = 0; i < quantityofwhitekeys; i++){WhiteKeyType key=Fncs.Order[i.GetWhiteKeyIndex()];keyboard.DrawKey(key);}return keyboard.TOTALSTRING;}}public class PianoKeyboard{public PianoKeyboard(){}private Dictionary<int, string> lines = new Dictionary<int, string>();public void Append(int index,string value){if (index > 8 || index < 1){throw new Exception("URGH!");}else{if (lines.Keys.Contains(index)){lines[index] += value;}else{lines.Add(index, value);}}}public string TOTALSTRING{get{string returner = "";foreach (int key in lines.Keys){returner += lines[key] + "\n";}return returner;}}}}
```
]