An error in PHP code - php

this is extremely basic I'm sure but I haven't used PHP ever and thus finding it hard, a code that I am using is giving me an error and I'm unsure what I can do to fix it
<?php
$query = 'dogs';
$searches = 100; // number of results
$start = 0;
$pos = 1;
while($start < $searches)
{
$data = getPage('http://www.google.com/search?start=' . $start . '&q=' . urlencode($query));
preg_match_all("/\<li class\=g\>\<h3 class\=\"r\"\>\<a href\=\"([^\<\>]*)\" class\=l\>/",$data,$matches);
for($x = 0; $x < count($matches[1]); $x++)
{
echo '<p>' . $pos . ' ' . ($matches[1][$x]) . '</p>';
$pos++;
}
$start += 10;
}
?>
Error:
Call to undefined function getPage() on line 11
Any help?

There is no "getPage" function in PHP (unless you defined it).
It looks like the function file_get_contents() is what your going for.

Is the getPage() function being defined somewhere else that you're not including?
My guess is you want to use file_get_contents() instead.

There's no getPage(); function in your code and in PHP. You have to have one in order to call/use it.
See file_get_contents(); | fopen();

Related

Can't understand why my php cosine similarity code isn't working

I'm working on a website for my friend's gaming clan. I'm trying to have a php code that takes the player's coordinates, loops over some known locations and print the name of the closest location.
I can't get it to work however. It always seems to want to print "Balota" which is index 1 in the array. I also noticed that the cosine function can't be working as all values are above 1.0.
But I'm completely stuck now. I think I've been beating my head over it for too long and its something right in front of me but I can't see it.
<?php
function DotProd($loc1,$loc2){
return array_sum(array_map(create_function('$a, $b', 'return $a * $b;'), $loc1, $loc2));
}
function CosineSim($loc1,$loc2){
return DotProd($loc2,$loc2)/sqrt(DotProd($loc1,$loc2)*DotProd($loc1,$loc2));
}
function Closest($loc){
$novo = array(11300,14300);
$balota = array(4500,2500);
$zelen = array(2500,5200);
$sever = array(7900,12600);
$vybor = array(4500,8200);
$nwaf = array(4500,10200);
$neaf = array(12100,12500);
$kamensk = array(7870,14600);
$bere = array(12900,10000);
$gorka = array(9600,8900);
$elektro = array(10100,2000);
$cherno = array(6600,2600);
$stary = array(6100,7700);
$novy = array(7000,7700);
$mysk = array(1100,7200);
$locations = array($novo,$balota,$zelen,$sever,$vybor,$nwaf,$neaf,
$kamensk,$bere,$gorka,$elektro,$cherno,$stary,$novy,$mysk);
$sim = 99999999999;
$locat = 0;
for($i = 14; $i >= 0; $i--){
$s = CosineSim($loc,$locations[$i]);
echo "<br>" . $i . " " . CosineSim($loc,$locations[$i]);
if($s < $sim){
$sim = $s;
$locat = $i;
}
}
$items = array("Novo","Balota","Zelenogorsk","Severograd","Vybor","NWAF","NEAF","Kamensk Military","Berezino",
"Gorka","Elektro","Cherno","Stary Sobor","Novy Sobor","Myshkino");
return $items[$locat];
}
$x = $_GET["xpos"];
$y = $_GET["ypos"];
$location = array($x,$y);
echo "<b>You are at " . $x . ":" . $y;
$index = Closest($location);
echo "<br>You're pretty close to ". $index . "<br>";
?>
I am using a distance calculation formula based on the link: https://www.mathwarehouse.com/algebra/distance_formula/index.php
I only changed CosineSim. The rest of the code remains the same. And you don't actually need DotProd. It's not elegant but it works for me.
function CosineSim($loc1,$loc2){
// sum of x coordinates
$x1 = ($loc1[0]-$loc2[0])*($loc1[0]-$loc2[0]);
// sum of y coordinates
$y2 = ($loc1[1]-$loc2[1])*($loc1[1]-$loc2[1]);
$summ = $x1 + $y2;
$sqrt_res = sqrt($summ);
return $sqrt_res;
}
If I enter something like:
You are at 4640:7205
...
You're pretty close to Vybor
Hope this helps!

PHP How do I loop through pages of this api?

So basically I am trying to get the sum of AveragePrice of every single page on this api. Right now it only gets first page the things i've tried have only gotten it to go on an endless loop crashing wamp. Heres my code for 1 page of working.
I am just really unsure how I can get it to loop through pages and get sum of every page.
<?php
function getRap($userId){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=1&itemsPerPage=14");
$results = file_get_contents($url);
$json = json_decode($results, true);
$data = $json['data']['InventoryItems'];
$rap = 0;
foreach($data as $var) {
$rap += $var['AveragePrice'];
}
echo $rap;
}
$userId = 1;
getRap($userId);
?>
You may get better answers by looking into the API you are working with regarding how many pages to look for. You want to loop until you hit the max pages. There should be an value in the result of your request that tells you that you've asked for a page that doesn't exist (ie. no more results). If you can get a total number of results to search for then you could do a for loop with that as your limit.
//Change the function to accept the page number as a variable
function getRap($userId, $i){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=" . $i . "&itemsPerPage=14");
//work out how many pages it takes to include your total items
// ceil rounds a value up to next integer.
// ceil(20 / 14) = ceil(1.42..) == 2 ; It will return 2 and you will look for two pages
$limit = ceil($totalItems / $itemsPerPage);
// Then loop through calling the function passing the page number up to your limit.
for ($i = 0; $i < $limit; $i++) {
getRap($userId, $i);
}
If you cannot get the total number of items, you could loop while a fail state hasn't occured
// look for a fail state inside your getRap()
function getRap($userId, $i) {
if ($result = error) { //you will have to figure out what it returns on a fail
$tooMany = TRUE;
}
}
for ($i = 0; $tooMany !== TRUE ; $i++) {
getRap($userId, $i);
}
Edit: Reviewing my answer, looking for the fail state inside your function is poor form (and won't work because of the scope of the variable in this case). You could pass the variable back and forth, but I'll leave that part up to you.
To get the total, make sure that your function doesn't print the result (echo $rap) but returns it for further use.
Full example
<?php
function getRap($userId, $i){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=" . $i . "&itemsPerPage=25");
$results = file_get_contents($url);
$json = json_decode($results, true);
if ($json['msg'] == "Inventory retreived!") {
$data = $json['data']['InventoryItems'];
$rap = 0;
foreach($data as $var) {
$rap += $var['AveragePrice'];
}
return $rap;
} else {
return FALSE;
}
}
$total = 0;
$userId = 1;
for ($i = 0; $i < 1000 /*arbitrary limit to prevent permanent loop*/ ; $i++) {
$result = getRap($userId, $i);
if ($result == FALSE) {
$pages = $i;
break;
} else {
$total += getRap($userId, $i);
}
}
echo "Total value of $total, across $pages pages";
?>

PHP - latex format of function with regex

Is it possible to write a regex which would take input like 'sqrt(2 * (2+2)) + sin(pi/6)' and transform it into '\sqrt{2 \cdot (2+2)} + \sin(\pi/6)'?
The problem is the 'sqrt' and parentheses in it. It is obvious I can't simply use something like this:
/sqrt\((.?)\)/ -> \\sqrt{$1}
because this code would create something like this '\sqrt{2 \cdot (2+2)) + \sin(\pi/6}'.
My solution: it simply go throw the string converted to char array and tests if a current substring starts with $latex, if it does second for-cycle go from this point in different direction and by parentheses decides where the function starts and ends. (startsWith function)
Code:
public static function formatFunction($function, $latex, $input) {
$input = preg_replace("/" . $function . "\(/", $latex . "{", $input);
$arr = str_split($input);
$inGap = false;
$gap = 0;
for ($i = count($arr) - 1; $i >= 0; $i--) {
if (startsWith(substr($input, $i), $latex)) {
for ($x = $i; $x < count($arr); $x++) {
if ($arr[$x] == "(" || $arr[$x] == "{") { $gap++; $inGap = true; }
else if ($arr[$x] == ")" || $arr[$x] == "}") { $gap--; }
if ($inGap && $gap == 0) {
$arr[$x] = "}";
$inGap = false;
break;
}
}
}
$gap = 0;
}
return implode($arr);
}
Use:
self::formatFunction("sqrt", "\\sqrt",
"sqrt(25 + sqrt(16 - sqrt(49)) + (7 + 1)) + sin(pi/2)");
Output:
\sqrt{25+\sqrt{16-\sqrt{49}}+(7+1)}+\sin (\pi/2)
Note: sin and pi aren't formated by this code, it's only str_replace function...
In general, no regular expression can effectively handle nested parentheses. Sorry to be the bearer of bad news! The MathJAX parser library can interpret LaTeX equations and you could probably add a custom output routine to do what you want.
For TeX questions, you can also try http://tex.stackexchange.com .
Some time ago i soved a similar problem in such way. Maybe it will be helpful for you
$str = 'sqrt((2 * (2+2)) + sin(pi/(6+7)))';
$from = []; // parentheses content
$to = []; // patterns for replace #<number>
$brackets = [['(', ')'], ['{', '}'], ['[', ']']]; // new parentheses for every level
$level = 0;
$count = 1; // count or replace made
while($count) {
$str = preg_replace_callback('(\(([^()]+)\))',
function ($m) use (&$to, &$from, $brackets, $level) {
array_unshift($to, $brackets[$level][0] . $m[1] . $brackets[$level][1]);
$i = '#' . (count($to)-1); // pattern for future replace.
// here it '#1', '#2'.
// Make it so they will be unique
array_unshift($from, $i);
return $i; }, $str, -1, $count);
$level++;
}
echo str_replace($from, $to, $str); // return content back
// sqrt[{2 * (2+2)} + sin{pi/(6+7)}]
I forgot all details, but it, seems, works

How to reliably find similar strings to that typed in

I have an interface where a user will enter the name of a company. It then compares what they typed to current entries in the database, and if something similar is found it presents them with options (in case they misspelled) or they can click a button which confirms what they typed is definitely new and unique.
The problem I am having is that it is not very accurate and often brings up dozens of "similar" matches that aren't that similar at all!
Here is what I have now, the first large function I didn't make and I am not clear on what exactly it does. Is there are much simpler way to acheive what I want?
// Compares strings and determines how similar they are based on a nth letter split comparison.
function cmp_by_optionNumber($b, $a) {
if ($a["score"] == $b["score"]) return 0;
if ($a["score"] > $b["score"]) return 1;
return -1;
}
function string_compare($str_a, $str_b)
{
$length = strlen($str_a);
$length_b = strlen($str_b);
$i = 0;
$segmentcount = 0;
$segmentsinfo = array();
$segment = '';
while ($i < $length)
{
$char = substr($str_a, $i, 1);
if (strpos($str_b, $char) !== FALSE)
{
$segment = $segment.$char;
if (strpos($str_b, $segment) !== FALSE)
{
$segmentpos_a = $i - strlen($segment) + 1;
$segmentpos_b = strpos($str_b, $segment);
$positiondiff = abs($segmentpos_a - $segmentpos_b);
$posfactor = ($length - $positiondiff) / $length_b; // <-- ?
$lengthfactor = strlen($segment)/$length;
$segmentsinfo[$segmentcount] = array( 'segment' => $segment, 'score' => ($posfactor * $lengthfactor));
}
else
{
$segment = '';
$i--;
$segmentcount++;
}
}
else
{
$segment = '';
$segmentcount++;
}
$i++;
}
// PHP 5.3 lambda in array_map
$totalscore = array_sum(array_map(function($v) { return $v['score']; }, $segmentsinfo));
return $totalscore;
}
$q = $_POST['stringA'] ;
$qLengthMin = strlen($q) - 5 ; // Part of search calibration. Smaller number = stricter.
$qLengthMax = strlen($q) + 2 ; // not in use.
$main = array() ;
include("pdoconnect.php") ;
$result = $dbh->query("SELECT id, name FROM entity_details WHERE
name LIKE '{$q[0]}%'
AND CHAR_LENGTH(name) >= '$qLengthMin'
#LIMIT 50") ; // The first letter MUST be correct. This assumption makes checker faster and reduces irrelivant results.
$x = 0 ;
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
$percent = string_compare(strtolower($q), strtolower(rawurldecode($row['name']))) ;
if($percent == 1) {
//echo 1 ;// 1 signifies an exact match on a company already in our DB.
echo $row['id'] ;
exit() ;
}
elseif($percent >= 0.6) { // Part of search calibration. Higher deci number = stricter.
$x++ ;
$main[$x]['name'] = rawurldecode($row['name']) ;
$main[$x]['score'] = round($percent, 2) * 100;
//array_push($overs, urldecode($row['name']) . " ($percent)<br />") ;
}
}
usort($main, "cmp_by_optionNumber") ;
$z = 0 ;
echo '<div style="overflow-y:scroll;height:175px;width:460px;">' ;
foreach($main as $c) {
if($c['score'] > 100) $c['score'] = 100 ;
if(count($main) > 1) {
echo '<div id="anysuggested' . $z . '" class="hoverdiv" onclick="selectAuto(' . "'score$z'" . ');">' ;
}
else echo '<div id="anysuggested' . $z . '" class="hoverdiv" style="color:#009444;" onclick="selectAuto(' . "'score$z'" . ');">' ;
echo '<span id="autoscore' . $z . '">' . $c['name'] . '</span></div>' ;
$z++ ;
}
echo '</div>' ;
Comparing strings is a huge topic and there are many ways to do it. One very common algorithm is called the Levenshtein difference. This is a native implementation in PHP but none in MySQL. There is however an implementation here that you could use.
You need aproximate/fuzzy string matching.
Read more about
http://php.net/manual/en/function.levenshtein.php, http://www.slideshare.net/kyleburton/fuzzy-string-matching
The best way would be to use some index based search engine like SOLR http://lucene.apache.org/solr/.

strpos problem: getting value UBLIC returned

I am making a class to open a webpage and store the href values of all outbound links on the page. For some reason it works for the first 3 then goes wierd. Below is my code:
class Crawler {
var $url;
function construct($url) {
$this->url = 'http://'.$url;
$this->crawl();
}
function crawl() {
$str = file_get_contents($this->url);
$start = 0;
for($i=0; $i<10; $i++) {
$beg = strpos($str, '<a href="http://',$start)+16;
$end = strpos($str,'"',$beg);
$diff = $end - $beg;
$links[$i] = substr($str,$beg, $diff);
$start = $start + $beg;
}
print_r($links);
}
}
$crawler = new Crawler;
$crawler->construct('www.yahoo.com');
Ignore the for loop for the time being I know this will only return the first 10 and won't do the whole document. But if you run this code the first 3 work fine but then all the other values are UBLIC.
Can anyone help? Thanks
Instead of:
$start = $start + $beg;
try:
$start = $beg;
That's likely why you are only seeing the first three matches.
Also, you need to insert a check that $beg is not FALSE:
for($i=0; $i<10; $i++) {
$beg = strpos($str, '<a href="http://',$start)+16;
if ($beg === FALSE)
break;
//...
Note, however, that you really should be using DOMDocument to find all tags in a document with a given tag name (a here). In particular, because this is HTML that might not be valid XHTML, you should consider using the loadHTML method.
I think you have a problem in your logic:
you use $start to mark the place where to start looking for the href, but the resulting $beg will still be an index into the complete string. So when you update $start by adding $beg you get to high values. You should try $start = $beg + 1 instead of $start = $start + $beg

Categories