Colloquio
Molto tempo fa ho intervistato molti candidati per molte posizioni di programmazione grafica. Essere un buon intervistatore è un duro lavoro; i miei primi tentativi non sono stati eccezionali. Nel corso del tempo mi è venuta in mente questa domanda per avviare una conversazione.
Io: Cosa fai se un collega viene da te e ti dice "Devo disegnare un cerchio?"
- Candidato 0: Non lo so.
- Candidato 1: Non lo so. Una bussola?
- Candidato 2: Hmmmm. Stamperei una piccola lettera "o".
- Candidato 3: La radice quadrata dovrebbe farlo.
- Candidato 4: Seni e coseni dovrebbero farlo.
- Candidato 5: L'algoritmo di disegno del cerchio di Bresenham dovrebbe farlo.
- Candidato 6: Direi loro di cercare una funzione di biblioteca, di mostrare loro dove si trova la documentazione. Meglio riutilizzare che inventare.
- Candidato 7: Direi "Non lo so. Perché vuoi disegnare un cerchio?" perché forse non hanno davvero bisogno di disegnarne uno. Forse hanno bisogno di sapere cosa c'è all'interno del cerchio usando la radice quadrata. Forse hanno bisogno di un'ellisse. Una volta deciso che un cerchio disegnato è davvero necessario, dove viene disegnato? Sarà pieno, solido o con un motivo? È probabile che esista già una funzione per farlo e che ormai sia ben eseguito il debug. Probabilmente non è necessario scriverlo tu, ma se lo fai, usa seni e coseni e rendi la dimensione del passo una funzione del raggio. Quanto deve essere veloce? A seconda del dispositivo, Bresenham potrebbe essere appropriato. Su una stampante, una piccola lettera "o" potrebbe funzionare come pennarello ed essere sufficiente.
Discussione
I candidati 0,1,2,3,4,5 hanno tutti mancato la foresta. Se sei l'intervistatore, assicurati di aiutarlo a vedere l'altra persona nella domanda, perché quella è metà della domanda. E se sei il candidato, fai attenzione alle domande in due parti.
Se sei l'intervistato, non fermarti mai dove ha fatto il candidato 0. I candidati 1 e 2 forniscono all'intervistatore un gancio sufficiente per porre un'altra domanda. Se sei l'intervistatore, ricorda che il candidato si trova in una situazione stressante e ha bisogno di un po' di aiuto per sbloccare maggiori dettagli.
I candidati 3, 4 e 5 suggeriscono ciascuno una soluzione tecnica, ognuna delle quali potrebbe funzionare, nessuna delle quali è sempre la migliore. Se sei tu il candidato, continua a parlare della tua risposta. Se sei l'intervistatore, istruiscilo: "sarà (veloce, sicuro, corretto, ecc.)?"
I candidati 6 e 7 si collocano in posizioni diverse sulla scala pragmatica. Sono necessarie ulteriori domande e discussioni per determinare la soluzione migliore.
Risposte
La domanda dell'intervista non riguarda molto il disegno di un cerchio, ma se è questo il motivo per cui stai ancora leggendo, ecco JSL per le risposte 2,3,4,5,6.
O minuscola, tre direzioni
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.Il testo si trova sopra la linea di base.
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.Utilizzando un pennarello con la O maiuscola.
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.Se puoi usare un pennarello, puoi scegliere il simbolo del cerchio.
Radice quadrata, due modi
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.L'approccio sqrt sembra approssimativo a sinistra e a destra a causa dei passaggi di uguali dimensioni in 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.La funzione Y regola automaticamente la dimensione del passo x.
Seni e coseni
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.Mi piace molto la funzione XY per questa descrizione parametrica di un cerchio.
Bresenham
//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.)Lo scopo dell'algoritmo di disegno del cerchio di Bresenham è utilizzare solo numeri interi ed evitare moltiplicazioni e divisioni (*2 e *4 possono essere operazioni di spostamento).
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.Ingranditi i pixel passano sempre in xo y o in entrambi.
Funzioni della libreria
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.La funzione Cerchio utilizza la dimensione Y e crea un cerchio visibilmente rotondo. Poiché gli assi non sono isometrici, qualcosa sembra strano.
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.Il menu a comparsa del grafico, Dimensioni/Scala->DimensioneIsometrica, effettuerà automaticamente questa regolazione.
Potresti preferire la funzione ovale:
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.La funzione Ovale ha un'API chiara per le dimensioni verticale e orizzontale.
Idraulica
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.Ho rintracciato un DVD; la mano del cyborg insegna davvero l'idraulica, le leve e il mettere insieme i pezzi.
Ho passato gennaio e febbraio ad aiutare un bambino di cinque anni ad assemblare questa mega mano cyborg. Consiglierei sette anni come età minima ragionevole (come fa la scatola); facevamo sessioni da 10 a 15 minuti a giorni alterni circa. È un valore incredibile per circa $ 30. La parte migliore: tornando a casa l'altro giorno, il 5enne vede un escavatore e mi parla dei cilindri idraulici.
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.Enorme! In realtà troppo grande per un bambino di cinque anni.