90 Ball Bingo

Interesting problems
R Models
Author

JRowing

Published

April 19, 2025

Creating a 90-ball bingo card can be challenging because of several key rules and requirements that must be followed, including the distribution of numbers, the uniqueness of each row, and ensuring a balanced and fair game. Here’s why it’s particularly tricky:

  1. Fixed Number Range per Column In 90-ball bingo, there are 90 possible numbers, ranging from 1 to 90. The card consists of 3 rows and 9 columns, with each column corresponding to a specific range of numbers:

Column 1: Numbers 1–9

Column 2: Numbers 10–19

Column 3: Numbers 20–29

And so on until…

Column 9: Numbers 80–90

The challenge comes from the need to distribute the numbers across the 9 columns so that:

Each column contains a random selection of numbers from the correct range.

The total number of numbers in the card is limited (i.e., each row contains only 5 numbers and each column contains exactly 3 numbers).

  1. Ensuring No Duplicates Each bingo card must be unique — no two cards can have the same number in the same place. This means that not only do we need to distribute the numbers according to the column ranges, but we also have to ensure that across multiple cards, the number placement is randomized without repeating the exact same pattern.

  2. Each Row Must Contain 5 Numbers A 90-ball bingo card has 3 rows and 9 columns, but only 5 numbers per row. This means that in each row, there will be some empty cells (spots with no numbers). The challenge is to:

Ensure that the numbers are spread out across the entire row while keeping the 5-number constraint.

Maintain a consistent structure across multiple cards.

  1. Ensuring Fair Distribution For the game to be fair, numbers should be distributed as evenly as possible across the 9 columns. This means ensuring that there are no biases, such as certain columns being overly dense with numbers or others being too sparse. The balancing between columns is vital to prevent players from having an unfair advantage.

  2. Randomization While bingo cards are created with specific rules for how numbers are placed, there is still a randomness aspect involved. Ensuring that every generated card adheres to the required constraints (e.g., 3 numbers per column, 5 numbers per row) while still being unique and random adds an additional layer of complexity.

  3. Maintaining Consistency with Game Rules 90-ball bingo has 3 types of wins: line, two lines, and full house. Ensuring that the card layout doesn’t favor one type of win over another or create any unintentional patterns adds to the challenge of card creation.

This is my effort:

generate_bingo_card <- function() {
  # Define column ranges
  col_ranges <- list(
    1:9, 10:19, 20:29, 30:39, 40:49,
    50:59, 60:69, 70:79, 80:90
  )
  
  repeat {
    # Create an empty card with NA values
    card <- matrix(NA, nrow = 3, ncol = 9)
    positions <- matrix(0, nrow = 3, ncol = 9)
    
    # Step 1: Randomly assign 5 filled positions per row
    for (i in 1:3) {
      positions[i, sample(1:9, 5)] <- 1
    }

    # Step 2: Ensure every column has at least one number
    cols_with_numbers <- colSums(positions)
    if (all(cols_with_numbers > 0)) break
  }

  # Step 3: Fill in numbers from correct column ranges
  for (col in 1:9) {
    n_numbers <- sum(positions[, col])
    numbers <- sort(sample(col_ranges[[col]], n_numbers))
    rows <- which(positions[, col] == 1)
    for (i in seq_along(rows)) {
      card[rows[i], col] <- numbers[i]
    }
  }
  
  card
}

format_bingo_card <- function(card) {
  apply(card, 1, function(row) {
    paste(sprintf("%2s", ifelse(is.na(row), ".", row)), collapse = " ")
  })
}

generate_and_save_bingo_cards <- function(n_cards = 5, filename = "bingo_tickets.txt") {
  lines <- c()
  for (i in 1:n_cards) {
    card <- generate_bingo_card()
    lines <- c(lines, sprintf("Card %d:", i))
    lines <- c(lines, format_bingo_card(card))
    lines <- c(lines, "")  # Blank line between cards
  }
  writeLines(lines, con = filename)
  message("Bingo cards saved to ", filename)
}

# Run it
set.seed(42)
generate_and_save_bingo_cards(n_cards = 5)
Bingo cards saved to bingo_tickets.txt

Card 1: 1 17 25 . . 51 61 . . . . . 33 45 54 63 71 . . 19 27 39 . . . 77 82

Card 2: 8 10 . . 48 . 62 74 . . 14 . 33 . 53 . 75 84 . 18 26 . 49 58 . 77 .

Card 3: . . 29 37 40 52 . 75 . 1 . . 39 44 . 60 . 84 5 16 . . 48 58 . . 87

Card 4: 1 10 . . . . 63 79 80 . 12 29 30 . . 69 . 83 . 14 . 34 42 55 . . 89

Card 5: 1 . 20 38 45 53 . . . 4 15 . . . 55 66 75 . 9 17 25 . 49 . . . 89