তারা-বর্ণিত কোড চ্যালেঞ্জ


21

আমেরিকা যুক্তরাষ্ট্রের পতাকাটিতে তার ক্যান্টনে 50 টি স্টার রয়েছে যা 50 টি রাজ্যের প্রতিনিধিত্ব করে।

50-তারা মার্কিন পতাকা

অতীতে, যখন কম রাজ্য ছিল, অবশ্যই কম তারা ছিল, এবং তাদের আলাদাভাবে সাজানো হয়েছিল। উদাহরণস্বরূপ, 1912-1959 (নিউ মেক্সিকো এবং অ্যারিজোনার প্রবেশের পরে তবে আলাস্কার আগে), 6 × 8 আয়তক্ষেত্রাকার বিন্যাসে 48 তারা ছিল।

48-তারা মার্কিন পতাকা

1867-1877 (নেব্রাস্কা ভর্তির পরে কিন্তু কলোরাডোর আগে) থেকে ব্যবহৃত 37-তারাযুক্ত পতাকাটিতে একটি অসম্পূর্ণ তারকা বিন্যাস ছিল।

37-তারা মার্কিন পতাকা

ভবিষ্যতে একটি 51 তম রাষ্ট্র যুক্ত হওয়ার পরে, হেরাল্ড্রি আর্মি ইনস্টিটিউট ইতিমধ্যে একটি নতুন পতাকার জন্য প্রাথমিক নকশা তৈরি করেছে।

51-তারা মার্কিন পতাকা

তবে তারাগুলি সাজানোর জন্য কোনও সাধারণ অ্যালগরিদম নেই , সুতরাং আসুন এটি তৈরি করা যাক!

চ্যালেঞ্জ

একটি প্রোগ্রাম লিখুন যা কোনও মার্কিন পতাকার ক্যান্টনে (নীল অংশ) স্থাপনের জন্য প্রদত্ত সংখ্যক তারকাদের জন্য, এই নক্ষত্রগুলি রাখার জন্য আউটপুট অনুকূল স্থানাঙ্ক করে। সমন্বয় সিস্টেমটি ক্যান্টন দিয়ে [ পুরো পতাকা নয় পুরো হিসাবে] 0≤x≤W এবং 0≤y≤H দিয়ে সংজ্ঞায়িত করা হয়।

এই চ্যালেঞ্জের উদ্দেশ্যে, একটি "অনুকূল" বিন্যাসটি সংজ্ঞায়িত করা হয়েছে যা ক্যান্টনের একটি বিন্দু এবং নিকটতম তারার কেন্দ্রের মধ্যবর্তী গড় (ইউক্লিডিয়ান) দূরত্বকে হ্রাস করে।

এই মানটির আনুমানিক জন্য একটি সোজাসাপ্টা (যদি সম্ভবত suboptimal হয়) অ্যালগোরিদম হ'ল:

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

অতিরিক্ত নিয়ম ও নোট

  • আমার যে কোনও সময় নিয়মের ফাঁকগুলি বন্ধ করার অধিকার রয়েছে।
  • উত্তরের শেষ তারিখটি শুক্রবার, 4 জুলাই 24:00 সিডিটি-তে (ইউটিসি -05: 00)। জবাব না থাকায় সময়সীমা বাড়ানো হয়েছে। ধাই।
  • আপনার উত্তরে অন্তর্ভুক্ত করুন:
    • আপনার প্রোগ্রামের কোড
    • এটি কীভাবে কাজ করে তার একটি ব্যাখ্যা
    • কমান্ড-লাইন আর্গুমেন্টগুলির সাথে এর আউটপুট 50 1.4 1.0
  • আপনার প্রোগ্রামটি অবশ্যই একটি যুক্তিসঙ্গত সময়ের মধ্যে চলতে হবে: একটি সাধারণ পিসিতে সর্বাধিক 5 মিনিট। আমি এ বিষয়ে অতি কঠোর হব না, তবে কয়েক ঘন্টা সময় লাগলে আপনার প্রোগ্রামটিকে অযোগ্য ঘোষণা করব ।
  • আপনার প্রোগ্রামটি অবশ্যই ডিটারমিনিস্টিক হওয়া উচিত, অর্থাৎ সর্বদা একই যুক্তিগুলির জন্য ঠিক একই আউটপুট দেয়। সুতরাং, time()বা উপর নির্ভর করে না rand()। মন্টে কার্লো পদ্ধতিগুলি যতক্ষণ আপনি নিজের PRNG রোল করেন ততক্ষণ ঠিক OK
  • তারকাদের কেবলমাত্র কেন্দ্রের পয়েন্টগুলিই গুরুত্বপূর্ণ। ওভারল্যাপ বা এ জাতীয় কিছু এড়ানোর চেষ্টা করার বিষয়ে চিন্তা করবেন না।

স্কোরিং

  • ক্যান্টনের একটি বিন্দু থেকে নিকটতম তারার মধ্যবর্তী দূরত্বটি হ্রাস করুন। (উপরে দেখুন.)
  • আপনি 13 এবং 50 তারকার মধ্যে কোনও historicalতিহাসিক মার্কিন পতাকাগুলির ভিত্তিতে স্কোর করতে পারেন। একক র‌্যাঙ্কিংয়ে স্কোর ওয়েট করার জন্য সঠিক অ্যালগরিদম পরে পোস্ট করা হবে।
  • টাই করার ক্ষেত্রে, বিজয়ী নেট আপভোটিসের সংখ্যা দ্বারা চয়ন করা হবে।
  • আমি সম্ভবত আমার নিজের একটি প্রোগ্রাম পোস্ট করব, তবে চেকমার্কের জন্য নিজেকে যোগ্য হতে বঞ্চিত করব।

@ প্রিমো: আপনি এটি কীভাবে দেখেন? আমার উদাহরণটির নিকটতম তারার 0.28 এর গড় দূরত্ব রয়েছে, যেখানে কেন্দ্রের সমস্ত 5 পয়েন্ট স্থাপনের এমডিএনএস থাকে 0.51।
dan04

আপনি আমার পূর্ববর্তী কমেন্ট উপেক্ষা করতে পারেন। আমি থেকে গড় দূরত্ব ভুল ব্যাখ্যা করা ক্যান্টন প্রতি বিন্দু নিকটতম তারকা থেকে গড় দূরত্ব যেমন প্রত্যেক তারকা নিকটতম তারকা হতে।
প্রিমো

3
আপনার অনুমোদনের সাথে মিলিত হলে, উত্তরগুলির আউটপুট যাচাই করতে প্রশ্নে jsfiddle.net/nf2mk2gr একটি স্ট্যাক স্নিপেট হিসাবে অন্তর্ভুক্ত নির্দ্বিধায় মনে করুন । এটি এন বাই এন গ্রিডের উপর ভিত্তি করে গড় দূরত্বটি প্রদর্শন করে, N আপনার ক্রম অপেক্ষা যত বেশি সময় বাড়িয়ে দেবে N এর সাথে। (এটি এই প্রশ্নের জন্য বিশেষভাবে লেখা হয়েছিল।)
ট্রাইকপ্লেক্স 14:15

উত্তর:


4

জাভাস্ক্রিপ্ট - বেশিরভাগ বিচ্ছিন্ন পয়েন্টের দিকে তারা সরান

(প্রক্রিয়াটির একটি অ্যানিমেশন সহ)

পদ্ধতির খুব সহজ:

  • প্রচুর সংখ্যক এলোমেলো পয়েন্ট চয়ন করুন
  • প্রতিটি নিকটতম তারা খুঁজে
  • যে বিন্দুর জন্য নিকটতম তারকাটি সবচেয়ে বেশি দূরে তা চয়ন করুন
  • সেই তারাটিকে সেই বিন্দুতে সরান

এই প্রক্রিয়াটি বৃহত সংখ্যক বার পুনরাবৃত্তি হয়, ধীরে ধীরে তারগুলি সরানো পরিমাণটি হ্রাস করে। এটি একটি বিন্দু থেকে নিকটতম তারার সর্বাধিক দূরত্বকে হ্রাস করে, পরোক্ষভাবে বিন্দু থেকে নিকটতম তারাতে গড় দূরত্ব হ্রাস করে।

প্রশ্নের দ্বারা প্রয়োজনীয় হিসাবে, এটি জোরশিফ্ট ব্যবহার না করে, এলোমেলো ফাংশনে অন্তর্নির্মিত ব্যবহার করে না ।

বেশিরভাগ কোড সেট আপ এবং অ্যানিমেশন কভার করে - যে অংশটি অ্যালগরিদম প্রয়োগ করে তা হ'ল ফাংশন 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

আপনার অ্যানিমেশনটি বিভিন্ন সংখ্যক তারার সাথে চালানোর পরে, মনে হয় তারার বাক্সের প্রান্তের কাছে রাখার প্রবণতা রয়েছে। তবে আসল সর্বোত্তম ব্যবস্থাটি না জেনে আমি এটি বলতে পারি না এটি কোনও বাগ বা কোনও বৈশিষ্ট্য is
dan04

@ dan04 না ​​আমি - যদিও এটি ঘটে তবে আমার ধারণা আছে। প্রান্তের কাছাকাছি তারাগুলি এটির দিকে এগিয়ে যাওয়ার উল্লেখযোগ্য সম্ভাবনা থাকার জন্য এটির খুব কাছাকাছি রয়েছে (তারাগুলি বেশিরভাগ বিচ্ছিন্ন পয়েন্টগুলির দিকে এগিয়ে যায়, পয়েন্টগুলি নয়)। তবে তারা এখনও প্রান্তের কাছাকাছি প্রান্তের কাছাকাছি দুটি দূরের পয়েন্টের দিকে অগ্রসর করে পরিবর্তে একটি জিগজ্যাগ পথ তৈরি করতে পারে। আমি সন্দেহ করি এর অর্থ হল যে প্রান্তগুলির নিকটে তারার থাকা প্রয়োজন তবে আমি বাগ / বৈশিষ্ট্যটি ভাগ করে নিয়েছে কিনা তা দেখার জন্য আমি আরও একটি পদ্ধতি দেখার অপেক্ষায়
রয়েছি

@ ডান04 আমার দ্বিতীয় উত্তরটি দেখে মনে হচ্ছে যে তারকাদের আমি যতটা ভাবছিলাম তত কাছাকাছি হওয়ার দরকার নেই এবং আমার প্রথম উত্তরের চেয়ে ভাল ফলাফল দেয়। সর্বাধিক পরিবর্তে অপ্রত্যক্ষভাবে পরিবর্তনের চেয়ে গড়ের সাথে সরাসরি কাজ করা আরও কার্যকর বলে প্রমাণিত হয়।
ট্রাইকোপল্যাক্স

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

জাভাস্ক্রিপ্ট - যদি গড় দূরত্ব হ্রাস হয় তবে এলোমেলোভাবে একটি তারা সরান

(প্রক্রিয়াটির একটি অ্যানিমেশন সহ)

এটি আমার প্রথম উত্তর হিসাবে এত ব্যস্ত অ্যানিমেশন দেয় না, সম্ভাব্য পুনঃস্থাপনগুলি পরীক্ষা করা এবং প্রত্যাখ্যাত হওয়ার কারণে দীর্ঘ সময় ধরে কোনও আন্দোলন না করে। যাইহোক, চূড়ান্ত ফলাফলের একটি কম গড় দূরত্ব রয়েছে, সুতরাং এই পদ্ধতিটি একটি উন্নতি।

পদ্ধতির এখনও খুব সহজ:

  • এলোমেলোভাবে একটি তারা চয়ন করুন
  • এলোমেলোভাবে এটিকে এলোমেলো দিকের দিকে নিয়ে যান
  • যদি গড় দূরত্ব হ্রাস পায় তবে নতুন অবস্থানটি রাখুন

এই প্রক্রিয়াটি বৃহত সংখ্যক বার পুনরাবৃত্তি হয়, ধীরে ধীরে তারগুলি সরানো পরিমাণটি হ্রাস করে। সরানোর জন্য দূরত্বের এলোমেলো পছন্দটি ছোট দূরত্বের দিকে পক্ষপাতদুষ্ট, তাই মাঝে মাঝে বড় লাফের সাথে ছেদ করা ছোট ছোট পরিবর্তনতে অগ্রগতি হয়। প্রতিটি পদক্ষেপটি আমার প্রথম উত্তরের চেয়ে বেশি সময় নেয়, কারণ গড় দূরত্বটি পরিমাপ করা একটি ধীর প্রক্রিয়া যা পুরো ক্যান্টনকে নমুনা দেওয়ার প্রয়োজন হয়।

প্রশ্নের দ্বারা প্রয়োজনীয় হিসাবে, এটি জোরশিফ্ট ব্যবহার না করে, এলোমেলো ফাংশনে অন্তর্নির্মিত ব্যবহার করে না ।

বেশিরভাগ কোড সেট আপ এবং অ্যানিমেশন কভার করে - যে অংশটি অ্যালগরিদম প্রয়োগ করে তা হ'ল ফাংশন 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 at

স্থানাঙ্ক:

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.