Regex Number reservations - php

Good afternoon, I am creating a form with a number reservation field, for the user to pick. The system i had would only allow the reservation number by number, example: 1,2,3 and it would book the numbers 1,2 and 3.
Now i would like to add the option to book several numbers at once, example: 1-5,9,10and in this case it would book numbers 1 to 5, 9 and 10.
I'm using the following regex code, but it's not working as I want
^\d{1,5}(?:-\d{1,5})*(?:,\d{1,5})*(?:,\d{1,5}-\d{1,5})*(?:-\d{1,5},\d{1,5})*$
The problem with this code is whenever the user inserts two 1-3,4-6 it only allows one more number. For example 1-3,4-6,2,3 shows error when the ,3 is inserted.
There is also a problem where it allows to write several dashes without commas
example 1-3-6-8-9

perhaps something like this:
\A\d{1,5}(?:-\d{1,5})?(?:,\d{1,5}(?:-\d{1,5})?)*\z
The idea:
the range is optional (?:-\d{1,5})? (and follows the first number)
The group, that contains a comma followed by a number or a range, can occur zero or more times
Note that a problem can't be solved by regex since 6-4 or 1-5,2,3,4 are always possible. So you will need sooner or later to explode the string and to check if numbers and ranges are coherent.

Related

From 6 random numbers calculate random three-digit number?

I have 4 years PHP and C# experience, but Math is not my better side.
I thnik that i need in this project use some math algorithms.
When page load I need randomly create 7 numbers, 6 are numbers that I can use to calculate given three digit number:
rand 1-9
rand 1-9
rand 1-9
rand 1-9
rand 10-100 //5 steps
rand 10-100 //5 steps
and given number to calculate is 100-999,
I can use this operations: +, -, /, *, (, )
What is best algorithm for this?
I probably need to try all possible combinations with this 6 numbers to calculate given number or closest number of calculations.
example:
let say that given three digit number is
350, and I need to calculate this number from this numbers:
3,6,9,5 10, 100
so formula for this is:
(100*3)+(5*10) = 350
if is not possible to calculate exact number, than calculate closest.
You don't need to solve this problem completely, you can introduce me to solve this problem by paste some pseudo, or describing how to do that.
I have no actual experience that might help you with this, though since you're asking for some insight, I'll share my thoughts on how to do this.
As I typed my answer, I realised that this is in fact a knapsack problem, which means you can solve it to optimality using any algorithm that solves the knapsack problem. I recommend using dynamic programming to make your program run faster.
What you need to do is construct all numbers you can generate by combining two numbers with an operator, so that after this you have a list containing the numbers you started with, and the numbers you generated.
Then you solve the knapsack problem using the numbers as items with their value as their weight, and the number as the weight you can store at most.
The only thing that is slightly different is that you have an extra constraint that says that you may only use a number once. So you need to add into your implementation that if you add a combination of numbers, that you must remove the option of storing another combination that is constructed with the same number.
You could enumerate all the solutions by building "Abstract syntax trees", binary trees with the following informations :
the leaves are the 6 numbers
the nodes are the operations, for example a node '+' with the leaf '7' for left son and another node for right son that is 'x' with '140' for left son and '8' for right son would represent (7+(140*8)). Additionally, at each node you store the numbers that you already used (the leaves used in the tree), and the total.
Let's say you store all the constructed trees in the associative map TreeSets, but indexed by the number of leaves you use. For example, the tree (7+(140*8)) would not be stored directly in TreeSets but in TreeSets[3] (TreeSets[3] contains several trees, it is also a set).
You store the most close score in BestScore and one solution of the BestScore in BestSolution.
You start by constructing the 6 leaves (that makes you 6 different trees consisting of only one leaf). You save the closer number in Bestscore and the corresponding leaf in BestSolution.
Then at each step, you try to construct the trees with i leaves, i from 2 to 6, and store them in TreeSets[i].
You take j from 1 to i-1, you take each tree in TreeSets[j] and each tree in TreeSets[i-j], you check that those two trees don't use the same leaves (you don't have to check at the bottom of the tree since you have stored the leaves used in the node), if so you build the four nodes '+', 'x', '/', '-' with the tree from TreeSets[j] as left son and the tree from TreeSets[i-j] and store all four of them in TreeSets[i]. While building a node, you take the total from both tree and apply the operation, you store the total, and you check if it is closer than BestScore (if so you update BestScore and BestSolution with this new total and with the new node). If the total is exactly the value you were looking for, you can stop here.
If you didn't stopped the program by finding an exact solution, there is no such solution, and the closer one is in BestSolution at the end.
Note : You don't have to build a complete tree each time, just build the node with two pointers on other trees.
P.S. : You may avoid to enumerate all the solutions by using the dynamic programming approach, as Glubus said. In this case, it would consist, at each step (i) to remove some solutions that are considered sub-optimal. But with this problem I'm not sure that is possible (except maybe remove the nodes with a total of 0).

How to take off the phone extension from a number and put it in a separate column

I am currently working with an Oracle database trying to validate phone numbers within my PHP code. I have one column "PHONE 1" that contains a string phone number. This phone number may contain a leading country code "1" or a trailing phone extension (usually 4 digits). I need PHONE 1 to only contain the 10 digit phone number and then if it has country code or extension, I need to remove them and store them in separate columns which are currently empty within my Oracle database ("PHONE 1 COUNTRY CODE" and "PHONE 1 EXTENSION"). I have found a way to remove the leading country code, but I am not sure how to remove the trailing extension. I looked into possibly using the explode() function but cannot figure it out. Here is my code that I am using to remove the leading 1:
while($row=oci_fetch_array($array, OCI_ASSOC+OCI_RETURN_NULLS)){
//VALIDATE PHONE NUMBERS AND COUNTRY CODES
if(isset($row["PHONE 1"])){
if (strlen($row["PHONE 1"])>10){
$row["PHONE 1"] = preg_replace("/^1/", '',$row["PHONE 1"]);
$row["PHONE 1 COUNTRY CODE"]="1";
if(strlen($row["PHONE 1"])>10){
//insert code here that will remove the extension and add it to the column $row["PHONE 1 COUNTRY CODE"]
}
}
}
I think that using adding the second if statement within the other will be the easiest way to remove the extension. Essentially, this should say if there are more than 10 digits, remove the leading 1, and then if there are still more than 10 digits, remove the trailing extension. I just need to figure out how to code the latter. Any input on how to improve my current code or add the new one will be appreciated.
How you handle the phone numbers varies, depending on what you're starting with and what you want to end up with.
A good strategy for this type of problem is to "divide & conquer".
Divide your data into two groups - for example, those with extensions & those without.
Take the ones with extensions and divide them further, say into groups like "8005551212x100" (ie. with an 'x' denoting the extension) and others. Now you know how to handle the first group - split the string on the 'x', put the phone number into one column in your database and the extension into another. Now you have a few more phone numbers (with a variety formats, probably), but the extensions have been taken care of.
Methods for handling the phone numbers include:
explode - good for separating strings with clearly defined delimiters. Eg. explode("x", "8005551212x100") == array("8005551212", "100")
substr - good for strings where specific information appears at specific locations in the string. Eg. substr("8005551212",3,3) == "555"
regular expressions - can be good for variable data. Eg. for phone numbers where the extension is delimited by "x" or "ext" or "extension": preg_match("/^[0-9]+(x|ext|extension)[0-9]+$/", "8005551212ext100"). Be careful, though, to resist the temptation to write one regular expression that covers ALL types of numbers in your database - it's probably possible, but you're drive yourself crazy trying to write & debug an insanely long regular expression. That's why I suggest dividing your data up into groups of similar formats.

Select first or last character groups from string with period separators

I am asking help with php code to manipulate a string that I am retrieving from an SQL database. The string is in this format: Groups of 3-5 alphanumerics separated by periods. The number of alphanumeric groups in the string is quite variable (from 1 - 20 or more groups).
Example 1: J89.NEWTT.IIU.MZZ.OXI.
Example 2: ORD6.BAE.J89.DLH.YRL.N5500.W9700.NUGSM.N6500.
I need to do 2 things with these:
separate into a new string just the first 3 groups between periods (in Example 1, results would be "J89.NEWTT.IIU")
separate into a new string just the last 3 groups between periods (in Example 2, results would be "W9700.NUGSM.N6500")
I'm having trouble getting the usual players to work with this. Thanks for any help!
Split it (explode), slice out the parts you want, then join them back together with . again.
This is a strange format and picking the first/last three chunks seems really arbitrary. Is it structured data? If so, why are you storing it in a single field in your database?

Parsing input from user in any order or format

I am having some trouble trying to figure out how to parse information collected from user. The information I am collecting is:
Age
Sex
Zip Code
Following are some examples of how I may receive this from users:
30 Male 90250
30/M/90250
30 M 90250
M 30 90250
30-M-90250
90250,M,30
I started off with explode function but I was left with a huge list of if else statements to try to see how the user separated the information (was it space or comma or slash or hypen)
Any feedback is appreciated.
Thanks
It's easy enough. The ZIP code is always 5 digits, so a simple regex matching /\d{5}/ will work just fine. The Age is a number from 1 to 3 digits, so /\d{1,3}/ takes care of that. As for the gender, you could just look for an f for female and if there isn't one assume male.
With all that said, what's wrong with separate input fields?
You might want to use a few regular expressions:
One that looks for 5 numeric digits: [^\d]\d{5}[^\d]
One that looks for 2 numeric digits: [^\d]\d{2}[^\d]
One that looks for a single letter: [a-zA-Z]
[EDIT]
I've edited the RegExes. They now match every one of the presented alternatives, and don't require any alteration of the input string (which makes it a more efficient choice). They can also be run in any order.

How can I use regex to solve this?

I have two strings that I need to pull data out of but can't seem to get it working. I wish I knew regular expression but unfortunately I don't. I have read some beginner tutorials but I can't seem to find an expression that will do what I need.
Out of this first string delimited by the equal character, I need to skip the first 6 characters and grab the following 9 characters. After the equal character, I need to grab the first 4 characters which is a day and year. Lastly for this string, I need the remaining numbers which is a date in YYYYmmdd.
636014034657089=130719889904
The second string seems a little more difficult because the spaces between the characters differ but always seem to be delimited by at minimum, a single space. Sometimes, there are as many as 15 or 20 spaces separating the blocks of data.
Here are two different samples that show the space difference.
!!92519 C 01 M600200BLNBRN D55420090205M1O
!!95815 A M511195BRNBRN D62520070906 ":%/]Q2#0*&
The data that I need out of these last two strings are:
The zip code following the 2 exclamation marks.
The single letter 'M' following that. It always appears to be in a 13 character block
The 3 numbers after the single letter
The next 3 numbers which are the person's height
The following next 3 are the person's weight
The next 3 are eye color
The next block of 3 which are the person's hair color
The last block that I need data from:
I need to get the single letter which in the example appears to be a 'D'.
Skip the next 3 numbers
The last and remaining 8 numbers which is a date in YYYYmmdd
If someone could help me resolve this, I'd be very grateful.
For the first string you can use this regular expression:
^[0-9]{6}([0-9]{9})=([0-9]{4})([0-9]{4})([0-9]{2})([0-9]{2})$
Explanation:
^ Start of string/line
[0-9]{6} Match the first 6 digits
([0-9]{9}) Capture the next 9 digits
= Match an equals sign
([0-9]{4}) Capture the "day and year" (what format is this in?)
([0-9]{4}) Capture the year
([0-9]{2}) Capture the month
([0-9]{2}) Capture the date
$ End of string/line
For the second:
^!!([0-9]{5}) +.*? +M([0-9]{3})([0-9]{3})([A-Z]{3})([A-Z]{3}) +([A-Z])[0-9]{3}([0-9]{4})([0-9]{2})([0-9]{2})
Rubular
It works in a similar way to the first. You may need to adjust it slightly if your data is not exactly in the format that the regular expression expects. You might want to replace the .*? with something more precise but I'm not sure what because you haven't described the format of the parts you are not interested in.

Categories