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.43.3.4.4.33.4.4.3.34.4.3.3.34.3.3.3.4. Должны ли мы поддерживать все синонимы или только лексически низший (как указано в вопросе)? Кроме того,3.3.3.3.6существует в двух формах зеркального отображения. Я понимаю, что либо приемлемо.