Tag Archives: php - Page 2

『バイナリクロック』投稿

どう書く?への投稿。

お題:バイナリクロック
http://ja.doukaku.org/275/

時刻を二進数相当の表現で出力する時計アプリケーションを書いてください。

 他言語の投稿では、お題で例示されている■□で表現しているのだけど、同じでは面白くないのでケンシロウ進数で表現した。感嘆符はサービスだ。

$decs = explode(‘:’, date(‘H:i:s’, time()));
foreach ( $decs as $dec ) {
    $search = array(’1′, ’0′, ‘ ‘);
    $replace = array(‘あ’,'た’, ‘ ’);
    echo str_replace($search, $replace, sprintf(‘%6s’, decbin($dec))).”!\n”;
}
echo implode(‘:’, $decs);

出力:

 あたあたあ!
あたたあたた!
  あたたた!
21:36:08

『実用 R アナグラミング』を刷新中

 『実用 R アナグラミング』を書き直している。
 目的は、アナグラミングのスピードアップと、対応文字列長リミット(現在11文字)を伸ばす事、そして、「安易な兄」問題の対応。
 処理のタイムリミット(30秒)がなければ、理論的にいくらでも長い文字列を処理できるので、スピードアップは文字列長リミットに直接関わっている(今回の刷新では考えてないけど、更なるスピードアップを狙うなら、処理(作業)の一部をCで書くつもり)。
 あと、今回はローマ字文字列をマトリクスで読ませようとしている(既存では、かなり格好の悪いプログラムになっているので)。
実用 R アナグラミング
http://www.ivoryworks.com/anagram/
* 『実用 R アナグラミング』はローマ字のアナグラムを生成するWebサービスです。

PHP:switchブロック case 0 の混在はNG?

 少しハマったので。
 PHPはcase文に文字列を用いることが出来るが、以下のswitchブロックのように、比較対照を0としたcase文と’x'としたcase文が混在する場合、期待通りに動作しないようである。
 以下の例でechoによって出力されるのは、期待に反して’0′である。

$value = ‘x’;

switch ( $value ) {
case 0:
echo 0;
break;
case ‘x’:
echo ‘x’;
break;
default:
break;
}

 以下の例でechoによって出力されるのは、’x'である(期待通り)。

$value = ‘x’;

switch ( $value ) {
case ‘x’:
echo ‘x’;
break;
case 0:
echo 0;
break;
default:
break;
}

 なお、以下のように0を1に変更して実行すると、期待通り’x'が出力される。

$value = ‘x’;

switch ( $value ) {
case 1:
echo 1;
break;
case ‘x’:
echo ‘x’;
break;
default:
break;
}

 よって、型の混在が問題を引き起こしているのではなさそうであるが、マニュアルを読んでもこの件については触れられておらず、少し調べた限りではこの件に関する情報は得られなかった。
 ただ、このswitchブロックに達した時、比較対象とする変数が整数型と文字列型のどちらの可能性もあるというのはナンセンスであり、そのようなプログラムを組んではいけない。

『ケブンッリジ関数』投稿

 久々の『どう書く?』投稿。

お題:
ケブンッリジ関数
http://ja.doukaku.org/249/

 与えた文章の各単語の最初と最後の文字以外の文字を入れ替えた文章を出力する処理を実装して下さい。元の文章の与え方は特に問いません。
参考: 確かに”読めてしまう”コピペ

 話題になったケンブリッジ大学の研究成果。

こんちには みさなん おんげき ですか? わしたは げんき です。
この ぶんょしう は いりぎす の ケブンッリジ だがいく の けゅきんう の けっか
にんんげ は もじ を にしんき する とき その さしいょ と さいご の もさじえ あいてっれば
じばんゅん は めくちちゃゃ でも ちんゃと よめる という けゅきんう に もづいとて
わざと もじの じんばゅん を いかれえて あまりす。
どでうす? ちんゃと よゃちめう でしょ?
ちんゃと よためら はのんう よしろく 

 以下投稿したコード。PHP。ネストがダサい。マルチバイト対応のstr_shuffle()がないのでmb_str_shuffle()を作成。

$utf8_str = <<<HERE
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
HERE;

echo Cambridge( $utf8_str, ‘UTF-8′ );

function Cambridge( $text, $enc )
{
$ret = ”;
$lines = explode( “\n”, $text );
foreach ( $lines as $line ) {
$words = explode( ‘ ‘, trim($line) );
foreach ( $words as $word ) {
$len = mb_strlen( $word, $enc );
if ( 3 <  $len ) {
$head = mb_substr( $word, 0, 1, $enc );
$body = mb_str_shuffle( mb_substr( $word, 1, $len-2, $enc ), $enc );
$foot = mb_substr( $word, $len-1, 1, $enc );
$word = $head.$body.$foot;
}
$ret .= $word.’ ‘;
}
$ret = rtrim( $ret ).”\n”;
}
return $ret;
}

function mb_str_shuffle( $str, $enc )
{
$buff = array();
while ( $len = mb_strlen( $str, $enc ) ) {
$buff[] = mb_substr( $str, 0, 1, $enc );
$str = mb_substr( $str, 1, $len, $enc);
}
shuffle( $buff );
return implode( ”, $buff );
}

 文字を並び替えた結果、元の並びと同じになる事と、句読点や疑問符、感嘆符などを1文字として扱っている事(そうすべきではないと思う)は、単純さを優先したため考慮していない。
 以下出力結果。よしろく。

こんにちは みさなん おんげき でかす? わしたは げんき です。
この ぶょしんう は いぎりす の ケンッブリジ だいがく の けんゅきう の けっか
にんげん は もじ を にしんき する とき その さいしょ と さいご の もじさえ あれいてっば
じんゅばん は めちゃちくゃ でも ちゃんと よめる という けゅきんう に もとづいて
わざと もじの じばゅんん を いれえかて あますり。
どでうす? ちゃんと よちめゃう でょし?
ちんゃと よためら はのんう よしろく

PHP rank:14(64.0%)

fsockopen()が失敗する

Warning [PHP]: fsockopen() [function.fsockopen]: unable to connect to example.com 110

 外部のメールサーバにPOPで接続してメールを取得するPHPスクリプトで上記エラー。正確にはxoopsモジュールの一部。

 別のサーバでは正常に動作していたのに。
 名前が引けないのかと思い、SSHでサーバに接続し、コンソールでnslookup。

> nslookup example.com

 問題なく引ける。
 では、コンソールでPOP接続してみる。

> telnet example.com 110

 問題なく接続できる。更にアカウントとパスワードを叩いてメールボックスの中も除ける。
 で、ここまできて思い出した。似たような事が前にも。
 SELinux
 Google様に聞いてみると、httpd_can_network_connect がデフォルトで無効になっているからだと。

/usr/sbin/setsebool -P httpd_can_network_connect=1

 これでOKだ。
第5回 トラブルシューティングはCentOS 5におまかせ

アナグラムの促音対応

実用 R アナグラミング

 促音に対応するよう修正しました。
 促音とは「ppa(ッパ)」や「kka(ッカ)」のような、つまる音の事です。

 現在の最大文字列長11文字、長くしたいね・・・。

ローマ字アナグラム作る名も無いツール

 引き続き、ローマ字のアナグラムを作るプログラムを組んでます。

 やっぱり、元の文字列が長いと処理に時間がかかる。
 今、せいぜい10文字が限界。
 これ工夫しないと実用的じゃないですね。

 アナグラム化する元の文字列の文字列長、およびその文字構成によって何千というアナグラムが生まれる事があります。
 最初、1ページ30件くらいのリストを表示して「次のページ」とか「前のページ」とかいうリンクでリスト遷移させれば良いと思ってたけど、それだとどうにも使い勝手悪いので、リストを先頭の文字(音)で切り分けてインデックス振って、そのインデックスで切り分けられたリスト内を「次」「前」で移動させれば幾分か良さそう。

 プログラミング中、このアプリの名前を考えてます。
 難航。
 最初、ANAGRAMのアナグラムにしようかと思ったけど、ローマ字のアナグラム作るサービスなのに英語かよ、というので却下。
 なんたらメーカーとか、なんたらシステムとかそういうのは付けたくない。
 きっと何か日本語のアナグラムになると思うけど、あまりに突飛すぎるとシステムの機能を連想できないというジレンマが付きまとう。
 アナグラム前、アナグラム後、双方の言葉がこのシステムに関連するようなものだとベストなんだけどね。

『必ず解ける迷路』投稿

 どう書く?orgに投稿。

 今回のお題は必ず解ける迷路です。

以下のルールを満たすn×mの迷路を出力するプログラムを作ってください。

  1. 格子状の迷路であること。
  2. 経路の幅は均等であること。
  3. 迷路のある地点からの全ての地点に到達する経路が1つだけ存在すること。ループも認めません。
  4. 出力の度にランダムな迷路であること。ランダムシードが同じ時に同じ迷路になってしまうのはよいです。

 迷路生成のアルゴリズムはここを参考にさせて頂きました。
 迷路のアルゴリズムなんてこんな機会が無ければ調べたり考えたりする事ないので楽しかったです。

 以下投稿したコード。選択した言語はPHP。「棒倒し法」と呼ばれるアルゴリズムを採用しています。暇を見つけて「穴掘り法」や「壁延ばし法」などでも組んで見たいと思っています。

<?php
function Maze($x, $y)
{
    /* init     */
    $l_array = str_repeat(’1′, $x*2-1+2);
    $s_array = array_fill(0, $x*2-1, ’0′);
    $p_array = str_split(str_repeat(’01′, $x-1).’0′);
    $work = array();
    $work[] = $s_array;
    $work[] = $p_array;
    $work[] = $s_array;

    /* build    */
    $maze = $l_array.”\n”;
    for ($row = 0; $row < $y-1; $row++) {
        for ($col = 0; $col < $x-1; $col++) {
            wall($work, $row, $col);
        }
        $maze .= ’1′.implode(”, array_shift($work)).”1\n”;
        $maze .= ’1′.implode(”, array_shift($work)).”1\n”;
        $work[] = $p_array;
        $work[] = $s_array;
    }
    $maze .= ’1′.implode(”, array_shift($work)).”1\n”;
    $maze .= $l_array.”\n”;
    $maze = strtr($maze, array(’1′=>’■’, ’0′=>’ ’));

    return $maze;
}

function wall(&$work, $row, $col)
{
    $w = array();
    if ($row == 0 && $work[0][$col*2+1] == ’0′) {
        $w[] = array(0, $col*2+1);
    }
    if ($work[1][$col*2+2] == ’0′) {
        $w[] = array(1, $col*2+2);
    }
    if ($work[2][$col*2+1] == ’0′) {
        $w[] = array(2, $col*2+1);
    }
    if ($work[1][$col*2] == ’0′) {
        $w[] = array(1, $col*2);
    }
    shuffle($w);
    $work[$w[0][0]][$w[0][1]] = ’1′;
}
?>

『文字のセンタリング』投稿

 どう書く?orgに投稿。

 お題は文字のセンタリングです。

 文字列を指定のカラム幅にセンタリング配置する関数を示してください。文字列の長さが指定した幅より長い場合には文字列の両端をできるだけ均等に切り落して指定幅に収めてください。1文字は1カラムに収まるものと仮定してかまいません。

 最初、文字列と幅を比較して、幅に収まるようなら前後にスペースをWhileで追加、幅を超えるようなら前後をWhileで切り飛ばしていくという力任せ的なコード書いたんですけど、マニュアル読んだらPHPには本件にうってつけの関数が既に用意されていました。
 str_padは前後にスペース(文字種指定可)を追加するのみでなく、文字列の切り飛ばしも行ってくれるのですが、今回のお題のように「前後から均等に」という仕様ではないのでifで処理分けてます。

 以下投稿したコード。選択した言語はPHP。シンプルでわかりやすいと思う。

<?php
function Centering($str, $width)
{
    $slen = strlen($str);
    if ($slen < $width) {
        $str = str_pad($str, $width, ‘ ‘, STR_PAD_BOTH);
    } else {
        $str = substr($str, (int)(($slen – $width)/2), $width);
    }
    return $str;
}
?>

『与えられた並べ替えを実現するあみだくじの生成』投稿

 どう書く?orgに投稿。

お題は与えられた並べ替えを実現するあみだくじの生成です。

 0からn (n>=1) までの数字を任意の順で並べたリストが与えられた時、0からnまでが順に並んだ状態から出発して、与えられたリストの順で結果が得られるようなあみだくじを作成して出力するプログラムを書いてください。

制約条件

  • あみだの横棒は縦棒をまたぐことはできません。常に隣接する縦棒同士の交換となります 。
  • 同じ行に複数の横棒があっても良いですが、ひとつの縦棒の同じ点からふたつ横棒が出ることはありません。

 最初、ここここを読んで、どうやってロジック組むかと考えたのですが、前回投稿した『あみだくじ』を組んだ際、ソートすれば良い事に気づきました。
 パラメータで渡されるリストの先頭から隣り合う要素同士を比較し、その大小によって要素を入れ替え、これをリスト末端まで試行します。要素入れ替えの発生はあみだくじの横棒になります。これを1ステップとして記録し、ソートが完了するまで繰り返します。
 このソート方法はバブルソートに似ていますが、バブルソートと異なる点は、入れ替えが発生した要素は、そのステップ内ではもう動かしてはいけないという点です。
 ソートが完了したら、記録したソート過程(ステップ)を逆順とし、これをあみだくじのパターンとします。

 以下、投稿したコード。選択した言語はPHP。パラメータとして渡すリストは文字列型にする必要があります。また、お題では数字のリストという事ですが、英数字に対応した関数となっています。

<?php
function CreateAmida($org)
{
    if (!ctype_alnum($org) ||
        count(array_unique(str_split($org))) != count(str_split($org))) {
        return NULL;
    }
    $bridge_num = strlen($org)-1;
    $p = $org;
    $step = array();
    while (1) {
        $chg = FALSE;
        $step_buf = array_fill(0, $bridge_num, ‘ ‘);
        for ($i = 0; $i < $bridge_num; $i++) {
            if ($p[$i] > $p[$i+1]) {
                $sub = array($p[$i]=>$p[$i+1], $p[$i+1]=>$p[$i]);
                $p = strtr($p, $sub);
                $step_buf[$i] = ‘-’;
                $i++;
                $chg = TRUE;
            }
        }
        if ($chg) {
            $step[] = ‘|’.implode(‘|’, $step_buf).’|';
        } else {
            break;
        }
    }
    $res = implode(‘ ‘, str_split($p)).”\n”;
    $res .= implode(“\n”, array_reverse($step)).”\n”;
    $res .= implode(‘ ‘, str_split($org)).”\n”;
    return $res;
}
?>