임의의 6 각형 그림 그리기


23

여기에 이미지 설명을 입력하십시오

위의 이미지를 hexa-glyph라고합니다. Hexa-glyphs는 DiffEq 수업 중에 낙서하는 동안 만들어 낸 멋진 패턴입니다. 하나 만드는 방법은 다음과 같습니다.

  1. 일반 hexagram 모양의 다음 포인트 세트를 고려하십시오. 내부 육각형은 최종 글리프를 포함하는 반면, 외부 6 점은 별을 형성하며 선 그리기를 시작할 곳입니다.

여기에 이미지 설명을 입력하십시오

  1. 바깥 쪽 6 점에서 무작위로 쌍을 선택하십시오. 효율성을 위해 선택한 두 지점 사이에 하나 이상의 다른 지점이 있어야합니다 (그렇지 않으면 최종 그림에는 영향을 미치지 않습니다). 그런 다음 두 지점 각각 에서 다른쪽으로 광선 을 투사합니다 . 이 광선은 이전 선으로 차단 되어 있습니다.

여기에 이미지 설명을 입력하십시오

  1. 다음 몇 개의 이미지와 같이 9 개의 모서리가 모두 형성 될 때까지이 과정을 반복하십시오.

여기에 이미지 설명을 입력하십시오

  1. 다음은 광선이 차단 된 예입니다. 광선 선단의 끝은 여전히 ​​표시되지만 가운데 부분은 처음 두 선분으로 가려집니다.

여기에 이미지 설명을 입력하십시오

  1. 이 두 광선도 "차단"되지만 동일한 선으로 차단되어 눈에 띄는 차이가 발생하지 않습니다.

여기에 이미지 설명을 입력하십시오

  1. 9 개의 선이 모두 그려 질 때까지 빨리 감기. 건너 뛴 단계에 대한 자세한 설명을 원한다면 설명해 드리겠습니다.

여기에 이미지 설명을 입력하십시오

  1. 마지막으로 별의 점을 제거하십시오. 더 예쁘게 보이기 위해 두꺼운 점들도 제거됩니다.

여기에 이미지 설명을 입력하십시오

도전

임의의 16 진수 글리프를 시각적으로 표시해야합니다. 이것은 코드 골프이며 가장 적은 바이트 수입니다.

  1. 가능한 모든 hexa-glyph는 긍정적 인 확률로 나타나야합니다. 9 개의 모서리가 그려지는 순서를 변경하여 다른 6 각 문자가 생성됩니다.

  2. 또한 프로그램에서 출력 된 모든 이미지는 유효한 16 진수 문자 여야합니다. 내부 육각형의 전체 윤곽선과 같은 특정 패턴은 16 진수 문자로 나타날 수 없으므로 프로그램에서 이러한 패턴을 출력하지 않아야합니다.

  3. 출력은 그래픽 이미지 (스크린 또는 파일로 인쇄) 여야합니다.

  4. 육각형은 규칙적이어야하지만 모든 방향으로 나타날 수 있습니다.

  5. 반사 / 회전은 고유 한 것으로 간주 되지 않습니다 . (이로 인해 요구 사항 1을 더 쉽게 따를 수 있습니다).


8
I made up while doodling during my DiffEq class. 모든 위대한 발견이 일어나는 방식 ... : P
Rɪᴋᴇʀ

이미지의 최소 요구 사항은 무엇입니까? 각 모서리가 모호하게 올바른 지점에 배치되어있는 한 ASCII 예술을 어느 정도까지 인식 할 수 있어야합니까?
John Dvorak

@JanDvorak ASCII 아트 및 그래픽 출력을 생성하는 프로그램은 쉽게 비교할 수 없기 때문에 도전의 ASCII 아트 옵션 (예 : 게시 후 2 분 이내)을 제거했습니다.
PhiNotPi

그러면 픽셀 아트는 어떻습니까? PPM 헤더는 너무 무겁지 않으며 나중에 유일한 차이점은 '01'공백 대신 인터리브 된 것을 사용 하는 것입니다 ' *'.
John Dvorak

그러면 @JanDvorak Output이 올바른 형식의 이미지 파일이됩니다. 그런 다음 아무 문제가 없습니다.
PhiNotPi

답변:


18

매쓰, 273 268 264 242 바이트

c=CirclePoints;b@_=k=1>0;Graphics[Line/@Cases[Append[Join@@({c@6,{3^.5/2,-Pi/6}~c~6}),{0,0}][[b@#=!k;#]]&/@TakeWhile[#,t=k;(r=t;t=b@#;r)&]&/@Join@@RandomSample[{#,Reverse@#}&/@Partition[Range@12,3,2,1]~Join~Array[{2#,13,2#+6}&,3]],{_,__}]]

첨자로 렌더링 T매쓰 및 후위 전치 연산자이다.

이것의 버그를 분류하는 데는 영원히 걸렸습니다 ... 결국 끝까지 나는 몇 가지를 해킹하여 작동 시켰습니다. 그래서 이것은 차선책입니다. 또한 육각형 외부의 선을 통해 문자 그대로 스펙을 구현하고 Mathematica의 지오메트리 함수가 교차점을 처리하도록하는 것이 전체적으로 더 나은지 궁금합니다.

이 프로그램은 전체 프로그램이므로 단일 REPL 세션에서 코드를 여러 번 실행하려면 앞에 접두사를 붙여야합니다 Clear[b].

20 회 실행 결과는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

설명

이 솔루션은 외부 별점을 전혀 사용하지 않습니다. 대신 6 각형의 일부인 점과 한 번에 3 개의 점을 덮는 선으로 직접 작동합니다.

포인트에 라벨을 붙입니다.

여기에 이미지 설명을 입력하십시오

1약간 이상한 코너에서 시작하지만 이것은 (또한 다소 이상한) 기본 동작 때문입니다 CirclePoints. 거기에서 육각형을 시작하면 가장 저렴했습니다.

이제 우리는 바깥 별의 연결된 점에 해당하는 세 점을 통해 관련 선을 찾고 싶습니다. 육각형 주위의 것은 물론 홀수에서 시작하여 3 개의 인접한 점 (모듈로 12)입니다. 중심을 가로 지르는 사람은 짝수로 구성 n, 13n+6.

이 라인의 표현 (3 개의 포인트 목록 형태로 다음 코드에 의해 생성됨) :

Partition[Range@12,3,2,1]~Join~Array[{2#,13,2#+6}&,3]

Partition육각형 주위 선과 생성 Array중심을 통해 라인. 두 빔을 처리하기 위해이 함수를 선리스트에 매핑합니다.

{#,Reverse@#}&

이제 RandomSample무작위 순서로 처리하기 위해 이것들을 섞 습니다. Join @@빔리스트를 갖도록 쌍리스트를 평탄화합니다.

짧은 중단 : 어떤 지점이 이미 차단되었는지 추적하기 위해 조회 기능을 사용합니다.이 기능 은 모든 값에 대해 b로 초기화 True됩니다 b@_=k=1>0;. 빔을 처리 할 때 우리는이 첫 번째 점까지의 모든 점 유지 b[n] == False( 포함 하는 하나) :

TakeWhile[#,t=k;(r=t;t=b@#;r)&]&

나는 이것이 가장 골프 가능한 부분이라고 생각합니다. Mastermind 를하기 위해 두 개의 임시 변수를 사용하는 것은 정말 비싸 보입니다. 어쨌든, 이것의 결과는 우리가 그릴 수있는 선의 포인트를 제공합니다. 이제이 함수는 각 지점에 매핑됩니다.

Append[Join@@({c@6,{3^.5/2,-Pi/6}~c~6}),{0,0}][[b@#=!k;#]]&

첫 번째 부분은 두 번의 호출의 인터리브 결과를 사용하여 CirclePoints(가장자리 중심과 육각형의 모서리가 다른) 13 개의 모든 점리스트를 생성합니다 . 참고 b@#=!k지금 현재 포인트에 대한 룩업 테이블의 값을 설정하는 False더 빔이 통과 할 수 없도록한다. 마지막으로이 값은 올바른 2D 점을 얻기 위해 좌표 목록에 대한 인덱스로 사용됩니다.

Cases[...,{_,__}]

개별 단일 (및 표시) 포인트로 렌더링되므로 모든 단일 요소 목록이 삭제됩니다. 마지막으로 결과를 렌더링합니다.

Graphics[Line/@...]

b@_=1>0=b=1>0&
CalculatorFeline

@CatsAreFluffy 나중에 개별 값을 덮어 쓸 수 있어야하기 때문에 그것이 효과가 있다고 생각하지 않습니다.
Martin Ender

CirclePoints를 잘 사용합니다.
DavidC

유튜브 링크에 감사드립니다.
DanTheMan

8

신발 (루비) Rev C 184 bytes

메인 프로그램에서 드로잉 방법으로 특정 하프 라인을 그려야하는지 확인하는 책임을 전달하여 12 바이트를 절약했습니다. 그러나 메인 프로그램은 여전히 ​​전체 라인이 완전히 차단되었는지 확인해야합니다.

Shoes.app{t=[]
d=->p,q{t[p]&&t[q]||line(p/6*8,p%6*14,q/6*8,q%6*14)}
%w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|b=i.sum/2
c=b*2-a=i.ord
t[a]&&t[c]||(d[a,b]
d[b,c]
t[a]=t[b]=t[c]=1)}}

신발 (루비) 205 ... Rev B 196 bytes

Shoes는 GUI 등을 빌드하기위한 루비 기반 도구입니다. 처음 사용한 것입니다. mothereff.in/byte-counter는 제 제출을 196 바이트로 계산하지만 어떤 이유로 든 Shoes는 202로 계산합니다.

또한 루비를 사용하면 t[a=i.ord]이상하게도 할 수 있지만 신발에서는 예상대로 작동하지 않는 것 같습니다.

Shoes.app{t=[]
d=->p,q{line(p/6*8,p%6*14,q/6*8,q%6*14)}
%w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|b=i.sum/2
c=b*2-a=i.ord
t[a]&&t[c]||(t[a]&&t[b]||d[a,b]
t[b]&&t[c]||d[b,c]
t[a]=t[b]=t[c]=1)}}

설명

육각형 외부의 선 부분은 고려하지 않습니다. 그려야 할 부분 만 그립니다. 중요한 점은 선이 교차점을 교차하는지 여부입니다 (그린 부분 만 그릴 경우 교차점에서 시작 / 종료한다는 의미입니다).

기본 규칙은 선의 두 끝 점이 모두 방문 된 경우 선이 차단되어 그려지지 않아야한다는 것입니다. 선이 두 개 반으로 그려 지므로 중간 점을 방문했는지 확인하여 각 반쪽을 그려야하는지 확인해야합니다.

나는 배열에서 어떤 지점을 방문했는지 추적한다 t[]. 이것은 아래 그리드의 각 물리적 좌표에 대한 항목을 포함합니다. 별도의 13 요소 논리 배열이 없습니다. 결국, t[]최대 13 개만 유용한 데이터를 포함하지만 87 개의 요소를 가질 수 있습니다.

내부적으로 선 끝점의 좌표는 단일 숫자 z로 표시됩니다. 여기서 z % 6은 y 좌표이고 z / 6은 x 좌표입니다. 이 시스템에서 육각형이 평평 해집니다. 선이 그려지면 x 스케일에 8이 곱해지고 y 스케일에 14가 곱해집니다. 14는 14 / 8 = 1.75 vs sqrt (3) = 1.732에 대한 아주 가까운 합리적인 근사치입니다.

내부 좌표계는 샘플 출력과 함께 아래에 나와 있습니다.

여기에 이미지 설명을 입력하십시오

언 골프

Shoes.app{
  t=[]                                          #Empty array for status tracking
  d=->p,q{line(p/6*8,p%6*14,q/6*8,q%6*14)}      #Drawing method. Convert p and q into x,y pairs, scale and draw line.
  %w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|#take an array of the coordinates of the endpoints of each line, shuffle, then for each line
    b=i.sum/2                                   #b = midpoint of line, convert ASCII sum to number (average of the two coordinates)
    a=i.ord                                     #a = first endpoint of line, convert ASCII to number (no need to write i[0].ord)
    c=b*2-a                                     #c = second endpoint of line (calculating is shorter than writing i[1].ord)
    t[a]&&t[c]||(                               #if both endpoints have already been visited, line is completely blocked, do nothing. ELSE
      t[a]&&t[b]||d[a,b]                        #if first endpoint and midpoint have not both been visited, draw first half of line
      t[b]&&t[c]||d[b,c]                        #if second endpoint and midpoint have not both been visited, draw second half of line
      t[a]=t[b]=t[c]=1                          #mark all three points of the line as visited
    )
  }
}

더 많은 샘플 출력

이것은 이전 버전의 프로그램에서 수행되었습니다. 유일한 차이점은 창에서 hexaglyph의 위치가 약간 다르다는 것입니다.

여기에 이미지 설명을 입력하십시오


mothereff.in/byte-counter counts my submission as 196 bytes, but for some reason Shoes counts it as 202.이것이 사실인지 100 % 알지 못하지만 Shoes가 코드를 196 대신 202 바이트로 계산 한 이유는 줄 바꿈이 실제로 두 문자 시퀀스 "\ r \ n"이기 때문이라고 생각합니다. 이렇게하면 모든 줄 바꿈이 두 번 계산됩니다. \ r 및 \ n에 관한 스택 오버플로 답변입니다.
K Zhang

Hehe 나는 신발 XD 와 루비 라는 이름을 얻을 수 없습니다
Beta Decay

3

파이썬 604 591 574 561 538 531 536 534 528 493 483 452 431 420 419 415 388 385 384 바이트

나는 라인의 두 끝 점이 이미 방문했는지 확인하여 라인이 막혔는지 확인하는 Level River St의 아이디어 를 채택 했습니다. 27 바이트가 절약됩니다. 골프 제안을 환영합니다.

편집 :g(p,q) 3 바이트 버그 수정 및 골프 . L1 바이트 골프 .

from turtle import*
from random import*
R=range
G=goto
*L,=R(9)
shuffle(L)
a=[0]*13
ht()
T=12
c=[(j.imag,j.real)for j in(1j**(i/3)*T*.75**(i%2/2)for i in R(T))]+[(0,0)]
def g(p,q):pu();G(c[p]);a[p]*a[q]or pd();G(c[q])
for m in L:
 p=2*m;x,y,z=R(p,p+3)
 if m<6:
  if a[x]*a[z%T]<1:g(x,y);g(y,z%T);a[x]=a[y]=a[z%T]=1
 else:
  if a[p-11]*a[p-5]<1:g(p-11,T);g(p-5,T);a[p-11]=a[p-5]=a[T]=1

풀기 :

from turtle import*
from random import*

def draw_line(points, p_1, p_2):
    penup()
    goto(points[p_1])
    if not (a[p] and a[q]):
        pendown()
    goto(points[p_2])

def draw_glyph():
    ht()
    nine_lines = list(range(9))
    shuffle(nine_lines)
    size = 12
    center = [0,0]

    points = []
    for i in range(12):      # put in a point of a dodecagon
                             # if i is even, keep as hexagon point
                             # else, convert to hexagon midpoint
        d = 1j**(i/3) * 12   # dodecagon point
        if i%2:
            d *= .75**.5     # divide by sqrt(3/4) to get midpoint
        points += (d.imag, d.real)
    points.append(center)

    a = [0]*13
    for m in nine_lines:
        p = 2*m
        if m<6:
            x, y, z = p, p+1, p+2
            if not (a[x] and a[z%12]):
                draw_line(points, x, y)
                draw_line(points, y, z%12)
                a[x] = a[y] = a[z%12] = 1
        else:
            if not (a[p-11] and a[p-5]):
                draw_line(p-11, 12)
                draw_line(p-5, 12)
                a[p-11] = a[p-5] = a[12] = 1

헥사 글리프 자체는 12 픽셀 육각형을 기본으로 사용하기 때문에 매우 작습니다 (골프 목적으로). 다음은 hexa-glyphs의 예입니다 (잘못 잘린 것에 대한 사과) :

hexa-glyph의 예 hexa-glyph의 예 hexa-glyph의 예 hexa-glyph의 예 hexa-glyph의 예 hexa-glyph의 예


몇 바이트를 절약 할 수 있습니다 :R=range;G=goto
Tim Čas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.