2

ウラムのスパイラルを無限に大きくするためのアイデア/コード(できればC#ですが、他の言語も機能します)を探しています(プログラムの実行時間の長さ、または停止するまで制限されます)。

代替テキスト

現在、数値はすべて素数であるため、それらのコードはかなり無関係です。興味深いのは、増え続ける (無限の) スパイラルでの配置をどのようにコーディングするか、それをサポートするにはどのようなデータ構造が適しているか、そしておそらく出力のアイデア (グラフィック ファイル、テキスト ファイル?) です。

これについてどう思いますか?

4

4 に答える 4

8

各辺の長さを考慮してください: 1, 1, 2, 2, 3, 3, 4, 4, ...

簡単なことは、各面を反復処理して、その面をレンダリングすることです。LOGO スタイルのレンダリング プリミティブを使用できます。

Angle = 0;
x=0; y = 0;
int number = 1;
int sideLength = 1;

StartLine();
for (int side = 1; side < maxSize; side++) {
 for (int k = 0; k < sideLength; k++) {
  Forward(1);
  number++;

  if (isPrime(number)) {
   StopLine();
   Ouput(number);
   StartLine();
  }
 }
 TurnLeft();
 if (side % 2 == 0) sideLength++;
}

片側の素数のみを反復処理することで、これを改善できます。

于 2009-08-20T19:48:40.673 に答える
6

次のプログラムは、数値の座標を直接計算することによって機能します。このメソッドNumberToPoint()は、次のマッピングを実行します。

0 => (x0    , y0    )
1 => (x0 + 1, y0    )
2 => (x0 + 1, y0 - 1)
3 => (x0    , y0 - 1)
4 => (x0 - 1, y0 - 1)
5 => (x0 - 1, y0    )
6 => ...

残りは非常に単純な素数テストと小さなコンソールアプリケーションです。

画像を保存するために、2つの解決策を検討します。画像全体のバッファを作成できる場合は、以下のプログラムを使用してバッファを埋めることができます。

バッファが大きすぎる場合は、メソッドを作成しPointToNumber()て計算を逆にします。メソッドは2つの座標を取り、この時点で数値を返します。この方法を使用すると、上から下、左から右に繰り返し、この時点で数値を計算し、素数であるかどうかを確認し、バッファーなしでピクセルを出力できます。ただし、どちらのソリューションでも、上下にピクセルを追加するのは非常にコストがかかるため、開始する前に画像サイズを知っておく必要があります(ただし、原因は考えられます)。

質問

  1. モジュロ、整数除算、および1000回の符号を使用せずに、係数ルックアップをNumberToPoint()堅実な数学に変換するための良いアイデアはありますか?
  2. 素数テストを短縮または高速化するための良いアイデアはありますか?

コード

using System;
using System.Drawing;
using System.Linq;
using System.Threading;

namespace UlamsSpiral
{
   public static class Program
   {
      public static void Main()
      {
         Int32 width = 60;
         Int32 height = 60;

         Console.SetWindowSize(Math.Min(width, 120), Math.Min(height, 60));
         Console.SetBufferSize(width, height);
         Console.CursorVisible = false;

         Int32 limit = (Int32)Math.Pow(Math.Min(width, height) - 2, 2);

         for (Int32 n = 1; n <= limit; n++)
         {
            Point point = NumberToPoint(n - 1, width / 2 - 1, height / 2);

            Console.ForegroundColor = n.IsPrime() ? ConsoleColor.DarkBlue : ConsoleColor.DarkGray;

            Console.SetCursorPosition(point.X, point.Y);
            Console.Write('\u25A0');

            Console.SetCursorPosition(0, 0);
            Console.Write(n);

            Thread.Sleep(10);
         }

         Console.ReadLine();
      }

      private static Point NumberToPoint(Int32 n, Int32 x0, Int32 y0)
      {
         Int32[,] c = { { -1, 0, 0, -1, 1, 0 }, { -1, 1, 1, 1, 0, 0 }, { 1, 0, 1, 1, -1, -1 }, { 1, -1, 0, -1, 0, -1 } };

         Int32 square = (Int32)Math.Floor(Math.Sqrt(n / 4));

         Int32 index;
         Int32 side = (Int32)Math.DivRem(n - 4 * square * square, 2 * square + 1, out index);

         Int32 x = c[side, 0] * square + c[side, 1] * index + c[side, 2];
         Int32 y = c[side, 3] * square + c[side, 4] * index + c[side, 5];

         return new Point(x + x0, y + y0);
      }

      private static Boolean IsPrime(this Int32 n)
      {
         if (n < 3) return (n == 2);
         return Enumerable.Range(2, (Int32)Math.Sqrt(n)).All(m => n % m != 0);
      }
   }
}
于 2009-08-20T22:15:37.427 に答える
0

可能な方法の 1 つは、線形配列またはリストを作成して数値を格納し、数式を使用して方向を変更する必要があるタイミングを判断することです。出力に関しては、ウィキペディアの素数に黒いピクセルを描画し、他のすべての数字に白いピクセルを描画する例が好きでした。

于 2009-08-20T19:23:51.533 に答える
0

数字を作成する「ジェネレーター」プロセス/スレッドと、それらを表示する「リーダー/ディスプレイ」プロセス/スレッドを持たないのはなぜですか。その後、作成をディスプレイから分離することができ、プログラムは実際にはデータの量によってのみ制限されます「リーダー/ディスプレイ」が消費します。「ジェネレーター」には、かなり一定のサイズのデータ​​セットが必要であると想定しているためです。

于 2009-08-20T22:49:55.457 に答える