Representação gráfica do floco de neve de Koch


13

Gere um floco de neve Koch

Um floco de neve Koch é um triângulo que, para cada um n, é adicionado outro ponto equilateral no meio de cada lado: http://en.wikipedia.org/wiki/Koch_snowflake#Properties

Já tínhamos um desafio para o Koch Snowflake de . O novo desafio é desenhar um floco de neve Koch entre e .n=4n110

Regras

Os flocos de neve podem não estar codificados no programa ou em arquivos - eles devem ser gerados pelo seu programa.

Seu programa deve suportar todos os tamanhos nentre 1 e 10.

O número de lados deve ser inserido pelo usuário por meio de entrada padrão.

Você deve imprimir uma representação gráfica do floco de neve na tela.

Amostra de flocos de neve Koch niguais a 1, 2, 3 e 4 (linhas verdes apenas para maior clareza, não os reproduzem):

Flocos de neve de Koch

No caso de um desempate, o programa com o maior número de upvotes vence (concurso pop).


Não estou entendendo isso: "Você deve usar uma função para calcular onde colocar o pixel. Se o seu programa não possui uma função interna para esse fim, você pode deduzir o custo da implementação de uma da sua pontuação. " Qual pixel?
Xnor

@xnor Foi originalmente criado para calcular como desenhar o floco de neve em uma base por pixel / caractere (o desafio também era originalmente um desafio da arte ASCII). A maioria das pessoas provavelmente usará apenas linhas, então removerei isso.

Pode-se desenhar todo o floco de neve preenchido?
Xnor

Claro. Este comentário precisa ser mais longo.

Além disso n=7, você não pode ver os triângulos recém-adicionados no floco de neve na tela do computador. Existe algum "melhor esforço" aqui? Existe uma resolução mínima para soluções baseadas em pixel?
Xnor

Respostas:


7

Mathematica 72

Region@Line@AnglePath[Nest[Join@@({#,1,4,1}&/@#)&,{4,4,4},Input[]-1]π/3]

n = 3

insira a descrição da imagem aqui

Obrigado por alefhalpha.


Bom trabalho. Jogue com dois caracteres e você ganha a vitória!

@ Hosch250 Atualizado, obrigado.
chyanog

Você pode usar AnglePathno Mathematica 10.1.
alephalpha

@chyaongGraphics@Line@AnglePath[Nest[Join@@({-1,2,-1,#}&/@#)&,{2,2,2},Input[]-1]Pi/3]
alephalpha

1
@alephalpha 73 chars:ListLinePlot@AnglePath[Nest[Join@@({#,1,4,1}&/@#)&,{4,4,4},Input[]-1]π/3]
chyanog

15

MATLAB, 119 115

Em uma virada incomum de eventos, descobri que esse programa realmente funcionava melhor quando jogava golfe. Primeiro, ficou muito mais rápido devido à vetorização. Agora, ele exibe um prompt útil ~n:~lembrando ao usuário qual quantidade inserir!

Novas linhas não fazem parte do programa.

x=exp(i*pi/3);
o='~n:~';
P=x.^o;
for l=2:input(o);
P=[kron(P(1:end-1),~~o)+kron(diff(P)/3,[0 1 1+1/x 2]) 1];
end;
plot(P)

n = 9: n = 9

oé uma corda arbitrária que é igual ao [0 2 4 0]módulo 6. e iπ / 3 elevado a essas potências fornece os vértices de um triângulo equilátero no plano complexo. O primeiro kroné usado para fazer uma cópia da lista de pontos com cada um duplicado 4 vezes. ~~oé a maneira conveniente de obter um vetor de 4. Em segundo lugar, diff(P)encontra o vetor entre cada par de pontos consecutivos. Múltiplos deste vetor (0, 1/3, (1 + e -iπ / 3 ) / 3 e 2/3) são adicionados a cada um dos pontos antigos.


Hum, você poderia explicar um pouco mais como esse código funciona? Eu pensei que conhecia algum Matlab, mas isso é ... insanidade ?? =)
flawr

@ flawr Adicionei algumas notas, isso ajuda alguma?
feersum

Muito obrigado! Eu vou manter esse truque cadeia de abuso em mente =)
flawr

9

T-SQL: 686 (excluindo formatação)

Para o SQL Server 2012 ou superior.

Mesmo que isso nunca seja um candidato, eu tinha que ver se conseguia fazê-lo no T-SQL. Acabou a abordagem de começar com as três arestas iniciais, recorrendo a cada aresta e substituindo-as por 4 arestas para cada nível. Finalmente, unindo tudo em uma única geometria para o nível especificado para @i

DECLARE @i INT=8,@ FLOAT=0,@l FLOAT=9;
WITH R AS(
    SELECT sX,sY,eX,eY,@l l,B,1i
    FROM(VALUES(@,@,@l,@,0),(@l,@,@l/2,SQRT(@l*@l-(@l/2)*(@l/2)),-120),(@l/2,SQRT(@l*@l-(@l/2)*(@l/2)),@,@,-240))a(sX,sY,eX,eY,B)
    UNION ALL
    SELECT a.sX,a.sY,a.eX,a.eY,l/3,a.B,i+1
    FROM R 
        CROSS APPLY(VALUES(sX,sY,sX+(eX-sX)/3,sY+(eY-sY)/3,sX+((eX-sX)/3)*2,sY+((eY-sY)/3)*2))x(x1,y1,x2,y2,x3,y3)
        CROSS APPLY(VALUES(x2+((l/3)*SIN(RADIANS(B-210.))),y2+((l/3)*COS(RADIANS(B-210.)))))n(x4,y4)
        CROSS APPLY(VALUES(x1,y1,x2,y2,B),
            (x3,y3,eX,eY,B),
            (x2,y2,x4,y4,B+60),
            (x4,y4,x3,y3,B-60)
        )a(sX,sY,eX,eY,B)
WHERE @i>i)
SELECT Geometry::UnionAggregate(Geometry::Parse(CONCAT('LINESTRING(',sX,' ',sY,',',eX,' ',eY,')')))
FROM R 
WHERE i=@i

insira a descrição da imagem aqui insira a descrição da imagem aqui


Eu não tinha ideia de que essa magia poderia ser alcançada com o T-SQL!
Harry Mustoe-Playfair

9

LOGO: 95

to w:c ifelse:c=1[fd 2 lt 60][w:c-1 w:c-1 lt 180 w:c-1 w:c-1]end
to k:c repeat 3[w:c rt 180]end

Define a função kcom um parâmetro de nível único.

Editar

No editor online deste http://www.calormen.com/jslogo/, você pode adicionar k readwordpara usar o prompt de entrada, mas por algum motivo esse comando não suporta a abreviação padrão rw.

A solução de 102 caracteres abaixo funciona no USBLogo com entrada padrão, conforme especificado na pergunta. No entanto, o código precisou de pequenas alterações, pois o UCBLogo possui um analisador estranho. Requer toe enddeve estar em linhas e espaço separados antes que :seja necessário, mas, por outro lado, :são opcionais.

to w c
ifelse c=1[fd 2 lt 60][w c-1 w c-1 lt 180 w c-1 w c-1]
end
to k c
repeat 3[w c rt 180]
end
k rw

Como você executa o LOGO?
Beta Decay

@BetaDecay eu usei isso: logo.twentygototen.org mas esta foi a primeira que eu encontrei: calormen.com/jslogo Você também pode instalar USBLogo
nutki

8

BBC BASIC, 179

REV 1

INPUTn
z=FNt(500,470,0,0,3^n/9)END
DEFFNt(x,y,i,j,a)
LINEx-36*a,y-21*a,x+36*a,y-a*21PLOT85,x,y+a*42IFa FORj=-1TO1FORi=-1TO1z=FNt(x+24*a*i,y+j*14*a*(i*i*3-2),i,j,-j*a/3)NEXTNEXT
=0

Como antes, mas em preto e branco, nas versões não-golfadas (mas simplificadas) e golfe. Não é um vencedor, apesar de fazê-lo dessa maneira, evita a necessidade de um tratamento especial para n = 1.

  INPUTn
        REM call function and throw return value away to z
  z=FNt(500,470,0,0,3^n/9)
  END

        REM x,y=centre of triangle. a=scale.
        REM loop variables i,j are only passed in order to make them local, not global.
  DEFFNt(x,y,i,j,a)

        REM first draw a line at the bottom of the triangle. PLOT85 then draws a filled triangle,
        REM using the specified point (top of the triangle) and the last two points visited (those used to draw the line.)
  LINEx-36*a,y-21*a,x+36*a,y-21*a
  PLOT85,x,y+42*a

        REM if the absolute magnitude of a is sufficient to be truthy, recurse to the next level.
        REM j determines if the triangle will be upright, inverted or (if j=0) infinitely small.
        REM i loops through the three triangles of each orientation, from left to right.
  IFa FORj=-1TO1 FORi=-1TO1:z=FNt(x+24*a*i,y+j*14*a*(i*i*3-2),i,j,-j*a/3):NEXT:NEXT

        REM return 0
  =0

insira a descrição da imagem aqui

REV 0

De acordo com a resposta do OP ao @xnor, flocos de neve preenchidos são aceitáveis. Esta resposta foi inspirada no comentário do xnor. As cores são apenas para diversão e para mostrar como é construído. Pegue um triângulo (magenta neste caso) e plote com 6 triângulos 1/3 da base.

  INPUTn
  z=FNt(500,470,n,1,0,0)
  END

  DEFFNt(x,y,n,o,i,a)
  a=3^n/22
  GCOLn
  MOVEx-36*a,y-o*21*a
  MOVEx+36*a,y-o*21*a
  PLOT85,x,y+o*42*a
  IFn>1FORi=-1TO1:z=FNt(x+24*a*i,y+14*a*(i*i*3-2),n-1,-1,i,a):z=FNt(x+24*a*i,y-14*a*(i*i*3-2),n-1,1,i,a)NEXT
  =0

insira a descrição da imagem aqui


1
Eu gosto de como parece que 7 deles se fundiram.

@ hosch250 De fato, parece que "inventei" um novo fractal cuja silhueta é um floco de neve Koch, e se você excluir a parte magenta, ficará com 6 flocos de neve Koch menores. A versão golfada será apenas uma silhueta preta simples, mas vou deixar essa imagem também.
Level River St

Você escreve BBC Basic ou BBC BASIC? Eu vou para o último, mas não sei se está correto ...
Decay Beta

2
O @BetaDecay BASIC é uma sigla para o Código de Instrução Padrão / Simbólico para Todos os Principiantes. O bit "Padrão" é discutível, pois há muitas variantes. en.wikipedia.org/wiki/BASIC . A maioria das variantes do BASIC prefere a versão em maiúscula, mas, de acordo com a página da Wikipedia, o Visual Basic prefere letras minúsculas. Eu acho que o BBC BASIC enviado foi em maiúsculas. Estou usando a versão em bbcbasic.co.uk/bbcwin/bbcwin.html . Está em maiúsculas no site e no IDE, então eu diria que a versão em maiúsculas está mais correta. Mas acho que não importa muito.
Level River St

Ahh ok, eu vou continuar com a versão em maiúsculas
Decay Beta

8

Mathematica - 177

r[x_, y_] := Sequence[x, RotationTransform[π/3, x]@y, y]
Graphics@Polygon@Nest[
 ReplaceList[#, {___, x_, y_, ___}  Sequence[x,r[2 x/3 + y/3, 2 y/3 + x/3], y]
  ] &, {{0, 0}, {.5, √3/2}, {1, 0}, {0, 0}}, Input[]]

insira a descrição da imagem aqui

Clipe de bônus de variação do ângulo da peça do meio

insira a descrição da imagem aqui


6

Python 3-139

Usa a biblioteca de gráficos da tartaruga.

from turtle import*
b=int(input())
a=eval(("FR"*3)+".replace('F','FLFRFLF')"*~-b)
for j in a:fd(9/b*("G">j));rt(60*(2-3*("Q">j))*("K"<j))])

Legal. Eu gosto da sua abordagem baseada em string de encontrar a forma com não mais de duas linhas de código! Mas você não pode verificar "G">j, "Q"<je usar fd(9/b)para salvar 3 bytes? Além disso, você pode evitar que as ifdeclarações se multipliquem, por exemplo, ("G">j)com o argumento 9/be colocá-las todas em uma linha atrás for. Oh! Depois, você pode até combinar rte ltusar120*(...)-60*(...)
Falko

Isso parece renderizar a entrada do floco de neve Koch + 1. Uma entrada de 1 deve ser apenas um triângulo, como mostra a figura acima.

@ Falko Obrigado por toda a ajuda!
Beta Decay

@ hosch250 Editado
Decaimento beta

Agora, ele não desenha nada, e uma entrada 1 cria uma divisão por 0 erro.

4

Python 3, 117 bytes

from turtle import*
ht();n=int(input())-1
for c in eval("'101'.join("*n+"'0'*4"+")"*n):rt(60+180*(c<'1'));fd(99/3**n)

Método:

  • A solução usa gráficos de tartaruga do Python.
  • n é input - 1
  • A partir da string 0000, juntamos todos os caracteres com 101 ntempos iterativamente com o repetidas truque eval (graças a @xnor por isso).
  • Para cada caractere na sequência final, giramos 60 graus para a direita ou 120 graus para a esquerda com base no valor do caractere ( 1ou0 ) e depois avançamos um comprimento ( 99/3^n) que garante um tamanho semelhante para todos n.
  • O último 0da string será inútil, mas apenas redesenha a mesma linha do primeiro0 desenha.

Exemplo de saída para input = 3:

koch


2

R: 240 175

Porque eu estou tentando entender o R, aqui está outra versão. É provável que haja maneiras muito melhores de fazer isso, e fico feliz em receber dicas. O que eu fiz parece muito complicado.

n=readline();d=c(0,-120,-240);c=1;while(c<n){c=c+1;e=c();for(i in 1:length(d)){e=c(e,d[i],d[i]+60,d[i]-60,d[i])};d=e};f=pi/180;plot(cumsum(sin(d*f)),cumsum(cos(d*f)),type="l")

insira a descrição da imagem aqui


2

Sábio fwom youw gwave ...

Eu sabia que gostaria de tentar implementar isso no Befunge-98 usando o TURT, mas não consegui descobrir como fazer isso e fiquei sentado por vários meses. Agora, apenas recentemente, descobri uma maneira de fazer isso sem usar a auto-modificação! E entao...

Befunge-98 com a impressão digital TURT, 103

;v;"TRUT"4(02-&:0\:0\1P>:3+:4`!*;
>j$;space makes me cry;^
^>1-:01-\:0\:01-\:0
0>I@
^>6a*L
^>ca*R
^>fF

Vamos resolver alguns detalhes da implementação primeiro:

  • Eu testei isso usando o CCBI 2.1 , cuja implementação do TURT (a impressão digital dos gráficos das tartarugas) faz com que I"imprima" a imagem em um arquivo SVG. Se você executar isso no CCBI sem o argumento de comando --turt-line=PATH, ele sairá como um arquivo chamado CCBI_TURT.svg por padrão. Este é o mais próximo que pude "imprimir uma representação gráfica do floco de neve na tela" com os intérpretes disponíveis do Funge que pude encontrar. Talvez um dia haja um intérprete melhor por aí que tenha uma exibição gráfica para a tartaruga, mas por enquanto ...
  • É necessário que haja uma nova linha no final para o CCBI executá-la sem interrupção (isso está incluído na contagem de caracteres). Eu sei direito?

Basicamente, isso funciona usando a pilha como uma espécie de sistema L improvisado e expandindo-a rapidamente. Em cada passagem, se o número superior na pilha for:

  • -2, depois imprime e para;
  • -1, a tartaruga gira 60 graus no sentido anti-horário;
  • 0, gira no sentido horário 120 graus;
  • 1, ele avança (por 15 pixels aqui, mas você pode alterá-lo modificando o fna última linha);
  • algum número n igual a 2 ou superior, é expandido na pilha para n-1, -1, n-1, 0, n-1, -1, n-1.

Pois n = 10esse processo leva muito tempo (alguns minutos no meu sistema) e o SVG resultante tem aproximadamente 10 MB de tamanho e fica invisível quando visualizado no navegador, porque você não pode ajustar o tamanho do pincel usando TURT. O IrfanView parece funcionar decentemente se você tiver os plugins certos. Não conheço muito bem o SVG, portanto não sei qual é o método preferido para exibir esses arquivos (especialmente quando eles são realmente grandes).

Ei, pelo menos funciona - o que, considerando o Befunge, é algo para agradecer por si só.


1

Python 2, 127 bytes

from turtle import *
def L(l,d=input()-1):
 for x in[1,-2,1,0]:[L(l,d-1),rt(60*x)] if d>0 else fd(l)
for i in'lol':lt(120);L(9)

1
Obrigado por ter o 50.000º post aqui.
30819 Andrew
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.