C Answers to Exercises

\(\newcommand{\footnotename}{footnote}\) \(\def \LWRfootnote {1}\) \(\newcommand {\footnote }[2][\LWRfootnote ]{{}^{\mathrm {#1}}}\) \(\newcommand {\footnotemark }[1][\LWRfootnote ]{{}^{\mathrm {#1}}}\) \(\let \LWRorighspace \hspace \) \(\renewcommand {\hspace }{\ifstar \LWRorighspace \LWRorighspace }\) \(\newcommand {\TextOrMath }[2]{#2}\) \(\newcommand {\mathnormal }[1]{{#1}}\) \(\newcommand \ensuremath [1]{#1}\) \(\newcommand {\LWRframebox }[2][]{\fbox {#2}} \newcommand {\framebox }[1][]{\LWRframebox } \) \(\newcommand {\setlength }[2]{}\) \(\newcommand {\addtolength }[2]{}\) \(\newcommand {\setcounter }[2]{}\) \(\newcommand {\addtocounter }[2]{}\) \(\newcommand {\arabic }[1]{}\) \(\newcommand {\number }[1]{}\) \(\newcommand {\noalign }[1]{\text {#1}\notag \\}\) \(\newcommand {\cline }[1]{}\) \(\newcommand {\directlua }[1]{\text {(directlua)}}\) \(\newcommand {\luatexdirectlua }[1]{\text {(directlua)}}\) \(\newcommand {\protect }{}\) \(\def \LWRabsorbnumber #1 {}\) \(\def \LWRabsorbquotenumber "#1 {}\) \(\newcommand {\LWRabsorboption }[1][]{}\) \(\newcommand {\LWRabsorbtwooptions }[1][]{\LWRabsorboption }\) \(\def \mathchar {\ifnextchar "\LWRabsorbquotenumber \LWRabsorbnumber }\) \(\def \mathcode #1={\mathchar }\) \(\let \delcode \mathcode \) \(\let \delimiter \mathchar \) \(\def \oe {\unicode {x0153}}\) \(\def \OE {\unicode {x0152}}\) \(\def \ae {\unicode {x00E6}}\) \(\def \AE {\unicode {x00C6}}\) \(\def \aa {\unicode {x00E5}}\) \(\def \AA {\unicode {x00C5}}\) \(\def \o {\unicode {x00F8}}\) \(\def \O {\unicode {x00D8}}\) \(\def \l {\unicode {x0142}}\) \(\def \L {\unicode {x0141}}\) \(\def \ss {\unicode {x00DF}}\) \(\def \SS {\unicode {x1E9E}}\) \(\def \dag {\unicode {x2020}}\) \(\def \ddag {\unicode {x2021}}\) \(\def \P {\unicode {x00B6}}\) \(\def \copyright {\unicode {x00A9}}\) \(\def \pounds {\unicode {x00A3}}\) \(\let \LWRref \ref \) \(\renewcommand {\ref }{\ifstar \LWRref \LWRref }\) \( \newcommand {\multicolumn }[3]{#3}\) \(\require {textcomp}\) \(\newcommand {\intertext }[1]{\text {#1}\notag \\}\) \(\let \Hat \hat \) \(\let \Check \check \) \(\let \Tilde \tilde \) \(\let \Acute \acute \) \(\let \Grave \grave \) \(\let \Dot \dot \) \(\let \Ddot \ddot \) \(\let \Breve \breve \) \(\let \Bar \bar \) \(\let \Vec \vec \) \(\renewcommand {\vec }{\boldsymbol }\) \(\newcommand {\Edge }{\ensuremath {\,\textemdash \,}}\) \(\newcommand \Const [1]{\text {\textsf {#1}}}\) \(\DeclareMathOperator {\lerp }{lerp}\) \(\DeclareMathOperator {\bitlen }{bitlen}\) \(\DeclareMathOperator {\sign }{sign}\) \(\newcommand {\I }{\mathrm {i}}\) \(\newcommand \AND {\mathbin {\&}}\) \(\newcommand \OR {\mathbin {|}}\) \(\newcommand \XOR {\mathbin {{}^{\wedge }}}\) \(\newcommand \shl {\ll }\) \(\newcommand \shr {\ggg }\) \(\newcommand \asr {\gg }\) \(\newcommand \NOT {\ensuremath {\mathord {\sim }}}\) \(\newcommand {\isep }{\mathrel {{.}\,{.}}}\) \(\newcommand {\Id }[1]{\mathit {#1}}\) \(\newcommand {\const }[1]{\mathsf {#1}}\) \(\newcommand {\algorithmname }[1]{\text {\textsc {#1}}}\) \(\newcommand {\bits }[1]{\text {#1}}\) \(\newcommand {\hexa }[1]{\mathtt {0x#1}}\) \(\newcommand {\num }[1]{#1}\) \(\newcommand {\qed }{\quad \square }\) \(\newcommand {\idiv }[2]{\lfloor #1/#2\rfloor }\) \(\newcommand \attribdot {\ensuremath {\mkern 1.5mu.\mkern 1.5mu}}\) \(\newcommand \attribxr [2]{#1\attribdot \text {#2}}\) \(\newcommand \attribir [2]{\Id {#1}\attribdot \text {#2}}\) \(\newcommand \attribii [2]{\Id {#1}\attribdot \Id {#2}}\) \(\newcommand \textsc [1]{#1}\) \(\require {colortbl}\) \(\let \LWRorigcolumncolor \columncolor \) \(\renewcommand {\columncolor }[2][named]{\LWRorigcolumncolor [#1]{#2}\LWRabsorbtwooptions }\) \(\let \LWRorigrowcolor \rowcolor \) \(\renewcommand {\rowcolor }[2][named]{\LWRorigrowcolor [#1]{#2}\LWRabsorbtwooptions }\) \(\let \LWRorigcellcolor \cellcolor \) \(\renewcommand {\cellcolor }[2][named]{\LWRorigcellcolor [#1]{#2}\LWRabsorbtwooptions }\) \(\newcommand {\tcbset }[1]{}\) \(\newcommand {\tcbsetforeverylayer }[1]{}\) \(\newcommand {\tcbox }[2][]{\boxed {\text {#2}}}\) \(\newcommand {\tcboxfit }[2][]{\boxed {#2}}\) \(\newcommand {\tcblower }{}\) \(\newcommand {\tcbline }{}\) \(\newcommand {\tcbtitle }{}\) \(\newcommand {\tcbsubtitle [2][]{\mathrm {#2}}}\) \(\newcommand {\tcboxmath }[2][]{\boxed {#2}}\) \(\newcommand {\tcbhighmath }[2][]{\boxed {#2}}\) \(\newcommand {\toprule }[1][]{\hline }\) \(\let \midrule \toprule \) \(\let \bottomrule \toprule \) \(\def \LWRbooktabscmidruleparen (#1)#2{}\) \(\newcommand {\LWRbooktabscmidrulenoparen }[1]{}\) \(\newcommand {\cmidrule }[1][]{\ifnextchar (\LWRbooktabscmidruleparen \LWRbooktabscmidrulenoparen }\) \(\newcommand {\morecmidrules }{}\) \(\newcommand {\specialrule }[3]{\hline }\) \(\newcommand {\addlinespace }[1][]{}\) \(\newcommand {\LWRsubmultirow }[2][]{#2}\) \(\newcommand {\LWRmultirow }[2][]{\LWRsubmultirow }\) \(\newcommand {\multirow }[2][]{\LWRmultirow }\) \(\newcommand {\mrowcell }{}\) \(\newcommand {\mcolrowcell }{}\) \(\newcommand {\STneed }[1]{}\) \(\newcommand {\LWRldelimtwo }[1][]{\text {#1}~\LWRbigdelim }\) \(\newcommand {\LWRldelimone }[2][]{\LWRldelimtwo }\) \(\def \ldelim #1#2{\def \LWRbigdelim {#1}\LWRldelimone }\) \(\newcommand {\LWRrdelimtwo }[1][]{\LWRbigdelim ~\text {#1}}\) \(\newcommand {\LWRrdelimone }[2][]{\LWRrdelimtwo }\) \(\def \rdelim #1#2{\def \LWRbigdelim {#1}\LWRrdelimone }\) \(\let \symnormal \mathit \) \(\let \symliteral \mathrm \) \(\let \symbb \mathbb \) \(\let \symbbit \mathbb \) \(\let \symcal \mathcal \) \(\let \symscr \mathscr \) \(\let \symfrak \mathfrak \) \(\let \symsfup \mathsf \) \(\let \symsfit \mathit \) \(\let \symbfsf \mathbf \) \(\let \symbfup \mathbf \) \(\newcommand {\symbfit }[1]{\boldsymbol {#1}}\) \(\let \symbfcal \mathcal \) \(\let \symbfscr \mathscr \) \(\let \symbffrak \mathfrak \) \(\let \symbfsfup \mathbf \) \(\newcommand {\symbfsfit }[1]{\boldsymbol {#1}}\) \(\let \symup \mathrm \) \(\let \symbf \mathbf \) \(\let \symit \mathit \) \(\let \symsf \symsfit \) \(\let \symtt \mathtt \) \(\let \symbffrac \mathbffrac \) \(\newcommand {\mathfence }[1]{\mathord {#1}}\) \(\newcommand {\mathover }[1]{#1}\) \(\newcommand {\mathunder }[1]{#1}\) \(\newcommand {\mathaccent }[1]{#1}\) \(\newcommand {\mathbotaccent }[1]{#1}\) \(\newcommand {\mathalpha }[1]{\mathord {#1}}\) \(\def\Alpha{\unicode{x1D6E2}}\) \(\def\Beta{\unicode{x1D6E3}}\) \(\def\Gamma{\unicode{x1D6E4}}\) \(\def\Digamma{\mathit{\unicode{x03DC}}}\) \(\def\Delta{\unicode{x1D6E5}}\) \(\def\Epsilon{\unicode{x1D6E6}}\) \(\def\Zeta{\unicode{x1D6E7}}\) \(\def\Eta{\unicode{x1D6E8}}\) \(\def\Theta{\unicode{x1D6E9}}\) \(\def\Vartheta{\unicode{x1D6F3}}\) \(\def\Iota{\unicode{x1D6EA}}\) \(\def\Kappa{\unicode{x1D6EB}}\) \(\def\Lambda{\unicode{x1D6EC}}\) \(\def\Mu{\unicode{x1D6ED}}\) \(\def\Nu{\unicode{x1D6EE}}\) \(\def\Xi{\unicode{x1D6EF}}\) \(\def\Omicron{\unicode{x1D6F0}}\) \(\def\Pi{\unicode{x1D6F1}}\) \(\def\Rho{\unicode{x1D6F2}}\) \(\def\Sigma{\unicode{x1D6F4}}\) \(\def\Tau{\unicode{x1D6F5}}\) \(\def\Upsilon{\unicode{x1D6F6}}\) \(\def\Phi{\unicode{x1D6F7}}\) \(\def\Chi{\unicode{x1D6F8}}\) \(\def\Psi{\unicode{x1D6F9}}\) \(\def\Omega{\unicode{x1D6FA}}\) \(\def\alpha{\unicode{x1D6FC}}\) \(\def\beta{\unicode{x1D6FD}}\) \(\def\varbeta{\unicode{x03D0}}\) \(\def\gamma{\unicode{x1D6FE}}\) \(\def\digamma{\mathit{\unicode{x03DD}}}\) \(\def\delta{\unicode{x1D6FF}}\) \(\def\epsilon{\unicode{x1D716}}\) \(\def\varepsilon{\unicode{x1D700}}\) \(\def\zeta{\unicode{x1D701}}\) \(\def\eta{\unicode{x1D702}}\) \(\def\theta{\unicode{x1D703}}\) \(\def\vartheta{\unicode{x1D717}}\) \(\def\iota{\unicode{x1D704}}\) \(\def\kappa{\unicode{x1D705}}\) \(\def\varkappa{\unicode{x1D718}}\) \(\def\lambda{\unicode{x1D706}}\) \(\def\mu{\unicode{x1D707}}\) \(\def\nu{\unicode{x1D708}}\) \(\def\xi{\unicode{x1D709}}\) \(\def\omicron{\unicode{x1D70A}}\) \(\def\pi{\unicode{x1D70B}}\) \(\def\varpi{\unicode{x1D71B}}\) \(\def\rho{\unicode{x1D70C}}\) \(\def\varrho{\unicode{x1D71A}}\) \(\def\sigma{\unicode{x1D70E}}\) \(\def\varsigma{\unicode{x1D70D}}\) \(\def\tau{\unicode{x1D70F}}\) \(\def\upsilon{\unicode{x1D710}}\) \(\def\phi{\unicode{x1D719}}\) \(\def\varphi{\unicode{x1D711}}\) \(\def\chi{\unicode{x1D712}}\) \(\def\psi{\unicode{x1D713}}\) \(\def\omega{\unicode{x1D714}}\) \(\def\upAlpha{\unicode{x0391}}\) \(\def\upBeta{\unicode{x0392}}\) \(\def\upGamma{\unicode{x0393}}\) \(\def\upDigamma{\unicode{x03DC}}\) \(\def\upDelta{\unicode{x0394}}\) \(\def\upEpsilon{\unicode{x0395}}\) \(\def\upZeta{\unicode{x0396}}\) \(\def\upEta{\unicode{x0397}}\) \(\def\upTheta{\unicode{x0398}}\) \(\def\upVartheta{\unicode{x03F4}}\) \(\def\upIota{\unicode{x0399}}\) \(\def\upKappa{\unicode{x039A}}\) \(\def\upLambda{\unicode{x039B}}\) \(\def\upMu{\unicode{x039C}}\) \(\def\upNu{\unicode{x039D}}\) \(\def\upXi{\unicode{x039E}}\) \(\def\upOmicron{\unicode{x039F}}\) \(\def\upPi{\unicode{x03A0}}\) \(\def\upVarpi{\unicode{x03D6}}\) \(\def\upRho{\unicode{x03A1}}\) \(\def\upSigma{\unicode{x03A3}}\) \(\def\upTau{\unicode{x03A4}}\) \(\def\upUpsilon{\unicode{x03A5}}\) \(\def\upPhi{\unicode{x03A6}}\) \(\def\upChi{\unicode{x03A7}}\) \(\def\upPsi{\unicode{x03A8}}\) \(\def\upOmega{\unicode{x03A9}}\) \(\def\itAlpha{\unicode{x1D6E2}}\) \(\def\itBeta{\unicode{x1D6E3}}\) \(\def\itGamma{\unicode{x1D6E4}}\) \(\def\itDigamma{\mathit{\unicode{x03DC}}}\) \(\def\itDelta{\unicode{x1D6E5}}\) \(\def\itEpsilon{\unicode{x1D6E6}}\) \(\def\itZeta{\unicode{x1D6E7}}\) \(\def\itEta{\unicode{x1D6E8}}\) \(\def\itTheta{\unicode{x1D6E9}}\) \(\def\itVartheta{\unicode{x1D6F3}}\) \(\def\itIota{\unicode{x1D6EA}}\) \(\def\itKappa{\unicode{x1D6EB}}\) \(\def\itLambda{\unicode{x1D6EC}}\) \(\def\itMu{\unicode{x1D6ED}}\) \(\def\itNu{\unicode{x1D6EE}}\) \(\def\itXi{\unicode{x1D6EF}}\) \(\def\itOmicron{\unicode{x1D6F0}}\) \(\def\itPi{\unicode{x1D6F1}}\) \(\def\itRho{\unicode{x1D6F2}}\) \(\def\itSigma{\unicode{x1D6F4}}\) \(\def\itTau{\unicode{x1D6F5}}\) \(\def\itUpsilon{\unicode{x1D6F6}}\) \(\def\itPhi{\unicode{x1D6F7}}\) \(\def\itChi{\unicode{x1D6F8}}\) \(\def\itPsi{\unicode{x1D6F9}}\) \(\def\itOmega{\unicode{x1D6FA}}\) \(\def\upalpha{\unicode{x03B1}}\) \(\def\upbeta{\unicode{x03B2}}\) \(\def\upvarbeta{\unicode{x03D0}}\) \(\def\upgamma{\unicode{x03B3}}\) \(\def\updigamma{\unicode{x03DD}}\) \(\def\updelta{\unicode{x03B4}}\) \(\def\upepsilon{\unicode{x03F5}}\) \(\def\upvarepsilon{\unicode{x03B5}}\) \(\def\upzeta{\unicode{x03B6}}\) \(\def\upeta{\unicode{x03B7}}\) \(\def\uptheta{\unicode{x03B8}}\) \(\def\upvartheta{\unicode{x03D1}}\) \(\def\upiota{\unicode{x03B9}}\) \(\def\upkappa{\unicode{x03BA}}\) \(\def\upvarkappa{\unicode{x03F0}}\) \(\def\uplambda{\unicode{x03BB}}\) \(\def\upmu{\unicode{x03BC}}\) \(\def\upnu{\unicode{x03BD}}\) \(\def\upxi{\unicode{x03BE}}\) \(\def\upomicron{\unicode{x03BF}}\) \(\def\uppi{\unicode{x03C0}}\) \(\def\upvarpi{\unicode{x03D6}}\) \(\def\uprho{\unicode{x03C1}}\) \(\def\upvarrho{\unicode{x03F1}}\) \(\def\upsigma{\unicode{x03C3}}\) \(\def\upvarsigma{\unicode{x03C2}}\) \(\def\uptau{\unicode{x03C4}}\) \(\def\upupsilon{\unicode{x03C5}}\) \(\def\upphi{\unicode{x03D5}}\) \(\def\upvarphi{\unicode{x03C6}}\) \(\def\upchi{\unicode{x03C7}}\) \(\def\uppsi{\unicode{x03C8}}\) \(\def\upomega{\unicode{x03C9}}\) \(\def\italpha{\unicode{x1D6FC}}\) \(\def\itbeta{\unicode{x1D6FD}}\) \(\def\itvarbeta{\unicode{x03D0}}\) \(\def\itgamma{\unicode{x1D6FE}}\) \(\def\itdigamma{\mathit{\unicode{x03DD}}}\) \(\def\itdelta{\unicode{x1D6FF}}\) \(\def\itepsilon{\unicode{x1D716}}\) \(\def\itvarepsilon{\unicode{x1D700}}\) \(\def\itzeta{\unicode{x1D701}}\) \(\def\iteta{\unicode{x1D702}}\) \(\def\ittheta{\unicode{x1D703}}\) \(\def\itvartheta{\unicode{x1D717}}\) \(\def\itiota{\unicode{x1D704}}\) \(\def\itkappa{\unicode{x1D705}}\) \(\def\itvarkappa{\unicode{x1D718}}\) \(\def\itlambda{\unicode{x1D706}}\) \(\def\itmu{\unicode{x1D707}}\) \(\def\itnu{\unicode{x1D708}}\) \(\def\itxi{\unicode{x1D709}}\) \(\def\itomicron{\unicode{x1D70A}}\) \(\def\itpi{\unicode{x1D70B}}\) \(\def\itvarpi{\unicode{x1D71B}}\) \(\def\itrho{\unicode{x1D70C}}\) \(\def\itvarrho{\unicode{x1D71A}}\) \(\def\itsigma{\unicode{x1D70E}}\) \(\def\itvarsigma{\unicode{x1D70D}}\) \(\def\ittau{\unicode{x1D70F}}\) \(\def\itupsilon{\unicode{x1D710}}\) \(\def\itphi{\unicode{x1D719}}\) \(\def\itvarphi{\unicode{x1D711}}\) \(\def\itchi{\unicode{x1D712}}\) \(\def\itpsi{\unicode{x1D713}}\) \(\def\itomega{\unicode{x1D714}}\) \(\let \lparen (\) \(\let \rparen )\) \(\newcommand {\cuberoot }[1]{\,{}^3\!\!\sqrt {#1}}\,\) \(\newcommand {\fourthroot }[1]{\,{}^4\!\!\sqrt {#1}}\,\) \(\newcommand {\longdivision }[1]{\mathord {\unicode {x027CC}#1}}\) \(\newcommand {\mathcomma }{,}\) \(\newcommand {\mathcolon }{:}\) \(\newcommand {\mathsemicolon }{;}\) \(\newcommand {\overbracket }[1]{\mathinner {\overline {\ulcorner {#1}\urcorner }}}\) \(\newcommand {\underbracket }[1]{\mathinner {\underline {\llcorner {#1}\lrcorner }}}\) \(\newcommand {\overbar }[1]{\mathord {#1\unicode {x00305}}}\) \(\newcommand {\ovhook }[1]{\mathord {#1\unicode {x00309}}}\) \(\newcommand {\ocirc }[1]{\mathord {#1\unicode {x0030A}}}\) \(\newcommand {\candra }[1]{\mathord {#1\unicode {x00310}}}\) \(\newcommand {\oturnedcomma }[1]{\mathord {#1\unicode {x00312}}}\) \(\newcommand {\ocommatopright }[1]{\mathord {#1\unicode {x00315}}}\) \(\newcommand {\droang }[1]{\mathord {#1\unicode {x0031A}}}\) \(\newcommand {\leftharpoonaccent }[1]{\mathord {#1\unicode {x020D0}}}\) \(\newcommand {\rightharpoonaccent }[1]{\mathord {#1\unicode {x020D1}}}\) \(\newcommand {\vertoverlay }[1]{\mathord {#1\unicode {x020D2}}}\) \(\newcommand {\leftarrowaccent }[1]{\mathord {#1\unicode {x020D0}}}\) \(\newcommand {\annuity }[1]{\mathord {#1\unicode {x020E7}}}\) \(\newcommand {\widebridgeabove }[1]{\mathord {#1\unicode {x020E9}}}\) \(\newcommand {\asteraccent }[1]{\mathord {#1\unicode {x020F0}}}\) \(\newcommand {\threeunderdot }[1]{\mathord {#1\unicode {x020E8}}}\) \(\newcommand {\Bbbsum }{\mathop {\unicode {x2140}}\limits }\) \(\newcommand {\oiint }{\mathop {\unicode {x222F}}\limits }\) \(\newcommand {\oiiint }{\mathop {\unicode {x2230}}\limits }\) \(\newcommand {\intclockwise }{\mathop {\unicode {x2231}}\limits }\) \(\newcommand {\ointclockwise }{\mathop {\unicode {x2232}}\limits }\) \(\newcommand {\ointctrclockwise }{\mathop {\unicode {x2233}}\limits }\) \(\newcommand {\varointclockwise }{\mathop {\unicode {x2232}}\limits }\) \(\newcommand {\leftouterjoin }{\mathop {\unicode {x27D5}}\limits }\) \(\newcommand {\rightouterjoin }{\mathop {\unicode {x27D6}}\limits }\) \(\newcommand {\fullouterjoin }{\mathop {\unicode {x27D7}}\limits }\) \(\newcommand {\bigbot }{\mathop {\unicode {x27D8}}\limits }\) \(\newcommand {\bigtop }{\mathop {\unicode {x27D9}}\limits }\) \(\newcommand {\xsol }{\mathop {\unicode {x29F8}}\limits }\) \(\newcommand {\xbsol }{\mathop {\unicode {x29F9}}\limits }\) \(\newcommand {\bigcupdot }{\mathop {\unicode {x2A03}}\limits }\) \(\newcommand {\bigsqcap }{\mathop {\unicode {x2A05}}\limits }\) \(\newcommand {\conjquant }{\mathop {\unicode {x2A07}}\limits }\) \(\newcommand {\disjquant }{\mathop {\unicode {x2A08}}\limits }\) \(\newcommand {\bigtimes }{\mathop {\unicode {x2A09}}\limits }\) \(\newcommand {\modtwosum }{\mathop {\unicode {x2A0A}}\limits }\) \(\newcommand {\sumint }{\mathop {\unicode {x2A0B}}\limits }\) \(\newcommand {\intbar }{\mathop {\unicode {x2A0D}}\limits }\) \(\newcommand {\intBar }{\mathop {\unicode {x2A0E}}\limits }\) \(\newcommand {\fint }{\mathop {\unicode {x2A0F}}\limits }\) \(\newcommand {\cirfnint }{\mathop {\unicode {x2A10}}\limits }\) \(\newcommand {\awint }{\mathop {\unicode {x2A11}}\limits }\) \(\newcommand {\rppolint }{\mathop {\unicode {x2A12}}\limits }\) \(\newcommand {\scpolint }{\mathop {\unicode {x2A13}}\limits }\) \(\newcommand {\npolint }{\mathop {\unicode {x2A14}}\limits }\) \(\newcommand {\pointint }{\mathop {\unicode {x2A15}}\limits }\) \(\newcommand {\sqint }{\mathop {\unicode {x2A16}}\limits }\) \(\newcommand {\intlarhk }{\mathop {\unicode {x2A17}}\limits }\) \(\newcommand {\intx }{\mathop {\unicode {x2A18}}\limits }\) \(\newcommand {\intcap }{\mathop {\unicode {x2A19}}\limits }\) \(\newcommand {\intcup }{\mathop {\unicode {x2A1A}}\limits }\) \(\newcommand {\upint }{\mathop {\unicode {x2A1B}}\limits }\) \(\newcommand {\lowint }{\mathop {\unicode {x2A1C}}\limits }\) \(\newcommand {\bigtriangleleft }{\mathop {\unicode {x2A1E}}\limits }\) \(\newcommand {\zcmp }{\mathop {\unicode {x2A1F}}\limits }\) \(\newcommand {\zpipe }{\mathop {\unicode {x2A20}}\limits }\) \(\newcommand {\zproject }{\mathop {\unicode {x2A21}}\limits }\) \(\newcommand {\biginterleave }{\mathop {\unicode {x2AFC}}\limits }\) \(\newcommand {\bigtalloblong }{\mathop {\unicode {x2AFF}}\limits }\) \(\newcommand {\arabicmaj }{\mathop {\unicode {x1EEF0}}\limits }\) \(\newcommand {\arabichad }{\mathop {\unicode {x1EEF1}}\limits }\)

Chapter 6

Solution to Exercise 6.1

It computes the set of all holes that can be reached by moving any of the pegs on board.

Solution to Exercise 6.2

Consider all eight possible assignments of three bits and verify that the expressions on either side of the equation produce the same result:

\begin{equation*} \begin{array}{c@{}c@{}ccccc} A & B & C & A\AND (B\OR C) & (A\AND B)\OR (A\AND C) & A\OR (B\AND C)&(A\OR B)\AND (A\OR C)\\ \hline 0 & 0 & 0 & 0\AND 0 = 0 & 0\OR 0=0 & 0 \OR 0=0 & 0\AND 0=0 \\ 0 & 0 & 1 & 0\AND 1 = 0 & 0\OR 0=0 & 0 \OR 0=0 & 0\AND 1=0 \\ 0 & 1 & 0 & 0\AND 1 = 0 & 0\OR 0=0 & 0 \OR 0=0 & 1\AND 0=0 \\ 0 & 1 & 1 & 0\AND 1 = 0 & 0\OR 0=0 & 0 \OR 1=1 & 1\AND 1=1 \\ 1 & 0 & 0 & 1\AND 0 = 0 & 0\OR 0=0 & 1 \OR 0=1 & 1\AND 1=1 \\ 1 & 0 & 1 & 1\AND 1 = 1 & 0\OR 1=1 & 1 \OR 0=1 & 1\AND 1=1 \\ 1 & 1 & 0 & 1\AND 1 = 1 & 1\OR 0=1 & 1 \OR 0=1 & 1\AND 1=1 \\ 1 & 1 & 0 & 1\AND 1 = 1 & 1\OR 1=1 & 1 \OR 1=1 & 1\AND 1=1 \end {array} \end{equation*}

The same laws must hold for sequences of bits since the bit operators \(\AND \) and \(\OR \) operate element-wise.

Solution to Exercise 6.3

b)With the numbering scheme shown in Fig. C.9, the offsets between neighboring cells are constant and it becomes possible to use bitboards and the techniques discussed in the text to compute possible jumps.

Figure C.9 Numbering scheme for triangular peg solitaire.

Solution to Exercise 6.4

The problem can be represented using one bitboard for each player. Some bit operations become easier if we add an empty column to the board, so we will use bitboards of size \(8\times 6\), which easily fit into long integers. The variable BOARD_MASK in Listing C.41 selects the bits of the board proper, without the empty column on the left.

Listing C.41ch6 / Connect4

static int WIDTH = 7, HEIGHT = 6;

// Bit board of size (WIDTH + 1) x HEIGHT
static long BOARD_MASK
        = 0b01111111_01111111_01111111_01111111_01111111_01111111L;
//          row 1    row 2    row 3    row 4    row 5    row 6
// bits:   47..40   39..32   31..24   23..16    15..8    7..0

Adjacent squares on the board are separated by a constant offset on the bitboard:

.
direction left right down up up+left up+right
offset \(+1\) \(-1\) \(+8\) \(-8\) \(+9\) \(+7\)

We can therefore use bit shifts to move the entire board in a certain direction. The added empty column serves as a buffer that prevents bit shifts from moving tokens to the opposite side of the board.

The fourBitsSet() function in Listing C.42 checks whether there are four bits with a certain offset from each other on a given board; notice how BOARD_MASK is used to clear the extra column after every shift. The checkWin() method in the same listing now identifies a winning position by checking for a line of four tokens in all four directions: horizontal, vertical, and the two diagonals.

Listing C.42ch6 / Connect4

// Check whether the board contains a sequence of four bits at a
// certain offset.
static boolean fourBitsSet(long board, int offset) {
    long step1 = (board >>> offset) & BOARD_MASK;
    long step2 = (step1 >>> offset) & BOARD_MASK;
    long step3 = (step2 >>> offset) & BOARD_MASK;
    return (board & step1 & step2 & step3) != 0;
}

// Check whether there is a line of four adjacent tokens
// anywhere on the bitboard.
static boolean checkWin(long board) {
    int leftOffset = 1;
    int upOffset = WIDTH + 1;
    int upLeftOffset = WIDTH + 1 + 1;
    int upRightOffset = WIDTH + 1 - 1;
    return fourBitsSet(board, leftOffset)
            || fourBitsSet(board, upOffset)
            || fourBitsSet(board, upLeftOffset)
            || fourBitsSet(board, upRightOffset);
}

Connect4: BOARD_MASK, HEIGHT, WIDTH

Solution to Exercise 6.5

We can obtain a rough estimate by timing how long it takes the program in Listing 6.5 to generate a few thousand solutions and then extrapolating the result to 41 quadrillion possible solutions. On the author’s machine, generating 10 000 solutions without printing them takes 27 seconds, which gives us an estimate of

\begin{equation*} \frac {40\,861\,647\,040\,079\,968}{10\,000\cdot 60\cdot 60\cdot 24\cdot 365}\times 27\,\text {s}\approx 349\,843\,\text {years} \end{equation*}

to generate all solutions.

Solution to Exercise 6.6

After the algorithm has completed, there are 23 475 687 entries in numSolutions, which is the number of visited boards. Only 1 679 071 of those entries have a nonzero count associated with them, so only approximately 7 % of all reachable boards are actually solvable. This explains why humans find peg solitaire moderately difficult, despite there being quadrillions of possible solutions.

Solution to Exercise 6.7

The implementation in Listing C.43 stores previously computed values of the Fibonacci sequence in an array fibArray. The value 0 indicates an unknown value.

Listing C.43ch6 / FibMemoize

private static int[] fibArray = {1, 1};

public static int fib(int n) {
    if (n >= fibArray.length)
        fibArray = Arrays.copyOf(fibArray, n + 1);
    if (fibArray[n] == 0)
        fibArray[n] = fib(n - 1) + fib(n - 2);
    return fibArray[n];
}

JDK: Arrays

Solution to Exercise 6.8

The Memoizer class shown in Listing C.44 implements the same interface as the function func it wraps. To cache previous return values of func, we use a hash table that is queried and updated every time the apply() method is called.

Listing C.44ch6 / Memoizer

public class Memoizer<T, R> implements Function<T, R> {
    private final Function<T, R> func;
    private final HashMap<T, R> cache = new HashMap<>();

    public Memoizer(Function<T, R> func) {
        this.func = func;
    }

    public R apply(T t) {
        return cache.computeIfAbsent(t, func);
    }
}

Solution to Exercise 6.9

a)The outcomes for a few small values of \(n\) and \(m\) are shown in Table C.1. For \(1,1\)-Nim, the first player always loses. For \(1,m\)-Nim with \(m>1\), the first player wins by removing \(m-1\) coins from the second pile. For \(2,2\)-Nim, the first player loses since all moves lead to a winning state for the opponent, but for \(2,m\)-Nim with \(m>2\) the first player wins by taking \(m-2\) coins from the second pile. The same pattern repeats for \(n,m\)-Nim in general: The first player wins if \(n\ne m\) but loses if \(n=m\), because in this case every possible move leads to a winning position for the opponent.

Table C.1 Winning strategies for \(n,m\)-Nim
.
\(n\) \(m\) Outcome Winning move
1 1 loss
1 \(> 1\) win Take \(m-1\) coins
2 2 loss
2 \(>2\) win Take \(m-2\) coins
3 3 loss
3 \(>3\) win Take \(m-3\) coins

b)The detailed evaluation is fairly complex, but we can use the symmetry of \(W\) and a few logical shortcuts to simplify the computation:

\begin{align*} W(1,1,2) &= \neg W(0,1,2) \lor \neg W(1,0,2) \lor \neg W(1,1,1) \lor \neg W(1,1,0)\\ &= \neg W(0,1,2) \lor \neg W(1,1,1) \lor \neg W(1,1,0) \tag {1}\\ &= \neg W(0,1,2) \lor W(1,1,0) \lor \neg W(1,1,0) \tag {2}\\ &= \mathsf {T} \tag {3} \end{align*} (1) follows from the fact that \(W\) is symmetric, so \(W(1,0,2) = W(0,1,2)\); (2) from \(W(1,1,1)=\neg W(1,1,0)\); and (3) from the fact that \(\neg X\lor X=\mathsf {T}\) for all \(X\).

c)We can represent each position as a list of integers that holds the number of coins in each pile. The goal is to implement a program that maps such a list to a Boolean value that indicates whether the corresponding position is winnable.

We use memoization to remember all previously computed values of this mapping in a hash table called winningCache; see Listing C.45. The constructor NimMemoize() initializes this table by mapping the empty list to false: The state with no coins left is by definition a losing position.

Listing C.45ch6 / NimMemoize

public class NimMemoize {
    private final Map<List<Integer>, Boolean> winningCache;

    public NimMemoize() {
        winningCache = new HashMap<>();
        // The empty list (no coins) is a losing position
        winningCache.put(List.of(), false);
    }

    public static List<Integer> normalize(List<Integer> piles) {
        var newPiles = new ArrayList<>(piles);
        newPiles.sort(Integer::compare);
        newPiles.removeIf(k -> k == 0);
        return newPiles;
    }

    // Determine whether 'piles' is a winning position.
    public boolean isWinning(List<Integer> piles) {
        piles = normalize(piles);
        if (winningCache.containsKey(piles))
            return winningCache.get(piles);
        for (int h = 0; h < piles.size(); h++) {
            for (int n = 1; n <= piles.get(h); n++) {
                var newPiles = new ArrayList<>(piles);
                newPiles.set(h, piles.get(h) - n);
                if (!isWinning(newPiles)) {
                    winningCache.put(piles, true);
                    return true;
                }
            }
        }
        winningCache.put(piles, false);
        return false;
    }
}

The normalize() method is used to map all equivalent positions to a single unique representative. Since empty piles can be ignored and the order of piles doesn’t matter, we can normalize a game state by sorting the piles by size and keeping only nonzero entries. The function isWinning() in Listing C.45 checks whether removing \(n\) coins from the \(k\)th pile produces a position that is unwinnable for the opponent. We memoize previous results in the hash table winningCache.

Calling this function tells us that the position \(10,5,4,3\) is winnable.

d)The Nim sum of \((2,5,6)\) is

\begin{equation*} \begin{array}{ccc@{\extracolsep {1cm}}l} 0 & 1 & 0 & =2\\ 1 & 0 & 1 & =5\\ 1 & 1 & 0 & =6\\ \midrule 0 & 0 & 1 & \text {Sum, ignoring carries}\\ \end {array} \end{equation*}

The result is nonzero, so this is a winning position. Only the last bit changes for \((2,5,7)\), which is therefore a losing position.

e)To find all possible winning moves, we first compute the Nim sum of the position. We then check for each pile of coins whether there is a positive number of coins n whose removal would reduce the Nim sum to zero, which indicates a losing position for the opponent. The printWinningMoves() function in Listing C.46 implements this algorithm. The winning moves for \((3,6,6)\) are:

- take 3 coin(s) from pile 0
- take 1 coin(s) from pile 1
- take 1 coin(s) from pile 2

Listing C.46ch6 / Nim

static void printWinningMoves(List<Integer> piles) {
    int nimSum = 0;
    for (int pile : piles)
        nimSum ^= pile;
    System.out.printf("Winning moves for %s:%n", piles);
    for (int pile = 0; pile < piles.size(); pile++) {
        int n = piles.get(pile) - (piles.get(pile) ^ nimSum);
        if (n > 0) {
            System.out.printf(
                    "- take %d coin(s) from pile %d%n", n, pile);
        }
    }
}

JDK: System

Solution to Exercise 6.10

b)To represent the Sudoku board, we use an array of \(9\times 9\) integers in which empty squares are marked using the number 0 (Listing C.47). In addition, we use a handful of bit sets to keep track of which digits can still be placed in each of the 9 rows (rowOptions), columns (colOptions), and \(3\times 3\) blocks (boxOptions). (The bit sets are stored in integers of type long instead of int to make it easier to use the utility functions we defined in Chapter 5.) The putDigit() method writes a digit to the specified square on the board and then removes it from the pool of available digits by modifying the corresponding bit sets. The removeDigit() method undoes this action.

Listing C.47ch6 / Sudoku

public class Sudoku {
    private int[][] board = new int[9][9];
    private long[] rowOptions = new long[9];
    private long[] colOptions = new long[9];
    private long[] boxOptions = new long[9];

    static int blockIndex(int row, int col) {
        return 3 * (row / 3) + col / 3;
    }

    void putDigit(int row, int col, int digit) {
        this.board[row][col] = digit;
        rowOptions[row] &= ~Bits.bit(digit);
        colOptions[col] &= ~Bits.bit(digit);
        boxOptions[blockIndex(row, col)] &= ~Bits.bit(digit);
    }

    void removeDigit(int row, int col, int digit) {
        board[row][col] = 0;
        rowOptions[row] |= Bits.bit(digit);
        colOptions[col] |= Bits.bit(digit);
        boxOptions[blockIndex(row, col)] |= Bits.bit(digit);
    }

    public Sudoku(String[] board) {
        long ALL_DIGITS = Bits.bits(1, 2, 3, 4, 5, 6, 7, 8, 9);
        Arrays.fill(rowOptions, ALL_DIGITS);
        Arrays.fill(colOptions, ALL_DIGITS);
        Arrays.fill(boxOptions, ALL_DIGITS);
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                if (!Character.isDigit(board[row].charAt(col)))
                    continue;
                int digit = board[row].charAt(col) - '0';
                if (digit != 0)
                    putDigit(row, col, digit);
            }
        }
    }

    // ...
}

Bits: bit()

The final method in Listing C.47 is the constructor Sudoku(), which uses an array of Strings to initialize the board. Each entry of board describes one row of the board. For example, the board in Fig. 6.7 is encoded as follows:

String[] board = {
        "000000308", "027100060", "004002001",
        "080540009", "750900000", "000010080",
        "006000050", "408009000", "000000040"
};

The solve() method in Listing C.48 attempts to solve a given board using backtracking. The function first searches for the next empty square on the board (row and col) and then tries all valid digits for this square; the set of valid digits is obtained by intersecting the corresponding bit sets in rowOptions, colOptions, and boxOptions. For each possible digit, solve() calls itself recursively to complete the solution.

Listing C.48ch6 / Sudoku

public String solve() {
    // Find first row with empty squares
    int row = 0;
    while (row < 9 && rowOptions[row] == 0)
        row++;
    if (row >= 9) {
        // Solution found
        var sb = new StringBuilder();
        for (int[] r : board)
            sb.append(Arrays.toString(r)).append('\n');
        return sb.toString();
    } else {
        // Find first empty column
        int col = 0;
        while (col < 9 && board[row][col] != 0)
            col++;
        // Recursively try all allowed digits.
        long validDigits = rowOptions[row] & colOptions[col]
                & boxOptions[blockIndex(row, col)];
        for (int digit : Bits.iterate(validDigits)) {
            putDigit(row, col, digit);
            var solution = solve();
            if (solution != null)
                return solution;
            removeDigit(row, col, digit);
        }
    }
    return null;
}