회견
오래 전에 나는 많은 그래픽 프로그래밍 직책에 대해 많은 후보자들을 인터뷰했습니다. 좋은 면접관이 되는 것은 힘든 일입니다. 나의 초기 시도는 좋지 않았습니다. 시간이 지나면서 나는 대화를 시작하기 위해 이 질문을 떠올렸습니다.
나: 직장 동료가 와서 "원을 하나 그려야겠어"라고 하면 어떻게 하시나요?
- 후보자 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.텍스트는 기준선 위에 위치합니다.
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.대문자 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.마커를 사용할 수 있으면 원 기호를 선택할 수 있습니다.
제곱근, 두 가지 방법
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.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.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.저는 원에 대한 파라메트릭 설명을 위한 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.)Bresenham 원 그리기 알고리즘의 요점은 정수만 사용하고 곱셈과 나눗셈을 피하는 것입니다( *2 및 *4는 시프트 연산이 가능함).
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.Circle 함수는 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.그래프의 팝업 메뉴인 Size/Scale->SizeToIsometric은 자동으로 이 조정을 수행합니다.
타원형 기능을 선호할 수도 있습니다.
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.Oval 함수에는 수직 및 수평 치수에 대한 명확한 API가 있습니다.
유압장치
I traced a DVD; the cyborg hand is really teaching about hydraulics and levers and putting pieces together.나는 DVD를 추적했습니다. 사이보그 손은 실제로 유압 장치와 레버를 가르치고 부품을 조립하는 역할을 합니다.
저는 1월과 2월에 5살짜리 아이가 메가 사이보그 손을 조립하는 것을 도왔습니다. 나는 합리적인 최소 연령으로 7세를 추천하고 싶습니다(상자도 마찬가지입니다). 우리는 격일로 10~15분씩 세션을 진행했습니다. 약 30달러에 달하는 놀라운 가격입니다. 가장 좋은 점은 일전에 집으로 걸어가던 중 5yo가 굴착기를 발견하고 유압 실린더에 대해 알려준다는 것입니다.
Huge! Actually too big for a five year old.거대한! 사실 5세 아이에게는 너무 크네요.