An application on Bertrandís ballot theorem in C/C++

Bertrand's ballot theorem states that in an election where candidate A receives p votes and candidate B receives q votes (where p > q), the probability that A is always strictly ahead throughout the counting process is (p-q)/(p+q). This theorem has practical applications in probability theory and combinatorics.

Syntax

Probability = (p - q) / (p + q)
where p > q > 0

Mathematical Example

Let there are 5 voters, of whom 3 vote for candidate A and 2 vote for candidate B (so p = 3 and q = 2). Ten possibilities exist for the order of the votes cast −

  • AAABB

  • AABAB

  • ABAAB

  • BAAAB

  • AABBA

  • ABABA

  • BAABA

  • ABBAA

  • BABAA

  • BBAAA

For the order AABAB, the tally of votes as the election progresses is −

Candidate A A B A B
A 1 2 2 3 3
B 0 0 1 1 2

Here, A is always strictly ahead of B. For the order AABBA, the tally is −

Candidate A A B B A
A 1 2 2 2 3
B 0 0 1 2 2

Here, B ties with A after the fourth vote, so A is not always strictly ahead.

C Implementation

The following program implements Bertrand's ballot theorem to calculate the probability and verify it with enumeration −

#include <stdio.h>
#include <stdlib.h>

/* Function to calculate factorial */
long long factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

/* Function to calculate combinations C(n,r) */
long long combination(int n, int r) {
    if (r > n) return 0;
    return factorial(n) / (factorial(r) * factorial(n - r));
}

/* Function to check if sequence maintains A always ahead */
int isValidSequence(int *sequence, int p, int q) {
    int countA = 0, countB = 0;
    
    for (int i = 0; i < p + q; i++) {
        if (sequence[i] == 1) countA++;  /* A vote */
        else countB++;                   /* B vote */
        
        if (countA <= countB) return 0;  /* A not strictly ahead */
    }
    return 1;
}

/* Generate all permutations and count valid ones */
void generatePermutations(int *sequence, int pos, int p, int q, 
                         int usedA, int usedB, int *validCount, int *totalCount) {
    if (pos == p + q) {
        (*totalCount)++;
        if (isValidSequence(sequence, p, q)) {
            (*validCount)++;
        }
        return;
    }
    
    /* Try placing A */
    if (usedA < p) {
        sequence[pos] = 1;
        generatePermutations(sequence, pos + 1, p, q, usedA + 1, usedB, 
                           validCount, totalCount);
    }
    
    /* Try placing B */
    if (usedB < q) {
        sequence[pos] = 0;
        generatePermutations(sequence, pos + 1, p, q, usedA, usedB + 1, 
                           validCount, totalCount);
    }
}

int main() {
    int p = 3, q = 2;  /* A gets 3 votes, B gets 2 votes */
    
    /* Theoretical probability using Bertrand's formula */
    double theoretical = (double)(p - q) / (p + q);
    
    /* Count valid sequences by enumeration */
    int sequence[10];
    int validCount = 0, totalCount = 0;
    
    generatePermutations(sequence, 0, p, q, 0, 0, &validCount, &totalCount);
    
    double empirical = (double)validCount / totalCount;
    
    printf("Bertrand's Ballot Theorem Verification\n");
    printf("======================================\n");
    printf("Candidate A votes (p): %d\n", p);
    printf("Candidate B votes (q): %d\n", q);
    printf("Total sequences: %d\n", totalCount);
    printf("Valid sequences (A always ahead): %d\n", validCount);
    printf("Theoretical probability: %.3f\n", theoretical);
    printf("Empirical probability: %.3f\n", empirical);
    printf("Formula verification: (p-q)/(p+q) = (%d-%d)/(%d+%d) = %.3f\n", 
           p, q, p, q, theoretical);
    
    return 0;
}
Bertrand's Ballot Theorem Verification
======================================
Candidate A votes (p): 3
Candidate B votes (q): 2
Total sequences: 10
Valid sequences (A always ahead): 2
Theoretical probability: 0.200
Empirical probability: 0.200
Formula verification: (p-q)/(p+q) = (3-2)/(3+2) = 0.200

Key Points

  • The theorem applies only when p > q (winning candidate must have more votes).
  • Of the 10 possible vote orderings, only 2 maintain A always ahead (probability = 2/10 = 0.2).
  • This matches the theoretical formula: (3-2)/(3+2) = 1/5 = 0.2.

Conclusion

Bertrand's ballot theorem provides an elegant formula for calculating the probability that the winning candidate stays ahead throughout the entire counting process. The C implementation demonstrates both the theoretical calculation and empirical verification through enumeration.

Updated on: 2026-03-15T12:41:27+05:30

270 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements