BBC BASIC, 570 514 490 bytes ASCII
Faça o download do intérprete em http://www.bbcbasic.co.uk/bbcwin/download.html
435 bytes tokenizados
O programa completo exibe uma entrada L.bmp
na tela e a modifica para encontrar uma solução.
*DISPLAY L
t=PI/8q=FNa(1)
DEFFNa(n)IFn=7END
LOCALz,j,p,i,c,s,x,y,m,u,v
F.z=0TO99u=z MOD10*100v=z DIV10*100ORIGINu,v
F.j=0TO12S.4p=0F.i=j+3TOj+9S.2c=9*COS(i*t)s=9*SIN(i*t)p=p*4-(POINT(c,s)<>0)*2-(POINT(9*c,9*s)<>0)N.
m=n:IFn=5A.(43A.p)=0p=0m=7
IF(ASCM."??O|(C",n)-64A.p)=0THEN
F.i=-1TO0GCOL0,-i*n:c=99*COS(j*t)s=99*SIN(j*t)y=402/3^m MOD3-1MOVE-c-s*y,c*y-s:x=n<3MOVEc*x-s*x,s*x+c*x:x=2778/3^m MOD3-1y=5775/3^m MOD3-1PLOT85-32*(n MOD6>3),c*x-s*y,s*x+c*y:IFi q=FNa(n+1)ORIGINu,v
N.
ENDIF
N.N.=0
Explicação
Observe que no básico da BBC uma distância de 1 pixel = 2 unidades, a grade de 50x50 pixels se torna uma grade de 100x100.
Usamos uma função recursiva para colocar os 2 triângulos grandes, triângulo médio, quadrado e paralelogramo na forma. A forma anterior da lista é desenhada antes da próxima chamada recursiva. se uma chamada recursiva retornar sem encontrar uma solução, a forma anterior será substituída em preto e uma nova posição da forma anterior será tentada.
Depois que essas cinco formas são desenhadas, colocar os dois pequenos triângulos é apenas uma formalidade. É necessário desenhar um deles, no entanto, para distingui-los se eles compartilham uma vantagem comum. Nós colorimos apenas um dos dois pequenos triângulos. O outro é deixado em preto natural.
A colocação de cada forma é tentada em diferentes coordenadas x, y e em 4 rotações diferentes. Para testar se há espaço livre para desenhar uma forma, usamos o modelo abaixo, com ângulos de 45 graus. As rotações são feitas em torno dos *
8 pixels testados e estão em 2 semicírculos dos raios 9 e 81 unidades e caem nas linhas radiantes em múltiplos ímpares de 22,5 graus para os eixos xe y.
Para um triângulo grande, todos os 8 espaços devem estar limpos. Para outras formas, apenas algumas das células devem estar limpas para que uma máscara seja aplicada.
+----+---- Shape Mask HGFEDCBA Mask decimal
|\ E/|\G /
| \/F|H\/ 1,2. Large triangle 11111111 -1
|C/\ | / 3. Med triangle 00001111 15
|/ D\|/ 4. Square 00111100 60
+----* 5. Parallelogram 11101000 -24
|\ B/ 6. Small triangle 00000011 3
|A\/ 7. Parallogr reversed 00101011 43
| / Note: reversed parallelogram is checked/drawn at recursion depth n=5
|/ with a special check, but the coordinates are encoded as m=7.
Uma vez estabelecido que uma forma se encaixa, ela deve ser desenhada. Se é um triângulo com o qual é plotado PLOT 85
, se é um paralelogramo, o número é 32 maior (observe que, para PLOT
fins, consideramos um quadrado um paralelogramo especial). Nos dois casos, três vértices consecutivos devem ser dados. O segundo vértice é a origem da forma (marcada *
na tabela acima), exceto no caso do triângulo grande, onde (antes da rotação) ele é. -1,-1.
Os outros 2 vértices podem ter coordenadas x e y -1,0 or 1
extraídas da base 3 números codificados e, em seguida, redimensionados por 99 e rotacionados conforme necessário pela transformação com c
e s
.
Código ungolfed
*DISPLAY L
t=PI/8 :REM Constant 22.5 degrees.
q=FNa(1) :REM Call function, return dummy value to q
END :REM End the program gracefully if no solution. Absent in golfed version.
DEFFNa(n) :REM Recursive function to place shapes.
IFn=7END :REM If n=7 solution found, end program.
LOCALk,z,j,p,i,c,s,x,y,m,u,v :REM declare local variables for function.
k=ASCMID$("??O|(C",n)-64 :REM Bitmasks for big tri, big tri, med tri, sq, normal paralellogram, small tri.
FORz=0TO99 :REM For each point on the grid
u=z MOD10*100:v=z DIV10*100 :REM calculate its x and y coordinates relative to bottom left of screen
ORIGINu,v :REM and set the origin to this point.
FORj=0TO12STEP4 :REM For each rotation 0,90,180,270deg
p=0 :REM assume no non-black pixels found
FORi=j+3TOj+9STEP2 :REM test angles of 3,5,7,9 times 22.5 deg anticlockwise from right x axis.
c=9*COS(i*t) :REM Coords of test points at radius ll
s=9*SIN(i*t)
p*=4 :REM Leftshift any existing data in p
p-=(POINT(c,s)<>0)*2+(POINT(9*c,9*s)<>0) :REM and check pixels at radius 11 and 99.
NEXT
m=n :REM The index of the shape to plot normally corresponds with recursion depth n.
IF n=5 AND (43ANDp)=0 p=0:m=7 :REM If n=5 check if a reverse parallelogram is possible (mask 43). If so, clear p and change m to 7.
REM :REM Check p against mask k, if the shape fits then...
IF (k ANDp)=0 THEN
FOR i=-1 TO 0 :REM draw the shape in colour, and if deeper recursions prove unsuccesful, redraw it in black.
GCOL0,-i*n :REM Colour is equal to n.
c=99*COS(j*t) :REM Set parameters c and s for scaling by 99
s=99*SIN(j*t) :REM and rotation by 0,90,180 or 270 as appropriate.
x=-1 :REM For vertex 1, x=-1 always.
y=402/3^m MOD3-1 :REM Lookup y value for vertex 1.
MOVEc*x-s*y,s*x+c*y :REM Use c and s to transform the vertex and move to it.
x=n<3 :REM For vertex 2, coords are 0,0 except for large triangle where they are -1,-1
y=x :REM in BBC BASIC, TRUE=-1
MOVEc*x-s*y,s*x+c*y :REM Use c and s to transform the vertex and move to it.
x=2778/3^m MOD3-1 :REM Lookup x and y value for vertex 3.
y=5775/3^m MOD3-1 :REM PLOT85 uses last 2 points + specified point to make triangle, PLOT85+32 makes paralelogram (or square.)
PLOT85-32*(n MOD6>3),c*x-s*y,s*x+c*y :REM Use c and s to transform the vertex and draw shape.
IFi q=FNa(n+1):ORIGINu,v :REM If i=-1 recurse to next level. If it fails, reset the origin before replotting this level's shape in black.
NEXT
ENDIF
NEXT
NEXT
=0 :REM Dummy value to return from function
Saída
Esta é uma montagem das soluções encontradas pelo programa para os casos de teste. O uso de 99 em vez de 100 por razões de golfe deixa algumas pequenas lacunas negras. Como as formas são redesenhadas durante as pesquisas, pode demorar alguns segundos para executar em alguns casos, e é fascinante assistir.