Yep, just realised this (it was never explicitly asked for, I say in my defence; sometimes I do allow passwords to include other characters).
But the extra regexp is a bit overboard. After checking string length and the presense of letters and digits, all that still needs to be verified is that [a-zA-Z0-9] doesn't match.
I'd use strlen() to check string length explicitly - it's a lot faster than building a regexp to do the job, and it tends to be the most likely reason a password will fail.
I mean, if you were wanting to do the whole shebang with regexps:
if(!preg_match('/^(?=[a-z\d]{6})(?![a-z\d]{16})[a-z\d]*([a-z]\d|\d[a-z])[a-z\d]*$/i',$newpass))
does the job. 'Cept I still prefer to separate out the strlen checks. If I do those first, I can simplify down to:
if(strlen($newpass)<6 || strlen($newpass)>15 || !preg_match('/^[a-z\d]*([a-z]\d|\d[a-z])[a-z\d]*$/i',$newpass))
The key point being: if there are both letters and digits in the password, then there has to be some point where there is a letter followed by a digit or a digit followed by a letter.