Creating non reoccuring random groups of people - math

So this isn't really an informatics question but I'm guessing the solution lies in informatics.
We have a group of 100 students that are meant to have discussion amongst each other. For this we want to separate them into 10 groups of 10 people.
We want to have three rounds of discussions, however we want the groups to be different each time. No one person should get to sit with the same person twice.
Say we assign our groups letters
abcdefghij (10)
Person1 gets Round1:A Round2:B Round3:C
Person2 gets Round1:A but then can't have Round2:B or Round3:C because they would then meet again.
Doing this by hand sounds pretty insane and I'm sure there is a pretty simple solution for this. Maybe even a program that does exactly this, but I just can't find it or don't know what to search for...
Sadly I have no skills whatsoever in programming, but maybe this can even be done in excel or sth like that?
All help or tips apreciated.
Thanks for taking the time!

Yes, it can be done in the excel. You just need the 3 step approach:
Mix the students in the random fashion.
Create one set of mixes which don't repeat the students
Apply the transformation of the order to the students
The tricky one is 2nd.
The exemplary mix is:
Since the order of the students is random, you can divide them in the 10 groups of ten people, that is easy. So we have the 1st discussion done.
For second discussion you can take the 1st person of each group (take every 10th person) as they were not in the same groups at the 1st time.
Then take the 1st person from 1st group, 2nd from the 2nd, 3rd from the 3rd. In this way you can clearly see that no person is with the same person in the group. For the rest of groups just go with different starts so 1st person from 2nd group goes with the 2nd person to 3rd group etc.
Even though this is not the only solution it is reasonably easy to implement. Even doable in excel.

If you just need three rounds, you can probably get by with a "difference scheme", or even a random process coupled with rejection of unsuitable arrangements. However, if you can change the number 100 a little bit, you can get some more interesting results.
For example, it is easy to construct so-called "resolvable balanced incomplete block designs" on a set of 81 elements, 9 groups, no pair appears more than once in a group. You can do that with the sage system command echo 'print(designs.AffineGeometryDesign(2,1,9))' | sage > output.txt. Unfortunately, sage prints the blocks in lexicographic order, but you can easily rearrange them in a more useful order. Similarly print(designs.AffineGeometryDesign(2,1,11)) provides a block design with 121 elements in groups of 11. Using 10 instead of 9 or 11 doesn't work out: the number must be a power of a prime.
The output of those commands is rather long, so I'll do a simpler example, with 4 instead of 9. The output is
AffineGeometryDesign<points=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
blocks=[[0, 1, 2, 3], [0, 4, 8, 12], [0, 5, 10, 15], [0, 6, 11, 13], [0, 7, 9, 14],
[1, 4, 11, 14], [1, 5, 9, 13], [1, 6, 8, 15], [1, 7, 10, 12], [2, 4, 9, 15],
[2, 5, 11, 12], [2, 6, 10, 14], [2, 7, 8, 13], [3, 4, 10, 13], [3, 5, 8, 14],
[3, 6, 9, 12], [3, 7, 11, 15], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]>
points just gives the numbering of the points; note that it starts at 0 instead of 1, and that there are 16 points altogether. More interesting is blocks. We can rearrange the blocks as follows:
[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]
[0, 4, 8, 12], [1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15]
[0, 5, 10, 15], [1, 4, 11, 14], [2, 7, 8, 13], [3, 6, 9, 12]
[0, 6, 11, 13], [1, 7, 10, 12], [2, 4, 9, 15], [3, 5, 8, 14]
[0, 7, 9, 14], [1, 6, 8, 15], [2, 5, 11, 12], [3, 4, 10, 13]
Each row covers the ground set with 4 disjoint subsets. Pick any pair of numbers and you'll find that they are in one and only one block together. This allows you to extend beyond three rounds in cases where an rBIBD exists.
One way to deal with 100 students would be to add 21 "fake" students (which could just be empty placeholders or could be teachers, teaching assistants, research assistants, etc.) and use the (121,11,1)-rBIBD generated by Sage.

Related

Find index of element comparing with sorted vector

If I have a sorted vector, like
vec <- c(5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
and I have
x <- 9.5
Then x is between the 5th and 6th value in my sorted row, and I want to get the index 5. How can I do it?
The following will give the result you're looking for:
x<-c(5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
findInterval(9.5,x)
> [1] 5
Alternative solutions include:
> max(which(x < 9.5))
[1] 5
There should be multiple ways to do this. One way using which.max
which.max(vec > x) - 1
#[1] 5
This finds first index where vec is greater than x and then returns an index 1 less than that.
As it is sorted the opposite should work as well
which.min(vec < x) - 1
#[1] 5

Arithmetic operation (Difference) between a vector and a Matrix in R

I am facing this issue when I am trying to calculate the difference between list and matrix in R, it is giving me weird results.
matrix <- matrix(1:10,1:10,nrow = 10,ncol=10)
list1 <- seq(1:10)
diff <- list1-matrix
Below is the output that I am trying to achieve but it does not work. Please let me know what I am doing wrong.
We can do this with multiple ways
1) Transpose the matrix, subtract from the vector and then do the transpose
t(t(matrix)- list1)
2) replicate the vector to make the lengths same and then do the difference
matrix - list1[col(matrix)]
3) Using sweep
sweep(matrix, 2, list1, `-`)
What you need to understand is that in R matrices are stored in column-major order. This means that a matrix is a sequence of numbers order by columns from top to down.
So when you subtract a vector from a matrix you can imagine it as operation with 4 steps:
matrix is turned into a sequence of numbers (a vector)
your "list1" is expanded (repeated) so that it's length matches the length of the vector constructed from the matrix.
the elements in each are subtracted from each other
the numbers are assembled into the matrix form again.
In your case:
1) matrix is turned into a sequence of numbers (by columns) giving you:
1, 1, 1 ,1 ... 1, 2, 2, 2, 2, ... 2, ... ... 10, 10, 10, 10, ... 10
2) Your second vector is repeated until it matches the first one:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8, 9, 10, ... 1, 2, 3, ... 10
3) Now both of them have the same length so they are subtracted from each other:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, ..., -9, -8, -7, ... 0
4) The result is transformed into a matrix again giving you the matrix that you see.
In order to obtain your desired result you have to take this into account. One way is to transpose your matrix, do the subtraction, and transpose it back again:
t(t(matrix) - list1)
This works because after the transpose t the rows are turned into columns.
Another approach is to construct a matrix out of your list1 vector:
matrix2 <- matrix(list1, nrow=10, ncol=10, byrow=TRUE)
And then do the subtraction:
diff <- matrix - matrix2

How to count the number of times a pattern changes?

I have a vector created simulating a continious time Markov Chain. The vector represents the path the chain may describe. Simulating 20 steps we could have:
Xt <- c(5, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0 ,0)
Further, the vector can jump 1 by 1 or jump from any state (5,4,3,2,1) to 0. So other simulation could be:
Xt <- c(5, 5, 5, 5, 5, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
I want to count the number of times the simulated chain jumps to other state (when the vector changes of number) within a determined interval. For example:
The number of jumps for the first vector I wrote for the first 10 elements is 2 (Jumps from 5 to 4 and 4 to 0). The number of jumps for the second vector I wrote for the last 10 elements is 0 (The last 10 elements are all 0)
So I would like to count the number of jumps (the number of times the pattern changes). I tried using toString(Xt)and then trying to match some regex but nothing worked. Any ideas?
You can use diff for this which counts the difference between adjacent numbers in a vector. Sum all instances not equal to zero to get total times the pattern changes.
First 10:
sum(diff(Xt[1:10])!=0)
[1] 2
Last 10:
sum(diff(Xt[(length(Xt)-10):length(Xt)])!=0)
[1] 0
Seems like just count the number of times the difference was not zero would deliver the desired result:
Xt <- c(5, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0 ,0)
sum(diff(Xt) != 0)
If the goal was to write a function that takes a string and a starting positon it could be done thusly:
jump_in_next_10 <- function(string, start){
sum( diff(string[start:(start+9)]) != 0 )}
jump_in_next_10(Xt, 3)
#[1] 2

subsetting a range between two percentages (R)

I have a numeric vector consisting of 150 observations ranging from -217544 to 319842.
I would like to create a subset based on a range of percentages. In other words I would like to subset everything between 30% and 70%.
for instance:
bm.sort <- c(1, 2, 3, 4, 5, 6, 7, 8, 9 ,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
I would like for the code to select the middle 40% (7 to 14).
I have so far tried the code
bm.m <- subset(bm.sort, bm.sort >= quantile(bm.sort, 0.3 %between% bm.sort <= quantile(bm.sort, 0.7)))
and
bm.m <- subset(bm.sort, bm.sort >= quantile(bm.sort, 0.3 | bm.sort <= quantile(bm.sort, 0.7)))
However when I use this code I only receive one observation instead of the range of 60 observations that i should receive.
Any help would be appreciated.
I managed to figure it out (missing ")" ), sorry for taking up your time unnecessarily.
Thank you for all the help.

Subsets having duplicates?

Can a subset, not a proper subset, have duplicate values?
Example
A = {1, 2, 3, 3, 4, 5}
B = {1, 2, 3, 4, 5}
is AcB or does the duplicate value cancel that out?
Your question makes little sense, but I'll try answering anyway.
Can a subset, not a proper subset, have duplicate values?
No, a subset is a set, and sets do not have duplicate values.
Example A = {1, 2, 3, 3, 4, 5} B = {1, 2, 3, 4, 5}
is AcB or does the duplicate value cancel that out?
I'm not even sure if A = {1, 2, 3, 3, 4, 5} is valid notation, but yes, unless you're talking about multisets, A is a subset of B in this case.

Resources