先日、以下の動画を見ました。
ぷりんは思いました。
「そんな雑な計算で満足すんの??」
ということで、真面目に追試してみます。
問題の条件
通常のシャトルランのルールは以下のサイトにまとまっていたので、この記事では詳細は割愛します。
音源は youtube で簡単に聞くことができます。例えば↓
ルールの重要な部分だけまとめると、以下の通りです。
- 平行線の間隔は20m
- 所定の法則に則って決められた時間内に一方の直線から他方に移動することを繰り返す
- 二回連続でラインを踏めなければアウト
これらのルールに則った上で
- 法則を適当に外挿し、仮想的にいくらでもシャトルランが続く状況を作る
- 平行線の間は光速 で移動できるものとする
- 方向転換の時間は無視する
の条件で
- 最大レベル
- 最後に平行線に到達した時点までの累計移動回数
- 同累計移動距離
- 同累計移動時間
をなるべく正確に計算したいと思います。
条件の整理
公式?では247回までの折り返し回数を想定しており、具体的に間隔が与えられています。以下は wikipedia に掲載されていた法則を抜粋したものです。
レベル | 折り返し回数 | 速度 (km/h) | 折り返し時間 (秒) | レベル内 合計時間(秒) |
---|---|---|---|---|
1 | 7 | 8 | 9 | 63 |
2 | 8 | 9 | 8 | 64 |
3 | 8 | 9.5 | 7.58 | 60.63 |
4 | 9 | 10 | 7.2 | 64.8 |
5 | 9 | 10.5 | 6.86 | 61.71 |
6 | 10 | 11 | 6.55 | 65.5 |
7 | 10 | 11.5 | 6.26 | 62.61 |
8 | 11 | 12 | 6 | 66 |
9 | 11 | 12.5 | 5.76 | 63.36 |
10 | 11 | 13 | 5.54 | 60.92 |
11 | 12 | 13.5 | 5.33 | 64 |
12 | 12 | 14 | 5.14 | 61.71 |
13 | 13 | 14.5 | 4.97 | 64.55 |
14 | 13 | 15 | 4.8 | 62.4 |
15 | 13 | 15.5 | 4.65 | 60.39 |
16 | 14 | 16 | 4.5 | 63 |
17 | 14 | 16.5 | 4.36 | 61.09 |
18 | 15 | 17 | 4.24 | 63.53 |
19 | 15 | 17.5 | 4.11 | 61.71 |
20 | 16 | 18 | 4 | 64 |
21 | 16 | 18.5 | 3.89 | 62.27 |
この表から法則性を見出し、高いレベルまで外挿します。
じっと眺めると、折り返し時間 (秒) とレベル内合計時間 (秒) の間に
最大レベル
光速を (m/s)とすれば、ギリギリ光速を超えないレベル は
となるのでを満たします。よってとなります。累計移動回数
累計移動回数 は
と表されます。 を で割ったときの商を あまりを とするととなるのでとなります。 の部分の1サイクル分の和を計算するととなります。 を が小さい順に並べるととなります。 とおけばとなります。ちなみに が大きいところが和に影響すると考えてとしても概ね近い値が出ます。(7桁一致)累計移動距離
累計移動距離は
になります。これは約 光年です。累計移動時間
もはや厳密に計算するのが厳しいため、近似計算を行います。 が大きい近似を行うと
となります。これを について の範囲で和を取りますが、ここでを用いればとなります。これは約 年に相当します。[追記: 2020/08/22]
プログラムを組んで計算してみたところ
結果
以上をまとめると次のようになります。
- 最大レベル
21億5850万5681
- 累計移動回数
97京655兆5941億1501万5833回
- 同累計移動距離
1941京3111兆8823億0031万6660m (約2053.373光年)
- 同累計移動時間
約4106.746年
[追記: 2020/08/22]
129510342313.7983240214824584秒(若干の誤差含む)
いやはや、光ってすごいですね。
追記(2020/08/22): 累計移動時間の計算プログラム
以下の Julia のコードで計算しました。
mutable struct LongFloat seisu::Int shosu::Float64 end function Base.show(io::IO, x::LongFloat) s_seisu = string(x.seisu) s_shosu = string(x.shosu) print(io, s_seisu, " + ", s_shosu) end function simplify!(x::LongFloat) if x.shosu < 0 || x.shosu >= 1 n = floor(Int, x.shosu) x.seisu += n x.shosu -= n end end function num(level::Int)::Int if level==1 return 7 else return div(92 + 5*level, 12) end end function time!(level::Int, cum_time::LongFloat) if level==1 cum_time.seisu += 63 else numer = num(level) * 144 denom = 16 + level add_sei = div(numer, denom) add_sho = (numer % denom) / denom cum_time.seisu += add_sei cum_time.shosu += add_sho simplify!(cum_time) end end function main() LMAX = 2158505681 all_time = LongFloat(0, 0.) for level = 1:LMAX time!(level, all_time) end println(all_time) end main()