PHPでカレンダーとか死ぬほどよくありますが、mktime()とか使って手動で作ってるタイプばっかりで、DateTimeを使ったカレンダーが見当たらなかったので作ってみる。
当月や週末の判定が微妙だな。
完全にやるならDatePeriodをくるくるしたときに出てくるDateTimeを上書きしてisPresentMonth()的なメソッドを追加するか、描画系もクラス内で行えるようにしておくとよいでしょう。
ここまで作っておいてなんですが、どうしても外部ライブラリが許されざる状況にあるとかでない限りはPEAR::Calendarとかに任せとけばいいんじゃないかな。
<?php
// かれんだー
class Calendar{
private $datetime;
public function getDatetime(){ return clone $this->datetime; }
/**
* コンストラクタ
* @param int 年
* @param int 月
* @param int 日
*/
public function __construct($year = NULL, $month = NULL, $day = NULL){
// デフォルト
$default = new DateTime();
if($year ===NULL){ $year = $default->format('Y'); }
if($month ===NULL){ $month = $default->format('m'); }
if($day ===NULL){ $day = $default->format('d'); }
// 本日
$str =sprintf('%04d-%02d-%02d', (int)$year, (int)$month, (int)$day);
$this->datetime = DateTime::createFromFormat('Y-m-d', $str, new DateTimeZone('Asia/Tokyo'));
if(!$this->datetime){ throw new InvalidArgumentException(); }
}
/**
* 日曜開始、土曜終了のカレンダーを取得
* @return DatePeriod
*/
public function getCalendar(){
// 開始日 月初を含む週の日曜日
$start = clone $this->datetime;
$start->modify('first day of')->modify('+1 day')->modify('last Sunday');
// 終了日 月末を含む週の土曜の次の日 DatePeriodは最終日が含まれないため+1する
$finish = clone $this->datetime;
$finish->modify('last day of')->modify('-1 day')->modify('next Saturday')->modify('+1 day');
return new DatePeriod($start, new DateInterval('P1D'), $finish);
}
}
// インスタンス
$calendar = new Calendar($_REQUEST['y'], $_REQUEST['m'], $_REQUEST['d']);
// 画面表示
print('<table><tr><th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th></tr><tr>');
foreach($calendar->getCalendar() as $key=>$val){
if($val->format('w') === '0'){
// 日曜日
print('<tr><td>');
}else{
// その他
print('</td><td>');
}
if($val->format('m') === $calendar->getDatetime()->format('m')){
// 当月
print($val->format('d'));
}else{
// 当月ではない
print(' ');
}
if($val->format('w') === '6'){
// 土曜日
print('</td></tr>');
}
}
print('</table>');
2038年問題フリーで、9999年まで使えるカレンダーです。当月や週末の判定が微妙だな。
完全にやるならDatePeriodをくるくるしたときに出てくるDateTimeを上書きしてisPresentMonth()的なメソッドを追加するか、描画系もクラス内で行えるようにしておくとよいでしょう。
ここまで作っておいてなんですが、どうしても外部ライブラリが許されざる状況にあるとかでない限りはPEAR::Calendarとかに任せとけばいいんじゃないかな。
PR
PHP5.3で悪名高いgotoが実装されました。
あえて実装されたということはそれだけ有用でもあるということでしょう。
前作ったフィボナッチ数列をgotoで再現してみましょう。
しかもfib3()並に高速です。
本当は「goto使うのはやめとけ」って書くつもりだったのだがどうしてこうなった。
gotoの本当の恐ろしさ(そして有用さ)は、「あらゆる文脈を無視して強制的にジャンプを行うことができる」という点です。
PHPの場合は同一ファイル内のみ、関数内←→関数外への移動はできないなど一部制限はありますが、それでもその威力は暴力的です。
なおgotoのラベルには値しか使用できないようです。
変数はおろか定数すら指定できません。
まあ、万一これが動いてしまったら更なる地獄になるのは間違いありませんが。
実のところPHPではgotoの使いどころがほぼありません。
他の関数が豊富なので、あえて使おうと思わない限り出番がないんですよね。
他言語では唯一の使いどころとして挙げられる多重ループ脱出についても、PHPでは普通に脱出レベルを設定できます。
いったいどんなときに使えばいいのか、私にはよくわかりません。
あえて実装されたということはそれだけ有用でもあるということでしょう。
前作ったフィボナッチ数列をgotoで再現してみましょう。
<?php
function fib5($n){
$fib= [0, 1];
$count = 1;
loop:
$count++;
$fib[$count] = $fib[$count-1] + $fib[$count-2];
if(!isset($fib[$n])){ goto loop; }
return $fib[$n];
}
あれ、予想外にわかりやすい。しかもfib3()並に高速です。
本当は「goto使うのはやめとけ」って書くつもりだったのだがどうしてこうなった。
gotoの本当の恐ろしさ(そして有用さ)は、「あらゆる文脈を無視して強制的にジャンプを行うことができる」という点です。
PHPの場合は同一ファイル内のみ、関数内←→関数外への移動はできないなど一部制限はありますが、それでもその威力は暴力的です。
<?php
// http://www.php.net/manual/ja/control-structures.goto.php#109027
$link = true;
if($link)goto iw_link_begin;
iw__link_begin:
if($link)goto iw_link_text;
iw__link_text:
if($link)goto iw_link_end;
iw__link_end:
goto iw_end_gt;
iw_link_begin:
echo'<a href="#">';
goto iw__link_begin;
iw_link_text:
echo'SampleText';
goto iw__link_text;
iw_link_end:
echo'</a>';
goto iw__link_end;
iw_end_gt:
// 普通に書くとこう
if($link)iw_link_begin();
if($link)iw_link_text();
if($link)iw_link_end();
function iw_link_begin(){
echo'<a href="#">';
}
function iw_link_text(){
echo'SampleText';
}
function iw_link_end(){
echo'</a>';
}
上記はマニュアルのコメントに書かれている例ですが、こんなもん納品されてきた日には実装者をぶん殴るしかない。なおgotoのラベルには値しか使用できないようです。
変数はおろか定数すら指定できません。
<?php $a = 'label1'; goto $a; label1:みたいなコードはパースエラーになります。
まあ、万一これが動いてしまったら更なる地獄になるのは間違いありませんが。
実のところPHPではgotoの使いどころがほぼありません。
他の関数が豊富なので、あえて使おうと思わない限り出番がないんですよね。
他言語では唯一の使いどころとして挙げられる多重ループ脱出についても、PHPでは普通に脱出レベルを設定できます。
いったいどんなときに使えばいいのか、私にはよくわかりません。
http://qiita.com/Nabetani/items/cba03c96d1ea55f6e861
http://nabetani.sakura.ne.jp/hena/ord15elebubo/
異星の電光掲示板。
解き方自体は前やったエントロピー符号と同じです。
しかし今回は、単純に「00」を詰めると「110111101110」みたいな一意にならない値が出てしまうので注意が必要です。
と思ったけど別に注意するようなことは全くなかった。
preg_replace()とかでまとめてできないかと思ったけど無理だった。
かかった時間は45分くらい。
ところでBUBOって何ですかね。
http://nabetani.sakura.ne.jp/hena/ord15elebubo/
異星の電光掲示板。
解き方自体は前やったエントロピー符号と同じです。
しかし今回は、単純に「00」を詰めると「110111101110」みたいな一意にならない値が出てしまうので注意が必要です。
と思ったけど別に注意するようなことは全くなかった。
<?php
class ELEBUBO{
/**
* 異星の電光掲示板
* @param String 「2ed8aeed/34b0ea5b」みたいな文字列
* @return String 「LTRSUNTSJ」みたいな文字列
*/
public function get($input){
// 入力を2進数に
$input =explode('/', $input);
$upper = sprintf('%032s', base_convert($input[0], 16, 2));
$under = sprintf('%032s', base_convert($input[1], 16, 2));
// 一列にする
$string = '';
for($key=0;$key<strlen($upper); $key++){
$string .= $upper[$key] . $under[$key];
}
// 置換
$search = ['00', '101110', '110111', '111011', '011110', '101101', '1101', '1110', '0111'];
$replace = ['', 'T', 'U', 'N', 'S', 'Z', 'L', 'R', 'J'];
$ret = '';
do{
foreach($search as $key=>$val){
if(strpos($string, $val) === 0){
$string = substr($string, strlen($val));
$ret .= $replace[$key];
continue 2;
}
}
}while(strlen($string));
return $ret;
}
}
// 以下はテスト
$test = [
['2ed8aeed/34b0ea5b', 'LTRSUNTSJ'],
['00000200/00000300', 'L'],
['00018000/00010000', 'R'],
['00002000/00006000', 'J'],
['00000700/00000200', 'T'],
['01400000/01c00000', 'U'],
['00003800/00002800', 'N'],
['000c0000/00180000', 'S'],
['00003000/00001800', 'Z'],
['132eae6c/1a64eac6', 'LRJTUNSZ'],
['637572d0/36572698', 'ZSNUTJRL'],
['baddb607/d66b6c05', 'LTJZTSSSN'],
['db74cd75/6dac6b57', 'ZZZTJZRJNU'],
['3606c2e8/1b0d8358', 'ZZSSLTJ'],
['ad98c306/e6cc6183', 'UZZZZZZ'],
['4a4aaee3/db6eeaa6', 'JJLLUUNNS'],
['ecd9bbb6/598cd124', 'TSSZZTTRR'],
['e0000002/40000003', 'TL'],
['a0000007/e0000005', 'UN'],
['c0000003/80000006', 'RS'],
['40000006/c0000003', 'JZ'],
['01da94db/00b3b6b2', 'TSUJLRSR'],
['76eeaaea/24aaeeae', 'TRNNUUNU'],
['1dacaeee/1566e444', 'NRJZUTTT'],
['26c9ac60/6c6d66c0', 'JSZLRJZS'],
['6c977620/36da5360', 'ZZLLTNZJ'],
['069aeae6/0db34eac', 'SJSLTUNS'],
['06d53724/049da56c', 'RRULRNJJ'],
['069b58b0/04d66da0', 'RLRSLZJR'],
['1b6eced4/11b46a9c', 'RZZTZNRU'],
['522e8b80/db6ad900', 'JLLJNLJT'],
['6546cdd0/376c6898', 'ZULSZRTL'],
['4e6d5b70/6ad9d620', 'LNSSURST'],
['37367772/65635256', 'SNSZNTNJ'],
['25535d58/377669cc', 'LUUSLTUZ'],
['0ae6a55d/0eacedcb', 'UNSUJUTJ'],
['76762edc/23536a88', 'TZNZJNRT'],
/**/
];
$elebubo = new ELEBUBO();
foreach($test as $key=>$data){
$answer = $elebubo->get($data[0]);
if($answer !== $data[1]){
print('えらー');
}
}
うーん置換のあたりが微妙。preg_replace()とかでまとめてできないかと思ったけど無理だった。
かかった時間は45分くらい。
ところでBUBOって何ですかね。
http://qiita.com/Nabetani/items/0597bd3af481e5834ae1
http://nabetani.sakura.ne.jp/hena/ord14linedung/
眠れるモンスターを狩ります。
武器AでモンスターBを狩れる、モンスターBは武器Cを落とす、武器CはモンスターDを狩れる、という連鎖です。
単純に、手持ちの武器でモンスターを狩って、その戦利品で次のモンスターを狩って、を繰り返しただけです。
ArrayIteratorは、反復処理中に値の変更が可能という便利な配列です。
ここが普通の配列だとaddしたループ中は参照してくれません。
かかった時間は1時間くらい。
最初上で書いたとおり普通の配列でやろうとして動かなかった。
あとモンスターと武器の文字が順に並んでるので、ビット演算とかで解けないかと思ったがさっぱりわからなかった。
「オフラインリアルタイムどう書く」の一覧
http://nabetani.sakura.ne.jp/hena/ord14linedung/
眠れるモンスターを狩ります。
武器AでモンスターBを狩れる、モンスターBは武器Cを落とす、武器CはモンスターDを狩れる、という連鎖です。
<?php
class MONSTER{
// 武器で狩れるモンスターと落とす武器
private $list = [
'a' => 'Bc',
'c' => 'De',
'e' => 'Fg',
'g' => 'Hi',
'i' => 'Jk',
'k' => 'La',
];
/**
* 狩ったモンスターの数を返す
* @param String 「gLDLBgBgHDaD」みたいな文字列
* @return int 「6」みたいな数値
*/
public function get($input){
// 初期値
$weapons = new ArrayIterator();
$monsters = [];
$ret = 0;
// 入力値を整形
foreach(count_chars($input, 1) as $key=>$val){
// 小文字は武器、大文字はモンスター
if($key < 97){
$monsters[chr($key)] = $val;
}else{
$weapons[chr($key)] = $val;
}
}
// 武器でくるくる
foreach($weapons as $weapon=>$val){
// その武器で狩れるモンスターがいれば
if(isset($monsters[$this->list[$weapon][0]])){
// 狩る
$ret += $monsters[$this->list[$weapon][0]];
// 落とした武器を入手
$weapons[$this->list[$weapon][1]] = 1;
}
}
return $ret;
}
}
// 以下はテスト
$test = [
['gLDLBgBgHDaD', '6'],
['DBcDLaLgDBH', '6'],
['JJca', '0'],
['FJDLBH', '0'],
['HJBLFDg', '6'],
['HBaDLFJ', '6'],
['DJaHLB', '2'],
['gDLHJF', '3'],
['cJFgLHD', '5'],
['FFBJaJJ', '1'],
['FJeJFBJ', '2'],
['iJFFJJB', '3'],
['JBJiLFJF', '5'],
['JDiFLFBJJ', '8'],
['BDFDFFDFFLLFFJFDBFDFFFFDDFaDBFFB', '28'],
['DDFBFcBDFFFFFFLBFDFFBFLFDFDJDFDF', '24'],
['FDLBFDDBFFFeFFFFFDFBLDDFDDFBFFJF', '16'],
['FDBFFLFDFFDBBDFFBJDLFgDFFFDFFDFF', '0'],
['FDiFLDFFFFBDDJDDBFBFDFFFBFFDFLFF', '31'],
['FDFDJBLBLBFFDDFFFDFFFFFDDFBkFDFF', '30'],
['HBkFFFFHBLH', '3'],
['FBHHFFFHLaB', '2'],
['LFHFBBcHFHF', '0'],
['LFBHFFeFHBH', '7'],
['LgFHHHBFBFF', '3'],
['FFiFHBHLBFH', '0'],
['BFHHFFHBeFLk', '10'],
['FHFaBBHFHLFg', '5'],
['FFgacaFg', '0'],
['JHDaDcBJiiHccBHDBDH', '9'],
['FHJJLckFckFJHDFF', '12'],
['DeDHJHDFHJBLHDLLDHJLBDD', '22'],
['gJLLLJgJgJLJL', '0'],
['DaaaDDD', '0'],
['HFeJFHiBiiBJeJBBFFB', '9'],
['FJFFJDBHBHaLJBHJHDLHkLLLFFFgJgHJLHkJkB', '32'],
['giFLBiBJLLJgHBFJigJJJBLHFLDLL', '23'],
['cgkLJcLJJJJgJc', '2'],
['LDFHJHcFBDBLJBLFLcFJcDFBL', '22'],
['JJHHHkHJkHLJk', '1'],
['kHHBBaBgHagHgaHBBB', '11'],
['HDBFFDHHHDFLDcHHLFDcJD', '20'],
['HFFFHeFFee', '7'],
['gLLDHgDLgFL', '1'],
['JJJBBaBBHBBHaLBHJ', '7'],
['FBFBgJBDBDgF', '0'],
['LLLLakakLakLL', '7'],
['HeJHeJe', '0'],
['LDFLBLLeBLDBBFFBLFBB', '4'],
];
$monster = new MONSTER();
foreach($test as $key=>$data){
$answer = $monster->get($data[0]);
if($answer !== (int)$data[1]){
print('えらー');
}
}
単純に、手持ちの武器でモンスターを狩って、その戦利品で次のモンスターを狩って、を繰り返しただけです。
ArrayIteratorは、反復処理中に値の変更が可能という便利な配列です。
ここが普通の配列だとaddしたループ中は参照してくれません。
かかった時間は1時間くらい。
最初上で書いたとおり普通の配列でやろうとして動かなかった。
あとモンスターと武器の文字が順に並んでるので、ビット演算とかで解けないかと思ったがさっぱりわからなかった。
「オフラインリアルタイムどう書く」の一覧
http://d.hatena.ne.jp/palu0707/20131030/1383143532
とりあえずgetDay()を実行してみる。
Notice: Undefined variable: lenght in C:\xampp\test.php on line 33
Notice: Undefined offset: 6 in C:\xampp\test.php on line 50
Notice: Undefined offset: 5 in C:\xampp\test.php on line 50
Notice: Undefined offset: 4 in C:\xampp\test.php on line 50
Notice: Undefined offset: 3 in C:\xampp\test.php on line 50
Notice: Undefined offset: 2 in C:\xampp\test.php on line 50
Notice: Undefined offset: 1 in C:\xampp\test.php on line 50
これを実行したのは2013/11/06。
月またぎの処理に異常があるようです。
修正しましょう。
というか、こういう処理はビルトインに任せるべきで、わざわざ自力でやる意味は全くありません。
閏年なんてこちら側では一切考慮する必要はなく、DateTimeがよしなに処理してくれます。
返り値はDatePeriodなので、返ってきた側での使い方も非常に簡単です。
とりあえずgetDay()を実行してみる。
Notice: Undefined variable: lenght in C:\xampp\test.php on line 33
Notice: Undefined offset: 6 in C:\xampp\test.php on line 50
Notice: Undefined offset: 5 in C:\xampp\test.php on line 50
Notice: Undefined offset: 4 in C:\xampp\test.php on line 50
Notice: Undefined offset: 3 in C:\xampp\test.php on line 50
Notice: Undefined offset: 2 in C:\xampp\test.php on line 50
Notice: Undefined offset: 1 in C:\xampp\test.php on line 50
array(3) {
["year"]=>
string(4) "2013"
["month"]=>
array(2) {
[0]=>
int(10)
[1]=>
string(2) "11"
}
["day"]=>
array(7) {
[0]=>
int(6)
[6]=>
int(31)
[5]=>
int(31)
[4]=>
int(31)
[3]=>
int(31)
[2]=>
int(31)
[1]=>
int(31)
}
}
line 50はforの行です。これを実行したのは2013/11/06。
月またぎの処理に異常があるようです。
修正しましょう。
というか、こういう処理はビルトインに任せるべきで、わざわざ自力でやる意味は全くありません。
<?php
function getDay($year = NULL, $month = NULL, $day = NULL, $length = NULL) {
if(!$year) {$year = date('Y');}
if(!$month) {$month = date('m');}
if(!$day) {$day = date('d');}
if(!$length){$length = 6;}
// 終了日
$end = new DateTime($year.'-'.$month.'-'.$day, new DateTimeZone('Asia/Tokyo'));
// 開始日
$start = clone $end;
$start->modify($length . ' days ago');
// DatePeriodにして返す
return new DatePeriod($start, new DateInterval('P1D'), $end);
}
// 使い方
$datePeriod = getDay();
foreach($datePeriod as $key=>$val){
print(($key+1) . '日目:' . $val->format('Y年m月d日'));
}
跡形が無くなってしまった。閏年なんてこちら側では一切考慮する必要はなく、DateTimeがよしなに処理してくれます。
返り値はDatePeriodなので、返ってきた側での使い方も非常に簡単です。
http://qiita.com/Nabetani/items/cbc3af152ee3f50a822f
ポーカーの役を求めます。
集計する対象はワンペア、ツーペア、スリーカード、フォーカード、フルハウス。
つまりスートは一切無視してよいということです。
これまでで一番簡単だった気がします。
かかった時間は20分程度。
「オフラインリアルタイムどう書く」の一覧
ポーカーの役を求めます。
集計する対象はワンペア、ツーペア、スリーカード、フォーカード、フルハウス。
つまりスートは一切無視してよいということです。
<?php
class POKER{
// 役
private $roles = [
'4K'=>[4, 1],
'FH'=>[3, 2],
'3K'=>[3, 1, 1],
'2P'=>[2, 2, 1],
'1P'=>[2, 1, 1, 1],
];
/**
* ポーカー
* @param String 「D3C3C10D10S3」みたいな文字列
* @return String 「FH」みたいな文字列
*/
public function get($input){
// 値をカウント
$cards = array_count_values(explode('-', trim( str_replace(['S', 'H', 'D', 'C'], '-', $input), '-')));
rsort($cards);
// 同じ役があるか確認
foreach($this->roles as $key=>$val){
if($cards === $val){
return $key;
}
}
// なかった
return '--';
}
}
// テスト
$test = [
['D3C3C10D10S3', 'FH'],
['S8D10HJS10CJ', '2P'],
['DASAD10CAHA', '4K'],
['S10HJDJCJSJ', '4K'],
['S10HAD10DAC10', 'FH'],
['HJDJC3SJS3', 'FH'],
['S3S4H3D3DA', '3K'],
['S2HADKCKSK', '3K'],
['SASJDACJS10', '2P'],
['S2S10H10HKD2', '2P'],
['CKH10D10H3HJ', '1P'],
['C3D3S10SKS2', '1P'],
['S3SJDAC10SQ', '--'],
['C3C9SAS10D2', '--'],
];
$poker = new POKER();
foreach($test as $key=>$data){
$answer = $poker->get($data[0]);
if($answer !== $data[1]){
print('えらー');
}
}
数字ごとの枚数に一切ぶれがないため、===で簡単にマッチング可能です。これまでで一番簡単だった気がします。
かかった時間は20分程度。
「オフラインリアルタイムどう書く」の一覧
http://nabetani.sakura.ne.jp/hena/1/
三目並べの勝敗を決定します。
勝利パターンは8種類しかないので別に正規表現使わなくても十分だったりしますがまあいいや。
ちなみに「o..o..o」が縦、「^(...){0,2}ooo」が横、「o...o...o」「..o.o.o..」が斜めです。
まあ見ればわかるか。
「オフラインリアルタイムどう書く」の一覧
三目並べの勝敗を決定します。
<?php
class TICKTACKTOE{
// 勝利パターン
private $pattern = [
'/o..o..o|^(...){0,2}ooo|o...o...o|..o.o.o../',
'/x..x..x|^(...){0,2}xxx|x...x...x|..x.x.x../'
];
// プレイヤー
private $player = ['o', 'x'];
/**
* 三目並べ
* @param String 「79538246」みたいな文字列
* @return String 「x won.」みたいな文字列
*/
public function get($input){
// 9文字で打ち切り
$input = substr($input, 0, 9);
// 初期化
$tick = '---------';
for($i=0; $i<strlen($input); $i++){
// 既に入っていたら負け
if($tick[$input[$i]-1] !== '-'){
return 'Foul : '.$this->player[($i+1)%2].' won.';
}
// 該当値をセット
$tick[$input[$i]-1] = $this->player[$i%2];
// 勝っていれば終了
if(preg_match($this->pattern[$i%2], $tick)){
return $this->player[$i%2].' won.';
}
}
// 引き分け
return 'Draw game.';
}
}
// テスト
$test = [
['79538246', 'x won.'],
['35497162193', 'x won.'],
['61978543', 'x won.'],
['254961323121', 'x won.'],
['6134278187', 'x won.'],
['4319581', 'Foul : x won.'],
['9625663381', 'Foul : x won.'],
['7975662', 'Foul : x won.'],
['2368799597', 'Foul : x won.'],
['18652368566', 'Foul : x won.'],
['965715', 'o won.'],
['38745796', 'o won.'],
['371929', 'o won.'],
['758698769', 'o won.'],
['42683953', 'o won.'],
['618843927', 'Foul : o won.'],
['36535224', 'Foul : o won.'],
['882973', 'Foul : o won.'],
['653675681', 'Foul : o won.'],
['9729934662', 'Foul : o won.'],
['972651483927', 'Draw game.'],
['5439126787', 'Draw game.'],
['142583697', 'Draw game.'],
['42198637563', 'Draw game.'],
['657391482', 'Draw game.'],
];
$ticktacktoe = new TICKTACKTOE();
foreach($test as $key=>$data){
$answer = $ticktacktoe->get($data[0]);
if($answer !== $data[1]){
print('えらー');
}
}
なんの変哲もなく、普通に正規表現で勝利パターンを引っかけてるだけです。勝利パターンは8種類しかないので別に正規表現使わなくても十分だったりしますがまあいいや。
ちなみに「o..o..o」が縦、「^(...){0,2}ooo」が横、「o...o...o」「..o.o.o..」が斜めです。
まあ見ればわかるか。
「オフラインリアルタイムどう書く」の一覧
http://qiita.com/Nabetani/items/9d80de41903775296ca6
画像を回転させる問題です。
絶対に誰も真似しない方法で回答。
もちろん、このような回りくどいことをする必要性は皆無です。
単にやってみたかっただけという。
なおbase_convert()のあたりがややこしいのは、16桁以上の16進数をbase_convert()に突っ込むと正しくない値が返ってきてしまうせいです。
そのせいで最後の2サンプルだけ正しく動かなかったという。
「オフラインリアルタイムどう書く」の一覧
画像を回転させる問題です。
絶対に誰も真似しない方法で回答。
<?php
class ROTATE{
/**
* 画像を回転させる
* @param String 「3:5b8」みたいな文字列
* @return String 「3:de0」みたいな文字列
*/
public function get($input){
// 入力を2進数に
list($size, $hex) = explode(':', $input);
$bit = '';
$tmp = str_split($hex, 4);
foreach($tmp as $key=>$val){
$bit .= sprintf('%0'.(strlen($val)*4).'s', base_convert($val, 16, 2));
}
// 指定サイズの黒画像を作成
$image = imagecreatetruecolor($size, $size);
$dot = imagecolorallocate($image, 0, 0, 1);
// 1のビットに点を打つ
for($y=0; $y<$size; $y++){
for($x=0; $x<$size; $x++){
if($bit[$x+$y*$size]){
imagesetpixel($image, $x, $y, $dot);
}
}
}
// 画像を回転
$image = imagerotate($image, 270, 0);
// 色を取得
$rot = '';
for($y=0; $y<$size; $y++){
for($x=0; $x<$size; $x++){
$rot .= imagecolorat($image, $x, $y);
}
}
imagedestroy($image);
// 16進数にして戻す
$rot = str_pad($rot, (strlen($bit)), '0', STR_PAD_RIGHT);
$ret = '';
$tmp = str_split($rot, 16);
foreach($tmp as $key=>$val){
$ret .= sprintf('%0'.(strlen($val)/4).'s', base_convert($val, 2, 16));
}
return $size . ':' . $ret;
}
}
// テスト
$test = [
['3:5b8', '3:de0'],
['1:8', '1:8'],
['2:8', '2:4'],
['2:4', '2:1'],
['2:1', '2:2'],
['3:5d0', '3:5d0'],
['4:1234', '4:0865'],
['5:22a2a20', '5:22a2a20'],
['5:1234567', '5:25b0540'],
['6:123456789', '6:09cc196a6'],
['7:123456789abcd', '7:f1a206734b258'],
['7:fffffffffffff', '7:ffffffffffff8'],
['7:fdfbf7efdfbf0', '7:ffffffffffc00'],
['8:123456789abcdef1', '8:f0ccaaff78665580'],
['9:112233445566778899aab', '9:b23da9011d22daf005d40'],
];
$rotate = new ROTATE();
foreach($test as $key=>$data){
$answer = $rotate->get($data[0]);
if($answer !== $data[1]){
print('えらー');
}
}
実際に画像を作って回転させました。もちろん、このような回りくどいことをする必要性は皆無です。
単にやってみたかっただけという。
なおbase_convert()のあたりがややこしいのは、16桁以上の16進数をbase_convert()に突っ込むと正しくない値が返ってきてしまうせいです。
そのせいで最後の2サンプルだけ正しく動かなかったという。
「オフラインリアルタイムどう書く」の一覧
http://nabetani.sakura.ne.jp/hena/ord2/
配置済のテトリスです。
横に揃った行を削除して、消した結果を出力します。
何回ループ回してんだよ。
見たかんじビット演算使えば即座に解けるような内容だと思うんですよね。
しかし私はビット演算が苦手(というかまともに勉強したことがない)ので、入力を横に切って全部1だったら消すという超絶力業での回答です。
いやはや酷いもんだ。
かかった時間は1時間くらい。
「オフラインリアルタイムどう書く」の一覧
配置済のテトリスです。
横に揃った行を削除して、消した結果を出力します。
<?php
class TETRIS{
/**
* テトリス
* @param String 「ff-2f-23-f3-77-7f-3b」みたいな文字列
* @return String 「1f-03-00-1c-0d-0f-06」みたいな文字列
*/
public function get($input){
// 入力
$input = explode('-', $input);
$arr = array_fill(0, 8, '');
$arr2 = array_fill(0, count($input), '');
$ret = '';
// 横向きに切る
foreach($input as $key=>$val){
$tmp = sprintf('%08s', base_convert($val, 16, 2));
for($i=0; $i<8; $i++){
$arr[$i] .= $tmp[$i];
}
}
// 揃ってるところは消えて落ちる
foreach($arr as $key=>$val){
if(strpos($val, '0')=== false){
unset($arr[$key]);
array_unshift($arr, str_repeat('0', strlen($val)));
}
}
// 縦に戻す
foreach($arr as $key=>$val){
for($i=0; $i<strlen($val); $i++){
$arr2[$i] .= $val[$i];
}
}
// 文字列にして戻す
foreach($arr2 as $key=>$val){
$ret .= '-' . sprintf('%02s', base_convert($val, 2, 16));
}
return substr($ret, 1);
}
}
// テスト
$test = [
['ff-2f-23-f3-77-7f-3b', '1f-03-00-1c-0d-0f-06'],
['01', '00'],
['00', '00'],
['7a-4e', '0c-02'],
['56-b6', '08-14'],
['12-12-12', '00-00-00'],
['de-ff-7b', '0a-0f-05'],
['95-be-d0', '05-1e-20'],
['7c-b0-bb', '1c-20-2b'],
['7a-b6-31-6a', '3a-56-11-2a'],
['32-0e-23-82', '18-06-11-40'],
['ff-7f-bf-df-ef', '0f-07-0b-0d-0e'],
['75-df-dc-6e-42', '35-5f-5c-2e-02'],
['62-51-ef-c7-f8', '22-11-6f-47-78'],
['0c-47-8e-dd-5d-17', '04-23-46-6d-2d-0b'],
['aa-58-5b-6d-9f-1f', '52-28-2b-35-4f-0f'],
['ff-55-d5-75-5d-57', '0f-00-08-04-02-01'],
['fe-fd-fb-f7-ef-df-bf', '7e-7d-7b-77-6f-5f-3f'],
['fd-fb-f7-ef-df-bf-7f', '7e-7d-7b-77-6f-5f-3f'],
['d9-15-b5-d7-1b-9f-de', '69-05-55-67-0b-4f-6e'],
['38-15-fd-50-10-96-ba', '18-05-7d-20-00-46-5a'],
['fe-fd-fb-f7-ef-df-bf-7f', 'fe-fd-fb-f7-ef-df-bf-7f'],
];
$tetris = new TETRIS();
foreach($test as $key=>$data){
$answer = $tetris->get($data[0]);
if($answer !== $data[1]){
print('えらー');
}
}
言いたいことはわかる。何回ループ回してんだよ。
見たかんじビット演算使えば即座に解けるような内容だと思うんですよね。
しかし私はビット演算が苦手(というかまともに勉強したことがない)ので、入力を横に切って全部1だったら消すという超絶力業での回答です。
いやはや酷いもんだ。
かかった時間は1時間くらい。
「オフラインリアルタイムどう書く」の一覧
http://qiita.com/Nabetani/items/ebd8a56b41711ba459f9
野球のスコアカウントを行います。
得点やランナー等の無い超簡易版です。
ひっかかるところが何一つ無かった。
やろうと思えば全サブルーチンを1行で実装可能ですが、そこまで削る必要もないでしょう。
「オフラインリアルタイムどう書く」の一覧
野球のスコアカウントを行います。
得点やランナー等の無い超簡易版です。
<?php
class BASEBALL{
/**
* 野球のスコアカウント
* @param String 「ssbbbb」みたいな文字列
* @return String 「010,020,021,022,023,000」みたいな文字列
*/
public function get($input){
$baseball = [[0, 0, 0]];
// すすめる
for($i=0; $i<strlen($input); $i++){
$baseball[] = $this->{'get'.strtoupper($input[$i])}(end($baseball));
}
// 文字列にして返す
array_shift($baseball);
$ret = '';
foreach($baseball as $val){
$ret .= ','.implode('',$val);
}
return substr($ret, 1);
}
// ストライク
private function getS($input){
// ストライク
if(++$input[1] >= 3){
$input[1] = 0;
++$input[0];
// アウト
if($input[0] >=3){
$input = [0, 0, 0];
}
}
return $input;
}
// ボール
private function getB($input){
if(++$input[2] >= 4){
$input[1] = $input[2] = 0;
}
return $input;
}
// ファウル
private function getF($input){
if($input[1] < 2){
$input[1]++;
}
return $input;
}
// ヒット
private function getH($input){
$input[1] = $input[2] = 0;
return $input;
}
// ピッチャーフライ
private function getP($input){
$input[1] = $input[2] = 0;
// アウト
if(++$input[0] >= 3){
$input[0] = 0;
}
return $input;
}
}
// テスト
$test = [
['s', '010'],
['sss', '010,020,100'],
['bbbb', '001,002,003,000'],
['ssbbbb', '010,020,021,022,023,000'],
['hsbhfhbh', '000,010,011,000,010,000,001,000'],
['psbpfpbp', '100,110,111,200,210,000,001,100'],
['ppp', '100,200,000'],
['ffffs', '010,020,020,020,100'],
['ssspfffs', '010,020,100,200,210,220,220,000'],
['bbbsfbppp', '001,002,003,013,023,000,100,200,000'],
['sssbbbbsbhsbppp', '010,020,100,101,102,103,100,110,111,100,110,111,200,000,100'],
['ssffpffssp', '010,020,020,020,100,110,120,200,210,000']
];
$baseball = new BASEBALL();
foreach($test as $key=>$data){
$answer = $baseball->get($data[0]);
if($answer !== $data[1]){
print('えらー');
}
}
30分かからずで実装完了。ひっかかるところが何一つ無かった。
やろうと思えば全サブルーチンを1行で実装可能ですが、そこまで削る必要もないでしょう。
「オフラインリアルタイムどう書く」の一覧