RSS Amplifier

Eric's Site · Feb 10, 2022

Simulating bingo for fun

0
Sign in to vote or save

This page cannot be shown here. You can still read it on the original site — the toolbar below keeps your place in the directory.

The other day, I was playing bingo with the family. The rules are simple, each person has a 5x5 card with the center number “free”. You pick numbers from 1 to 75 without replacement until some matches 5 in a row on their card (diagonal matches are allowed). Playing with young kids, I knew there was a clock ticking on how long their attention would last. We had three bingo cards going. How many…

The other day, I was playing bingo with the family. The rules are simple, each person has a 5x5 card with the center number “free”. You pick numbers from 1 to 75 without replacement until some matches 5 in a row on their card (diagonal matches are allowed).

Playing with young kids, I knew there was a clock ticking on how long their attention would last. We had three bingo cards going.

How many numbers would we have to pick for someone to win?

There may actually a closed for solution estimate the mean number of picks for someone to get Bingo with n cards in play. Alas, that is far beyond my remaining math skills. Luckily, I can simply write a Montecarlo simulation. This is about the same difficulty of an Advent of Code problem.

My solution ended up with three classes: board, game, and experiment.

Working on a project like this, I’m still frustrated with code reloading in `irb`. I should probably be able to wire zeitwerk (code loader used in Rails) to accomplish this in the future.

Final solution: playing by yourself you’ll need to pick ~41 numbers on average. And with the three of us, this drops to ~35. So now I have a good idea of how long these games will go on for.



Maybe I'll come back later and add the variance to know how often I’m going to have to wait a lot longer.

Here is the code I wrote to simulate bingo.
module Bingo
  class Experiment
    def run(epsilon = 2, boards=1)
      @games = []
      last_mean = 0
      while true do
        @games.push Game.new.play(boards)
        mean = @games.sum.fdiv(@games.size)
        if (mean-last_mean).abs < epsilon
          return mean
        end
        last_mean = mean
      end
    end
  end
  class Game
    def initialize
      reset
      @i = -1
    end
    def play(board_count=1)
      boards = board_count.times.map { Board.new }
      5.times { draw }
      while(boards.none? { |b| b.win?(drawn) }) do
        draw
      end
      @i
    end
    def drawn
      return [] if @i < 0
      @pulls[0..@i]
    end
    def draw
      @i+=1
      drawn
    end
    def reset
      @pulls = pulls
    end
    def pulls
      1.upto(75).to_a.shuffle
    end
  end
  class Board
    attr_reader :board
    def initialize
      # order col, row
      @board = init_board
    end
    def win?(picks)
      full_picks = picks + [0]
      return true if match?(full_picks, diag_1)
      return true if match?(full_picks, diag_2)
      0.upto(4).each do |i|
        return true if match?(full_picks, col_vals(i))
        return true if match?(full_picks, row_vals(i))
      end
      false
    end
    def match?(a1, a2)
      (a1 & a2).length == 5
    end
    def to_s
      @board
    end
    def pretty
      0.upto(4).each do |i|
        puts row_vals(i).map { |c| c.to_s.rjust(3) }.join
      end
    end
    def col_vals(j)
      @board[j]
    end
    def row_vals(i)
      @board.map { |c| c[i] }
    end
    def diag_1
      @board.map.with_index { |c, i| c[i] }
    end
    def diag_2
      @board.map.with_index { |c, i| c[4-i] }
    end
    private
    def init_board
      5.times.map do |i|
        if i == 2
          (i*15+1).upto(i*15+15).to_a.shuffle[0..3].insert(2, 0) # center is always a match
        else
          (i*15+1).upto(i*15+15).to_a.shuffle[0..4]
        end
      end
    end
  end
end
# write out a CSV to stdout
puts "cards,mean win round"
1.upto(50) do |i|
  result = Bingo::Experiment.new.run(0.001, i)
  puts "#{i},#{result}"
end

Read on /posts/8-simulating-bingo-for-fun/

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.