PHP Add Leading Zeros based on query array - php

I am trying to add leading zeros to all skus in my table. I need every sku to have a 3 digit number in front of it. For 1-9 skus would be 001$row['sku'], 002$row['sku'], 009$row['sku'], 010$row['sku'], 011$row['sku'],...etc I am using $n=sizeof($row). But every time I echo this out I get 22 skus (which there are about 50) and only returns the first letter of the sku. I don't understand how to fix this, I am trying to build an array from my query to determine how many skus there are in order to add leading zeros. Any help is much appreciated.
$result = mysql_query("SELECT * FROM temp_table WHERE po='ABCD'");
$row = mysql_fetch_array($result);
for ($i=0, $n=sizeof($row); $i<$n; $i++) {
if ($i < 9) {
$Zeros="00";
}
elseif ($i < 99) {
$Zeros="0";
}
else{
$Zeros="";
}
$num=$i+1;
echo $Zeros.$num. "=" . $row[$i]['sku'] . "`<br />`";

You aren't looping through the resulting data set quite right, or I don't fully understand the situation.
Assuming you want to build a three-digit SKU based on each row's SKU, here's a better way:
// query the database
$result = mysql_query("SELECT * FROM temp_table WHERE po='ABCD'");
$count = 0;
// Loop through every row in the data result set
while ( $row = mysql_fetch_assoc( $result ) ){
$count++; // Increment SKU #
// Build integer SKU based on count of item in order and pad with zeros
$this_sku = str_pad( $count, 3, '0', STR_PAD_LEFT);
// Build onto integer SKU based on row data and pad with zeros
$this_sku .= str_pad( $row['sku'], 3, '0', STR_PAD_LEFT);
echo "This product SKU is $this_sku<br/>";
}

I don't fully understand the context, but it sounds as though you want to be using the str_pad function.
e.g.
$num1 = str_pad(1, 3, '0', STR_PAD_LEFT); // = 001
$num2 = str_pad(10, 3, '0', STR_PAD_LEFT); // = 010
// etc...

You are looking for the str_pad function.
example:
$num = str_pad($input, 4, "0", STR_PAD_LEFT);

The most elegant way is use sprintf() http://php.net/manual/en/function.sprintf.php
sprintf(%'0'3d=%d`<br />`, $num, $row[$i]['sku']);

Related

add value +1 in phrase number

I want to add value in phrase in database sql in database i save phrasr like this
DO-2500-01
DO-2500-02
now my question how can add +1 in last value like this DO-2500-03 / DO-2500-04
this my code
$getse = $DB_con->prepare("SELECT serial FROM `customer` WHERE user_add=:id ORDER BY serial DESC LIMIT 1");
$getse->execute(array(":id"=>$user_id));
$getse = $getse->fetch(PDO::FETCH_OBJ);
$addone = $getse->serial + 1;
echo $addone;
this is my code i get last serial and i want to add +1 for example last serial in database is DO-2500-04 I want to get this value and add +1 To become like this DO-2500-05
Split string, increase the last part and combine it back
$addone = explode('-', "DO-2500-04");
$addone[count($addone)-1] += 1;
// Append 0 if the last part less then 10
$addone[count($addone)-1] = str_pad($addone[count($addone)-1], 2, 0, STR_PAD_LEFT);
echo $addone = implode('-', $addone);
You can get this based on your requirement.
If DO-2500-99 should be DO-2501-00 then below code can work.
$serialArr= explode('-', $getse->serial);
$serialNo = (int)$serialArr [1].$serialArr [2];
$newSerialNo = $serialNo + 1;
$newSerialNo = substr($newSerialNo, 0, -2)."-".substr($newSerialNo , -2);
$newSerial = $serialArr[0].'-'.$newSerialNo;
If DO-2500-99 should be DO-2500-100 then below code can work.
$getse = 'DO-2500-99';
$serialArr= explode('-', $getse->serial);
$serialNo = (int)$serialArr [2];
$serialArr[2] = $serialNo + 1;
$newSerial = implode('-',$serialArr);
DO-2500-04 it's a String value and you cannot use arithmetic operators on it. If you just want last counter to get incremented, what you need to do is get the last value by splitting the string by -.
Then get the last value and increment it and then again join the array by -.
To split and join the array we can use explode() and implode().
This is how you can get the last value from string using explode()
$values=explode("-","DO-2500-04"); // $values is now array.
$lastvalue=(int)$values[2];
$lastvalue++;
if($lastvalue<9) {
$lastvalue = "0" . $lastvalue;
}
$values[2]=$lastvalue;
$incremented_string=implode("-",$values);
First parameter in explode denotes the chracter by you want to split the string same as first parameter in implode denotes the glue by you want to join the array.
http://php.net/manual/en/function.explode.php
http://php.net/manual/en/function.implode.php
Just for fun, you could do a lot of this in the SQL like:
$getse = $DB_con->prepare("SELECT serial,
LEFT(serial,8) AS serialBase,
SUBSTRING(serial,8) AS serialIdx
FROM `customer` WHERE user_add=:id
ORDER BY serial DESC LIMIT 1");
$getse->execute(array(":id"=>$user_id));
$getse = $getse->fetch(PDO::FETCH_OBJ);
$addone = $getse->serialBase + str_pad(($getse->serialIdx + 1),2,'0',STR_PAD_LEFT);
echo $addone;
Updated the SQL.

Strip down a number and return it every time minus the last digit

Let's say i have a number 1234567890 andi want to do some sort of loop that creates something usable in an MySQL query.
For example:
Number is 1234567890.
The usable part in the query should look like:
SELECT * FROM table WHERE column IN (1234567890, 123456789, 12345678, 1234567, 123456, 12345, 1234, 123, 12, 1)
breaking my head on this one so i hope someone can help me out.
Thank you very much in advance...
Is this what you want?
where '1234567890' like concat(column, '%') and length(column) > 0
$number = "1234567890"; // Has to be string
$array = array();
while( strlen($number) > 1 )
{
$array[] = $number;
$number = substr($number, 0, strlen($number)-1);
}
$strForMySQL = implode(",", $array); // would return "1234567890,123456789,12345678,........1"
$query = "SELECT * FROM table WHERE column IN (".$strForMySQL.")";
You could use substr to keep stripping the last character of the number with a loop. If you start with an integer, you will need to type cast this into a string for it to work.
$x=1234567;
$x=(string)$x;
for($i=0; $i<strlen($x); $i++){
//Write SQL here or store them in an array, print...etc.
echo substr($x, 0,strlen($x)-$i);
}

Generate an id with fixed alpha numeric string and variable integer part php

I am trying to generate an id with fixed alphanumeric part and a varying 3 digit numeric part.
That is, the id will look like:
LAB-SER-420316-1415-000
LAB-SER-420316-1415-001
...
LAB-SER-420316-1415-010
LAB-SER-420316-1415-020
...
LAB-SER-420316-1415-110
LAB-SER-420316-1415-210
.....
My task is to generate this id's only once, that is repeating id has to be avoided. Also once the page is loaded, it should generate single id.This is like giving a bill number or something like that. I've created a function to generate this string upto a limit. But I need it to generate everytime the page is loaded.
Code:
<?php
function generatebillno()
{
$saved="LAB-SER-420316-1415-";
for($count = 0; $count <= 999; $count++)
{
$var= str_pad($count, 3, '0', STR_PAD_LEFT);
return $saved.$var;
}
}
echo generatebillno();
?>
Can anyone help me to do this. I am stuck here..
try this -
//fetch the max id (the last digit as number)
$sql = $mysqli->query('select max(cast(substring(demo_field, 21) as unsigned)) as digit,
demo_field from demo');
$res = $sql->fetch_assoc();
//check for empty valyues
if (empty($res['demo_field'])) {
$str = "LAB-SER-420316-1415";
$res['digit'] = 0;
} else {
$str = substr($res['demo_field'], 0, 19);
}
$dig = $res['digit'] + 1;
//add padding if needed
$dig= str_pad($dig, 3, '0', STR_PAD_LEFT);
$newStr = $str.'-'.$dig;
var_dump($newStr);

I want to calculate the score of the characters in a sentence

I have a sentence as an input.
I want to be able to calculate the total score of a sentence (a=1, b=2, c=3), according to the letters that form each word.
Also, if a sentence has a double letter i want to double its value.
Finally, I want to filter out characters different from a-z.
Code (Edited)
$words = "Try to do this";
$letters = str_split($words);
$value = '0 a b c d e f g h i j k l m n o p q r s u v w x y z';
$value = explode(' ',$value);
$value1 = array_flip($value);
$result = array_intersect($letters, $value);
This is something I started but can't finish and I post it just to see if my logic is correct!
I reworked your code & think this will work as expected. I have edited this code so it can now account for double score items properly. Note that the $double_score_array has only single letters, but the regex has {2} to indicate that 2 letters in a row should be looked at. Comments are in place to explain each stage:
// Set the '$words' string.
$words = "Try to do thiis.";
// Set an array for double score items.
$double_score_array = array('i');
// Init the '$raw_results' array
$raw_results = array();
// Create a '$value_array' using the range of 'a' to 'z'
$value_array = range('a','z');
// Prepend a '0' onto the '$value_array'
array_unshift($value_array, 0);
// Flip the '$value_array' so the index/key values can be used for scores.
$value_array_flipped = array_flip($value_array);
// Filter out any character that is not alphabetical.
$words = preg_replace('/[^a-zA-Z]/', '', strtolower($words));
// Let's roll through the double score items.
foreach ($double_score_array as $double_score_letter) {
preg_match('/' . $double_score_letter . '{2}/', $words, $matches);
$double_score_count = count($matches);
// With double score items accounted, let's get rid of the double score item to get normal scores.
$words = preg_replace('/' . $double_score_letter . '{2}/', '', $words);
}
// Split the '$words' string into a '$letters_array'
$letters_array = str_split($words);
// Now let's set the value for the double score items.
$raw_results[] = (($value_array_flipped[$double_score_letter] * 2) * $double_score_count);
// Roll through the '$letters_array' and assign values.
foreach ($letters_array as $letter_key => $letter_value) {
$raw_results[] = $value_array_flipped[$letter_value];
}
// Filter out the empty values from '$raw_results'.
$filtered_results = array_filter($raw_results);
// Run an 'array_sum()' on the '$filtered_results' to get a final score.
$final_results = array_sum($filtered_results);
// Echo the score value in '$final_results'
echo 'Score: ' . $final_results;
// Dump the '$filtered_results' for debugging.
echo '<pre>';
print_r($filtered_results);
echo '</pre>';
EDIT In the comments the original poster states that the code above does not double the score. Unclear about that since—as per the example—the letter i is the 9th letter of the alphabet. So the score would be 9. So wouldn’t double score be 18? Or so you mean it should be 36 meaning double the score of the two individual i items?
If “double score” actually means taking the score of the two individual items & doubling it, then simply go to this portion of the code:
// Now let's set the value for the double score items.
$raw_results[] = (($value_array_flipped[$double_score_letter] * 2) * $double_score_count);
And change the 2 to 4 like so to effectively double the score of double letter ietms:
// Now let's set the value for the double score items.
$raw_results[] = (($value_array_flipped[$double_score_letter] * 4) * $double_score_count);
ANOTHER EDIT Okay, I think I understand the original posters request. Specifically when they ask, “Also, if a sentence has a double letter i want to double its value.” Which I—and others interpreted as two letters in a row such as ii, but seems that if those two letters show up in a sentence only then would the score be doubled. So I reworked the logic to account for any two instances of i showing up in a sentence. And since it’s unclear what should happen if more than 2 i’s show up in a sentence, I set logic to account for cases like that; those extra i’s just get a single value. Adding my new version. Compare & contrast with the first version above. You should now be able to do whatever you need to.
// Set the '$words' string.
$words = "Try to do thiiis.";
// Set an array for double score items.
$double_score_array = array('i');
// Set a double score multiplier.
$double_score_multiplier = 2;
// Init the '$raw_results' array
$raw_results = array();
// Create a '$value_array' using the range of 'a' to 'z'
$value_array = range('a','z');
// Prepend a '0' onto the '$value_array'
array_unshift($value_array, 0);
// Flip the '$value_array' so the index/key values can be used for scores.
$value_array_flipped = array_flip($value_array);
// Filter out any character that is not alphabetical.
$words = preg_replace('/[^a-zA-Z]/', '', strtolower($words));
// Let's roll through the double score items.
$double_score_count = $non_double_count = 0;
foreach ($double_score_array as $double_score_letter) {
$double_score_regex = sprintf('/%s{1}/', $double_score_letter);
preg_match_all($double_score_regex, $words, $matches);
$count = count($matches[0]);
// We only want to double the score for the first two letters found.
if ($count >= 2) {
$double_score_count = 2;
}
// This handles the accounting for items past the first two letters found.
$non_double_count += ($count - 2);
// This handles the accounting for single items less than the first two letters found.
if ($count < 2) {
$non_double_count += $count;
}
// With double score items accounted, let's get rid of the double score item to get normal scores.
$words = preg_replace($double_score_regex, '', $words);
}
// Split the '$words' string into a '$letters_array'
$letters_array = str_split($words);
// Now let's set the value for the double score items.
if ($double_score_count > 0) {
$raw_results[] = (($value_array_flipped[$double_score_letter] * $double_score_multiplier) * $double_score_count);
}
// And get the values of items that are non-double value.
if ($non_double_count > 0) {
$raw_results[] = $value_array_flipped[$double_score_letter] * $non_double_count;
}
// Roll through the '$letters_array' and assign values.
foreach ($letters_array as $letter_key => $letter_value) {
$raw_results[] = $value_array_flipped[$letter_value];
}
// Filter out the empty values from '$raw_results'.
$filtered_results = array_filter($raw_results);
// Run an 'array_sum()' on the '$filtered_results' to get a final score.
$final_results = array_sum($filtered_results);
// Echo the score value in '$final_results'
echo 'Score: ' . $final_results;
// Dump the '$filtered_results' for debugging.
echo '<pre>';
print_r($filtered_results);
echo '</pre>';
// Input string
$str = 'Try to do this';
// Remove irrelevant characters, convert to lowercase
$str = preg_replace('/[^a-z]/', '', strtolower($str));
// Create a function to determine the value of a character
function my_char_value($char) {
return ord($char) - 96;
}
// Convert the string to an array and apply our function to each element
$arr = array_map('my_char_value', str_split($str));
// Add each array element to determine subtotal
$sum = array_sum($arr);
// Double the sum if two "i"s are present in the string
if (preg_match('/i.*?i/', $str)) {
$sum *= 2;
}
print $sum;
I have found out a better solution
Check this code out
<?php
/**
* Script to calculate the total score of a sentence (a=1, b=2, c=3), according to the letters that form each word.
* Also, if a sentence has a double letter i want to double its value.
* Finally, I want to filter out characters different from a-z.
*
* Author: Viswanath Polaki
* Created: 5-12-2013
*/
//array to define weights
$weight = array(
'a' => 1,
'b' => 2,
'c' => 3,
'd' => 4,
'e' => 5,
'f' => 6,
'g' => 7,
'h' => 8,
'i' => 9,
'j' => 10,
'k' => 11,
'l' => 12,
'm' => 13,
'n' => 14,
'o' => 15,
'p' => 16,
'q' => 17,
'r' => 18,
's' => 19,
't' => 20,
'u' => 21,
'v' => 22,
'w' => 23,
'x' => 24,
'y' => 25,
'z' => 26
);
//your sentance
$sentance = "My name is Viswanath Polaki. And my lucky number is 33";
$asentance = array();
$strlen = strlen($sentance);
//converting sentance to array and removing spaces
for ($i = 0; $i < $strlen; $i++) {
if ($sentance[$i] != " ")
$asentance[] = strtolower($sentance[$i]);
}
$sumweights = array();
//calculation of weights
foreach ($asentance as $val) {
if (key_exists($val, $weight)) {
$sumweights[$val] += $weight[$val];
} else {
$sumweights['_unknown'][] = $val;
}
}
ksort($sumweights);//sorting result
echo "<pre>";
print_r($sumweights);
echo "</pre>";
?>
How about:
function counter($string) {
// count the number of times each letter occurs, filtering out anything other than a-z
$counts = array_count_values(
str_split(
preg_replace('/[^a-z]/iS', '', strtolower($string))
)
);
// convert the counts to Caeser ciphers (a => 1, aa => 2, bb => 4, etc.)
array_walk(
$counts,
function (&$value, $letter) {
$value = $value * (ord($letter) - 96);
}
);
// sum up the encodings
$sum = array_sum($counts);
// if there's a double i, double again
if (preg_match('/ii/iS', $string)) {
$sum *= 2;
}
return $sum;
}
Test cases
echo counter("i"); // = 9
echo counter("ii"); // = 36
echo counter("abc0"); // = 6
echo counter("aabc0"); // = 7
echo counter("aabbcc00"); // = 12
echo counter("Try to do this"); // = 173

Awkward criteria when generating random sequence

What I need to do to generate a sequence of non-repeating integers within a given range that meets the specific criteria that I have?
Here are the criteria:
Use only the numbers between 1 and MAX (let's say 9).
Numbers cannot repeat within the sequence except:
2a. Two of the first 5 numbers from the sequence must be repeated.
2b. These two numbers must be repeated at random points within the last 5 places in the final sequence (the last 5 includes the repeats).
For example:
SET: 1,2,3,4,5,6,7,8,9
Random Sequence (with repeats):
2,4,6,9,3,1,5,2,8,7,3
r, , , ,r, , ,x, , ,x
Here I have indicated the numbers that were randomly selected to be repeated (out of the first 5 in the random sequence) with an r and the insertion points where they were randomly placed (into the last 5 of the final sequence) with an x.
Any help in figuring this out is much appreciated. Actual use will be a bit more complicated than this, but I know what I will need to do once I can get this far.
Edit
To clarify a little more, I have 1-20, and I need a 22 digit random sequence. Every number must be used, two will be used twice as discussed in my original post. I chose 10 above to simplify a little. I should be able to adapt the logic you've all given.
I assume when you say "non-repeating" you mean "distinct" (unique) as opposed to "eventually becomes periodic" (as in "the digits of pi do not repeat")
Generate n distinct integers in your range.
Pick two from the first 5. Call these a and b.
Remove the last 3 from the list.
Insert a at position 0, 1, 2, or 3 in the sublist.
Insert b at position 0, 1, 2, 3, or 4 in the sublist.
Add the sublist back to the end of the list.
Removal of the sublist is not necessary but makes it easier to conceptualize.
Not obvious what to do if n+2 is less than 10. In particular, this algorithm may crash for n < 5 and return the wrong result for n=7.
If I understand you correctly, you have 1 to N random numbers that must be used in a 10-set permutation with some specific criteria about repeats. In php, I suggest this (not counting php-internals) O(n) solution:
//Generate a full list of keys
$source = range(1, MAX);
//NOTE: if MAX < 10, you must pad the array
//Get a random group of 10 of the keys
$input = array_rand(array_flip($source), 10);
//Shuffle (can be done later as well; this is the randomization).
//array_rand() does not change order.
shuffle($input);
//Select the first of 5 that must be repeated in the last 5
$one = rand(0, 4);
$onev = $input[$one];
//Remove this array key to prevent collisions with the second of 5
$input = array_diff($input, array($onev));
//Select a random index in the last 5 to be replaced with $one
$rep = rand(5, 9);
$repv = $input[$rep];
//Remove this array key to prevent collisions with the other to-be-replaced
$input = array_diff($input, array($repv));
//Acquire the new keys list of input now that two elements have been removed
$keys = array_slice(array_keys($input), 0, 3);
//Select the second-of-5 to replace in the last 5. No worry of collision now.
$two = array_rand($keys, 1);
$two = $keys[$two];
//Select the second from the last-of-5 to be replaced by $two
//No worry of collision because the other index is removed.
$keys = array_slice(array_keys($input), 4, 8);
$rept = array_rand($keys, 1);
$rept = $keys[$rept];
//Replace one of the last-of-five with one of the first-of-five
$input[$rept] = $input[$two];
//Restore removed keys as well as perform replacement of other last-of-five
$input[$one] = $onev;
$input[$rep] = $onev;
//re-randomize based on shuffle
ksort($input);
No loops, no conditionals.
A word of warning on this solution. I wouldn't use it for a large set of numbers. If I were doing this same solution for a much larger set, I would use array_splice to drop chosen members from the array. As you get a much larger space, finding an unused number in your range becomes quite expensive, and demands a better solution than the brute force method below.
This will build half of your target set. You will call it twice, once for each half.
function build_half($min, $max, $num_elements, $arr = array() ){
while( count($arr) <= $num_elements)
{
$candidate = rand($min, $max);
if( !in_array($candidate, $arr))
{
array_push($arr, $candidate);
}
}
return $arr;
}
This will grab $this_many elements from the array.
function random_grab($arr, $this_many){ // don't try this on the subway
$nums_to_repeat = array();
// catch some edge cases...
if( $this_many > count($arr) )
{
return FALSE;
}
else if( $this_many == count($arr) )
{
return shuffle($arr);
}
while( count($nums_to_repeat) <= $this_many)
{
$rand_key = rand(0, count($arr) - 1);
if( ! in_array($arr[$rand_key], $nums_to_repeat))
{
array_push($nums_to_repeat, $arr[$rand_key]);
}
}
return $nums_to_repeat;
}
This is a fairly specialized case, but could be made more general by allowing the offset floor and ceiling to be passed in as parameters. For your problem they would be 5 and 9, so we just derive them directly.
function random_insert_2nd_half($target, $source){
$offsets_consumed = array();
$num_elements = count($target);
while( count($source) > 0 )
{
$offset = rand( ($num_elements/2), $num_elements - 1);
if( ! in_array( $offset, $offsets_consumed)
{
$arr[$offset] = array_pop($nums_to_repeat);
}
}
}
Ok so after having done all that, let's put it to work.
// Generate the first half of the array
$my_array = $repeated_nums = array();
$my_array = build_half(1, 10, 5);
// then grab the 2 random numbers from that first half.
$repeated_nums = random_grab($my_array, 2);
// So now we have our random numbers and can build the 2nd half of the array.
// we'll just repeat the call to the first function.
$my_array = build_half(1, 10, 5, $my_array);
// Then swap out two of the values in the second half.
$my_array = random_insert_2nd_half($my_array, $repeated_nums);
// at this point $my_array should match what you are looking for.
Hope this gets you on your way:
$max = 20; // max value
$repeats = 2; // numbers to be repeated
$nums = range(1, $max);
shuffle($nums);
$halfPoint = ceil($max / 2);
$firstHalf = array_slice($nums, 0, $halfPoint);
$repeaters = array_intersect_key($firstHalf, array_flip(array_rand($firstHalf, $repeats)));
$secondHalf = array_merge(array_slice($nums, $halfPoint), $repeaters);
shuffle($secondHalf);
$result = array_merge($firstHalf, $secondHalf);
var_dump(join(',', $result));
To generate distinct numbers within a range you can use something like this:
$arr_num = array();
while(count($arr_num)<=7)
{
$num = rand(1, 9);
if (!in_array($num, $arr_num))
{
$arr_num[] = $num;
}
}
$arr_num now has 8 distinct elements. Pick five elements of the array:
for ($i=0; $i<=4; $i+=1)
{
$new_arr[$i] = $arr_num[$i];
}
Now pick two numbers from $new_arr numbers:
$r1 = array_rand($new_arr);
$r2 = array_rand($new_arr);
Now you can insert these numbers into the original array at two of the last random positions. Hope it helped!
$max = 15;
$array = array(1, $max);
for($x = 1; $x <= $max; $x++)
{ $array[$x] = rand(1, $max); }
$firstDup = $array[rand(1,5)];
$secondDup = $firstDup;
do { $firstDup = $array[rand(1,5)];
} while($firstDup == $secondDup);
do { $array[rand($max-5,$max)] = $firstDup;
} while(!in_array($firstDup,array_slice($array,$max-5,5)));
do { $array[rand($max-5,$max)] = $secondDup;
} while(!in_array($secondDup,array_slice($array,$max-5,5)));

Categories