自然数の対を自然数に写像する関数（全単射）それとRubyで九九を作ってみた

表題のとおりの内容で、ただのメモ書きです。
どっかにメモすればいいのだけど毎回計算してるのでここに投稿することにします。

# 全単射な写像

二つの自然数を一つの自然数に変換する関数で、結果に重複が無いように作りたい。
こういうのがあると例えばDBの主キーが二つ（両方整数）あるときに、一つの整数をキーにして検索できる。

こうなった。（この例では、1以上の自然数）

```rb
f = ->(x,y){ (x+y)*(x+y-1)/2 - (x-1) }
```

`f`の逆関数はまだ作れていない。
<del>面倒そうなので</del> 頭の良い人、教えてくださいお願いします。

## 追記

2個の自然数を1個に集約できるので、それを(N-1)回繰り返せば任意の個数Nの自然数を1個にまとめることができる。

# Rubyで九九

作った関数の実行結果がみたかったので作った。
ついでに遊んでみた。

```rb
def show_table(list, f = nil, width: nil)
  f = ->(x,y){ yield x, y } if block_given?
  width = f[list.last, list.last].to_s.size + 1 unless width
  show = ->x{ x.to_s.rjust(width) }
  print show['']
  puts list.map(&show).join
  list.each do |y|
    puts [show[y], *list.map{|x| show[f[x, y]] }].join
  end 
end

puts '9 x 9'
show_table(1..9){|x, y| x * y } 

puts
puts 'one based'
f = ->(x,y){ (x+y)*(x+y-1)/2 - (x-1) }
show_table(1..9, f)

puts
puts 'zero based'
f = ->(x,y){ (x+y+1)*(x+y+2)/2 - (x+1) }
show_table(0..9, f)

puts
puts 'hexadecimal chars'
hex = [*'0'..'9',*'a'..'f']
show_table(hex, &:+)
```


出力はこんな感じ

```text
9 x 9
     1  2  3  4  5  6  7  8  9
  1  1  2  3  4  5  6  7  8  9
  2  2  4  6  8 10 12 14 16 18
  3  3  6  9 12 15 18 21 24 27
  4  4  8 12 16 20 24 28 32 36
  5  5 10 15 20 25 30 35 40 45
  6  6 12 18 24 30 36 42 48 54
  7  7 14 21 28 35 42 49 56 63
  8  8 16 24 32 40 48 56 64 72
  9  9 18 27 36 45 54 63 72 81

one based
       1   2   3   4   5   6   7   8   9
   1   1   2   4   7  11  16  22  29  37
   2   3   5   8  12  17  23  30  38  47
   3   6   9  13  18  24  31  39  48  58
   4  10  14  19  25  32  40  49  59  70
   5  15  20  26  33  41  50  60  71  83
   6  21  27  34  42  51  61  72  84  97
   7  28  35  43  52  62  73  85  98 112
   8  36  44  53  63  74  86  99 113 128
   9  45  54  64  75  87 100 114 129 145

zero based
       0   1   2   3   4   5   6   7   8   9
   0   0   1   3   6  10  15  21  28  36  45
   1   2   4   7  11  16  22  29  37  46  56
   2   5   8  12  17  23  30  38  47  57  68
   3   9  13  18  24  31  39  48  58  69  81
   4  14  19  25  32  40  49  59  70  82  95
   5  20  26  33  41  50  60  71  83  96 110
   6  27  34  42  51  61  72  84  97 111 126
   7  35  43  52  62  73  85  98 112 127 143
   8  44  53  63  74  86  99 113 128 144 161
   9  54  64  75  87 100 114 129 145 162 180

hexadecimal chars
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
  0 00 10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0
  1 01 11 21 31 41 51 61 71 81 91 a1 b1 c1 d1 e1 f1
  2 02 12 22 32 42 52 62 72 82 92 a2 b2 c2 d2 e2 f2
  3 03 13 23 33 43 53 63 73 83 93 a3 b3 c3 d3 e3 f3
  4 04 14 24 34 44 54 64 74 84 94 a4 b4 c4 d4 e4 f4
  5 05 15 25 35 45 55 65 75 85 95 a5 b5 c5 d5 e5 f5
  6 06 16 26 36 46 56 66 76 86 96 a6 b6 c6 d6 e6 f6
  7 07 17 27 37 47 57 67 77 87 97 a7 b7 c7 d7 e7 f7
  8 08 18 28 38 48 58 68 78 88 98 a8 b8 c8 d8 e8 f8
  9 09 19 29 39 49 59 69 79 89 99 a9 b9 c9 d9 e9 f9
  a 0a 1a 2a 3a 4a 5a 6a 7a 8a 9a aa ba ca da ea fa
  b 0b 1b 2b 3b 4b 5b 6b 7b 8b 9b ab bb cb db eb fb
  c 0c 1c 2c 3c 4c 5c 6c 7c 8c 9c ac bc cc dc ec fc
  d 0d 1d 2d 3d 4d 5d 6d 7d 8d 9d ad bd cd dd ed fd
  e 0e 1e 2e 3e 4e 5e 6e 7e 8e 9e ae be ce de ee fe
  f 0f 1f 2f 3f 4f 5f 6f 7f 8f 9f af bf cf df ef ff
```