เกลียวสามเหลี่ยมอูลาม


21

ที่เราเคยมีคู่ของความท้าทายเกี่ยวกับเกลียวลาม แต่นั่นยังไม่เพียงพอ

ในการท้าทายนี้เราจะวางแผนเกลียวสามเหลี่ยมอูลาม (ตรงข้ามกับเกลียวอูลาอัมสี่เหลี่ยมทั่วไป) นี่คือภาพร่างของเกลียวที่มีลักษณะ

ป้อนคำอธิบายรูปภาพที่นี่

ดังที่เราทราบเกลียว Ulamจัดเรียงหมายเลขธรรมชาติทั้งหมดในเกลียวภายนอกและทำเครื่องหมายเฉพาะหมายเลขที่ดีที่สุดเท่านั้น ดังนั้นในภาพร่างด้านบนจะแสดงเฉพาะตัวเลขที่ปรากฏเป็นสีดำ (จำนวนเฉพาะ)

ความท้าทาย

ยอมรับตัวเลขNเป็นอินพุตและแสดงเกลียว Ulam แบบสามเหลี่ยมขึ้นไปยังหมายเลขนั้น

  • อินพุตสามารถเป็น stdin หรือฟังก์ชันอาร์กิวเมนต์
  • เกลียวควรหมุนไปในทิศทางบวก (นั่นคือทวนเข็มนาฬิกา) ดังที่แสดงในภาพด้านบน
  • การหมุนรอบ 120 องศาของรูปด้านบนจะถูกต้องและการเลี้ยวอาจแตกต่างกันไปสำหรับอินพุตที่แตกต่างกัน แต่ด้านต่ำสุดของสามเหลี่ยมที่บอกเป็นนัยควรเป็นแนวนอนเนื่องจากมีการเลี้ยวที่อนุญาตเท่านั้นคือ (ทวีคูณของ) 120 องศา
  • รหัสควรทำงานตามหลักวิชา (ให้เวลาและหน่วยความจำเพียงพอ) สำหรับNใด ๆถึงสิ่งที่ได้รับอนุญาตจากการคำนวณระดับกลางใด ๆ ที่คุณทำกับชนิดข้อมูลเริ่มต้นของคุณ doubleก็เพียงพอแล้ว ไม่จำเป็นสำหรับประเภทจำนวนเต็มขนาดใหญ่
  • อนุญาตให้ใช้ฟังก์ชันในตัวทั้งหมด
  • ฉันจะไม่ยอมรับคำตอบของตัวเอง (ไม่ใช่ว่าฉันคิดว่ามันจะสั้นที่สุดแล้ว ... )

รูปแบบเอาต์พุต

เลือกข้อใดข้อหนึ่งต่อไปนี้

  1. แสดงกราฟที่มีเครื่องหมาย (จุด, วงกลม, กากบาท, สิ่งที่คุณต้องการ) ที่จำนวนเฉพาะและไม่มีอะไรที่ตัวเลขที่ไม่สำคัญ สเกลไม่จำเป็นต้องเหมือนกันสำหรับสองแกน นั่นคือรูปสามเหลี่ยมโดยนัยไม่จำเป็นต้องมีด้านเท่ากันหมด แกนเส้นกริดและป้ายกำกับแกนเป็นอุปกรณ์เสริม จำเป็นต้องมีเครื่องหมายที่จำนวนเฉพาะ

    ตัวอย่างเอาต์พุตสำหรับN = 12 จะเป็นดังนี้ (เปรียบเทียบกับร่างด้านบน) พล็อตที่สองเป็นตัวอย่างที่น่าสนใจยิ่งขึ้นซึ่งสอดคล้องกับN = 10,000

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

  1. สร้างไฟล์รูปภาพด้วยข้างต้นในรูปแบบภาพที่รู้จักกันดี (เช่น png, tiff, bmp)
  2. แสดงรูปเกลียวเป็นศิลปะ ASCIIโดยใช้อักขระเดี่ยวที่คุณเลือกสำหรับช่วงเวลาและพื้นที่ว่างสำหรับช่วงเวลาที่ไม่ว่างพร้อมพื้นที่ว่างเพื่อแยกตำแหน่งตัวเลขในแถวเดียวกัน อนุญาตการนำหน้าหรือเว้นวรรคหรือขึ้นบรรทัดใหม่ ตัวอย่างเช่นกรณีN = 12 ที่ใช้oเป็นอักขระจะเป็น

                 o
                · ·
               · o ·
                o · ·
               · o · o
    

    โดยที่แน่นอนจะมีเฉพาะoเครื่องหมายที่แสดงถึงช่วงเวลาเท่านั้น ·ที่ไม่ใช่เฉพาะ-จะแสดงที่นี่สำหรับการอ้างอิงเท่านั้น

เกณฑ์การชนะ

รางวัลที่แท้จริงคือการเห็นรูปแบบที่น่าทึ่งของคุณเองกอล์ฟโค๊ดรหัสที่สั้นที่สุดชนะ


2
ในอนาคตฉันขอแนะนำให้เลือกเพียงหนึ่งใน [กราฟิก - เอาท์พุต] และ [ascii-art] เพราะมันทำให้การเปรียบเทียบนั้นน้อยกว่า แต่ความท้าทายที่ดีอยู่แล้ว :)
อเล็กซ์ A.

@AlexA ขอบคุณ! ฉันจะคำนึงถึงเรื่องนั้น ดังนั้น ... จะมีคำตอบ Julia ไหม? ;-)
Luis Mendo

ว้าวขอบคุณมากสำหรับเงินรางวัล แต่คุณควรยอมรับคำตอบของคุณเอง มันเป็นที่สั้นที่สุด :)
Martin Ender

มันสมควรได้รับอย่างดี! สำหรับการยอมรับคำตอบหนึ่งในกฎท้าทายคือ "ฉันจะไม่ยอมรับคำตอบของตัวเอง" เมื่อฉันคิดว่าความท้าทายนี้ฉันจำได้ว่ามีความซับซ้อนของ MATL เป็นจำนวนเชิงซ้อนและฟังก์ชั่นแบบกราฟิกดังนั้นมันจึงเป็นเหมือนการโกง :-)
Luis Mendo

คำตอบ:


13

CJam, 49 42 ไบต์

Lri{)mp0S?}%{1$,)/(a@Wf%z+\L*}h;eeSff*W%N*

อินพุตเป็นจำนวนเต็มเดียวใน STDIN เอาต์พุตเป็นตาราง ASCII พร้อมกับ0จำนวนเฉพาะ การหมุนของเกลียวไม่สอดคล้องกัน: จำนวนเกลียวที่ใหญ่ที่สุดจะอยู่แถวล่างเสมอ

ทดสอบที่นี่

คำอธิบาย

แนวคิดพื้นฐานคือการแสดงรูปสามเหลี่ยมเป็นอาเรย์ 2 มิติที่ขรุขระขณะทำการคำนวณ คุณได้รับอาร์เรย์นี้โดยการย้อนกลับบรรทัดและจัดแถวทั้งหมดไปทางซ้าย:

   4
  5 3
 6 1 2
7 8 9 A

จะแสดงเป็น

[[7 8 9 A]
 [6 1 2]
 [5 3]
 [4]]

เนื่องจากเราสะท้อนเส้นเราต้องการม้วนเกลียวในลักษณะตามเข็มนาฬิกา สะดวกสบายเพราะสิ่งที่เราต้องทำคือหมุนสามเหลี่ยมทวนเข็มนาฬิกาและเพิ่มรายการย่อยถัดไปตามลำดับ เราสามารถหมุนอาเรย์แบบ ragged ได้โดยการย้อนกลับทุกบรรทัดและทำการเปลี่ยนมัน:

                                                           [[B C D E F]
[[7 8 9 A]         [[A 9 8 7]           [[A 2 3 4]          [A 2 3 4]
 [6 1 2]   reverse  [2 1 6]   transpose  [9 1 5]   prepend  [9 1 5]
 [5 3]      ---->   [3 5]      ------>   [8 6]      ---->   [8 6]
 [4]]               [4]]                 [7]]               [7]]

ดังนั้นนี่คือรหัส รายละเอียดหนึ่งที่ฉันอยากจะให้ความสนใจคือบิตสุดท้ายที่สร้างเลย์เอาต์สามเหลี่ยม ฉันคิดว่ามันค่อนข้างดี :)

L     e# Push an empty array. This will become the spiral.
ri    e# Read input and convert to integer N.
{     e# Map this block over 0 to N-1...
  )   e#   Increment to get 1 to N.
  mp  e#   Test for primality.
  0S? e#   Select 0 or a space correspondingly.
}%
{     e# While the list we just created is not empty yet...
  1$  e#   Copy the spiral so far.
  ,)  e#   Get the number of lines and increment.
  /   e#   Split the list into chunks of that size.
  (a@ e#   Pull off the first chunk, wrap it in an array, pull up the spiral.
  Wf% e#   Reverse the lines of the spiral.
  z   e#   Transpose the spiral.
  +   e#   Prepend the new line.
  \L* e#   Swap with the remaining chunks and join them back together into a single list.
}h
;     e# Discard the empty list that's left on the stack.
ee    e# Enumerate the spiral. This turns each line into a pair of 0-based index
      e# and the line itself.
Sff*  e# Multiply each element of each pair with a space. For the enumeration index i,
      e# this produces a string of i spaces - the required indentation (keeping in
      e# mind that our spiral is still upside down). For the line itself, this
      e# riffles the cells with spaces, creating the required gaps between the cells.
      e# All of this works because we always end the spiral on the bottom edge.
      e# This ensures that the left edge is always complete, so we don't need
      e# different indentation such as in the N=12 example in the challenge.
W%    e# Reverse the lines to make the spiral point upwards.
N*    e# Join the lines with linefeeds.

1
ฉันรู้ว่าคุณเป็นคนแรก!
Luis Mendo

@ LuisMendo จริง ๆ แล้วฉันจะข้ามอันนี้เพราะฉันคิดว่าการคำนวณดัชนีกริดนั้นน่าเบื่อ แต่แล้วฉันก็รู้ว่าฉันสามารถหมุนสามเหลี่ยมทั้งหมดในขณะที่ต่อท้ายบรรทัด
Martin Ender

1
ฉันชอบคำอธิบายของโปรแกรม CJam ของคุณเสมอเพราะฉันเข้าใจพวกเขาได้และฉันประหลาดใจกับความซับซ้อนของโปรแกรมเหล่านี้สั้น แต่สั้น
ETHproductions

10

MATL , 48 36 ไบต์

:1-H*X^.5+Y[2j3/*YP*ZeYsG:Zp)'.'2$XG

ใช้รุ่นปัจจุบัน (9.3.0)

ลองออนไลน์! ไม่ทราบว่าคอมไพเลอร์ออนไลน์จัดการเพื่อแปลงกราฟิกเอาต์พุตเป็น ASCII แต่ทำสิ่งนี้สร้างพล็อต ASCII โดยประมาณขอบคุณคุณลักษณะ Octaveที่รองรับโดยคอมไพเลอร์ออนไลน์!

แก้ไข (4 เมษายน 2016): ฟังก์ชั่นY[ถูกเปลี่ยนชื่อเป็นkตั้งแต่รุ่น 13.0.0 ลิงก์ไปยังคอมไพเลอร์ออนไลน์รวมการเปลี่ยนแปลงนี้เพื่อให้สามารถทดสอบรหัสได้

ตัวอย่าง

>> matl
 > :1-H*X^.5+Y[2j3/*YP*ZeYsG:Zp)'.'2$XG
 > 
> 20000

สร้างเอาท์พุทกราฟิก (เวอร์ชั่น MATLAB แสดง):

ป้อนคำอธิบายรูปภาพที่นี่

คำอธิบาย

รหัสใช้ตัวเลขที่ซับซ้อนเพื่อติดตามเส้นทางตามด้วยเกลียว ดังที่เห็นได้จากรูปแรกในการท้าทายแต่ละขาตรงของเกลียวเป็นส่วนที่มีความยาวเพิ่มขึ้น 1, 2, 3, 4 ... และเพิ่มการหมุนเป็นวงกลม 120 องศา, 240 องศา, 0 องศา, 120 องศา ..

รหัสจะสร้างการกำจัดที่ซับซ้อนแต่ละรายการจากหมายเลขจำนวนเต็มไปยังลำดับถัดไป displacements ที่ซับซ้อนเหล่านี้มีขนาด 1 และมุม2*pi/3, 4*pi/3หรือ0(เรเดียน) ดังนั้นพวกมันสามารถสร้างได้อย่างง่ายดายในรูปแบบเลขชี้กำลังเชิงจินตภาพ สำหรับสิ่งนั้นลำดับเลขจำนวนเต็ม 0,1,2,2,3,3,3,4,4,4,4 ... จะถูกใช้ก่อน

ลำดับจำนวนเต็มนี้คล้ายกับลำดับ "n ปรากฏ n คูณ " ( OEIS A002024 ) และสามารถรับได้โดยfloor(sqrt(2*n)+.5)ที่n0,1,2,3, ... การคูณโดย2j*pi/3ที่ไหนjหน่วยจินตภาพจะสร้างการกระจัดที่ซับซ้อนที่ต้องการ

การกระจัดจะถูกสะสมเพื่อคำนวณตำแหน่งที่สอดคล้องกับตัวเลขจำนวนเต็มในเกลียว เลขจำนวนเต็มแรกในเกลียวซึ่งก็1คือตั้งอยู่ในตำแหน่ง1ในระนาบเชิงซ้อน

ในที่สุดตำแหน่งที่สอดคล้องกับตัวเลขที่ไม่สำคัญจะถูกยกเลิกและส่วนที่เหลือจะถูกพล็อตในระนาบเชิงซ้อน

:1-H*X^.5+Y[     % floor(sqrt(2*n)+.5) for n from 0 to N-1, where N is implicit input
2j3/*YP*Ze       % exp(2j*pi/3* ... )
Ys               % cumulative sum. Produces complex positions
G:               % vector 1,2...,N, where N is previous input
Zp               % logical index to select only prime numbers
)                % use that index to keep only complex positions of primes
'.'2$XG          % plot using marker '.'

ฉันต้องอ่านอะไรต่อไปนี้
Brain Guider

ลองออนไลน์หรือไม่! สนับสนุนกราฟิกเอาต์พุตสำหรับ MATL หรือไม่
Alex A.

ฉันคิดว่า TIO ไม่รองรับเอาต์พุตกราฟิกหรือไม่ ถ้าเป็นเช่นนั้นฉันสามารถให้ MATL ถ่ายโอนรูปภาพไปยัง.pngไฟล์ที่หน้าเว็บ @AlexA แสดงโดยอัตโนมัติได้อย่างง่ายดาย
Luis Mendo

เฮ้! ฉันทำแบบทดสอบง่ายๆ ( plot(1:5)) และมันจะสร้างเอาท์พุทกราฟิกข้อความ !! matl.tryitonline.net/#code=NTpYRw&input= @AlexA เป็นไงบ้าง ??
Luis Mendo

4
โว้ว! ที่น่ากลัว!
Alex A.

8

ควรวาดภาพด้วย

LaTeX / PGF, 527 594ไบต์

\documentclass{standalone}\usepackage{pgf}\let\z\let\z\e\advance\z\f\ifnum\z\h\the\z\a\newcount\a\i\a\j\a\l\a\x\a\y\a\p\a\q\a\n\i=1\l=1\p=-1\q=1\def\m#1{\e\i by1\e\j by1\e\x by\h\p\e\y by\h\q\pgfmathparse{isprime(\h\i)}\f\pgfmathresult=1\pgfpathcircle{\pgfpoint{\h\x cm}{\h\y cm}}3pt\fi\f\j=\l\e\l by1\j=0\f\p=1\p=-1\q=1\else\f\p=-1\p=0\q=-1\else\p=1\q=0\fi\fi\fi\f#1>0\e#1by-1\m#1\fi}\begin{document}\begin{pgfpicture}\pgftransformcm10{cos(60)}{sin(60)}\pgfpointorigin\n=4000\m\n\pgfusepath{fill}\end{pgfpicture}\end{document}

527 ไบต์เป็นเอกสารเต็มรูปแบบดังกล่าวข้างต้นเช่นรวมถึงการเริ่มนำและพารามิเตอร์ (ที่นี่ 4000 ดังนั้น ~ 523 ไม่มีพารามิเตอร์) สร้างไฟล์ PDF

ความคิดพื้นฐาน: ก็แค่วาด ใช้การแปลงเมทริกซ์สำหรับกริดสามเหลี่ยม ปัญหาเดียวก็คือจุดที่ได้รับผลกระทบ (และยืดออก) โดยการแปลง ดังนั้นฉันเลือกเครื่องหมายวงรี :) สิ่งที่ฉันหมายถึงชัดเจนในภาพที่สอง (n = 250, 5pt)

ข้อแม้อื่น: สามารถจัดการได้น้อยกว่า 5000 เล็กน้อยเนื่องจากขนาดสแต็กสูงสุดของ TeX ภาพแรกสำหรับ n = 4000 เห็นได้ชัดว่าเป็นไปได้ที่จะเพิ่มขนาดสแต็คฉันไม่ได้ลองเลย

ใช้ isprime()PGF

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

Ungolfed:

\documentclass[border=10cm]{standalone}

\usepackage{pgf}

\newcount\ulami
\newcount\ulamj
\newcount\ulamlen

\newcount\ulamx
\newcount\ulamy
\newcount\ulamdx
\newcount\ulamdy

\ulami=1 %
\ulamj=0 %
\ulamlen=1 %
\ulamdx=-1 %
\ulamdy=1 %
\ulamx=0 %
\ulamy=0 %

\def\ulamplot#1{%
  \advance\ulami by 1 %
  \advance\ulamj by 1 %

  \advance\ulamx by \the\ulamdx %
  \advance\ulamy by \the\ulamdy %

  \pgfpathmoveto{\pgfpoint{\the\ulamx cm}{\the\ulamy cm}}

  \pgfmathparse{isprime(\the\ulami)}
  \let\r=\pgfmathresult
  \ifnum\r=1
    \pgfpathcircle{\pgfpoint{\the\ulamx cm}{\the\ulamy cm}}{5pt}
  \fi

  \ifnum\ulamj=\the\ulamlen %
    \advance\ulamlen by 1 %
    \ulamj=0 %
    \ifnum\ulamdx=1 %
      \ulamdx=-1 %
      \ulamdy=1 %
    \else%
      \ifnum\ulamdx=-1 %
        \ulamdx=0 %
        \ulamdy=-1 %
      \else%
        \ulamdx=1 %
        \ulamdy=0 %
      \fi
    \fi
  \fi

  \ifnum#1>0 %
    \advance#1 by -1 %
    \ulamplot{#1}%
  \fi
}

\begin{document}

\begin{pgfpicture}
  \pgfmathsetmacro{\x}{cos(60)}
  \pgfmathsetmacro{\y}{sin(60)}
  \pgftransformcm{1}{0}{\x}{\y}{\pgfpointorigin}

  \pgfpathmoveto{\pgfpointorigin}
  \color{blue}
  \newcount\ulamn
  \ulamn=400
  \ulamplot{\ulamn}
  \pgfusepath{stroke,fill}
\end{pgfpicture}

\end{document}

1
ว้าว. มันไม่เคยเกิดขึ้นกับฉันที่จะทำเช่นนี้ใน LaTeX
Luis Mendo

การใช้lualatexหรือคอมไพเลอร์อื่นที่จัดสรรแบบไดนามิกควรอนุญาตให้คุณข้ามขนาดสแต็กถ้าฉันเข้าใจความคิดเห็นที่เกี่ยวข้องของคุณอย่างถูกต้อง ดังนั้นจึงไม่ใช่ข้อ จำกัด ของคำตอบของคุณเพียง แต่การใช้งานส่วนใหญ่ที่คุณใช้งาน
Andras Deak

ขออภัยฉันได้ตรวจสอบแล้วและขีด จำกัด ขนาดสแต็กป้อนข้อมูลไม่เกี่ยวข้องกับการจัดสรรหน่วยความจำซึ่งฉันได้กล่าวถึงในความคิดเห็นก่อนหน้าของฉัน :(
Andras Deak

@AndrasDeak ไม่เป็นไรขอบคุณที่มองหามัน ฉันพบวิธีการที่เห็นได้ชัดว่าเพิ่มขนาดสแต็ก แต่ไม่ลองด้วยตัวเอง (ยัง)

@CamilStaps ขอบคุณฉันได้พบโพสต์อื่นที่คล้ายกัน แต่ฉันไม่ได้ลองเลย อย่างไรก็ตามฉันใช้โพสต์ของ Christian Feuersängerเป็นสาธุคุณ :)
Andras Deak


2

Python ขนาด 263 ไบต์

เป็นสิ่งใหม่สำหรับ Python แน่นอนว่าจะมีการปรับปรุง :)

from matplotlib.pyplot import*
from math import*
def f(m):
 s=[];X=[];Y=[];i=x=y=0
 while len(s)<m:i+=1;s+=[i%3*pi*2/3]*i
 for i in range(m):
  x+=cos(s[i]);y+=sin(s[i]);j=i+2
  if all(map(lambda a:j%a>=1,range(2,int(j**.5+1)))):X+=[x];Y+=[y]
 scatter(X,Y);show()

ตัวอย่าง:

f(100000)

ป้อนคำอธิบายรูปภาพที่นี่


คุณสามารถร่นs=[];X=[];Y=[];i=1;x=0;y=0ไปs=X=Y=[];i=1;x=y=0;
rp.beltran

ไม่ต้องสนใจเครื่องหมายอัฒภาคพิเศษในตอนท้าย ควรสำรองคุณ 8 ไบต์
rp.beltran

@ rp.beltran สิ่งนี้ใช้ไม่ได้ ฉันคิดว่ามันเกี่ยวข้องกับความจริงที่ว่าวัตถุมีค่าเดียวกัน เพียง x=y=0แต่สามารถเพิ่ม
lambruscoAcido

ฉันไม่ดีคุณพูดถูก ฉันลืมว่า Python ส่งรายการโดยอ้างอิง ตัวเลขไม่มีการเปลี่ยนแปลงและดังนั้นจึงปลอดภัยที่จะทำกับจำนวนเต็ม
rp.beltran

1

R, 137 ไบต์

ใช้ฟังก์ชั่นในตัวเท่านั้นแม้สำหรับหมายเลขเฉพาะ ด้วยวิธีการเวกเตอร์แทนการวนซ้ำมันเร็ว แต่ไม่สามารถรองรับจำนวนมากได้

แข็งแรงเล่นกอล์ฟ:

g=function(m){M=1:m;s=rep(M,M)[M]%%3*pi*2/3;k=cumsum;j=sapply(seq(s)+1,function(n)n<4|all(n%%2:n^.5>=1));plot(k(cos(s))[j],k(sin(s))[j])}

Ungolfed:

g=function(m) {
  M = 1:m
  s = rep(M,M)[M] %% 3 * pi * 2/3
  k=cumsum
  j=sapply(seq(s)+1,function(n)n<4|all(n%%2:n^.5>=1)) # primes
  plot(k(cos(s))[j],k(sin(s))[j])    # cumulated coordinates
}

ตัวอย่าง:

g(10000)

ป้อนคำอธิบายรูปภาพที่นี่


คุณสามารถเพิ่มผลลัพธ์ตัวอย่างได้หรือไม่
Luis Mendo

@LuisMendo แน่ใจ ฉันต้องคิดหาวิธีเพิ่มพล็อตเท่านั้น
lambruscoAcido
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.