2019年が縁起のいい年である3つの理由

あけましておめでとうございます！2019年になりました！

というわけで今回は 2019 がとても縁起のいい数であることを証明していきたいと思います！

#① 2019 はハッピー数

[ハッピー数 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%83%E3%83%94%E3%83%BC%E6%95%B0)

ハッピー数とは「各桁の数字を2乗して足し合わせる」という操作を繰りかえすと、いずれ 1 に到達するような数のことを指します。

例えば 13 はハッピー数です：

```math
13 \rightarrow 1^2 + 3^2 = 10 \rightarrow 1^2 + 0^2 =1
```


ちなみに何故ハッピー数と呼ばれるかはよくわかっていないそうです。

###ハッピー数の判定

2019 がハッピーであることを Python を使って判定していきましょう。

まず「各桁の数字を2乗して足し合わせる」操作を***「ハッピー操作」***、
$13, 10, 1, 1,...$ のようなハッピー操作から得られる列を***「ハッピー列」***と呼ぶことにします。

ハッピー数判定には、次の命題が重要です。

***「数にハッピー操作を続けていくと、必ず 1 または 4 に到達する」***

残念ながら 4 に到達した数はアンハッピー数ということになります:tired_face:

上記命題を利用した判定コードは以下です。

```python:happy.py
# ハッピー列を作る
def make_happy_seq(n):
  result = [n]
  while n not in [1, 4]:
    n = sum([int(d) ** 2 for d in str(n)])
    result.append(n)
  return result

# 判定する
def is_happy(n):
  return make_happy_seq(n)[-1] == 1
```

ここではあえて判定だけではなく列自体も取得できるようにしています。
判定するだけであれば関数を一まとめにしたほうが良いでしょう。

試しに2017年から2019年でやってみると、きちんと判定されました。

```python
print( map(is_happy, [2017, 2018, 2019]) )
# => [False, False, True]

print(make_happy_seq(2019))
# => [2019, 86, 100, 1]
```

#② 2019 はラッキー数

ハッピーなだけでなくラッキーでもあります。

[ラッキー数 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%B9%B8%E9%81%8B%E6%95%B0)

ラッキー数は少々特殊な方法で作られます。
まず、自然数を順番に並べます。

```math
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ...

```

そして、偶数番目にある数をふるい落とします。

```math
1, 3, 5, 7, 9, 11, 13, 15, 17, 19...
```

3 がふるい落とされずに残ったので、今度は 3 番目ごとに数をふるい落とします。
つまり 5, 11, 17 などがふるい落とされます。

```math
1, 3, 7, 9, 13, 15, 19, ...
```

今度は 7 が生き残ったので、7 番目ごとにふるい落とします。
すると 9 が生き残っているので、、を延々と続けて最後まで残る数がラッキー数です。

例えば 30 までのラッキー数は、

```
1, 3, 7, 9, 13, 15, 21, 25
```

の 7 つです。

###ラッキー数の判定

```python:lucky.py
# n番目の要素を削除したリストを返す
def get_nth_elements_removed(li, n):
  return list(filter(lambda i: i not in li[n-1::n], li))

# n以下のラッキー数のリストを返す
def get_lucky_num_below(n):
  if n <= 2:
    return [1]

  result = range(1, n+1, 2) # あらかじめ偶数番目はふるい落としておく
  index = 0
  step = result[index] # step番目ごとにふるい落とす

  while len(result) >= step:
    index += 1
    step = result[index]
    result = get_nth_elements_removed(result, step)

  return result

```

以下のように 2019 を判定すると True が返ってきます。

```python
# lucky数かどうかを返す
def is_lucky(n):
  return n in get_lucky_num_below(n)

print(is_lucky(2019))
# => True
```

#③2019の約数も全てラッキー数

さらに、2019 の約数（1, 3, 673）も全てラッキー数です！

```python
def are_factors_lucky(n):
  lucky_numbers = get_lucky_num_below(n)
  return all([ d in lucky_numbers for d in xrange(1,n+1) if n % d == 0 ])

print(are_factors_lucky(2019))
# => True
```

`all(list)`は、listの要素が全て Truthy な値なら`True`を返してくれる便利な関数です！

# こんなにハッピーでラッキーな年は他にあるのか

他にもこんな年があるのかを調べてみました。

2500年以下で探索してみます。

```python
numbers = range(1, 2501)
print( filter(lambda i: is_happy(i) and are_factors_lucky(i), numbers) )

# => [1, 7, 13, 31, 49, 79, 129, 193, 219, 331, 367, 409, 487, 673, 739, 937, 1009, 1039, 1093, 1303, 1533, 1663, 1857, 1933, 2019, 2221]
```

富豪的にやりましたがいくつか出てきました。

一つ前が1933年（86年前）、一つ後が2221年（202年後）なので、結構珍しいと言ってよさそうです。

[1933年の出来事](https://ja.wikipedia.org/wiki/1933%E5%B9%B4#%E3%81%A7%E3%81%8D%E3%81%94%E3%81%A8)を見てもあまりハッピーな印象がないことには目をつむってください。

#まとめ

2019年というスーパーハッピーラッキーイヤーを存分に楽しんでいきましょう:muscle::muscle::muscle:
今年もどうぞよろしくお願いいたします:bow_tone1: