별 모양의 코드 도전


21

아메리카 합중국의 국기에는 주에 50 개의 주를 나타내는 50 개의 별이 있습니다.

50 성 미국 국기

과거에는 더 적은 주가 있었을 때, 물론 더 적은 별이 있었으며, 다르게 배열되었습니다. 예를 들어 1912 년에서 1959 년 (뉴 멕시코 및 애리조나의 입국 후 알래스카 이전에)에는 6x8 직사각형 배열에 48 개의 별이있었습니다.

48 성급 미국 국기

1867-1877 년 (네브라스카 입국 후, 콜로라도 전)에 사용 된 37 성 깃발은 비대칭적인 별 모양을 가졌다.

37 성 미국 국기

이 경우 51 상태가 향후에 추가되어, 장학의 육군 연구소는 이미 새로운 국기에 대한 예비 설계를 개발했다.

51 성급 미국 국기

그러나 별을 배열하는 일반적인 알고리즘은 없으므로 별을 만들어 봅시다!

도전

주어진 수의 별이 미국 국기의 주 (파란색 부분)에 배치되도록 해당 별을 배치 할 최적의 좌표를 출력하는 프로그램을 작성하십시오. 좌표계는 0≤x≤W 및 0≤y≤H의 구획 (전체 플래그가 아님 )으로 정의됩니다 .

이 도전의 목적을 위해, "최적의"배열은 광저우의 한 지점과 가장 가까운 별의 중심 사이의 평균 (유클리드) 거리최소화하는 것으로 정의된다 .

이 값을 근사화하는 간단한 (아마도 최적이 아닌) 알고리즘은 다음과 같습니다.

def mean_distance_to_nearest_star(stars, width, height, point_density=100):
   """
   Approximate the mean distance between a point in the rectangle
   0 < x < width and 0 < y < height, and the nearest point in stars.

   stars -- list of (x, y) points
   width, height -- dimensions of the canton
   """
   total = 0.0
   nx = round(width * point_density)
   ny = round(height * point_density)
   for ix in range(nx):
       x = (ix + 0.5) * width / nx
       for iy in range(ny):
          y = (iy + 0.5) * width / ny
          min_dist = float('inf')
          for sx, sy in stars:
              min_dist = min(min_dist, math.hypot(x - sx, y - sy))
          total += min_dist
   return total / (nx * ny)

프로그램은 세 가지 명령 줄 인수를 사용합니다 (프로그램 이름 자체는 포함하지 않음).

  1. 캔톤에 넣을 별의 개수입니다.
  2. 캔톤의 너비입니다. 부동 소수점 값을 수락해야합니다.
  3. 캔톤의 높이입니다. 부동 소수점 값을 수락해야합니다.

선호하는 프로그래밍 언어가 명령 줄 인수를 지원하지 않는 경우 이에 상응하는 것을 수행하고 답변에 문서화하십시오.

출력은 쉼표로 구분 된 X 및 Y 값 (한 줄에 하나씩)으로 구성되어야합니다. (포인트의 순서는 중요하지 않습니다.)

예를 들면 다음과 같습니다.

~$ flagstar 5 1.4 1.0
0.20,0.20
0.20,0.80
0.70,0.50
1.20,0.20
1.20,0.80

추가 규칙 및 참고 사항

  • 본인은 언제든지 규칙의 허점을 닫을 권리가 있습니다.
  • 답변 마감일은 7 월 4 일 금요일 24:00 CDT (UTC-05 : 00)입니다. 답변이 부족하여 마감일이 연장되었습니다. TBA.
  • 답변에 포함하십시오 :
    • 프로그램 코드
    • 작동 방식에 대한 설명
    • 명령 행 인수를 사용한 출력 50 1.4 1.0
  • 프로그램은 적당한 시간 내에 실행되어야합니다 : 일반적인 PC에서 최대 5 분. 나는 이것에 대해 매우 엄격하지는 않지만 몇 시간 이 걸리면 프로그램을 실격시킬 것 입니다.
  • 프로그램은 결정 론적이어야합니다. 즉, 동일한 인수에 대해 항상 동일한 결과를 제공해야합니다. 따라서 time()또는에 의존하지 마십시오 rand(). 몬테 카를로 방법은 자신의 PRNG를 굴리는 한 괜찮습니다.
  • 별의 중심점 만 중요합니다. 겹침이나 그와 비슷한 것을 피하려고 걱정하지 마십시오.

채점

  • 광저우의 한 지점에서 가장 가까운 별까지의 평균 거리를 최소화하십시오. (위 참조.)
  • 13 ~ 50 개의 별 사이에서 역사적인 미국 국기를 기준으로 점수를 매길 수 있습니다. 점수를 단일 순위로 가중시키는 정확한 알고리즘은 나중에 게시됩니다.
  • 동점 인 경우, 순 공감 수에 따라 우승자가 선정됩니다.
  • 본인의 프로그램을 게시 할 수도 있지만 확인 표시 대상에서 제외됩니다.

@primo : 어떻게 알 수 있습니까? 내 예제는 가장 가까운 별까지의 평균 거리가 0.289 인 반면 중앙에 5 개의 점을 모두 배치하면 MDNS는 0.561입니다.
dan04

당신은 나의 이전의 약속을 무시할 수 있습니다. 모든 별 과의 평균 거리와 같이 광저우의 모든 지점에서 가장 가까운 별 까지의 평균 거리를 잘못 읽습니다. 에서 가장 가까운 별까지의 .
primo

3
포함 자유롭게 jsfiddle.net/nf2mk2gr 그것은 당신의 승인을 충족하는 경우, 응답의 출력을 확인하는 질문에 스택 코드 조각으로. N x N 그리드를 기준으로 한 평균 거리를 표시하며 대기 시간이 길어질수록 N이 점차 증가합니다. (이 질문을 위해 특별히 작성되었습니다.)
trichoplax

답변:


4

자바 스크립트-별을 가장 고립 된 지점으로 이동

(프로세스 애니메이션과 함께)

접근 방식은 매우 간단합니다.

  • 다수의 랜덤 포인트를 선택하십시오
  • 가장 가까운 별을 찾으십시오
  • 가장 가까운 별이 가장 먼 지점을 선택하십시오
  • 그 별을 그 지점에 더 가깝게 옮기십시오

이 과정은 여러 번 반복되어 별의 이동량을 점차적으로 줄입니다. 이렇게하면 점에서 가장 가까운 별까지의 최대 거리가 줄어들고 점에서 가장 가까운 별까지의 평균 거리가 간접적으로 줄어 듭니다.

질문에서 요구하는대로 내장 임의 함수를 사용하지 않고 대신 xorshift .

대부분의 코드는 설정 및 애니메이션을 다루며 알고리즘을 적용하는 부분은 함수입니다. adjustStars 입니다.

암호

아래의 스택 스 니펫에서 진행중인 프로세스를 볼 수 있습니다.

stars = [];
timeoutId = 0;

resetRandomNumberGenerator();

function resetRandomNumberGenerator() {
  rng_x = 114; // Numbers for the random number generator.
  rng_y = 342;
  rng_z = 982;
  rng_w = 443;
}

$(document).ready(function() {
  c = document.getElementById('canton');
  ctx = c.getContext('2d');
  resizeCanvas();
});

function stop() {
  clearTimeout(timeoutId);
}

function arrange() {
  clearTimeout(timeoutId);
  resetStars();
  resetRandomNumberGenerator();
  maxStepSize = Math.min(cantonWidth, cantonHeight) / 4;
  adjustStars(maxStepSize, 8000, 10000);
}

function resizeCanvas() {
  cantonWidth = parseFloat($('#width').val());
  cantonHeight = parseFloat($('#height').val());
  starRadius = cantonHeight / 20;
  document.getElementById('canton').width = cantonWidth;
  document.getElementById('canton').height = cantonHeight;
  ctx.fillStyle = 'white';
  resetStars();
}

function resetStars() {
  stop();
  stars = [];
  population = parseInt($('#stars').val(), 10);
  shortSide = Math.floor(Math.sqrt(population));
  longSide = Math.ceil(population / shortSide);
  if (cantonWidth < cantonHeight) {
    horizontalStars = shortSide;
    verticalStars = longSide;
  } else {
    horizontalStars = longSide;
    verticalStars = shortSide;
  }
  horizontalSpacing = cantonWidth / horizontalStars;
  verticalSpacing = cantonHeight / verticalStars;
  for (var i = 0; i < population; i++) {
    x = (0.5 + (i % horizontalStars)) * horizontalSpacing;
    y = (0.5 + Math.floor(i / horizontalStars)) * verticalSpacing;
    stars.push([x, y]);
  }
  drawStars();
  updateOutputText();
}

function adjustStars(stepSize, maxSteps, numberOfPoints) {
  $('#stepsRemaining').text(maxSteps + ' steps remaining');
  points = randomPoints(numberOfPoints);
  mostIsolatedPoint = 0;
  distanceToNearestStar = 0;
  for (var i = 0; i < numberOfPoints; i++) {
    point = points[i];
    x = point[0];
    y = point[1];
    star = stars[nearestStar(x, y)];
    d = distance(x, y, star[0], star[1]);
    if (d > distanceToNearestStar) {
      distanceToNearestStar = d;
      mostIsolatedPoint = i;
    }
  }
  point = points[mostIsolatedPoint];
  x = point[0];
  y = point[1];

  starToMove = nearestStar(x, y);

  star = stars[starToMove];
  separationX = x - star[0];
  separationY = y - star[1];
  if (separationX || separationY) {
    hypotenuse = distance(x, y, star[0], star[1]);
    currentStep = Math.min(stepSize, hypotenuse / 2);
    deltaX = currentStep * separationX / hypotenuse;
    deltaY = currentStep * separationY / hypotenuse;
    star[0] += deltaX;
    star[1] += deltaY;
    if (star[0] < 0) star[0] = 0;
    if (star[0] > cantonWidth) star[0] = cantonWidth;
    if (star[1] < 0) star[1] = 0;
    if (star[1] > cantonHeight) star[1] = cantonHeight;

    drawStars();
    updateOutputText();
  }

  if (maxSteps > 0) {
    timeoutId = setTimeout(adjustStars, 10, stepSize * 0.9992, maxSteps - 1, numberOfPoints);
  }
}

function updateOutputText() {
  starText = '';
  for (var i = 0; i < stars.length; i++) {
    starText += stars[i][0] + ', ' + stars[i][1] + '\n';
  }
  $('#coordinateList').text(starText);
}

function randomPoints(n) {
  pointsToReturn = [];
  for (i = 0; i < n; i++) {
    x = xorshift() * cantonWidth;
    y = xorshift() * cantonHeight;
    pointsToReturn.push([x, y]);
  }
  return pointsToReturn;
}

function xorshift() {
  rng_t = rng_x ^ (rng_x << 11);
  rng_x = rng_y;
  rng_y = rng_z;
  rng_z = rng_w;
  rng_w = rng_w ^ (rng_w >> 19) ^ rng_t ^ (rng_t >> 8);
  result = rng_w / 2147483648
  return result
}

function nearestStar(x, y) {
  var distances = [];
  for (var i = 0; i < stars.length; i++) {
    star = stars[i];
    distances.push(distance(x, y, star[0], star[1]));
  }
  minimum = Infinity;
  for (i = 0; i < distances.length; i++) {
    if (distances[i] < minimum) {
      minimum = distances[i];
      nearest = i;
    }
  }
  return nearest;
}

function distance(x1, y1, x2, y2) {
  var x = x2 - x1;
  var y = y2 - y1;
  return Math.sqrt(x * x + y * y);
}

function drawStars() {
  ctx.clearRect(0, 0, cantonWidth, cantonHeight);
  for (i = 0; i < stars.length; i++) {
    star = stars[i];
    x = star[0];
    y = star[1];
    drawStar(x, y);
  }
}

function drawStar(x, y) {
  ctx.beginPath();
  ctx.moveTo(x, y - starRadius);
  ctx.lineTo(x - 0.588 * starRadius, y + 0.809 * starRadius);
  ctx.lineTo(x + 0.951 * starRadius, y - 0.309 * starRadius);
  ctx.lineTo(x - 0.951 * starRadius, y - 0.309 * starRadius);
  ctx.lineTo(x + 0.588 * starRadius, y + 0.809 * starRadius);
  ctx.fill();
}
canvas {
  margin: 0;
  border: medium solid gray;
  background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input id='stars' onchange='resetStars()' type='number' value='13' min='13' max='50' maxlength='2' step='1'>stars
<br>
<input id='width' onchange='resizeCanvas()' type='number' value='494' min='1' max='500' maxlength='3' step='any'>width
<br>
<input id='height' onchange='resizeCanvas()' type='number' value='350' min='1' max='500' maxlength='3' step='any'>height
<br>
<button type='button' onclick='resetStars()'>Reset Stars</button>
<button type='button' onclick='arrange()'>Arrange Stars</button>
<button type='button' onclick='stop()'>Stop</button>
<textarea id='stepsRemaining' rows='1' readonly></textarea>
<br>
<canvas id='canton' width='494' height='350'></canvas>
<br>
<textarea id='coordinateList' rows='50' cols='40' readonly></textarea>

별 50 개 출력

(너비 = 1.4, 높이 = 1.0)

평균 거리는 0.0655106697162357로 추정됩니다.

좌표 :

0.028377044205135808, 0.2128159150679491
0.10116766857540277, 0.05156676609341312
0.2903566419069437, 0.07216263690037035
0.49154061258041604, 0.004436102736309105
0.6930026352073071, 0.07060477929576484
1.0988644764108417, 0.022979778480838074
1.1735677936511582, 0.18600858289592742
1.3056806950504931, 0.062239869036660435
0.3967626880807638, 0.24483447327177033
0.27004118129346155, 0.40467589936498805
0.4996665039421278, 0.13023282430440133
0.5148978532656602, 0.6161298793146592
0.5907056537744844, 0.2614323599301046
0.8853042432872087, 0.048123917861564044
0.7753680330575412, 0.22938793622044834
1.365432954694329, 0.2355377720528128
0.1985172068244217, 0.23551298706793927
0.4477558465270544, 0.4170264112485973
0.6084424566752479, 0.7764909501169484
0.6099528761580699, 0.4395002434593519
0.9506038166406011, 0.34903243854585914
1.1898331497634231, 0.5756784243472182
1.0933574395540542, 0.46422120794648786
1.1516574254138159, 0.2930213338333888
0.07646053006349718, 0.40665000611360175
0.0634456093015551, 0.5853189455014883
0.3470036636019768, 0.5938838331082922
0.7591083341283029, 0.4005456925638841
0.9745306853981277, 0.184624209972443
1.3552011948311598, 0.549607060691302
1.3334000268566828, 0.7410204535471169
1.2990417572304487, 0.39571229988825735
0.05853941030364222, 0.7734808757471414
0.19396697551982484, 0.5678753467094985
0.7103231124251072, 0.5955041661956884
0.6168410756137566, 0.948561537739087
0.8967624790188228, 0.5368666961690878
0.9751229155529001, 0.8323724819557795
0.9987127931392165, 0.652902038374714
1.3231032600971289, 0.9164326184290812
0.20785221980162555, 0.7566700629874374
0.3987967842137651, 0.7678025218448816
0.44395949605458546, 0.9137553802571048
0.775611700149756, 0.9029717946067138
0.806442448003616, 0.7328147396477286
0.9481952441521928, 0.9872963855418118
1.1528689317425114, 0.9346775634274639
1.1651295140721658, 0.7591158327925681
0.09316709042512515, 0.934205211493484
0.2769325337580081, 0.9341145493466471

다양한 수의별로 애니메이션을 실행 한 후 별을 상자 가장자리에 가깝게 배치하는 경향이있는 것 같습니다. 그러나 진정한 최적의 배열을 알지 못하면 이것이 버그인지 또는 기능인지 알 수 없습니다.
dan04

@ dan04 나도-왜 그런 일이 일어 났는지 알 수 있습니다. 가장자리 근처의 별은 별에 너무 가까이 접근 할 수 있기에 너무 가깝습니다 (별은 대부분 주변 지점이 아닌 가장 고립 된 지점으로 이동합니다). 그러나 가장자리 근처의 두 먼 지점으로 이동하여 지그재그 경로를 번갈아 가면서 가장자리를 향해 간접적으로 이동할 수 있습니다. 나는 이것이 가장자리 근처에 별 있어야 한다는 것을 의미한다고 생각 하지만, 그것이 버그 / 기능을 공유하는지 확인하기위한 또 다른 접근법을 기대하고있다.
trichoplax

@ dan04 내 두 번째 대답 은 별이 내가 생각했던 것처럼 가장자리에 가까울 필요가 없으며 첫 번째 대답보다 더 나은 결과를 제공한다는 것을 보여줍니다. 최대 값을 통해 간접적으로가 아니라 평균으로 직접 작업하는 것이 더 효과적입니다.
trichoplax

3

다음은 간단한 예입니다. 항상 별을 직사각형 그리드로 정렬하고 그리드 셀이 가능한 정사각형에 가까운 인수 분해를 선택하여 별을 최적화합니다. 별의 수가 제곱근에 가까운 제수를 가질 때 효과적이며 별의 수가 소수 일 때 비관적으로 작동합니다.

from __future__ import division
import math
import sys

def divisors(n):
    """
    Return all divisors of n (including n itself) as a set.
    """
    result = {1, n}
    # Use +2 instead of +1 to allow for floating-point error.
    for i in range(2, int(math.sqrt(n)) + 2):
        if n % i == 0:
            result.add(i)
            result.add(n // i)
    return result

def squareness(width, height):
    """
    Given the dimensions of a rectangle, return a value between 0 and 1
    (1 iff width == height) measuring how close it is to being a square.
    """
    if width and height:
        return min(width / height, height / width)
    else:
        return 0.0

def star_grid(num_stars, width, height):
    """
    Return the factors (x, y) of num_stars that optimize the mean
    distance to the nearest star.
    """
    best_squareness = 0.0
    best_dimensions = (None, None)
    for nx in divisors(num_stars):
        ny = num_stars // nx
        sq = squareness(width / nx, height / ny)
        if sq > best_squareness:
            best_squareness = sq
            best_dimensions = (nx, ny)
    return best_dimensions

def star_coords(num_stars, width, height):
    """
    Return a list of (x, y) coordinates for the stars.
    """
    nx, ny = star_grid(num_stars, width, height)
    for ix in range(nx):
        x = (ix + 0.5) * width / nx
        for iy in range(ny):
            y = (iy + 0.5) * height / ny
            yield (x, y)

def _main(argv=sys.argv):
    num_stars = int(argv[1])
    width = float(argv[2])
    height = float(argv[3])
    for coord in star_coords(num_stars, width, height):
        print('%g,%g' % coord)

if __name__ == '__main__':
    _main()

별 50 개 출력

(너비 = 1.4, 높이 = 1.0)

10 × 5 직사각형.

0.07,0.1
0.07,0.3
0.07,0.5
0.07,0.7
0.07,0.9
0.21,0.1
0.21,0.3
0.21,0.5
0.21,0.7
0.21,0.9
0.35,0.1
0.35,0.3
0.35,0.5
0.35,0.7
0.35,0.9
0.49,0.1
0.49,0.3
0.49,0.5
0.49,0.7
0.49,0.9
0.63,0.1
0.63,0.3
0.63,0.5
0.63,0.7
0.63,0.9
0.77,0.1
0.77,0.3
0.77,0.5
0.77,0.7
0.77,0.9
0.91,0.1
0.91,0.3
0.91,0.5
0.91,0.7
0.91,0.9
1.05,0.1
1.05,0.3
1.05,0.5
1.05,0.7
1.05,0.9
1.19,0.1
1.19,0.3
1.19,0.5
1.19,0.7
1.19,0.9
1.33,0.1
1.33,0.3
1.33,0.5
1.33,0.7
1.33,0.9

0

자바 스크립트-평균 거리가 줄어들면 별을 임의로 움직입니다.

(프로세스 애니메이션과 함께)

이것은 잠재적 인 재배치가 테스트되고 거부되어 움직임이없는 오랜 기간 동안 첫 대답과 같은 바쁜 애니메이션을 제공하지 않습니다. 그러나 최종 결과는 평균 거리가 낮으므로이 방법이 개선되었습니다.

접근 방식은 여전히 ​​매우 간단합니다.

  • 무작위로 별을 선택하십시오
  • 임의의 방향으로 임의의 거리로 이동
  • 평균 거리가 줄어들면 새 위치를 유지하십시오

이 과정은 여러 번 반복되어 별의 이동량을 점차적으로 줄입니다. 이동 거리의 무작위 선택은 더 작은 거리로 편향되므로, 진행은 가끔 큰 점프로 산재되는 작은 변경으로 진행됩니다. 평균 거리를 측정하는 것은 전체 캔톤을 샘플링해야하는 느린 프로세스이므로 각 단계는 첫 번째 답변보다 시간이 오래 걸립니다.

질문에서 요구하는대로 xorshift 대신 내장 임의 함수를 사용하지 않습니다 .

대부분의 코드는 설정 및 애니메이션을 다루며 알고리즘을 적용하는 부분은 함수adjustStars 입니다.

암호

아래의 스택 스 니펫에서 진행중인 프로세스를 볼 수 있습니다.

stars = [];
timeoutId = 0;

resetRandomNumberGenerator();

function resetRandomNumberGenerator() {
  rng_x = 114; // Numbers for the random number generator.
  rng_y = 342;
  rng_z = 982;
  rng_w = 443;
}

$(document).ready(function() {
  c = document.getElementById('canton');
  ctx = c.getContext('2d');
  resizeCanvas();
});

function stop() {
  clearTimeout(timeoutId);
}

function arrange() {
  clearTimeout(timeoutId);
  resetStars();
  resetRandomNumberGenerator();
  maxStepSize = Math.min(cantonWidth, cantonHeight) / 16;
  adjustStars(maxStepSize, 7000, 15000);
}

function resizeCanvas() {
  cantonWidth = parseFloat($('#width').val());
  cantonHeight = parseFloat($('#height').val());
  starRadius = cantonHeight / 20;
  document.getElementById('canton').width = cantonWidth;
  document.getElementById('canton').height = cantonHeight;
  ctx.fillStyle = 'white';
  resetStars();
}

function resetStars() {
  stop();
  stars = [];
  population = parseInt($('#stars').val(), 10);
  shortSide = Math.floor(Math.sqrt(population));
  longSide = Math.ceil(population / shortSide);
  if (cantonWidth < cantonHeight) {
    horizontalStars = shortSide;
    verticalStars = longSide;
  } else {
    horizontalStars = longSide;
    verticalStars = shortSide;
  }
  horizontalSpacing = cantonWidth / horizontalStars;
  verticalSpacing = cantonHeight / verticalStars;
  for (var i = 0; i < population; i++) {
    x = (0.5 + (i % horizontalStars)) * horizontalSpacing;
    y = (0.5 + Math.floor(i / horizontalStars)) * verticalSpacing;
    stars.push([x, y]);
  }
  drawStars();
  updateOutputText();
}

function adjustStars(stepSize, maxSteps, numberOfPoints) {
  $('#stepsRemaining').text(maxSteps + ' steps remaining');
  var points = randomPoints(numberOfPoints);
  currentMean = meanDistance(stars, points);
  potentialStars = shiftedStars(stepSize);
  potentialMean = meanDistance(potentialStars, points);
  if (potentialMean < currentMean) {
    stars = potentialStars;
  }
  drawStars();
  updateOutputText();
  
  if (maxSteps > 0) {
    timeoutId = setTimeout(adjustStars, 10, stepSize * 0.999, maxSteps - 1, numberOfPoints);
  }
}

function shiftedStars(stepSize) {
  shifted = [];
  chosenOne = Math.floor(xorshift() * stars.length);
  for (i = 0; i < stars.length; i++) {
    star = stars[i];
    x = star[0];
    y = star[1];
    if (i === chosenOne) {
      for (n = 0; n < 10; n++) {
        x += xorshift() * stepSize;
        x -= xorshift() * stepSize;
        y += xorshift() * stepSize;
        y -= xorshift() * stepSize;
      }
      if (x < 0) x = 0;
      if (x > cantonWidth) x = cantonWidth;
      if (y < 0) y = 0;
      if (y > cantonHeight) y = cantonHeight;
    }
    shifted.push([x, y]);
  }
  return shifted;    
}

function meanDistance(arrayOfStars, arrayOfPoints) {
  var totalDistance = 0;
  for (i = 0; i < arrayOfPoints.length; i++) {
    point = arrayOfPoints[i];
    x = point[0];
    y = point[1];
    totalDistance += nearestStarDistance(x, y, arrayOfStars);
  }
  return totalDistance / arrayOfPoints.length;
}

function randomPoints(numberOfPoints) {
  var arrayOfPoints = [];
  for (i = 0; i < numberOfPoints; i++) {
    x = xorshift() * cantonWidth;
    y = xorshift() * cantonHeight;
    arrayOfPoints.push([x, y]);
  }
  return arrayOfPoints;
}

function updateOutputText() {
  starText = '';
  for (var i = 0; i < stars.length; i++) {
    starText += stars[i][0] + ', ' + stars[i][1] + '\n';
  }
  $('#coordinateList').text(starText);
}

function xorshift() {
  rng_t = rng_x ^ (rng_x << 11);
  rng_x = rng_y;
  rng_y = rng_z;
  rng_z = rng_w;
  rng_w = rng_w ^ (rng_w >> 19) ^ rng_t ^ (rng_t >> 8);
  result = rng_w / 2147483648
  return result
}

function nearestStarDistance(x, y, starsToUse) {
  var distances = [];
  for (var i = 0; i < stars.length; i++) {
    star = starsToUse[i];
    distances.push(distance(x, y, star[0], star[1]));
  }
  minimum = Infinity;
  for (i = 0; i < distances.length; i++) {
    if (distances[i] < minimum) {
      minimum = distances[i];
    }
  }
  return minimum;
}

function distance(x1, y1, x2, y2) {
  var x = x2 - x1;
  var y = y2 - y1;
  return Math.sqrt(x * x + y * y);
}

function drawStars() {
  ctx.clearRect(0, 0, cantonWidth, cantonHeight);
  for (i = 0; i < stars.length; i++) {
    star = stars[i];
    x = star[0];
    y = star[1];
    drawStar(x, y);
  }
}

function drawStar(x, y) {
  ctx.beginPath();
  ctx.moveTo(x, y - starRadius);
  ctx.lineTo(x - 0.588 * starRadius, y + 0.809 * starRadius);
  ctx.lineTo(x + 0.951 * starRadius, y - 0.309 * starRadius);
  ctx.lineTo(x - 0.951 * starRadius, y - 0.309 * starRadius);
  ctx.lineTo(x + 0.588 * starRadius, y + 0.809 * starRadius);
  ctx.fill();
}
canvas {
  margin: 0;
  border: medium solid gray;
  background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input id='stars' onchange='resetStars()' type='number' value='13' min='13' max='50' maxlength='2' step='1'>stars
<br>
<input id='width' onchange='resizeCanvas()' type='number' value='494' min='1' max='500' maxlength='3' step='any'>width
<br>
<input id='height' onchange='resizeCanvas()' type='number' value='350' min='1' max='500' maxlength='3' step='any'>height
<br>
<button type='button' onclick='resetStars()'>Reset Stars</button>
<button type='button' onclick='arrange()'>Arrange Stars</button>
<button type='button' onclick='stop()'>Stop</button>
<textarea id='stepsRemaining' rows='1' readonly></textarea>
<br>
<canvas id='canton' width='494' height='350'></canvas>
<br>
<textarea id='coordinateList' rows='50' cols='40' readonly></textarea>

별 50 개 출력

(너비 = 1.4, 높이 = 1.0)

평균 거리는 0.06402754713808706로 추정됩니다.

좌표 :

0.08147037630270487, 0.07571240182553095
0.24516777356538358, 0.0803538189052793
0.431021735247462, 0.07821284835132788
0.6001163609128221, 0.08278495286739646
0.7668077034213632, 0.0821321119375313
0.941333266969696, 0.08040530195264808
1.1229190363750599, 0.07255685332834291
1.3074771164489858, 0.07681674948141588
0.09227450444336446, 0.2257047798057907
0.33559513774978766, 0.20668611954667682
0.5182463448452704, 0.23841239342827816
0.6630614113293541, 0.26097114328053417
0.821886619004045, 0.23577904321258844
1.012597304977012, 0.23308200382761057
1.174938874706673, 0.22593017096601203
1.3285181935709358, 0.24024108928169902
0.0746772556909648, 0.3920030109869904
0.23006559905554042, 0.3204287339854068
0.4086004105498357, 0.3507788129168045
0.5669847710831315, 0.4371913211100495
0.7399474422203116, 0.41599441829489137
0.9099913571857917, 0.36933063808924294
1.1170137101288482, 0.3905679602615213
1.3037811235560612, 0.3979526346564911
0.09290206345982034, 0.5678420747594305
0.23463227399157258, 0.47552307265325633
0.4042403660145938, 0.5030345851947539
0.6611151741402685, 0.5918138006294138
0.8237963249937061, 0.5663224022272697
0.9812774216782155, 0.5032518469083094
1.146386501309064, 0.570255729516661
1.3185563715676663, 0.5571870810112576
0.07541940949872694, 0.7356649763259809
0.2877585652075202, 0.6321535875762999
0.4952646673275116, 0.6343336480073624
0.6965646728710738, 0.9178076185211137
0.7903485281657828, 0.7508031981325222
0.9774998621426763, 0.6683301268754337
1.1539480102558823, 0.7513836972857155
1.3177199931376755, 0.7245296168327016
0.22215183098388988, 0.7769843436963862
0.4048364942297627, 0.7779653803681718
0.5021290208205218, 0.9254525763987298
0.6058821167972933, 0.7683130432395833
0.8777330967719849, 0.9201076171801651
0.9894820530574747, 0.8172934111543102
1.1143371956097312, 0.9265012354173626
1.3045771339439551, 0.9069856484512913
0.0930066325438706, 0.9157592790749175
0.2959676633891297, 0.9251379492518523
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.