忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2024/11/24 05:43 |
PHP5.6.0 「第20回オフラインリアルタイムどう書くの問題」をPHPで解く
http://qiita.com/Nabetani/items/5791f8ae1bb5d069a49b
http://nabetani.sakura.ne.jp/hena/ord20meetime/

会議に都合のいい時間を探します。
<?php
	class MEETING{
		/**
		* ミーティングの時間
		* @param String 「A1000-1130,B1230-1800,Z0800-2200」みたいな文字列
		* @return String 「1130-1230」みたいな文字列
		*/
		public function get($input){
			// 初期値
			$all1 = str_repeat('1', 480);
			$freetime = ['A'=>$all1, 'B'=>$all1, 'I'=>$all1, 'J'=>$all1, 'Z'=>$all1];
			$starttime = mktime(10, 0, 0);
			
			// 入力値を整形
			$input = explode(',', $input);
			
			// 都合の悪い時間帯は0にする
			foreach($input as $val){
				$start = (mktime(substr($val, 1, 2), substr($val, 3, 2), 0) - $starttime)/60;
				$end   = (mktime(substr($val, 6, 2), substr($val, 8, 2), 0) - $starttime)/60;
				if($start < 0){ $start = 0; }elseif($start>480){ $start=480; }
				if($end < 0){ $end = 0; }elseif($end>480){ $end=480; }
				for($i=$start; $i<$end; $i++){
					$freetime[$val[0]][$i] = 0;
				}
			}
			
			// GMPにする
			foreach($freetime as $key=>$val){
				$freetime[$key] = gmp_init($val, 2);
				// Zのみビット反転
				if($key==='Z'){
					$freetime[$key] = gmp_xor($freetime[$key], gmp_init($all1, 2));
				}
			}
			
			// 全員'1'が60回続く箇所を見つける
				// ABIZで一番早い時間
				$andi = sprintf('%0480s', gmp_strval(gmp_and(
					gmp_and($freetime['A'], $freetime['B']),
					gmp_and($freetime['I'], $freetime['Z']) ), 2));
				$starti = strpos($andi, str_repeat('1', 60));
				// ABJZで一番早い時間
				$andj = sprintf('%0480s', gmp_strval(gmp_and(
					gmp_and($freetime['A'], $freetime['B']),
					gmp_and($freetime['J'], $freetime['Z']) ), 2));
				$startj = strpos($andj, str_repeat('1', 60));
				// どっちも無ければ解なし
				if($starti === false && $startj === false){ return '-'; }
			
			// 整形して返却
				$start = $starti===false ? $startj : ( $startj===false ? $starti : min($starti, $startj));
				$return date('Hi', $starttime + $start*60) . '-' . date('Hi', $starttime + $start*60+3600);
		}
		
	}
	
	// 以下はテスト
	$test = [
		['A1050-1130,B1400-1415,I1000-1400,I1600-1800,J1100-1745,Z1400-1421,Z1425-1800', '1425-1525'],
		['A1000-1200,B1300-1800,Z1000-1215,Z1230-1800', '-'],
		/* 省略 */
	];

	$meeting = new MEETING();
	foreach($test as $key=>$data){
		$answer = $meeting->get($data[0]);
		if($answer !== $data[1]){
			print('えらー');
		}
	}

暇な時間は1、用事があれば0を入れたビット列を作り、1が60回続くところを探しています。
発想は簡単ですが、文字列に対して論理演算を使うと想定外の結果になるのでビット操作が面倒なことになっていたり、日付を文字列にするところが妙にややこしかったり、あと最後の三項演算子は絶対もっと簡単な書き方があるだろ。

なんともすっきりしない解答。
時間も無駄にかかっていて3時間くらい。
何故か日時をDateTimeにしようとしたり文字列のまま処理しようとしたりで大混乱。
PR


2014/05/23 23:21 | Comments(0) | PHP

コメント

コメントを投稿する






Vodafone絵文字 i-mode絵文字 Ezweb絵文字 (絵文字)



<<買ったものリスト 2014/05/25 | HOME | PHP5.6.0 「第21回オフラインリアルタイムどう書くの参考問題」をPHPで解く>>
忍者ブログ[PR]