You*_*uri 11 php class permutation
我已经根据分数计算了一次计算.
例如,如果分数当前为140,则该类返回一个包含可能抛出的集合的数组:
[10] => Array
(
[0] => T18
[1] => T18
[2] => D16
)
[11] => Array
(
[0] => T18
[1] => T16
[2] => D19
)
[13] => Array
(
[0] => T17
[1] => T17
[2] => D19
)
[14] => Array
(
[0] => 50
[1] => 50
[2] => D20
Run Code Online (Sandbox Code Playgroud)
但计算这样的事情是相当缓慢的.有什么方法可以优化这个课程吗?
<?php
/**
* PHP Dartgame calculating class
* @author Youri van den Bogert
*/
class Darts {
/**
* @var string
*/
public static $notation_triple = 'T';
/**
* @var string
*/
public static $notation_double = 'D';
/**
* @var int
*/
private static $maxCheckout = 170;
/**
* @var string
*/
private static $doubleBull = 'Bull';
/**
* @var string
*/
private static $singleBull = 'Single';
/**
* @var array
*/
private static $scoreSheet = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '25', '50');
/**
* Get a total thrown score
* @param $score1
* @param $score2
* @param $score3
* @return array
*/
public static function getTotalScore ($score1, $score2, $score3) {
return array(
'dart1' => self::getScoreOfDart($score1),
'dart2' => self::getScoreOfDart($score2),
'dart3' => self::getScoreOfDart($score3),
'total' => self::getScoreOfDart($score1) + self::getScoreOfDart($score2) + self::getScoreOfDart($score3)
);
}
/**
* Get score of a single dart
* @param $score
* @return mixed
*/
public static function getScoreOfDart ($score) {
if (is_numeric($score)) {
return $score;
}
if ($score[0] == self::$notation_triple) {
$multiplier = 3;
} elseif ($score[0] == self::$notation_double) {
$multiplier = 2;
} else {
$multiplier = 1;
}
$correctScore = filter_var($score, FILTER_SANITIZE_NUMBER_INT);
return ($correctScore * $multiplier);
}
public static function getScoreSheet () {
return self::$scoreSheet;
}
public static function calculatePossibleCheckout ($currentScore) {
// We cant checkout higher then $maxCheckout
if ($currentScore > self::$maxCheckout || $currentScore == 1) {
return false;
}
// Return bull
if ($currentScore == 50) {
return array(
'dart1' => self::$doubleBull
);
}
if ($currentScore == self::$maxCheckout) {
return array(
'dart1' => self::$notation_triple . '20',
'dart2' => self::$notation_triple . 'T20',
'dart3' => 'Bull'
);
}
$lastScore = $currentScore;
$lastPossibleThrow = 0;
$checkOut = array();
// Can current score be checked out?
if (self::canScore($currentScore) == true) {
return array(
'dart1' => self::$notation_double . ($currentScore / 2)
);
// Current score can't be checked out - calculate what to throw
} else {
for ($x=60; $x >= 0; --$x) {
if ($x <= 20 || $x == 50 || $x == 25 || ($x % 3 == 0) || ($x <= 40 && ($x % 2 == 0))) {
for ($xx=60; $xx >= 0; --$xx) {
if ($x <= 20 || $x == 50 || $x == 25 || ($x % 3 == 0) || ($x <= 40 && ($x % 2 == 0))) {
for ($xxx=50; $xxx > 0; $xxx = $xxx - 2) {
if ($xxx == 48) {
$xxx = 40;
}
if (self::checkIfScoreExists($xxx) == true && self::checkIfScoreExists($xx) == true && self::checkIfScoreExists($x) == true && ($xxx + $xx + $x) == $currentScore) {
$score_1 = self::getCorrectDartName($xxx);
$score_2 = self::getCorrectDartName($xx);
$score_3 = self::getCorrectDartName($x, true);
if ($score_1[0] == 'D' || $score_2[0] == 'D' || $score_3[0] == 'D') {
$nextKey = (count($checkOut)+1);
if ($xxx != 0) $checkOut[$nextKey][] = $score_1;
if ($xx != 0) $checkOut[$nextKey][] = $score_2;
if ($x != 0) $checkOut[$nextKey][] = $score_3;
usort($checkOut[$nextKey], function($a, $b) {
if (is_int($a) || is_float($a)) {
if (is_int($b) || is_float($b)) {
return $a - $b;
}
else
return -1;
}
elseif (is_int($b) || is_float($b)) {
return 1;
}
else {
return strcmp($b, $a);
}
});
}
}
}
}
}
}
}
}
return array_unique($checkOut, SORT_REGULAR);
}
public static function getCorrectDartName ($total, $isLast = false) {
if ($total == 25 || $total == 50) {
return $total;
}
if ($total < 20 && $isLast == false) {
return $total;
}
if ($total %3 == 0) {
return self::$notation_triple . ($total/3);
} elseif ($total %2 == 0) {
return self::$notation_double . ($total/2);
}
return $total;
}
/**
* Check if score exists
* @param $score
* @return bool
*/
public static function checkIfScoreExists ($score) {
if ($score == 50 || $score == 25 || $score == 0) return true;
$possibleScores = array_merge(range(1,20));
foreach ($possibleScores as $posScore) {
if ($score == self::getScoreOfDart(self::$notation_double . $posScore) || $score == self::getScoreOfDart(self::$notation_triple . $posScore) || $score == $posScore) {
return true;
}
}
return false;
}
/**
* Check if a specific score can be thrown by one dart
* @param $score
* @return bool
*/
public static function canScore ($score) {
if ($score == 50) {
return true;
} elseif ($score < 40 || $score == 40) {
if ($score % 2 == 0) {
return true; // Score is even - so its possible to throw
} else {
return false;
}
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
我已经使用了基本排列生成,而且速度非常快(0.06秒).它当然可以优化,但我认为没有意义,因为它已经如此之快.
<?php
class DartUtils {
private static $possible_points;
public static function getPossibleThrowsForScore($score) {
// generate all possible single throws and their score
// I didn't want to write them all out
// but it's certainly an option (and faster)
self::$possible_points = array();
for ($i = 1; $i <= 20; $i += 1) {
self::$possible_points["S" . $i] = $i; // S = single
self::$possible_points["D" . $i] = $i * 2;
self::$possible_points["T" . $i] = $i * 3;
}
self::$possible_points["bull"] = 25;
self::$possible_points["double bull"] = 50;
// self::$possible_points["miss"] = 0;
$throws = self::findSatisfyingThrowsForScore($score, 3, array());
foreach ($throws as $i => $serialized_throw) {
$throws[$i] = unserialize($serialized_throw);
}
return $throws;
}
private static function findSatisfyingThrowsForScore($score, $num_throws, $base_notation) {
$possible_throws = array();
foreach (self::$possible_points as $notation => $value) {
if ($num_throws === 1) { // we've done all throws
if ($score - $value === 0) { // we satisfied the score
$throw = array_merge($base_notation, array($notation));
sort($throw);
$possible_throws[] = serialize($throw);
}
} else {
// so long as there are num_throws, recurse with all possible throws
$possible_throws = array_merge($possible_throws,
self::findSatisfyingThrowsForScore($score - $value, $num_throws - 1, array_merge($base_notation, array($notation))));
}
}
$possible_throws = array_unique($possible_throws);
sort($possible_throws);
return $possible_throws;
}
}
var_dump(DartUtils::getPossibleThrowsForScore(140));
Run Code Online (Sandbox Code Playgroud)
输出是:
array(21) {
[0]=>
array(3) {
[0]=>
string(3) "D10"
[1]=>
string(3) "T20"
[2]=>
string(3) "T20"
}
[1]=>
array(3) {
[0]=>
string(3) "D13"
[1]=>
string(3) "T18"
[2]=>
string(3) "T20"
}
[2]=>
array(3) {
[0]=>
string(3) "D13"
[1]=>
string(3) "T19"
[2]=>
string(3) "T19"
}
[3]=>
array(3) {
[0]=>
string(3) "D15"
[1]=>
string(3) "T20"
[2]=>
string(11) "double bull"
}
[4]=>
array(3) {
[0]=>
string(3) "D16"
[1]=>
string(3) "T16"
[2]=>
string(3) "T20"
}
[5]=>
array(3) {
[0]=>
string(3) "D16"
[1]=>
string(3) "T17"
[2]=>
string(3) "T19"
}
[6]=>
array(3) {
[0]=>
string(3) "D16"
[1]=>
string(3) "T18"
[2]=>
string(3) "T18"
}
[7]=>
array(3) {
[0]=>
string(3) "D18"
[1]=>
string(3) "T18"
[2]=>
string(11) "double bull"
}
[8]=>
array(3) {
[0]=>
string(3) "D19"
[1]=>
string(3) "T14"
[2]=>
string(3) "T20"
}
[9]=>
array(3) {
[0]=>
string(3) "D19"
[1]=>
string(3) "T15"
[2]=>
string(3) "T19"
}
[10]=>
array(3) {
[0]=>
string(3) "D19"
[1]=>
string(3) "T16"
[2]=>
string(3) "T18"
}
[11]=>
array(3) {
[0]=>
string(3) "D19"
[1]=>
string(3) "T17"
[2]=>
string(3) "T17"
}
[12]=>
array(3) {
[0]=>
string(3) "D20"
[1]=>
string(11) "double bull"
[2]=>
string(11) "double bull"
}
[13]=>
array(3) {
[0]=>
string(3) "D20"
[1]=>
string(3) "D20"
[2]=>
string(3) "T20"
}
[14]=>
array(3) {
[0]=>
string(3) "S20"
[1]=>
string(3) "T20"
[2]=>
string(3) "T20"
}
[15]=>
array(3) {
[0]=>
string(3) "T10"
[1]=>
string(3) "T20"
[2]=>
string(11) "double bull"
}
[16]=>
array(3) {
[0]=>
string(3) "T11"
[1]=>
string(3) "T19"
[2]=>
string(11) "double bull"
}
[17]=>
array(3) {
[0]=>
string(3) "T12"
[1]=>
string(3) "T18"
[2]=>
string(11) "double bull"
}
[18]=>
array(3) {
[0]=>
string(3) "T13"
[1]=>
string(3) "T17"
[2]=>
string(11) "double bull"
}
[19]=>
array(3) {
[0]=>
string(3) "T14"
[1]=>
string(3) "T16"
[2]=>
string(11) "double bull"
}
[20]=>
array(3) {
[0]=>
string(3) "T15"
[1]=>
string(3) "T15"
[2]=>
string(11) "double bull"
}
}
Run Code Online (Sandbox Code Playgroud)
我添加的投掷是:1-20单,双或三,公牛和双公牛.如果有更多或特殊投掷,您可以添加它们.
排序+序列化是快速删除重复项的技巧.对于抛出验证目的,将重复项留在其中可能实际上是有益的.
您可以考虑将符号作为字符串接受,例如:S10D20BULL或DBULLDBULLT20.如果你介绍S单曲,你永远不会有困惑.D112T20是ambigous,是它D11S2T20还是D1S12T20?字符串更容易使用,因此您甚至可以获得性能.将字符串符号拆分成它的部分有点棘手但可行.
请注意,我没有添加特殊检查,>170或者1因为列表只是空的.这是您可以应用的优化.
您可以选择添加miss得分为的throw 0.
我不太了解你的代码,它太复杂了.我认为你正在失去很多时间进行排序和表示法之间的转换.正如您在我的解决方案中所看到的,我快速构建结果集并同时进行分数计算和符号生成.
我还要提一下,我对飞镖规则不太熟悉.我假设公牛和双牛,但如果单公牛和公牛是准确的,请随意纠正我.
| 归档时间: |
|
| 查看次数: |
719 次 |
| 最近记录: |