竞彩足球的注数是由选号方式和过关方式确定的,为了便于描述,我以竞彩足球的胜平负,过关投注, 同时去掉让球数为例子进行展开,至于什么是胜平负,什么是 让球数我在这里就不解释了。假设我选择了三场比赛 [C1, 胜], [C2, 负], [C3, 平], [C1, 胜]的意思是: C1比赛,我选择主队胜, 我们要知道竞 彩足球里的胜负平都是针对主队来说的,[C2, 负] 表示 C2比赛主队负, [C3, 平] 表示C3比赛主客平, 这样我们就完成了一次选号, 进一步我们可以为 这个选号定义数据结构, 在 ruby 中的实现如下, 我们把这个选号方式记做为 C,

~~~ruby [ [‘C1’, 3], [‘C2’, 1], [‘C3’, 0] ] ~~~

3 表示主队胜, 1 表示主队负, 0 表示主客平。接下来我们选择过关方式, 首先我们看一张图, 此图叫做过关投注图, 过关方式

单场也叫单关, 即一场比赛的竞猜为一注, [‘C1’, 3] 为一个单关

两关, 即两场比赛的竞猜为一注, [‘C1’, 3] 和 [‘C2’, 1] 组合起来为一个两关, [‘C1’, 3] 和 [‘C3’, 0] 组合起来为一个两关, [‘C2’, 1] 和 [‘C3’, 0] 组合起来也为一个两关

三关, 即三场比赛的竞猜为一注, [‘C1’, 3], [‘C2’, 1], [‘C3’, 0] 三者组合起来为一个三关

四到八关的定义类似

由过关投注图, 我们可以知道选号 C 的过关方式可以为: 单场, 2串1, 2串3, 3串1, 3串3, 3串4, 3串6, 3串7, 现在我们来计算选号 C 在不同过关方式下的注数,所谓的注数其实就是过关集合的大小,于是计算注数,变成了求过关集合

  • 选择单场, 过关集合由单关组成, 集合大小为 3, 因而此时注数为 3

      [['C1', 3], ['C2', 1], ['C3', 0]]
    
  • 选择2串1, 过关集合由两关组成, 集合大小为 3, 因而此时注数为 3

      [
        [["C1", 3], ["C2", 1]],
        [["C1", 3], ["C3", 0]],
        [["C2", 1], ["C3", 0]]
      ]
    
  • 选择2串3, 过关集合由单关两关组成, 集合大小为 6, 其中单关双关各3个, 因而此时注数为 6

    [
      [["C1", 3], ["C2", 1]],
      [["C1", 3], ["C3", 0]],
      [["C2", 1], ["C3", 0]],
      [["C1", 3]],
      [["C2", 1]],
      [["C3", 0]]
    ]
    

3串1, 3串3, 3串4, 3串6, 3串7 等过关方式的解法类似,我们重点看下 3串4的解法,

  • 选择3串4, 过关集合由两关三关组成, 集合大小为 4, 其中两关 3 个, 三关 1个, 因而此时注数为 4
  [
    [["C1", 3], ["C2", 1]],
    [["C1", 3], ["C3", 0]],
	[["C2", 1], ["C3", 0]],
	[["C1", 3], ["C2", 1], ["C3", 0]]
  ]

从过关投注图中,我们可以看到 3*4(即3串4) 那一行有数字 3 在两关列, 数字 1 在三关列,我们可以忽略这些数字的大小,这些数字的意义就是告诉我们 过关方式3串4是由两关三关组成,其他过关方式的构造也可以由此方法得到。于是我们可以得到一张表用来表示各个过关方式的结构, 用 ruby 代码可以表示为,

BET_TABLE = {
  '1*1'=>[1],
  '2*1'=>[2],
  '2*3'=>[2, 1],
  '3*1'=>[3],
  '3*3'=>[2],
  '3*4'=>[2,3],
  '3*7'=>[3, 2, 1],
  '4*1'=>[4],
  '4*4'=>[3],
  '4*5'=>[4,3],
  '4*6'=>[2],
  '4*11'=>[2, 3, 4],
  '4*15'=>[4, 3, 2, 1],
  '5*1'=>[5],
  '5*5'=>[4],
  '5*6'=>[5, 4],
  '5*10'=>[2],
  '5*16'=>[5, 4, 3],
  '5*20'=>[3, 2],
  '5*26'=>[5, 4, 3, 2],
  '5*31'=>[5, 4, 3, 2, 1],
  '6*1'=>[6],
  '6*6'=>[5],'6*7'=>[6, 5],
  '6*15'=>[2],
  '6*20'=>[3],
  '6*22'=>[6, 5, 4],
  '6*35'=>[3,2],
  '6*42'=>[6, 5, 4, 3],
  '6*50'=>[4, 3, 2],
  '6*57'=>[6, 5, 4, 3, 2],
  '6*63'=>[6, 5, 4, 3, 2, 1],
  '7*1'=>[7],
  '7*7'=>[6],
  '7*8'=>[7,6],
  '7*21'=>[5],
  '7*35'=>[4],
  '7*120'=>[7,6,5,4,3,2],
  '8*1'=>[8],
  '8*8'=>[7],
  '8*9'=>[8,7],
  '8*28'=>[6],
  '8*56'=>[5],
  '8*70'=>[4],
  '8*247'=>[8,7,6,5,4,3,2],
  '9*1'=>[9],
  '10*1'=>[10],
  '11*1'=>[11],
  '12*1'=>[12],
  '13*1'=>[13],
  '14*1'=>[14],
  '15*1'=>[15]
}

'1*1' => [1] 表示 1串1单关组成, '2*3' => [2, 1] 表示 2串3两关单关组成,'3*4' => [2,3] 表示 3串4二关三关组成, 其他元素的意义类似。

我们开始用 ruby 程序来计算注数,


  teams = [
   ['C1', 3],
   ['C2', 1],
   ['C3', 0]
  ]
  play_kind = "3*4"

  def combination(num, teams)
    teams.combination(num).to_a
  end

  def get_bet_collection(play_kind, teams)
    BET_TABLE[play_kind].flat_map {|num|
      combination(num, teams)
    }
  end

  bet_collection = get_bet_collection play_kind, teams

  # 注数
  betsum = bet_collection.size

代码非常简单, teams 表示选号方式, play_kind 表示过关方式, combination(num, teams) 用于计算 teams 的过关集合, 比如 combination(2, teams) 可以计算出 teams 的两关集合, combination(3, teams)可以计算出 teams 的三关集合, 于是 combination(2, teams) 和 combination(3, teams) 的合集就是我们需要的3串4的过关集合, 方法 get_bet_collection 的实现原理即如此。

现在我们考虑一种稍微复杂点的情况,

  teams =  [
   ['C1', 3,1,0],
   ['C2', 1,3],
   ['C3', 0,1]
   ]
  play_kind = "3*4"

  def combination(num, teams)
    teams.combination(num).to_a
  end

  def get_bet_collection(play_kind, teams)
    BET_TABLE[play_kind].flat_map {|num|
      combination(num, teams)
    }
  end

  bet_collection = get_bet_collection play_kind, teams

选号方式 teams 变得稍微复杂了点, [‘C1’, 3, 1, 0] 可以拆成 [‘C1’, 3], [‘C1’, 1] 和 [‘C1’, 0];

[‘C2’, 1, 3] 可以拆成 [‘C2’, 1] 和 [‘C2’, 3];

[‘C3’, 0, 1] 可以拆成 [‘C3’, 0] 和 [‘C3’, 1]。

于是我们增加一个方法,

  def split_teams_to_single_teams teams
    single_teams = []
    teams.each {|team|
      team[1..-1].uniq.each {|st|
        single_teams << [team[0], st]
      }
    }
	single_teams
  end

调用 split_teams_to_single_teams teams 可以得到:

single_teams = [
                 ["C1", 3],
				 ["C1", 1],
				 ["C1", 0],
				 ["C2", 1],
				 ["C2", 3],
				 ["C3", 0],
				 ["C3", 1]
			  ]

问题来了,[“C1”, 3], [“C1”, 1] 和 [“C1”, 0] 这类属于同一场比赛的单关是不允许组合起来成为二关三关等多关, 比如 [[“C1”, 3], [“C1”, 1]]这种组合是不允许的。因此我们需要在过关集合中把这类元素去掉,于是我们对 combination 方法进行修改, 结果如下,

  def combination(num, teams)
    teams.combination(num).to_a.delete_if {|team|
	  tnames = team.map {|t| t[0]}
	  tnames.size > tnames.uniq.size
	}
  end

从而我们就能把那些由同一场比赛的单关组合成的元素去掉。最后我们的程序如下,


  def combination(num, teams)
	teams.combination(num).to_a.delete_if {|team|
	  tnames = team.map {|t| t[0] }
	  tnames.size > tnames.uniq.size
	}
  end

  def get_bet_collection(play_kind, teams)
    BET_TABLE[play_kind].flat_map {|num|
      combination(num, teams)
    }
  end

  def split_teams_to_single_teams teams
    single_teams = []
    teams.each {|team|
      team[1..-1].uniq.each {|st|
        single_teams << [team[0], st]
      }
    }
    single_teams
  end

  teams = [
   ['C1', 3,1,0],
   ['C2', 1,3],
   ['C3', 0,1]
   ]
  play_kind = "3*4"

  single_teams = split_teams_to_single_teams teams
  bet_collection = get_bet_collection play_kind, single_teams

  # 注数
  betsum = bet_collection.size
  puts bet_collection.inspect
  puts betsum

我们计算出 bet_collection 是,

[
  [["C1", 3], ["C2", 1]],
  [["C1", 3], ["C2", 3]],
  [["C1", 3], ["C3", 0]],
  [["C1", 3], ["C3", 1]],
  [["C1", 1], ["C2", 1]],
  [["C1", 1], ["C2", 3]],
  [["C1", 1], ["C3", 0]],
  [["C1", 1], ["C3", 1]],
  [["C1", 0], ["C2", 1]],
  [["C1", 0], ["C2", 3]],
  [["C1", 0], ["C3", 0]],
  [["C1", 0], ["C3", 1]],
  [["C2", 1], ["C3", 0]],
  [["C2", 1], ["C3", 1]],
  [["C2", 3], ["C3", 0]],
  [["C2", 3], ["C3", 1]],
  [["C1", 3], ["C2", 1], ["C3", 0]],
  [["C1", 3], ["C2", 1], ["C3", 1]],
  [["C1", 3], ["C2", 3], ["C3", 0]],
  [["C1", 3], ["C2", 3], ["C3", 1]],
  [["C1", 1], ["C2", 1], ["C3", 0]],
  [["C1", 1], ["C2", 1], ["C3", 1]],
  [["C1", 1], ["C2", 3], ["C3", 0]],
  [["C1", 1], ["C2", 3], ["C3", 1]],
  [["C1", 0], ["C2", 1], ["C3", 0]],
  [["C1", 0], ["C2", 1], ["C3", 1]],
  [["C1", 0], ["C2", 3], ["C3", 0]],
  [["C1", 0], ["C2", 3], ["C3", 1]]
 ]

我们看到集合由 16 个二关和 12 个三关组成, 因此注数是 28 注。