代数曲線プロッター


14

代数曲線は{(x,y) in R^2 : f(x,y)=0 }、多項式のゼロのセットとして記述できる「2D平面」の特定の「1Dサブセット」ですf。ここでは、2D平面を実際の平面と見なし、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 デカルトの葉
  • 0 = x^4 - (x^2 - y^2) レムニスケート
  • 0 = (x^2 + y^2)^2 - (x^3 - 3xy^2) トリフォリウム
  • 0 = (x^2 + y^2 - 1)^3 + 27x^2y^2 アストロイド

仕事

多項式f(以下で定義)およびx / y範囲が与えられた場合、少なくとも100x100ピクセルの白黒画像を出力します。この画像は、白い背景に黒い線として曲線を示します。

詳細

:選択した他の2色を使用できます。区別するのは簡単です。

プロット:ピクセル画像の代わりに、この画像を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]

必要に応じて、マトリックスは正方であると想定できます(必要なゼロパディングで常に実行できます)。また、必要に応じて、マトリックスのサイズが追加の入力として与えられると想定することもできます。

以下では、上記の例は、このように定義されたマトリックスとして表されます。

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からいくつかの曲線のインスピレーションを得ました


エイリアシングを心配する必要はありません」ということは、各ピクセルの中心が線上にあるかどうかに応じて各ピクセルに色を付けることができるということですか?
ピーターテイラー

エイリアシングへの接続が表示されません。しかし、いや、異なる兆候の領域を区切る連続した線があるはずです。
flawr

行列はmx nではなく(m+1)x (n+1)です。入力として何を取りますか:m, nまたは m+1,n+1または選択できますか?
ルイスメンドー

グラフ化された関数を新しいウィンドウに表示できますか?
R.ガプス

1
@LuisMendoはい、軸は好きな方向にできます。(それらが直交している限り=)
flawr

回答:


10

Haskell、283 275バイト

関数gは、行列と2つの範囲を引数として呼び出してください。マトリックスはリストのリストであり、範囲はそれぞれ2要素のリストです。

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に縮小する必要があったことに注意してください(ハードコードされた102を小さい数字に変更するだけです)。また、y軸が下を向いていることに注意してください。


ここでできる小さなゴルフはいくつかあります。最後の行は$、バイトの保存に使用できる場合に括弧を使用しています。使用する場所は両方ともであるmap可能性があり(<$>)e一度使用するだけなので、その(0<)内部をプルできます。3バイトを節約するためeに名前(!)を付けることもできます。
ポストロックガーフハンター

zの定義に挿入すると、v4つの括弧(z(&)f g)を取り除くことができます。
ポストロックガーフハンター

また#、1文字(たとえばs)に名前を変更し、リストのパターンマッチをの代わりに使用することもできますg。(例s[a,b]=[a,a+(b-a)/102..b];g m u i=unlines$v[m!y<$>s u|y<-s i]
ポストロックガーフハンター

6

Matlab、114 100 92バイト

仕事に適したツールは?Matlabの興味深い方法を使用しprintfて、多項式を文字列として生成します。この多項式は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
flawr

fix代わりに使用するとfloor、2桁のバイトカウントに到達するのに役立ちます:-)
ルイスメンドー

[h,w]=size(A);t=0:h*w-1;別の3バイトを保存するためにも使用できます!
flawr

@LuisMendo実際、私はもっとうまくできる。Matlabのprintfに整数プレースホルダーがないのは残念でしたが、それでものようなものをサポートしています%.0f。それは私がフローリングを完全に落とし、それをprintf修理できるようにすることを意味する!
アルグミー

@flawr後半の繰り返しでは、その2番目の部分を使用します。最後の最良のバージョンでの書式設定は完全には明らかではなかったと思います。このクリスタルを明確にするためにフォーマットを編集しました。
アルグミー

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

これは、1次近似dxy)= | を使用して、すべてのピクセル中心から曲線までの距離を推定します。pxy)| / |∇ PXY)|、∇ pは多項式の勾配であるP。(これは、(xy)から(xypxy))での接平面とxy平面の交点までの距離です。)次に、dxy)は、dxy)に比例して曲線の1ピクセル幅未満であり、(それは必須ではありませんが)アンチエイリアス処理された良い線になります。

出力

これは、距離関数を16で割って表示する同じグラフです。


待ってください、実際のグラフィカルなプロットはコードのどこで行われますか?
R. Kap

@ R.Kapコードは、標準のPGM形式で画像をstdoutに書き込みます。print画像ヘッダー用のステートメントが1つと、各ピクセルの値用のループ内に1つのprintステートメントがありwhileます。
アンデルスカセオルグ16

うわー、それは本当にクールです!プロットアルゴリズムについてもう少し詳しく説明していただけますか?
-flawr

@flawr説明を少し拡張しました。それはあなたの質問に答えますか?
アンデルスカセオルグ16

@AndersKaseorgはい、ありがとうございました!
-flawr

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()

名前付き関数。かなり長いですが、ちょっと、タスクを達成できて本当にうれしいです。m by n行列、x-range、-rangeの3つの入力をy受け取ります。これらはすべて配列(たとえば、[[-1,0,1],[0,0,0],[1,0,0]],[-2,2],[-2,2])にある必要があります。完成したグラフを、新しいグラフィカルなインタラクティブウィンドウに出力します。私はできる限りこれをもっと時間をかけてゴルフしますが、今のところは満足しています。

テストケースの最終出力:

最終出力


5

MATL67 61バイト

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

このコードは、チャレンジの前のリリース18.5.0の言語で実行されます。入力オプションを使用してmnパラメータを。マトリックスには、行区切り記号としてセミコロンがあります。正確な入力形式(例として放物線を使用)は

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

コードは サイズが255×255の画像ます。これは@SueverMATLオンラインコンパイラを使用してテストできます。これには、他の非常に興味深い機能の中でも、グラフィカルな出力が含まれています。たとえば

このコンパイラはまだ実験段階です。MATLチャットルームで @Sueverに問題を報告してください。[実行]ボタンが機能しない場合は、ページを更新してもう一度クリックしてください。

ご希望の場合 ASCII出力、コードを少し変更する必要があります(変更は上記のコードの最初の2文字と最後の4文字にのみ影響します)。

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

これにより、文字*を使用して曲線を表す100×100 ASCIIグリッドが生成されます。@Dennisでこれをテストすることもできます ' オンラインで試してみてください!プラットホーム:

ASCII出力のアスペクト比は、文字が幅よりもわずかに高いため変更されることに注意してください。

説明

コードは、最初にx - yグリッドで2変数多項式を計算します。これはブロードキャストを多用し、各次元がx値、y値、x指数、yを表す中間4D配列を計算します指数をます。

その関数から、ゼロレベルラインが計算されます。チャレンジでは符号の変更のみを検出する必要があると指定されているため、コードは1の2×2ブロックで2D畳み込みを適用し、ブロックの4つの値が同じ符号を持たない場合、ピクセルを行に属するものとしてマークします。

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

@flawr はPerl LOL よりも読みやすくなっています。オンラインコンパイラについては、Sueverの仕事です!
ルイスメンドー

1
@flawr畳み込みができました!
ルイスメンドー

1
<3畳み込み!
-flawr
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.