Created
May 14, 2021 05:05
-
-
Save WhiteGrouse/ad3c77603ab8e45d74b4901f0ea670d3 to your computer and use it in GitHub Desktop.
原点からの距離が一定で、どの2点をとっても距離が同じであるような座標をN次元空間にN+1個配置する方法
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Linq; | |
| namespace NPlusOneCoordProblem | |
| { | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| double R = 2; | |
| int N = 100; | |
| var solver = new Solver(R, N); | |
| PrintCoordinates(solver.N, solver.Get()); | |
| for (int i = 2; i <= N; i++) | |
| { | |
| solver.Next(); | |
| solver.Check(); | |
| PrintCoordinates(solver.N, solver.Get()); | |
| } | |
| } | |
| static void PrintCoordinates(int n, double[][] coordinates) | |
| { | |
| Console.WriteLine("N = {0}", n); | |
| foreach (var coord in coordinates) | |
| { | |
| Console.WriteLine("({0})", string.Join(", ", coord.Select(v => v.ToString("F3")))); | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// 原点からの距離が一定で、どの2点をとっても距離が同じであるような座標をN次元空間にN+1個配置する | |
| /// </summary> | |
| class Solver | |
| { | |
| public readonly double Radius; | |
| public int N { get; private set; } | |
| private readonly double[,] _Matrix; | |
| public Solver(double radius, int maxN) | |
| { | |
| Radius = radius; | |
| _Matrix = new double[maxN + 1, maxN]; | |
| _Matrix[0, 0] = radius; | |
| _Matrix[1, 0] = -radius; | |
| N = 1; | |
| } | |
| public void Next() | |
| { | |
| // 1. 新しく追加した座標軸上に、各座標間の距離が等しくなるような座標を配置 | |
| // 2. 重心を原点に移動 | |
| // 3. 原点からの距離を調整 | |
| N++; | |
| double length = 2 * _Matrix[0, 0]; | |
| _Matrix[N, N - 1] = Math.Sqrt(Math.Pow(length, 2) - Math.Pow(Radius, 2)); | |
| for (int i = 0; i < N + 1; i++) | |
| _Matrix[i, N - 1] -= _Matrix[N, N - 1] / (N + 1); | |
| for (int i = 0; i < N + 1; i++) | |
| for (int j = 0; j < N; j++) | |
| _Matrix[i, j] = _Matrix[i, j] / _Matrix[N, N - 1] * Radius; | |
| } | |
| public void Check() | |
| { | |
| for (int i = 0; i < N + 1; i++) | |
| { | |
| var r = Enumerable.Range(0, N).Select(d => Math.Pow(_Matrix[i, d], 2)).Sum(); | |
| if (Math.Abs(r - Math.Pow(Radius, 2)) > 0.0000001) | |
| { | |
| throw new Exception(); | |
| } | |
| for (int j = i + 1; j <= N; j++) | |
| { | |
| var distance2 = Enumerable.Range(0, N).Select(d => Math.Pow(_Matrix[i, d] - _Matrix[j, d], 2)).Sum(); | |
| var length = 2 * _Matrix[0, 0]; | |
| if (Math.Abs(distance2 - Math.Pow(length, 2)) > 0.0000001) | |
| { | |
| throw new Exception(); | |
| } | |
| } | |
| } | |
| } | |
| public double[][] Get() | |
| { | |
| var result = new double[N + 1][]; | |
| for (int i = 0; i < N + 1; i++) | |
| { | |
| result[i] = new double[N]; | |
| for (int j = 0; j < N; j++) | |
| result[i][j] = _Matrix[i, j]; | |
| } | |
| return result; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment