Split SMS gateway answer in PHP [closed] - php

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 1 year ago.
Improve this question
I am wondering what other approaches you would take to do some simple string splitting in PHP. I am receiving a response from a SMS gateway where two of the interesting values are the code used and the users text message.
The code could be something like: Freetrip (lowercase, uppercase, mixed case)
The user message should in the best case scenario be e.g. like: Freetrip 12345 ($code "space" XXXXX).
Each X should be a digit between 1 and 5. Any other value/character should return an error. So the regex would be simplified as: chars=5 where each digit >=1 and <=5.
What I need to store at the end would be each of the 5 digits values.
My simplest approach would be to lowercase the entire message string and subtract the also lowercased code (plus the space) from the message string. That would leave me with the 5 digits which I would then split into 5 unique variables to store in the DB.
Now the tricky part is that the best case scenario described above may be hard to achieve. Typing a SMS is fiddly and typing errors occur easily. Some errors that may occur are the following:
Too few or many digits.
Non-digits characters.
More characters after the XXXXX combination.
Probably some other cases.
Any of those should return an individual error message which I can return to the sender.

if (!preg_match('/^freetrip\s+([1-5]{5})$/i', $sms, $matches)) exit("error");
print_r($matches);
I had some experience with SMS-platforms and AFAIK one error is enough. We tried to detect similar characters like small L and big I etc, or zero and O-letter. For example in your case you could write something like this:
preg_match('/^freetr[il1|]p\s+([1-5]{5})$/i', $sms, $matches);
the same you can do in any place of message pattern (if you want).
I did something like this (not sure - it was 5 years ago):
if (!preg_match('/^(\w+)\s+(.*)/i', $sms, $matches)) exit('bad message format');
$value = $matches[2];
// some letters look like digits
$value = str_replace(array('o', 'O'), 0);
$value = str_replace(array('i', 'I', 'l'), 1);
if (!preg_match('/^[12345]{5}/')) exit("invalid code");
// do something here... message is OK.
Sure in this case you can check "freetrip" or not, value is [1-5]{5} or not etc, and response your error as much as allows your imagination :). Good luck.
EDIT: The last one is updated and should fit your case. It's better, because it will be very simple to create another service on it's example if you'll need it.

You could do something like that:
$code = 'Freetrip';
if (strlen($input) <= strlen($code)) {
// too short
} elseif (!preg_match('/^'.preg_quote($code, '/').'(.*)/i', $input, $match)) {
// wrong code
} else {
$x = (int)trim($match[0]);
if ($x < 11111) {
// too small
} elseif ($x > 55555) {
// too large
} else {
// valid
}
}

Related

Can regex be used to validate numbers OUTSIDE a range of specific numbers?

I have referred to several SO webpages for the answer to my question, but I keep reading that regex should not be used for validating numbers which are less than or greater than a certain range. I want to ensure that a user enters numbers within the following ranges: 11--20 and 65-100. Anything less than 11 will not be allowed, anything between 21 and 64 will not be allowed and anything from 101 above will not be allowed. I realize I can write something like
if ($num <=10 and $num >= 21 and $num <=64 and $num >=101) {
$num = "";
$numErr = "Number must be within specified ranges";
}
But what I really want is to use regex to preclude the range of numbers I do not want from being entered but I have not seen any satisfactory answers on SO. Can someone please help?
The regex would be less readable but like
/^(1[1-9]|20|6[5-9]|[7-9][0-9]|100)$/
Regex Demo

Can't validate numbers in my string

I need to check that a string
contains only digits and
the first digit is 0, and
the whole string has at least 8 digits and maximum 25
I have tried this, but it doesn't work:
if (!preg_match('/^[0][0-9]\d{8-25}$/', $ut_tel))
Try this regex:
/^0\d{7,24}$/
It seemed to work here.
Use this regex pattern
^(0[0-9]{7,24})$
Demo
If I was you, I'd do each check separately. This way you won't have issues in the future, should you decide to remove one of them or add additional checks.
(Note to all potential downvoters: I realize the question asked for a regex way, but since that was already provided in other answers - I think it is good to have a different approach as an answer as well.)
function validateNumber($number){
if(!is_numeric($number))
return false;
if(strlen($number)>25 || strlen($number)<8)
return false;
if(substr($number, 0, 1) != 0)
return false;
return true;
}
var_dump(validateNumber('0234567')); // shorter than 8
var_dump(validateNumber('02345678')); // valid
var_dump(validateNumber('12345678')); // doesn't start with 0
var_dump(validateNumber('02345678901234567890123456')); // longer than 25

Probability of a random variable [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I really feel ashamed to ask this question however I don't have time for revision. Also not a native English speaker, so excuse my lack of math vocabulary.
I am writing a program that requires assigning probabilities to variables then selecting one randomly.
Example:
Imagine that I have I coin, I would like to assign the probably of 70% to heads and 30% to tails. When I toss it I would like to have 70% chance that the heads appears and 30% tails.
A dumb way to do it is to create an array of cells insert the heads 70 cells and the tail in 30. Randomize them and select one randomly.
Edit 1: I also would like to point out that I am not limited to 2 variables. For example lets say that I have 3 characters to select between (*,\$,#) and I want to assign the following probably to each of them * = 30%, \$ = 30%, and # = 40%.
That's why I did not want to to use the random function and wanted to see how it was done mathematically.
You want another way to do it? Most rand functions produce a decimal from [0, 1). For 30%, check produced number is less than 0.3
Though note, if you actually test the perceived "randomness", it's not really random..
In PHP, you can use rand(0, 99) (integer instead of double, 30 instead of 0.3). PHP rand function is a closed interval (both inclusive)
function randWithWeight($chanceToReturnTrue) { // chance in percent
return rand(0, 99) < $chanceToReturnTrue;
}
Edit: for the note about perceived randomness. Some math since you say you're coming from math... Generate numbers from 0-99, adding them to an array. Stop when the array contains a duplicate. It usually takes about ~20 passes (I'm getting 3-21 passes before duplicate, 10+ tries). So it's not what you'd expect as "random". Though, (I know I'm going off track), take a look at the birthday problem. It is "more random" than it seems.
Here is a simple function to calculate weighted rand:
<?php
function weightedRand($weights, $weight_sum = 100){
$r = rand(1,$weight_sum);
$n = count($weights);
$i = 0;
while($r > 0 && $i < $n){
$r -= $weights[$i];
$i++;
}
return $i - 1;
}
This function accepts an array. For example array(30,70) will have 30% chance getting 0 and 70% chance getting 1. This should work for multiple weights.
Its principle is to subtract the generated random number by the weight until it gets less than or equal to zero.
Demo with 30%:70%
Demo with 20%:30%:50%
If you want 30% probability just do
if(rand(1,100) <= 30){
// execute code
}
One way would be
$r=rand(1,100);
if($r<70)
{
echo "Head";
}
else
{
echo "Tail";
}

encrypt string to numbers in php [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert a string to number and back to string?
I have a string that looks like:
AhgRtlK==
and I need to be able to encrypt and decrypt this string into numbers that might look like this:
1275653444
It's like phone charge credit (some thing like that)
EDIT :
i want to create some thing like mobile charge credit that contains value of credit card
but encrypted
I don't think you understand the problem well enough to ask the right question. To the extent I understand what you're saying, it's not well thought out. Suppose some code meant a credit of $500. Well, it would always mean that, today, tomorrow, and forever, even after I spent some of it.
So you don't want codes that decrypt to values. You want codes that identify unique accounts that have balances. (There are great algorithms to do that, and they're generally based on HMACs.)
You can just use the ascii value to convert a string into a number:
$integer = '';
foreach (str_split($string) as $char) {
$integer .= sprintf("%03s", ord($char));
}
return $integer;
To convert it back you can use this:
$string = '';
foreach (str_split($integer, 3) as $number) {
$string .= chr($number);
}
return $string;

Divide amount by characters present in string, found via regex

Suggestions for an updated title are welcome, as I'm having trouble easily quantifying what I'm trying to do.
This is a web-based form with PHP doing the calculations, though this question probably has an algorithmic or language agnostic answer.
Essentially, there is an Amount field and a Charge Code field.
The Charge code entered represents a short-hand for several 'agents' to whom the Amount is divided by. Most cases are single letters, however there are a couple cases where this varies, and gives a bit of trouble.
Basically, A = AgentType1, J = AgentType2, L = AgentType3, and as paperwork and user requirements would have it, "A2" is also a valid replacement for "J".
So an amount of 50 and a Charge Code of "AJ" would result in the Amount being divided by 2 (two agents) and dispersed accordingly. The same for a string like "AA2".
I have currently set up process (that works) that goes like this:
Divide = 0;
RegEx check for AgentType1 in Charge Code:
Divide++;
Set This-AgentType-Gets-Return;
RegEx check for AgentType2 in Charge Code:
Devide++;
Set This-AgentType-Gets-Return;
... etc ...
Then I divide the Amount by the "Divide" amount, and the result gets divvied up to each AgentType present in the Charge Code.
I know there must be an easier/simpler way to implement this, but it's not coming to me at the moment.
Is there a way to quickly derive the number of AgentTypes involved in the Charge Code, and which they are?
I would probably just do something simple like this:
$valid_codes = array('A', 'J', 'L');
// deal with the special A2 case first, to get it out of the string
// this code could be generalized if more special cases need to be handled
if (stripos($charge_code, 'A2') !== FALSE)
{
$found['J'] = true;
str_ireplace('A2', '', $charge_code);
}
foreach ($valid_codes as $code)
{
if (stripos($charge_code, $code) !== FALSE) // if the code was in the string
{
$found[$code] = true;
}
}
Now you can get the number you need to divide amount by with count($found), and the codes you need to divide between with array_keys($found).
Can you change the charge code field to an array of fields? Something like:
<input type="hidden" name="agent[]" value="A" />
for all your agents would let you do:
$divide = count($_POST["agent"]);
foreach($_POST["agent"] as $agent) {
$sum = $_POST["amount"] / $divide;
//do other stuff
}
Couldn't you match the string by something like this regex
^([A-Z]\d*)*$
and then work through the generated match list? The divisor would just be the length of this list (perhaps after removing duplicates).
For mapping symbols to Agents (why AgentTypes?), you could use a simple associative list, or a hashmap (I don't know what kind of constructs are easiest available in PHP).

Categories