Code Golf: Piano

code-golflanguage-agnosticrosetta-stone

The challenge

The shortest code by character count to output a part of a piano keyboard starting from input note in a given length.

Input will be composed of a note ([ACDFG]#|[A-G]) to start printing the keyboard from and a positive number representing length of keys to print including the first note.

The first key should be printed in full – if it has a left sharp key, it will be cut, same for when the start key is sharp, the left key will be cut as well.

A Sharp key is not counted, only white keys.

Test cases

Input
    C 14
Output
    |   ###  ###   |   ###  ###  ###   |   ###  ###   |   ###  ###  ###   |
    |   ###  ###   |   ###  ###  ###   |   ###  ###   |   ###  ###  ###   |
    |   ###  ###   |   ###  ###  ###   |   ###  ###   |   ###  ###  ###   |
    |   ###  ###   |   ###  ###  ###   |   ###  ###   |   ###  ###  ###   |
    |   ###  ###   |   ###  ###  ###   |   ###  ###   |   ###  ###  ###   |
    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |
    |____|____|____|____|____|____|____|____|____|____|____|____|____|____|

Input
    D# 1
Output
    ###   |
    ###   |
    ###   |
    ###   |
    ###   |
     |    |
     |    |
     |    |
    _|____|

Input
    A 7
Output
    ##  ###   |   ###  ###   |   ###  ##
    ##  ###   |   ###  ###   |   ###  ##
    ##  ###   |   ###  ###   |   ###  ##
    ##  ###   |   ###  ###   |   ###  ##
    ##  ###   |   ###  ###   |   ###  ##
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |    |    |    |    |    |    |    |
    |____|____|____|____|____|____|____|

Code count includes input/output (i.e full program).

Best Answer

Perl, 133 (129) chars

Perl, 167 160 156 147 142 133 D'oh! 147 144 137 134 133 chars

    $_=shift;die grep{5>$n?y/*/#/:y/#*/ |/;$n++-8||y/ /_/}
    @Q=(substr(("*#  #".("*#  #*#   |   #")x2)x9,
    4*/#/+(7&ord)*5,1+/#/+5*pop).$/)x9

Here's a 129 char solution, borrowing several ideas from molf's Ruby solution:

    ($_,$c)=@ARGV;$j=($k=/#/)+ord;
    for$n(0..8){print$/,substr+(join'',map{8-$n?5>$n&&$_%7%4?"###  "
    :" |   ":"_|___"}$j..$j+$c),!$k,-3}

and with help from the Acme::AsciiArtinator:

                sub init_piano{$S=$";$H='#';
                (                            $
               T                              ,$P,$U)=qw(
              T                                          |
             _                                            |
            /                                              )
           ;                                                $
          d             =$T.$H.$S.$S;$t                     =
         $             d               .                   $H
        .              $               d                  . $
       S               .$P.$S.$S.$S.$H;$                t=  $
      d.$H.$t.$t;};$_=shift;-/-/;&init_piano();$Z=/#/;-/|   |
      |                                                 |   |
      |                    YAMAHA                       |  /
      ;die grep{4>$n++?y/T/#/:y/#T/ |/;$n-8||y/ /_/;}@q=(m{
     // // /// // /// // /// // /// // /// // /// // /// /   
    // // /// // /// // /// // /// // /// // /// // /// /
   }                                                   .
   substr(${t}x(9),4*${Z}+(7&ord)*5,1+$Z+5*pop).$/)x(8)
          ;   '                            \   /
           | |                              | |
           /_\                              /';