Php shuffle 2 unique numbers - php

I got a database with users and numbers.
I built a shuffle and tried to randomly give a user a number, that worked.
Now I have the issue that I want to give the user 2 random numbers with shuffle which shall be unique.
Main Code looks like this:
$numbers = range(0, $counts); // $counts are the number of users in my databse
$numbers2 = range(0, $counts);
shuffle($numbers);
shuffle($numbers2);
foreach($users as $user) {
# Starts from 1 if higher than 52
$uniqueRand = (array_pop($numbers)+$currentWeek) % 52 + 1;
$uniqueRand2 = (array_pop($numbers2)+$currentWeek) % 52 + 1;
# tried something like this but did
while($uniqueRand == $uniqueRand2) {
$numbers2 = range(0, $counts);
shuffle($numbers2);
$uniqueRand2 = (array_pop($numbers2)+$currentWeek) % 52+1;
}
...# Storing in database
}
Here a little sketch of the application
Users | numbers
__________________________
Frank | 14, 24
Tim | 21, 43
Tom | 52, 6
Hanz | 8, 3
Benjamin | 5, 1
West | 7, 6
Thompson | 4, 9
.....
The first line of numbers 14,21,52... stand for $numbers and the second line for $numbers2, I want to create unique random values which do not repeat themselves, but how do I check if the $number do not repeat in the same line and are still vertical unique.
So for instance would something like this be wrong:
Users | numbers
_________________________
Frank | 14, 14
Something like this would be wrong too:
Users | numbers
_________________________
Frank | 14, 24
Tim | 21, 14
Tom | 14, 6
Hanz | 8, 3
Benjamin | 5, 14
West | 14, 6
Thompson | 4, 9

Related

How to compact/rearrange a multi-dimensional array by removing null values

I have an array called $rows. The first row is the header.
The first column is X (input signal), the other columns are Y1,Y2,Y3, etc. (output signals).
For any X value some of Y values may be NULL.
I print it with this code:
$first_key = key($rows);
foreach ($rows as $key => $row) {
if($key == $first_key) { // print header
fputcsv($out, array_keys($row));
}
fputcsv($out, $row);
}
The output of this code look like this (sorted by X column):
X | Y1 | Y2 | Y3 |
--------------------------
0.1 | | 10 | |
0.5 | 90 | | 7 |
0.7 | 15 | 40 | |
1.2 | | 12 | |
Goal: reorganize output to have columns X1,Y1,X2,Y2, etc such that in every pair (Xi,Yi) no NULL(empty) values are in between the row data and the header:
X1 | Y1 | X2 | Y2 | X3 | Y3 |
------------------------------------------
0.5 | 90 | 0.1 | 10 | 0.5| 7 |
0.7 | 15 | 0.7 | 40 | | |
| | 1.2 | 12 | | |
My attempt:
$current_header = array_keys($rows[0]);
$size = count($current_header);
$new_header=array(); // the new header: X1, Y1, X2, Y2,...
$arr_X=array();
$arr_Y=array();
$x_column=$current_header[0];
for ($i=1; $i<$size; $i++) {
$y_column=$current_header[$i];
$new_header[2*$i] = $x_column;
$new_header[2*$i+1] = $y_column;
$arr_Y[$y_column] = array_column($rows, $y_column);
$arr_X[$y_column] = array_column($rows, $x_column);
}
Next step: join $arr_X[$y_column] and $arr_Y[$y_column] into arr_XY. I think in this array the key should be the index (row#); also arr_XY should not include the points where $arr_Y[$y_column] is NULL: I do not know how to do it
$arr_XY=array();
for ($i=1; $i<$size; $i++) {
$y_column=$current_header[$i];
// here should be the code to join arrays and eliminate NULL arr_Y points
$arr_XY[$y_column] = ($arr_X[$y_column], $arr_Y[$y_column]);
}
The final step is where I need help: build and print the output rows by combining all arr_XY[$y_column] by row index.
Is this what you are after?
Input:
$rows=[
['X','Y1','Y2','Y3'],
[.1,null,10,null],
[.5,90,null,7],
[.7,15,40,null],
[1.2,null,12,null]
];
Method:
foreach($rows as $i=>$row){
if(!isset($result)){ // prepare result keys in order
foreach(array_slice($row,1) as $col){ // don't iterate X column of header
$no=substr($col,1); // get number following Y
$result["X$no"]=[]; // declare X column with column integer
$result["Y$no"]=[]; // declare Y column with column integer
}
}else{
foreach(array_slice($row,1,null,true) as $i=>$col){ // ignore X column
if(!is_null($col)){ // only store non-null values
$result["X$i"][]=$row[0]; // assign X value
$result["Y$i"][]=$col; // assign Y value
}
}
}
}
var_export($result);
Alternative Method:
foreach($rows as $i=>$row){
foreach(array_slice($row,1,null,true) as $c=>$col){
if($i==0){
$result["X$c"]=[];
$result["Y$c"]=[];
}elseif(!is_null($col)){
$result["X$c"][]=$row[0];
$result["Y$c"][]=$col;
}
}
}
Output:
array (
'X1' => [0.5, 0.7],
'Y1' => [90, 15],
'X2' => [0.1, 0.7, 1.2],
'Y2' => [10, 40, 12],
'X3' => [0.5],
'Y3' => [7]
];

Manipulating/formatting database output

I've got a database query that outputs the data I need, but I'm not sure how to get it into the format I need (also need to get it into csv format, but need to get the output right first).
SELECT `user_id`, `assessment_name`, `question_id`, `question_type_id`, `answer`, `created_at` FROM answer WHERE `assessment_id` = 1
The output is like this (although with 30 rows per submission - just put three each here as an example):
11 Three Intelligences 31 6 4 7/22/08 11:30
11 Three Intelligences 40 4 4 7/22/08 11:30
11 Three Intelligences 41 6 5 7/22/08 11:30
10 Three Intelligences 31 6 3 7/22/08 14:54
10 Three Intelligences 40 4 4 7/22/08 14:54
10 Three Intelligences 41 6 4 7/22/08 14:54
12 Three Intelligences 31 6 4 7/29/08 10:31
12 Three Intelligences 40 4 4 7/29/08 10:31
12 Three Intelligences 41 6 4 7/29/08 10:31
What I need is to reformat this so that it can be used for data analysis, which means getting the data into a single row for each user_id and assessment_name and created_at
assessment_name, user_id, answer(for question 31), question_type_id(for question 31), answer(for question 40), question_type_id(for question 40), answer(for question 41), question_type_id(for question 41), created_at
Three Intelligences, 11, 6, 4, 4, 4, 6, 5, 7/22/08 11:30
Three Intelligences, 10, 6, 3, 4, 4, 6, 4, 7/22/08 14:54
Three Intelligences, 12, 6, 4, 4, 4, 6, 4, 7/29/08 10:31
Is this possible? If so, I also assume I can do it in php, but I don't know enough to figure out the 'while' loops necessary. It probably doesn't even need to produce a csv file output... if I can just get it properly formatted on the page I can copy/paste for this particular project.
Thanks
--EDIT--
Here's what I've got so far -- this will generate the semi-raw output of the data... I think what I need is just to figure out what loops within loops are required within the 'while' to get the desired output.
<?php
require_once '../connection.php';
// Create connection
$conn = new mysqli(localhost, $dbuser, $dbpass, $db);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$query_responses = "SELECT `user_id`, `assessment_name`, `question_id`, `question_type_id`, `answer`, `created_at` FROM answer WHERE `assessment_id` = 1";
$result_responses = $conn->query($query_responses);
if ($result_responses->num_rows > 0) {
// output data of each row
while($row = $result_responses->fetch_assoc()){
echo $row["created_at"]. ", " .$row["assessment_name"]. ", " .$row["user_id"]. "," .$row["question_id"]. "," .$row["question_type_id"]. "," .$row["answer"]. "<br />";
}
} else {
echo "0 results";
}
$conn->close();
?>
is it this what you looking for:
SELECT
`user_id`,
`assessment_name`,
CONCAT(
GROUP_CONCAT(
CONCAT(`question_type_id`, ', ', `answer`)
SEPARATOR ', ' ), ', ', `created_at`) AS RESULT
FROM answer
WHERE `assessment_id` = 1
GROUP BY `user_id`
ORDER BY `user_id`;
Sample
MariaDB []> SELECT
-> `user_id`,
-> `assessment_name`,
-> CONCAT(
-> GROUP_CONCAT(
-> CONCAT(`question_type_id`, ', ', `answer`)
-> SEPARATOR ', ' ), ', ', `created_at`) AS RESULT
-> FROM answer
-> -- WHERE `assessment_id` = 1
-> GROUP BY `user_id`
-> ORDER BY `user_id`;
+---------+---------------------+---------------------------------------------+
| user_id | assessment_name | RESULT |
+---------+---------------------+---------------------------------------------+
| 11 | Three Intelligences | 6, 4, 4, 4, 6, 5, 2016-01-01 00:00:00 |
| 12 | Three Intelligences | 6, 4, 6, 4, 6, 4, 6, 4, 2016-01-01 00:00:00 |
+---------+---------------------+---------------------------------------------+
2 rows in set (0.00 sec)
MariaDB []>
Please let me know if it works for you

Walk through a table to grab unique certificate numbers for shares

The table I am working with is named shares. Assuming $share is an instance of the model Share. A share belongs to a company.
| id | company_id | number_of_shares |
| 31 | 1 | 3 |
| 33 | 1 | 9 |
| 34 | 1 | 4 |
I want to call $share->getCertificate() and have it return a certificate number, these should be:
id 31 -> 1
id 33 -> 2
id 34 -> 3
Note: this increments a unique certificate number based on its location in the table.
Then when I call $share->getDistinctive() I wish to have it return the following:
id 31 -> array('start' => 1, 'end' => 3)
id 33 -> array('start' => 4, 'end' => 13)
id 34 -> array('start' => 14, 'end' => 18)
Note: this increments based on the number of shares starting at 1
Assumptions
Table will always be ordered by id
I am using laravel 4.0.
Happy for someone to recommend a better title so that other people can find the the solution to their problem.
Worked it out - not sure why I thought it would've been more complicated.
getCertificateNumber()
public function getCertificateNumber()
{
$x=1;
foreach($this->company->holdings()->get() as $holding)
{
if($holding->id == $this->id)
{
return $x;
}
$x++;
}
}
getDistinctiveNumbers()
public function getDistinctiveNumbers()
{
$shares=0;
foreach($this->company->holdings()->orderBy('id')->get() as $holding)
{
if($holding->id == $this->id)
{
return ['start'=> $shares + 1, 'end' => $shares + $this->number_shares];
}
$shares += $holding->number_shares;
}
}

Combining multiple arrays in a timetable

I need a solution how to find all possible combinations of a schedule. There are courses on given dates that can vary by length. There is a given number of weeks. I need to find a solution to all possible combinations including all courses, with no overlapping.
$courses = array ("A", "B", "C", "D");
$duration = array (2, 3, 1, 2); // duration of $courses (in weeks)
$start_dates = array (
$courses[0] => array (1, 3, 5),
$courses[1] => array (1, 2, 5, 6),
$courses[2] => array (3, 4, 5, 9),
$courses[3] => array (1, 4, 8));
I would like to get all the possible combinations, e.g. this:
Week | Course
1 | A
2 | A
3 | C
4 | D
5 | D
6 | B
7 | B
8 | B
9 | -
10 | -
Second combination would be e.g. this:
Week | Course
1 | A
2 | A
3 | -
4 | C
5 | B
6 | B
7 | B
8 | D
9 | D
10 | -
The preferred output would be an array with week => course, like this:
$combinations = array (
0 => array (
1 => $courses[0],
2 => $courses[0],
3 => $courses[2],
4 => $courses[3],
...
),
1 => array (
1 => $courses[0],
2 => $courses[0],
4 => $courses[2],
5 => $courses[1],
6 => $courses[1],
7 => $courses[1],
...
)
);
I am really stuck with this problem. Thanks a lot for your help.

How to find the best subset from an array whose sum is equal to X number in php

I have an array as
$array = array(3,5,6,10,15,30);
$sum = 69;
then there are 3 different sums that equal 69:
3+5+6+10+15+30,
3+6+10+20+30,
3+6+30+30,
The best one is 3+6+30+30. Because it contains higher number from array to complete the sum that reduce the number count.
(A number can be used within a sum as many times as it appears in the list, and a single number counts as a sum.)
Here is the code that I am implementing
$sum = 18;
$list = array();
$this->sumUpRecursive(array(3,5,6,10,15,30), $list); //function call
$list = array_filter($list,function($var) use ($sum) { return(array_sum($var) == $sum);});
var_dump($list);
function sumUpRecursive($array, &$list, $temp = array()) {
if (count($temp) > 0 && !in_array($temp, $list))
$list[] = $temp;
for ($i = 0; $i < sizeof($array); $i++) {
$copy = $array;
$elem = array_splice($copy, $i, 1);
if (sizeof($copy) > 0) {
$add = array_merge($temp, array($elem[0]));
sort($add);
$this->sumUpRecursive($copy, $list, $add);
}
else {
$add = array_merge($temp, array($elem[0]));
sort($add);
if (!in_array($temp, $list)) {
$list[] = $add;
}
}
}
}
Result:
Array
(
[9] => Array
(
[0] => 3
[1] => 5
[2] => 10
)
[28] => Array
(
[0] => 3
[1] => 15
)
)
I hope this might be bit complex . Its taking a number from array once. But how to figure out for 69...
Thanks
This should work for you:
What does this code do (the function getKnapsackSum())?
1. prepare data
In the first few lines of the function I prepare the data, that means I sort the array DESC with rsort(). I get the last element of the list with end(), reset the array pointer with rest() and assign it to a temp variable.
2. input check
Before I begin to calculate the sum I check that the input isn't 0.
3. calculate the sum
After this the real stuff happens (IT voodoo, not really)! I start with a loop which is false as long as I didn't got the sum. The next 2 lines in the while loop are there to check, that first if the sum can't be calculated, that it returns an array with a 0 and second that when we got a "offset" of the array pointer, that I set it back the last array element.
Then the first if clause is there to check if it made a mistake and it has to try it with lower values. So as an example:
list = [3, 5, 6]
sum = 8
//entire sum
| 0
|
check 6: |
|
6 + sum -> 8 | 6 | fits
6 + sum -> 8 | | does not fit
|
check 5: |
|
5 + sum -> 8 | | does not fit
|
check 3: |
|
3 + sum -> 8 | | does not fit
--------------------------------------------------------
= sum = [6] != 8
As you can see right here with this example the algorithm made a mistake, because it started to build the sum with 6, but after this it couldn't build it until the end, now here is where the first if clause checks, if the current element of the array pointer is the end of the array and this value + the current sum is higher than the goal.
If this is the case it deletes the last value from the sum array and pops off the highest element of the list. So now it tries it again with the following data:
list = [3, 5]
//^ As you can see it removed the highest value of the list
sum = 8
//entire sum
| 0 <- it removed the last value of the sum array, here 6
|
check 5: |
|
5 + sum -> 8 | 5 | fits
5 + sum -> 8 | | does not fit
|
check 3: |
|
3 + sum -> 8 | 3 | fits
3 + sum -> 8 | | does not fit
--------------------------------------------------------
= sum = [5, 3] == 8
So as you can see now the first if clause made it possible to build the sum with the list. So the if statement makes sure that it corrects errors of level 1.
Now the second if statement in my while loop corrects errors of level 2. So what are errors of level 2? We also look again at an example:
list = [3, 5, 6]
sum = 22
//entire sum
| 0
|
check 6: |
|
6 + sum -> 22 | 6 | fits
6 + sum -> 22 | 6 | fits
6 + sum -> 22 | 6 | fits
6 + sum -> 22 | | does not fit
|
check 5: |
|
5 + sum -> 22 | | does not fit
|
check 3: |
|
3 + sum -> 22 | 3 | fits
3 + sum -> 22 | | does not fit
--------------------------------------------------------
= sum = [6, 6, 6, 3] != 22
So as you can see it couldn't build the sum entirely. But this time it isn't an error of level 1, because if we take the last element away from the current sum and go through the new list where we removed the highest element it still can't build the sum as you can see here:
correction of errors level 1:
list = [3, 5]
//^ As you can see it removed the highest value of the list
sum = 22
//entire sum
| [6, 6, 6] <- it removed the last value of the sum array, here 3
|
check 5: |
|
5 + sum -> 22 | | does not fit
|
check 3: |
|
3 + sum -> 22 | 3 | fits
3 + sum -> 22 | | does not fit
|
--------------------------------------------------------
= sum = [6, 6, 6, 3] != 22
So as you can see it is stuck now, it can't correct the mistake only with the first if clause. And here is where the second if statement checks if the list is empty, if this is the case that means that you tried every value, but the mistake is higher up in the sum array.
So now it goes back 1 array element of the sum array and deletes it. It also takes the mistake as offset to get a list without the number which was the mistake. So here: [6, 6, 6, 3] the 3 gets removed from the first if clause so now the array looks like this: [6, 6, 6]. Now the second if statement see's that the mistake was 6. It removes it and also corrects the list where it chooses the numbers from.
So now the result array looks like: [6, 6] and the list to choose numbers from like this: [5, 3]. And now that it made a correction of level 2 it can build the sum as you can see here:
list = [3, 5]
//^ As you can see it removed the highest value of the list
sum = 22
//entire sum
| [6, 6] <- it removed the last value of the sum array, here 3 and 6
|
check 5: |
|
5 + sum -> 22 | 5 | fits
5 + sum -> 22 | 5 | fits
5 + sum -> 22 | | does not fit
|
check 3: |
|
3 + sum -> 22 | | does not fit
|
|
--------------------------------------------------------
= sum = [6, 6, 5, 5] == 22
So after this the if else statement is there just to check if the current value of the list fits into the sum array and isn't bigger than the goal. If it fits it adds it to the array otherwise it goes to the next list element.
Now as you can see my code corrects a few errors, but I'm not 100% sure that it works for everything and I'm also not sure if you can produce errors of level 3 where you have to go back in the sum array an correct 3 values, and if there is one I'm also not sure if my code corrects it or maybe even fall into a endless loop.
But after all this talking here is the code which does all the magic:
<?php
//data
$arr = [3,5,6,10,15,30];
$sum = 69;
//get sum
function getKnapsackSum($arr, $sum) {
//prepare data
rsort($arr);
$end = end($arr);
reset($arr);
$tmp = $arr;
$result = [];
//check if it is not a empty input
if($sum == 0 || empty($tmp) || array_sum($tmp) == 0) return [0];
//calculate the sum
while(array_sum($result) != $sum) {
if(empty($tmp) && empty($result)) return [0];
if(current($tmp) === FALSE) end($tmp);
//correction for errors level 1
if(current($tmp) == $end && array_sum($result) + current($tmp) > $sum) {
array_pop($result);
array_shift($tmp);
reset($tmp);
}
//correction for errors level 2
if(empty($tmp)) {
$mistake = array_pop($result);
if($mistake == NULL) return [0];
$tmp = array_slice($arr, array_search($mistake, $arr)+1);
reset($tmp);
}
if(array_sum($result) + current($tmp) <= $sum)
$result[] = current($tmp);
else
next($tmp);
}
return $result;
}
$result = getKnapsackSum($arr, $sum);
print_r($result);
?>
Output:
Array ( [0] => 30 [1] => 30 [2] => 6 [3] => 3 )
Also here a few examples of inputs and there outputs from my code:
input | output
------------------------------------
list: [] |
goal: 0 | sum: [0]
------------------------------------
list: [] |
goal: 1 | sum: [0]
------------------------------------
list: [0] |
goal: 1 | sum: [0]
------------------------------------
list: [0] |
goal: 0 | sum: [0]
------------------------------------
list: [3, 5, 6] | //error level 1
goal: 8 | sum: [5, 3]
------------------------------------
list: [3, 5, 6] | //error level 2
goal: 22 | sum: [6, 6, 5, 5]
------------------------------------
list: [5, 7, 9] | //can't build the sum
goal: 56 | sum: [0]
------------------------------------
list: [5, 7, 9] |
goal: 34 | sum: [9, 9, 9, 7]
------------------------------------

Categories