A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 49KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang=fr>
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset=utf-8>
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Interviewing for a JavaScript Job (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="http://raganwald.com/2015/02/21/interviewing-for-a-front-end-job.html">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. Interviewing for a JavaScript Job (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="http://raganwald.com/2015/02/21/interviewing-for-a-front-end-job.html">Source originale du contenu</a></h3>
  445. <p>“The Carpenter” was a JavaScript programmer, well-known for a meticulous attention to detail and love for hand-crafted, exquisitely joined code. The Carpenter normally worked through personal referrals, but from time to time a recruiter would slip through his screen. One such recruiter was Bob Plissken. Bob was well-known in the Python community, but his clients often needed experience with other languages.</p>
  446. <p>Plissken lined up a technical interview with a well-funded startup in San Francisco. The Carpenter arrived early for his meeting with “Thing Software,” and was shown to conference room 13. A few minutes later, he was joined by one of the company’s developers, Christine.</p>
  447. <h3 id="the-problem">the problem</h3>
  448. <p>After some small talk, Christine explained that they liked to ask candidates to whiteboard some code. Despite his experience and industry longevity, the Carpenter did not mind being asked to demonstrate that he was, in fact, the person described on the resumé.</p>
  449. <p>Many companies use white-boarding code as an excuse to have a technical conversation with a candidate, and The Carpenter felt that being asked to whiteboard code was an excuse to have a technical conversation with a future colleague. “Win, win” he thought to himself.</p>
  450. <p><a href="https://www.flickr.com/photos/stigrudeholm/6710684795"><img src="/assets/images/chessboard.jpg" alt="Chessboard"/></a></p>
  451. <p>Christine intoned the question, as if by rote:</p>
  452. <blockquote>
  453. <p>Consider a finite checkerboard of unknown size. On each square, we randomly place an arrow pointing to one of its four sides. A chequer is placed randomly on the checkerboard. Each move consists of moving the chequer one square in the direction of the arrow in the square it occupies. If the arrow should cause the chequer to move off the edge of the board, the game halts.</p>
  454. </blockquote>
  455. <blockquote>
  456. <p>The problem is this: The game board is hidden from us. A player moves the chequer, following the rules. As the player moves the chequer, they calls out the direction of movement, e.g. “↑, →, ↑, ↓, ↑, →…” Write an algorithm that will determine whether the game halts, strictly from the called out directions, in finite time and space.</p>
  457. </blockquote>
  458. <p>“So,” The Carpenter asked, “I am to write an algorithm that takes a possibly infinite stream of…”</p>
  459. <p>Christine interrupted. “To save time, we have written a template of the solution for you in ECMASCript 2015 notation. Fill in the blanks. Your code should not presume anything about the gameboard’s size or contents, only that it is given an arrow every time though the while loop. You may use <a href="http://babeljs.io">babeljs.io</a>, or <a href="http://www.es6fiddle.net">ES6Fiddle</a> to check your work. “</p>
  460. <p>Christine quickly scribbled on the whiteboard:</p>
  461. <div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kr">const</span> <span class="nx">Game</span> <span class="o">=</span> <span class="p">(</span><span class="nx">size</span> <span class="o">=</span> <span class="mi">8</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  462. <span class="c1">// initialize the board</span>
  463. <span class="kr">const</span> <span class="nx">board</span> <span class="o">=</span> <span class="p">[];</span>
  464. <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">size</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
  465. <span class="nx">board</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">[];</span>
  466. <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o">&lt;</span> <span class="nx">size</span><span class="p">;</span> <span class="o">++</span><span class="nx">j</span><span class="p">)</span> <span class="p">{</span>
  467. <span class="nx">board</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'←→↓↑'</span><span class="p">[</span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)];</span>
  468. <span class="p">}</span>
  469. <span class="p">}</span>
  470. <span class="c1">// initialize the position</span>
  471. <span class="kd">let</span> <span class="nx">initialPosition</span> <span class="o">=</span> <span class="p">[</span>
  472. <span class="mi">2</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="p">(</span><span class="nx">size</span> <span class="o">-</span> <span class="mi">4</span><span class="p">)),</span>
  473. <span class="mi">2</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="p">(</span><span class="nx">size</span> <span class="o">-</span> <span class="mi">4</span><span class="p">))</span>
  474. <span class="p">];</span>
  475. <span class="c1">// ???</span>
  476. <span class="kd">let</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">]</span> <span class="o">=</span> <span class="nx">initialPosition</span><span class="p">;</span>
  477. <span class="kr">const</span> <span class="nx">MOVE</span> <span class="o">=</span> <span class="p">{</span>
  478. <span class="s2">"←"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">y</span><span class="p">],</span>
  479. <span class="s2">"→"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">y</span><span class="p">],</span>
  480. <span class="s2">"↓"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span>
  481. <span class="s2">"↑"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
  482. <span class="p">};</span>
  483. <span class="k">while</span> <span class="p">(</span><span class="nx">x</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nx">y</span> <span class="o">&gt;=</span><span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nx">x</span> <span class="o">&lt;</span> <span class="nx">size</span> <span class="o">&amp;&amp;</span> <span class="nx">y</span> <span class="o">&lt;</span> <span class="nx">size</span><span class="p">)</span> <span class="p">{</span>
  484. <span class="kr">const</span> <span class="nx">arrow</span> <span class="o">=</span> <span class="nx">board</span><span class="p">[</span><span class="nx">x</span><span class="p">][</span><span class="nx">y</span><span class="p">];</span>
  485. <span class="c1">// ???</span>
  486. <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">]</span> <span class="o">=</span> <span class="nx">MOVE</span><span class="p">[</span><span class="nx">arrow</span><span class="p">]([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">]);</span>
  487. <span class="p">}</span>
  488. <span class="c1">// ???</span>
  489. <span class="p">};</span></code></pre></div>
  490. <p>“What,” Christine asked, “Do you write in place of the three <code>// ???</code> placeholders to determine whether the game halts?”</p>
  491. <h3 id="the-carpenters-solution">the carpenter’s solution</h3>
  492. <p>The Carpenter was not surprised at the problem. Bob Plissken was a crafty, almost reptilian recruiter that traded in information and secrets. Whenever Bob sent a candidate to a job interview, he debriefed them afterwards and got them to disclose what questions were asked in the interview. He then coached subsequent candidates to give polished answers to the company’s pet technical questions.</p>
  493. <p>And just as companies often pick a problem that gives them broad latitude for discussing alternate approaches and determining that depth of a candidate’s experience, The Carpenter liked to sketch out solutions that provided an opportunity to judge the interviewer’s experience and provide an easy excuse to discuss the company’s approach to software design.</p>
  494. <p>Bob had, in fact, warned The Carpenter that “Thing” liked to ask either or both of two questions: Determine how to detect a loop in a linked list, and determine whether the chequerboard game would halt. To save time, The Carpenter had prepared the same answer for both questions.</p>
  495. <p>The Carpenter coughed softly, then began. “To begin with, I’ll transform a game into an iterable that generates arrows, using the ‘Starman’ notation for generators.”</p>
  496. <p>“I will add just five lines of code the <code>Game</code> function, and two of those are closing braces:”</p>
  497. <div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="k">return</span> <span class="p">({</span>
  498. <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">iterator</span><span class="p">]</span><span class="o">:</span> <span class="kd">function</span><span class="o">*</span> <span class="p">()</span> <span class="p">{</span></code></pre></div>
  499. <p>And:</p>
  500. <p>And:</p>
  501. <p>“The finished function reads:”</p>
  502. <div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kr">const</span> <span class="nx">Game</span> <span class="o">=</span> <span class="p">(</span><span class="nx">size</span> <span class="o">=</span> <span class="mi">8</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  503. <span class="c1">// initialize the board</span>
  504. <span class="kr">const</span> <span class="nx">board</span> <span class="o">=</span> <span class="p">[];</span>
  505. <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">size</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
  506. <span class="nx">board</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">[];</span>
  507. <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o">&lt;</span> <span class="nx">size</span><span class="p">;</span> <span class="o">++</span><span class="nx">j</span><span class="p">)</span> <span class="p">{</span>
  508. <span class="nx">board</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="nx">j</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'←→↓↑'</span><span class="p">[</span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)];</span>
  509. <span class="p">}</span>
  510. <span class="p">}</span>
  511. <span class="c1">// initialize the position</span>
  512. <span class="kd">let</span> <span class="nx">initialPosition</span> <span class="o">=</span> <span class="p">[</span>
  513. <span class="mi">2</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="p">(</span><span class="nx">size</span> <span class="o">-</span> <span class="mi">4</span><span class="p">)),</span>
  514. <span class="mi">2</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="p">(</span><span class="nx">size</span> <span class="o">-</span> <span class="mi">4</span><span class="p">))</span>
  515. <span class="p">];</span>
  516. <span class="k">return</span> <span class="p">({</span>
  517. <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">iterator</span><span class="p">]</span><span class="o">:</span> <span class="kd">function</span><span class="o">*</span> <span class="p">()</span> <span class="p">{</span>
  518. <span class="kd">let</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">]</span> <span class="o">=</span> <span class="nx">initialPosition</span><span class="p">;</span>
  519. <span class="kr">const</span> <span class="nx">MOVE</span> <span class="o">=</span> <span class="p">{</span>
  520. <span class="s2">"←"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">y</span><span class="p">],</span>
  521. <span class="s2">"→"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">y</span><span class="p">],</span>
  522. <span class="s2">"↓"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span>
  523. <span class="s2">"↑"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
  524. <span class="p">};</span>
  525. <span class="k">while</span> <span class="p">(</span><span class="nx">x</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nx">y</span> <span class="o">&gt;=</span><span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nx">x</span> <span class="o">&lt;</span> <span class="nx">size</span> <span class="o">&amp;&amp;</span> <span class="nx">y</span> <span class="o">&lt;</span> <span class="nx">size</span><span class="p">)</span> <span class="p">{</span>
  526. <span class="kr">const</span> <span class="nx">arrow</span> <span class="o">=</span> <span class="nx">board</span><span class="p">[</span><span class="nx">x</span><span class="p">][</span><span class="nx">y</span><span class="p">];</span>
  527. <span class="k">yield</span> <span class="nx">arrow</span><span class="p">;</span>
  528. <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">]</span> <span class="o">=</span> <span class="nx">MOVE</span><span class="p">[</span><span class="nx">arrow</span><span class="p">]([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">]);</span>
  529. <span class="p">}</span>
  530. <span class="p">}</span>
  531. <span class="p">});</span>
  532. <span class="p">};</span></code></pre></div>
  533. <p>“Now that we have an iterable, we can transform the iterable of arrows into an iterable of positions.” The Carpenter sketched quickly. “We’ll need some common utilities. You’ll find equivalents in a number of JavaScript libraries, but I’ll quote those given in <a href="https://leanpub.com/javascriptallongesix">JavaScript Allongé</a>:”</p>
  534. <p>“For starters, <code>takeIterable</code> transforms an iterable into one that yields at most a fixed number of elements. It’s handy for debugging. We’ll use it to check that our <code>Game</code> is working as an iterable:”</p>
  535. <div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kr">const</span> <span class="nx">takeIterable</span> <span class="o">=</span> <span class="p">(</span><span class="nx">numberToTake</span><span class="p">,</span> <span class="nx">iterable</span><span class="p">)</span> <span class="o">=&gt;</span>
  536. <span class="p">({</span>
  537. <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">iterator</span><span class="p">]</span><span class="o">:</span> <span class="kd">function</span><span class="o">*</span> <span class="p">()</span> <span class="p">{</span>
  538. <span class="kd">let</span> <span class="nx">remainingElements</span> <span class="o">=</span> <span class="nx">numberToTake</span><span class="p">;</span>
  539. <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">element</span> <span class="nx">of</span> <span class="nx">iterable</span><span class="p">)</span> <span class="p">{</span>
  540. <span class="k">if</span> <span class="p">(</span><span class="nx">remainingElements</span><span class="o">--</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
  541. <span class="k">yield</span> <span class="nx">element</span><span class="p">;</span>
  542. <span class="p">}</span>
  543. <span class="p">}</span>
  544. <span class="p">});</span></code></pre></div>
  545. <p>“This doesn’t actually end up in our solution, it’s just to check our work as we go along. And you can find it in libraries, it’s not something we need to reinvent whenever we work with iterables.”</p>
  546. <p>“But now to the business. We want to take the arrows and convert them to positions. For that, we’ll map the Game iterable to positions. A <code>statefulMap</code> is a lazy map that preserves state from iteration to iteration. That’s what we need, because we need to know the current position to map each move to the next position.”</p>
  547. <p>“Again, this is a standard idiom we can obtain from libraries, we don’t reinvent the wheel. I’ll show it here for clarity:”</p>
  548. <div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kr">const</span> <span class="nx">statefulMapIterableWith</span> <span class="o">=</span> <span class="p">(</span><span class="nx">fn</span><span class="p">,</span> <span class="nx">seed</span><span class="p">,</span> <span class="nx">iterable</span><span class="p">)</span> <span class="o">=&gt;</span>
  549. <span class="p">({</span>
  550. <span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">iterator</span><span class="p">]</span><span class="o">:</span> <span class="kd">function</span><span class="o">*</span> <span class="p">()</span> <span class="p">{</span>
  551. <span class="kd">let</span> <span class="nx">value</span><span class="p">,</span>
  552. <span class="nx">state</span> <span class="o">=</span> <span class="nx">seed</span><span class="p">;</span>
  553. <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">element</span> <span class="nx">of</span> <span class="nx">iterable</span><span class="p">)</span> <span class="p">{</span>
  554. <span class="p">[</span><span class="nx">state</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span> <span class="o">=</span> <span class="nx">fn</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">element</span><span class="p">);</span>
  555. <span class="k">yield</span> <span class="nx">value</span><span class="p">;</span>
  556. <span class="p">}</span>
  557. <span class="p">}</span>
  558. <span class="p">});</span></code></pre></div>
  559. <p>“Armed with this, it’s straightforward to map an iterable of directions to an iterable of strings representing positions:”</p>
  560. <div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kr">const</span> <span class="nx">positionsOf</span> <span class="o">=</span> <span class="p">(</span><span class="nx">game</span><span class="p">)</span> <span class="o">=&gt;</span>
  561. <span class="nx">statefulMapIterableWith</span><span class="p">(</span>
  562. <span class="p">(</span><span class="nx">position</span><span class="p">,</span> <span class="nx">direction</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  563. <span class="kr">const</span> <span class="nx">MOVE</span> <span class="o">=</span> <span class="p">{</span>
  564. <span class="s2">"←"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">y</span><span class="p">],</span>
  565. <span class="s2">"→"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">y</span><span class="p">],</span>
  566. <span class="s2">"↓"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span>
  567. <span class="s2">"↑"</span><span class="o">:</span> <span class="p">([</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
  568. <span class="p">};</span>
  569. <span class="kr">const</span> <span class="p">[</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">]</span> <span class="o">=</span> <span class="nx">MOVE</span><span class="p">[</span><span class="nx">direction</span><span class="p">](</span><span class="nx">position</span><span class="p">);</span>
  570. <span class="k">return</span> <span class="p">[</span><span class="nx">position</span><span class="p">,</span> <span class="err">`</span><span class="nx">x</span><span class="o">:</span> <span class="nx">$</span><span class="p">{</span><span class="nx">x</span><span class="p">},</span> <span class="nx">y</span><span class="o">:</span> <span class="nx">$</span><span class="p">{</span><span class="nx">y</span><span class="p">}</span><span class="err">`</span><span class="p">];</span>
  571. <span class="p">},</span>
  572. <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
  573. <span class="nx">game</span><span class="p">);</span></code></pre></div>
  574. <p>The Carpenter reflected. “Having turned our game loop into an iterable, we can now see that our problem of whether the game terminates is isomorphic to the problem of detecting whether the positions given ever repeat themselves: If the chequer ever returns to a position it has previously visited, it will cycle endlessly.”</p>
  575. <p>“We could draw positions as nodes in a graph, connected by arcs representing the arrows. Detecting whether the game terminates is equivalent to detecting whether the graph contains a cycle.”</p>
  576. <p><img src="/assets/images/cycle.png" alt="Cycle Detection"/></p>
  577. <p>“There’s an old joke that a mathematician is someone who will take a five-minute problem, then spend an hour proving it is equivalent to another problem they have already solved. I approached this question in that spirit. Now that we have created an iterable of values that can be compared with <code>===</code>, I can show you this function:”</p>
  578. <div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="c1">// implements Tortoise and Hare cycle</span>
  579. <span class="c1">// detection algorithm.</span>
  580. <span class="kr">const</span> <span class="nx">hasCycle</span> <span class="o">=</span> <span class="p">(</span><span class="nx">orderedCollection</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  581. <span class="kr">const</span> <span class="nx">hare</span> <span class="o">=</span> <span class="nx">orderedCollection</span><span class="p">[</span><span class="nx">Symbol</span><span class="p">.</span><span class="nx">iterator</span><span class="p">]();</span>
  582. <span class="kd">let</span> <span class="nx">hareResult</span> <span class="o">=</span> <span class="p">(</span><span class="nx">hare</span><span class="p">.</span><span class="nx">next</span><span class="p">(),</span> <span class="nx">hare</span><span class="p">.</span><span class="nx">next</span><span class="p">());</span>
  583. <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">tortoiseValue</span> <span class="nx">of</span> <span class="nx">orderedCollection</span><span class="p">)</span> <span class="p">{</span>
  584. <span class="nx">hareResult</span> <span class="o">=</span> <span class="nx">hare</span><span class="p">.</span><span class="nx">next</span><span class="p">();</span>
  585. <span class="k">if</span> <span class="p">(</span><span class="nx">hareResult</span><span class="p">.</span><span class="nx">done</span><span class="p">)</span> <span class="p">{</span>
  586. <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
  587. <span class="p">}</span>
  588. <span class="k">if</span> <span class="p">(</span><span class="nx">tortoiseValue</span> <span class="o">===</span> <span class="nx">hareResult</span><span class="p">.</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
  589. <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  590. <span class="p">}</span>
  591. <span class="nx">hareResult</span> <span class="o">=</span> <span class="nx">hare</span><span class="p">.</span><span class="nx">next</span><span class="p">();</span>
  592. <span class="k">if</span> <span class="p">(</span><span class="nx">hareResult</span><span class="p">.</span><span class="nx">done</span><span class="p">)</span> <span class="p">{</span>
  593. <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
  594. <span class="p">}</span>
  595. <span class="k">if</span> <span class="p">(</span><span class="nx">tortoiseValue</span> <span class="o">===</span> <span class="nx">hareResult</span><span class="p">.</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
  596. <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
  597. <span class="p">}</span>
  598. <span class="p">}</span>
  599. <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
  600. <span class="p">};</span></code></pre></div>
  601. <p>“A long time ago,” The Carpenter explained, “Someone asked me a question in an interview. I have never forgotten the question, or the general form of the solution. The question was, <em>Given a linked list, detect whether it contains a cycle. Use constant space.</em>”</p>
  602. <p>“This is, of course, the most common solution, it is <a href="https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare">Floyd’s cycle-finding algorithm</a>, although there is some academic dispute as to whether Robert Floyd actually discovered it or was misattributed by Knuth.”</p>
  603. <p>“Thus, the solution to the game problem is:”</p>
  604. <div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kr">const</span> <span class="nx">terminates</span> <span class="o">=</span> <span class="p">(</span><span class="nx">game</span><span class="p">)</span> <span class="o">=&gt;</span>
  605. <span class="o">!</span><span class="nx">hasCycle</span><span class="p">(</span><span class="nx">positionsOf</span><span class="p">(</span><span class="nx">game</span><span class="p">))</span></code></pre></div>
  606. <p>“This solution makes use of iterables and a single utility function, <code>statefulMapIterableWith</code>. It also cleanly separates the mechanics of the game from the algorithm for detecting cycles in a graph.”</p>
  607. <h3 id="the-aftermath">the aftermath</h3>
  608. <p>The Carpenter sat down and waited. This type of solution provided an excellent opportunity to explore lazy versus eager evaluation, the performance of iterators versus native iteration, single responsibility design, and many other rich topics.</p>
  609. <p>The Carpenter was confident that although nobody would write this exact code in production, prospective employers would also recognize that nobody would try to detect whether a chequer game terminates in production, either. It’s all just a pretext for kicking off an interesting conversation, right?</p>
  610. <p><a href="https://www.flickr.com/photos/jlhopgood/6795353385"><img src="/assets/images/time.jpg" alt="Time"/></a></p>
  611. <p>Christine looked at the solution on the board, frowned, and glanced at the clock on the wall. “<em>Well, where has the time gone?</em>”</p>
  612. <p>“We at the Thing Software company are very grateful you made some time to visit with us, but alas, that is all the time we have today. If we wish to talk to you further, we’ll be in touch.”</p>
  613. <p>The Carpenter never did hear back from them, but the next day there was an email containing a generous contract from Friends of Ghosts (“FOG”), a codename for a stealth startup doing interesting work, and the Thing interview was forgotten.</p>
  614. <p>Some time later, The Carpenter ran into Bob Plissken at a local technology meet-up. “John! What happened at Thing?” Bob wanted to know, “I asked them what they thought of you, and all they would say was, <em>Writes unreadable code</em>. I thought it was a lock! I thought you’d finally make your escape from New York.”</p>
  615. <p>The Carpenter smiled. “I forgot about them, it’s been a while. So, do They Live?”</p>
  616. <hr/>
  617. <p>p.s. <a href="http://raganwald.com/2015/02/23/the-last-word-on-interviewing.html">(unlikely to be) The Last Word on Interviewing for a JavaScript Job</a></p>
  618. <p>p.p.s. The Carpenter probably cribbed the solution from <a href="http://raganwald.com/2013/02/17/a-drunken-walk.html">The “Drunken Walk” Programming Problem</a>, and <a href="http://raganwald.com/2013/02/18/drunken-walk-solution.html">Solving the “Drunken Walk” problem with iterators</a>.</p>
  619. </article>
  620. </section>
  621. <nav id="jumpto">
  622. <p>
  623. <a href="/david/blog/">Accueil du blog</a> |
  624. <a href="http://raganwald.com/2015/02/21/interviewing-for-a-front-end-job.html">Source originale</a> |
  625. <a href="/david/stream/2019/">Accueil du flux</a>
  626. </p>
  627. </nav>
  628. <footer>
  629. <div>
  630. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  631. <p>
  632. Bonjour/Hi!
  633. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  634. Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
  635. </p>
  636. <p>
  637. Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
  638. </p>
  639. <p>
  640. Voici quelques articles choisis :
  641. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  642. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  643. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  644. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  645. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  646. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  647. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  648. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  649. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  650. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  651. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  652. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  653. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  654. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  655. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  656. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  657. </p>
  658. <p>
  659. On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
  660. </p>
  661. <p>
  662. Je ne traque pas ta navigation mais mon
  663. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  664. conserve des logs d’accès.
  665. </p>
  666. </div>
  667. </footer>
  668. <script type="text/javascript">
  669. ;(_ => {
  670. const jumper = document.getElementById('jumper')
  671. jumper.addEventListener('click', e => {
  672. e.preventDefault()
  673. const anchor = e.target.getAttribute('href')
  674. const targetEl = document.getElementById(anchor.substring(1))
  675. targetEl.scrollIntoView({behavior: 'smooth'})
  676. })
  677. })()
  678. </script>