Code Golf: Piano - language-agnostic

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
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).

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)
; ' \ /
| | | |
/_\ /';

Ruby - 125 chars
146 144 140 137 134 126 125 chars
a,n=$*;h=a[1]?0:1;s=a[0]-h+1
9.times{|t|puts (s..s+n.to_i).map{|i|i%7%4<1||t>4?" | ":"### "
}.join[h..-4].tr t>7?" ":n,"_"}
(The second newline is not necessary and added only to avoid a scrollbar on SO. Semi-colons can be replaced by newlines if desired.)
The Ruby 1.9 version is different but of equal length (replacing a[0] by a.ord and "_" by ?_):
a,n=$*;h=a[1]?0:1;s=a.ord-h+1
9.times{|t|puts (s..s+n.to_i).map{|i|i%7%4<1||t>4?" | ":"### "
}.join[h..-4].tr t>7?" ":n,?_}
Call with
$ ruby piano.rb C 14

LilyPond, 285 288 291 310 315 330 333 340 350 characters
In keeping with the music theme, here's a solution in a language designed for typesetting music scores, LilyPond:
x=#ly:string-substitute
u=#(x"*""### ""| *** | ** ")t=#(x"###"" | "u)q=#read-char
z=#(q)v=#(if(eq?(q)#\#)1 0)y=#(iota(+(*(read)5)1 v))#(format #t"~{~{~a~}
~}"(map(lambda(s)(map(lambda(i)(string-ref s(modulo(+(*(char->integer z)5)i(* v
4))35)))y))(list u u u u u t t t(x" ""_"t))))
Usage: $ lilypond thisfile.ly <input.in >output.out 2>/dev/null

GolfScript - 80 Characters
Fits in one line of #SO without the scroll bar :)
' ':s/~~5*\(7&5*\,.4*#+):k;+):c;9,{5<'#'9**' | '4*+3/4<.1>+c*s.+*k>c<n+}%)s/'_'*
GolfScript - 81 Characters
' ': /((7&\,.4*#5*+:k;\~~5*+):c;9,{5<'#'9**' | '4*+3/4<.1>+c* +*k)>c<n+}%) /'_'*
Nicely formatted version (27 x 3)
' ': /((7&\,.4*#5*+:k;\~~5*
+):c;9,{5<'#'9**' | '4*+3/4
<.1>+9* +*k)>c<n+}%) /'_'*
GolfScript - 82 Characters
' '/((7&\,.4*#5*+:k;\~~5*+):c;9,{5<3*'### '*' | '4*+20<.5>+c*k)>c<n+}%)' '/'_'*
GolfScript - 85 Characters
' '/((7&\,.4*#5*+:k;\~~5*+):c;9,{.5<3*'### '*' _'1/#8=='|'1$3*++4*+20<.5>+c*k)>c<n}%
Nicely formatted version (17 x 5)
' '/((7&\,.4*#5*+
:k;\~~5*+):c;9,{.
5<3*'### '*' _'1
/#8=='|'1$3*++4*+
20<.5>+c*k)>c<n}%
GolfScript - 94 Characters
' ': /~~5*:c;(7&5*:^;,:&;['### '3*' | '+.5>+c*1>{^4&*+>&c+)<n}:f~]5*' _'1/{'|'\4*+7*c*f}%
GolfScript - 98 Characters
' ': /~~5*:c;(7&5*:^;,:&;['### '3*' | '+.5>+c*^4&*+:^)>&c+):&<n]5*[ '_']{['|'\4*+7*c*^>&<n]}%
GolfScript - 101 Characters
' ': /~~5*:c;(7&5*:^;,:&;['### '3*' | '+.5>+c*^4&*+)>&c+)<n]5*[ '_']{['|'\4*+7*c*^4&*+>&c+)<n]}%
GolfScript - 109 Characters
' ': /~~5*:c;(7&5*:^;,:&;['##'' ###'.' | '++.' #'+++c*^4&*+>&c+)<n]5*[ '_']{['|'\4*+7*c*^4&*+>&c+)<n]}%
GolfScript - 120 Characters
' '/~~5*:c;(7&5*:^;,:&;['##'' ###'.' | '++.' #'+++c*^4&*+>&c+)<n]5*['| '7*c*^4&*+>&c+)<n]3*'|____'7*c*^4&*+>&c+)<
GolfScript - 127 Characters
' '/~~5*:c;(7&5*:^;,:&;['## ### ### | ### ### | #'c*^4&*+>&c+)<n]5*['| '7*c*^4&*+>&c+)<n]3*'|____'7*c*^4&*+>&c+)<
$ echo -n C 14 | ruby golfscript.rb piano.gs
| ### ### | ### ### ### | ### ### | ### ### ### |
| ### ### | ### ### ### | ### ### | ### ### ### |
| ### ### | ### ### ### | ### ### | ### ### ### |
| ### ### | ### ### ### | ### ### | ### ### ### |
| ### ### | ### ### ### | ### ### | ### ### ### |
| | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |
|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
$ echo -n D# 1| ruby golfscript.rb piano.gs
### |
### |
### |
### |
### |
| |
| |
| |
_|____|
$ echo -n A 7| ruby golfscript.rb piano.gs
## ### | ### ### | ### ##
## ### | ### ### | ### ##
## ### | ### ### | ### ##
## ### | ### ### | ### ##
## ### | ### ### | ### ##
| | | | | | | |
| | | | | | | |
| | | | | | | |
|____|____|____|____|____|____|____|

RetroGolf - Applesoft BASIC: 236 239 245 249 257 245 267 285
Shown in multiple lines for readability, but should be a single line:
1K$="## | ### #":K$="## #"+K$+K$:
FORI=1TO21:F$=F$+"|____":L$=L$+"| ":NEXT:
INPUTN$:S=MID$(N$,2,1)="#":O=(ASC(N$)-65)*5+1+S*4:L=VAL(RIGHT$(N$,2))*5+1+S:
FORI=1TO5:?MID$(K$+K$+K$,O,L):NEXT:FORI=1TO3:?MID$(L$,O,L):NEXT:?MID$(F$,O,L)
Can be tested with this Applesoft BASIC Interpreter in Javascript or an emulator.

C# - 315
I persist to golf in C# although it's not a very terse language...
using C=System.Console;class P{static void L(int o,int c,string s){while(c-->0)C.Write(s[(420>>o++%5*2&3)+(91>>(o+2)/5%7&1)*3]);C.WriteLine();}static void Main(string[]a){int i=0,s=a[0].Length-1,c=int.Parse(a[1])*5+1+s,o=(a[0][0]-65+s)*5-s;while(i++<5)L(o,c,"| ## ");while(i++<8)L(o,c,"| | ");L(o,c,"|__|__");}}

Python - 164
k,n=raw_input().split()
m=k[1:]>""
n=int(n)*5+1
o=(ord(k[0])-65)*5+4*m
for x in["## ### | ### "]*5+[n*"| "]*3+[n*"|____"]:print((x+x[::-1][:-1])*n)[o:o+n+m]

Octave, 153 154 155 158 159 162 172 180 186 185 188 197 199 200 206 207 209 212 214 215 219 240 244 268 characters
Why use just C or C# or F# (or B or D) when you can program with a full Octave?
(wrapped every 60 chars for clarity)
x=5*scanf("%2c%d");for k=-8:0disp((s={[t="| ### ### ","#
## ",t" "]"| ","|____"}{(k>-4)+!k+1})(1+mod(5*(y=x(2)>1
60)+(-y:x(3))+x(1),rows(s'))))end
Yes ... this solution really does compute the complex conjugate transpose of a string.
Usage: $ octave -q thisfile.m <input.in >output.out

C — 197 203 207 216 224 232 240 characters
#define S"# | ### ### ##"
main(i,j,l,h,t){char*X[]={"____|"," |",S S,S S},s[i=11];for(scanf("%s%n%d",s,&h,&l);--i>1;puts(""))for(j=t=*s%7*5+h*4;j<t+l*5+h;putchar(X[i/3][j++%(i>5?35:5)]));}
This equivalent 194-character version assumes buffer overflow is fine.
#define S"# | ### ### ##"
i=11;main(j,l,h,t){char*X[]={"____|"," |",S S,S S},s;for(scanf("%s%n%d",&s,&h,&l);--i>1;puts(""))for(j=t=s%7*5+h*4;j<t+l*5+h;putchar(X[i/3][j++%(i>5?35:5)]));}

PostScript: 239 245 293 312 (regular); 219 224 225 231 (ASCII85)
/r{(%stdin)(r)file token pop}def[(]){mul add}/z r(:-)cvs dup length 1
sub/v exch/p r/s(| ### ### ### | ### ### )([){0 1 v p 5]{s
exch z 0 get 5]v 4]s length mod 1 getinterval print}for/
=}>>begin[[[[[/s(| )def[[[/s(|____)def[
Binary version expanded through ASCII85 encoding into a 219-character program with only ASCII printable characters:
/(|____)/(| )[/r/(| ### ### ### | ### ### )<~Ou%G5-$+0=Bl5#JE[d/;P,jagI?HCK#<*JGP,4<rOuSV60p8LhG*5%O8oc=a.=3b)!HsVu23Md=!IHJ_A<K->#5*j;23Md=!HoSBP&-9^09Tk/#ZkI\P"_$^I?I,S+?b-:5*?#Z>?b<9Ou$<H>EUc~>cvx
exec[
Usage: $ gs -q -dNOPROMPT -dNODISPLAY -dBATCH thisfile.ps <input.in >output.out

F#: 224 225, 226, 248, 252, 270, 276, 299, 306 Chars
let x,(/)=System.Console.ReadLine(),String.replicate
let t,p=(int x.[0]-60)%7*5,int x.[1]%2
let g s i=printf"%s"(i/((99/s).[t+4*p..t+int x.[2..]*5+5*p]+"\n"))
g"| ### ### | ### ### ### "5
g"| "3
g"|____"1
I used modules of 2 to detect for a space or pound.
' ' is 32 % 2 = 0
'#' is 35 % 2 = 1
and since my conditional returned zeros for false I just multiplied the modules result.
Used the <| operator to shave off one space char.
Used operator overloading to save another char.
original
let piano_long (input:string) =
let sharp, flat = if input.[1] = '#' then 4, 1 else 0, 0
let note = (int input.[0] - 60) % 7
let num = int (input.Substring 2)
let start = note * 5 + sharp
let stop = num * 5 + 1 + flat
let top = "| ### ### | ### ### ### | ### ### | ### ### ### |"
let middle = "| | | | | | | | | | | | | | |"
let bottom = "|____|____|____|____|____|____|____|____|____|____|____|____|____|____|"
let mutable piano = ""
for i in 1..5 do
piano <- piano + top.Substring(start, stop) + "\n"
for i in 1..3 do
piano <- piano + middle.Substring(start, stop) + "\n"
piano <- piano + bottom.Substring(start, stop)
printf "%s\n\n" piano

sed, 231 235 234 235 237 238 244 268 269 270 276 279 280 282 287 300 307 314 329 338 characters
Works for up to 99 keys. The standard piano has 52 white keys, so this should be sufficient.
s/.*/CDEFGABC&=0123456789-/
s/(.).=(.*)\1.*/&\2\2\2\2\2\2\2\2\2\2/
s/ .?(.)=(.*)\1.*-/\2/
s/.*#/%&/
:
s/((.)(.).*\2)[#-9]/\1 \3/
t
s/[^ %CF]/###/g
s/C|F/ | /g
s/(%....)?.{25}(.*)./\2/p
p
p
p
p
s/## /| /g
s/#[|#]/ |/g
p
p
p
y/ /_/
Examples:
$ echo C 14 | sed -rf piano.sed
| ### ### | ### ### ### | ### ### | ### ### ### |
| ### ### | ### ### ### | ### ### | ### ### ### |
| ### ### | ### ### ### | ### ### | ### ### ### |
| ### ### | ### ### ### | ### ### | ### ### ### |
| ### ### | ### ### ### | ### ### | ### ### ### |
| | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |
|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
$ echo D# 1 | sed -rf piano.sed
### |
### |
### |
### |
### |
| |
| |
| |
_|____|
$ echo A 7 | sed -rf piano.sed
## ### | ### ### | ### ##
## ### | ### ### | ### ##
## ### | ### ### | ### ##
## ### | ### ### | ### ##
## ### | ### ### | ### ##
| | | | | | | |
| | | | | | | |
| | | | | | | |
|____|____|____|____|____|____|____|
$ echo A 52 | sed -rf piano.sed
## ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ##
## ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ##
## ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ##
## ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ##
## ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ### ### | ### ### ### | ##
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
The last example prints the standard keyboard, along with imaginary black keys on either end.

PianoScript - 2 characters
It's a one-liner:
go
Usage:
PianoScript piano.ps G# 11
Output:
### ### | ### ### | ### ### ### | ### ##
### ### | ### ### | ### ### ### | ### ##
### ### | ### ### | ### ### ### | ### ##
### ### | ### ### | ### ### ### | ### ##
### ### | ### ### | ### ### ### | ### ##
| | | | | | | | | | | |
| | | | | | | | | | | |
_|____|____|____|____|____|____|____|____|____|____|____|
More information on the PianoScript language can be found here.

JavaScript - 195 chars
Hey, golf is a game where you only compete against yourself right? :)
k=readFile(0).split(' ')
q=!k[0][1]
r=k[1]
o=''
for(x=10;x--;){p=k[0].charCodeAt(0)-65+!q
s=''
for(j=+r+1;j--;){p=++p%7
s+=x>4&&!p|p%3?'### ':x?' | ':'_|___'}o+=s.substring(q,r*5+2)+'\n'}print(o)
Solution by gnarf; ported to Rhino (with a minor fix and formatting changes) by KirarinSnow; further chipped away by gnarf; error corrected by KirarinSnow. cache k[1] by cwallenpoole
Usage: $ cp input.in 0; rhino thisfile.js
Quick HTML Demo Version:
Golf Test -
Adds readFile=prompt;print=function(a) {document.write("<pre>"+a);}

Python3 - 158
Save on input vs raw_input. Lose on () for print
k,n=input().split()
o=(ord(k[0])-65)*5
n=int(n)*5+1
for x in["## ### | ### "]*5+[n*"| "]*3+[n*"|____"]:print(((x+x[::-1][:-1])*n)[o+3*len(k[1:]):o+n])

F#: 355 significant chars
All on one line:
let[|x;y|]=System.Console.ReadLine().Split([|' '|])in[for i in 1..9->let r (a:string) b j (s:string)=s.Replace(a,if i>j then b else a)in((String.replicate(int y+1)"23012123012121").Substring(int(x.[0])-65,int y*2+x.Length).Replace("0","| ")|>r"1""#"0|>r"2""## "0|>r"3"" "0).TrimEnd()|>r"###"" | "5|>r"##""| "5|>r" ""_"8]|>String.concat"\n"|>printfn "%s"
Expanded:
let piano() =
let[|x;y|]=System.Console.ReadLine().Split([|' '|])in
[for i in 1..9->
let r (a:string) b j (s:string) = s.Replace(a,if i>j then b else a) in
((String.replicate (int y+1) "23012123012121")
.Substring(int(x.[0])-65,int y*2+x.Length).Replace("0","| ")
|> r "1" "#" 0
|> r "2" "## " 0
|> r "3" " " 0)
.TrimEnd()|> r "###" " | " 5|> r "##" "| " 5|> r " " "_" 8]
|> String.concat "\n"
|> printfn "%s"

SETL
165 characters; Translation of gribblers Python solution.
get(l);[k,n]:=split(l);o:=(abs k(1)-65)*5;n:=1+5*val n;(for x in['## ### | ### ']*5+[n*'| ']*3+[n*'|____'])print(((x+reverse x(2..))*n)(o+4*#k-3..o+n));end;

D2 (templates): 331 370 400 + 17 characters
(based on the Ruby solution.)
Compressed:
template J(alias T,int b,int e,r...){static if(e)enum J=T!(b,r)~J!(T,b+1,e-1,r);else enum J="";}template K(int i,int t){enum K=t>7?"_|___":t<5&&3&i%7?"### ":" | ";}template R(int t,int s,int l,int h){enum R=J!(K,s-h,l,t)[h..$-3]~"\n";}template M(alias k){enum M=J!(R,0,9,k[0]+1,k[$-2]>32?k[$-1]+10*k[$-2]-527:k[$-1]-47,k[0]&1);}
Explained:
/**
Macros:
D = <tt>$0</tt>
*/
;
/**
$(D_PSYMBOL J) (short for "join") will evaluate $(D T!(i,r)) for
$(D_PARAM i) in $(D [b..b+e]). Then, these compile-time strings will be
concatenated.
*/
template J(alias T,int b,int e,r...){
static if(e)
enum J=T!(b,r)~J!(T,b+1,e-1,r);
else
enum J="";
}
/**
$(D_PSYMBOL K) (short for "key") will generate 5 characters as a row of
key $(D_PARAM i) at row $(D_PARAM t).
*/
template K(int i,int t){
enum K=t>7?"_|___":t<5&&3&i%7?"### ":" | ";
}
/**
$(D_PSYMBOL R) (short for "row") will generate the keyboard at row
$(D_PARAM t), from key $(D_PARAM s) and sharpness $(D_PARAM h) with a
length of $(D_PARAM l) keys.
*/
template R(int t,int s,int l,int h){
enum R=J!(K,s-h,l,t)[h..$-3]~"\n";
}
/**
$(D_PSYMBOL M) (short for "main") results in the whole keyboard as a string.
Example:
-----
pragma(msg,M!("C 14"));
pragma(msg,M!("D# 1"));
pragma(msg,M!("A 7"));
-----
*/
template M(alias k){
enum M=J!(R,0,9,k[0]+1,k[$-2]>32?k[$-1]+10*k[$-2]-527:k[$-1]-47,k[0]&1);
}
Since we can't pass parameters from dmd the input must be done in the code. Supports only up to 99 keys.

Haskell: 212 211 208 characters
a=" | "
b=" ### "
d=concat.cycle
e=d[b,b,a,b,b,a,b]
f=d[a]
t x s m n=map(take(5*read s+m).drop(5*length['#'..x]-n))[e,e,e,e,e,f,f,f,d["__|__"]]
u(x:'#':s)=t x s 2 4
u(x:s)=t x s 1 8
main=interact$unlines.u
It still assumes ascii-compatible letters (specifically, the sequence "#ABCDEFG"), but no longer requires Char.ord

Ruby - 113 chars
Runs with command line arguments
$ ruby piano.rb A 7
k,c=$*
9.times{|x|puts (((b=x<8?' | ':'__|__')+(a=x<5?' ### ':b)*3+b+a*2)*j=k[0]*5-2+4*s=k.size)[j,c.to_i*5+s]}
Ruby - 118 chars
k,c=$*
9.times{|x|puts (((b=x<8?' | ':'__|__')+(a=x<5?' ### ':b)*3+b+a*2)*j=2+k[0]*5+4*s=k.size-1)[j..c.to_i*5+s+j]}

PHP - 208 chars
<?$e=45*substr($a=PIANO,2+$d=!($a[1]^~ì))+9+$d*45;$j=9*$c=4*$d;for($b=ord($a[0])-65,--$c;$j<$e;$f[$i=$j++%9].=($c=($c+!$i)%5)%4<2&$i>3&$b%3!=2?Ü:($c?$i?ß: :))$j%45-36?:$b=++$b%7;for(;$a=$f[$i--];)echo~$a,~õ;
Shall have to be improved.
The input has to be delivered in the constant named PIANO.

F# 414 386 372 significant characters:
//wins me 2 characters
open System
//String.replicate, didn't know this existed before reading Juliet
let r=String.replicate
//print s n times, each time on a newline
let P n s=printf"%s"(r n (s+"\n"))
//define top rows
let t="## ### | ### ### | ### #"
//middle and bottom rows can be defined using 'r'
let m,b=r 7"| ",r 7"|____"
//pick of chars from O to n+O from string, wrap round if we go beyond s.Length
let L(s:string)O n=String([|5*O..5*(n+O)|]|>Array.map(fun i->s.[i%35]))
//match input string into two halves
let[|k;n|]=Console.ReadLine().Split([|' '|])
//work out start pos and length (in chars, not keys)
let O,N=
let K=int k.[0]-65 //'A'=65, this is why t starts at A
if k.[0]='#'then(K+3,int n+2)else(K,int n)
//Print 5 top rows, 3 middle rows and the bottom row
P 5(L t O N)
P 3(L m O N)
P 1(L b O N)
Oh, and one bonus, this script will actually handle "F# 372" correctly - I won't annoy you by pasting it here though...
System.Console.ReadLine() is such a bummer...

Related

Yii2 findBySql: How to specify $params?

Yii2 provides ActiveRecord::findBySql für raw SQL queries:
public static yii\db\ActiveQuery findBySql ( $sql, $params = [] )
Since there is no hint in the documentation: How to specify $params?
UPDATE
The reason there isn't any docs about the params passed to the findBySql() method is because the method returns the instance of ActiveQuery and if you see the last line of this method in yii\db\ActiveRecord.php it sets the $params via $query->params($params), means the yii\db\ActiveQuery function params($params) which defines the $params as
$params list of query parameter values indexed by parameter
placeholders. For example, [':name' => 'Dan', ':age' => 31].
I guess you should try the following way if lets say you have a table with name product
+----+-----------------+------------+--------+
| id | name | is_deleted | price |
+----+-----------------+------------+--------+
| 1 | shugal | 1 | 65.00 |
| 2 | spoon | 1 | 55.00 |
| 4 | kettle | 1 | 15.00 |
| 5 | spoon | 0 | 15.00 |
| 6 | plates | 0 | 105.00 |
| 7 | dishes | 0 | 15.00 |
| 8 | forks | 0 | 15.00 |
| 10 | pressure cooker | 0 | 203.00 |
| 16 | shugal | 1 | 65.00 |
| 17 | something | 0 | 25.00 |
| 25 | multi product | 0 | 0.00 |
| 66 | pans | 0 | 15.00 |
+----+-----------------+------------+--------+
using the following code you can select all the products that are deleted using params
$q = Product::findBySql(
"SELECT * FROM product where is_deleted=:deleted",
[':deleted' => 1]
)->all();
Hope this helps

how to select the first row with minimum date for each unique value and specific condition

i have the following table
table 1
------------------------------------------
| animal_id | animal_name | animal_type |
------------------------------------------
| 1 | kay | cat |
| 2 | sandy | dog |
------------------------------------------
table 2
--------------------------------------------------------------------------
| vaccine_id | animal_id | vaccine_name | vaccine_status | vaccine_date |
--------------------------------------------------------------------------
| 1 | 1 | rabies | done | 2015-09-09 |
| 2 | 1 | chlamydiasis | undone | 2015-09-15 |
| 3 | 1 | parasite | undone | 2015-10-20 |
| 4 | 2 | parasytosis | undone | 2015-11-10 |
| 5 | 2 | rabies | undone | 2015-11-05 |
expected result:
--------------------------------------------------------------------------------------------------------------
| animal_id | animal_name | animal_type | vacccine_id | vaccine_name | vaccine_status | vaccine_date |
--------------------------------------------------------------------------------------------------------------
| 1 | kay | cat | 2 | chlamydiasis | undone | 2015-09-15 |
| 2 | sandy | dog | 5 | rabies | undone | 2015-11-05 |
the result will show all the first row of each unique value between two tables with the most recent vaccine_date and the condition where the vaccine_status is undone. I'm using SQL by the way
For complex queries you often need to manipulate the data with something like PHP. For example, using 2 queries on the data you provided:
<?php
$link=mysqli_connect("host","user","password","database");
// Start with the list of animals
$sql = "SELECT * FROM animals";
$res = $link->query($sql);
for($i=0; $i<mysqli_num_rows($res); ++$i){
$row1 = mysqli_fetch_assoc($res);
$animal_id = $row1['animal_id'];
$sql = "SELECT * FROM vaccines WHERE animal_id = $animal_id AND vaccine_status = 'undone' ORDER BY vaccine_date ASC LIMIT 1";
$res2 = $link->query($sql);
$row2 = mysqli_fetch_assoc($res2);
$arr[$animal_id] = array();
array_push($arr[$animal_id], $row1['animal_name'], $row1['animal_type'], $row2['vaccine_id'], $row2['vaccine_name'], $row2['vaccine_status'], $row2['vaccine_date']);
}
echo "RESULT:";
echo "<table border=1><tr><th>animal_id</th><th>animal_name</th><th>animal_type</th><th>vaccine_id</th><th>vaccine_name</th><th>vaccine_status</th><th>vaccine_date</th></tr>";
foreach($arr as $key => $val){
echo "<tr><td>$key</td><td>".implode("</td><td>", $val)."</td></tr><br>";
}
?>
...produces the following output:

Gulp - one stream splits into multiple threads

I'm need implement that gulp task, where stream splits into multiple threads.
gulp.src("./src/index.coffee")
|
|
V
.pipe(coffee())
|
...
|
V
_____________________________________________
| | . . . | |
| | . . . | |
V V V V
.pipe(replace("a", "b")) .pipe(replace("a", "c")) .pipe(replace("a", "y"))
| | | |
| | | |
V V V V
.pipe(gulp.dest("./b")) .pipe(gulp.dest("./c")) .pipe(gulp.dest("./y"))
Anyone have ideas how to?

MySQL. Can i choose rows with map?

So, I have an array id=>time and a table.
| id | text | created_at |
How to get all rows where CREATED_AT>array['id'] and ID=id in one query?
i can do, something like this
foreach (array as $key=>$value) {
query("SELECT * FROM table WHERE CREATED_AT>$value and ID=$key");
}
but i would like to put it all in one query.
Sample data:
| id | text | created_at |
--------------------------
| 1 | aaaa | 123 |
| 2 | bbbb | 124 |
| 1 | cccc | 122 |
| 3 | dddd | 125 |
| 1 | eeee | 125 |
array( '1' => 123, '2' => 125, '3' => 124);
Query should return this rows:
| 1 | aaaa | 123 |
| 3 | dddd | 125 |
| 1 | eeee | 125 |
You could do a long series of
$my_query = "SELECT * FROM table WHERE";
$counter = 0;
foreach (array as $key=>$value) {
if ($counter > 0)
$my_query += " OR ";
$my_query += "(CREATED_AT>$value and ID=$key)";
$counter++;
}
However this is ugly. I wouldn't recommend doing it. Aside from that I think there's no easy way to do this in one query. It would be easy if there was just a single batch of IDs you are querying for, but given both criteria I can't think of any other way.
I don't think it's such a bad idea to do it in a for loop... It's definitely more readable than the code I gave above.

Unicorns eat up MySQL connections not respecting the pool size - Rails

I run 4 Unicorn processes for my Rails app and they eat up all the available MySQL connections causing it to collapse with 'too many connections' error. Today I had to reboot my DB instance 4 times. =(
Processes
$ ps ax | grep [u]ni
21618 ? Sl 0:15 unicorn master -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production
21632 ? Sl 0:20 unicorn worker[0] -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production
21636 ? Sl 0:14 unicorn worker[1] -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production
21640 ? Sl 0:20 unicorn worker[2] -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production
21645 ? Sl 0:12 unicorn worker[3] -D -c /home/deployer/apps/XXX/shared/config/unicorn.rb -E production
My database.yml is setting up 22 connections for the ActiveRecord pool...
...
production:
adapter: mysql2
encoding: utf8
database: xxx
username: xxx
password: xxx
host: xxx
port: 3306
pool: 22
...
And the Unicorn config file looks like this:
working_directory "/home/deployer/apps/XXX/current"
pid "/home/deployer/apps/XXX/shared/pids/unicorn.pid"
stderr_path "/home/deployer/apps/XXX/shared/log/unicorn.log"
stdout_path "/home/deployer/apps/XXX/shared/log/unicorn.log"
listen "/tmp/unicorn.XXX.sock"
worker_processes 4
timeout 100
preload_app true
before_fork do |server, worker|
# Disconnect since the database connection will not carry over
if defined? ActiveRecord::Base
ActiveRecord::Base.connection.disconnect!
end
# Quit the old unicorn process
old_pid = "#{server.config[:pid]}.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end
after_fork do |server, worker|
# Start up the database connection again in the worker
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
end
child_pid = server.config[:pid].sub(".pid", ".#{worker.nr}.pid")
system("echo #{Process.pid} > #{child_pid}")
end
And if we look into the DB console, we'll see something like this. They've eaten most of the connections. (I had nothing but Unicorn running at the moment) To my mind there should have been 1 connection * 4 unicorns = 4 connections.
mysql> show full processlist;
+-----+----------+--------------------------------------------------+------------------------+---------+------+-------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+----------+--------------------------------------------------+------------------------+---------+------+-------+-----------------------+
| 2 | rdsadmin | localhost:31383 | NULL | Sleep | 9 | | NULL |
| 52 | level | 212.100.140.42:50683 | leveltravel_production | Query | 0 | NULL | show full processlist |
| 74 | level | ip-10-55-10-151.eu-west-1.compute.internal:38197 | leveltravel_production | Sleep | 5 | | NULL |
| 75 | level | ip-10-55-10-151.eu-west-1.compute.internal:38199 | leveltravel_production | Sleep | 8 | | NULL |
| 76 | level | ip-10-55-10-151.eu-west-1.compute.internal:38201 | leveltravel_production | Sleep | 8 | | NULL |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CUT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 157 | level | ip-10-55-10-151.eu-west-1.compute.internal:38321 | leveltravel_production | Sleep | 154 | | NULL |
| 158 | level | ip-10-55-10-151.eu-west-1.compute.internal:38322 | leveltravel_production | Sleep | 17 | | NULL |
| 159 | level | ip-10-55-10-151.eu-west-1.compute.internal:38325 | leveltravel_production | Sleep | 54 | | NULL |
| 160 | level | ip-10-55-10-151.eu-west-1.compute.internal:38326 | leveltravel_production | Sleep | 54 | | NULL |
| 161 | level | ip-10-55-10-151.eu-west-1.compute.internal:38327 | leveltravel_production | Sleep | 54 | | NULL |
| 162 | level | ip-10-55-10-151.eu-west-1.compute.internal:38329 | leveltravel_production | Sleep | 42 | | NULL |
+-----+----------+--------------------------------------------------+------------------------+---------+------+-------+-----------------------+
90 rows in set (0.15 sec)
You may also have a look at Issue #503 in sidekiq repository for the background of this problem https://github.com/mperham/sidekiq/issues/503
You have run 4 unicorn process. It is the PROCESS, NOT THREAD.
Every process have 22 connections in pool. Totally they have 22*4 = 88 connections.
If you want have 4 connection for 4 worker process, you can set pool: 1 in database.yml