六村リオ / 霧島京子 / 緑川つばめ / 島根ルミ / 島根ルミ149 / 島根ルミ121 / 共通解
https://paiza.jp/poh/joshibato/matsue-ruby/
何故かこの問題だけ、提出コードバイト数が表示されるようになってます。
これはつまりgolfしろという無言の圧力ですかね。
ということで締切を過ぎたので私的最短149バイトのコードを公開します。
なお、PHPは0.02秒の争いになっているのですが、私は0.02秒が取れなかったので0.03秒を取れるコードを出しておきます。
たぶん何十回か投稿すればそのうち一回くらい平均0.02秒台になれるんじゃないかと思います。
台じゃなくて四捨五入だったらどうしよう。
<?php for($f=split(B^H,`dd`);$r=strrev($v=$f[++$i]);)${$v.$c=$v!=$r?$v<$r?:!$v=$r:$x.=$v}?$p[]=$v:${$v.!$c}++;sort($p);echo$y=join($p),$x,strrev($y);
結果。
https://paiza.jp/poh/joshibato/matsue-ruby/result/f77e5c71
とりあえず整形。
<?php
for(
$f = split(B^H,`dd`);
$r = strrev( $v = $f[++$i] );
)
${$v.$c=
$v!=$r
? $v<$r
?
: !$v=$r
: $x.=$v
}
? $p[]=$v
: ${$v.!$c}++;
sort($p);
echo $y=join($p), $x, strrev($y);
見返してみても、我ながら全く意味がわかりません。
これはソースを解説するより、試行錯誤の過程をさらした方がわかりやすいのではないかと思うので、下に並べておきます。
あまり大きな発想の転換というものはなく、縮める場所を探していたら少しずつ減っていきました。
しかし最後の方はもう何やってるのかわからない感。
// 316バイト 単に詰めただけ
<?php $f=file('php://stdin', FILE_IGNORE_NEW_LINES);unset($f[0]);foreach($f as$v){$r=strrev($v);if($v<$r)$c=2;elseif($v>$r){$v=$r;$c=0;}else$c=1;if($l[$v][2-$c]>0){$p[$v]++;$l[$v][2-$c]--;}else$l[$v][$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as $k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 284バイト 標準入力を省力化
<?php for($j=fgets(STDIN);$i++<$j;){$r=strrev($v=trim(fgets(STDIN)));$c=1;if($v<$r)$c=2;elseif($v>$r){$v=$r;$c=0;}if($l[$v][2-$c]>0){$p[$v]++;$l[$v][2-$c]--;}else$l[$v][$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 282バイト 条件>0は不要
<?php for($j=fgets(STDIN);$i++<$j;){$r=strrev($v=trim(fgets(STDIN)));$c=1;if($v<$r)$c=2;elseif($v>$r){$v=$r;$c=0;}if($l[$v][2-$c]){$p[$v]++;$l[$v][2-$c]--;}else$l[$v][$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 274バイト `dd`で標準入力を取れる
<?php $f=explode("\n",`dd`);while($v=next($f)){$r=strrev($v);$c=1;if($v<$r)$c=2;elseif($v>$r){$v=$r;$c=0;}if($l[$v][2-$c]){$p[$v]++;$l[$v][2-$c]--;}else$l[$v][$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 272バイト $cと2-$cを逆に
<?php $f=explode("\n",`dd`);while($v=next($f)){$r=strrev($v);$c=1;if($v<$r)$c=0;elseif($v>$r){$v=$r;$c=2;}if($l[$v][$c]){$p[$v]++;$l[$v][$c]--;}else$l[$v][2-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 269バイト ようやくループ内部に手を付け始める
<?php $f=explode("\n",`dd`);while($v=next($f)){$r=strrev($v);$c=1;if($v<$r)$c=0;elseif($v>$r){$v=$r;$c=2;}if($l[$v][$c])$p[$v]+=$l[$v][$c]--;else$l[$v][2-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 266バイト 関数の引数内でも代入できる
<?php $f=explode("\n",`dd`);while($r=strrev($v=next($f))){$c=1;if($v<$r)$c=0;elseif($v>$r){$v=$r;$c=2;}if($l[$v][$c])$p[$v]+=$l[$v][$c]--;else$l[$v][2-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 256バイト ifは三項演算子で代用可能
<?php $f=explode("\n",`dd`);while($r=strrev($v=next($f))){$c=$v<$r?0:1;if($v>$r){$v=$r;$c=2;}if($l[$v][$c])$p[$v]+=$l[$v][$c]--;else$l[$v][2-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 253バイト ifは&&で代用可能
<?php $f=explode("\n",`dd`);while($r=strrev($v=next($f))){$c=$v<$r?0:1;$v>$r&&++$c&&$v=$r;if($l[$v][$c])$p[$v]+=$l[$v][$c]--;else$l[$v][2-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 246バイト 三項演算子増やした
<?php $f=explode("\n",`dd`);while($r=strrev($v=next($f))){$c=$v<$r?0:1;$v>$r&&++$c&&$v=$r;$l[$v][$c]?$p[$v]+=$l[$v][$c]--:$l[$v][2-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)if($v[1])$x=$k;echo$y.$x.strrev($y);
// 244バイト ついにifがなくなった
<?php $f=explode("\n",`dd`);while($r=strrev($v=next($f))){$c=$v<$r?0:1;$v>$r&&++$c&&$v=$r;$l[$v][$c]?$p[$v]+=$l[$v][$c]--:$l[$v][2-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);foreach($l as$k=>$v)$v[1]&&$x=$k;echo$y.$x.strrev($y);
// 214バイト 中央部分は1種類しかないので先に分けても問題ない
<?php $f=file('/dev/fd/0',2);while($r=strrev($v=$f[++$i])){$c=$v<=$r?$v==$r?$x.=$v:-1:!!$v=$r;$l[$v][$c]?$p[$v]+=$l[$v][$c]--:$l[$v][-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);echo$y.$x.strrev($y);
// 213バイト 順番を変えて演算子を1バイト削る
<?php $f=file('/dev/fd/0',2);while($r=strrev($v=$f[++$i])){$c=$v!=$r?$v>$r?!!$v=$r:-1:$x.=$v;$l[$v][$c]?$p[$v]+=$l[$v][$c]--:$l[$v][-$c]++;}ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);echo$y.$x.strrev($y);
// 207バイト ついにfor内部が1文になった
<?php for($f=file('/dev/fd/0',2);$r=strrev($v=$f[++$i]);)$l[$v][$c=$v!=$r?$v>$r?!!$v=$r:-1:$x.=$v]?$p[$v]+=$l[$v][$c]--:$l[$v][-$c]++;ksort($p);foreach($p as$k=>$v)$y.=str_repeat($k,$v);echo$y.$x.strrev($y);
// 174バイト 同じ単語は出てこないのでチェックする必要なし
<?php for($f=file('/dev/fd/0',2);$r=strrev($v=$f[++$i]);)$l[$v][$c=$v!=$r?$v>$r?!!$v=$r:-1:$x.=$v]?$p[]=$v:$l[$v][-$c]++;sort($p);foreach($p as$v)$y.=$v;echo$y.$x.strrev($y);
// 163バイト foreachもなくなった
<?php for($f=file('/dev/fd/0',2);$r=strrev($v=$f[++$i]);)$l[$v][$c=$v!=$r?$v>$r?!!$v=$r:-1:$x.=$v]?$p[]=$v:$l[$v][-$c]++;sort($p);echo$y=implode($p),$x,strrev($y);
// 162バイト よく見たら/dev/fd/0よりddのほうが短かった
<?php for($f=explode("\n",`dd`);$r=strrev($v=$f[++$i]);)$l[$v][$c=$v!=$r?$v>$r?!!$v=$r:-1:$x.=$v]?$p[]=$v:$l[$v][-$c]++;sort($p);echo$y=implode($p),$x,strrev($y);
// 161バイト がんばって消した2-$cが戻ってきた
<?php for($f=explode("\n",`dd`);$r=strrev($v=$f[++$i]);)$l[$v][$c=$v!=$r?$v>$r?!$v=$r:2:$x.=$v]?$p[]=$v:$l[$v][2-$c]++;sort($p);echo$y=implode($p),$x,strrev($y);
// 158バイト implode=join
<?php for($f=explode("\n",`dd`);$r=strrev($v=$f[++$i]);)$l[$v][$c=$v!=$r?$v>$r?!$v=$r:2:$x.=$v]?$p[]=$v:$l[$v][2-$c]++;sort($p);echo$y=join($p),$x,strrev($y);
// 156バイト $lいらないんじゃねと思ったら削れた
<?php for($f=explode("\n",`dd`);$r=strrev($v=$f[++$i]);)${$v}[$c=$v!=$r?$v>$r?!$v=$r:2:$x.=$v]?$p[]=$v:${$v}[2-$c]++;sort($p);echo$y=join($p),$x,strrev($y);
// 154バイト splitはPHP7で削除された
<?php for($f=split("\n",`dd`);$r=strrev($v=$f[++$i]);)${$v}[$c=$v!=$r?$v>$r?!$v=$r:2:$x.=$v]?$p[]=$v:${$v}[2-$c]++;sort($p);echo$y=join($p),$x,strrev($y);
// 153バイト 三項演算子短絡表現を導入
<?php for($f=split("\n",`dd`);$r=strrev($v=$f[++$i]);)${$v}[$c=$v!=$r?$v<$r?:!$v=$r:$x.=$v]?$p[]=$v:${$v}[1-$c]++;sort($p);echo$y=join($p),$x,strrev($y);
// 152バイト 0/1なら!でいい
<?php for($f=split("\n",`dd`);$r=strrev($v=$f[++$i]);)${$v}[$c=$v!=$r?$v<$r?:!$v=$r:$x.=$v]?$p[]=$v:${$v}[!$c]++;sort($p);echo$y=join($p),$x,strrev($y);
// 151バイト LFを1バイト減らした
<?php for($f=split(B^H,`dd`);$r=strrev($v=$f[++$i]);${$v}[$c=$v!=$r?$v<$r?:!$v=$r:$x.=$v]?$p[]=$v:${$v}[!$c]++);sort($p);echo$y=join($p),$x,strrev($y);
// 149バイト 配列をフラットにした
<?php for($f=split(B^H,`dd`);$r=strrev($v=$f[++$i]);)${$v.$c=$v!=$r?$v<$r?:!$v=$r:$x.=$v}?$p[]=$v:${$v.!$c}++;sort($p);echo$y=join($p),$x,strrev($y);
なんとなくもう少し縮められそうな気はするんだけどなあ。
以下はおまけです。
// おまけ 真の最短コード
<?=`ruby -e 'Rubyの最短コード'`;
はい、真の最短はRubyの呼び出しで、Rubyの最短+16バイトです。
2015/09/25時点でのRuby最短は67バイトなので、83バイト。
なんと100バイトを切りました。
PHPだけでこの文字数を実現するのは、さすがにちょっと無理でしょう。
なお、中に何が入るのかはわからない模様。
あとRuby呼び出しはそれだけで0.1秒かかるので、タイム争いには全くついて行けません。
が、実は、かわりにPerl呼び出しにすれば0.03秒を保ったままもっと縮められたり。