พล็อตเตอร์เชิงพีชคณิต


14

โค้งพีชคณิตเป็นบางอย่าง "1D เซต" ของ "2D เครื่องบิน" ที่สามารถอธิบายเป็นชุดของศูนย์ของพหุนาม{(x,y) in R^2 : f(x,y)=0 } fที่นี่เราพิจารณาระนาบ 2 มิติเป็นระนาบจริงR^2ซึ่งเราสามารถจินตนาการได้อย่างง่ายดายว่าเส้นโค้งดังกล่าวจะมีลักษณะอย่างไรโดยทั่วไปสิ่งที่คุณสามารถวาดด้วยดินสอ

ตัวอย่าง:

  • 0 = x^2 + y^2 -1 วงกลมรัศมี 1
  • 0 = x^2 + 2y^2 -1 วงรี
  • 0 = xyข้ามรูปร่างพื้นสหภาพของแกน x และแกน y
  • 0 = y^2 - x พาราโบลา
  • 0 = y^2 - (x^3 - x + 1)ไข่โค้ง
  • 0 = x^3 + y^3 - 3xy the folium of Descartes
  • 0 = x^4 - (x^2 - y^2) lemniscate
  • 0 = (x^2 + y^2)^2 - (x^3 - 3xy^2) trifolium
  • 0 = (x^2 + y^2 - 1)^3 + 27x^2y^2 แอสโตรอย

งาน

กำหนดพหุนามf(ตามที่กำหนดไว้ด้านล่าง) และช่วง x / y ให้ส่งภาพขาวดำอย่างน้อย 100x100 พิกเซลที่แสดงเส้นโค้งเป็นเส้นสีดำบนพื้นหลังสีขาว

รายละเอียด

สี : คุณสามารถใช้สองสีที่คุณเลือกได้มันควรจะบอกได้ง่าย

เรื่องย่อ: แทนที่จะเป็นภาพพิกเซลคุณยังสามารถส่งออกภาพนี้เป็น ascii-art โดยที่พื้นหลัง "พิกเซล" ควรเว้นวรรค / ขีดเส้นใต้หรือตัวละครอื่น ๆ ที่ "ดูว่างเปล่า" และบรรทัดสามารถสร้างตัวละครที่มีลักษณะ " เต็ม" เหมือนMหรือหรือX#

คุณไม่ต้องกังวลกับนามแฝง

คุณจะต้องพล็อตบรรทัดที่สัญญาณของการเปลี่ยนแปลงพหุนามจากด้านหนึ่งของบรรทัดไปที่อื่น (นั่นหมายความว่าคุณสามารถใช้อัลกอริธึมยกกำลังสอง) คุณไม่จำเป็นต้องพล็อต "กรณีพยาธิวิทยาเหมือน0 = x^2ที่สัญญาณทำไม่ได้เปลี่ยนไปจากเมื่อด้านหนึ่งของสายไปที่อื่น ๆ . f(x,y)แต่สายที่ควรจะเป็นอย่างต่อเนื่องและการแยกภูมิภาคของสัญญาณที่แตกต่างกันของ

พหุนาม : พหุนามได้รับเป็น(m+1) x (n+1)เมทริกซ์ / รายการของค่าสัมประสิทธิ์ (จริง) ในตัวอย่างด้านล่างเงื่อนไขของสัมประสิทธิ์จะได้รับในตำแหน่งของพวกเขา:

[   1 * 1,   1 * x,   1 * x^2,   1 * x^3,  ... , 1 * x^n ]
[   y * 1,   y * x,   y * x^2,   y * x^4,  ... , y * x^n ]
[   ...  ,   ...   ,   ...   ,    ...   ,  ... ,   ...   ]
[ y^m * 1, y^m * x, y^m * x^2, y^m * x^3 , ..., y^m * x^n]

หากคุณต้องการคุณสามารถสมมติว่าเมทริกซ์เป็นสี่เหลี่ยมจัตุรัส (ซึ่งสามารถทำได้ด้วยการเติมศูนย์ที่จำเป็นเสมอ) และหากคุณต้องการคุณสามารถสันนิษฐานได้ว่าขนาดของเมทริกซ์นั้นเป็นอินพุตแบบ aditional

ในตัวอย่างต่อไปนี้ตัวอย่างจากด้านบนแสดงเป็นเมทริกซ์ที่นิยามดังนี้:

Circle:       Ellipse:      Parabola:  Cross:    Elliptic Curve: e.t.c
[-1, 0, 1]    [-1, 0, 1]    [ 0,-1]    [ 0, 0]   [-1, 1, 0,-1]
[ 0, 0, 0]    [ 0, 0, 0]    [ 0, 0]    [ 0, 1]   [ 0, 0, 0, 0]
[ 1, 0, 0]    [ 2, 0, 0]    [ 1, 0]              [ 1, 0, 0, 0]

กรณีทดสอบที่มีช่วง x / ช่วง y:

(ในรูปแบบที่ไม่สามารถอ่านได้ แต่ดีกว่าคัดลอกวางได้ที่นี่ใน pastebin )

Circle:     
[-1, 0, 1]   [-2,2]   [-2,2]
[ 0, 0, 0]
[ 1, 0, 0]

Ellipse:
[-1, 0, 1]   [-2,2]   [-1,1]
[ 0, 0, 0]
[ 2, 0, 0]

Cross:
[ 0, 0]      [-1,2]   [-2,1]
[ 0, 1]

Parabola:
[ 0,-1]      [-1,3]   [-2,2]
[ 0, 0]
[ 1, 0]

Elliptic Curve:
[-1, 1, 0,-1]    [-2,2]   [-3,3]
[ 0, 0, 0, 0]  
[ 1, 0, 0, 0]  

Folium of Descartes:
[  0,  0,  0,  1]    [-3,3]   [-3,3]
[  0, -3,  0,  0]
[  0,  0,  0,  0]
[  1,  0,  0,  0]

Lemniscate:
[  0,  0, -1,  0,  1]    [-2,2]   [-1,1]
[  0,  0,  0,  0,  0]
[  1,  0,  0,  0,  0]

Trifolium:
[ 0, 0, 0,-1, 1]    [-1,1]   [-1,1]
[ 0, 0, 0, 0, 0]
[ 0, 3, 2, 0, 0]
[ 0, 0, 0, 0, 0]
[ 1, 0, 0, 0, 0]

Astroid:
[ -1,  0,  3,  0, -3,  0,  1]    [-1,1]   [-1,1]
[  0,  0,  0,  0,  0,  0,  0]
[  3,  0, 21,  0,  3,  0,  0]
[  0,  0,  0,  0,  0,  0,  0]
[ -3,  0,  3,  0,  0,  0,  0]
[  0,  0,  0,  0,  0,  0,  0]
[  1,  0,  0,  0,  0,  0,  0]

ฉันได้รับแรงบันดาลใจจากเส้นโค้งบางส่วนจากไฟล์ PDF นี้


" คุณไม่ต้องกังวลกับนามแฝง " หมายความว่าเราสามารถระบายสีแต่ละพิกเซลตามจุดศูนย์กลางของเส้นหรือไม่
Peter Taylor

ฉันไม่เห็นการเชื่อมต่อกับนามแฝง แต่ไม่ควรมีเส้นต่อเนื่องคั่นบริเวณที่มีสัญญาณต่างกัน
ข้อบกพร่อง

เมทริกซ์ไม่mx nแต่x(m+1) (n+1)เราทำอะไรใช้เป็น input: m, nหรือm+1,n+1? หรือเราจะเลือก?
Luis Mendo

เราสามารถแสดงฟังก์ชันกราฟในหน้าต่างใหม่ได้หรือไม่?
R. Kap

1
@ LuisMendo ใช่แกนสามารถไปในทิศทางใดก็ได้ที่คุณต้องการ (ตราบเท่าที่พวกเขาเป็นมุมฉาก =)
ข้อบกพร่อง

คำตอบ:


10

Haskell, 283 275 ไบต์

gควรเรียกใช้ฟังก์ชันด้วยเมทริกซ์และทั้งสองช่วงเป็นอาร์กิวเมนต์ เมทริกซ์เป็นเพียงรายการของรายการช่วงแต่ละรายการองค์ประกอบสองรายการ

import Data.List
t=transpose
u=tail
z=zipWith
l%x=sum$z(*)l$iterate(*x)1                                   --generate powers and multiply with coefficients
e m y x=[l%x|l<-m]%y                                         --evaluate the encoded polynomial
a#b=[a,a+(b-a)/102..b]                                       --create a range
g m[u,w][i,j]=unlines$v[map((0<).e m y)$u#w|y<-i#j]          --evaluate the function on the grid, get the sign
f g=u[u$u$map fst$scanl(\(r,l)c->(c==l,c))(1<0,1<0) l|l<-g]  --find +- or -+ transitions within lines
a&b|a&&b=' '|0<1='#'                                         --helper function for creating the string
v g=z(z(&))(f g)(t$f$t g)                                    --create the string

นี่คือผลลัพธ์สำหรับกรณีที่น่าสนใจยิ่งขึ้น: โปรดทราบว่าฉันต้องลดขนาดผลลัพธ์จาก 100x100 เป็นประมาณ 40x40 เพื่อให้พอดีกับคอนโซล โปรดทราบว่าแกน y กำลังชี้ลงด้านล่าง


มีสนามกอล์ฟขนาดเล็กสองสามแห่งที่คุณสามารถสร้างได้ที่นี่ บรรทัดสุดท้ายใช้ parens เมื่อสามารถใช้$เพื่อบันทึกไบต์ ทั้งสองสถานที่ที่คุณmapสามารถใช้เป็น(<$>)และเนื่องจากคุณใช้เพียงeครั้งเดียวคุณสามารถดึง(0<)ด้านในของมันเป็นคำจำกัดความ นอกจากนี้ยังeจะได้รับการตั้งชื่อ(!)เพื่อบันทึก 3 ไบต์
โพสต์ร็อค Garf Hunter

และ infixing zในคำจำกัดความของการvอนุญาตให้คุณกำจัด 4 วงเล็บ (รอบz(&)และf g)
โพสต์ร็อค Garf Hunter

นอกจากนี้คุณยังสามารถเปลี่ยนชื่อ#ไปตัวเดียว (เช่นs) gและมีมันตรงกับรูปแบบในรายการแทน (เช่นs[a,b]=[a,a+(b-a)/102..b];g m u i=unlines$v[m!y<$>s u|y<-s i])
โพสต์ร็อค Garf Hunter

6

Matlab, 114 100 92 ไบต์

เครื่องมือที่เหมาะสมสำหรับงานหรือไม่ ฉันใช้วิธีที่น่าสนใจใน Matlabprintfเพื่อสร้างพหุนามเป็นสตริง พหุนามนี้สามารถให้ezplotที่โค้งกราฟนัยในโดเมนที่ระบุ เพื่อความสะดวกในการอ่านรหัสจะถูกนำเสนอด้วยการขึ้นบรรทัดใหม่หลังจาก; ซึ่งไม่จำเป็นและไม่นับรวมในขนาด

function P(A,W,H,h,w)
t=0:h*w-1;
ezplot(sprintf('+%d*x^%.0f*y^%d',[A(:)';t/h;rem(t,h)]),[W,H])

ความคืบหน้าการเล่นกอล์ฟเป็นข้อมูลโค้ดที่ขยายได้


ผลลัพธ์ของกรณีทดสอบ (คลิกเพื่อดูแบบเต็ม): กรณีทดสอบ


2
ทางออกที่ดีจริงๆใช้sprintf/ezplot!
ข้อบกพร่อง

การใช้fixแทนfloorอาจช่วยให้คุณมีจำนวนไบต์สองหลัก :-)
Luis Mendo

คุณสามารถใช้[h,w]=size(A);t=0:h*w-1;เพื่อบันทึกอีกสามไบต์!
ข้อบกพร่อง

@ LuisMendo จริงๆแล้วฉันทำได้ดีกว่า ฉันเสียใจที่ printf Matlab ไม่ได้มีตัวยึดจำนวนเต็ม %.0fแต่ก็ยังคงสนับสนุนสิ่งที่ต้องการ นั่นหมายความว่าฉันสามารถปูพื้นด้วยกันและปล่อยให้printfแก้ไข!
algmyr

@ flawr ฉันจะใช้ส่วนที่สองของการทำซ้ำในภายหลัง ฉันรู้ว่าการจัดรูปแบบของฉันกับรุ่นที่ดีที่สุดครั้งล่าสุดนั้นไม่ชัดเจนอย่างสมบูรณ์ การจัดรูปแบบที่แก้ไขเพื่อทำให้คริสตัลนี้ชัดเจน
algmyr

6

Python 2, 261 ไบต์

E=enumerate
M,[a,c],[b,d]=input()
e=(c-a)/199.
I=200
J=-int((b-d)/e-1)
print'P2',I,J,255
i=I*J
while i:i-=1;x,y=c-i%I*e,b+i/I*e;u,v,w=map(sum,zip(*((z*p/x,z*q/y,z)for q,R in E(M)for p,t in E(R)for z in[t*x**p*y**q])));print int(255*min(1,(w*w/(u*u+v*v))**.5/e))

รูปแบบอินพุต: matrix,xbounds,ybounds(เช่น[[-1,0,1],[0,0,0],[1,0,0]],[-2,2],[-2,2] ) รูปแบบการออก: PGM ธรรมดา

สิ่งนี้จะประมาณระยะทางจากจุดศูนย์กลางพิกเซลทุกจุดไปยังเส้นโค้งโดยใช้การประมาณลำดับแรกd ( x , y ) = | p ( x , y ) | / | ∇ P ( x , Y ) | ที่∇ พีคือการไล่ระดับสีของพหุนามP (นี่คือระยะทางจาก ( x , y ) ถึงจุดตัดของระนาบแทนเจนต์ที่ ( x , y , p ( x , y )) ด้วยxy –plane.) จากนั้นพิกเซลที่d (x , y ) มีความกว้างน้อยกว่าหนึ่งพิกเซลของเส้นโค้งตามสัดส่วนd ( x , y ) ส่งผลให้เส้นที่มีการลดรอยหยักนั้นดี (แม้ว่าจะไม่ใช่ข้อกำหนด)

เอาท์พุต

นี่คือกราฟเดียวกันกับฟังก์ชันระยะทางหารด้วย 16เพื่อให้มองเห็นได้


รอสักครู่แล้วรหัสพล็อตกราฟิกที่เกิดขึ้นจริงจะเกิดขึ้นที่ไหนในรหัส?
R. Kap

@ R.Kap รหัสเขียนภาพในรูปแบบ PGM ธรรมดาไปยัง stdout มีอยู่อย่างหนึ่งprintคำสั่งสำหรับส่วนหัวของภาพและหนึ่งชุดprintคำสั่งในwhileลูปสำหรับค่าของแต่ละพิกเซล
Anders Kaseorg

ว้าวนั่นเจ๋งจริงๆ! คุณจะช่วยให้ลึกลงไปอีกเล็กน้อยเกี่ยวกับอัลกอริทึมการวางแผน
ข้อบกพร่อง

@ flawr ฉันได้ขยายคำอธิบายเล็กน้อย; ที่ตอบคำถามของคุณ?
Anders Kaseorg

@AndersKaseorg ใช่ขอบคุณมาก!
ข้อผิดพลาด

5

Python 3.5 + MatPlotLib + Numpy, 352 ไบต์:

from matplotlib.pyplot import*;from numpy import*
def R(M,S,U,r=range):N=linspace;E='+'.join([str(y)+'*'+m for y,m in[q for i,g in zip(M,[[i+'*'+p for p in['1']+['x^%d'%p for p in r(1,len(M[0]))]]for i in['1']+['y^%d'%i for i in r(1,len(M))]])for q in zip(i,g)if q[0]]]);x,y=meshgrid(N(*S,200),N(*U,200));contour(x,y,eval(E.replace('^','**')),0);show()

ฟังก์ชั่นที่มีชื่อ ค่อนข้างนาน แต่เดี๋ยวก่อนฉันมีความสุขฉันสามารถทำงานให้สำเร็จได้ รับอินพุต 3 ค่าซึ่ง ได้แก่m by nเมทริกซ์, x-range และy-range ซึ่งทั้งหมดควรอยู่ในอาร์เรย์ (ตัวอย่างเช่น[[-1,0,1],[0,0,0],[1,0,0]],[-2,2],[-2,2]) แสดงกราฟที่เสร็จสมบูรณ์ในหน้าต่างแบบกราฟิกแบบโต้ตอบใหม่ จะลงสนามนี้มากขึ้นเมื่อฉันสามารถ แต่ตอนนี้ฉันมีความสุขกับมัน

ผลลัพธ์สุดท้ายสำหรับกรณีทดสอบ:

ผลลัพธ์สุดท้าย


5

MATL , 67 61 ไบต์

8Wt:qwq/t2:"wid*2M1)+i:q!^]!2&!w[1IK2]&!**ss&eZS5Y62&Y+|4=0YG

รหัสนี้ทำงานในรุ่น 18.5.0 ของภาษาซึ่งนำหน้าความท้าทาย อินพุตใช้จำเป็นm, nพารามิเตอร์ เมทริกซ์มีเครื่องหมายอัฒภาคเป็นตัวคั่นแถว รูปแบบการป้อนข้อมูลที่แน่นอน (ใช้พาราโบลาเป็นตัวอย่าง) คือ

[-1,3]
3  
[-2,2]
2
[0,-1; 0, 0; 1, 0]

รหัสสร้างภาพที่มีขนาด 255 × 255 นี้สามารถทดสอบโดยใช้@Suever 's MATL ออนไลน์คอมไพเลอร์ซึ่งในคุณสมบัติที่น่าสนใจมาก ๆ รวมถึงผลกราฟิก ดูตัวอย่าง

คอมไพเลอร์นี้ยังอยู่ในช่วงทดลอง กรุณารายงานปัญหาใด ๆ ต่อ @Suever ในเนต MATL หากปุ่ม "เรียกใช้" ไม่ทำงานให้ลองรีเฟรชหน้าและคลิกอีกครั้ง

หากคุณต้องการเอาต์พุต ASCIIต้องแก้ไขโค้ดเล็กน้อย (การเปลี่ยนแปลงจะส่งผลเฉพาะอักขระสองตัวแรกและตัวสุดท้ายสี่ตัวของรหัสด้านบน):

101t:qwq/t2:"wid*2M1)+i:q!^]!2&!w[1IK2]&!**ss&eZS5Y62&Y+|4<42*c

สิ่งนี้สร้างกริด ASCII ขนาด 100 × 100 ซึ่งใช้ตัวละคร*เพื่อแสดงเส้นโค้ง คุณสามารถทดสอบได้ด้วย@Dennis 'ลองออนไลน์! แพลตฟอร์ม:

โปรดทราบว่าอัตราส่วนภาพของเอาต์พุต ASCII นั้นเปลี่ยนแปลงเนื่องจากตัวอักษรนั้นสูงกว่าความกว้างเล็กน้อย

คำอธิบาย

รหัสจะคำนวณพหุนามแบบสองตัวแปรแรกในตารางx - y สิ่งนี้ใช้การกระจายเสียงอย่างหนักโดยคำนวณอาร์เรย์ 4D กลางซึ่งแต่ละมิติแสดงค่าx , ค่าy , xเลขชี้กำลัง, y exponentsตามลำดับ

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

8W      % Push 2^8, that is, 256. (The ASCII-output version pushes 101 instead)
t:q     % Duplicate. Push range [0 1 ... 255]
wq      % Swap. Subtract 1 to obtain 255
/       % Divide. Gives normalized range [0 1/255 2/255... 1]
t       % Duplicate
2:"     % For loop: do this twice
  w     %   Swap top two elements in the stack
  i     %   Input two-number array defining x range (resp. y in second iteration)
  d     %   Difference of the two entries
  *     %   Multiply by normalized range
  2M1)  %   Push the array again and get its first entry
  +     %   Add. This gives the range for x values (resp. y)
  i     %   Input m (n in second iteration)
  :q    %   Range [0 1 ...m-1] (resp. [0 1 ...n-1])
  !     %   Convert to column array
  ^     %   Power, element-wise with broadcast. This gives a matrix of size m×256
        %   (resp. n×256) of powers of x (resp. y) for the range of values computed
        %   previously
]       % End for loop
!       % Transpose. This transforms the n×256 matrix of powers of y into 256×n
2       % Push 2
&!      % Permute dimensions 1 and 3: transforms the 256×n matrix into a 4D array
        % of size 1×n×256×1
w       % Swap top two elements in the stack: bring 256×m matrix to top
[1IK2]  % Push vector [1 3 4 2]
&!      % Permute dimensions as indicated by the vector: transforms the m×256 matrix
        % into a 4D array of size m×1×1×256
*       % Multiply element-wise with broadcast: gives 4D array of size m×n×256×256
        % with mixed powers of x and y for at the grid of x, y values
*       % Implicitly input m×n matrix. Multiply element-wise with broadcast: gives
        % 4D array of size m×n×256×256
ss      % Sum along first two dimensions: gives 4D array of size 1×1×256×256
&e      % Squeeze singleton dimensions: gives matrix of size 256×256. This is the
        % two-variable polynomial evaluated at the x, y grid.
        % Now we need to find the zero level curve of this function. We do this by 
        % detecting when the sign of the function changes along any of the two axes
ZS      % Matrix of sign values (1, 0 or -1)
5Y6     % Predefined literal: matrix [1 1; 1 1]
2&Y+    % Compute 2D convolution, keeping only the valid (central) part
|4=     % True if absolute value of result is 4, which indicates no sign changes.
        % (The ASCII version computes a negated version of this, for better display)
0YG     % Display as image. (The ASCII-output version does the following instead:
        % multiply by 42 and convert to char. 42 is ASCII for '*', and character 0 
        % is shown as space. The 2D char array is then implicitly displayed)

กรณีทดสอบทั้งหมด

นี่คืออินพุตทั้งหมดในรูปแบบที่เหมาะสมในกรณีที่คุณต้องการลอง:

Circle:
[-2,2]
3
[-2,2]
3
[-1, 0, 1; 0, 0, 0; 1, 0, 0]

Ellipse:
[-2,2]
3
[-1,1]
3
[-1, 0, 1; 0, 0, 0; 2, 0, 0]

Cross:
[-1,2]
2
[-2,1]
2
[0, 0; 0, 1]

Parabola:
[-1,3]
3  
[-2,2]
2
[0,-1; 0, 0; 1, 0]

Elliptic Curve:
[-2,2]
3
[-3,3]
4
[-1, 1, 0,-1; 0, 0, 0, 0; 1, 0, 0, 0]

Folium of Descartes:
[-3,3]
4
[-3,3]
4
[0,  0,  0,  1; 0, -3,  0,  0; 0,  0,  0,  0; 1,  0,  0,  0]


Lemniscate:
[-2,2]
3
[-1,1]
5
[0,  0, -1,  0,  1; 0,  0,  0,  0,  0; 1,  0,  0,  0,  0]

Trifolium:
[-1,1]
5
[-1,1]
5
[0, 0, 0,-1, 1; 0, 0, 0, 0, 0; 0, 3, 2, 0, 0; 0, 0, 0, 0, 0; 1, 0, 0, 0, 0]

Astroid
[-1,1]
7
[-1,1]
7
[-1,  0,  3,  0, -3,  0,  1; 0,  0,  0,  0,  0,  0,  0; 3,  0, 21,  0,  3,  0,  0; 0,  0,  0,  0,  0,  0,  0; -3,  0,  3,  0,  0,  0,  0; 0,  0,  0,  0,  0,  0,  0; 1,  0,  0,  0,  0,  0,  0]

2
ยังอ่านได้ง่ายกว่า Perl เยี่ยมมากยังเป็นคอมไพเลอร์ออนไลน์อีกด้วย!
ข้อบกพร่อง

@flawr สามารถอ่านได้มากกว่า Perl LOL สำหรับคอมไพเลอร์ออนไลน์มันเป็นงานของ Suever!
Luis Mendo

1
@ flawr ตอนนี้ด้วย convolution!
Luis Mendo

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