Random Error with in_array - php

So, i was challenged by a coworker to build a random poker hand generator. At the time, all I had was my phone that I could run php with.
So, after some tinkering and lots of searching, i came up with this:
<?php
$cards;
$card = array();
function GetCard($getSuit, $getNumber){
for($s=0; $s < 4; $s++){
for($n=0; $n < 13; $n++){
if($s == 0){
//Clubs
$suits[$s] = "-C";
} else if($s == 1){
//Hearts
$suits[$s] = "-H";
} else if($s == 2){
//Spades
$suits[$s] = "-S";
} else if($s == 3){
//Diamonds
$suits[$s] = "-D";
}
if($n == 0){
$num[$n] = "A";
} else if($n == 10){
$num[$n] = "J";
} else if($n == 11){
$num[$n] = "Q";
} else if($n == 12){
$num[$n] = "K";
} else {
$num[$n] = $n+1;
}
$cards[$s][$n] = $num[$n].$suits[$s];
}
}
return $cards[$getSuit][$getNumber];
}
function GetRandomPokerHand(){
$i = 0;
while($i < 5){
mt_srand();
$rs = mt_rand(0,3);
$rn = mt_rand(0,12);
$randomCard = GetCard($rs,$rn);
if(!in_array($randomCard,$card)){
$card[i] = GetCard($rs,$rn);
echo $card[i];
echo " ";
$i++;
}else{
echo " found ";
}
}
}
GetRandomPokerHand();
?>
I get the hand, however... every so often in_array fails and I get the same card twice. i added the "else" statement with "found" to see if it was finding the duplicate at all. It did and echos "found", and occasionally it STILL displays a duplicate.
So I decided to try the same code (well roughly the same) when i got home with c++: (Using "switch" instead of "if" was because of preference and switch statements are too much trouble on a phone)
#include <iostream>
#include <string>
#include <vector>
#include <time.h>
using namespace std;
string suits[4];
string num[13];
string cards[4][13];
string GetCard(int getSuit, int getNumber){
for (int s = 0; s < 4; s++){
for (int n = 0; n < 13; n++){
switch (s){
case 0:
suits[s] = "-C";
break;
case 1:
suits[s] = "-H";
break;
case 2:
suits[s] = "-S";
break;
case 3:
suits[s] = "-D";
break;
}
switch (n){
case 0:
num[n] = "A";
break;
case 10:
num[n] = "J";
break;
case 11:
num[n] = "Q";
break;
case 12:
num[n] = "K";
break;
default:
num[n] = to_string(n + 1);
break;
}
cards[s][n] = num[n] + suits[s];
}
}
string card = { cards[getSuit][getNumber] };
return card;
}
bool in_array(const string &value, const vector<string> &array){
return find(array.begin(), array.end(), value) != array.end();
}
void GetRanddomPokerHand(){
int hand = 0;
srand(time(NULL));
while (hand < 5){
int suit = rand() % 4;
int value = rand() % 13;
string randomCard = GetCard(suit, value);
vector<string> card = { "", "", "", "", "" };
if (!in_array(randomCard, card)){
card[hand] = randomCard;
cout << card[hand] << endl;
hand++;
}else{
cout << "found";
}
}
}
int main(){
GetRanddomPokerHand();
char stop;
cin >> stop; // yes, i know this isn't necessary in VE2013
return 0;
}
Same problem. I can't seem to figure out why the duplicates are being printed in either case.
Any ideas?

In the c++ one you have this line inside your loop
vector<string> card = { "", "", "", "", "" };
That is creating a fresh blank hand each time, so it never will have duplicates.

$card[i] need to be $card[$i]
your $card array always has only 1 element which is last card cause of that mistake ;)

Related

automatic number increase in php based web form [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
So I have created an html form which then posts the results to a php file that overlays them on a PDF and then emails that PDF to myself and the email that was put in the form. All I want to do now is find a simple way to make it so that the PDF includes a sequential number.
For example: When the form is filled out for the first time the number 0001 is input automatically into the PDF and 0002 for the second time and so on.
Is there an easy PHP function to accomplish this?
Essentially I am creating an online invoicing form so when I do service calls I can create an invoice on the spot from a web browser which is then emailed to my office and the client.
Any help would be greatly appreciated.
For an incrementing number, you could keep a number in a database and then extract it, add 1 to it, use it, and then put it back in the DB for next time, but this seems complicated. Somebody in the comments mentioned using the timestamp, which would be done like so:
$invoicenumber = time(); //This number will always be unique
The time function works like so (copied from w3schools):
The time() function returns the current time in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).
Since actual seconds can only go up (increment), this number will never be the same twice.
I hope this is helpful.
-Edit
You can also display this date/time in a readable format like so:
$time = time();
echo date("Y-m-d H:i:s",$time);
-Edit 2
If you want an incrementing number, you basically need a very simple database to save it, which might be as simple as a table called invoices, with a column called invoicenumber, which stores your invoice number in it. You could / probably should use this to store other invoice information in it too, so you'd have each invoice number saved (which means we want to only get the highest one)
Then your code would look like this, for each time you want to use it:
Firstly you'd have a database information file (settings.php or something similar) with your database definitions in it, which might look like this:
define('DB_HOST', 'localhost');
define('DB_USER', 'db_username');
define('DB_PASS', 'db_password');
define('DB_NAME', 'database_name');
Your code would look like this:
//Establish a mysql connection
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
//Set up a query to get the highest number
$query = "SELECT invoicenumber FROM invoices ORDER BY invoicenumber DESC LIMIT 1";
//Get the result
$result = $mysqli->query($query);
$row = $result->fetch_assoc();
//If we have a record
if($row){
//New invoice number
$invoicenumber = $row['invoicenumber']++;
//Else (database is empty, so start at the beginning)
}else{
$invoicenumber = 1;
}
//Now we have our invoice number, so do whatever you want with it
/**
* Code here to use the number
* */
//Now we wanna add the new invoice to the database, so
/**
* Add any other info to this statement if you want.
* If any of it is user submitted data, be sure to use prepared statements
* (just look at php.net's documentation on prepared statements)
* w3schools also has some nice tutorials on how to safely insert stuff
* in to a database, so check it all out :)
* */
$query = "INSERT INTO invoices(invoicenumber) VALUES($invoicenumber)";
//Execute the query
if($mysqli->query($query)){
//Show success
echo "Invoice $invoicenumber has been added to the database.";
}else{
//Show error
echo "Unfortunately we could not add invoice $invoicenumber to the database.";
}
//Now we can clear up our resources
$stmt->free_result(); $stmt->close(); $mysqli->close();
Please note: this is a very basic example. Yours will have additions and enhanced security if you are using user submitted data, so please do your homework and make sure that you fully understand each line of this code before you proceed to use it.
I do exactly the same with patient accession numbers on patient reports.
include('/home/user/php/class.pdf2text.php');
$p2t = new PDF2Text();
$p2t->setFilename($pdf);
$p2t->decodePDF();
$data = $p2t->output();
$len = strlen($data);
$pos = strpos($data,$accession);
if (pos){
$in .= "$accession,";
$checked++;
}
else{
$missingPDF += 1;echo "\n<p> <span class='bold red'>INCORRECT ACCESSION NUMBER c=$row[0] p=$row[1]</span>\n";
}
if ($checked > 0){
$in = substr($in,0,-1) . ')';
$sql = "UPDATE `Patient` SET `PDF`=1 WHERE $in";
}
pdf2text.php
class PDF2Text {
// Some settings
var $multibyte = 4; // Use setUnicode(TRUE|FALSE)
var $convertquotes = ENT_QUOTES; // ENT_COMPAT (double-quotes), ENT_QUOTES (Both), ENT_NOQUOTES (None)
var $showprogress = true; // TRUE if you have problems with time-out
// Variables
var $filename = '';
var $decodedtext = '';
function setFilename($filename) {
// Reset
$this->decodedtext = '';
$this->filename = $filename;
}
function output($echo = false) {
if($echo) echo $this->decodedtext;
else return $this->decodedtext;
}
function setUnicode($input) {
// 4 for unicode. But 2 should work in most cases just fine
if($input == true) $this->multibyte = 4;
else $this->multibyte = 2;
}
function decodePDF() {
// Read the data from pdf file
$infile = #file_get_contents($this->filename, FILE_BINARY);
if (empty($infile))
return "";
// Get all text data.
$transformations = array();
$texts = array();
// Get the list of all objects.
preg_match_all("#obj[\n|\r](.*)endobj[\n|\r]#ismU", $infile . "endobj\r", $objects);
$objects = #$objects[1];
// Select objects with streams.
for ($i = 0; $i < count($objects); $i++) {
$currentObject = $objects[$i];
// Prevent time-out
#set_time_limit ();
if($this->showprogress) {
// echo ". ";
flush(); ob_flush();
}
// Check if an object includes data stream.
if (preg_match("#stream[\n|\r](.*)endstream[\n|\r]#ismU", $currentObject . "endstream\r", $stream )) {
$stream = ltrim($stream[1]);
// Check object parameters and look for text data.
$options = $this->getObjectOptions($currentObject);
if (!(empty($options["Length1"]) && empty($options["Type"]) && empty($options["Subtype"])) )
// if ( $options["Image"] && $options["Subtype"] )
// if (!(empty($options["Length1"]) && empty($options["Subtype"])) )
continue;
// Hack, length doesnt always seem to be correct
unset($options["Length"]);
// So, we have text data. Decode it.
$data = $this->getDecodedStream($stream, $options);
if (strlen($data)) {
if (preg_match_all("#BT[\n|\r](.*)ET[\n|\r]#ismU", $data . "ET\r", $textContainers)) {
$textContainers = #$textContainers[1];
$this->getDirtyTexts($texts, $textContainers);
} else
$this->getCharTransformations($transformations, $data);
}
}
}
// Analyze text blocks taking into account character transformations and return results.
$this->decodedtext = $this->getTextUsingTransformations($texts, $transformations);
}
function decodeAsciiHex($input) {
$output = "";
$isOdd = true;
$isComment = false;
for($i = 0, $codeHigh = -1; $i < strlen($input) && $input[$i] != '>'; $i++) {
$c = $input[$i];
if($isComment) {
if ($c == '\r' || $c == '\n')
$isComment = false;
continue;
}
switch($c) {
case '\0': case '\t': case '\r': case '\f': case '\n': case ' ': break;
case '%':
$isComment = true;
break;
default:
$code = hexdec($c);
if($code === 0 && $c != '0')
return "";
if($isOdd)
$codeHigh = $code;
else
$output .= chr($codeHigh * 16 + $code);
$isOdd = !$isOdd;
break;
}
}
if($input[$i] != '>')
return "";
if($isOdd)
$output .= chr($codeHigh * 16);
return $output;
}
function decodeAscii85($input) {
$output = "";
$isComment = false;
$ords = array();
for($i = 0, $state = 0; $i < strlen($input) && $input[$i] != '~'; $i++) {
$c = $input[$i];
if($isComment) {
if ($c == '\r' || $c == '\n')
$isComment = false;
continue;
}
if ($c == '\0' || $c == '\t' || $c == '\r' || $c == '\f' || $c == '\n' || $c == ' ')
continue;
if ($c == '%') {
$isComment = true;
continue;
}
if ($c == 'z' && $state === 0) {
$output .= str_repeat(chr(0), 4);
continue;
}
if ($c < '!' || $c > 'u')
return "";
$code = ord($input[$i]) & 0xff;
$ords[$state++] = $code - ord('!');
if ($state == 5) {
$state = 0;
for ($sum = 0, $j = 0; $j < 5; $j++)
$sum = $sum * 85 + $ords[$j];
for ($j = 3; $j >= 0; $j--)
$output .= chr($sum >> ($j * 8));
}
}
if ($state === 1)
return "";
elseif ($state > 1) {
for ($i = 0, $sum = 0; $i < $state; $i++)
$sum += ($ords[$i] + ($i == $state - 1)) * pow(85, 4 - $i);
for ($i = 0; $i < $state - 1; $i++) {
try {
if(false == ($o = chr($sum >> ((3 - $i) * 8)))) {
throw new Exception('Error');
}
$output .= $o;
} catch (Exception $e) { /*Dont do anything*/ }
}
}
return $output;
}
function decodeFlate($data) {
return #gzuncompress($data);
}
function getObjectOptions($object) {
$options = array();
if (preg_match("#<<(.*)>>#ismU", $object, $options)) {
$options = explode("/", $options[1]);
#array_shift($options);
$o = array();
for ($j = 0; $j < #count($options); $j++) {
$options[$j] = preg_replace("#\s+#", " ", trim($options[$j]));
if (strpos($options[$j], " ") !== false) {
$parts = explode(" ", $options[$j]);
$o[$parts[0]] = $parts[1];
} else
$o[$options[$j]] = true;
}
$options = $o;
unset($o);
}
return $options;
}
function getDecodedStream($stream, $options) {
$data = "";
if (empty($options["Filter"]))
$data = $stream;
else {
$length = !empty($options["Length"]) ? $options["Length"] : strlen($stream);
$_stream = substr($stream, 0, $length);
foreach ($options as $key => $value) {
if ($key == "ASCIIHexDecode")
$_stream = $this->decodeAsciiHex($_stream);
elseif ($key == "ASCII85Decode")
$_stream = $this->decodeAscii85($_stream);
elseif ($key == "FlateDecode")
$_stream = $this->decodeFlate($_stream);
elseif ($key == "Crypt") { // TO DO
}
}
$data = $_stream;
}
return $data;
}
function getDirtyTexts(&$texts, $textContainers) {
for ($j = 0; $j < count($textContainers); $j++) {
if (preg_match_all("#\[(.*)\]\s*TJ[\n|\r]#ismU", $textContainers[$j], $parts))
$texts = array_merge($texts, array(#implode('', $parts[1])));
elseif (preg_match_all("#T[d|w|m|f]\s*(\(.*\))\s*Tj[\n|\r]#ismU", $textContainers[$j], $parts))
$texts = array_merge($texts, array(#implode('', $parts[1])));
elseif (preg_match_all("#T[d|w|m|f]\s*(\[.*\])\s*Tj[\n|\r]#ismU", $textContainers[$j], $parts))
$texts = array_merge($texts, array(#implode('', $parts[1])));
}
}
function getCharTransformations(&$transformations, $stream) {
preg_match_all("#([0-9]+)\s+beginbfchar(.*)endbfchar#ismU", $stream, $chars, PREG_SET_ORDER);
preg_match_all("#([0-9]+)\s+beginbfrange(.*)endbfrange#ismU", $stream, $ranges, PREG_SET_ORDER);
for ($j = 0; $j < count($chars); $j++) {
$count = $chars[$j][1];
$current = explode("\n", trim($chars[$j][2]));
for ($k = 0; $k < $count && $k < count($current); $k++) {
if (preg_match("#<([0-9a-f]{2,4})>\s+<([0-9a-f]{4,512})>#is", trim($current[$k]), $map))
$transformations[str_pad($map[1], 4, "0")] = $map[2];
}
}
for ($j = 0; $j < count($ranges); $j++) {
$count = $ranges[$j][1];
$current = explode("\n", trim($ranges[$j][2]));
for ($k = 0; $k < $count && $k < count($current); $k++) {
if (preg_match("#<([0-9a-f]{4})>\s+<([0-9a-f]{4})>\s+<([0-9a-f]{4})>#is", trim($current[$k]), $map)) {
$from = hexdec($map[1]);
$to = hexdec($map[2]);
$_from = hexdec($map[3]);
for ($m = $from, $n = 0; $m <= $to; $m++, $n++)
$transformations[sprintf("%04X", $m)] = sprintf("%04X", $_from + $n);
} elseif (preg_match("#<([0-9a-f]{4})>\s+<([0-9a-f]{4})>\s+\[(.*)\]#ismU", trim($current[$k]), $map)) {
$from = hexdec($map[1]);
$to = hexdec($map[2]);
$parts = preg_split("#\s+#", trim($map[3]));
for ($m = $from, $n = 0; $m <= $to && $n < count($parts); $m++, $n++)
$transformations[sprintf("%04X", $m)] = sprintf("%04X", hexdec($parts[$n]));
}
}
}
}
function getTextUsingTransformations($texts, $transformations) {
$document = "";
for ($i = 0; $i < count($texts); $i++) {
$isHex = false;
$isPlain = false;
$hex = "";
$plain = "";
for ($j = 0; $j < strlen($texts[$i]); $j++) {
$c = $texts[$i][$j];
switch($c) {
case "<":
$hex = "";
$isHex = true;
$isPlain = false;
break;
case ">":
$hexs = str_split($hex, $this->multibyte); // 2 or 4 (UTF8 or ISO)
for ($k = 0; $k < count($hexs); $k++) {
$chex = str_pad($hexs[$k], 4, "0"); // Add tailing zero
if (isset($transformations[$chex]))
$chex = $transformations[$chex];
$document .= html_entity_decode("&#x".$chex.";");
}
$isHex = false;
break;
case "(":
$plain = "";
$isPlain = true;
$isHex = false;
break;
case ")":
$document .= $plain;
$isPlain = false;
break;
case "\\":
$c2 = $texts[$i][$j + 1];
if (in_array($c2, array("\\", "(", ")"))) $plain .= $c2;
elseif ($c2 == "n") $plain .= '\n';
elseif ($c2 == "r") $plain .= '\r';
elseif ($c2 == "t") $plain .= '\t';
elseif ($c2 == "b") $plain .= '\b';
elseif ($c2 == "f") $plain .= '\f';
elseif ($c2 >= '0' && $c2 <= '9') {
$oct = preg_replace("#[^0-9]#", "", substr($texts[$i], $j + 1, 3));
$j += strlen($oct) - 1;
$plain .= html_entity_decode("&#".octdec($oct).";", $this->convertquotes);
}
$j++;
break;
default:
if ($isHex)
$hex .= $c;
elseif ($isPlain)
$plain .= $c;
break;
}
}
$document .= "\n";
}
return $document;
}
}

String to Bool Conversion ... works in 4 bit but not 8 bit

Trying to put together a php program that reads a 'menu' integer variable (passed through the URL) that converts it to a binary string ... then reads each Boolean in the string and adds it to an array.
Works fine for 4-bit (albeit perhaps not very efficient) .... but won't work for 8-bit?
<?php
$menubin = decbin($_GET['menu']);
$menulen = strlen($menubin)-1;
for($x=$menulen; $x > -1; $x--)
{
$array = $menulen-$x;
$menubool[$array] = substr($menubin,$x,1);
}
if($menubool[0] == '1') { ... }
if($menubool[1] == '1') { ... }
if($menubool[2] == '1') { ... }
if($menubool[3] == '1') { ... }
if($menubool[4] == '1') { ... }
if($menubool[5] == '1') { ... }
if($menubool[6] == '1') { ... }
if($menubool[7] == '1') { ... }
?>
Assuming that your $menubin string looks something like 0100. This can be achieved with bitwise operands and a switch statement. This approach will give you some flexibility and allow you to select menu items arbitrarily.
<?php
//string of selections
$string = "1011";
// result of bitshift on string
$bits = 0;
for($i = strlen($string); $i >= 0; $i -= 1){
$bits += (int)$string[$i] << $i;
}
// arbitrarily make selections and cases as you add menu items
switch($bits) {
case 1:
echo "menu item 1";
break;
case 2:
echo "menu item 2";
break;
case 4:
echo "menu item 3";
break;
case 8:
echo "menu item 4";
break;
case 13:
echo "menu item 1, 3 and 4";
break;
}
?>
You can do something like this:
$int = 37; // for example
$bits = array();
$str = str_pad(decbin($int),8,"0",STR_PAD_LEFT);
for ($i=0; $i<=7; $i++){
$bits[7-$i] = substr($str,$i,1);
}
var_dump($bits);
Then just access the bits of the array as you require for your menu options.
Your initial problem was that decbin doesn't return the correct string length, hence the padding function above.
In your case, 64 would return 1000000 and not 01000000

MySQL Select Not Returning resource

I am having a small problem with my PHP MySQL Select. The function is inside of a PHP class. Here is the error I get:
Warning: mysql_fetch_array() expects parameter 1 to be resource,
integer given in C:\xampp\htdocs\include\database.php on line 59
Warning: extract() expects parameter 1 to be array, null given in
C:\xampp\htdocs\include\database.php on line 59
The function just simply updates the database to show what browser and OS they visited the site with. The function is called from another file that is called by an AJAX call that uses POST to send the data about the OS and browser that was gathered from a Javascript file. It only fails if there is an entry of the IP address already in the database. If there is no IP Address entry in the database it succeeds in creating one.
Here is my code:
function addStat($browser, $os){
$IE = 0; $Firefox = 0; $Safari = 0; $Opera = 0; $Chrome = 0; $otherb = 0;
$Windows = 0; $Linux = 0; $Mac = 0; $Android = 0; $iOS = 0; $otheros = 0;
$ql = 0; $totalVisits = 0;
$ip = ip2long($_SERVER['REMOTE_ADDR']);
$q1 = mysql_query("SELECT * FROM " . DB_STATS . " WHERE ip='$ip'", $this->connection);
if (mysql_num_rows($q1)==0){
$browser = mysql_real_escape_string($browser);
$os = mysql_real_escape_string($os);
switch($browser){
case "Internet Explorer":
$IE += 1;
break;
case "Firefox":
$Firefox += 1;
break;
case "Safari":
$Safari += 1;
break;
case "Opera":
$Opera += 1;
break;
case "Chrome":
$Chrome += 1;
break;
default:
$otherb += 1;
break;
}
switch($os){
case "Windows":
$Windows += 1;
break;
case "Mac OS X":
$Mac += 1;
break;
case "Linux":
$Linux += 1;
break;
case "Android":
$Android += 1;
break;
case "iOS":
$iOS += 1;
break;
default:
$otheros += 1;
break;
}
$q = $this->query("INSERT INTO " . DB_STATS . " VALUES (null, '$ip', '$Chrome', '$IE', '$Firefox', '$Opera', '$Safari', '$otherb', '$Windows', '$Mac', '$Linux', '$Android' , '$iOS' , '$otheros', 1)");
if ($q == true){
return(1);
}
else{
return(0);
}
}
else if (mysql_num_rows($q1)==1){
extract(mysql_fetch_array($ql));
switch($browser){
case "Internet Explorer":
$IE += 1;
break;
case "Firefox":
$Firefox += 1;
break;
case "Safari":
$Safari += 1;
break;
case "Opera":
$Opera += 1;
break;
case "Chrome":
$Chrome += 1;
break;
default:
$otherb += 1;
break;
}
switch($os){
case "Windows":
$Windows += 1;
break;
case "Mac OS X":
$Mac += 1;
break;
case "Linux":
$Linux += 1;
break;
case "Android":
$Android += 1;
break;
case "iOS":
$iOS += 1;
break;
default:
$otheros += 1;
break;
}
$totalVisits += 1;
$q = $this->query("UPDATE " . DB_STATS . " set Chrome='$Chrome', IE='$IE', Firefox='$Firefox', Opera='$Opera', Safari='$Safari', otherb='$otherb', Windows='$Windows', Mac='$Mac', Linux='$Linux', Android='$Android' , iOS='$iOS' , otheros='$otheros', totalVisits='$totalVisits'");
if ($q == true){
return(1);
}
else{
return(0);
}
}
else{
return(-1);
}
}
I hope everything made sense and that someone will help.
I see it now -- you used $ql (lower case L) when you intend to use $q1. Let this be a lesson against using very short variable names or very similar names.
// $ql was initialized to 0
$ql = 0; $totalVisits = 0;
// $q1 holds the result resource
extract(mysql_fetch_array($q1));
It is not advisable to call extract() on the output of mysql_fetch_array() unless you also specify the second parameter MYSQL_ASSOC as the fetch type. By default it returns both numeric and associative indices for each column.
extract(mysql_fetch_array($q1, MYSQL_ASSOC));
// Or better
extract(mysql_fetch_assoc($q1));
In general, I would probably advise against using extract() in most any situation, since it results in numerous variables dumped into the global namespace, in particular when you have done SELECT * without being specific about which columns are selected. Better to access them via their array:
$row = mysql_fetch_assoc($q1);
echo $row['browser'];

Where in the PHP source is the code for incrementing strings?

PHP has a feature where you can use increment operators on strings. It behaves similarly to an odometer, where once you reach the end of a range, it "rolls over".
<?php
$str = 'zy';
$str++;
echo "$str\n"; // zz
$str++;
echo "$str\n"; // aaa
Just curious where in the PHP source code this is. I often look in the source code at functions/extensions, but something like this I have no idea where to look.
A link to the file using their web based SVN would be awesome.
The implementation for this operator is conveniently located in zend_operators.c, in a function that's even more conveniently called increment_string():
static void increment_string(zval *str) /* {{{ */
{
int carry=0;
int pos=Z_STRLEN_P(str)-1;
char *s=Z_STRVAL_P(str);
char *t;
int last=0; /* Shut up the compiler warning */
int ch;
if (Z_STRLEN_P(str) == 0) {
STR_FREE(Z_STRVAL_P(str));
Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
Z_STRLEN_P(str) = 1;
return;
}
if (IS_INTERNED(s)) {
s = (char*) emalloc(Z_STRLEN_P(str) + 1);
memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1);
Z_STRVAL_P(str) = s;
}
while (pos >= 0) {
ch = s[pos];
if (ch >= 'a' && ch <= 'z') {
if (ch == 'z') {
s[pos] = 'a';
carry=1;
} else {
s[pos]++;
carry=0;
}
last=LOWER_CASE;
} else if (ch >= 'A' && ch <= 'Z') {
if (ch == 'Z') {
s[pos] = 'A';
carry=1;
} else {
s[pos]++;
carry=0;
}
last=UPPER_CASE;
} else if (ch >= '0' && ch <= '9') {
if (ch == '9') {
s[pos] = '0';
carry=1;
} else {
s[pos]++;
carry=0;
}
last = NUMERIC;
} else {
carry=0;
break;
}
if (carry == 0) {
break;
}
pos--;
}
if (carry) {
t = (char *) emalloc(Z_STRLEN_P(str)+1+1);
memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str));
Z_STRLEN_P(str)++;
t[Z_STRLEN_P(str)] = '\0';
switch (last) {
case NUMERIC:
t[0] = '1';
break;
case UPPER_CASE:
t[0] = 'A';
break;
case LOWER_CASE:
t[0] = 'a';
break;
}
STR_FREE(Z_STRVAL_P(str));
Z_STRVAL_P(str) = t;
}
}
/* }}} */

how to optimise this code?

I have a solution to the below problem in PHP.
But it is taking too much time to execute for 10 digit numbers. I want to know where am I going wrong ?
I am new to dynamic programming .Can someone have a look at this ?
Problem
In Byteland they have a very strange monetary system.
Each Bytelandian gold coin has an integer number written on it. A coin n
can be exchanged in a bank into three coins: n/2, n/3 and n/4.
But these numbers are all rounded down (the banks have to make a profit).
You can also sell Bytelandian coins for American dollars. The exchange
rate is 1:1. But you can not buy Bytelandian coins.
You have one gold coin. What is the maximum amount of American dollars
you can get for it?
========================================================
<?php
$maxA=array();
function exchange($money)
{
if($money == 0)
{
return $money;
}
if(isset($maxA[$money]))
{
$temp = $maxA[$money]; // gets the maximum dollars for N
}
else
{
$temp = 0;
}
if($temp == 0)
{
$m = $money/2;
$m = floor($m);
$o = $money/3;
$o = floor($o);
$n = $money/4;
$n = floor($n);
$total = $m+$n+$o;
if(isset($maxA[$m]))
{
$m = $maxA[$m];
}
else
{
$m = exchange($m);
}
if(isset($maxA[$n]))
{
$n = $maxA[$n];
}
else
{
$n = exchange($n);
}
if(isset($maxA[$o]))
{
$o = $maxA[$o];
}
else
{
$o = exchange($o);
}
$temp = max($total,$m+$n+$o,$money);
$maxA[$money]=$temp; //store the value
}
return $temp;
}
$A=array();
while(1)
{
$handle = fopen ("php://stdin","r");
$line = fgets($handle);
if(feof($handle))
{
break;
}
array_push($A,trim($line));
}
$count =count($A);
for($i=0;$i<$count;$i++)
{
$val = exchange($A[$i]);
print "$val \n";
}
?>
Here a reformatted version of the code for the ones (like I) who could understand the above. It doesn't improve anything.
function exchange($money) {
static $maxA = array(0 => 0);
if (isset($maxA[$money])) {
return $money;
}
$m = floor($money/2);
$o = floor($money/3);
$n = floor($money/4);
$total = $m+$n+$o;
if (isset($maxA[$m])) {
$m = $maxA[$m];
} else {
$m = exchange($m);
}
if (isset($maxA[$n])) {
$n = $maxA[$n];
} else {
$n = exchange($n);
}
if (isset($maxA[$o])) {
$o = $maxA[$o];
} else {
$o = exchange($o);
}
return $maxA[$money] = max($total, $m + $n + $o, $money);
}
I still have my code from this problem. But it's in c++. It's by no means the most efficient, but it passed. It might not be too hard to port to php.
#include <cstdio>
#include <queue>
using namespace std;
unsigned long results;
queue to_test;
int main()
{
char tmp_val[30];
unsigned long coin_value = 1;
while (coin_value)
{
scanf("%s", tmp_val);
coin_value = 0;
results = 0;
for (int w = 0; tmp_val[w] != '\0'; w++)
{
coin_value *= 10;
coin_value += tmp_val[w] - 0x30;
}
if (coin_value != 0)
{
to_test.push(coin_value);
while(!to_test.empty())
{
unsigned long tester = to_test.front();
to_test.pop();
unsigned long over2 = tester/2;
unsigned long over3 = tester/3;
unsigned long over4 = tester/4;
if (tester < over2 + over3 + over4)
{
to_test.push(over2);
to_test.push(over3);
to_test.push(over4);
}
else
{
results += tester;
}
}
printf("%lu\n", results);
}
}
}

Categories