LSC-система рендеринга ASCII


16

Фон

L-система (или система Линденмайер) представляет собой систему параллельных перезаписи , что, помимо прочего, может быть легко использована для модельных фракталов. Этот вопрос касается детерминированных L-систем без контекста . Они состоят из алфавита символов, начальной строки аксиомы и набора правил перезаписи, отображающих каждый символ алфавита в новую строку. Правила применяются к аксиоме параллельно, генерируя новую строку. Этот процесс затем повторяется.

Например, система с аксиомой «A» и правилами A = ABA; B = BBB генерирует последовательность строк «ABA», «ABABBBABA», «ABABBBABABBBBBBBBBABABBBABA» и т. Д. Для краткости мы не упоминаем явно алфавит при определении L-системы. Кроме того, любой символ без явного правила перезаписи предполагается неизменным (т. Е. Правилом по умолчанию для символа A является A = A).

L-системы могут быть визуализированы с использованием графических изображений черепах. По соглашению, черепаха начинает смотреть направо. Строка затем рисуется путем итерации по ее символам: F означает «переместиться вперед на одну единицу», G означает «переместиться вперед на одну единицу», a + означает «повернуть на одну единицу угла» и a - означает «повернуть направо на один угол единица измерения". Все остальные символы в строке игнорируются. Для целей этого вопроса предполагается, что угловые единицы всегда равны 90 °.

задача

Учитывая спецификацию любой L-системы и количество итераций, ваша программа должна вывести ASCII-рендеринг полученной строки (как описано выше), используя символы рисования блоков.

  • Параметры передаются в виде разделенной пробелами строки, содержащей аксиому, правила перезаписи (в виде списка уравнений, разделенных;) и количество итераций перезаписи. Например, вход «FF = FGF; G = GGG 2» генерирует строку «FGFGGGFGF» и, следовательно, рисует четыре линии с соответствующими пробелами.
  • Символы, используемые L-системой, могут быть любым символом ASCII, кроме пробела и точки с запятой. Для каждого символа указывается не более одного явного правила (при этом правилом перезаписи по умолчанию является отображение идентификаторов, как описано выше).
  • Можно предположить, что на выходе всегда будет хотя бы один F.
  • В выводе должны использоваться следующие символы рисования блоков ЮНИКОД для представления визуализации: ─ (U + 2500), │ (U + 2502), ┌ (U + 250C), ┐ (U + 2510), └ (U + 2514) , ┘ (U + 2518), ├ (U + 251C), ┤ (U + 2524), ┬ (U + 252C), ┴ (U + 2534), ┼ (U + 253C), ╴ (U + 2574), ╵ (U + 2575), ╶ (U + 2576) и ╷ (U + 2577). Смотрите ниже примеры.
  • Вывод не должен содержать пустых строк над самым верхним символом поля или под самым нижним. Он также не должен содержать пробелов слева от крайнего левого прямоугольника или справа от самого правого. Разрешены строки с завершающими пробелами, которые не выходят за крайний правый символ.

Вы можете написать программу или функцию, используя ввод через STDIN (или ближайшую альтернативу), аргумент командной строки или аргумент функции. Результаты должны быть напечатаны в STDOUT (или ближайшую альтернативу), сохранены в файл или возвращены в виде строки.

Примеры

# Cantor dust
>> "F F=FGF;G=GGG 0"
╶╴
>> "F F=FGF;G=GGG 1"
╶╴╶╴
>> "F F=FGF;G=GGG 2"
╶╴╶╴  ╶╴╶╴
>> "F F=FGF;G=GGG 3"
╶╴╶╴  ╶╴╶╴        ╶╴╶╴  ╶╴╶╴

# Koch curve
>> "F F=F+F−F−F+F 1"
 ┌┐
╶┘└╴
>> "F F=F+F-F-F+F 2"
    ┌┐
   ┌┘└┐
  ┌┘  └┐
 ┌┼┐  ┌┼┐
╶┘└┘  └┘└╴

Другие примеры для тестирования вашей программы включают в себя:

# Dragon curve
>> "FX X=X+YF+;Y=-FX-Y n"

# Hilbert curve
>> "A A=-BF+AFA+FB-;B=+AF-BFB-FA+ n"

# Sierpinski carpet
>> "F F=F+F-F-F-G+F+F+F-F;G=GGG n"

Первые два из них выглядят следующим образом (производится с использованием ответа @ edc65):

введите описание изображения здесь введите описание изображения здесь

Вы можете протестировать любую из систем на этой странице .

счет

Самый короткий код (в байтах) выигрывает. Стандартные правила применяются.

Miscellania

Этот вызов был вдохновлен Draw a Random Walk with Slashes . На самом деле, случайное блуждание можно представить как L-систему, если мы расширим систему, чтобы разрешить несколько правил на символ, причем расширение выбирается недетерминистически во время перезаписи. Одна формулировка:

"F F=FF;F=F+F;F=F++F;F=F+++F"

Другим распространенным расширением, часто используемым при моделировании растений, является интерпретация символов [и] как нажатие и выталкивание текущей позиции и угла. Большинство растений используют углы меньше 90 °, но вот один пример, который этого не делает:

"FAX X=[-FAX][FAX][+FAX];A=AFB;B=A"

Ни один из этих примеров не должен поддерживаться в этой задаче.

Эта задача также похожа на «Извините, молодой человек, но это Черепахи!» , Тем не менее, эта задача использовала рендеринг строк, а не ASCII и позволила использовать более гибкий синтаксис.

Ответы:


7

JavaScript (ES6), 440 байт (410 символов)

F=p=>([a,r,n]=p.split(' '),t=>{r.split(';').map(x=>r[x[0]]=x.slice(2),r={});for(;n--;)a=[...a].map(c=>r[c]||c).join('');u=x=y=0,g=[];for(c of a)c=='+'?[t,u]=[u,-t]:c=='-'?[u,t]=[t,-u]:c<'F'|c>'G'?0:((y+=u)<0?(g=[[],...g],++y):g[y]=g[y]||[],(x+=t)<0?(g=g.map(r=>[,...r]),++x):0,c>'F'?0:g[g[f=t?0.5:2,y][x]|=(3+t-u)*f,y-u][x-t]|=(3+u-t)*f)})(1)||g.map(r=>[for(c of r)' ╶╴─╵└┘┴╷┌┐┬│├┤┼'[~~c]].join('')).join('\n')

Меньше гольфа

F=p=>{
  [a,r,n]=p.split(' '),
  r.split(';').map(x=>r[x[0]]=x.slice(2),r={}); // set rules
  for(;n--;)a=[...a].map(c=>r[c]||c).join(''); // build string
  t=1,u=x=y=0, // start pos 0,0 start direction 1,0
  g=[[]]; // rendering in bitmap g
  for(c of a)
    c=='+'?[t,u]=[u,-t] // left turn
    :c=='-'?[u,t]=[t,-u] // right turn
    :c=='F'|c=='G'?(     // move or draw
      (y+=u)<0?(g=[[],...g],++y):g[y]=g[y]||[], // move vertical, enlarge grid if needed
      (x+=t)<0?(g=g.map(r=>[,...r]),++x):0, // move horizontal, enlarge grid if needed
      c=='F'&&( // draw: set bits
        f=t?0.5:2,
        g[y][x]|=(3+t-u)*f,
        g[y-u][x-t]|=(3+u-t)*f
      )
    ):0;
  // render bits as box characters
  return g.map(r=>[' ╶╴─╵└┘┴╷┌┐┬│├┤┼'[~~c]for(c of r)].join('')).join('\n')
}

Тестовый фрагмент кода для тестирования (в Firefox)


Отличный (и быстрый!) Ответ. Я добавил скриншоты выводов кривой Дракона и Гильберта к вопросу.
Ури Гранта

6

Haskell, 568 байт

import Data.List.Split
p=splitOn
l=lookup
m=maximum
n=minimum
o[h,x]=(h,x)
Just x#_=x
_#x=x
g[s,r,i]=iterate((\c->lookup[c](map(o.p"=")(p";"r))#[c])=<<)s!!read i
u v@(a,x,y,d,e)c|c=='+'=(a,x,y,-e,d)|c=='-'=(a,x,y,e,-d)|c=='G'=(a,x+d,y+e,d,e)|c=='F'=(s(x,y)(d%e)a:s(x+d,y+e)(d?e)a:a,x+d,y+e,d,e)|1<2=v
s p n a=(p,n+(l p a)#0)
1%0=2;0%1=8;-1%0=1;0%(-1)=4
1?0=1;0?1=4;-1?0=2;0?(-1)=8
f z=unlines[[" ╴╶─╷┐┌┬╵┘└┴│┤├┼"!!(l(x,y)q#0)|x<-[n a..m a]]|y<-[m b,m b-1..n b]]where a=map(fst.fst)q;b=map(snd.fst)q;(q,_,_,_,_)=foldl u([],0,0,1,0)$g$p" "z

Тестовый забег:

*Main> putStr $ f "F F=F-F+F+F-F 3"
╶┐┌┐  ┌┐┌┐        ┌┐┌┐  ┌┐┌╴
 └┼┘  └┼┼┘        └┼┼┘  └┼┘
  └┐  ┌┼┼┐        ┌┼┼┐  ┌┘
   └┐┌┼┘└┘        └┘└┼┐┌┘
    └┼┘              └┼┘   
     └┐              ┌┘
      └┐┌┐        ┌┐┌┘
       └┼┘        └┼┘
        └┐        ┌┘
         └┐┌┐  ┌┐┌┘
          └┼┘  └┼┘
           └┐  ┌┘
            └┐┌┘
             └┘

Как это устроено:

  • переписывание (функция g): я разбираю правила в список ассоциаций (буква -> строка замены) и многократно сопоставляю их с аксиомой.
  • создавая путь (функция uдля одного шага): Я не хранить путь в матрице , но в другом списке ассоциации с (х, у) позиции в качестве ключей и битовых комбинаций из 4 -х основных блоков ( , , и ) в качестве значений , По пути я отслеживаю текущую позицию и направление.
  • рисование пути (функция f): сначала я вычисляю максимальные / минимальные размеры из списка путей, а затем перебираю [max y -> min y] и [min x -> max x] и ищу блоки для рисования.

0

ES7, 394 символа, 424 байта

F=p=>([a,r,n]=p.split` `,t=>{r.split`;`.map(x=>r[x[0]]=x.slice(2),r={});for(;n--;)a=[...a].map(c=>r[c]||c).join``;u=x=y=0,g=[];for(c of a)c=='+'||c=='-'?[t,u]=[u,-t]:c<'F'|c>'G'?0:((y+=u)<0?(g=[[],...g],++y):g[y]=g[y]||[],(x+=t)<0?(g=g.map(r=>[,...r]),++x):0,c>'F'?0:g[g[f=t?0.5:2,y][x]|=(3+t-u)*f,y-u][x-t]|=(3+u-t)*f)})(1)||g.map(r=>[for(c of r)'╶╴─╵└┘┴╷┌┐┬│├┤┼'[~~c]].join``).join`
`
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.