JSFiddle - React, Tailwind, and code Playground

HTML

<table>
  <tr>
    <td>
      Challenge input - write this yourself or generate below
      <br>
      <textarea id="chal-input" rows="20" cols="30"></textarea>
    </td>
    <td>
      <canvas id="visualisation" width="200" height="200">
        
      </canvas>
      <div id="result"></div>
    </td>
  </tr>
  <tr>
    <td>
      <label>Input size: <input type="text" id="chal-size" style="width: 3em" value="100"></label>
      <br>
      <button id="gen-challenge">
        Generate!
      </button>
      <button id="vis-challenge">
        Visualise!
      </button>
      <button id="solve-challenge">
        Solve!
      </button>
    </td>
    <td>
      Challenge output - enter your generated solution
      <br>
      <textarea id="chal-output" rows="3" cols="30"></textarea>
      <br>
      <button id="validate-solution">
        Validate!
      </button>
      <button id="vis-solution">
        Visualise!
      </button>
      <button id="rand-solution">
        Random circle!
      </button>
    </td>
  </tr>
</table>

CSS

#visualisation {
  background-color: white;
}

JavaScript

var print = console.log
function Point(x, y) {
	this.x = x
	this.y = y
}
Point.prototype.distSq = function(b) {
	let a = this
	return Math.pow(a.x-b.x,2) + Math.pow(a.y-b.y,2)
}
Point.prototype.dist = function(b) {
	return Math.sqrt(this.distSq(b))
}

function Circle(x, y, r) {
	this.p = new Point(x,y)
	this.r = r
	this.r2 = r*r
}
Circle.prototype.show = function() {
	return `${this.p.x} ${this.p.y}\n${this.r}`
}
Circle.random = function() {
	let r = Math.random()*0.5
	let x = r+Math.random()*(1-2*r)
	let y = r+Math.random()*(1-2*r)
	return new Circle(x,y,r)
}
Circle.prototype.clone = function() {
	let c = new Circle(this.p.x, this.p.y, this.r)
	c.r2 = this.r2
	c.inside = this.inside
	c.lastScore = this.lastScore
	return c
}
Circle.prototype.mutate = function() {
	let c = this.clone()
	c.r += 0.7*Math.random()*(0.5-c.r)
	c.p.x += 0.5*( (c.r-c.p.x) * Math.random()*(1-2*c.r) )
	c.p.y += 0.5*( (c.r-c.p.y) * Math.random()*(1-2*c.r) )
	c.r2 = c.r*c.r
	return c
}
// print(Circle.random().show())
Circle.prototype.score = function(points) {
	let inside = 0
	for(let p of points)
		if( this.p.distSq(p) <= this.r2 )
			inside++
	this.inside = inside
	this.lastScore = Math.abs(inside/points.length - 0.5)
				 + this.r
	return this.lastScore
}

var popSize = 100
var topSize = parseInt(popSize/4)
var iterations = 1000
function solve(points) {
	let population = []
	for(let i=0; i < popSize; i++)
		population.push(Circle.random())
	best = {score: 1}
	for(let it=0; it < iterations; it++) {
		for(let c of population)
			c.score(points)
		_population = population.sort((a,b)=>a.lastScore-b.lastScore)
		if(_population[0].lastScore < best.score)
				best = _population[0].clone()
		population = []
		for(let i=0; i < topSize; i++) {
			population.push(_population[i].mutate())
			population.push(_population[i].mutate())
			population.push(_population[i].mutate())
		}
		while(population.length < popSize)
			population.push(Circle.random())
	}
	return best
}

function parseInput(input)...