BBC BASIC
Ред. 1 Гольф-код, 655 символов ASCII, размер файла токена 614
Некоторые существенные улучшения в таблице данных: хеширование строки A.B..N
до числа (1*A+2*B+..n*N)+n
перед поиском и сохранение только одного вектора перевода (другой генерируется кодом.) Дополнительные пояснения, когда я закончу игру в гольф.
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
Ред. 0 Гольф-код, 770 символов ASCII, размер файла маркеров 728
Все, что я сделал здесь, это удалил комментарии, ненужные пробелы и кавычки и поместил все в DATA
одну строку. Там наверняка есть место для большего количества игры в гольф.
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
объяснение
Это продолжение моего предыдущего ответа уровня 1, но я решил опубликовать его отдельно, потому что он довольно длинный.
Уровень 2
Это достигается путем перевода моих шаблонов "уровня 1.5" из моего предыдущего ответа. Два вектора трансляции для каждой плитки жестко закодированы. Я использую тот факт, что равнобедренный треугольник с основанием 80 и высотой 70 является очень хорошим приближением равностороннего треугольника, а прямоугольный треугольник с вектором гипотенузы (56,56)
имеет длину гипотенузы, очень близкую к 80.
Уровень 3
Чтобы построить дуалы, вместо того, чтобы рисовать ребро многоугольника, мы строим спицу от середины этого ребра до центра многоугольника. Он находится под прямым углом к краю и имеет длину 1/TAN/(PI/n)
вектора (u, v), которая, в свою очередь, вдвое меньше длины края.
К сожалению, из-за того, что некоторые полигоны в мозаиках 3.3.3.3.6
и 3.4.6.4
не нанесены в явном виде, они не будут построены, если мы только сделаем это. Поэтому спица также простирается наружу от многоугольника. Внешнее расширение контролируется переменной o
.
По умолчанию расширение является достаточным для достижения центра треугольника, но для 3.4.6.4
его необходимо расширить больше, чтобы нарисовать двойные квадраты, которые не отображаются в явном виде. Таким образом, расширение, достаточное для заполнения пропущенных квадратов, применяется, когда шестиугольники и треугольники отображаются явно, но нормальное расширение применяется, когда квадраты отображаются явно, чтобы избежать ложных линий в соседних треугольниках.
Вот как они выглядят без расширений спиц. Отверстия в двойном узоре хорошо видны. Правильный вывод можно увидеть на главной картинке внизу ответа
Код комментирования
Отличия от моего предыдущего ответа указаны в строке
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
Выход
Программа выполняет только одну плитку или двойную для каждого запуска. Однако он отображает двойники в красном. Чтобы сэкономить место, я дважды запустил программу, не очищая экран, чтобы наложить двойное поверх обычного тайлинга.
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
. Должны ли мы поддерживать все синонимы или только лексически низший (как указано в вопросе)? Кроме того,3.3.3.3.6
существует в двух формах зеркального отображения. Я понимаю, что либо приемлемо.