2
2

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.

POH6 漫画版: 女子高生プログラマーの大バトル!〜コボール文明の逆襲〜 六村リオ

Last updated at Posted at 2015-09-03

六村リオ / 霧島京子 / 緑川つばめ / 島根ルミ / 島根ルミ149 / 島根ルミ121 / 共通解

https://paiza.jp/poh/joshibato
色々混ざりすぎだろ。

コーヒーの濃さを求める問題

<?php
	// インプット
	$f = file('php://stdin', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
	// 1行目は不要
	unset($f[0]);
	
	// 初期化
	$oyu = $coffee = 0;
	
	// くるくる
	foreach($f as $v){
		$v=explode(' ', $v, 2);
		if($v[0]==="1"){ // お湯
			$oyu += $v[1];
		}elseif($v[0]==="2"){ // コーヒー
			$coffee += $v[1];
		}else{ // 飲んだ
			$oyu -= ($v[1]*$oyu) / ($oyu+$coffee);
			$coffee -= ($v[1]*$coffee) / ($oyu+$coffee);
		}
	}
	
	// 濃度
	echo intval(100*$coffee/($oyu+$coffee));

https://paiza.jp/poh/joshibato/rio/result/a0b8757d
どう見ても合ってるはずなんだが、何故かテストケース5が誤答になる。
なんで??
誤差か?誤差のせいなのか?

<?php
	// インプット
	$f = file('php://stdin', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
	// 1行目は不要
	unset($f[0]);
	
	// 初期化
	$oyu = $cof = "0";
	bcscale(64);
	
	// くるくる
	foreach($f as $v){
		$v=explode(' ', $v, 2);
		if(!$v[1]){continue;}
		
		if($v[0]==="1"){ // お湯
			$oyu = bcadd($oyu, $v[1]);
		}elseif($v[0]==="2"){ // コーヒー
			$cof = bcadd($cof, $v[1]);
		}else{ // 飲んだ
			$oyu = bcsub($oyu, bcdiv(bcmul($v[1], $oyu), bcadd($oyu, $cof)));
			$cof = bcsub($cof, bcdiv(bcmul($v[1], $cof), bcadd($oyu, $cof)));
		}
	}
	
	// 濃度
	echo (int)bcdiv(bcmul($cof, "100"), bcadd($oyu, $cof));

https://paiza.jp/poh/joshibato/rio/result/540f6b4c
やはり駄目だった。
どうも誤差のせいではないようだ。
なおGMP関数は使えなかった。

と、ここまで書いたところでようやく大ポカに気付く。

<?php
	// インプット
	$f = file('php://stdin', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
	// 1行目は不要
	unset($f[0]);
	
	// 初期化
	$oyu = $coffee = 0;
	
	// くるくる
	foreach($f as $v){
		$v=explode(' ', $v, 2);
		if($v[0]==="1"){ // お湯
			$oyu += $v[1];
		}elseif($v[0]==="2"){ // コーヒー
			$coffee += $v[1];
		}else{ // 飲んだ
			$tmp = $oyu - ($v[1]*$oyu) / ($oyu+$coffee);
			$coffee -= ($v[1]*$coffee) / ($oyu+$coffee);
			$oyu = $tmp;
		}
	}
	
	// 濃度
	echo intval(100*$coffee/($oyu+$coffee));

https://paiza.jp/poh/joshibato/rio/result/80a1508f
飲んだ時に$oyuを上書きしてしまったため、$coffeeの計算がおかしくなっていただけだった。
これは恥ずかしい。

PHPでは複数の計算を副作用なしに同時に行う術はないはずなので、一時変数を使って回避。
list($a, $b) = ($a+$b, $a-$b);
UPDATE table SET 主キー = CASE WHEN 主キー=1 THEN 2 WHEN 主キー=2 THEN 1 ELSE 主キー END;
みたいな芸当ができないのが悲しいところ。

これでようやく100点が取れました。

なお気付いた経緯は、入力サンプルとして
1 10
2 10
3 10
を突っ込んでみたから。

2
2
1

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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?