Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designing a function to output the smallest plurality winner possible

I'm trying to design a function/formula where you're given two integer variables representing, say for example, 5 and 100. The first number could represent 5 ice cream flavours on a survey, and the 100 the number of people being sampled being asked their favourite ice cream.

I want to design a function/formula which would produce the combination of numbers where 1 of the 5 ice cream flavour's can win by smallest plurality (so, I'm guessing in most cases, by 1), and have the smallest number possible based on the number of ice cream flavours on the survey.

So with 5 ice cream flavour's and 100 respondents, I would want R to produce a vector of (order not really important):

[1] 21 20 20 20 19

As 21 is the smallest number possible for a majority ice cream flavour winner out of 100 respondants and 5 flavours. As a function it would need to deal with when numbers of choices don't neatly divide with the numeber of respondants as well.

Desired output

combinations_function <- function(x, y) {
  ?????
}

combinations_function(5, 100)
[1] 21 20 20 20 19

combinations_function(5, 38)
[1] 9 8 7 7 7

combinations_function(7, 48)
[1] 8 7 7 7 7 6 6
like image 996
Nautica Avatar asked Mar 02 '23 22:03

Nautica


2 Answers

Think I got it:

smallest_margin <- function(choices, respondents)
{
    values = rep(respondents %/% choices, choices)
    remainder = respondents %% choices
    while(remainder != 0)
    {
      values[which.min(values)] <- values[which.min(values)] + 1
      remainder = remainder - 1
    }
    if(length(which(values == max(values))) > 1)
      values[which(values == max(values))[1:2]] <- 
      values[which(values == max(values))[1:2]] + c(-1, 1)
    return(sort(values))
}

smallest_margin(5, 100)
# [1] 19 20 20 20 21
smallest_margin(1, 100)
# [1] 100
smallest_margin(5, 99)
# [1] 19 19 20 20 21
smallest_margin(12, 758)
# [1] 63 63 63 63 63 63 63 63 63 63 63 65
like image 188
Allan Cameron Avatar answered Mar 05 '23 15:03

Allan Cameron


Here is a code-golfian approach

f <- function(x,y) 
  rep(y%/%x, x) + ifelse(rep(y%%x>0, x), 
                         c(1^(1:(y%%x)), 0*((y%%x+1):x)), 0) + c((-1)^(0:1), 0*(3:x))

Example

f(5, 100)
# [1] 21 19 20 20 20
f(5, 38)
# [1] 9 7 8 7 7
f(5, 48)
# [1] 11  9 10  9  9
f(7, 48)
# [1] 8 6 7 7 7 7 6
like image 21
niko Avatar answered Mar 05 '23 14:03

niko