<?php class Calculus{const GREATEST_NUMBER_WITH_UNIQUE_DIGITS='9876543210';static function nbOfNumbersWithUniqueDigits($min,$max=self::GREATEST_NUMBER_WITH_UNIQUE_DIGITS,$leadingZeros=TRUE){if(!(ctype_digit("$min")||ctype_digit("$max"))){return0;}if(bccomp($max,self::GREATEST_NUMBER_WITH_UNIQUE_DIGITS)==1){$max=self::GREATEST_NUMBER_WITH_UNIQUE_DIGITS;}$comp=bccomp($min,$max);if($comp===1){return0;}elseif($comp===0){return(self::hasUniqueDigits($min))?1:0;}$nb=0;$min="$min";$max="$max";$equalizeLength=function()use(&$min,&$max){if(strlen($min)<strlen($max)){$min=str_pad($min,strlen($max),'0',STR_PAD_LEFT);}elseif(strlen($min)>strlen($max)){$max=str_pad($max,strlen($min),'0',STR_PAD_LEFT);}};if($leadingZeros){$equalizeLength();}if($min[strlen($min)-1]==9){if(self::hasUniqueDigits($min)){++$nb;}$min=bcadd($min,1);}if($max[strlen($max)-1]==0){if(self::hasUniqueDigits($max)){++$nb;}$max=bcsub($max,1);}if(FALSE===$leadingZeros){$equalizeLength();}$steps=self::steps($min,$max);foreach($steps as $step){$nb+=self::countAllowedNumbers($step[0],$step[1],$leadingZeros);}return $nb;}static function hasUniqueDigits($p){return(ctype_digit("$p"))?(count(array_flip(str_split($p,1)))===strlen($p)):FALSE;}static private function steps($minRange,$maxRange){$descendingSearch=FALSE;$len=strlen($minRange);$i=$len;$min=$minRange;$base=$minRange;$steps=array();while(--$i>=0){$left=substr($min,0,$i);$right=str_repeat('9',$len-$i);$max=$left.$right;$comp=bccomp($maxRange,$max);if($comp>=0){$steps[]=array($min,$max);$min=bcadd($max,1);$min=str_pad($min,$len,'0',STR_PAD_LEFT);$base=$min;if($comp===0){break;}}else{$descendingSearch=TRUE;break;}}if($descendingSearch){$i=$len;$max=$maxRange;while(--$i>=0){$left=substr($max,0,$i);$right=str_repeat('0',$len-$i);$min=$left.$right;$comp=bccomp($min,$base);if($comp>=0){$steps[]=array($min,$max);if($comp===0){break;}$max=bcsub($min,1);}else{$steps[]=array($base,$max);break;}}}return $steps;}static private function countAllowedNumbers($min,$max,$leadingZeros){$nbAllowed=array();if(FALSE===$leadingZeros){$min=($min==0)?'0':ltrim($min,'0');$max=($max==0)?'0':ltrim($max,'0');}$iMax=strlen($min)-1;for($i=0;$i<=$iMax;++$i){$structure[$i]=array('possible'=>array(),'forbidden'=>array(),'substract'=>0);}$i=-1;while(++$i<=$iMax){$structure[$i]['possible']=range($min[$i],$max[$i]);if($min[$i]==$max[$i]){for($j=$i+1;$j<=$iMax;++$j){$structure[$j]['forbidden'][]=$min[$i];}}else{for($j=$i+1;$j<=$iMax;++$j){++$structure[$j]['substract'];}}}foreach($structure as $value){$nbAllowed[]=count(array_diff($value['possible'],$value['forbidden']))-$value['substract'];}return(($nb=array_product($nbAllowed))>0)?$nb:0;}}?> |