Nickolay.info. PHP. Спиральные коврики из чисел

Чиркая вот эту заметку, вспомнил о сделанном ещё в детстве "открытии" - все числа, набранные на клавиатуре калькулятора

"прямоугольником", делятся без остатка на 11, например, 1397, 5632, 4631 и т.д. Прямоугольник может быть и с одной "нулевой" стороной, вроде 7997, и даже вовсе "вырожденным", например, 4444. Более того, тем же свойством обладают и числа, полученные аналогичным проходом по диагоналям клавиатуры, такие как 1991, 6886, 6842 или 3773. Неизвестно почему это навело меня на мысль, что обходом по спирали можно нанести на картинку точки-числа, подчиняющиеся какому-нибудь общему свойству, например, являющиеся простыми, кратные тем же 11 и т.д.

Ну а вечером сразу же выбрал время проверить, не люблю такие вещи откладывать.

Вот простые числа, не превышающие 160000, вписанные в спираль:

Спираль простых чисел из диапазона 1-160000

Не правда ли, чувствуется закон распределения, пусть и не такой примитивный как для чисел, кратных 11:

Спираль из чисел, кратных 11

(тело функции simple заменено оператором return ($n%11);).

Для создания таких картинок можно было найти что-то явно побыстрее PHP, но ничего подходящего под рукой не было... вот полный текст скрипта:

<?php
set_time_limit (45); //Лимит времени выполнения

function get_rgb_from_hex ($hex) { //Цвет RRGGBB (Hex) в массив (r,g,b) десятичные
 $rgb=array();
 for ($i=0; $i<6; $i+=2) $rgb[]=hexdec(substr($hex,$i,2));
 return $rgb;
}

function simple ($n) { //Проверка положительного числа на простоту - неоптимальна!
 if ($n<4) return true;
 if ($n%2==0) return false;
 $n2=floor($n/2);
 for ($i=3; $i<$n2; $i+=2) if ($n%$i==0) return false;
 return true;
}

//Обработка параметров
$params = array ('xy','back','lines','d','cw');
while (list($num,$var) = each($params)) {
 if (!empty($_GET[$var])) $$var = intval($_GET[$var]);
 else $$var=0;
}

if (!$xy) $xy = 400;
if ($xy<10) $xy=10;
if ($xy>1000) $xy=1000; // Размер стороны картинки 10-1000
$dir=0;
if ($d>-1 and $d<4) $dir=$d; //Направление первого шага

$transparent=false; //Прозрачность
$rback=$gback=$bback=255;
if (isset($_GET['back'])) { //Цвет фона RRGGBB, если меньше 0 - прозрачный
 $back=htmlspecialchars(trim($_GET['back']));
 if (preg_match("#^[0-9A-Fa-f]{6}$#",$back)) list ($rback,$gback,$bback) = get_rgb_from_hex ($back);
 else if (intval($back)<0) $transparent=true;
}
$rlines=$glines=$blines=0;
if (isset($_GET['lines'])) { //Цвет линий RRGGBB
 $lines=htmlspecialchars(trim($_GET['lines']));
 if (preg_match("#^[0-9A-Fa-f]{6}$#",$lines)) list ($rlines,$glines,$blines) = get_rgb_from_hex ($lines);
}

//Отрисовка
if (!extension_loaded('gd')) die('Cannot initialize GD library');
$img = @imagecreatetruecolor($xy, $xy) or die ('Cannot initialize new GD image stream');
$back = imagecolorallocate($img,$rback,$gback,$bback); 
$lines = imagecolorallocate($img,$rlines,$glines,$blines);
imagefilledrectangle ($img, 0, 0, $xy, $xy, $back);
if ($transparent) imagecolortransparent($img, $back);

$x=$y=round($xy/2);
$step=1;
$k=0;
$cnt=1;
$xy2=$xy*$xy;
do {
 switch ($dir) {
  case 0: $dx=1; $dy=0; break;  //0 - вправо
  case 1: $dx=0; $dy=-1; break; //1 - вверх
  case 2: $dx=-1; $dy=0; break; //2 - влево
  case 3: $dx=0; $dy=1; break;  //3 - вниз
 }
 for ($s=1; $s<=$step; $s++) {
  if ($x>-1 and $x<$xy and $y>-1 and $y<$xy) {
   if (simple($cnt)) imagesetpixel ($img, $x, $y, $lines);
   $cnt++;
  }
  $x+=$dx;
  $y+=$dy;
 }
 if ($cw) { //крутить спираль по часовой
  $dir--; if ($dir==-1) $dir=3;
 }
 else {
  $dir++; if ($dir==4) $dir=0;
 }
 $k++;
 if ($k==2) { $step++; $k=0; }
} while ($cnt<$xy2);

//Вывод
header ('Content-Type: image/gif');
imagepng ($img);
imagedestroy($img);
?>

Скрипт довольно медленный и не несёт ничего нового, так что онлайн себе не ставлю :) Эффективнее простые числа на PHP ищутся здесь.

Реагирует на следующие параметры, переданные в URL (методом GET):

Например, скрипт можно вызвать так:

http://ВАШ_URL/spiral_of_prime_numbers.php?xy=100&back=000000&lines=FFFFFF&d=2&cw

и получить следующую "свастику":

Вызов скрипта с параметрами URL

Рейтинг@Mail.ru

вверх гостевая; E-mail