正しい文(クイズ)
Posted feedbacks - PHP
とりあえず乱暴な方法だけど2進から16進まで一つずつ答えを得た。 この文は0が11個,1が100個あります。 この文は0が1個,1が11個,2が2個あります。 この文は0が1個,1が11個,2が2個,3が1個あります。 ... この文は0が1個,1が11個,2が2個,3が1個,4が1個,5が1個,6が1個,7が1個,8が1個,9が1個あります。 ... この文は0が1個,1が11個,2が2個,3が1個,4が1個,5が1個,6が1個,7が1個,8が1個,9が1個,aが1個,bが1個,cが1個,dが1個,eが1個,fが1個あります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php
for($n=2;$n<=16;++$n)
{ $str="";
do{
$a=count_chars($str);
$b=array();
for($i=0;$i<$n;++$i)
{ $c=base_convert($i,10,$n);
$b[]="${c}が".base_convert($a[ord($c)],10,$n)."個";
}
$str0=$str;
$str=implode(",",$b);
}while($str!=$str0);
echo "この文は${str}あります。\n";
}
?>
|
全探索バージョン。 直前のお題"自然数の分割"のプログラムを応用して 「数字の数は2n~2n+2 (2進は例外)」という条件で探索範囲を限定。 2進から16進まで探索してCore2Duo 1.2GHzで 29秒 2進: この文は0が11個,1が100個あります。 3進: この文は0が10個,1が10個,2が2個あります。 この文は0が1個,1が11個,2が2個あります。 この文は0が2個,1が2個,2が10個あります。 ... 10進: この文は0が1個,1が11個,2が2個,3が1個,4が1個,5が1個,6が1個,7が1個,8が1個,9が1個あります。 この文は0が1個,1が7個,2が3個,3が2個,4が1個,5が1個,6が1個,7が2個,8が1個,9が1個あります。 ... 16進: この文は0が1個,1が11個,2が2個,3が1個,4が1個,5が1個,6が1個,7が1個,8が1個,9が1個,aが1個,bが1個,cが1個,dが1個,eが1個,fが1個あります。 この文は0が1個,1がd個,2が3個,3が2個,4が1個,5が1個,6が1個,7が1個,8が1個,9が1個,aが1個,bが1個,cが1個,dが2個,eが1個,fが1個あります。 28.799607992172sec
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <?php
function cmp(&$a1,&$a2)
{
foreach($a2 as $k=>$v)
if($a1[ord(base_convert($k,10,36))]!=$v)
return false;
return true;
}
function judge($a,$n)
{
$b=array();
for($i=0;$i<$n;++$i)
{ $c=base_convert($i,10,$n);
$b[]="${c}が".base_convert($a[$i],10,$n)."個";
}
$str=implode(",",$b);
$a1=count_chars($str);
if(cmp($a1,$a))
echo "この文は${str}あります。\n";
}
function part($a,$n,$c,$s1,$s2,$m)
{
if(!$c)
{ $m1=min($m-$s1,$s2+1);
for($i=$n*2-$s1;$i<=$m1;++$i)
{ $a[$c]=$i;
judge($a,$n);
}
}
else
{ $m1=min($m-$s1,$s2/$c+1);
for($i=1;$i<=$m1;++$i)
{ $a[$c]=$i;
part($a,$n,$c-1,$s1+$i,$s2-$c*($i-1),$m);
}
}
}
$t=microtime(true);
for($n=2;$n<=16;++$n)
{ echo "${n}進:\n";
$m=max($n*2+2,10);
part(array(),$n,$n-1,0,$m,$m);
}
echo microtime(true)-$t,"sec\n";
?>
|
数字の出現回数の合計と(数字x(出現回数-1))の積分の関係で縛りを追加したら #4376と同条件で4.1秒ほどになりました。 リストは変更していないcmp()とjudge()省略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?php
function part($a,$n,$c,$s1,$s2,$m)
{
if(!$c)
{ for($i=$s2-$s1;$i<=min($m-$s1,$m-$s2+1);$i+=$n-1)
if($i>=$n*2-$s1)
{ $a[$c]=$i;
judge($a,$n);
}
}
else
{ $m1=min($m-$s1,($m-$s2)/$c+1);
for($i=1;$i<=$m1;++$i)
{ $a[$c]=$i;
part($a,$n,$c-1,$s1+$i,$s2+$c*($i-1),$m);
}
}
}
$t=microtime(true);
for($n=2;$n<=16;++$n)
{ echo "${n}進:\n";
$m=max($n*2+2,10);
part(array(),$n,$n-1,0,0,$m);
}
echo microtime(true)-$t,"sec\n";
?>
|




herumi
#4100()
Rating4/14=0.29
[ reply ]