PHP: Compare two sets of numbers, no dupes - php

I'm creating a lottery contest for my site, and I need to know the easiest way to compare numbers, so that no two people can choose the same numbers. It's 7 sets of numbers, each number is a number between 1 and 30.
For example, if user 1 chooses: 1, 7, 9, 17, 22, 25, 29 how can I make sure that user 2 can't choose those same exact number?
I was thinking about throwing all 7 numbers into an array, sort it so the numbers are in order, then join them into one string. Then when another user chooses their 7 numbers, it does the same, then compares the two. Is there a better way of doing it?

What you describe sounds like the best way to me, IF you are dealing with all submissions in the same script - I would trim(implode(',',$array)) the sorted array, store the resulting string in an array and call in_array() to determine whether the value already exists.
HOWEVER I suspect that what you are actually doing is storing the selections in a database table and comparing later submissions against this table. In this case (I am taking a liberty and assuming MySQL here but I would say it is the most common engine used with PHP) you should create a table with 7 columns choice_1, choice_2 ... choice_7(along with whatever other columns you want) and create a unique index across all seven choice_* columns. This means that when you try and insert a duplicate row, the query will fail. This lets MySQL do all the work for you.

Try array_diff. There are some really good examples on php.net.

Related

How to sort numbers containing current year in prefix

I am having trouble sorting the job numbers in my project.
My client requirement is to store the job numbers in the below format:-
current year-1, current year-2, current year-3, and so on...
For example:-
The current year is 2021 so the job number will be like this:-
21-1, 21-2, 21-3, 21-4, and so on...
When the year changes it should start again from 1 and so on for the next year.
For example:-
22-1, 22-2, 22-3, 22-4, and so on...
I had stored the job numbers in the above format successfully but I am unable to sort the job numbers in the correct way as required by the client.
I had sorted the data in this way:-
21-1, 21-10, 21-100 to 21-109, 21-11 to 21-19, 21-2 and so on...
but the actual sort should be like this:-
21-1, 21-2, 21-3, 21-4...21-10, 21-11 to 21-99, 21-100 to 21-199 and so on...
And if the year changes then:-
22-1, 22-2, 22-3, 22-4...22-10, 22-11 to 22-99, 22-100 to 22-199 and so on...
I hope I have explained my problem briefly. Please help me in sorting out the job numbers.
I assume you need the sorting to occur in your database because you're paging or just otherwise not holding all results in application memory, use use the following sql order by clause:
select my_column
from my_table
order by left(my_column, 2),
len(my_column),
right(my_column, len(my_column) - 2)
Explanation:
left(my_column, 2), numerically sort first two digits so years are grouped together.
len(my_column) group record sequence based on magnitude (i.e., xx-100 appears after xx-2 because it's longer).
right(my_column, len(my_column) - 2) numerically sort record sequence.
Hint: This assumes your year-code is always exactly two digits. I could have found the index of the dash instead, but that feels even more presumptive.
If you require an application-side (PHP) solution, you can use natsort. From W3Schools:
Definition and Usage
The natsort() function sorts an array by using a
"natural order" algorithm. The values keep their original keys.
In a natural algorithm, the number 2 is less than the number 10. In
computer sorting, 10 is less than 2, because the first number in "10"
is less than 2.
Syntax
natsort(array)
21-1, 21-10, 21-100, 1, 10, 100
These are your ids from the database. At first, declare an empty array and a variable for serial then loop through the objects. Push every object with two new keys array["date_serial"], array["serial"]. Then take the new array and then display the result by sorting the array by "serial" key or asc or desc order.

How to get sql result before and after a given result in array

I am completely perplexed as to how to do what I am attempting to do.
I have an mysql array of various numbers selected based on username. Each user will have different numbers. So an example of output would look similar to:
13
23
47
79
150
216
Again array is completely different and based entirely upon username. I am trying to determine how to get the number from the row before and the row after when I know a given number.
So for example if I know that one of the results in the array is 79, how would I determine the result before and the result after? Mind you I don't know number 79 is row 4, and I don't know the number before it is 47 nor do I know the number after is 150.
How could I get the results of the row before and after a given number?
Please avoid PDO answers if possible as I am just learning and mixing PDO and non-PDO code seems to create issues whenever I try.
This was one of those issues where I spent to long programming and I was overlooking the logical answer.
Logically I need to set a loop counter on the original array so that not only the number is returned, but also the row containing said number. If I knew that the number is 79, I should have also been able to determine that it was row 4, and because of that, set a variable for row 3 and row 5.
So the simple stupid answer to my retarded question was, use a loop counter when determining the number. :)

Generating unique fixed integer ids from array of ids

So here is the situation... I got array of objects, each marked with unique integer id, and for each and every combination of those objects, I need to create new ones, each with unique ids. Problem is that that list of objects is dynamic, used in stateless environment, so newly generated ids must be same for every run.
To make it clearer what I need here, consider that array of objects as array of their ids, for example: [10, 7, 23]. And basically, I need to get ids for all the possible combinations:
10, 7
10, 23
7, 23
10, 7, 23
What's important here is that generated ids must be same for each distinct combination (for example: 10 and 7 should always produce same id). Also, newly added objects should not affect previously generated ids. So for example, when some new object is later on added to that list, ids generated from previous combinations must remain the same as before new object was added.
Currently, I have a solution that pretty much comes down to generating new id as a result of the sum of combining ids, so resulting ids are:
17
33
30
40
Of course, this approach can produce duplicate ids, and that's the reason I'm asking for advice for some more sophisticated algorithm. I also tried introducing fixed offset of 1000 for newly generated ids and multiplying sum with number of objects in combination, so that for example resulting ids are 1034 (1000+(10+7)*2), 1066 (1000+(10+23)*2), etc., but I'm not sure that it would save me from duplicates. :)
Clear mention, I need this for the purpose of certain PHP project, but as this problem is not language-specific, I hope that there are some good mathematicians that can bring some good solution. :)
Useful information is fact that combining ids are in range from 10000-99999 and maximum number of items in combination does not exceed 10.
Please note that I do not need solution for how to make all the combinations from array elements, but only that "formula" for producing integer id.
Thanks in advance.
Not really sure what your aim is, but I'll have a go...
Have you tried using character keys? For example 10, 7, 3 becomes a sequence with an underscore. Each sequence will have a unique hash.
$arrayOfKeys = array(10, 7, 3);
$hash = implode('_', $arrayOfKeys);
print $hash;
# 10_7_3
Personally I'd go for this simple approach. If you're using a database and you're not producing, say, 100k records per day, it should be pretty fast using an indexed (primary key or unique) varchar field.
If you are to create numbers, here a tip: take the length of the largest number and that will be the prefix of your sequence, e.g.:
10, 5, 1 -> 2100501
105, 45, 201 -> 3105045201
The prefix will tell you what the length of the following sequences are. I can't think of any way you'd get doubles... Anyone? ;)
Hope it helps...
Step 1: Sort the values you get.
eg: if you get 10, 7 or 7, 10 it should result result in 7, 10 before going to the ID generator. If you know the range of your numbers i.e lets assume [0-100] use radix or count sort, will be fast.
Step 2 : Represent the numbers as strings, seperated by any chosen seperator.(':') maybe.
eg: for 7, 10 id will become "7:10".
Sorting is being done to avoid generating different ID's for 10, 7 and 7, 10.
BTW What do these numbers represent?
I don't think this is possible unless you allow labels of increasing length.
Assume you have a maximum of N distinct objects, corresponding to N distinct labels.
If you want to be able to represent all possible pairs, assuming order in a pair does not matter, you potentially need N.(N-1)/2 extra labels, whatever they are, and you need to reserve them all.
And for all triples, N.(N-1).(N-2)/6, for all quads N.(N-1).(N-2).(N-3)/24...
This grows exponentially and will very quickly exceed the capacity of integers.
Any other solution that tries to compress the space of labels, such as hashing, will result in collisions. You can resolve the collisions by maintaining collision table, but this will break the "generated ids must be same for every run" requirement.

Generate sequence on digits. Sequences should not be any similar

I'd like to generate a long list of 9-digits sequences.
Let's call them ID.
So each ID is unique and the main purpose is to have them all really different. It is unacceptable to have 2 IDs which differs by 1 or 2 digits in sequence.
Do you have any ideas how to implement it without comparing each new generated ID with each previously generated?
Probably there is some algorithm already or simple MYSQL function to compare how close those strings are?
You could try the following formula for your ID's - you would only need to check that the ID value doesn't already exist in the table (salt is a constant between 0 and 100 that doesn't ever change once you pick a value - I would recommend using a prime number, and definitely not 0):
ID = random integer * 101 + salt;
This generates ID values like the following (for salt = 73):
469956305
017775467
001195913
913620520
156482807
577463533
470183959
049290800
078643925
141526626
If you take any two of these ID values and compare them, you'll notice that no two numbers differ by only one or two digits in sequence. I wrote a script to compare all possible ID values between 0 and 3000000, and there were no two ID values of this form differing by 1 or 2 digits in sequence. If you want to test it out yourself, here's the script I used (in C#): http://ideone.com/lFHnlX - I reduced the upper limit because of timeout on IDEone.
You want to get away with not-checking for uniqueness and you don't want IDs to be similar? Then you're really looking for UUIDs/GUIDs.
MySQL's built-in uuid() function will get you there.
As Robert Harvey points out, UUIDs are alphanumeric (not numeric) and longer than 9 characters, but you're going to have to sacrifice something – you cannot satisfy all of your constraints simultaneously.

"Cluster analysis" with MySQL

This is a tough one. There is probably a name for this and I don't know it, so I'll describe the problem exactly.
I have a dataset including a number of user-submitted values. I need to be able to determine based on some sort of average, or better, a "closeness of data", which value is the correct value. For example, if I received the following three submissions from three users, 4, 10, 3, I would know that 3 or 4 would be the "correct" value in this case. If I were to average it out, I'd get 5.6 which is not the intended result.
I'm attempting to do this using MySQL and PHP.
tl;dr Need to find a value from a dataset based on "closeness" of relative values (using MySQL/PHP)
Thanks!
Clustering using a database isn't going to be a single query type of procedure. It takes iterations to generate the clusters effectively.
You first need to decide how many clusters you want. If you wanted only one cluster, then obviously everything would go into it. If you want two, then you can write your program to separate the nodes into two groups using some sort of correlation metric.
In other words, I don't think this is a MySQL question so much as a clustering question.
I think that is the kind of thing you're looking for:
SELECT id, MIN(ABS(id - (SELECT AVG(id) FROM table))) as min
FROM table
GROUP BY id
ORDER BY min
LIMIT 1;
Per example, if your data set contains the following IDs: 3, 4, 10, with an average of 5.6667. The closest value to 5.6667 is 4. If your data set is 3, 6, 10, 14, with an average of 8.25, the clostest value is 10.
This is what this query returns. Hope it helps.
I have the impression you are looking for the median
E.g. in the list 1 2 3 4 100, the median (central value) is 3.
You may want to search for [https://stackoverflow.com/search?q=sql+median finding the median in SQL].

Categories