競馬の枠番ってどうやって計算するんじゃろなと考えながら、こんなものが出来上がりました。
VBAの標準モジュールにOption Explicitから始まるコードをコピペした後、ワークシートのセルにこの関数を使用する数式を入れれば、枠番を出してくれます。
MITライセンスにするため、前置きのコメントが長いですがご容赦ください。
このプログラムについてのご質問やツッコミがありましたら、ツイッターやメールでお願いいたします。
プログラムバージョン:1.001 変数名や処理を微妙に変えました。返り値をVariantにして、不正な値を入力した時に#NUM!を返すようにしました。
プログラムバージョン:1.002 For文でゴリ押ししていたのを、シンプルな数式に変更。
プログラムバージョン:1.003 その他のエラーメッセージが表示されない状態だったので修正。
小の枠に入るパターンの条件数式を修正。切り捨て、切り上げしないで良いのに気がついた。プログラムは変更していません。
計算方法
出走数 ≦ 枠数 の場合
枠番 = 馬番
例:8頭立て以下の時。
出走数 > 枠数 の場合
まず以下の物を先に計算すること。
小の枠数 = 枠数 - 出走数を枠数で割った時の余り
小の枠に入る数 = 出走数 ÷ 枠数 (計算結果を小数点以下切り捨て)
例:18頭立ての時の1~6枠が小の枠数、その小の枠数に入る頭数が2頭。
馬番 ≦ 小の枠数 × 小の枠に入る数 の場合
枠番 = 馬番 ÷ 小の枠に入る数 (計算結果を小数点以下切り上げ)
例:18頭立てで12番までが該当。
それ以外の場合
枠番 = (馬番 - 小の枠数 × 小の枠に入る数) ÷ (小の枠に入る数 + 1) + 小の枠数 (計算結果を小数点以下切り上げ)
例:18頭立てで13番以降が該当。
数式
\[
\begin{array}{l}
出走数をa,\; 枠数をb,\; 馬番・車番をx,\; 求める枠番をyとする。\\
この時、a \gt 0,\; b \gt 0,\; 0 \lt x \leqq a\;とする。\\
小の枠数をp,\; 小の枠に入る数をqとすると、\\
p=b-(a \bmod b)\\
q=\left\lfloor \dfrac{a}{b} \right\rfloor
\end{array}
\]
\[
y=
\begin{eqnarray}
\left\{
\begin{array}{cc}
x & (a \leqq b) \\
\left\lceil \dfrac{x}{q} \right\rceil & (x \leqq pq) \\
\left\lceil \dfrac{x - pq}{q + 1} \right\rceil + p & (otherwise)
\end{array}
\right.
\end{eqnarray}
\]
(MathJaxで記載しています。もし正しく表示されていなかったらゴメンナサイ。)
Option Explicit
' GetBracketNum関数 番号と出走数から枠番を出す関数
' Copyright (C) 2020-2023 マヴユーユ (twitter:mavyuuyu)
' このプログラムのライセンスは、MIT Licenseです。
' This software is released under the MIT License.
' http://opensource.org/licenses/mit-license.php
' MIT Licenseの日本語訳は、以下のURLをご参照ください。
' https://ja.osdn.net/projects/opensource/wiki/licenses%2FMIT_license
'
' ******************** 使い方 ********************
' この関数は、シート上のセルでも計算することが出来ます。
' 数式例1・競馬の場合: =GetBracketNum(馬番, 出走数)
' 数式例2・競輪9車立ての場合: =GetBracketNum(車番, 9, 6)
' 枠数は省略すると、8が指定されます。
' ************************************************
Private Const ERR_INVALID_NUM = 10001
Public Function GetBracketNum( _
ByVal num As Long, _
ByVal entries As Long, _
Optional ByVal brackets As Long = 8 _
) As Variant
On Error GoTo ErrorHandler
If Not IsValidNum(num, entries, brackets) Then
Err.Raise ERR_INVALID_NUM
ElseIf entries <= brackets Then
GetBracketNum = num
Exit Function
ElseIf CalcLowerBracket(num, entries, brackets) <= _
CalcLowerLimit(entries, brackets) Then
GetBracketNum = CalcLowerBracket(num, entries, brackets)
Exit Function
Else
GetBracketNum = CalcHigherBracket(num, entries, brackets)
Exit Function
End If
ErrorHandler:
If Err.Number = ERR_INVALID_NUM Then
GetBracketNum = CVErr(xlErrNum)
Exit Function
End If
MsgBox "エラーが発生しました。" & vbCrLf & _
"エラー番号:" & Err.Number & vbCrLf & _
Err.Description
Exit Function
End Function
Private Function CalcLowerLimit(ByVal entries As Long, _
ByVal brackets As Long) As Long
CalcLowerLimit = brackets - (entries Mod brackets)
End Function
Private Function CalcLowerBracket(ByVal num As Long, ByVal entries As Long, _
ByVal brackets As Long) As Long
CalcLowerBracket = _
WorksheetFunction.RoundUp( _
num / WorksheetFunction.RoundDown(entries / brackets, 0), 0)
End Function
Private Function CalcHigherBracket(ByVal num As Long, ByVal entries As Long, _
ByVal brackets As Long) As Long
Dim base As Long
base = WorksheetFunction.RoundDown(entries / brackets, 0)
Dim a As Long
a = WorksheetFunction.RoundUp( _
(num - CalcLowerLimit(entries, brackets) * base) / (base + 1), 0)
CalcHigherBracket = CalcLowerLimit(entries, brackets) + a
End Function
Private Function IsValidNum( _
ByVal num As Long, _
ByVal entries As Long, _
ByVal brackets As Long _
) As Boolean
If num > 0 And _
entries > 0 And _
brackets > 0 And _
entries >= num Then
IsValidNum = True
Exit Function
Else
IsValidNum = False
Exit Function
End If
End Function
数式として使用するには、標準モジュールに上記のプログラムをコピペした後、以下のように数式を入力します。