I have a url with a page system.
For instance https://myURL?p=50
But I want a script to find the last page available, for instance, let's say p=187
I have a function checkEmpty() that tells me whether the page is empty or not.
So for instance:
$myUrl = new URL(50); //https://myURL?p=50
$myUrl->checkEmpty();
//This evaluates to false -> the page exists
$myUrl = new URL(188); //https://myURL?p=188
$myUrl->checkEmpty();
//This evaluates to true -> the page does NOT exist
$myUrl = new URL(187); //https://myURL?p=187
$myUrl->checkEmpty();
//This evaluates to false -> the page exists
I did a naive algorithm, that you might guess it, performs too much requests.
My question is:
What would be the algorithm to find the last page with the minimal amount of requests?
EDIT
As requested by people in the comment here is the checkEmpty() implementation
<?php
public function checkEmpty() : bool
{
$criteria = "Aucun contenu disponible";
if(strstr( $this->replace_carriage_return(" ", $this->getHtml()), $criteria) !== false)
{
return true;
}
else
{
return false;
}
}
Since the upper bound is not known, exponentially increase the page no by 2 starting from 1. The moment you hit a non-existent page, you can do a binary search from previous existing page + 1 till this new upper bound where the page doesn't exist.
This way, you can get your answer in O(log(n)) attempts asymptotically where n is the no. of existing pages here as the sample space.
<?php
$lowerBound = 1;
$upperBound = 1;
while(true){
$myUrl = new URL($upperBound);
if($myUrl->checkEmpty()){
break;
}
$lowerBound = $upperBound + 1;
$upperBound <<= 1;
}
$ans = $lowerBound;
while($lowerBound <= $upperBound){
$mid = $lowerBound + (($upperBound - $lowerBound) >> 1);
$myUrl = new URL($mid);
if($myUrl->checkEmpty()){
$upperBound = $mid - 1;
}else{
$lowerBound = $mid + 1;
$ans = $lowerBound;
}
}
echo $ans;
Related
My first ever question on here as I'm completely stuck, so apologies if I leave out any key information - please let me know!
I am creating a PHP Battleships game and trying to use full OO. I'm really close, however, an array for one of my classes does not hold any updates I make to it.
First off, I dynamically
created a HTML table with an onclick event - which passes the coordinates to a JS function.
I then make an AJAX call in jQuery:
function shotFired(row, column) {
var coords = {
x: row,
y: column
};
$.post("data/game_controller.php", {
jsonCoords: JSON.stringify(coords)
}, function(results) {
console.log(results)
console.log(results[4])
var playerShotResult = results[0];
var computerShotX = results[1] + 1;
var computerShotY = results[2] + 1;
var computerShotResult = results[3];
var positionsClicked = document.getElementById("computer_" + row + "," + column)
switch (playerShotResult) {
case "MISS":
positionsClicked.classList.add("miss");
break;
case "HIT":
positionsClicked.classList.add("hit");
break;
case "Already Hit":
document.getElementById("outputMessage").innerHTML = result
break;
default:
console.log("Player shot defaulted");
}
}, "json")
I then use game_controller.php to handle the request and call shotFired:
<?php
session_start();
require("../classes/Game.class.php");
if (isset($_POST['jsonCoords'])) {
if (isset($_SESSION['newGame'])) {
$game = unserialize($_SESSION['newGame']);
$coords = json_decode($_POST['jsonCoords']);
$results = $game->shotFired($coords->x, $coords->y);
echo json_encode($results);
}
}
shotFired from the Game.php Class file, gets an instance of the Fleet class called computer, and runs the checkPosition function:
public function shotFired($x, $y)
{
$computer = $this->getComputer();
$playerHit = $computer->checkPosition(($x - 1), ($y - 1));
$computerGrid = $computer->getBattleshipsGrid();
$computerHit = $this->simulateComputerShot();
return [$playerHit, $computerHit[0], $computerHit[1], $computerHit[2], $computerGrid];
}
checksPosition checks the State of the Position instance in the BattleshipGrid array, and then attempts to update the array with a H or M - using a standard setter method:
public function checkPosition($x, $y): string
{
$positionObj = $this->battleshipsGrid["(" . $x . "," . $y . ")"];
$positionState = $positionObj->getState();
if ($positionState == "#") {
$positionObj->setState("M");
return "MISS";
} elseif ($positionState == "M" || $positionState == "H") {
return "Already Fired";
} else {
$positionObj->setState("H");
return "HIT";
}
}
For reference, I set the Battleships board in the constructor for Fleet.php:
// Populate associative array with instances of position
for ($y = 0; $y < $gridSize; $y++) {
for ($x = 0; $x < $gridSize; $x++) {
$coordinates = "(" . $x . "," . $y . ")";
$this->battleshipsGrid[$coordinates] = new Position($x, $y);
}
}
It works directly after it has been set - however, on the next onclick event, the H or M value is reset to it's previous value?
Seen here in console output
After a couple of hours, the closest I've come to is passing byRef in the setState function (didn't make a difference).
I've seen some notes on array_map, but I'm not sure this is what I'm looking for?
For ref, this is how I output the battleshipGrid to the console:
public function getBattleshipsGrid()
{
$readableGrid = "";
$grid = $this->battleshipsGrid;
foreach ($grid as $coordsID => $positionObj) {
$readableGrid .= "\n" . $coordsID . ": " . $positionObj->getState();
}
return $readableGrid;
}
Apologies for the long post, but I didn't want to leave anything out. Any and all help would be extremely appreciated!
Many thanks
It looks like you're not saving the state of the coordinates of the hits. If you are using the eloquent model, and setState is changing the attribute's value, make sure that you call $positionObj->save() as php does not save state on each ajax request. You will need to use a database or some sort of storage to have the server 'remember' that you clicked a specific location.
I've written this function that returns a time(number )that must not exist in the same day in the database which means that the same time must not be repeated but when I execute it the time(number) is repeated
can you help me sort this one out?
screen shots of the tables
https://files.fm/u/9aw9yc8x
note: the table is empty and it will be filled when the entire code is executed I have just posted the function that must not repeat the time.
function checkTime($className,$day,$conn){
global $numberLimet,$Daily,$UserLimt,$exist;
$sqlHoure = "SELECT * from schedule WHERE classname='".$className."'";
$hourQuery = mysqli_query($conn,$sqlHoure);
$h = array();
while ($hour = mysqli_fetch_assoc($hourQuery)){
$h[$hour['hour']] = $hour['day1'];
// array_search();
}
$number = rand(1,7);
if(array_search($day,$h) && array_key_exists($number,$h)){
return 'error';
}else{
if($hour['hour'] != $number && $hour['day1'] != $day){
$numberLimet++;
if($numberLimet == $Daily){
$UserLimt = 1;
$FristAdd = false;
echo("UserLimt" . $UserLimt);
return 'errorLimit';
}else{
return $number;
}
}else{
}
}
return $h;
}
I have a function that shows a random banner from array:
//func.php
function rand_rek($rek_array){
$numberOfBanners = count($rek_array);
$numberOfBanners = $numberOfBanners - 1;
$randomBanner = rand(0,$numberOfBanners);
$rek = $rek_array[$randomBanner];
return $rek;
}
I have $reklamas array, that contains 3 banners:
//ads.php
$reklamas = array($rek1, $rek2, $rek3);
if $_GET["noa"] isnt true, I want to add more banners to $reklamas array:
if (!isset($_GET["noa"]))
array_push($reklamas, $rek_adc1, $rek_adc2, $rek_adc3, $rek_adc4);
And I want to display one of random banners x times:
for ($i=0;$i<$banneri;$i++) {
echo rand_rek($reklamas);
}
The problem:
These can be repeated as many times as they want array($rek1, $rek2, $rek3);,
while these array_push($reklamas, $rek_adc1, $rek_adc2, $rek_adc3, $rek_adc4); can be each showed only 1 time.
function rand_rek() is in func.php and it is being included from ads.php where is the rest of the code.
I think you're probably going about the problem all wrong, but in any case a solution could be
function rand_rek($rek_array){
$numberOfBanners = count($rek_array);
$numberOfBanners = $numberOfBanners - 1;
$randomBanner = rand(0,$numberOfBanners);
$rek = $rek_array[$randomBanner];
return [$randomBanner, $rek];
}
list($bannerNum, $banner) = rand_rek($reklamas);
if ($bannerNum < 3) {
$repeats = $x;
} else {
$repeats = 1;
}
for ($i=0;$i<$repeats;$i++) {
echo $banner;
}
Which retrieves the index of the banner and checks it before running the loop. I've also used your value $x that you mention in the text but not in your code.
My function searches google for the specific keyword and then checks for the site and then returns the what position it is on google (its for my seo dashboard) but it always return's 0, hopefully some fresh eyes can find the faults
<?php
function GoogleSerp($searchquery, $searchurl){
if(!empty($searchquery) && !empty($searchurl))
{
$query = str_replace(" ","+",$searchquery);
$query = str_replace("%26","&",$query);
// How many results to search through.
$total_to_search = 50;
// The number of hits per page.
$hits_per_page = 10;
// Obviously, the total pages / queries we will be doing is
// $total_to_search / $hits_per_page
// This will be our rank
$position = 0;
// This is the rank minus the duplicates
$real_position = 0;
$found = NULL;
$lastURL = NULL;
for($i=0;$i<$total_to_search && empty($found);$i+=$hits_per_page)
{
// Open the search page.
// We are filling in certain variables -
// $query,$hits_per_page and $start.
// $filename = "http://www.google.co.uk/xhtml?q=$query&start=$i&sa=N";
$filename = "http://www.google.co.uk/m?q=$query&num=$hits_per_page&filter=0&start=$i&sa=N";
$file = fopen($filename, "r");
if (!$file)
{
return "error";
}
else
{
// Now load the file into a variable line at a time
while (!feof($file))
{
$var = fgets($file, 1024);
// Try and find the font tag google uses to show the site URL
if(eregi("<span class=\"c\">(.*)</span>",$var,$out))
{
// If we find it take out any <B> </B> tags - google does
// highlight search terms within URLS
$out[1] = strtolower(strip_tags($out[1]));
// Get the domain name by looking for the first /
$x = strpos($out[1],"/");
// and get the URL
$url = substr($out[1],0,$x);
$url = str_replace("/","",$url);
$position++;
// If you want to see the hits, set $trace to something
// if($trace)return($url."<br>");
// If the last result process is the same as this one, it
// is a nest or internal domain result, so don't count it
// on $real_position
if(strcmp($lastURL,$url)<>0)$real_position++;
$lastURL = $url;
// Else if the sites match we have found it!!!
if(strcmp($searchurl,$url)==0)
{
$found = $position;
// We quit out, we don't need to go any further.
break;
}
}
}
}
fclose($file);
}
if($found)
{
$result = $real_position;
}else{
$result = 0;
}
}
return $result;
}
?>
Try urlencode() instead of the two replaces on the query.
I've created a loop where a variable is used to test if the current run-through of the loop is the first one. Its fairly simple:
$firstrun = true;
while(condition){
if($firstrun)
// Do this
else
// Do that
// Change $firstrun to false
}
I was just wondering (mostly out of curiosity because I'm it makes no real noticeable difference), when I need to change $firstrun to false, would be more efficient to test if the variable is true before assigning it to false or simply reassign it to false during each run-through?
Ex:
$firstrun = true;
while(condition){
if($firstrun)
// Do this
else
// Do that
if($firstrun)
$firstrun = false;
}
or simply
$firstrun = true;
while(condition){
if($firstrun)
// Do this
else
// Do that
$firstrun = false;
}
PS:
I guess this is a bad example also, because it would be most efficient to throw the reassignment of $firstrun in with the original condition, but as I said this is out of curiosity so I guess just pretend that is not an option for some reason.
PSS:
I was coding in PHP when this idea hit me, but I'm guessing the solution would be language agnostic. Just thought I would throw that in there in case it does for some reason matter.
So ultimately, which is faster, condition testing or variable assignment?
none of the above
$firstrun = true;
while(condition)
{
if($firstrun)
{
$firstrun = false;
}
else
{
}
}
reason I said so, because you are repetitively re-assign false to $firstrun, which you should just do at the first loop
condition test vs assignment which is faster?
for example you have shown, is the same (one execution cycle without some expensive call)
updated
I think condition testing will be slower, cause you might invoke series of subsequent action after that
This could be better, depending on what condition actually is:
if (condition) {
//execute first run code
while (condition) {
//execute subsequent run code
}
}
Given your example, you don't need the extra variable.
You don't even need the if statement if you know the code will always run at least once:
//execute first run code
while (condition) {
//execute subsequent run code
}
<?php
class Test
{
private $var = 156135135;
const SOMETHING = 156135135;
public function assign()
{
$this->var = self::SOMETHING;
}
public function conditionalAssign()
{
if ($this->var != self::SOMETHING) {
$this->var = SELF::SOMETHING;
}
}
}
$obj = new Test;
$start = microtime(true);
for ($i = 1; $i < 10000000; ++$i) {
$obj->assign();
}
echo round((microtime(true) - $start) * 1000, 2).' ms'.PHP_EOL;
$start = microtime(true);
for ($i = 1; $i < 10000000; ++$i) {
$obj->conditionalAssign();
}
echo round((microtime(true) - $start) * 1000, 2).' ms'.PHP_EOL;
conditionalAssign always faster when variable is integer, often faster when variable is boolean and almost equal, when variable is string.