Pythonで一般項によりコラッツ奇数遷移を出力する方法

### コラッツ演算しないでコラッツ一般項を使って計算する
実行結果は、下のように**奇数のみ**の演算結果を出力します。
でも、3かけて1を足したり、2で割ったり…はしていません。
した方が早いですけれどね:sweat_smile:
一般項を用いて、ひたすら計算しました（させました）。
これは、一般項が合っていますよ～という答え合わせになりますね:sparkles::sparkles:

```py:実行結果
PS C:\Users\default\python> python colla_cal ↵

2桁までのすきな奇数を入力してください：11 ↵
奇数のみのコラッツ計算: [11, 17, 13, 5, 1]

PS C:\Users\default\python> python colla_cal ↵

2桁までのすきな奇数を入力してください：13 ↵
奇数のみのコラッツ計算: [13, 5, 1]

PS C:\Users\default\python> python colla_cal ↵

2桁までのすきな奇数を入力してください：27 ↵
奇数のみのコラッツ計算: [27, 41, 31, 47, 71, 107, 161, 121, 91, 
137, 103, 155, 233, 175, 263, 395, 593, 445, 167, 251, 377, 283, 
425, 319, 479, 719, 1079, 1619, 2429, 911, 1367, 2051, 3077, 577, 
433, 325, 61, 23, 35, 53, 5, 1]

PS C:\Users\default\python> python colla_cal ↵

2桁までのすきな奇数を入力してください：55 ↵
奇数のみのコラッツ計算: [55, 83, 125, 47, 71, 107, 161, 121, 91, 
137, 103, 155, 233, 175, 263, 395, 593, 445, 167, 251, 377, 283, 
425, 319, 479, 719, 1079, 1619, 2429, 911, 1367, 2051, 3077, 577, 
433, 325, 61, 23, 35, 53, 5, 1]
```


```py:colla_cal
#--------------------------------------------------------------
#    一般項により奇数を計算し、s,tの値とともにリスト作成
#    リストから奇数を検索して求めたs,tより次の奇数を計算
#    1になるまで繰り返す
#--------------------------------------------------------------

n = 513	# 計算するtの上限
m = 4	# 計算するsの上限

num_i = int(input('2桁までのすきな奇数を入力してください：'))

odd_list = []		# 奇数リストを用意

#=======奇数eを計算し、s,tの値とともにリストに追加=======

for t in range(1, n+1): 	# tを指定
	
	for s in range(1, m+1): 	# sを指定
		
		tmp = int((4 ** (s - 1) * 4 - 1) / 3 + 8 * (t - 1) * 4 ** (s - 1) )
		if tmp < 10000:		#4桁以下の奇数だけリストにする
			odd_sublist_e = [] #奇数サブリストeを用意
			odd_sublist_e.append(tmp) 
			odd_sublist_e.append(s)
			odd_sublist_e.append(t)
			odd_sublist_e.append(0)	
			odd_list. append(odd_sublist_e) # 奇数サブリストe[奇数e,s,t,0]を奇数リストに追加
	
#=======奇数oを計算し、s,tの値とともにリストに追加=======

for t in range(1, n+1): 	# tを指定
	
	for s in range(1, m+1): 	# sを指定

		tmp = int( (4 ** (s - 1) * 10 - 1) / 3 + 4 * (t - 1) * 4 ** (s - 1) )
		if tmp < 10000:		#4桁以下の奇数だけリストにする
			odd_sublist_o = [] #奇数サブリストoを用意
			odd_sublist_o.append(tmp)
			odd_sublist_o.append(s)
			odd_sublist_o.append(t)
			odd_sublist_o.append(1)	
			odd_list. append(odd_sublist_o) # 奇数サブリストo[奇数e,s,t,1]を奇数リストに追加
	
odd_list = sorted(odd_list) 	# 奇数リストを1列目の奇数で昇順にソート
#print(odd_list)

list_i = [] 	# 奇数が一致したときの配列を入れるリストを用意
list_cal = [] 	# 計算結果を入れるリストを用意
list_cal.append(num_i) # 入力した奇数を計算結果リストに追加

while num_i != 1:		# num_iが1になるまで処理する
	
	list_i = list(filter(lambda x: x[0] == num_i, odd_list)) 	#1列目がnum_iである配列を取得

	if list_i == []: 	#エラー処理
		print("******* error_*******   num_i: " + str(num_i))
		break

	t_i = int(list_i[0][2]) 	#list_iからtの値を取得
	s_i = int(list_i[0][1]) 	#list_iからsの値を取得

	if num_i == (4 ** (s_i - 1) * 4 - 1) / 3 + 8 * (t_i - 1) * 4 ** (s_i - 1) :	#eの式の奇数である場合
		num_inext = 6 * t_i - 5		# 次の奇数を計算
		list_cal.append(num_inext)	# 求めた奇数を計算結果リストに追加
	else:					# oの式の奇数である場合
		num_inext = 6 * t_i - 1		# 次の奇数を計算
		list_cal.append(num_inext)	# 求めた奇数を計算結果リストに追加
	num_i = num_inext			# num_iに求めた奇数をセット

print("奇数のみのコラッツ計算: " + str(list_cal))
```
### 計算方法
まず、s,tの値を1から順に一般項に代入して奇数を計算し、参照するためのリストを作成します。

```py:
[[1, 1, 1, 0], [5, 2, 1, 0], [21, 3, 1, 0], [85, 4, 1, 0], [9, 1, 2, 0], 
[37, 2, 2, 0], [149, 3, 2, 0], [597, 4, 2, 0], [17, 1, 3, 0], [69, 2, 3, 0], 
[277, 3, 3, 0], [1109, 4, 3, 0], [25, 1, 4, 0], [101, 2, 4, 0], [405, 3, 4, 0], 
[1621, 4, 4, 0], [33, 1, 5, 0], [133, 2, 5, 0], [533, 3, 5, 0], [2133, 4, 5, 0], 
[41, 1, 6, 0], [165, 2, 6, 0], [661, 3, 6, 0], [2645, 4, 6, 0], [49, 1, 7, 0], 
[197, 2, 7, 0], [789, 3, 7, 0], [3157, 4, 7, 0], [57, 1, 8, 0], [229, 2, 8, 0],
[917, 3, 8, 0], [3669, 4, 8, 0], [65, 1, 9, 0], [261, 2, 9, 0], [1045, 3, 9, 0], 
[4181, 4, 9, 0], [73, 1, 10, 0], [293, 2, 10, 0], [1173, 3, 10, 0], 
[4693, 4, 10, 0], [81, 1, 11, 0], [325, 2, 11, 0], [1301, 3, 11, 0], …
```
上のような [奇数, s, t, (eタイプなら 0 or oタイプなら 1)] のようなリストを適当な数（ここでは2桁の奇数が1までの計算で通る奇数をすべて参照できるだけの最小のsとtの値をセットしました）計算した後に、奇数の昇順に並び替えします。
このリストから、最初に入力された奇数を検索してs,tの値を取得し、そのs,tを一般項に代入して、eタイプの奇数か、oタイプの奇数かを判定します。eタイプであれば、6t-5で次の奇数を求め、oタイプであれば、6t-1で次の奇数を求めます。
この計算を奇数が1になるまで繰り返し、奇数の遷移をリストにして出力します。

:::note warn
eタイプの奇数か、oタイプの奇数かの値(0 or 1)をリストに含めていますが、このフラグは計算に使っていないので、なくてもいいデータです。今回必要ないですが、s,t,フラグの3つの組み合わせでユニークとなり、重要な値なのでフラグもデータに入れました
:::
### まとめ
:::note info
このコードは、2桁の奇数のコラッツ計算の答え合わせ（手計算にもコード計算にも！）にどうぞご利用ください
:::

・・・ということで、こっそり言います:joy:が
ここで駆使した、下記の**コラッツ一般項は正しい**と思われます:raised_hand:


<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048186/a2f4832b-641a-4272-9972-c225ca75b671.jpeg">

最後までお読みいただき、ありがとうございました！