Skip to content

Instantly share code, notes, and snippets.

@WhiteGrouse
Created May 14, 2021 05:05
Show Gist options
  • Select an option

  • Save WhiteGrouse/ad3c77603ab8e45d74b4901f0ea670d3 to your computer and use it in GitHub Desktop.

Select an option

Save WhiteGrouse/ad3c77603ab8e45d74b4901f0ea670d3 to your computer and use it in GitHub Desktop.
原点からの距離が一定で、どの2点をとっても距離が同じであるような座標をN次元空間にN+1個配置する方法
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