Javascript 782 725 caracteres
primeiro post, seja gentil!
O programa agora é chamado através da função agrupada. Por exemplo: (function(e,f,g){...})(100,200,10)
.
function C(e,f,g,c,a,d){if(0>g-a||g+a>e||0>c-a||c+a>f)return d;for(var b in d)if(Math.sqrt(Math.pow(d[b].x-g,2)+Math.pow(d[b].y-c,2))<2*a)return d;d.push({x:g,y:c});for(b=0;b<Math.PI;)XX=Math.cos(b)*a*2+g,YY=Math.sin(b)*a*2+c,d=C(e,f,XX,YY,a,d),b+=.01;return d}
(function(e,f,g){var c=e+f,a,d;for(a=[];a.length<g;)a=d=c,a=C(e,f,a,d,c,[]),c-=.01;console.log("Highest possible radius: "+Math.round(100*c)/100);e='<svg width="'+e+'" height="'+f+'"><rect width="'+e+'" height="'+f+'" style="fill:red" />';for(var b in a)console.log("Circle "+b+" Focus: ("+Math.round(100*a[b].x)/100+", "+Math.round(100*a[b].y)/100+")"),e+='<circle cx="'+a[b].x+'" cy="'+a[b].y+'" r="'+c+'" fill="blue" />';console.log(e+"</svg>")})(400,300,13);
Teste 1
(function(e,f,g){...})(200,200,4)
Highest possible radius: 49.96
Circle 1 Focus: (49.97, 49.97)
Circle 2 Focus: (149.91, 49.97)
Circle 3 Focus: (149.99, 149.91)
Circle 4 Focus: (50.05, 149.91)
<svg width="200" height="200"><rect width="200" height="200" style="fill:blue;" /><circle cx="49.97000000021743" cy="49.97000000021743" r="49.960000000217434" fill="white" /><circle cx="149.9100000006523" cy="49.97000000021743" r="49.960000000217434" fill="white" /><circle cx="149.98958489212322" cy="149.90996831285986" r="49.960000000217434" fill="white" /><circle cx="50.04958489168835" cy="149.90996831285986" r="49.960000000217434" fill="white" /></svg>
Obviamente, esperávamos que o raio fosse exatamente 50, mas, por razões discutidas nos comentários da pergunta, eu não poderia razoavelmente fazer isso acontecer. O SVG fica assim ...
Teste 2
(function(e,f,g){...})(100,400,14)
Highest possible radius: 26.55
Circle 1 Focus: (26.56, 26.56)
Circle 2 Focus: (79.68, 26.56)
Circle 3 Focus: (132.8, 26.56)
Circle 4 Focus: (185.92, 26.56)
Circle 5 Focus: (239.04, 26.56)
Circle 6 Focus: (292.16, 26.56)
Circle 7 Focus: (345.28, 26.56)
Circle 8 Focus: (372.63, 72.1)
Circle 9 Focus: (319.52, 73.25)
Circle 10 Focus: (265.47, 72.64)
Circle 11 Focus: (212.35, 73.25)
Circle 12 Focus: (159.23, 72.64)
Circle 13 Focus: (106.11, 73.25)
Circle 14 Focus: (52.99, 72.64)
<svg width="400" height="100"><rect width="400" height="100" style="fill:blue;" /><circle cx="26.560000000311106" cy="26.560000000311106" r="26.550000000311105" fill="white" /><circle cx="79.68000000093332" cy="26.560000000311106" r="26.550000000311105" fill="white" /><circle cx="132.80000000155553" cy="26.560000000311106" r="26.550000000311105" fill="white" /><circle cx="185.92000000217774" cy="26.560000000311106" r="26.550000000311105" fill="white" /><circle cx="239.04000000279996" cy="26.560000000311106" r="26.550000000311105" fill="white" /><circle cx="292.16000000342217" cy="26.560000000311106" r="26.550000000311105" fill="white" /><circle cx="345.2800000040444" cy="26.560000000311106" r="26.550000000311105" fill="white" /><circle cx="372.6271770491687" cy="72.09972230654316" r="26.550000000311105" fill="white" /><circle cx="319.5195599732359" cy="73.24663493712801" r="26.550000000311105" fill="white" /><circle cx="265.47097406711805" cy="72.63752174440503" r="26.550000000311105" fill="white" /><circle cx="212.35454341475625" cy="73.25330971030218" r="26.550000000311105" fill="white" /><circle cx="159.23097406587362" cy="72.63752174440503" r="26.550000000311105" fill="white" /><circle cx="106.11454341351183" cy="73.25330971030218" r="26.550000000311105" fill="white" /><circle cx="52.99097406462921" cy="72.63752174440503" r="26.550000000311105" fill="white" /></svg>
E o SVG fica assim ...
Teste 3
(function(e,f,g){...})(400,400,3)
Highest possible radius: 101.68
Circle 1 Focus: (101.69, 101.69)
Circle 2 Focus: (298.23, 153.98)
Circle 3 Focus: (154.13, 298.19)
<svg width="400" height="400"><rect width="400" height="400" style="fill:blue;" /><circle cx="101.69000000059772" cy="101.69000000059772" r="101.68000000059772" fill="white" /><circle cx="298.2343937547503" cy="153.97504264473156" r="101.68000000059772" fill="white" /><circle cx="154.13153961740014" cy="298.19269546075066" r="101.68000000059772" fill="white" /></svg>
E o SVG fica assim ...
Eles não são todos bonitos.
Como funciona
Código não destruído abaixo. Este programa tem duas suposições:
- Um círculo estará sempre no canto. Parece uma aposta bastante segura.
- Cada círculo sempre estará tocando em outro círculo. Não vejo por que eles não seriam.
O programa começa calculando um raio grande com base nas dimensões da caixa. Em seguida, tenta ajustar um círculo no canto da caixa. Se esse círculo se encaixar, ele estende uma linha de diâmetro a partir desse círculo e tenta criar um círculo no final da linha. Se o novo círculo se encaixar, outra linha será estendida a partir do novo círculo. Se não couber, a linha oscilará 360 graus, verificando se há espaços abertos. Se a caixa for preenchida antes da criação do número desejado de círculos, o raio será reduzido e tudo começará novamente.
Código Ungolfed (snippet)
// this functions attempts to build a circle
// at the given coords. If it works, it will
// spawn additional circles.
function C(x, y, X, Y, r, cc){
// if this circle does not fit in the rectangle, BAIL
if(X-r < 0 || X+r > x || Y-r < 0 || Y+r > y)
return cc;
// if this circle is too close to another circle, BAIL
for(var c in cc){
if( Math.sqrt(Math.pow(cc[c].x - X, 2) + Math.pow(cc[c].y - Y, 2)) < (r*2) )
return cc;
}
// checks passed so lets call this circle valid and add it to stack
cc.push({"x": X, "y": Y});
// now rotate to try to find additional spots for circles
var a = 0; // radian for rotation
while(a < Math.PI){
XX = Math.cos(a)*r*2 + X;
YY = Math.sin(a)*r*2 + Y;
cc = C(x, y, XX, YY, r, cc);
a += .01; // CHANGE FOR MORE OR LESS PRECISION
}
return cc;
}
// this function slowly reduces the radius
// and checks for correct solutions
// also prints svg graphic code
(function B(x, y, n){
var r = x + y; // pick a big radius
var X, Y; // these are the coords of the current circle. golf by combining this with `var r..`?
var cc = []; // array of coordinates of the circles
// while we cant fit n circles, reduce the radius and try again
while(cc.length < n){
X = Y = r;
cc = C(x, y, X, Y, r, []);
r-=.01; // CHANGE FOR MORE OR LESS PRECISION
}
console.log('Highest possible radius: ' + Math.round(r*100)/100);
var s = '<svg width="' + x + '" height="' + y + '"><rect width="' + x + '" height="' + y + '" style="fill:red" />';
for(var c in cc){
console.log('Circle '+c+' Focus: (' + Math.round(cc[c].x*100)/100 + ', ' + Math.round(cc[c].y*100)/100 + ')');
s += '<circle cx="' + cc[c].x + '" cy="' + cc[c].y + '" r="' + r + '" fill="blue" />';
}
s += '</svg>';
console.log(s);
document.write(s);
})(150, 150, 5);