3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

「第20回オフラインリアルタイムどう書くの問題」をPHPで解く

Posted at

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にしようとしたり文字列のまま処理しようとしたりで大混乱。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?