BBC BASIC
Rev 1 Código de golf, 655 caracteres ASCII, tamaño de archivo tokenizado 614
Algunas mejoras importantes en la tabla de datos, al dividir la cadena A.B..N
en un número (1*A+2*B+..n*N)+n
antes de buscar, y al almacenar solo un vector de traducción (el otro es generado por el código). Más explicaciones cuando haya terminado de jugar golf.
t=PI*2DIMm(9)
c=0z=0INPUTz$
FORi=1TOLEN(z$)d%=VAL(MID$(z$,i))IFd%c+=1m(c)=d%i-=d%=12z+=c*d%
NEXTREPEATREADl,e,f
UNTILl=z+c
l=4-3*(m(3)MOD3=0)-8*(l=59)
DATA69,0,70,65,100,35,66,149,0,49,109,0,52,80,0,55,0,189,39,120,0,44,40,40,58,55,95,47,136,0,59,40,0
VDU23,23,3|
FORr=-9TO19FORs=-9TO9a=1+e*(r*2+s)-f*l*s/4b=1+f*(r*2+s)+e*l*s/4p=40q=0FORk=1TOm(c)/2FORj=1TOc
n=m(j)o=TAN(PI/3)IFe=109ANDn<>4o=1
w=-p*COS(t/n)-q*SIN(t/n)q=p*SIN(t/n)-q*COS(t/n)p=w
u=p:v=q
x=a:y=b
MOVEx,y
FORi=1TO14x+=u*2y+=v*2IFVAL(z$)DRAWx,y ELSEGCOL9LINEx-u-v/o,y-v+u/o,x-u+v/TAN(PI/n),y-v-u/TAN(PI/n)
w=v*COS(t/n)-u*SIN(t/n)u=v*SIN(t/n)+u*COS(t/n)v=w
NEXTNEXT
p=u:q=v
a=x:b=y
NEXTNEXTNEXT
Rev 0 Código de golf, 770 caracteres ASCII, tamaño de archivo tokenizado 728
Todo lo que he hecho aquí es eliminar comentarios, espacios en blanco innecesarios y comillas, y poner todo DATA
en una línea. Ciertamente hay espacio para más golf.
t=PI*2DIMm(9)
c=0INPUTz$
FORi=1TOLEN(z$)d%=VAL(MID$(z$,i))IFd%c+=1:m(c)=d%:i-=d%=12
NEXTREPEATREADl$,e,f,g,h
UNTILMID$(z$,1-(VAL(z$)=0))=l$
DATA3.3.3.3.3.3,240,0,120,70,3.3.3.3.6,200,70,40,210,3.3.3.4.4,80,0,40,150,3.3.4.3.4,-40,150,150,40,3.12.12,300,0,150,260,3.4.6.4,220,0,110,188,3.6.3.6,160,0,80,140,4.4.4.4,80,0,0,80,4.6.12,0,380,330,-190,4.8.8,272,0,136,136,6.6.6,240,0,120,70
VDU23,23,3|
FORr=-9TO19 FORs=0TO9a=1+e*r+g*s
b=1+f*r+h*s
p=40q=0FORk=1TOm(c)/2FORj=1TOc
n=m(j)o=TAN(PI/3):IFe=220ANDn<>4o=1
w=-p*COS(t/n)-q*SIN(t/n)q=p*SIN(t/n)-q*COS(t/n)p=w
u=p:v=q
x=a:y=b
MOVEx,y
FORi=1TO14x+=u*2y+=v*2IFVAL(z$)DRAWx,y ELSEGCOL9LINEx-u-v/o,y-v+u/o,x-u+v/TAN(PI/n),y-v-u/TAN(PI/n)
w=v*COS(t/n)-u*SIN(t/n)u=v*SIN(t/n)+u*COS(t/n)v=w
NEXTNEXT
p=u:q=v
a=x:b=y
NEXTNEXTNEXT
Explicación
Esta es una continuación de mi respuesta anterior de Nivel 1, pero decidí publicarla por separado porque es bastante larga.
Nivel 2
Esto se logra mediante la traducción de mis plantillas de "nivel 1.5" de mi respuesta anterior. Los dos vectores de traducción para cada mosaico están codificados. Aprovecho el hecho de que un triángulo isósceles de base 80 y altura 70 es una muy buena aproximación de un triángulo equilátero, y un triángulo rectángulo con vector de hipotenusa (56,56)
tiene una longitud de hipotenusa muy cercana a 80.
Nivel 3
Para trazar los duales, en lugar de trazar un borde del polígono, trazamos un radio desde el medio de ese borde hasta el centro del polígono. Esto está en ángulo recto con el borde y tiene una longitud de 1/TAN/(PI/n)
veces del vector (u, v) que a su vez es la mitad del borde.
Desafortunadamente, debido a que ciertos polígonos en las inclinaciones 3.3.3.3.6
y 3.4.6.4
no se trazan explícitamente, no se trazarían si solo hiciéramos esto. Por lo tanto, el radio también se extiende hacia afuera desde el polígono. La extensión hacia el exterior está controlada por la variable o
.
Por defecto, la extensión es suficiente para alcanzar el centro de un triángulo, pero para 3.4.6.4
ello debe extenderse más para dibujar los duales de los cuadrados que no se trazan explícitamente. Por lo tanto, se aplica suficiente extensión para completar los cuadrados faltantes cuando los hexágonos y los triángulos se trazan explícitamente, pero la extensión normal se aplica cuando los cuadrados se trazan explícitamente, para evitar líneas espurias en los triángulos adyacentes.
Así es como se ven sin las extensiones de radios. Los agujeros en el patrón dual se pueden ver claramente. La salida correcta se puede ver en la imagen principal en la parte inferior de la respuesta
Código comentado
Las diferencias con respecto a mi respuesta anterior se indican en línea.
t=PI*2 :REM constant Tau = PI*2
DIMm(9) :REM declare array for the numbers in the input
c=0 :REM number of polygons in the list
INPUTz$
FORi=1TOLEN(z$) :REM for each character in the input
d%=VAL(MID$(z$,i)) :REM use VAL to return the numeric value of the substring to the right and store to integer variable
IF d% c+=1 :m(c)=d%: i-=d%=12 :REM if the last character read was a number, d% contains it, otherwise 0. Advance c and store to m. If it is 12, increment i to skip a character.
NEXT
REM BLOCK OF NEW CODE to define vectors (e,f) and (g,h) for each possible tiling
REPEAT
READ l$,e,f,g,h :REM read an entire line of the data below
UNTIL MID$(z$,1-(VAL(z$)=0))=l$ :REM abort the loop when l$ coincides with the input. the MID$ strips off the 'V' from the input where necessary.
DATA"3.3.3.3.3.3",240,0,120,70
DATA"3.3.3.3.6",200,70,40,210
DATA"3.3.3.4.4",80,0,40,150
DATA"3.3.4.3.4",-40,150,150,40
DATA"3.12.12",300,0,150,260
DATA"3.4.6.4",220,0,110,188
DATA"3.6.3.6",160,0,80,140
DATA"4.4.4.4",80,0,0,80
DATA"4.6.12",0,380,330,-190
DATA"4.8.8",272,0,136,136
DATA"6.6.6",240,0,120,70
VDU23,23,3| :REM change linewidth to 3 (default is 1)
REM END BLOCK OF NEW CODE
FORr=-9TO19 FORs=0TO9 :REM two new loops for translations
a=1+e*r+g*s :REM modified code for
b=1+f*r+h*s :REM coordinates to start drawing at
p=40:q=0 :REM vector of first line
FORk=1TOm(c)/2 :REM draw half as many vertex figures as there are sides on the last polygon in the list
FORj=1TOc :REM for each polygon on the list
n=m(j) :REM n=number of sides
o=TAN(PI/3): IF e=220 AND n<>4 o=1 :REM new code for the spoke extension 1/o.
w=-p*COS(t/n)-q*SIN(t/n) :REM rotate the starting vector anticlockwise by the internal angle of the current polygon
q=p*SIN(t/n)-q*COS(t/n) :REM to avoid overlapping the previous one, if any.
p=w
u=p:v=q :REM make a local copy of the vector and coordinates
x=a:y=b :REM to avoid corruption of p,q,a,b during the drawing of the polygon
MOVE x,y :REM move the graphics cursor to the start without drawing
FORi=1TO14 :REM do 14 iterations regardless of the number of sides on the polygon
x+=u*2 :REM increment x and y by the vector representing the side
y+=v*2 :REM the value is double (u,v) to facilitate drawing duals later
REM if z$ begins with a numeric character, draw an edge. If not, change to red and draw a spoke.
IFVAL(z$) DRAW x,y ELSE GCOL9: LINEx-u-v/o,y-v+u/o,x-u+v/TAN(PI/n),y-v-u/TAN(PI/n)
w=v*COS(t/n)-u*SIN(t/n) :REM rotate the vector clockwise
u=v*SIN(t/n)+u*COS(t/n) :REM through the external angle of the polygon
v=w
NEXT :REM draw next edge of the current polygon
NEXT :REM draw next polygon of the current vertex
p=u:q=v :REM once the vertex is finished, we will be two sides around the perimeter of the last polygon.
a=x:b=y :REM copy the position and direction data into p,q,a,b.
NEXT :REM draw next vertex figure
NEXT :REM close the two new translation loops
NEXT
Salida
El programa realiza solo un mosaico o doble para cada ejecución. Sin embargo, traza los duales en rojo. Para ahorrar espacio, ejecuté el programa dos veces sin borrar la pantalla para superponer el dual encima del mosaico normal.
3.3.3.4.4
3.3.4.4.3
3.4.4.3.3
4.4.3.3.3
4.3.3.3.4
. ¿Tenemos que admitir todos los sinónimos, o solo el léxico más bajo (como se indica en la pregunta)? Además,3.3.3.3.6
existe en dos formas de imagen espejo. Entiendo que cualquiera es aceptable.