面試
很久以前,我面試了很多圖形程式設計職位的候選人。 成為一名優秀的面試官是一項艱苦的工作;我早期的嘗試並不好。 隨著時間的推移,我想出了這個問題來開始對話。
我:如果同事來找你說“我需要畫一個圓圈”,你會怎麼做?
- 候選人 0:我不知道。
- 候選人1:我不知道。 指南針?
- 候選人 2:嗯嗯。 我會印一個小寫字母“o”。
- 候選人 3:平方根應該可以。
- 候選 4:正弦和餘弦應該可以。
- 候選 5:Bresenham 的圓繪製演算法應該可以做到。
- 候選人 6:我會告訴他們尋找庫函數,向他們展示文件的位置。 重用比發明更好。
- 候選人 7:我會說「我不知道。 為什麼要畫一個圓?因為也許他們並不真的需要畫一個。 也許他們需要用平方根知道圓內有什麼。 也許他們需要一個橢圓。 一旦我們確定確實需要繪製一個圓,那麼在哪裡繪製它? 它是填滿的、實心的還是有圖案的? 很可能已經有一個函數可以做到這一點,現在已經調試得很好。 您可能不需要自己編寫它,但如果您這樣做,請使用正弦和餘弦,並使步長大小成為半徑的函數。 需要多快? 根據設備的不同,Bresenham 可能比較適合。 在印表機上,小寫字母“o”可能適用於標記並且足夠好。
討論
候選人 0、1、2、3、4、5 都錯過了森林。 如果你是面試官,一定要幫助他們看到問題中的另一個人,因為那是問題的一半。 如果您是候選人,請注意兩部分問題。
如果你是面試者,永遠不要像 0 號候選人那樣停止。 候選人 1 和 2 為面試官提出另一個問題提供了足夠的機會。 如果您是面試官,請記住,候選人正處於壓力之中,需要一些幫助來了解更多細節。
候選人 3、4 和 5 各自提出了一個技術解決方案,其中任何一個都可能有效,但沒有一個總是最好的。 如果您是候選人,請繼續談論您的答案。 如果你是面試官,指導他們:“那會(快速、安全、正確等)嗎?”
候選者 6 和候選者 7 在實用尺度上處於不同的位置。 需要更多的問題和討論來確定最合適的方案。
答案
面試問題實際上與畫圓無關,但如果這就是您仍在閱讀的原因,這裡有 JSL 的答案 2、3、4、5、6。
小寫字母 o,三種方式
New Window( "Candidate 2, literal",
Graph Box(
xaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
yaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
Text( Center Justified, {50, 50}, "o" ) // "o" sits above the point
)
);
Text sits above the baseline.Text sits above the baseline.Text sits above the baseline.Text sits above the baseline.Text sits above the baseline.文字位於基線上方。
New Window( "Candidate 2, modified",
Graph Box(
xaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
yaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
markersize(10),
marker( markerstate("O"), {50, 50}) // capital "O" is somewhat centered
)
);
Using a marker with a capital O.Using a marker with a capital O.Using a marker with a capital O.Using a marker with a capital O.Using a marker with a capital O.使用帶有大寫 O 的標記。
New Window( "Candidate 2, reinvented",
Graph Box(
xaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
yaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
Marker Size( 100 ),
Marker( Marker State( 8 ), {50, 50} ) // bigger is thicker
)
);
If you can use a marker, then you can pick the circle symbol.If you can use a marker, then you can pick the circle symbol.If you can use a marker, then you can pick the circle symbol.If you can use a marker, then you can pick the circle symbol.If you can use a marker, then you can pick the circle symbol.如果您可以使用標記,那麼您可以選擇圓形符號。
平方根,兩種方式
New Window( "Candidate 3, sqrt hard way",
Graph Box(
framesize( 300, 300 ),
xaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
yaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
// draw a circle at 50,50 with radius 30 using sqrt
// a lot of code, and not too pretty on the left and right
step=3; // to make the problem more obvious, use 1 to almost hide it
For( x = 0, x < 30, x += step,
// hyp = sqrt(x^2 + y^2)
// hyp^2 = x^2 + y^2
// hyp^2 - x^2 = y^2
y1 = Sqrt( 30 ^ 2 - x ^ 2 );
y2 = Sqrt( 30 ^ 2 - (x + step) ^ 2 );
// do all four quadrants in parallel
Line( {50 + x, 50 + y1}, {50 + (x + step), 50 + y2} );
Line( {50 - x, 50 + y1}, {50 - (x + step), 50 + y2} );
Line( {50 - x, 50 - y1}, {50 - (x + step), 50 - y2} );
Line( {50 + x, 50 - y1}, {50 + (x + step), 50 - y2} );
)
)
);
The sqrt approach looks rough on the left and right because of the equal-sized steps in x.The sqrt approach looks rough on the left and right because of the equal-sized steps in x.The sqrt approach looks rough on the left and right because of the equal-sized steps in x.The sqrt approach looks rough on the left and right because of the equal-sized steps in x.The sqrt approach looks rough on the left and right because of the equal-sized steps in x.sqrt 方法在左側和右側看起來很粗糙,因為 x 中的步長大小相等。
New Window( "Candidate 3, sqrt with YFunction",
Graph Box(
framesize( 300, 300 ),
xaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
yaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
// draw a circle at 50,50 with radius 30 using sqrt
// sqrt has two answers. Looks nice, thanks YFunction. Only a small gap.
Y Function( 50 + Sqrt( 30 ^ 2 - (x - 50) ^ 2 ), x );// top
Y Function( 50 - Sqrt( 30 ^ 2 - (x - 50) ^ 2 ), x );// bottom
)
);
The Y Function adjusts the x step size automatically.The Y Function adjusts the x step size automatically.The Y Function adjusts the x step size automatically.The Y Function adjusts the x step size automatically.The Y Function adjusts the x step size automatically.Y 函數自動調整 x 步長。
正弦和餘弦
New Window( "Candidate 4, sin/cos with XYFunction",
Graph Box(
framesize( 300, 300 ),
xaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
yaxis( Add Ref Line( 50, "Solid", "Black", "", 1 ) ),
// draw a circle at 50,50 with radius 30 using sin/cos
XY Function( 50 + 30 * Cos( t ), 50 + 30 * Sin( t ), t, Min( 0 ), Max( 2 * Pi() ) )
)
);
I really like the XYFunction for this parametric description of a circle.I really like the XYFunction for this parametric description of a circle.I really like the XYFunction for this parametric description of a circle.I really like the XYFunction for this parametric description of a circle.I really like the XYFunction for this parametric description of a circle.我真的很喜歡 XYFunction 對圓的參數化描述。
布雷森納姆
//Bresenham.
// using pixel functions (There is no reason I can think of to
// use this code; everything else will be faster! A long time
// ago there was no floating point arithmetic or sin/cos/sqrt
// and tricks like this were useful.)
drawCircle = Function( {xc, yc, x, y}, // not really pixels. this is not a good match for JMP!
Marker( Marker State( 0 ), {xc + x, yc + y} ); // invented for primitive hardware without
Marker( Marker State( 0 ), {xc - x, yc + y} ); // floating point.
Marker( Marker State( 0 ), {xc + x, yc - y} );
Marker( Marker State( 0 ), {xc - x, yc - y} );
Marker( Marker State( 0 ), {xc + y, yc + x} );
Marker( Marker State( 0 ), {xc - y, yc + x} );
Marker( Marker State( 0 ), {xc + y, yc - x} );
Marker( Marker State( 0 ), {xc - y, yc - x} );
);
circleBres = Function( {xc, yc, r}, // https://www.geeksforgeeks.org/bresenhams-circle-drawing-algorithm/
x = 0;
y = r;
d = 3 - 2 * r;
drawCircle( xc, yc, x, y );
While( y >= x,
x++;
If( d > 0,
y--;
d = d + 4 * (x - y) + 10;
,
d = d + 4 * x + 6
);
drawCircle( xc, yc, x, y );
);
);
New Window( "Candidate 5, really hard way using pixels",
Graph Box(
framesize( 900, 900 ),xscale(0,1000),yscale(0,1000),
xaxis( Add Ref Line( 500, "Solid", "Black", "", 1 ) ),
yaxis( Add Ref Line( 500, "Solid", "Black", "", 1 ) ),
// draw a circle at 500,500 with radius 300
circleBres( 500, 500, 300 ),
text({300,700},"Zoom in for detail")
)
);
The point of the Bresenham circle drawing algorithm is to only use integers and avoid multiply and divide ( *2 and *4 can be shift operations.)The point of the Bresenham circle drawing algorithm is to only use integers and avoid multiply and divide ( *2 and *4 can be shift operations.)The point of the Bresenham circle drawing algorithm is to only use integers and avoid multiply and divide ( *2 and *4 can be shift operations.)The point of the Bresenham circle drawing algorithm is to only use integers and avoid multiply and divide ( *2 and *4 can be shift operations.)The point of the Bresenham circle drawing algorithm is to only use integers and avoid multiply and divide ( *2 and *4 can be shift operations.)Bresenham 圓繪製演算法的要點是只使用整數並避免乘法和除法(*2 和 *4 可以是移位運算。)
Zoomed in the pixels always step in either x or y or both.Zoomed in the pixels always step in either x or y or both.Zoomed in the pixels always step in either x or y or both.Zoomed in the pixels always step in either x or y or both.Zoomed in the pixels always step in either x or y or both.放大像素始終步進 x 或 y 或兩者。
函式庫函數
New Window( "Candidate 6, Circle Function",
Graph Box(
xaxis( Show Major Grid( 1 ) ),
yaxis( Show Major Grid( 1 ) ),
Circle( {50, 50}, 30 )
)
);
The Circle Function uses the Y dimension and makes a visibly round circle. Because the axes are not isometric, something seems odd.The Circle Function uses the Y dimension and makes a visibly round circle. Because the axes are not isometric, something seems odd.The Circle Function uses the Y dimension and makes a visibly round circle. Because the axes are not isometric, something seems odd.The Circle Function uses the Y dimension and makes a visibly round circle. Because the axes are not isometric, something seems odd.The Circle Function uses the Y dimension and makes a visibly round circle. Because the axes are not isometric, something seems odd.圓形函數使用 Y 維度並形成一個明顯的圓形。 因為軸不是等軸測的,所以有些東西看起來很奇怪。
New Window( "Candidate 6, Circle on square paper",
Graph Box( framesize(400,400),
xaxis( Show Major Grid( 1 ) ),
yaxis( Show Major Grid( 1 ) ),
Circle( {50, 50}, 30 )
)
);
The graph's popup menu, Size/Scale->SizeToIsometric will automatically make this adjustment.The graph's popup menu, Size/Scale->SizeToIsometric will automatically make this adjustment.The graph's popup menu, Size/Scale->SizeToIsometric will automatically make this adjustment.The graph's popup menu, Size/Scale->SizeToIsometric will automatically make this adjustment.The graph's popup menu, Size/Scale->SizeToIsometric will automatically make this adjustment.圖形的彈出式選單“大小/比例”->“大小到等距”將自動進行此調整。
您可能更喜歡橢圓函數:
New Window( "Candidate 6, Oval function",
Graph Box( // framesize(600,400),
x=50;
y=50;
r=30;
Oval( x-r, y-r, x+r, y+r );
)
);
The Oval function has a clear API for the vertical and horizontal dimensions.The Oval function has a clear API for the vertical and horizontal dimensions.The Oval function has a clear API for the vertical and horizontal dimensions.The Oval function has a clear API for the vertical and horizontal dimensions.The Oval function has a clear API for the vertical and horizontal dimensions.Oval 函數對於垂直和水平尺寸有明確的 API。
液壓系統
I traced a DVD; the cyborg hand is really teaching about hydraulics and levers and putting pieces together.I traced a DVD; the cyborg hand is really teaching about hydraulics and levers and putting pieces together.I traced a DVD; the cyborg hand is really teaching about hydraulics and levers and putting pieces together.I traced a DVD; the cyborg hand is really teaching about hydraulics and levers and putting pieces together.I traced a DVD; the cyborg hand is really teaching about hydraulics and levers and putting pieces together.我追蹤了一張 DVD;機器人手實際上是在教授液壓系統和槓桿以及將零件組裝在一起。
我花了一月和二月幫助一個五歲的孩子組裝這個巨型機器人手。 我建議七歲作為合理的最低年齡(盒子也是如此);我們每隔一天左右進行一次 10 到 15 分鐘的課程。 大約 30 美元的價格非常超值。 最精彩的部分:有一天,5歲的孩子在回家的路上發現了一台挖土機,並告訴我有關液壓缸的資訊。
Huge! Actually too big for a five year old.Huge! Actually too big for a five year old.Huge! Actually too big for a five year old.Huge! Actually too big for a five year old.Huge! Actually too big for a five year old.巨大的! 對於五歲的孩子來說實際上太大了。