100% found this document useful (9 votes)
3K views820 pages

Algorithm Design

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (9 votes)
3K views820 pages

Algorithm Design

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 820

i i

i i

Algorithm Design

A bestseller in its French edition, this book is original in its construction and
its success in the French market demonstrates its appeal. It is based on three
principles: (1) An organization of the chapters by families of algorithms:
exhaustive search, divide and conquer, etc. On the contrary, there is no chapter
devoted only to a systematic exposure of, say, algorithms on strings. Some of
these will be found in different chapters. (2) For each family of algorithms, an
introduction is given to the mathematical principles and the issues of a rigorous
design, with one or two pedagogical examples. (3) For the most part, the book
details 150 problems, spanning seven families of algorithms. For each problem, a
precise and progressive statement is given. More importantly, a complete solution
is detailed, with respect to the design principles that have been presented; often,
some classical errors are pointed out. Roughly speaking, two-thirds of the book
is devoted to the detailed rational construction of the solutions.

i i

i i
Taylor & Francis
Taylor & Francis Group
http://taylorandfrancis.com
i i

i i

Algorithm Design
A Methodological Approach
150 Problems and Detailed Solutions

Patrick Bosc, Marc Guyomard and Laurent Miclet

i i

i i
i i

i i

First edition published 2023


by CRC Press
6000 Broken Sound Parkway NW, Suite 300, Boca Raton, FL 33487-2742

and by CRC Press


4 Park Square, Milton Park, Abingdon, Oxon, OX14 4RN

© 2023 Patrick Bosc, Marc Guyomard and Laurent Miclet

CRC Press is an imprint of Taylor and Francis Group, LLC

Reasonable efforts have been made to publish reliable data and information, but the author and publisher cannot
assume responsibility for the validity of all materials or the consequences of their use. The authors and publishers have
attempted to trace the copyright holders of all material reproduced in this publication and apologize to copyright holders
if permission to publish in this form has not been obtained. If any copyright material has not been acknowledged please
write and let us know so we may rectify in any future reprint.

Except as permitted under U.S. Copyright Law, no part of this book may be reprinted, reproduced, transmitted, or utilized
in any form by any electronic, mechanical, or other means, now known or hereafter invented, including photocopying,
microfilming, and recording, or in any information storage or retrieval system, without written permission from the
publishers.

For permission to photocopy or use material electronically from this work, access www.copyright.com or contact the
Copyright Clearance Center, Inc. (CCC), 222 Rosewood Drive, Danvers, MA 01923, 978-750-8400. For works that are
not available on CCC please contact [email protected]

Trademark notice: Product or corporate names may be trademarks or registered trademarks and are used only for
identification and explanation without intent to infringe.

ISBN: 978-1-032-36941-9 (hbk)


ISBN: 978-1-032-36939-6 (pbk)
ISBN: 978-1-003-33459-0 (ebk)

DOI: 10.1201/b23251

Typeset in URWPalladio font


by KnowledgeWorks Global Ltd.

i i

i i
i i

i i

Contents

Preface ix

1 Mathematics and computer science: some useful notions 1


1.1 Reasoning and proving . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Propositional and predicate calculus . . . . . . . . . . . . . . . . . . . 1
1.1.2 Proof by contradiction . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.3 Proof by induction with one index . . . . . . . . . . . . . . . . . . . . 4
1.1.3.1 Proof by simple induction . . . . . . . . . . . . . . . . . . . 4
1.1.3.2 Proof by partial induction . . . . . . . . . . . . . . . . . . . 6
1.1.3.3 Proof by strong induction . . . . . . . . . . . . . . . . . . . . 6
1.1.4 Partition induction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.5 Foundation of the proof by induction . . . . . . . . . . . . . . . . . . 9
1.1.6 Proof by induction with several indexes . . . . . . . . . . . . . . . . . 9
1.2 Recurrence relations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2.1 Generalities, examples and closed forms . . . . . . . . . . . . . . . . 10
1.2.2 Establishing and computing a recurrence relation . . . . . . . . . . . 11
1.2.2.1 Principles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.2.2.2 Some examples . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.2.2.3 Designing the algorithm associated with a recurrence . . . 14
1.3 Recurrence, induction, recursion, etc. . . . . . . . . . . . . . . . . . . . . . . 15
1.4 Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.4.1 Basic notations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.4.2 Definition of sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.4.3 Operations on sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.4.4 Special sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.4.5 Relations, functions and arrays . . . . . . . . . . . . . . . . . . . . . . 18
1.4.5.1 Relations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.4.5.2 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.4.5.3 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.4.6 Bags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.4.7 Cartesian product and inductive structures . . . . . . . . . . . . . . . 20
1.4.8 Strings and sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.5 Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.5.1 Directed graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.5.2 Undirected graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.5.3 Weighted graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.6 Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.7 Priority queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.7.1 Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.7.2 Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.8 FIFO and LIFO queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
1.9 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

v
i i

i i
i i

i i

vi Contents

1.10 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

2 Complexity of an algorithm 71
2.1 Reminders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.1.1 Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.1.2 Algorithmics, complexity of an algorithm . . . . . . . . . . . . . . . . 71
2.1.3 Minimum and maximum complexity of an algorithm . . . . . . . . . 73
2.1.4 Orders of growth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.1.5 Some examples of complexity . . . . . . . . . . . . . . . . . . . . . . . 76
2.1.6 About elementary operations . . . . . . . . . . . . . . . . . . . . . . . 77
2.1.7 Practical computing time . . . . . . . . . . . . . . . . . . . . . . . . . 77
2.1.8 Pseudo-polynomial problems . . . . . . . . . . . . . . . . . . . . . . . 78
2.2 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
2.3 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

3 Specification, invariants, and iteration 93


3.1 Principle for the construction of loops by invariant . . . . . . . . . . . . . . 93
3.2 An introductory example: the Euclidian division . . . . . . . . . . . . . . . . 95
3.3 Useful techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.3.1 Sequential composition . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.3.2 Predicate strengthening and weakening . . . . . . . . . . . . . . . . . 98
3.3.3 Strengthening by the introduction of programming variables . . . . 98
3.4 Heuristics for the discovery of invariants . . . . . . . . . . . . . . . . . . . . 99
3.4.1 Breakup of the postcondition . . . . . . . . . . . . . . . . . . . . . . . 99
3.4.2 Hypothesis of the work carried out partly . . . . . . . . . . . . . . . . 101
3.4.3 Strengthening the invariant . . . . . . . . . . . . . . . . . . . . . . . . 103
3.5 About bounded linear search . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
3.5.1 An example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
3.5.2 Special case and related pattern . . . . . . . . . . . . . . . . . . . . . . 109
3.6 Some key points to develop a loop . . . . . . . . . . . . . . . . . . . . . . . . 110
3.7 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
3.8 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

4 Reduce and conquer, recursion 157


4.1 A few reminders about recursion . . . . . . . . . . . . . . . . . . . . . . . . . 157
4.2 Recurrence relation and recursion . . . . . . . . . . . . . . . . . . . . . . . . 158
4.3 “Reduce and conquer” and its complexity . . . . . . . . . . . . . . . . . . . 159
4.3.1 Presentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
4.3.2 Example 1: the spiral pattern . . . . . . . . . . . . . . . . . . . . . . . 162
4.3.3 Example 2: Hanoi towers . . . . . . . . . . . . . . . . . . . . . . . . . 164
4.4 What should be reminded for “Reduce and conquer” . . . . . . . . . . . . . 166
4.5 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
4.6 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

5 Generate and test 197


5.1 Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
5.1.1 Principle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
5.1.2 Functions and related frames . . . . . . . . . . . . . . . . . . . . . . . 202
5.1.2.1 Total functions . . . . . . . . . . . . . . . . . . . . . . . . . . 202
5.1.2.2 The case of partial functions . . . . . . . . . . . . . . . . . . 207
5.1.3 Patterns for “Generate and test” . . . . . . . . . . . . . . . . . . . . . 210

i i

i i
i i

i i

Contents vii

5.1.3.1 Patterns derived from “AllSolutions” . . . . . . . . . . . . . 210


5.1.3.2 Patterns derived from “OptimalSolution” . . . . . . . . . . 212
5.1.3.3 Patterns derived from “OneSolution” . . . . . . . . . . . . . 212
5.1.3.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
5.2 An example: the optimal partition of an array . . . . . . . . . . . . . . . . . 215
5.2.1 The basic problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
5.2.2 The initial problem with a strengthened precondition and a strength-
ened postcondition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
5.2.3 The initial problem with a strengthened precondition . . . . . . . . . 221
5.3 What should be remembered from “Generate and test” . . . . . . . . . . . . 223
5.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
5.5 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

6 Branch and bound 307


6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
6.1.1 Branch and bound: the principle . . . . . . . . . . . . . . . . . . . . . 307
6.1.1.1 The separation phase . . . . . . . . . . . . . . . . . . . . . . 308
6.1.1.2 The selection phase . . . . . . . . . . . . . . . . . . . . . . . 308
6.1.1.3 The evaluation phase . . . . . . . . . . . . . . . . . . . . . . 309
6.1.2 The generic “Branch and bound” algorithm . . . . . . . . . . . . . . . 310
6.1.2.1 The priority queue . . . . . . . . . . . . . . . . . . . . . . . . 310
6.1.2.2 Construction of the generic “Branch and bound” algorithm 310
6.1.2.3 The generic “Branch and bound” algorithm itself . . . . . . 311
6.1.3 An interesting special case for the functions f∗ and f . . . . . . . . . . 312
6.1.4 An example: the traveling salesman . . . . . . . . . . . . . . . . . . . 314
6.1.4.1 Initial choices . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
6.1.4.2 The algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . 314
6.1.4.3 First case study: the zero heuristic function . . . . . . . . . 316
6.1.4.4 Second case study: uniform cost . . . . . . . . . . . . . . . . 318
6.2 What should be remembered about the “Branch and bound” approach . . . 320
6.3 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
6.4 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327

7 Greedy algorithms 335


7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
7.1.1 Presentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
7.1.2 Proving that a greedy algorithm is exact or optimal . . . . . . . . . . 336
7.1.3 An example: task scheduling on a photocopier . . . . . . . . . . . . . 336
7.1.4 The “lead run” method . . . . . . . . . . . . . . . . . . . . . . . . . . 336
7.1.5 Proof a posteriori: the transformation technique . . . . . . . . . . . . . 340
7.2 What to remember about greedy methods . . . . . . . . . . . . . . . . . . . 341
7.3 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
7.4 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375

8 Divide and conquer 415


8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
8.1.1 Presentation and principle . . . . . . . . . . . . . . . . . . . . . . . . . 415
8.1.2 An example: merge-sort . . . . . . . . . . . . . . . . . . . . . . . . . . 416
8.1.3 General pattern for “Divide and conquer” . . . . . . . . . . . . . . . 418
8.1.4 A typology of “Divide and conquer” algorithms . . . . . . . . . . . . 419
8.1.5 Complexity of “Divide and conquer” . . . . . . . . . . . . . . . . . . 420

i i

i i
i i

i i

viii Contents

8.1.5.1 Introduction to the master theorem . . . . . . . . . . . . . . 420


8.1.5.2 Other types of recurrence equations . . . . . . . . . . . . . . 423
8.1.6 About the size of the problem . . . . . . . . . . . . . . . . . . . . . . . 424
8.2 What to remember about the DaC approach . . . . . . . . . . . . . . . . . . 424
8.3 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
8.4 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491

9 Dynamic programming 631


9.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 631
9.2 An example: the longest sub-sequence common to two sequences . . . . . . 635
9.3 What should be remembered to apply dynamic programming . . . . . . . . 639
9.4 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640
9.4.1 Cutting and sharing: one-dimensional problems . . . . . . . . . . . . 640
9.4.2 Cutting and sharing: two-dimensional problems . . . . . . . . . . . . 648
9.4.3 Graphs and trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 660
9.4.4 Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673
9.4.4.1 Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674
9.4.4.2 The problem . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
9.4.5 Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 681
9.4.6 Games . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686
9.4.7 Pseudo-polynomial problems . . . . . . . . . . . . . . . . . . . . . . 689
9.5 Solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 690

Notations 791

List of problems 793

Bibliography 797

Index 799

i i

i i
i i

i i

Preface

What this book is


This is a book about algorithmics, and its goal is to teach this field and to help instruc-
tors to teach it. Algorithmics is, as generally admitted, “the science and art of designing
algorithms to solve a given problem, preferably in minimal time”. Consequently, this book
aims at presenting efficient methods to design algorithms—mainly through examples.
It is structured according to two rules:
• Each chapter is devoted to a methodology of algorithm design, which can be applied
to different data structures. For example, the chapter “Dynamic Programming” pro-
poses problems on 2D arrays, on trees, on strings, as well as on graphs. As a matter of
fact, some problems are proposed in two different chapters since they can be solved in
different ways—which is particularly interesting to study. We have taken care for each
problem to highlight different aspects of the methodologies: none of the 148 problems
is just a rewriting of another one. The particular interest of each problem is shortly
described at its beginning.
• Each chapter begins by an informal presentation on an example, then gives the techni-
cal bases of the methodology, and exposes a complete example. Then follows the main
part, composed of detailed problems with their complete solution. Somewhat complex
problems are tackled in a progressive manner in order to highlight the constructive
process of the analysis leading to the solution. This solution is itself exhaustively de-
tailed, concluding in programs written in pseudo-code. We do not give the coding in
a specific programming language since the transcription from this pseudo-code into
any usual one is generally straightforward. The correctness of all algorithms has been
tested through code written by the authors.

What this book is not


This book is not a “data structures and algorithms” textbook. There are some necessary
reminders about data structures in the first chapter, and they are intensively used in the
book, but their actual implementation is not described. The reader is supposed to be aware
of the good packages and classes she or he can use in her or his favorite programming
language.
It is not a textbook on algorithms either, since it does not describe systematically how
to solve a general problem, such as sorting or substring matching. It indeed exposes and
solves a great variety of problems, but all the examples have been designed to help the
reader to understand what is the efficient methodology that can be applied—not to give
an exhaustive list.
Let us qualify it as “an example-based book on algorithm design methodologies”.

ix
i i

i i
i i

i i

x Preface

What this book wishes to be


Algorithmics is, as we have said, “the science and art of designing algorithms”. We wish
the reader to reinforce these two skills. We would firstly like, when confronted with a
new problem, the reader would have an “intuition” of the method to use, thanks to the
numerous examples of the book. This would be the “art” or “craft” side of the matter.
Secondly, we wish the reader to become able to prove the efficiency of the chosen method,
as opposed to a naïve or more straightforward method. This would be the “science” side.
We have chosen to teach through examples, but it does not mean that we forsake rigour
and mathematical proofs. Designing an algorithm is basically using methodically well-
founded concepts, such as recurrence and computational complexity. There are generally
lots of very nice problems in the middle and at the end of the chapters of the classical
textbooks, but, too often, only those in the text itself are explicitly solved. Most of the
time, the solution (if any) is given as a hint which is more a “haha” or a white rabbit out
of a top-hat than an explanation. It baffles the reader and makes her or him feel that an
algorithmic problem is just a brain-teaser. On the contrary, we believe that the rigorous
and progressive construction of the solution will help the reader to master the designing
process. Both deduction and induction are reasoning ways to be practiced in algorithmics
as in many (if not all) fields.
We give a high value to the construction of the solutions: their total length is largely
more than half of the book. Why is it so? One could argue, as we have read at the head
of lecture notes on algorithms: “If you’re a student, seeing the solution will rob you of
the experience of solving the problem yourself, which is the only way to learn the mate-
rial. If you’re an instructor, you shouldn’t assign problems that you can’t solve yourself!”
Well, this may be true for easy math exercises or puzzle quizzes, but we disagree with this
opinion as far as algorithmics is concerned.
Murray Gell-Mann used to call the “Richard Feynman Problem-Solving Algorithm”
the following sequence: (i) write down the problem; (ii) think very hard; (iii) write down
the answer. Unfortunately, no student can use her or his fresh knowledge in such a way.
Understanding an example during the course is different from reconstructing the process
for solving a different problem. When the solution is explained, being not only a recurrence
equation or a hint on the invariant, it is obviously fruitful for the student to follow its
construction.
Lastly, let’s take a comparison with the game of Sudoku: if you do not succeed in solv-
ing a certain puzzle, reading the solution grid doesn’t bring anything in terms of learning.
On the contrary, if the solution is commented (as it rarely happens) you may discover and
memorize a new technique by the example. Concerning the instructors, a reference solu-
tion can also be very useful: the actual challenge is not “can you solve it yourself?”, but
rather “can you find a progressive and helping way to explain the solution?”.

Who must read it ?


This is definitely not a book for beginners in computer science. Some knowledge of classi-
cal mathematics is required, as well as a solid initial formation in programming languages
and data structures. It may be used by some classes of undergraduate students; however,
it is obviously more suited for graduate studies, where it can be indicated as a textbook in
algorithmics. It will also interest computer science professionals as a reference book.
The computer science instructors will find in this book a lot of useful material: the intro-
duction of each chapter can be used as a reference for a lesson; the abundance of problems
(along with their detailed solutions) will be an—almost—endless source for presenting to

i i

i i
i i

i i

Preface xi

the students examples of methodical design. No problem is the exact rewriting of another
one, and there is full freedom to transpose each of them in a different grounding.

Contents
As already pointed out, this book is organised to successively present the main methodolo-
gies of algorithm design. However, the first chapter “Mathematics and computer science:
some useful notions” recalls mathematical bases, mostly proof principles, with an insis-
tance on induction (recurrence) and combinatorial counting; it also gives a reminder in
data structures (sets, bags, graphs, files, etc.) and provides 21 short problems and solu-
tions. With the same goal, the chapter “Complexity of an algorithm” is a refresher on the
basic ideas of the field and proposes seven problems, the last one being non-classical.
In the chapter “Specification, invariants, and iteration”, we expose the principles of the
rational design of a while loop and give 15 problems, some rather easy and others quite dif-
ficult. The (lengthy) solutions of the latter are examples of what we have previously called
“practicing both deduction and induction”. The following chapter, “Reduce and conquer,
recursion”, shows how to design recursive algorithms with the help of eight classical prob-
lems. We particularly insist on showing how the proof by induction theory can be applied
to certify the exactness of a recursive procedure.
Chapter 5 describes the “Generate and test” methodology, also called “backtracking”.
We show how to obtain a recursive enumeration of the solutions to a combinatorial prob-
lem; we give the different patterns of a program according to its combinatorial nature. We
give general principles to prune the tree of the solutions and illustrate them with 18 prob-
lems. The following chapter tackles the same kind of problems, but with the “Branch and
bound” iterative technique. Here, four classical problems are given and resolved step by
step.
Chapter 7 is devoted to “Greedy algorithms”, suited to the same kind of combinatorial
problems, but with no backtracking. The proof that they produce a good solution is ob-
viously important to elaborate: we give the usual manners to check it, with 14 problems,
some of which require an elaborate solution.
In Chapter 8, the fruitful “Divide and conquer” methodology is carefully analyzed
and an original typology of the related algorithms is given. Their detailed construction is
explained throughout 29 problems—some of them rather sophisticated.
Finally, Chapter 9 describes the “Dynamic programming” approach, often very efficient
to elaborate an optimal (polynomial) solution to a combinatorial (exponential) problem.
The richness and variety of its applications is displayed through 32 problems. Again here,
some are classics and some are unexpected, some are easy and some are difficult.
To sum up, we describe seven methodologies of algorithm design, illustrated by 148
problems. Each problem is precisely described, often in a progressive organization, and
the complete solution up to the pseudo-code is given in a methodical and rational manner.

Helping the reader


The section “Notations”, on page 791 and following, describes the symbols we use in the
mathematical formulas and in the algorithms. The reader is invited to refer to these pages
every time she or he feels uneasy about the meaning of a symbol.

The problem and the solution are generally divided into several questions. A marginal
note recalls the number of the problem and the number of the question in the problem. For
example, this margin note would indicate the beginning of question 3 of problem 42. In the 42 - Q 3

i i

i i
i i

i i

xii Preface

solution, the answer to question 3 would be indicated in the same way with an A instead
of a Q.

Every problem is given a double evaluation: one for its intrinsic interest, the other for
◦ ◦

its difficulty. There are four levels of increasing interest denoted by ◦ ◦
◦ ◦ ◦ ◦
◦ and four
• •

levels of difficulty denoted by • •
• • • •
• .
Attributing an intrinsic interest to a problem is a rather arbitrary task. We have used a
mix of several criteria, the main being its pedagogical quality in illustrating the method-
ology of the chapter. The difficulty level takes into account the manner of describing the
problem; an intrisically difficult problem can be gently proposed when its description is
written as a gradual series of easier questions.

Sources and bibliography


The bibliography at the end of this book is deliberately composed of almost only textbooks.
In other terms, we have not sought to quote the original articles where the presented al-
gorithms have been published (if they have been). The reader interested in the personal
history of such-and-such algorithm can consult the reference books by D. Knuth [22],
G. Brassard and P. Bratley [8], T. Cormen et al. [9], E. Horowitz et al. [19], D. Stinson [33],
S. Russell [31] and P. Norvig [31].
No algorithm in this book is completely original, but the problem formulation leading
to the algorithm can be: sometimes it comes from the textbooks of the bibliography, it is
a “folk” formulation, and sometimes it is our own. Every problem has nevertheless been
rewritten and segmented in questions for pedagogical reasons. Many among them have in-
deed been “tested” on students by the authors and their colleagues at University of Rennes
1, France. Our originality does not lie in the material itself, but in formulating the problem
and in carefully constructing its solution and at times in investigating the problem further
than usual.
In his quite interesting book Problem on Algorithms, I. Parberry [28] gives a richly an-
notated bibliography on about 30 textbooks in the English language; the interested reader
will take advantage of his advice. We are less aware of the English language literature on
algorithms than of the French, so we apologize that this paragraph may be somewhat la-
cunar. We have the highest esteem for the books by T. Cormen et al. [9], J. Kleinberg and
E. Tardos [21] and D. Knuth [22], the first two being suitable for beginners up to master’s
students, the latter exhausive and brillant but more difficult to read. The books by R. John-
sonbaugh and M. Shaeffer [20], E. Horowitz et al. [19], S. Baase and A. Van Gelder [3],
R. Neapolitan and K. Naimipour [27], A. Levitin [24], S. Skenia [32] and T. Goodrich and
R. Tamassia [13] are also general purpose texts of high interest. More recently, the four
books by T. Roughgarden [30] have brought a nice contribution to the subject.
Coming to less comprehensive books, U. Manber [25], D. Gries [16], J. Edmonds [12]
and J. Bentley [4, 5] have written quite interesting texts. The book by R. Graham, D. Knuth
and O. Patashnik is a wonderful exposure to the so-called concrete mathematics and [23]
gives a solid mathematical foundation to all domains of computer science. The books by G.
Valiente [34] (trees and graphs) and M. Crochemore [10] (strings) are specialized on certain
data structures. On the program construction itself, the book by P. Berlioux and P. Bizard [6]
is a reference. If you can read French. . . and find them, the books by J. Arsac—for
example [2]—have, up to our knowledge, no equivalent one in English.

i i

i i
i i

i i

1
Mathematics and computer science: some useful
notions

Who can, does; who cannot do, teaches;


who cannot teach, teaches teachers.

P. Erdős

Throughout this book, the framework considered is that of a progressive development


of algorithms in which each step relies on a safe construction. In this perspective, a variety
of tools are presented, intended for ensuring the validity of the constructions that are used.
Moreover, during this development process, programs often call, on the one hand, on con-
ditions expressed in the language of predicates, and on the other hand on data structures
specified in the language of set theory. However, this approach is not sufficient to reach ef-
ficient solutions (especially from a temporal complexity viewpoint—see Chapter 2). Some
refinement is then needed on the basis of tailor-made data structures. This is why this in-
troduction is devoted to diverse mathematical tools and objects, as well as to the principal
data structures used later on.
This chapter starts with notions related to reasonings frequently used in the remain-
der of the book: (i) propositional and predicate calculus, (ii) proof by contradiction and
finally (iii) mathematical induction. Then, we raise the issue of recurrence relations (and
the associated computations) which are a prominent part in Chapter 9. We take this oppor-
tunity to make explicit our acceptance of the terms recurrence, induction and recursion.
The remainder of this chapter is organized mainly around the notion of set and we review
the concepts of Cartesian product, multiset, relation, function as well as their principal
related operators. We are interested in lists seen as an illustration of the notion of induc-
tive structure derived from that of Cartesian product. We also focus on trees and graphs
which originate numerous problems, before closing the chapter with the concept of prior-
ity queue whose interest will mainly appear in chapters 6 and 7, respectively dedicated to
branch and bound technique and greedy algorithms.
For the interested reader, a thorough construction of classical logic and set theory can be
found in [1]. As to formal refinement of data structures, [17, 7] can be profitably consulted.

1.1 Reasoning and proving


1.1.1 Propositional and predicate calculus
The predefined set B is defined as B =b {true, false}. These two values will sometimes be
referred as T/F or t/f in arrays for space purposes. The “iff” expression stands for the

DOI: 10.1201/b23251-1 1
i i

i i
i i

i i

2 Mathematics and computer science: some useful notions

equivalence relation “if and only if” and can also be written “≡”. If a and b are elements
of B, then:

• conjunction: “a and b” is true iff both a and b are true.

• disjunction: “a or b” is false iff both a and b are false.


• negation: “not a” is true iff a is false.
• logical implication: “a ⇒ b” is false iff both not a and b are false.

• logical equivalence: “a ⇔ b” is true iff a and b share the same value.

The existence of undefined expressions (for instance due to accessing a function out
of its domain or dividing by 0) requires the use of “short-circuit” operators stopping the
evaluation as soon as the result is known. The two short-circuit operators “and then” and
“or else” are defined as follows:
• If a and b are defined:
a and then b ⇔ a and b.
a or else b ⇔ a or b.
• If a is defined whereas b is not:
false and then b ⇔ false.
true and then b is undefined
false or else b is undefined.
true or else b ⇔ true.
• If a is undefined, then whatever b:
a and then b is undefined
a or else b is undefined.
In the context of predicate calculus, quantifiers ∀ and ∃ are defined as follows:
• ”∀x · (D ⇒ T (x))” is true iff, for any x in domain D then T (x) is true. Therefore, this
formula is true if D is empty.

• ”∃x · (D and T (x))” is true iff there is an x in domain D such that T (x) is true. Therefore,
this formula is false if D is empty.
The notation ∄ is a shorthand for not ∃.
The double equivalence:

(a ⇒ b) ≡ (not a or b) ≡ (not b ⇒ not a)

is the foundation for reasoning by contraposition, where the validity of the implication
not Q ⇒ not P is proven to show that P implies Q.

i i

i i
i i

i i

Reasoning and proving 3

1.1.2 Proof by contradiction


The proof by contradiction relies on two principles of propositional logic:

• excluded middle, claiming that a property which is not false is necessarily true, then its
conjunction with its negation is false,
• the definition of implication: (P ⇒ Q) =
b (not P or Q).

A consequence of these two properties is that (not P ⇒ false) is equivalent to P, which


ensures the validity of the proof by contradiction. In effect:

(not P ⇒ false)
⇔ definition of the implication
(not(not P) or false)
⇔ involutivity of the negation
(P or false)
⇔ property of the disjunction
P.

Proving a proposition P by contradiction encompasses two steps:


1. not P is assumed (i.e. the falsity of P),
2. a contradiction between this assumption and one of its entailments is pointed out.

It is important to note that when no contradiction can be exhibited, nothing can be con-
cluded as to P (neither truth nor falsity).

First example
Let us consider the following proposition P: “there is no smallest rational number strictly
greater than 0”. In order to prove P by contradiction, the negation of P is assumed, namely:
“there is a smallest rational number strictly positive r”. From the negation of P, a contra-
diction is searched.
Let s = r/2. By construction, s is a rational number strictly greater than 0 and strictly
smaller than r. This claim is in opposition to P, which states that r is the smallest rational
number.
Thus, it can be concluded that proposition P is for sure true and that there is no smallest
strictly positive rational number.

Second example
One would like to demonstrate that there is no rational number whose square is 2, in other
words one wants to prove the following proposition P “the square root of 2 is an irrational
number”.
Proof. One first assume that there is an element x = p/q of Q+ (the set of positive rational
numbers) such that x2 = 2, with p and q are relatively prime numbers (i.e. p/q is an
irreducible fraction). One has:

i i

i i
i i

i i

4 Mathematics and computer science: some useful notions


 2
p
=2
q
⇔ arithmetics
p2 = 2q2
⇔ reformulation
2 divides p2
⇔ any even square number is the square of an even number
2 divides p
⇔ p = 2p′
2 2
∃p · (p = 4p = 2q )
′ ′2

⇔ reformulation
2 is a divider of q2
⇔ any even square number is the square of an even number
2 is a divider of q.
One can then deduce that 2 is a divider of both p and q, which entails that p and q
are not relatively prime numbers which is in opposition to the fact p/q is an irreducible
fraction.
In a similar way, it is possible to demonstrate that there is no negative rational num-
ber whose square is 2, otherwise its opposite would be a positive rational number whose
square would be 2. As a consequence, the square root of 2 is an irrational number 1 .

1.1.3 Proof by induction with one index


In this section, we deal with another type of demonstration, namely proof by induction with
a single index. We successively review its most usual versions, in particular those used in
chapters 4 and 8.

1.1.3.1 Proof by simple induction


This type of demonstration is also called proof by weak induction. Let us consider a prop-
erty P(n), depending on the positive integer n ∈ N to be proven.

If the following two properties can be demonstrated:

Initialization P(n0 ) is true for a given n0 ∈ N


Induction ∀n · ((n ⩾ n0 and P(n)) ⇒ P(n + 1))

then:
Conclusion ∀n · (n ⩾ n0 ⇒ P(n))

The fact that P(n) is assumed to be true constitutes the induction hypothesis, in order to
(try to) prove P(n + 1). The initialization is also called the base.
Proof. The correction of the proof by induction can be made by reasoning by contradiction.
Let X = {k ∈ N | k ⩾ n0 and P(k) = false}, be the set of integers greater than k0 such that
property P(k) is false. If X is non-empty, it encompasses a smallest element (since in any
set of integers there is an element smaller than all the others), denoted as m. From the
1 This proof was made by Euclide, about 250 B.C.

i i

i i
i i

i i

Reasoning and proving 5

initialization, it is known that m > n0 . Therefore, m − 1 ⩾ n0 and since m is the smallest


element in X, m − 1 ̸∈ X and P(m − 1) is true. Using the induction step, it can be deduced
that P(m) is true, which contradicts m ∈ X. Consequently, X is empty.

Example
Let us prove by induction the formula:

X
n
n(n + 1)
i= .
2
i=1

Initialization This formula is true for n0 = 1, since we have:


1
X
i=1
i=1

and for n0 = 1 the formula yields:

1(1 + 1)
=1
2
which is the same result.
Induction Let us assume that the formula is true for n, with n ⩾ 1, and let us try to prove
that it is still true for (n + 1). In other words, let us try to prove that the induction
formula
Xn
n(n + 1)
i=
2
i=1

entails
X
n+1
(n + 1)(n + 2)
i= .
2
i=1

Indeed, it is correct since:

X
n+1
i
i=1
= ! arithmetics ((n + 1) > 1)
X
n
i + (n + 1)
i=1
= induction hypothesis
n(n + 1)
+ (n + 1)
2
= arithmetics
(n + 1)(n + 2)
.
2

Conclusion The formula is true for n0 = 1. In addition, if it is true for n (where n ⩾ 1),
then it is true for (n + 1). Finally, this demonstration by induction has proven that the
formula is true for any strictly positive integer.

i i

i i
i i

i i

6 Mathematics and computer science: some useful notions

Remark
This demonstration may also be used to prove a result concerning negative integers: if a
formula is true for n = 0, and if the fact that it is true for −n, where n ∈ N, entails that it is
true for (−n − 1), then it is true for any negative integer.

1.1.3.2 Proof by partial induction


P(n) denotes a property depending on an integer n ∈ N.

If it is possible to demonstrate the two following properties:

Initialization P(1) is true


Induction ∀n · ((k ∈ N and n = 2k and P(n)) ⇒ P(2n))
then:
Conclusion ∀n · ((k ∈ N and n = 2k ) ⇒ P(2n))

This variant concerns a proposition on integers that are powers of 2. It is also possible
to prove a property on even numbers, or more generally on any infinite subset of N that
may be built by induction (see section 1.3, page 15).

1.1.3.3 Proof by strong induction


The proof by strong (or total or generalized) induction seems to be more difficult to apply
than the regular induction. However it is appropriate and rightly often used. Here again,
one considers a property P(n), depending on an integer n ∈ N.

If it is possible to prove the following property:


Induction ∀n · ((n ⩾ n0 and ∀m · (m ∈ n0 .. n − 1 ⇒ P(m))) ⇒ P(n))
then:
Conclusion ∀n · (n ⩾ n0 ⇒ P(n))

The correctness of this demonstration pattern directly stems from that of the regular
(simple) induction.

Example
Let us prove the following property using strong induction:
Any integer strictly greater than 1 is the product of several prime numbers.
It is assumed that 1 (also called unity) is a prime number.

Induction Let us assume that any integer m less than n and greater than or equal to n0 = 2
is the product of several prime numbers. For n, two exclusive cases are singled out:
• n is prime and then the product of unity and itself, therefore the product of two
prime numbers.

i i

i i
i i

i i

Reasoning and proving 7

• n has a divisor d, other than 1 and itself. According to the induction hypothesis,
one has n = d · p, where d and p are two integers less than or equal to n and
strictly greater than 1. Each of them is the product of several prime numbers, and
n is also the product of several prime numbers.
Conclusion Any integer strictly greater than 1 is the product of several prime numbers.

1.1.4 Partition induction


An important type of proof by induction is partition induction (also called DaC induction
due to its role in the technique for designing algorithms called “Divide and conquer”
which is the subject of Chapter 8).
One considers a predicate P(i, s) depending on the two integers i and s such that i ⩽ s.
The partition induction consists of proving that P holds over any interval I = i .. s: (i) by
proving it for any element of I, and (ii) by proving that the correctness of P over each of
the intervals I1 = i .. m and I2 = m + 1 .. s (partition of I) entails that of P over I.

If it is possible to prove the two following properties:


Initialization ∀i · (i ∈ N ⇒ P(i, i))
Induction ∀(i, m, s) · ((i ∈ N and s ∈ N and m ∈ N and m ∈ i .. s −
1 and P(i, m) and P(m + 1, s)) ⇒ P(i, s))
then:
Conclusion ∀(i, s) · ((i ∈ N and s ∈ N and i ⩽ s) ⇒ P(i, s))

The correctness of this demonstration procedure is now demonstrated.


Proof. We proceed by contradiction. Let F be the set of pairs for which P does not hold, i.e.:

F = {(i, s) | (i, s) ∈ N × N and i ⩽ s and not P(i, s)}.


Assuming that F ̸= ∅, let (j, k) be one of the pairs of F for which l = (k − j + 1) is minimum.
From the initialization, l ̸= 1 and there is at least one value m such that j ⩽ m < k. The
pairs (j, m) and (m + 1, k) do not belong to F since (m − j + 1) < l and (k − (m + 1) +
1) < l). It comes that both predicates P(j, m) and P(m + 1, k) hold. From the induction,
it can be deduced that P(j, k) holds, which contradicts (j, k) ∈ F. Thus F = ∅ and ∀(i, s) ·
(i ∈ N and s ∈ N and i ⩽ s ⇒ P (i, s)).

Remarks
1. Partition induction must be based on an initialization P(i, s) for which s − i + 1 = 1. In
particular, it cannot rely on an initialization where s − i + 1 = 0. As a matter of fact, in
such a case there is no value for m such that i ⩽ m < s. Similarly, the induction cannot
be based on an initialization P(i, s) such that s − i + 1 > 1. Let us take the example of
P(i, i + 1) as the initialization and let us try to prove that P(i, i + 2) holds. The only two
possible values for m are m = i and m = i+1. If m = i, the first induction hypothesis is
P(i, i) and if m = i + 1, the second induction hypothesis is P(i + 2, i + 2). None of these
predicates is an instance of the initialization and then the related pattern is invalid.
2. The regular simple induction is a special case of partition induction obtained by taking
m = i.

i i

i i
i i

i i

8 Mathematics and computer science: some useful notions

Example
One will once more demonstrate that:

X
n
n · (n + 1)
k=
2
k=1
P
but, this time, using the technique of partition induction. Let us denote S(i, s) = sk=i k
and call P(i, s) the predicate S(i, s) = (s2 − i2 + s + i)/2. If we succeed in proving that
P(i, s) holds, we
P will have more specifically P(1, n) and it can be concluded that S(1, n) =
(n2 + n)/2 = n k=1 k.
Pi
Initialization For any i, one has: S(i, i) = (i2 − i2 + i + i)/2 = i = k=i k.
Induction hypothesis Let us choose m = ⌊(i + s)/2⌋. One has:

m2 − i2 + m + i
• S (i, m) = ,
2
s2 − (m + 1)2 + m + 1 + i
• S (m + 1, s) = .
2
Induction itself Let us demonstrate that, on the basis of the two above hypotheses,
S(i, s) = (s2 − i2 + s + i)/2 for i < s:

S(i, s)
= definition
X
s
k
k=i
= arithmetics (i < s), with m = ⌊(i + s)/2⌋
X
m X
s
k+ k
k=i k=m+1
= definition
S (i, m) + S (m + 1, s)
= induction hypothesis
m2 − i2 + m + i s2 − (m + 1)2 + s + m + 1
+
2 2
= arithmetics
s 2 − i2 + s + i
2

X
s
s 2 − i2 + s + i
Conclusion k= .
2
k=i

Remarks
1. One trick used in the example above consists in replacing a constant (1 as the lower
bound of the quantification) by a variable (i). Such a technique will be encountered
for the construction of iterations in the context of the “strengthening by introducing
variables” (confer section 3.3.3, page 98) where more than necessary is proven in order
to facilitate (in general) the demonstration.

i i

i i
i i

i i

Reasoning and proving 9

2. When used for the design of algorithms called “Divide and conquer”, the major dif-
ficulty with partition induction lies in the discovery of induction hypotheses and the
way they may be combined to make the final solution, what will be called “gathering
step”.

1.1.5 Foundation of the proof by induction


In the preceding paragraphs, some proofs by induction have been exhibited, all of them
relying on the natural order of integers. It is interesting and useful to extend this type of
proof to properties no longer characterized by an integer but by an element in a totally
ordered set.
The proof by induction comes from the following property.

Property 1:
Let E be a totally ordered set by means of the relation ⪯ and P be a property depending on the
element x of E. If the following property holds:

∀x · (x ∈ E and ∀y · ((y ∈ E and y ⪯ x and P(y)) ⇒ P(x))


then ∀x · (x ∈ E ⇒ P(x)).

Proving this property is achieved as a simple transposition of that given in section 1.1.3
for simple induction.

1.1.6 Proof by induction with several indexes


Property 1 stated in the previous section allows (in particular) the justification of a proof by
induction for properties depending on several integer indexes. In the case of two indexes,
one considers a property (or formula) P(m, n) depending on the two integers m and n,
which is to be proven by induction. Several patterns can be used, among which:

If it is possible to prove the two following properties:


Initialization ∀i · (i ∈ N ⇒ P(i, 0)) and ∀j · (j ∈ N ⇒ P(0, j))
Induction ∀(i, j) · ((i ∈ N1 and j ∈ N1 and P(i − 1, j) and P(i, j − 1)) ⇒ P(i, j)
then:
Conclusion ∀(m, n) · ((m ∈ N and n ∈ N) ⇒ P(m, n)).

The correctness of this pattern stems from the fact the set N2 of pairs of integers is
equipped with a total order (induced by the total order over N), defined as follows:

b a < c or (a = c and b ⩽ d).


(a, b) ⪯ (c, d) =

Let us consider q the point whose coordinates are denoted by (i, j). The pattern proposed
above aims at assessing that if P holds at any point: (i) of the rectangle 0 .. i − 1, 0 .. j − 1 (the
cases when i = 0 or j = 0 are covered by the initialization), (ii) from (i, 0) to (i, j − 1) of row
i and (iii) (0, j) to (i − 1, j) of column j, then P holds at point (i, j) as well. In other words, if
P holds at any point “lower” (according to ⪯) than point (i, j), P(i, j) holds as well, which
corresponds to the instance of property 1 for the pairs of (N2 , ⪯).

i i

i i
i i

i i

10 Mathematics and computer science: some useful notions

This demonstration pattern is used in problem 21, page 45. It may be transposed to N1 if
needed with an initialization referring to N1 and the induction with N1 −{1}, the conclusion
being:

∀(m, n) · ((m ∈ N1 and n ∈ N1 ) ⇒ P(m, n)).


Others patterns are applicable to prove an induction with two (or more) indexes. Their
correctness is ensured inasmuch as they comply with property 1 for a given order (see
problem 8, page 37).

1.2 Recurrence relations


After introducing the concept of recurrence relation, several examples are provided and
the topic of establishing a recurrence relation and its related algorithmic calculation is dealt
with.

1.2.1 Generalities, examples and closed forms


By definition, a series (also called a sequence) S(n), with n ∈ N, is defined by a recurrence
relation if, for n sufficiently large one has a relation of type: S(n) = f(S(n − 1), . . . , S(n−p)).
Moreover, it is necessary to identify values allowing for initializing the calculation of S.
Here only series valued as nonnegative integers are taken into account (especially because
they are associated with complexity calculations).
In the recurrence relation defining Fibonacci numbers:

F(1) = 1
F(2) = 1
F(n) = F(n − 1) + F(n − 2) n>2

or in the one giving Padovan numbers:

P(1) = 1
P(2) = 1
P(3) = 1
P(n) = P(n − 2) + P(n − 3) n>3

f is a linear function. On the other hand, the one appearing in the relation defining factori-
als (number of permutations in a set of n elements) is nonlinear:

Fact(1) = 1
Fact(n) = n · Fact(n − 1) n > 1.

Thanks to the theory of generative functions (see for example [14]), mathematics provide
powerful tools to find closed forms (i.e. nonrecurrent) for some series defined by means of
recurrence relations, especially when f is linear, but also in other cases. Thus, Fibonacci

i i

i i
i i

i i

Recurrence relations 11

sequence is expressed under closed form as:


" √ !n √ !n #
1 1+ 5 1− 5
F(n) = √ − n ⩾ 1.
5 2 2

Catalan numbers, which are the subject of problems 5, page 34, and 13, page 40, are
defined by the recurrence relation:

Cat(1) = 1
X
n−1
Cat(n) = Cat(i) · Cat(n − i) n>1
i=1

as well as by:

Cat(1) = 1
4n − 6
Cat(n) = · Cat(n − 1) n > 1.
n

It may also be expressed by the closed form 2 :


(2n − 2)! 1
Cat(n) = = · Cn−1
2n−2 n ⩾ 1.
(n − 1)! · n! n
From an algorithmic point of view, a closed form seems appealing since easy to com-
pute. However, if this choice is reasonable for computing the nth Catalan number, it may
be inappropriate as shown about Fibonacci numbers in problem 12, page 39.
A recurrence relation may serve as the definition of a series involving more than one
index. For instance, Ackerman numbers are defined by means of the following two index
nested recurrence:

A(0, n) = n + 1 n⩾0
A(m, 0) = A(m − 1, 1) m>0
A(m, n) = A(m − 1, A(m, n − 1)) m > 0 and n > 0.

Another example of two index recurrence is that of Stirling numbers, which correspond
to the number of partitions with p blocks of a set of n elements. Here, the recurrence is
much more simple than the previous one and Stirling numbers are studied in problem 16,
page 41.

1.2.2 Establishing and computing a recurrence relation


1.2.2.1 Principles
We now deal with the establishment and the computation of series defined by recurrence
relations. It turns out that numerous problems, for example related to enumeration, but
also to the calculation of the optimal value of a function (see Chapter 9), can be solved
in pointing out a recurrence allowing for computing the considered value. The recurrence
must be complete, i.e. any situation likely to happen must be taken into account.
2 It is assumed that closed forms may involve any type of quantifier, here the product underlying factorial

calculation.

i i

i i
i i

i i

12 Mathematics and computer science: some useful notions

As closed forms are rarely known, the computational procedure aims at building an
iterative program where a one (or more) dimensional array is used to store the successive
values of the considered series. This approach is discussed and justified in chapter 4.
According to the principle adopted, the value of a cell is calculated from those already
present in the array. Then the order for filling the array is of prime importance and the evo-
lution of the calculation strongly depends on dependence relationships between elements.
For one dimension recurrences, it is generally simple (increasing or decreasing index val-
ues), but multiple index recurrences require more attention. The examples given hereafter
illustrate the proposed approach.

1.2.2.2 Some examples


Single index recurrence: binary trees with n nodes
The objective is to compute nbBT (n) the number of binary trees (see section 1.6, page
27) that possess n nodes (including leaves). First, the recurrence defining this number is
defined. It can be observed that there is only one tree without nodes: the empty tree. For
establishing a recurrence for nbBT (n), a binary tree with n nodes is decomposed into
smaller trees. When n is positive, a tree with n nodes is made up of a root (one node),
possibly a left subtree with i nodes and possibly a right subtree with (n − i − 1) nodes. Let
us have a look at the possible ways to proceed to the decomposition:
• one can place no node in the left subtree (empty), which leads to nbBT (0)(= 1), and
(n − 1) nodes in the right subtree (by definition) with nbBT (n − 1) possibilities , which
makes finally nbBT (0) · nbBT (n − 1) cases,
• one can place a single node in the left subtree and (n − 2) nodes in the right subtree,
which leads to nbBT (1) · nbBT (n − 2) cases,
• ...
More generally, one place i nodes in the left subtree, thus nbBT (i) left subtrees, and (n−i−
1) nodes in the right subtree, thus nbBT (n − i − 1) right subtrees, which leads to nbBT (i) ·
nbBT (n − i − 1) such trees. This works for all values of i from 0 to (n − 1). Finally, the
number of trees with n nodes is:

nbBT (n) = nbBT (0) · nbBT (n − 1) + nbBT (1) · nbBT (n − 2) + · · ·


· · · + nbBT (i) · nbBT (n − i − 1) + · · ·
· · · + nbBT (n − 1) · nbBT (0)

from which comes:

nbBT (0) = 1
X
n−1
nbBT (n) = nbBT (i) · nbBT (n − i − 1) n ⩾ 1.
i=0

i i

i i
i i

i i

Recurrence relations 13

After having checked (by enumeration) that nbBT (1) = 1 and nbBT (2) = 2, the next
value is:
2
X
nbBT (3) = nbBT (i) · nbBT (n − i − 1)
i=0
= nbBT (0) · nbBT (2) + nbBT (1) · nbBT (1) + nbBT (2) · nbBT (0)
= 2 + 1 + 2 = 5.

Figure 1.1, page 13, shows all the binary trees for n ∈ 0 .. 3.

• • •

• •

• • • • •

• • • • • •

• • • •

Fig. 1.1 – Vizualization of all binary trees of size 0, 1, 2 and 3, in respective numbers: 1, 1, 2 and 5.

In the absence of additional information, the computation of nbBT (n) is achieved by


filling the array NBBT [0 .. n]. Since the value of nbBT (n) depends on lower index values,
the calculation is evolving according to increasing index values once the cell NBBT [0] is
initialized (with 1). The resulting procedure is the following:

1. constants
2. n ∈ N1 and n = . . .
3. variables
4. NBBT ∈ 0 .. n → N1
5. begin
6. NBBT [0] ← 1;
7. for i ranging 1 .. n do
8. NBBT [i] ← 0;
9. for j ranging 0 .. i − 1 do
10. NBBT [i] ← NBBT [i] + NBBT [j] · NBBT [i − j − 1]
11. end for
12. end for;
13. write(the number of binary trees having , n, nodes is , NBBT [n])
14. end
An alternate solution for this calculation is presented in problem 13, page 40.

i i

i i
i i

i i

14 Mathematics and computer science: some useful notions

Single index recurrence: factorial


We now consider a situation where the (one dimensional) recurrence is given a priori. Here,
one is interested in the computation of n!. It can be noticed that the only required value for
the computation of n! is (n − 1)!. Moreover, it is unnecessary to store the successive values
of factorial in an array, which simplifies the algorithm.
The following iterative procedure is devised without any storage of intermediate val-
ues:

1. constants
2. n ∈ N1 and n = . . .
3. variables
4. Facto ∈ N1
5. begin
6. Facto ← 1;
7. for i ranging 2 .. n do
8. Facto ← Facto · i
9. end for;
10. write(for n = , n, the value of n! is , Facto)
11. end

Two index recurrence: Delannoy numbers


We will emphasize on the evolution of the calculation of the two index recurrence defining
Delannoy numbers:

nbDel(0, j) = 1 0⩽j⩽m
nbDel(i, 0) = 
1   1⩽i⩽n
nbDel(i, j − 1) +  1⩽i⩽n
nbDel(i, j) =  nbDel(i − 1, j) +  et .

nbDel(i − 1, j − 1) 1⩽j⩽m

In order to compute nbDEL(n, m) where m and n are two integers, the array
NBD[0 .. n, 0 .. m] is associated with nbDEL. The computation of NBD[i, j] (connected with
nbDEL(i, j), the general term of the recurrence), it is necessary to know: (i) the value of the
cell with the same row index and the column index immediately lower, (ii) the value of the
cell with the same column index and the row index immediately lower and (iii) the value
of the cell with row and column immediately lower. One may then fill NBD according to
rows (but columns or diagonals as well). After initializing row 0 with 1 (first term of the
recurrence), rows are filled by increasing values of index i (until n is reached): cell (i, 0)
is set to 1 (second term of the recurrence), then cells (i, 1) to (i, m) are filled using the last
term of the recurrence.

1.2.2.3 Designing the algorithm associated with a recurrence


In general, given a (complete) recurrence formula for which no closed form is available,
the computational procedure is built as follows:
1. Specification of the tabular structure (array) associated with the calculation (dimen-
sions and size of each of them).

i i

i i
i i

i i

Recurrence, induction, recursion, etc. 15

2. Determination of the dependence relationships that connect the left element and those
present in the right part of the general term of the recurrence. An evolution of the
calculation can then be deduced, which ensures that the computation of any element
of the array calls only on previously computed elements (possibly using initialization
terms of the recurrence).
3. Optionally, improvements of the computation, e.g. restriction of the calculation only to
necessary elements.
4. Production of the code.
As it can be seen in the example of factorial (cf. also problem 12, page 39), the tabular
structure may be replaced by a few appropriate scalar variables. Awareness is required
about the representation of numbers, especially in the presence of a recurrence whose val-
ues grow very quickly. It is advisable to work with a floating point representation rather
than with integers. For example, Ackerman numbers are such that A(3, n) = 2n+3 − 3
2
..
et A(4, n) = 22 − 3 (n + 3 occurrences of 2), and this number becomes rapidly huge
2
22
(A(4, 2) = 2 − 3 = 216 − 3 = 265 536 − 3). Last, the dependence relationship connecting left
and right hand sides may be nontrivial. Here again, we refer to Ackerman numbers and
the computation of A(6, 1) = A(5, 65533).

1.3 Recurrence, induction, recursion, etc.


In the previous sections, proof by induction and recurrence have been dealt with and we
now try to clarify a vocabulary often perceived as somewhat confusing.

Proof by induction
When algorithms based on this type of reasoning are built, we frequently use the generic
term inductive reasoning, whose heart is induction. When reasoning on integers, it will be
mentioned if it the underlying induction is a simple or a strong one. They constitute the
two most often used variants in chapters 4 and 8.

Recursive program
An algorithm (as well as its coded form) is called recursive if it calls itself directly or by
means of other algorithms. The function Fact in page 16 illustrates the notion of recursive
algorithm, as well as numerous programs in chapters 4 and 8.
The “canonical” implementation of a recurrence is a recursive algorithm. However, it
will be seen in Chapter 4 that, for efficiency purposes, an iterative version will be preferred
where a tabular structure is filled (see preceding examples). This must not be confused
with the fact that a recursive program can be transformed (automatically but with the
explicit handling of a stack, see section 1.8) into an iterative one, which will have the same
behavior (especially the same performances) as the initial recursive program.
Nonetheless, there is a type of recursive program that can interestingly be transformed
into an iterative one: in the case of a terminal recursion. We will investigate this concept
with functions, but this would apply to procedures as well. A function F is terminal recur-
sive if it complies with the following pattern:
1. function F(. . .) result . . . pre
2. ...

i i

i i
i i

i i

16 Mathematics and computer science: some useful notions

3. begin
4. if C then
5. result V
6. else
7. result F(. . .)
8. end if
9. end
It is then possible to obtain an iterative program (whose execution is more efficient),
which is achievable by an smart compiler.

Example
The function hereafter:

1. function Fact(p) result N1 pre


2. p ∈ N1
3. begin
4. if p = 1 then
5. result 1
6. else
7. result p · Fact(p − 1)
8. end if
9. end
is not terminal recursive. It can be put into this form in the following way:

1. function Fact1(p) result N1 pre


2. p ∈ N1
3. begin
4. result FactRecTerm(p, 1)
5. end
6. function FactRecTerm(p, q) result N1 pre
7. p ∈ N1 and q ∈ N1
8. begin
9. if p = 1 then
10. result q
11. else
12. result FactRecTerm(p − 1, q · p)
13. end if
14. end
Here, function Fact1 is nonrecursive and function FactRecTerm is terminal recursive.

1.4 Sets
1.4.1 Basic notations
We begin with a particular formula called pair which will be frequently used in the follow-
ing. A pair is composed by two expressions separated by a comma or by the symbol 7→.

i i

i i
i i

i i

Sets 17

For example, the formula x, y + 3 is a pair. This pair may also be denoted by x 7→ y + 3, or
even (x, y + 3). In this notation, the first element is called the origin and the second one is
called the end.
C=b (x, y + 3) associates the name C to the object (x, y + 3).
The relational operators = and ̸=, with their common meaning, are assumed available
to compare two mathematical objects.

1.4.2 Definition of sets


Let E be a set, i.e. a collection of elements associated with the Boolean expression x ∈ E,
which states that x is an element of set E. Its negation is denoted ∈.
/ The set that contains no
element (the empty set) is denoted by ∅. When E and F are two sets, the expression E × F
denotes their Cartesian product which is defined by the equivalence (a, b) ∈ E × F ≡ (a ∈
E and b ∈ F).
A set may be defined by the properties of its elements. This is the intensional definition.
It is denoted by {x | x ∈ E and P}, where E is a set and P a selection predicate. This defines
the (sub)set of elements of E possessing the property P. Hence,
{x | x ∈ N and ∄ · (y ∈ N and x = 2 · y)}
defines the set of odd integers. The following property of the Cartesian product:
E × F = {(x, y) | x ∈ E and y ∈ F}
stems from the intensional definition of sets. The advantage of the second definition lies
in the fact that it allows, via a convention, for easily pointing a particular element of a pair.
As a matter of fact, let us consider the following definition of a point p in the Cartesian
plane: p ∈ {(x, y) | x ∈ R and y ∈ R}. It is then possible to use p.x (respectively p.y)
for the abscissa (respectively ordinate) of p. This advantage is also exploited for inductive
structures, in section 1.4.7, page 20, whereas the standard notation “×” does not provide
this facility.
A set may also be defined by means of the enumeration of its elements, which
corresponds to the extensional definition. The associated notation is {1, 3, true, 1.4}. This
latter set can also be written {1, true, 1.4, 3} (the order of elements is irrelevant), or
{1, 1, 3, true, 1.4, true, 3} (an element is present or not, the number of occurrences does not
matter inasmuch as the element is present). A set may also be defined in an inductive way.
A set X defined inductively is a special case of a recursive set. The function serving for its
definition has an inductive (or recurrent) nature, i.e.:
• some elements of X are explicitly given,
• the other elements are defined from elements already belonging to X.
For example, P the set of even numbers may be defined as the smallest subset of N comply-
ing with:
P = {0} ∪ {n | n ∈ N and ((n − 2 ∈ P) ⇒ n ∈ P)}.
We will see later in this book several examples of sets defined inductively, especially
trees. Often, properties of such sets are proven by an inductive reasoning.
P(E) stands for the powerset of set E and it is defined by
x ∈ P(E) ⇔ ∀y · (y ∈ x ⇒ y ∈ E).
Hence, if E =
b {1, 2, 3}, then P(E) = {∅, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}}.

i i

i i
i i

i i

18 Mathematics and computer science: some useful notions

1.4.3 Operations on sets


The reader is supposed aware of the definitions of the following set operations: ∩ (in-
tersection), ∪ (union), ⊆ (inclusion), ⊂ (strict inclusion), ̸⊂ (non inclusion), ̸⊆ (non strict
inclusion) ; the difference a − b between two sets is defined as {x : x ∈ a and x ̸∈ b}.
For a finite set E, card(E) represents the cardinality (the number of elements) of E.

1.4.4 Special sets


Beyond B, the set defined before for Booleans, the reader is assumed to be familiar with the
following numeric sets: N (natural numbers), Z (integers), R (real numbers, i.e. “discrete
reals” in computer representation), C (complex numbers).
Some subsets of the above sets have a specific notation. It is the case for N1 (which
represents N − {0}), R+ (which stands for the nonnegative elements of R), R∗+ (representing
the strictly positive elements of R).
As to complex numbers, i is the constant such that i2 = −1. The real componant of
the complex number c writes re(c) and its imaginary part im(c). Hence, for c = b 1 − 2i,
re(c) = 1 et im(c) = −2.
If E is a totally ordered numeric set, the operator min(E) (respectively max(E)) repre-
sents the smallest (respectively largest) element of E. When E is empty, min(E) = ∞ and
max(E) = −∞.
We denote the intervals of Z by exp1 .. exp2 . If exp2 < exp1 the interval corresponds
to the empty set. Since Z is an ordered set, an interval may be seen as a list (cf. section
1.4.7, page 20). The same applies to the expression exp1 .. exp2 − (F). This specificity is
used in loops of type for . . . range where, for instance, the range of the variable of the loop
1 .. 5 − {3, 4} corresponds to the set {1, 2, 5}, which is browsed in this order at runtime.

1.4.5 Relations, functions and arrays


1.4.5.1 Relations
Let E and F be two sets and R ⊆ E × F. R is called a (binary) relation between the source E
and the destination F. When F = E, the pair (E, R) is called graph (see section 1.5, page 22).
Functions are special binary relations and arrays are specific functions. It follows that
notions defined for relations are valid for these latter two notions.
Let R be a binary relation between E and F. The inverse relation of R is denoted R−1
and it is defined as:

b {(b, a) | (b, a) ∈ F × E and (a, b) ∈ R}.


R−1 =

Let R be a relation between E and F. The domain of R is denoted by dom(R) and it is


defined as the subset of E whose elements constitute the origin of at least one pair of R.
More formally:

dom(R) =
b {a | a ∈ E and ∃b · (b ∈ F and (a, b) ∈ R)}.

The co-domain of R is denoted by codom(R) and it is defined as the domain of R−1 . It


is also the subset of F whose elements constitute the extremity of at least one pair of R.
Let E be a set, the identity relation over E is denoted id(E) and it is defined as follows:

id(E) =
b {(a, b) | (a, b) ∈ E × E and a = b}.

i i

i i
i i

i i

Sets 19

T: Total
PI T PS P: Partial
I: Injective
S: Surjective
TI TS B: Bijective

TB

Fig. 1.2 – Inclusion diagram of the various types of function. A → B means that type A functions
are included in type B functions. From [1].

Let S be a relation between F and G, and R be a relation between E and F. The relation
R ◦ S is called the composition of R and S. It is defined by:

b {(a, c) | (a, c) ∈ E × G and ∃b · (b ∈ F and (a, b) ∈ R and (b, c) ∈ S)}.


R◦S=

1.4.5.2 Functions
A function f from E to F is a relation where there is no pairs (a, b) and (a, c) such that b ̸= c.
One writes f ∈ E → F. In the remainder, several types of functions will be singled out. Let
f ∈ E → F.

1. When f is a partial function, some elements of E may originate no pair of f.


2. When f is a total function, any element of E is the origin of one (and only one) pair of f.
3. When f is an injective function function, any element of F is the extremity of at most one
pair of f.
4. When f is a surjective function, any element of F is the extremity of at least one pair of
f.
5. When f is a bijective function function, f is both injective and surjective.
Let us notice that a total function is also a partial function. Figure 1.2, page 19, shows
the inclusion relationships valid between the various types of function.
In the remainder, a predicate such as “f ∈ E → F and T I(f)” must be understood as “f
is a total injective function from E to F”.

1.4.5.3 Arrays
An array t is a total function from an interval i .. s to a set F. One denotes t ∈ i .. s → F.
When i belongs to the definition domain of the array, t[i] stands for the element having the
index i of t. The set notation may be used, but when the context allows the determination
of the bounds, the notation [t1 , . . . , tn ] may be used as a constant of type array. A sub-array
(sometimes called array slice) defined on the domain i .. s is denoted by t[i .. s]. Hence, if the
interval 3 .. 5 is included in the definition domain of t, t[3 .. 5] ← [6, −1, 2] is a valid assign-
ment. It is equivalent to t[3 .. 5] ← {3 7→ 6, 5 7→ 2, 4 7→ −1}. Besides, after the assignment,
codom(t[3 .. 5]) = {−1, 2, 6}, whereas dom(t[3 .. 5]) = {3, 4, 5}.

i i

i i
i i

i i

20 Mathematics and computer science: some useful notions

A two-dimensional array is defined on the Cartesian product of two intervals. A con-


stant value of a two-dimensional array may be represented as an array of array (for exam-
ple [[0,1], [1, 1]]), but the two-dimensional notation, easier to read, is more used (the same
0 1
array: ).
1 1

1.4.6 Bags
A bag (or multiset) of elements of the set E is a mathematical structure inside which the
number of occurrences of a given element is meaningful. A bag S over E may be considered
as a function s from E to N, such that, for v ∈ E, s(v) is the number of occurrences of v in S.
In order to ease writing, we adopt an ad hoc notation instead of the set-oriented one. The
notations used further and their set-oriented equivalent forms are listed hereafter.
Bags Sets Bags Sets
<
− ∈ ̸< ̸⊂

 ∅ ⊑ ⊆
−̇ − ̸⊑ ̸⊆
⊓ ∩ |. . .| card
⊔ ∪ bmin min
< ⊂ bmax max
bag(E) represents the set of finite bags of the finite set E and J. . .K is equivalent to the
notation {. . .} for sets defined in extension. Last, mult(v, B) is the function returning the
multiplicity (the number of occurrences) of v in the bag B.

1.4.7 Cartesian product and inductive structures


Inductive structures, i.e. structures defined by induction (see page 17), play an important
role as data structures in this book. The two most typical cases are finite lists and finite
trees. The latter are dealt with in section 1.6, page 27. Here, we restrict ourselves to the
introduction of finite lists . What is the meaning of a formula such as:
list = {/} ∪ {(val, svt) | val ∈ N and svt ∈ list}. (1.1)
Informally, the set defined this way is the union between the empty list (denoted by /)
and the set of pairs made of an integer and a list of integers. (3, (1, (8, /))) is an example
of such a list. In principle, such a linguistic structure – which is an external representation
of lists – must not be confused with lists strictly speaking. In practice, this external nota-
tion will be authorized. It is necessary to add that we only deal with finite structures and
that, in this context, a list is the smallest set obeying equation 1.1. Based on the use of the
convention related to the dotted notation (see section 1.4.2, page 17), with the assignment
l ← (3, (1, (8, /))), one has l.val = 3 and l.svt = (1, (8, /)). Direct access to elements of
lists is not permitted and it is always necessary to go through one of the fields (such as
l.svt.svt.val for instance).
In practice, the (more concise) notation ⟨. . .⟩ is used. Hence, (3, (1, (8, /))) may also be
noted ⟨3, 1, 8⟩. The concatenation of lists is denoted by ·.

1.4.8 Strings and sequences


Strings (or sequences, sometimes words) are (right-) flexible arrays whose left bound is
implicitly 1. Their elements are usually called letters or characters. Thus, they are total

i i

i i
i i

i i

Sets 21

functions for which set operators are available (dom, codom, etc.). The size (length) of
the string c is denoted by |c|. The concatenation (denoted by ·) allows to extend a string
by adding another string, as well as a character (which is converted into a string). If
c = c[1] . . . c[n] denotes a string, c = c[n] . . . c[1] is the mirror of c. From an algorith-
mic point of view, a string c used as an input parameter implicitly conveys its definition
domain (dom(c)). If c is a string defined over 1 .. n, the slice c[i .. s] is a string defined
over 1 .. s − i + 1 provided that i .. s ⊆ 1 .. n. The empty string ε (neutral element for the
concatenation) is defined over 1 .. 0. The declaration of a symbolic constant, a variable or
a parameter c of type string is written c ∈ string with an implicitly vocabulary made up
of letters, numbers and special symbols. Calling on a specific vocabulary Σ is achieved by
c ∈ string(Σ). The following example illustrates the use of strings, especially constants not
surrounded by quotation marks which require a special font.

1. constants
2. a =abcd /% symbolic constant of type string %/
3. variables
4. b ∈ string({a,b,c,d,1,2,3,4}) /% variable of type string over the vocabulary
Σ = {a,b,c,d,1,2,3,4} %/
5. begin
6. write(Odd(a)) ; /% the function Odd(x) (see the code) delivers a string made
of the elements of x having an odd index %/
7. read(b) ; write(Odd(b)) ;
8. b ← acbd · 1234 · a[3 .. 4] · a[1] ; /% example of a concatenation %/
9. write(Odd(b))
10. end
1. function Odd(x) result string pre
2. x ∈ string and y ∈ string
3. begin
4. y ← ε ; /% y becomes an empty string %/
5. for i ranging
  dom(x) do
i
6. if 2 · ̸= i then
2
7. y ← y · x[i] /% extension of y by the next element of x having an odd
index %/
8. end if
9. end for;
10. result y
11. end

References to the notion of sequence


• The longest sub-sequence common to two sequences (page 635),
• Shuffling words (problem 21, page 45),
• The sluttering sub-sequence (problem 109, page 462),
• Distance or dissemblance between sequences (problem 107, page 452, problem 139,
page 674 and problem 140, page 678),
• Shortest common super-sequence (problem 138, page 674).

i i

i i
i i

i i

22 Mathematics and computer science: some useful notions

1.5 Graphs
Intuitively, a graph is a set of points, some of them being pairwise connected. It is a fairly
simple notion which allows for modeling numerous problems offering a great practical
interest, such as the search of the best route to reach a vacation home with a GPS device.
Graph theory is also the source of many mathematical and/or computer science com-
plex challenges such as the four color problem whose complete automated proof has been
carried out by the proof assistant Coq.
More simply, for us, the notion of graph originates numerous interesting problems
throughout this book.
Graph theory may be seen as an emanation of set theory (through the notion of binary
relation). However, the two theories have developed separately, thus often use divergent
vocabularies. In the following, directed graphs are first studied, then undirected ones. This
overview ends with the case of weighted (valued) graphs. Only finite graphs are taken into
consideration.

1.5.1 Directed graphs


A directed graph G is a pair (N, V), where N is a (finite) set and V a binary relation between
N and N (V is therefore a finite subset of N × N).
Elements of N are called nodes or vertices; those of V are called arrows or directed edges,
or (directed) arcs. The cardinality of N is called the order of the graph.

Example
The pair G defined by:
 
{a,b,c,d,e,f},
G=
{(a,b), (a,c), (a,f), (b,a), (b,c), (b,d), (c,e), (d,d), (d,f), (e,a), (e,f), (f,c)}
is a directed graph.
Figure 1.3 provides four possible representations for this graph. Schema (b), that has
the form of a square matrix, is often used as a computer representation.
An arrow that connects a vertex s with itself is called a loop over the vertex s; it writes
(s, s) with s ∈ N.
Let s be a vertex of a graph G. The out-degree (respectively in-degree) of s in G, de-
noted by d+G (s) (respectively dG (s)), is the number of arrows whose origin (respectively

extremity) is the vertex s.


A directed graph G ′ = (N ′ , V ′ ) is a subgraph of the directed graph G = (N, V) if N ′ ⊂ N
and V ′ = {(u, v) ∈ V | u ∈ N ′ , v ∈ N ′ }. G ′ is also called the graph induced from G by the
set of vertices N ′ .
In other words, a subgraph G ′ of a graph G is obtained by taking a strict subset N ′ of the
set N of vertices of G, keeping only the arrows whose origin and extremity belong to N ′ .
Let G = (N, V) be a directed graph and s ∈ N. The set of successors of s in G, denoted
by SuccG (s) is the set of vertices reached from s through the relation V.
The set of predecessors of s in G, denoted by PredG (s), is the set of vertices Succ(N,V −1 ) (s).

Example
In the example of graph G in figure 1.3, page 23, we have d+ G (d) = 2, dG (d) = 2, SuccG (a) =

{b, c, f} and PredG (c) = {a, b, f}. It can be noticed that the arrow (d, d) is a loop (over d).

i i

i i
i i

i i

Graphs 23

b
c
 
0 1 1 0 0 1
1 0 1 1 0 0
 
a d 0 0 0 0 1 0
 
0 0 0 1 0 1
 
e 1 0 0 0 0 1
f 0 0 1 0 0 0

(a) (b)

a× ×a
a • b • c • f /
b× ×b
b • a • c • d/
c× ×c c • e /

d× ×d d • d • f /
e • a • f /
e× ×e • c /
f
f× ×f

(c) (d)

Fig. 1.3 – Four representations of a directed graph. Schema (a) is the (usual) sagittal representation,
(b) is the representation by an adjacency matrix, (c) is a bipartite representation and (d) is a repre-
sentation by lists of successors.

The graph G1 = ({a, b, d, f}, {(a, b), (b, a), (a, f), (b, d), (d, d), (d, f)}) is the graph induced
from G by the set of vertices {a, b, d, f}.

If there is no ambiguity, the subscript G is omitted.


A path P in a graph G = ({s1 , . . . , sn }, V) is a nonempty list of vertices ⟨si1 , . . . , siq ⟩ such
that any pair of adjacent vertices in P is an arrow of G ((sik , sik+1 ) ∈ V for k ∈ 1 .. q − 1).
The length of the path P = ⟨si1 , . . . , siq ⟩ is the number of arrows (sik , sik+1 ) which con-
stitute it. It is denoted by |P|.
An elementary path is a path without any duplicate vertices.
A simple path is a path without arrows browsed more than once. Any elementary path
is a simple one.
A Hamiltonian path is a path where every vertex (of the graph) is present once and only
once. The list of vertices is a permutation of N.
An Eulerian path is a path which encompasses every arrow once and only once.

Examples of paths
In the graph of figure 1.3, page 23:
• ⟨a, b, a, c, e, a, b, d, d⟩ is a path. It is made up of the following list of arrows:
⟨(a, b), (b, a), (a, c), (c, e), (e, a), (a, b), (b, d), (d, d)⟩ and its length is 8. It is neither sim-
ple, nor elementary.

i i

i i
i i

i i

24 Mathematics and computer science: some useful notions

• ⟨b, c, e⟩ is an elementary path, it is therefore a simple path (of length 2).

• ⟨b, a, b⟩ is not an elementary path: the vertex b appears twice.


• ⟨a, b, c, e, f⟩ is a simple path. It is also elementary.
• ⟨a, b, a, c⟩ is also a simple path but it is not elementary.

• ⟨a, b, c, e, a, b⟩ is not a simple path: the arrow (a, b) is browsed twice. ⟨a, b, d, f, c, e⟩ is
a Hamiltonian path.

Schema (a) in figure 1.4, page 24, shows an Eulerian path, namely ⟨d, b, c, a, b, e, d, c, e⟩.
Let G = ({s1 , . . . , sn }, V) be a graph and C = ⟨si1 , . . . , siq ⟩ be a path in G. C is a circuit in
G if and only if siq = si1 .
The terms elementary, simple, Hamiltonian and Eulerian can be easily transposed from
path to circuit.

Examples of circuits
In the graph of figure 1.3, page 23:

• ⟨a, b, a, b, d, d, f, c, e, a⟩ is a circuit since on the one hand it is a path and on the other
hand vertex a is both its origin and its extremity.
• ⟨c, e, f, c⟩ is an elementary circuit.
• ⟨a, b, a, c, e, a⟩ is a simple circuit, but it is not elementary.
• ⟨a, b, d, f, c, e, a⟩ is a Hamiltonian circuit.

In the graph (b) of figure 1.4, page 24, the path ⟨d, b, c, a, b, e, d, c, e, f, d⟩ is an Eulerian
circuit.

a a

b c b c

d e d e

(a) (b)

Fig. 1.4 – Two directed graphs. Graph (a) contains the Eulerian path ⟨d, b, c, a, b, e, d, c, e⟩, but no
Eulerian circuit. Graph (b) contains at least one Eulerian circuit (⟨d, b, c, a, b, e, d, c, e, f, d⟩).

G+ = (N, V + ) is the transitive closure of G = (N, V) if and only if V + is the smallest


transitive relation containing V.
In other words, G+ is the transitive closure of G if, when there is a path between x and
y in G, there is an arrow between x and y in G+ .
In the schema hereafter, graph (b) represents the transitive closure of graph (a). Dashed
arrows are those stemming from the closure.

i i

i i
i i

i i

Graphs 25

b b

a c a c

f d f d

e e

(a) (b)

Let x be a vertex of a graph G. The vertex y is a descendant of x in G if there is an arrow


(x, y) in G+ . The vertex x is then an ascendant of y.
Two directed graphs G1 = (N1 , V1 ) and G2 = (N2 , V2 ) are isomorphic if and only if there
is a bijection f between N1 and N2 such that for any pair of vertices (i, j) of N1 :

(i, j) ∈ V1 ⇔ (f(i), f(j)) ∈ V2 .

In the schema given hereafter, graph (a) is represented in the plan, whereas (b) (the
grid “cylinder”) proposes a three-dimensional representation. They are isomorphic graphs
through the following bijection p:

p = {(H, c), (G, b), (J, a), (I, d), (C, g), (D, f), (F, e), (A, h)}.

c g
I H • •
A C
•h •f
d• b•
F D

J G • e
a
(a) (b)

1.5.2 Undirected graphs


An undirected graph G is a pair (N, V), where N is a finite set and V a subset of the powerset
of N with one or two elements.
As in directed graphs, the elements of N are called vertices or nodes. The elements of V
are called edges, or loops if they involve a single vertex.

Example
The pair G defined by:
 
{a,b,c,d,e,f},
G= 
{a, b}, {a, e}, {a, f}, {b, c}, {b, d}, {d}, {c, e}, {a, f}, {e, f}, {d, f}

is an undirected graph. Figure 1.5 provides three possible representations for this graph.
The terms string and cycle for undirected graphs are the counterparts of those of path
and circuit in directed graphs. The qualifiers elementary, simple, Hamiltonian and Eulerian
apply to undirected graphs as well. The same applies to the definitions of a subgraph, a
graph induced by a set of vertices and a transitive closure.

i i

i i
i i

i i

26 Mathematics and computer science: some useful notions

a× ×a
b
c
  b× ×b
0 1 1 0 1 1
1 0 1 1 0 0 c× ×c
 
a d fgk 1 1 0 0 1 1
  d× ×d
0 1 0 1 0 1
 
e 1 0 1 0 0 1 e× ×e
f 1 0 1 1 1 0
f× ×f

(a) (b) (c)

Fig. 1.5 – Three representations of an undirected graph. Schema (a) is the usual representation; (b)
is the representation by an adjacency matrix (this matrix is always symmetric); (c) is a bipartite
representation.

1.5.3 Weighted graphs


Intuitively, a weighted graph is a graph in which each arrow is provided with an attribute
(most often an integer or a real number, but it may be any type of value). This attribute
may stand for a distance, a duration, a cost, a potential, etc.
More formally, a weighted directed graph G is a triple (N, V, P), such that (N, V) is a di-
rected graph and P is a total function from V to the set of values E.
Figure 1.6 considers the directed graph in figure 1.3, page 23, with arrows valued in R
(E = R).

9.0

b 3.4
 
0

c ∞ 1.0 1.6 ∞ ∞ 4.2


1.

1.6
7
3.  3.7 ∞ 3.4 9.0 ∞ ∞ 
 
a 5.0 −2.7 ∞ ∞ ∞ ∞ 5.0 ∞ 
.0

7.0 d
 
12

∞ ∞ ∞ −2.7 ∞ 8.3 

 
4.
2

e  7.0 ∞ ∞ ∞ ∞ −1.0 
f −1.0 ∞ ∞ −12.0 ∞ ∞ ∞
8.3

(a) (b)

Fig. 1.6 – Two representations of a weighted directed graph. Schema (a) is the usual sagittal rep-
resentation, (b) is the matrix representation where absent arrows are provided with a conventional
symbol (here ∞).

An undirected weighted graph is a graph in which every edge is provided with an at-
tribute.
More formally, an undirected weighted graph G is a triple (N, V, P) such that (N, V) is an
undirected graph and P is total function from V to a set E of values.

i i

i i
i i

i i

Trees 27

In practice, the representation of a weighted graph may be restricted to that of N and


P, as shown in schema (b) in figure 1.6.

References to the notion of graph


Among the countless problems related to graphs (search for shortest paths or strings be-
tween two vertices, or between a given vertex and all others, or between all pairs of ver-
tices, the determination of the existence of an isomorphism between two graphs, coloring
of a graph, etc.), some are tackled as problems in this book. Let us quote:

Nonweighted directed graphs:

• Moving a knight under constraints (problem 15, page 41).


• Exhaustive visit of a chessboard (problem 49, page 170).
• The knight’s tour (problem 54, page 227).
• Eulerian circuits and paths (problem 55, page 230).
• Hamiltonian paths (problem 56, page 231).
• Graph isomorphism (problem 58, page 234).
• Graph coloring (problem 59, page 236).
• Tournaments and Hamiltonian paths (problem 85, page 370).

Weighted directed graphs:

• Optimal broadcast (problem 78, page 345).


• Best path in a conform graph (problem 131, page 660).
• Best paths from a source (problem 132, page 661).
• Best paths algebras (problem 133, page 664).
• Best path in an array (problem 134, page 667).
• Distance between sequences (problem 139, page 674).

Undirected weighted graphs:

• Optimal broadcast (problem 78, page 345).


• The traveling salesman (problem 57, page 233, and example page 314).
.

1.6 Trees
Beyond their intrinsic interest (compiling, automated proofs, natural language processing,
etc.), trees are at the root of efficient representations for a wide range of data structures
(sets, queues, priority queues, flexible arrays, etc. – see [22, 9]. Despite the use of numerous
types of trees throughout this book (see for instance recursion trees, Chapter 5, page 197),
here we restrict ourselves to binary and ternary trees. There are several ways to define this
notion. Using graph theory is one of them. A binary or ternary tree is defined as a specific
graph (an undirected connected loopless graph where a particular vertex – the root – is

i i

i i
i i

i i

28 Mathematics and computer science: some useful notions

dintinguished). However, our preference goes to an inductive definition more appropriate


for our use.
Figure 1.7, page 28, provides an example of both a binary and a ternary tree. They are di-
rected graphs. On this issue, graph theory terminology and the one used here diverge since,
in graph theory, these structures would be called “arborescence”. The term path is used ac-
cording to its meaning in graph theory. We will use the term “path” for routes/itineraries
where the direction of arrows is not taken into account. As to the term distance, it is indif-
ferently used for paths and “paths”.
The example below shows how a labeled binary tree is defined in a recursive manner
(each node is associated with a value, a positive integer here)3 :

1. constants
2. ab = {/} ∪ {(l, n, r) | l ∈ ab and n ∈ N and r ∈ ab}
3. variables
4. t ∈ ab
5. begin
6. t ← /;
7. t ← (((/, 0, /), 1, /), 3, (((/, 4, /), 5, (/, 6, /)), 7, (/, 9, /)));
8. write(t.l)
9. end
ab is the set of all finite binary trees of integers. It is defined (line 2 in the code) as the union
of two sets: {/} (the empty tree) and the set of triples (l, n, r), where l and r are binary trees
(respectively the left subtree and the right subtree) and n an integer. Line 4, t is a variable
defined as one of the elements the set ab. The instruction in line 6 assigns the empty tree
to t. That of next line assigns the tree of schema (a) in figure 1.7 to t. Line 8 displays (on a
regular terminal) the left subtree of t (denoted by t.l).

v = 5?
3 < = >
1 7 v = 3? P v = 9?
< = > < = >
0 5 9
A P A v = 7? P A
4 6 < = >
(a) A P A
(b)

Fig. 1.7 – Schema (a): a binary tree and Schema (b) : a (decision) ternary tree (A: absent P: present).

In a binary tree, a leaf is a childless node (without any successor); a simple point is a
node with a single child. The height of a binary tree is the distance (i.e. the number of
edges) between the root and the furthest leaf. The weight of a binary tree is the number of
its nodes/vertices. Among all the possible simple “paths” in a nonempty binary tree, there
is (at least) one with maximum length. This length is called the diameter. A diameter does
not necessarily include the root (see problem 94, page 431).
3 Even if, for convenience, they can be at the same place in the schemas, it is important to distinguish between

the name of a vertex or a node, which is an identifier, and the label, which is any type of value. The inductive
definition of trees allows for omitting the name of the node.

i i

i i
i i

i i

Trees 29

In the forthcoming schemas, “paths” connecting grey vertices are materialized by bold
arrows. In schema (a) (respectively (b)), the considered “path” is made of 5 (respectively 7)
arrows, so its length is 5 (respectively 7). The height of these two trees is 4, their diameter
is 7. The bold “path” in schema (b) is a diameter.

(a) (b)

Most of the above definitions can easily be transposed to ternary trees. Among par-
ticular binary trees, let us cite skinny trees, complete trees, full trees and perfect trees. A
skinny tree is a tree where no vertex has two children. A complete tree is a tree does not
contain any simple point. Trees (a) and (b) in figure 1.8, page 29, are complete trees. This
is not the case for the three others in this figure. A full tree is a tree where all leaves are
located at the same height. It is the case for tree (b) in figure 1.8, page 29. It is the only tree
of this type in this figure. A perfect tree is such that: (i) all leaves are located on the last
two levels, i.e. the lowest levels, (ii) when the (perfect) tree is not a full one, i.e. when the
leaves are spread over two levels, the leaves of the lowest level are left-gathered (iii) there
is at most one simple point and it is located on the penultimate level. Schema (c) in fig-
ure 1.8 provides an example of a perfect tree. Tree (b) is also a specific perfect tree (because
of the absence of a simple point). On the contrary, trees (d) and (e) in figure 1.8, page 29,
are not perfect trees, the first one because it possesses two simple points, the second one
because the leaves of the last level are left-gathered. Tree (a) is not a perfect tree. It is easy
– and often useful – to give an inductive definition of the notions studied in this section
(see problem 94, page 431). We draw the attention of the reader on the fact that definitions
concerning trees are far from consensual.

(a)
(b)

(c) (d) (e)

Fig. 1.8 – Complete, full and perfect trees—Examples and counter-examples.

i i

i i
i i

i i

30 Mathematics and computer science: some useful notions

A particular type of binary tree is worthy of a special attention, namely binary search
trees (called bst for short). An bst is either an empty tree, or a binary tree whose nodes
contain numeric values, and such that, if v is its root, its left (respectively right) subtree is
a bst containing, if nonempty, values lower (respectively greater) than v. Tree (a) in figure
1.7, page 28, is a bst.
At many places, we make use of particular trees called “decision trees”. A decision tree
allows for structuring a classification (see figure 8.1, page 421), for representing the various
executions of an algorithm (see figure 90, page 427), sometimes with aim of computing its
complexity (see figure 96, page 433). Usually, a decision tree appears as a binary tree where
each node is a predicate and each branch a possible answer (true or false). The predicate
can be replaced by a multiple choice question where the number of branches of each node
is that of the answers to the considered question. Tree (b) in figure 1.7, page 28, is a ternary
tree for deciding whether or not a given value v belongs to the set {3, 5, 7, 9}. In this tree,
each node is intended for comparing v with the value present in the considered node.
Leaves answer the question associated with the decision tree (P: the numeric value present
in the leaf belongs to {3, 5, 7, 9}, A : the numeric value present in the leaf does not appear in
{3, 5, 7, 9} – it is absent.)

References to the notion of tree


The notion of tree is the heart of several problems of this book. Let us quote the following
titles (of problems):
• Binary, ternary and interpolation searches (problem 90, page 427).
• Local minimum in a binary tree (problem 93, page 431).
• Diameter of a binary tree (problem 94, page 431).
• Nuts and bolts (problem 96, page 433).
• The largest rectangle under a histogram (problem 116, page 480).
• The egg problem (2) (problem 130, page 657).
• Weighted binary search trees (problem 135, page 669).
• The best triangulation of a convex polygon (problem 142, page 681).
This notion appears also in figure 8.1, page 421, as a decision tree in order to point out
a typology of “Divide and conquer” methods.

1.7 Priority queues


1.7.1 Definition
A priority queue is a data structure where each element is provided with a numeric value
which represents a priority level. By convention (i) the lower the value, the higher the
priority of the element and (ii) the effect of a deletion is to remove an occurrence of the
lowest value. In its standard version, a priority queue is defined by the following five
operations:

• InitPQ(q): procedure which empties the priority queue q.

i i

i i
i i

i i

Priority queues 31

• HeadPQ(q): function which delivers the priority element (the head) of the queue q. The
precondition of this function is that the queue involves at least one element.
• RemovePQ(q): procedure that removes the priority element (the head of the queue)
from the queue q. This procedure also has as a precondition that q contains at least one
element.

• AddPQ(q, e): procedure which inserts the element e in the queue q (this element is
assumed to convey its own priority).
• IsEmptyPQ(q): Boolean function which returns true if and only if the priority q is
empty.

Sometimes, it is necessary to enrich this set of operations with additional ones, such as
that consisting in modifying the priority of a given element of the queue (see for instance
problem 78, page 345). The size of the queue q is denoted by |q|.

1.7.2 Implementations
Several more or less sophisticated implementations of priority queues are reported in the
literature. Let us remind two of them for queues with n elements:

• Sorted lists for which the insertion operation is in O(n), the (re)initialization operation
is in Θ(n) or Θ(1) depending on the fact that space is recovered or not. Other operations
are in Θ(1). This type of solution is convenient only if n is small.
• Heaps. From a structural point of view, a heap is a perfect binary tree (leaves are located
on – at most – two consecutive levels and those of the last level are left-gathered). As
to the content, a heap is such that the value of any node is less than (or equal to) that
of all its descendants.
An important characteristic is that a heap can beneficially be represented by an array T
such that, for a given i, T [2i] and T [2i + 1], if they do exist, are the children of T [i].
The following schema (a) shows a heap defined on R+ according to its arborescent
form. Schema (b) is the array representation of schema (a).

2.3

4.0 5.6 1 2 3 4 5 5 7 8 9 10
T 2.3 4.0 5.6 6.1 7.9 7.3 9.8 9.5 8.0 8.3
6.1 7.9 7.3 9.8

9.5 8.0 8.3

(a) (b)

In terms of visited vertices (or evaluated conditions), the cost of the operation Delete
is in Θ(log2 (n)) and that of Insert is in O(log2 (n)). Other operations require a constant
time.

i i

i i
i i

i i

32 Mathematics and computer science: some useful notions

References to the notion of priority queues


This notion is at the heart of two chapters of this book: Chapter 6 about the “Branch and
Bound” technique and Chapter 7 devoted to greedy algorithms.

1.8 FIFO and LIFO queues


A FIFO (First In, First Out) queue may be considered as a particular priority queue whose
elements do not bear any explicit priority. The handling of priority is performed in an
implicit way, since an element is always inserted at the end of the queue and the head
element (the oldest one entered in the queue) is removed for a deletion. FIFO(E) represents
all the FIFO queues over elements belonging to E. Thus, if one writes F ∈ FIFO(R+ ×
R+ ), it is a declaration of a FIFO queue F containing pairs of nonnegative real numbers.
Operations used for dealing with FIFO queues are:

• InitFifo(F): procedure which empties the queue F.


• HeadFifo(F): if F is a FIFO queue of elements of type E, this function returns the head
element without removing it from the FIFO queue. This function supposes (precondi-
tion) that F is not empty.
• RemoveFifo(F): this procedure removes the head element from the FIFO queue F. Here
again, the precondition is that F is not empty.
• AddFifo(F, e): procedure which adds the element e at the end of the queue F.
• IsEmptyFifo(F): this function returns true if and only if the queue F is empty.

As for priority queues, it is sometimes useful to enrich this set of operations or to mod-
ify some of them.
A LIFO queue (hereafter called a stack) is a data structure designed to manage items
according to the following strategy: the element to be removed is the last one that was
introduced (hence the name LIFO: Last In First Out). Operations used to deal with stacks
are:
• initStack(S) procedure that empties the stack S,
• topStack(S) function that delivers the top of the stack S without modifying this latter
(precondition: the stack is not empty),
• Stack(S, v) procedure that puts the integer value v on top of the stack S,
• unStack(S) procedure that removes the top of the stack S (precondition: the stack is not
empty),

References to the notion of FIFO queues


The notion of FIFO queue is used in Chapter 7 dedicated to greedy algorithms.

References to the notion of stack


The notion of stack is used in the problem 116, The largest rectangle under a histogram,
page 480.

i i

i i
i i

i i

Problems 33

1.9 Problems
Problem 1. Is a neutral element unique? ◦ •

This problem mainly aims at a thorough use of the proof by contradiction.

Let S be a set provided with an internal operator ⊕. Let u ∈ S be a left neutral element
for ⊕, i.e.:
∀x · (x ∈ S ⇒ u ⊕ x = x).
Let v be a right neutral element for ⊕.
Question 1. Prove in a direct way that if ⊕ is a commutative operator, one has u = v. 1-Q1

Question 2. Prove this property by contradiction without calling on the commutativity 1-Q2
property of ⊕.
The solution is on page 46.

Problem 2. Minimum element of a partially ordered set ◦ •

The interest of this problem is to demonstrate the same property by means of both a proof by
contradiction and a proof by induction.

Let E be a finite set with a partial order relation denoted by ⪯ and F be a strict nonempty
subset of E. A strict antecedent of x is an element y distinct from x such that y ⪯ x. An
element m of F is said to be minimum if m has no strict antecedent in F.
Question 1. Prove by contradiction that F has at least one minimum element. 2-Q1

Question 2. Demonstrate by induction that F has at least one minimum element. 2-Q2

Question 3. One considers the set E made of pairs of integers and the partial order 2-Q3
relation ⪯ defined by:
b a ⩽ c and b ⩽ d.
(a, b) ⪯ (c, d) =
Let F(⊂ E) = {(a, b) | a ∈ 1..3 and b ∈ 1..2 and a ̸= b}. Enumerate the minimum elements
of F.
The solution is on page 46.

Problem 3. Factorial vs exponential ◦ •

In this problem, two results about the comparison of values of factorials and exponentials
are established. The first one constitutes a result useful for the order of two related classes of
complexity (see Chapter 2).

i i

i i
i i

i i

34 Mathematics and computer science: some useful notions

3-Q1 Question 1. Prove by simple induction that:

∀n · (n ∈ N1 ⇒ n! ⩾ 2n−1 ).

3-Q2 Question 2. What is the minimum value n0 such that:

∀n · ((n ∈ N1 and n0 ∈ N1 and n ⩾ n0 ) ⇒ n! > 22n ) ?

The solution is on page 47.

Problem 4. Currency change (1) ◦ •

In this problem, we first validate a new schema for the proof by simple induction. Then, it is
applied to a property about the construction of an amount of money. We also ask for making
the demonstration with the proof by regular simple induction. It is the possible to decide
whether one method is more “convenient” than the other one, noticing that the result holds
for this problem only.

4-Q1 Question 1. Prove that the following alternate pattern for simple induction proof
holds:

If it is possible to demonstrate the two following properties:


Initialization P(n0 ) and P(n0 + 1) hold for a given n0 ∈ N
Induction ∀n · ((n ⩾ n0 and P(n)) ⇒ P(n + 2))
then:
Conclusion ∀n · (n ⩾ n0 ⇒ P(n))

4-Q2 Question 2. Use this pattern to prove that any amount of money n over five cents can
be obtained with two and seven cent coins.
4-Q3 Question 3. Prove the same result by simple induction as given in section 1.1.3.1, page
4.
4-Q4 Question 4. Which is the maximum number of seven cent coins used in each of these
patterns?
4-Q5 Question 5. In your opinion, which of these two proofs is easier to perform?
The solution is on page 47.

Problem 5. Catalan numbers ◦ •

In this problem, it is proven (by simple induction) that the closed form of the recurrence rela-
tion proposed for Catalan numbers is valid. An upper bound of the value of the nth Catalan
number is also proposed.

i i

i i
i i

i i

Problems 35

Catalan numbers have been previously addressed and defined by the following recur-
rence relation (see page 11):

Cat(1) = 1
4n − 6
Cat(n) = · Cat(n − 1) n > 1.
n

Question 1. Prove by simple induction that, for any positive integer n, the closed form 5-Q1
of this recurrence relation is (see page 11):

(2n − 2)!
Cat(n) = .
(n − 1)! n!

Question 2. Prove by simple induction that, for any positive integer n, one can write: 5-Q2

4n−1
Cat(n) ⩽ .
n
The solution is on page 48.

Problem 6. Erroneous proofs by simple induction ◦ •

This problem is intended for drawing the attention on the compliance with the hypotheses
so as to perform a valid proof by induction. Two examples are successively proposed, where
the proposition P to prove is obviously false. It is interesting to point out the fallacy in the
reasoning suggested to make the proof.

First case
We envisage to prove the following property P1 :

Any pair of integers is made of two identical integers.

The reasoning is performed on the maximum of the two numbers a and b, denoted by
max(a, b).

Initialization If max(a, b) = 0, then obviously a = b = 0.


Induction Suppose that property P1 holds when the maximum of a and b is p. The induc-
tion hypothesis tells that:
if max(a, b) = p then a = b = p.
We have to demonstrate that P1 holds when the maximum of a and b is (p + 1). Let
(a, b) be a pair of integers such that max(a, b) = p + 1. The maximum of (a − 1) and
(b − 1) is p. According to the induction hypothesis, one has: a − 1 = b − 1 = p, hence:
a − 1 + 1 = b − 1 + 1 = p + 1, and finally a = b = p + 1.
Conclusion Property P1 holds for any pair of integers.

Question 1. Where is the flaw? 6-Q1

i i

i i
i i

i i

36 Mathematics and computer science: some useful notions

Second case
We consider the following property P2 :
n arbitrary points of a plane are aligned.
The induction relates to the number of points n.
Initialization For n = 2, proposition P2 holds, since two points are aligned.
Induction Suppose that property P2 holds for p points (induction hypothesis). Let us
prove that then the (p + 1) points A1 , A2 , A3 , . . . , Ap+1 are aligned. According to the
induction hypothesis, the first p points A1 , A2 , A3 , . . . , Ap are aligned on a straight
line (d1 ) and the last p points A2 , A3 , . . . , Ap+1 are aligned on a straight line (d2 ).
These two straight lines (d1 ) et (d2 ) have the points A2 and A3 in common and they
are one and the same. One has (d1 ) = (d2 ) = (A2 A3 ) and the points A1 , A2 , A3 , . . . ,
Ap , Ap+1 are aligned.
Conclusion Proposition P2 holds for any number of points strictly greater than 1.

6-Q2 Question 2. Find the flaw.


The solution is on page 49.

Problem 7. Erroneous proof by strong induction ◦ •


Following the previous one, this problem aims at pointing out a flaw in a reasoning by in-
duction. However, here, the formula to demonstrate is right and a direct appropriate proof is
expected.

It is proposed to demonstrate by simple induction that, for any strictly positive integer
n, one has: s r q p
n = 1 + (n − 1) 1 + n 1 + (n + 1) 1 + (n + 2) . . .

To start, it is assumed that the above expression makes sense, i.e. that it converges when
n increases indefinitely (which is true, as we will see later).
The proof by strong induction is performed as follows:
Initialization For n = 1, the right part of the formula becomes:
q p
1 + 0 1 + 1(. . .) = 1

and the equality holds.

Induction hypothesis For any n > 1:


s r q p
(n − 1) = 1 + (n − 2) 1 + (n − 1) 1 + n 1 + (n + 1) . . . .

i i

i i
i i

i i

Problems 37

Induction One has:


s r q p
(n − 1) = 1 + (n − 2) 1 + (n − 1) 1 + n 1 + (n + 1) . . .
⇒ r squaring
q p
(n − 1)2 = 1 + (n − 2) 1 + (n − 1) 1 + n 1 + (n + 1) . . .
⇔ r remarkable identity
q p
n2 − 2n + 1 = 1 + (n − 2) 1 + (n − 1) 1 + n 1 + (n + 1) . . .
⇔ r arithmetics
q p
n(n − 2) = (n − 2) 1 + (n − 1) 1 + n 1 + (n + 1) . . .
⇔ r division by n − 2 of the two members
q p
n(n − 2)
= 1 + (n − 1) 1 + n 1 + (n + 1) . . .
n−2
⇔ r arithmetics
q p
n = 1 + (n − 1) 1 + n 1 + (n + 1) . . . .

We have demonstrated that the induction hypothesis entails the formula to be proven.
Question 1. Where is the flaw in the above reasoning? 7-Q1

Question 2. Yet, this formula is valid. Give a valid proof. 7-Q2

The solution is on page 50.

Problem 8. Alternate pattern for two indexes recurrence proof ◦ •

In section 1.1.6, page 9, a two indexes recurrence proof pattern was proposed. The objective of
this problem is to validate another one.

Prove that the following pattern of proof is right:

If the following two properties can be proven:


Initialization P(i, 1) holds for any i ⩾ 1 and
P(1, j) holds for any j ⩾ 1
   
i ∈ N1 and P(i + 1, j) and
Induction ∀(i, j) ·  j ∈ N1 and  ⇒  P(i, j + 1) and 
P(i, j) P(i + 1, j + 1)
then:
Conclusion P(m, n) holds for any pair of integers such that m ⩾ 1 and n ⩾ 1

The solution is on page 50.

i i

i i
i i

i i

38 Mathematics and computer science: some useful notions

Problem 9. Divisibility by 7 ◦ •

This problem is devoted to the proof by induction of a property of the elements of a series of
integers given under its closed form.

Let A(n, p) be the integer defined as:

A(n, p) = 32n − 2n−p n ∈ N1 and p ∈ N and n ⩾ p.

9-Q1 Question 1. Prove by simple induction that whenever A(n, p) is (respectively is not) a
multiple of 7, A(n + 1, p) is (respectively is not) a multiple of 7.
9-Q2 Question 2. What can be said about the divisibility (by 7) of the series of numbers
A(n, 0), A(n, 1), A(n, 2) and A(n, 3)?
The solution is on page 51.

Problem 10. Proof by induction vs direct proof ◦ •

Here, a series of numbers is under consideration. Two properties are proven, one by simple
induction and the second one “directly”. It turns out that the proof by induction does not
appear to be the easiest one.

We consider the following recurrence defining the series of numbers A(n):

A(1) = 1
n2 − 3n + 1
A(n) = A(n − 1) + n ⩾ 2.
(n − 1)2 · n2

10 - Q 1 Question 1. Prove by simple induction that the closed form of numbers A(n) is (n2 −
2
n + 1)/n for any integer n ⩾ 1. What can be deduced as to the nature of these numbers?
10 - Q 2 Question 2. Prove that for any integer n > 2, A(n) lies in the open interval A(2) .. A(1).
The solution is on page 51.

Problem 11. The lizard sequence ◦ •


In this problem, one tries to build an infinite sequence of binary numbers which equals that
obtained by taking only one in three term, as well as that obtained by keeping the two in three
remaining terms. Of course, the two trivial sequences made solely of 0’s or 1’s are discarded.

Let S = ⟨s1 , s2 , . . . , sn , . . .⟩ be the binary sequence other than the trivial one composed
solely of 0’s (respectively 1’s). One denotes by S/3 the sequence built by taking one in three
element of S as follows: S/3 = ⟨s3 , s6 , . . . , s3n , . . .⟩. One denotes by S − S/3 the sequence

i i

i i
i i

i i

Problems 39

remaining from S when S/3 is removed, which gives: S − S/3 = ⟨s1 , s2 , s4 , s5 , s7 , s8 , . . .,


s3n−2 , s3n−1 , s3n+1 , s3n+2 , . . .⟩. For example, for S = ⟨0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, . . .⟩, one has:

S/3 = ⟨1, 0, 0, 1, . . .⟩ and S − S/3 = ⟨0, 0, 1, 0, 1, 1, 0, 1, . . .⟩.

Question 1. Propose a reasoning by induction which allows the construction of the two 11 - Q 1
sequence S1 and S2 (other than ⟨0, 0, 0, . . .⟩ and ⟨1, 1, 1, . . .⟩) such that S = S/3 = S − S/3.
They are called the “lizard sequence” (see [11]).
Question 2. Give their first 20 elements. 11 - Q 2
The solution is on page 52.

Problem 12. Fibonacci sequence; about the closed form ◦


◦ •

This problem highlights the fact that even if a closed form of a recurrence formula is known,
it can hardly be used in an algorithm.

Let us remind that Fibonacci sequence of integer numbers is defined (see page 10) by
the following recurrence:

F(1) = 1
F(2) = 1
F(n) = F(n − 1) + F(n − 2) n > 2.

Its closed form is:

" √ !n √ !n #
1 1+ 5 1− 5
F(n) = √ − n ⩾ 1.
5 2 2

Question 1. Explain why the above formula is not used to compute F(n) for a given 12 - Q 1
n.
Question 2. Propose an iterative algorithm returning the nth Fibonacci number. 12 - Q 2

Remark
Several other ways for the computation of Fibonacci numbers are discussed in problem 89,
page 425.
The solution is on page 53.

i i

i i
i i

i i

40 Mathematics and computer science: some useful notions

Problem 13. How many binary trees have n nodes? ◦ •

This problem is a complement to the example given page 12. Its objective is to design a variant
of the algorithm computing the number of binary trees possessing n elements on the basis of
a closed form, therefore expected to be more efficient.

It has been established that the number of binary trees with n nodes is given by the
following recurrence:

nbBT (0) = 1
X
n−1
nbBT (n) = nbBT (i) · nbBT (n − i − 1) n ⩾ 1.
i=0

13 - Q 1 Question 1. Prove that this recurrence can also be written:

nbBT (n) = Cat(n + 1) n⩾0


where Cat(n) is the n th
Catalan number (see definition page 11).
13 - Q 2 Question 2. Derive an iterative algorithm to compute nbBT (n).
The solution is on page 53.

Problem 14. Identifying a closed form ◦ •


This problem has a twofold interest. On the one hand, a practical way for the calculation of
the elements of a two index recurrence is studied. On the other hand, a closed form is proposed
and proven by means of a new pattern for two index proof by induction.

The following two index recurrence is considered:

a(0, j) = j + 1 j⩾0
a(i, 0) = 2 · a(i − 1, 0) + a(i − 1, 1) i>0
a(i, j) = a(i − 1, j − 1) + 2 · a(i − 1, j) + a(i − 1, j + 1) i > 0 and j > 0.

14 - Q 1 Question 1. Give the value a(3, 2). Propose a tabular structure and describe the evolu-
tion of the calculation of a(i, j) (i, j ⩾ 0).
14 - Q 2 Question 2. Write an iterative program which computes the value a(n, m) for a given
pair (n, m).
14 - Q 3 Question 3. Propose a closed form for a(i, j) and prove its validity by induction. What
is the interest of this expression from an algorithmic point of view?
The solution is on page 54.

i i

i i
i i

i i

Problems 41

Problem 15. Moving a knight under constraints ◦ •

One considers possible moves of the knight (in the spirit of the chessgame) under constraint
between the two extreme points of a board and their enumeration by means of a recurrence
formula.

One is interested in the paths of the knight (according to chessgame) over a board with
n > 4 rows and m > 3 columns. One wants to know the number of distinct ways to go
from the square (1, 1) (departure) to the square (n, m) (arrival). By convention, (i, j) stands
for the square of the board located on row i and column j. In contrast to chessgame where
the knight has eight possible moves (except if it would go outside the board), it is imposed
that the knight moves only in order to increase the column index (the second one), as
shown in figure 1.9.

7
ZnZ0Z0Z0Z
6
0Z0M0Z0Z0
5
Z0M0Z0M0Z
4
0Z0Z0Z0M0
3
Z0Z0ZnZ0Z
2
0Z0Z0Z0M0
1
Z0Z0Z0M0Z
1 2 3 4 5 6 7 8 9

Fig. 1.9 – The knight located in (7, 2) (respectively (3, 6)), plotted in black, can move to the two
(respectively four) positions, plotted in white.

Question 1. Let nbRout(i, j) be the count of distinct paths starting in (1, 1) and ending 15 - Q 1
in (i, j. Give the complete recurrence for calculating nbRout(i, j).
Question 2. Write the iterative algorithm derived from this formula for any given pair 15 - Q 2
of integers (n, m). Give the value of nbRout(5, 7).
The solution is on page 56.

Problem 16. How many partitions of n elements have p blocks? ◦ •

The main goal of this problem is to establish the recurrence formula defining Stirling numbers.

We denote by S(p, n) the number of partitions with p blocks of a set having n elements.
The values S(p, n) are called Stirling numbers. For example, {{a, c}, {b, d}} and {{b}, {a, c, d}}
are two out of the seven partitions with two blocks of the four element set {a, b, c, d} .

i i

i i
i i

i i

42 Mathematics and computer science: some useful notions

16 - Q 1 Question 1. Give all the partitions with one, two, three and four blocks of the latter
four element set (a block cannot be empty).
16 - Q 2 Question 2. What is the recurrence defining S(p, n)?
16 - Q 3 Question 3. Propose a progression of the calculation of S(p, n), then develop the cor-
responding iterative algorithm.
16 - Q 4 Question 4. Give the values of S(p, n) for 1 ⩽ p ⩽ 5 and 1 ⩽ n ⩽ 7.
The solution is on page 58.

Problem 17. Climbing a staircase ◦ •

The target of this problem is twofold: establishing a recurrence relation and optimizing its
algorithmic computation by obviating some of the cells of the underlying array.

One considers a m step staircase that can be climbed with jumps of a1 or a2 or . . . or


an steps. We would like to calculate nbCL(s, m) the number of distinct ways for climbing
exactly the m steps with s jumps.
For example, when m = 12 steps and the possible jumps are a1 = 2, a2 = 3 and a3 = 5
steps, the 12 steps of the staircase can be climbed (exactly) by the following successions of
jumps (among others):
(2, 2, 2, 2, 2, 2), (2, 3, 2, 3, 2), (2, 2, 2, 3, 3),
(3, 3, 3, 3), (2, 2, 3, 5), (3, 2, 5, 2), (2, 2, 5, 3).

17 - Q 1 Question 1. Give two ways for climbing up the 12 steps (not more, not less) of a stair-
case using exactly three jumps of a1 = 2 or a2 = 3 or a3 = 5 steps.
17 - Q 2 Question 2. Give the recurrence relation for the calculation of nbCL(s, m).
17 - Q 3 Question 3. Propose a progression for this calculation, then the iterative associated
program.
17 - Q 4 Question 4. Give the values nbCL(s, m) for m ⩽ 12, s ⩽ 6, n = 2, a1 = 2, a2 = 5.
17 - Q 5 Question 5. In the previous example, it can be noticed that some portions of the array
related to nbCL are filled in with 0’s. Explain why and suggest an improvement of the
algorithm proposed in question 3.
The solution is on page 59.

Problem 18. The Patagon game ◦ •


This problem introduces the Patagon game, where a single player aims at accumulating the
highest gain. One searches to count the “reasonable” ways of playing, which both comply
with the rule of the game and are likely to lead to the maximum gain. problem 146, page 687
is devoted to the determination of a way of playing according to which the highest gain is
reached.

i i

i i
i i

i i

Problems 43

When playing the Patagon game, the player is in front of n objects, arranged in line. Each
object possesses a given visible value. The player can take as many objects as he wants so
as to accumulate a total value as large as possible. Obviously, there is a constraint (and
only one): the player cannot take two of the objects of the initial configuration located side
by side.
Question 1. What is the best choice with the following line of objects (where an object 18 - Q 1
is represented by its value) ?
23 41 40 21 42 24
Question 2. The choice of the player is assumed to be represented by its n-sized char- 18 - Q 2
acteristic vector (1 in position i if the ith object is taken, 0 otherwise). In the previous
example, [0, 1, 0, 1, 0, 1] represents a game yielding 0 + 41 + 0 + 21 + 0 + 24 = 86 Patagon
currency units. Prove that, for n > 1, there are strictly less than 2n distinct ways of playing.
Question 3. Some ways of playing are, for sure, worse than others. For example, 18 - Q 3
[0, 1, 0, 1, 0, 0] (yielding 62) is worse than [0, 1, 0, 1, 0, 1] (paying 86). A way of playing is said
to be reasonable, if it does not leave objects that could have been taken (while obeying the
rule of the game). Hence, playing [0, 1, 0, 1, 0, 1] is reasonable, whereas playing [0, 1, 0, 0, 0, 1]
or [0, 1, 0, 1, 0, 0] is not. How can the reasonable ways of playing be characterized?
Question 4. The objective of the remainder of the problem is to count the number of 18 - Q 4
reasonable ways of playing, in other words, the number of n sized binary vectors related to
all reasonable ways of playing. For a n sized game, nbRWP0 (n) (respectively nbRWP1 (n))
denotes the number of reasonable ways of playing where the nth location of the vector is 0
(respectively 1). The total number of reasonable ways of playing, nbRWP(n), is obviously
the sum nbRWP0 (n) + nbRWP1 (n).

Prove that:
nbRWP0 (1) = 0, nbRWP1 (1) = nbRWP0 (2) = nbRWP1 (2) = nbRWP0 (3) =
nbRWP1 (3) = 1
and that for n > 3:
nbRWP0 (n) = nbRWP1 (n − 1)
nbRWP1 (n) = nbRWP1 (n − 2) + nbRWP1 (n − 3).

Question 5. Prove that: 18 - Q 5


nbRWP(1) = 1, nbRWP(2) = 2, nbRWP(3) = 2
and that for n > 3:
nbRWP(n) = nbRWP(n − 2) + nbRWP(n − 3).

Question 6. Give the values of nbRWP0 (n), nbRWP1 (n) and nbRWP(n) for n varying 18 - Q 6
from 1 to 15. Independently of nbRWP0 , which relation ties nbRWP and nbRWP1 ? Would
it have been possible to establish it before?
Question 7. Give the algorithm calculating nbRWP(n) for a given value n. 18 - Q 7

The solution is on page 61.

i i

i i
i i

i i

44 Mathematics and computer science: some useful notions

Problem 19. The game of two stacks ◦ •


In this problem, one is interested in the number nbWW of ways to win in a game where
tokens located in two stacks are added or removed. A property of nbWW is pointed out and
proven by induction.

Let us consider a game where two stacks P and Q containing respectively p and q
tokens (p, q > 1) are available. The goal is to reach one of the configurations (p = 0, q = 1)
or (p = 1, q = 0), called winning state later. The evolution of the stacks obeys the following
procedure: two tokens are removed from P (respectively Q), one is thrown away and the
other is added to Q (respectively P).
Example. (p = 4, q = 6) −→ (p = 2, q = 7) or (p = 5, q = 4).
We want to know the number nfg(p, q) of distinct ways allowing to reach one of the two
winning states starting from a configuration where stack P contains p tokens and stack Q
has q tokens.
19 - Q 1 Question 1. Give the recurrence expression of nbWW(p, q).
19 - Q 2 Question 2. Propose a tabular structure associated with the calculation of nbWWg as
well as the progression of its filling.
19 - Q 3 Question 3. Deduce an iterative algorithm for the computation of the number of dis-
tinct ways allowing to reach one of the two winning states of the game.
19 - Q 4 Question 4. Use this algorithm to compute nbWW(4, 2).
19 - Q 5 Question 5. Prove that any element nbWW(i, j), such that |i − j| is a multiple of 3, is
equal to 0 (excepted nbWW(0, 0), which makes no sense).
The solution is on page 63.

Problem 20. The yellow coins ◦ •


This problem raises the (apparently) simple problem of enumerating the distinct ways for
forming one euro with yellow coins. It is shown that the intuitive approach based on a single
index recurrence is not appropriate and that it is necessary to call on a double index one. The
approach developed here has a follow up in problem 148, page 689.

One wants to know the number of distinct ways for forming the amount of one euro
with yellow coins, in other words, using the six following coins of the European currency
system: 1, 2, 5, 10, 20 and 50 cents.
20 - Q 1 Question 1. Let us first reason in order to form any amount ranging from one to nine
cents. Obviously, there is a single solution to form the amount of one cent. For two cents,
one can take a single coin (two cents), or a one cent coin and one cent remains to be formed.
To form the amount s of three or four cents, one takes a one cent coin and the amount (s−1)
remains to be formed, or one takes a two cent coin and the amount (s − 2) remains to be
formed. To form five cents, one takes a single coin (five cents), or a one cent coin and the
amount of four cents remains to be formed, or a two cent coin and the amount of three
cents remains to be formed. Last, to form the amount s from six to nine cents, one takes
a five cent coin and the amount (s − 5) remains to be formed, or a one cent coin and the
amount (s − 1) remains to be formed, or a two cent coin and the amount (s − 2) remains

i i

i i
i i

i i

Problems 45

to be formed. One deduces the following recurrence defining nbWF1E(1), the number of
ways for forming one euro:

nbWF1E(1) = 1
nbWF1E(2) = 1 + nbWF1E(1)
nbWF1E(i) = nbWF1E(i − 1) + nbWF1E(i − 2) 3⩽i⩽4
nbWF1E(5) = 1 + nbWF1E(4) + nbWF1E(3)
nbWF1E(i) = nbWF1E(i − 5) + nbWF1E(i − 2) + nbWF1E(i − 1) 6 ⩽ i ⩽ 9.

Explain why this recurrence is not convenient.


Question 2. Propose a double index recurrence to calculate the number of ways for 20 - Q 2
forming one euro with yellow coins.
Question 3. Check that there are two ways for forming three cents. 20 - Q 3

Question 4. Write the iterative program performing the computation of the number of 20 - Q 4
ways for forming one euro with yellow coins.
Question 5. What is the number of ways for forming one euro with yellow coins? 20 - Q 5

Question 6. Prove that the number of ways for forming the amount m with all yellow 20 - Q 6
coins grows with m.
The solution is on page 65.

Problem 21. Shuffling words ◦ •


We define the shuffle operation of two words and want to determine the number of possible
shuffles of two given words. We also want to decide whether a word can be the result of the
shuffle of two others.

Let us take three words: u of length m, v of length n and w of length (m + n). The word
w is said to be a shuffle of the two words u and v if it obtained in shuffling the letters of
u and v while preserving their order of the letters in u and v. For example, with u = nose
and v = lips, the word w = nolispse is a shuffle of u and v, but not the word nlsoipes.
Question 1. Give a recurrence relation for the calculation of nbShuf(m, n) the number 21 - Q 1
of distinct shuffles that can be obtained from u and v, or more generally from any pair of
words of respective lengths m and n. What is the value of nbShuf(5, 4)?
Question 2. Prove by induction that nbShuf(m, n) = (m + n)!/(m! · n!). How could 21 - Q 2
we have found this result directly?
Question 3. Write an algorithme which decides if a word w is a shuffle of the words u 21 - Q 3
and v. Apply it to u = abc, v = db and w = dabbc.
The solution is on page 68.

i i

i i
i i

i i

46 Mathematics and computer science: some useful notions

1.10 Solutions
Answers to problem 1. Is a neutral element unique ? The problem is on page 33.
1-A1 Answer 1. Since the operator ⊕ is commutative, one has:

∀x · (x ∈ S ⇒ u ⊕ x = x ⊕ u).

u is a left neutral element, then u ⊕ x = x and x ⊕ u = x. It can be deduced that v is also


the right neutral element.
1-A2 Answer 2. Let us assume that the left neutral element u and the right neutral element
v of ⊕ are distinct. Since u is a left neutral element, one has: u ⊕ v = v. Similarly, since v is a
right neutral element, one has: u ⊕ v = u. Assuming that u ̸= v leads to say that operation
u ⊕ v has two different results, which contradicts the definition of an internal operation.
Consequently, since the assumption that u are v distinct leads to a contradiction, u and v
are necessarily equal.

Answers to problem 2. Minimum element of a partially ordered set The


problem is on page 33.
2-A1 Answer 1. Let us assume that any element x of F has at least one strict antecedent,
i.e. for any x ∈ F there is a element a(x) such that a(x) ̸= x and a(x) ⪯ x. In such a
case, there is at least one element a(a(x)) = a2 (x) and at least one element an (x) for any
integer n ⩾ 1. As soon as n exceeds the cardinality of F, in the series an (x), . . . , a(x) there
is at least an element appearing twice (or more) 4 . Thus, one has a situation of the type
a1 ⪯ a2 ⪯ . . . ⪯ ap ⪯ a1 , where all the elements a1 , . . . , ap are distinct, which is impossible,
since it contradicts the definition of a partial order relation whose antisymmetry property
entails that a ⪯ b and b ⪯ a ⇒ a = b.
The hypothesis according to which any element x of F has at least one strict antecedsent,
is thus false. Consequently, F contains one element without any strict antecedent, i.e. a
minimum element.
2-A2 Answer 2. The demonstration is based on a proof by induction (simple recurrence)
about the cardinality of F. P(n) is the following property “any strict subset F of E whose
size is n involves at least one minimum element”.
Initialization Any subset F of E whose cardinality is 1 involves one minimum element
(the single element of F).
Induction Let F be a strict subset of E with n elements that possesses a minimum element
m (induction hypothesis). Let us now consider the set F with an additional element
x (from E) that is not already in F. (x does exist since F is a strict subset of E). Three
exclusive cases can be singled out:
• x ⪯ m, and by transitivity (of the partial order relation ⪯), x is the minimum ele-
ment of F ∪ {x},
• m ⪯ x and m becomes the minimum element of F ∪ {x},
• m and x are not tied via the order relation and m is the minimum element of F ∪ {x}.
Conclusion P(1) holds, and moreover P(n) ⇒ P(n + 1), so P(n) holds for any integer n.
4 This claim is a consequence of the “pigeonhole principle ”, which states that when (k + 1) objects (or more)

are stored in k boxes, at least one box contains two (or more) objects.

i i

i i
i i

i i

Solutions 47

Answer 3. From the statement of the problem, one has: 2-A3

F = {(1, 2), (2, 1), (3, 1), (3, 2)}.

The element (1, 2) has no strict antecedent and is therefore a minimum of F. The same holds
for (2, 1). F possesses two minimum elements.

Answers to problem 3. Factorial vs exponential The problem is on page 33.


Answer 1. We follow the steps of the simple induction reasoning. 3-A1
0
Initialization For n = 1, one has 1! = 1 and 2 = 1, the (non strict) inequality holds.
Induction Suppose that the inequality hols for n ⩾ 1 (induction hypothesis). For (n + 1),
one has:
(n + 1)!
= definition of the factorial
(n + 1) · n!
⩾ induction hypothesis
(n + 1) · 2n−1
⩾ n ∈ N1 ⇒ n ⩾ 1
2 · 2n−1
= arithmetics
2n .

Conclusion The inequality holds for n = 1 as well as for (n + 1) if it does for n. It can be
deduced that n! ⩾ 2n−1 for any strictly positive integer n.

Answer 2. It is easy to observe that the inequality n! ⩾ n2n does not hold until n = 8 3-A2
since 8! = 40320 and 216 = 65536. On the contrary, it holds for n = 9 since 9! = 362880 and
218 = 262144.
We now prove that for n ⩾ 9, if n! > 22n then (n + 1)! > 22n+2 . One has:

(n + 1)!
= definition of a factorial
(n + 1) · n!
> induction hypothesis
(n + 1) · 22n
> n⩾9
4 · 22n
= property of the exponential
22n+2 .

It can be deduced that the proposed property (n! > 22n ) for any integer n strictly greater
than 8.

Answers to problem 4. Currency change (1) The problem is on page 34.

Answer 1. The proof of validity of this pattern is made in a way similar to the one used 4-A1
in section 1.1.3.1, page 4.

i i

i i
i i

i i

48 Mathematics and computer science: some useful notions

4-A2 Answer 2. First, this pattern is used to demonstrate the property claiming that any
amount of money n (strictly) greater than five cents may be obtained with coins of two
and seven cents.
Initialization We take n0 = 6 since it is impossible to form the amount of five cents with
the two considered coins. It is possible to obtain the amount of six (respectively seven)
cents with three two cent coins (respectively one seven cent coin).
Induction Suppose that the property holds for any amount n ⩾ 6 (induction hypothesis).
To form the amount (n + 2), it is sufficient to add one two cent coin to the combina-
tion of coins serving for the amount n (which does exist according to the induction
hypothesis).
Conclusion The property holds for any amount n ⩾ 6.

4-A3 Answer 3. We now proceed to the demonstration using the “regular” proof by simple
induction (see section 1.1.3.1, page 4).
Initialization The amount of six cents is obtained with three two cent coins.
Induction Assume that the property holds for a given value of n (n ⩾ 6). Two exclusive
cases occur:
• The amount n has been obtained with at least one seven cent coin. This coin is
discarded, four two cent coins are added and the amount n + 1 is thus formed.
• The amount n has been obtained only with two cent coins. Three of these coins are
removed and one seven cent coin is added, which makes the amount n + 1.
Conclusion The amount of six cents can be formed with two cent coins and (no) seven cent
coins and if it is possible to form the amount n, we know how to form the amount
(n + 1) with these coins. Hence, it is possible to form any amount strictly over five
cents with two and seven cent coins.

4-A4 Answer 4. According to the first pattern, only one seven cent coin can appear (pre-
cisely that used to form the amount of seven cents), since then only two cent coins are
added. It is the same with the second pattern, since as soon as a seven cent coin appears, it
is removed.
4-A5 Answer 5. The first (respectively second) pattern requires to prove the validity of the
property for n0 and n0 + 1 (respectively n0 ). On the contrary, in this example, the proof of
the induction step is shorter with the first schema where no distinction between situations
has to be made.

Answers to problem 5. Catalan numbers The problem is on page 34.

5-A1 Answer 1. We proceed using proof by simple induction.


Initialization For n = 1, the proposed closed form yields: 0!/(0! · 1!) = 1 (assuming that
0! = 1).
Induction Assume that, for n ⩾ 1, the closed form is suitable (induction hypothesis). For
(n + 1), the general term of the recurrence relation yields:
Cat(n + 1)
= general term of the recurrence relation
4(n + 1) − 6
· Cat(n)
n+1
= induction hypothesis

i i

i i
i i

i i

Solutions 49
4n − 2 (2n − 2)!
·
n + 1 (n − 1)! · n!
= arithmetics
(4n − 2) · (2n − 2)!
(n − 1)! · (n + 1)!
= numerator and denominator multiplied by n
(4n2 − 2n) · (2n − 2)!
n! · (n + 1)!
= arithmetics
(2n)!
n! · (n + 1)!
this latter expression being nothing but the closed form for (n + 1).
Conclusion The closed form holds for n = 1, and if it holds for n ⩾ 1, it does for (n + 1).
It can be concluded that the closed form is suitable for any positive value n.

Answer 2. Here again, a proof by simple induction is performed. 5-A2

Initialization For n = 1, one has Cat(1) = 1 and 4 n−1


/n = 1; the property holds.
Induction Assume that, for n ⩾ 1, the property holds (induction hypothesis). For n + 1,
one has:
Cat(n + 1)
= general term of the recurrence relation
4(n + 1) − 6
· Cat(n)
n+1
⩽ induction hypothesis
4(n + 1) − 6 4n−1
·
n+1 n
= rewriting
4n − 2 4n−1
·
n n+1
< (4n − 2)/n < 4 for n ⩾ 1
4n
n+1

Conclusion The property holds for any integer n.

Remark
Equality occurs only for n = 1. Beyond, 4n−1 /n is a strict upper bound for Cat(n). Hence,
one has: Cat(2) = 1 < 41 /2 (= 2), Cat(3) = 2 < 42 /3 (≈ 5.33), Cat(5) = 14 < 44 /5 (= 51.2).

Answers to problem 6. Erroneous proofs by simple induction The problem is


on page 35.

Answer 1. When we write: 6-A1


If max(a, b) = 0, then a = b = 0
we comply with the fact that the numbers under consideration are integers. The flaw is not
there, but in the following line that does not comply with the induction hypothesis with
p ⩾ 0:
The maximum of (a − 1) and (b − 1) is then p.

i i

i i
i i

i i

50 Mathematics and computer science: some useful notions

As a matter of fact, this line may produce negative numbers (when a or b equals 0): we are
no longer in the scope of property P1 applying to integers. Take the numbers a = 0 and
b = 1. One has: a − 1 = −1 and b − 1 = 0. Their maximum is 0 whereas these two numbers
are both equal to 0 (and therefore equal).
6-A2 Answer 2. The fallacy lies in the following sentence:
The two straight lines (d1 ) and (d2 ) have the two points A2 and A3 in common.
So that this claim is true, the number of points must be strictly over 2 (p ⩾ 3), in order to
be able to use points A2 and A3 . The induction hypothesis must start with p > 2. However,
for p = 2, the straight line (d1 ) is (A1 A2 ) and the straight line (d2 ) is (A2 A3 ), and they have
only one point (A2 ) in common and generally they are not collinear.

Answers to problem 7. Erroneous proof by strong induction The problem is


on page 36.

7-A1 Answer 1. The flaw appears when writing (implicitly for any n ⩾ 2):
2
((n − 1) − 1)/(n − 2) = n.
As a matter of fact, a division by (n − 2) is performed, but this denominator is equal to 0
when n = 2, and the division is illegal.
7-A2 Answer 2. For any n ⩾ 1, the following identity holds:
p
n = 1 + (n − 1)(n + 1).
p
In the right member, let us replace (n + 1) by 1 + n(n + 2), it yields:
q p
n = 1 + (n − 1) 1 + n(n + 2).
p
Now, let us replace (n + 2) by 1 + (n + 1)(n + 3), we get:
r q p
n = 1 + (n − 1) 1 + n 1 + (n + 1)(n + 3).

The substitution mechanism can be repeated for (n + 3), then (n + 4) and so on, and this
results in the proposed formula, namely:
s r q p
n = 1 + (n − 1) 1 + n 1 + (n + 1) 1 + (n + 2) . . . .

Answers to problem 8. Alternate pattern for two indexes recurrence


proof The problem is on page 37.

We use the total order relation over N1 2 given in section 1.1.6, page 9, namely:

b a < c or (a = c and b ⩽ d).


(a, b) ⪯ (c, d) =
The pattern suggested above aims at establishing that if P holds for any point of the rect-
angle (1 .. m, 1 .. n) – m = 1 or n = 1 is accounted for in the initialization – then P holds
also for any point (m + 1, 1) to (m + 1, n) and for any point (1, n + 1) to (m, n + 1); thus,
P holds for all the points “lower” (in the sense of ⪯) than the point (m + 1, n + 1). If, in
addition, we prove that P holds in (m + 1, n + 1), the newly proposed pattern of proof is
an instance of property (1), page 9, for the pair (N1 2 , ⪯).

i i

i i
i i

i i

Solutions 51

Answers to problem 9. Divisibility by 7 The problem is on page 38.

Answer 1. Let A(n, p) = q, where q is a nonnegative integer, then we have 32n = 9-A1
2n−p + q. By definition:
A(n + 1, p) = 32(n+1) − 2(n+1)−p = 9 · 32n − 2 · 2n−p .
Replacing 32n by (2n−p + q) in the right part of the preceding expression, we get:
A(n + 1, p) = 9 · (2n−p + q) − 2 · 2n−p = 7 · 2n−p + 9 · q.
This latter expression is likely to produce a multiple of 7 only if q (indeed A(n, p)) is itself
a multiple of’7. Thus, we have:
A(n, p) = q = 7k and A(n + 1, p) = 7 · (2n−p + 9k).
Consequently, if A(n, p) is a multiple of 7, A(n + 1, p) is also one and if A(n, p) cannot be
divided by 7, A(n + 1, p) cannot either.
Answer 2. From the previous answer, A(n, p) is made of integers multiple of 7 if and 9-A2
only if the first term of the series (A(n0 , p) = A(p, p)) is a multiple of 7. The first term of
each of the four proposed series is now considered:
• the first terms of the series A(n, 0) is A(1, 0) = 32 − 21 = 7 and A(2, 0) = 77 and the series
is made of integers multiple of 7 for any positive integer n,
• the series A(n, 1) starts with A(1, 1) = 32 −20 = 8, and this series is not made of numbers
multiple of 7 for any positive integer n,
• the first term of the series A(n, 2) is A(2, 2) = 34 − 20 = 80, and this series is not made of
multiples of 7 for any integer n strictly greater than 1,
• the series A(n, 3) starts with A(3, 3) = 36 − 20 = 728 = 7 · 104. It can be deduced that any
element of the series A(n, 3) can be divided by 7 for any integer n strictly greater than 2.

Answers to problem 10. Proof by induction vs direct proof The problem is on


page 38.

Answer 1. For n = 1, the suggested closed form yields A(1) = 1, which matches the 10 - A 1
value given by the recurrence formula. We will demonstrate that for any n > 1:

(n + 1)2 − (n + 1) + 1 n2 + n + 1
A(n + 1) = = .
(n + 1)2 (n + 1)2

One has:
(n + 1)2 − 3(n + 1) + 1 n2 − n − 1
A(n + 1) = A(n) + = A(n) +
n2 · (n + 1)2 n2 · (n + 1)2
and replacing A(n) by its value given by the recurrence relation:
n2 − n + 1 n2 − n − 1 n4 + n3 + n2 n2 + n + 1
A(n + 1) = + = =
n2 n2 · (n + 1)2 n2 · (n + 1)2 (n + 1)2
which is the expected expression.
The numerator and the denominator of the expression defining numbers A(n) are integers,
hence these numbers are rational ones.

i i

i i
i i

i i

52 Mathematics and computer science: some useful notions

On the other hand, they are positive since for any positive integer n:
 2
n2 − n + 1 n−1
A(n) = > ⩾ 0.
n2 n

10 - A 2 Answer 2. The “direct” demonstration of the property:

∀n · ((n ∈ N1 and n > 2) ⇒ (1 > A(n) > 3/4))


is easy and thus preferred to that by induction. First, let us work out (A(n) − 3/4):
 2
3 n2 − n + 1 3 n2 − 4n + 4 n−2
A(n) − = − = =
4 n2 4 4n2 2n
expression whose value is strictly positive for n > 2. Let us now determine the sign of
(1 − A(n)). One has:
n2 − n + 1 n−1
1 − A(n) = 1 − = .
n2 n2
Yet, ((n − 1)/n2 ) has a strictly positive value for n > 1. One concludes that, for n ⩾ 3, A(n)
is strictly greater than 3/4 (A(2)) and strictly less than 1 (A(1)).

Answers to problem 11. The lizard sequence The problem is on page 38.

11 - A 1 Answer 1. We denote by a and b the first two terms of a sequence S obeying the con-
straints of the statement. We will prove that, if we assume that the (3k − 1) first terms of
the sequence S = ⟨a, b, s3 , . . . , s3k−1 , . . .⟩ for k ⩾ 1 are known, the next three terms can be
identified. Then, it will be possible to deduce that it is possible to build a lizard sequence
S as long as desired. We use a proof by strong induction.
Induction For k ⩾ 1, the first (3k − 1) terms of S are assumed to be known (induction
hypothesis). Then:
S = ⟨a, b, s3 , . . . , s3k−1 , x, y, z, . . .⟩
and we want to determine the value of the terms x, y and z of respective rank 3k, 3k+1
and 3k + 2. More precisely, the three sequences are written:
S = ⟨a, b, s3 , . . . , sk , . . . , s2k+1 , s2k+2 . . . , s3k−1 , x, y, z, . . .⟩
S/3 = ⟨s3 , . . . , x, . . .⟩
S − S/3 = ⟨a, b, . . . , y, z, . . .⟩.
It turns out that: (i) x is the kth term of S/3 and it should be equal to the kth term of
S, so x = sk and sk is known since k ∈ 1 .. 3k − 1, (ii) y is the (2k + 1)th term of S − S/3
and it should be equal to the (2k + 1)th term of S, so y = s2k+1 . Now, (2k + 1) is in
the range 1 .. 3k − 1 only if k ⩾ 2. However, for k =1, the term s2k+1 is none other
than x which we know from the above, (iii) z is the (2k + 2)th term of S − S/3 and it
should be equal to the (2k + 2)th term of S, so z = s2k+2 . Now, (2k + 2) is in the range
1 .. 3k − 1 only if k ⩾ 3. However, for k = 1, the term s2k+2 is none other than y which
is known from the above, and if k = 2, the term s2k+2 is identified with x also known.
Conclusion It is possible to build a sequence S of any length given the first two terms a
and b.

11 - A 2 Answer 2. The first 20 elements of S are:


⟨a, b, a, a, a, b, a, b, a, a, b, a, a, a, a, b, a, b, a, a⟩.

i i

i i
i i

i i

Solutions 53

In addition to the two trivial sequence made solely of 0’s or 1’s, there are two lizard se-
quences, depending on the value (0 or 1) taken by a and b:

S1 = ⟨0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0⟩
S2 = ⟨1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1⟩
where S2 (respectively S1 ) is obtained from S1 (respectively S2 ) by the inversion of 0’s and
1’s.

Answers to problem 12. Fibonacci sequence; about the closed form The
problem is on page 39.

Answer 1. Programming directly the proposed formula delivers a real number, not an 12 - A 1
integer value as expected. In the experiment
√ that we have conducted with the language
Ada provided by the Ideone platform, 5 = 2.236068 and the simple precision number
representation, a difference between the exact value and the integer part of the real result
appears from n = 68.
Answer 2. The computation of the nth Fibonacci number is performed in an iterative 12 - A 2
fashion based on the recurrence. It can be noticed that, as for the computation of a factorial,
keeping values F(1) to F(n−1) is useless for the computation of F(n). Only three variables
are necessary x, y and z, which play the role of F(n − 2), F(n − 1) and F(n). The program
is the following:

1. constants
2. n ∈ N1 − {1, 2} and n = . . .
3. variables
4. x ∈ N1 and y ∈ N1 and z ∈ N1
5. begin
6. x ← 1; y ← 1 ;
7. for i ranging 3 .. n do
8. z ← x + y; x ← y; y ← z
9. end for;
10. write(Fibonacci number of rank , n, is , z)
11. end

Answers to problem 13. How many binary trees have n nodes? The problem
is on page 40.
Answer 1. Let j = i + 1, for n ⩾ 1, nbBT (n) can be rewritten: 13 - A 1
X
n
nbBT (n) = nbBT (j − 1) · nbBT (n − j).
j=1

Let T (j) = nbBT (j − 1), one has:


Xn
T (n + 1) = T (j) · T (n − j + 1).
j=1

Yet, the (n + 1) Catalan number is defined by:


th

Xn
Cat(n + 1) = Cat(i) · Cat(n − i + 1).
i=1

i i

i i
i i

i i

54 Mathematics and computer science: some useful notions

Since nbBT (0) = Cat(1) = 1, one has:

nbBT (n) = Cat(n + 1) n ⩾ 0.

13 - A 2 Answer 2. We have seen the closed form of Catalan numbers on page 11, namely:

(2n − 2)! 1
Cat(n) = = · Cn−1
2n−2 n ⩾ 1.
(n − 1)! n! n
The value nbBT (n) can be written thanks to the previous expression of the (n + 1)th Cata-
lan number:
nbBT (0) = 1
nbBT (1) = 1
1 (n + 2) · · · 2n
nbBT (n) = Cat(n + 1) = · Cn
2n = n > 1.
n+1 2···n
The corresponding program is:

1. constants
2. n ∈ N and n = . . .
3. variables
4. NBBT ∈ N1 and Denom ∈ N1
5. begin
6. NBBT ← 1;
7. for i ranging n + 2 .. 2n do
8. NBBT ← NBBT · i
9. end for;
10. Denom ← 1;
11. for i ranging 2 .. n do
12. denom ← Denom · i
13. end for;
14. NBBT ← NBBT/Denom;
15. write(the number of binary trees having , n, nodes is , NBBT )
16. end

Answers to problem 14. Identifying a closed form The problem is on page 40.
14 - A 1 Answer 1. To compute a(3, 2), we need the values a(2, 1), a(2, 2) and a(2, 3), which,
in turn, require the knowledge of a(1, 0), . . . , a(1, 4). The calculation of these latter values
is based on a(0, 0), . . . , a(0, 5), values obtained directly from the recurrence formula (first
line).
The values are computed as follows: (i) elements whose first index is 0 and second index
j ranges 0 .. 5, thanks to the first line of the recurrence formula, (ii) element a(1, 0) with
the second line of the recurrence, and elements whose first index equals 1 and second
index ranges 1 .. 4 using the third term of the recurrence, (iii) elements a(2, 1), a(2, 2) and
a(2, 3) with the third line, and last (iv) element a(3, 2) using once again the third line.
From a concrete point of view, the computations will result in the (partial) filling of the
array A[0 .. i, 0 .. i + j] whose values are reported in figure 1.10, page 55.
The calculation of a(i, j) corresponds to the filling of cell A[i, j]. We start with cells
A[0, max({j − i, 0})] to A[0, j + i] (first line of the recurrence), then (when i > 0) cells
A[k, max({j − i + k, 0})] to A[k, j + i − k] of any line whose index k is varying from 1

i i

i i
i i

i i

Solutions 55

j 0 1 2 3 4 5
i=0 1 2 3 4 5 6
1 4 8 12 16 20
2 32 48 64
3 192

Fig. 1.10 – Array A associated with the calculation of a(3, 2).

to i, using the second (respectively third) line of the recurrence for the first cell when
max({j − i + k, 0}) = 0 (respectively max({j − i + k, 0}) > 0) and the third line for all
other cells.
Answer 2. The following algorithm computes the value of cell A[n, m] related to 14 - A 2
a(n, m) according to the previously described progression.
1. constants
2. n ∈ N and n = . . . and m ∈ N and m = . . .
3. variables
4. A ∈ 0..n × 0..n + m → N1
5. begin
6. for j ∈ 0 .. m + n do
7. A[0, j] ← j + 1
8. end for;
9. for i ranging 1 .. n do
10. for j ranging max({m − n + i, 0}) .. n + m − i do
11. if j = 0 then
12. A[i, 0] ← 2 · A[i − 1, 0] + A[i − 1, 1]
13. else
14. A[i, j] ← A[i − 1, j − 1] + 2 · A[i − 1, j] + A[i − 1, j + 1]
15. end if
16. end for
17. end for;
18. write(the value of the sequence in , n, m, is , A[n, m])
19. end

Remark
We invite the reader to design another version where a two row array A is used.
Answer 3. It turns out that the formula a(i, j) = (j + 1) · 4i for i, j ⩾ 0 holds over the 14 - A 3
whole array of figure 1.10, page 55.
So as to prove it by induction, it is necessary to use a valid proof pattern. A glance at the
recurrence formula defining a(i, j) leads to think that neither the pattern given in page
9, nor that proposed in problem 8 page 37 is suitable, since their initialization requires to
demonstrate the validity of the formula for the first column of the tabular structure. From
the partial order relation ⪯ over N2 defined in section 1.1.6, page 9:

b a < c or (a = c and b ⩽ d)
(a, b) ⪯ (c, d) =

it is easy to show that the following pattern (of proof) is an instance of the property (1)
page 9, for the pair (N2 , ⪯):

i i

i i
i i

i i

56 Mathematics and computer science: some useful notions

If the two following properties can be proven:


Initialization P(0, j) holds for any j ⩾ 0
  
i ∈ N and  
k ∈ 0 .. j − 1
Induction ∀(i, j) ·  j ∈ N and  ⇒ ∀k · 
⇒P(i + 1, k)
P(i, j)
then:
Conclusion P(n, m) holds for any pair of integers n, m such that n ⩾ 0 and
m ⩾ 0.

It can be noticed that the proof to be done requires only an order over lines, but that the
reference property (property 1), page 9) requires a total order. This pattern is now used to
prove that

∀(i, j) · (i ∈ N and j ∈ N ⇒ a(i, j) = (j + 1) · 4i ).


Initialization Let us consider the formula for the elements a(0, j). By definition of the
sequence, one has a(0, j) = j + 1. Yet, j + 1 = (j + 1) · 40 for any j ⩾ 0 and a(0, j) =
(j + 1) · 4i holds for i = 0 and j ⩾ 0.
Induction Let us assume that the formula holds for any element whose first index is equal
to n (induction hypothesis) and let us demonstrate that it does for element a(n + 1, j)
(where j is an arbitrary nonnegative integer). Two cases can be singled out depending
on the value of j:
• When j = 0, by definition a(i, 0) = 2 · a(i − 1, 0) + a(i − 1, 1). From the induction
hypothesis, one can write a(i, 0) = 2·(0+1)·4i−1 +(1+1)·4i−1 = 4·4i−1 = (j+1)·4i .
• When j > 0, the last term of the recurrence states that a(i, j) = a(i − 1, j − 1) + 2 ·
a(i − 1, j) + a(i − 1, j + 1). Using the induction hypothesis to rewrite each of the
terms of the right hand side, we get:
a(i, j) = (j − 1 + 1) · 4i−1 + 2(j + 1) · 4i−1 + (j + 1 + 1) · 4i−1 = 4(j + 1) · 4i−1
= (j + 1) · 4i .
Conclusion Formula a(i, j) = (j + 1) · 4i holds for any nonnegative integers i and j.
The use of the closed form allows to build the following program computing a(i, j):

1. constants
2. n ∈ N and n = . . . and m ∈ N and m = . . .
3. begin
4. write(the value of the sequence in , n, m, is , (m + 1) · 4n )
5. end
both simpler and more efficient than the algorithm of the previous question.

Answers to problem 15. Moving a knight under constraints The problem is


on page 41.

15 - A 1 Answer 1. In general, there are four possibilities for reaching the square (i, j) in a single
move: the knight was in (i − 2, j − 1) or in (i − 1, j − 2) or in (i + 1, j − 2) or in (i + 2, j − 1).
It can be deduced that for 3 ⩽ i ⩽ n − 2 and 3 ⩽ j ⩽ m:

nbRout(i, j) = nbRout(i−2, j−1)+nbRout(i−1, j−2)+nbRout(i+1, j−2)+nbRout(i+2, j−1).

i i

i i
i i

i i

Solutions 57

This formula does not hold when i or j ar equal to 1 or 2 as well as when i is (n − 1) or n.


This leads to the (complete) recurrence hereafter:

nbRout(1, 1) = nbRout(3, 2) = 1
nbRout(i, 1) = 0 2⩽i⩽n
nbRout(i, 2) = 0 1 ⩽ i ⩽ n and i ̸= 3
nbRout(1, j) = nbRout(3, j − 1) + nbRout(2, j − 2) 3⩽j⩽m
nbRout(2, j) = nbRout(3, j − 2) + nbRout(1, j − 2) + nbRout(4, j − 1) 3⩽j⩽m
nbRout(n, j) = nbRout(n
 − 2, j − 1) + nbRout(n
 − 1, j − 2) 3⩽j⩽m
nbRout(n − 3, j − 1)+
nbRout(n − 1, j) =  nbRout(n − 2, j − 2)+  3⩽j⩽m
nbRout(n, j − 2)
 
nbRout(i − 2, j − 1)+ 
 nbRout(i − 1, j − 2)+   3⩽i⩽n−2
nparc(i, j) = 
 nbRout(i + 1, j − 2)+ 
 and .

3⩽j⩽m
nbRout(i + 2, j − 1)

Answer 2. The values of nbRout are stored in a n row, m column array, NR[1..n, 1..m]. 15 - A 2
Columns 1 and 2 are first initialized thanks to the first three terms of the recurrence. Due
to the fact that the calculation of any other square call only on values located “on its left
side”, columns 3 to m are then dealt with: the four extreme elements (row index 1, 2, (n−1)
and n) are calculated by means of terms 3 to 6 of the recurrence, others using the last term
of the recurrence (general case). This yields the following algorithm:

1. constants
2. n ∈ N1 − {1 .. 4} and n = . . . and m ∈ N1 − {1 .. 3} and m = . . .
3. variables
4. NR ∈ 1 .. n × 1 .. m → N1
5. begin
6. NR[1, 1] ← 1;
7. for i ranging 2 .. n do
8. NR[i, 1] ← 0
9. end for;
10. for i ranging 1 .. n do
11. NR[i, 2] ← 0
12. end for;
13. NR[3, 2] ← 1;
14. for j ranging 3 .. m do
15. NR[n, j] ← RP[n − 1, j − 2] + NR[n − 2, j − 1];
16. NR[n − 1, j] ← NR[n, j − 2] + NR[n − 2, j − 2] + NR[n − 3, j − 1];
17. NR[1, j] ← NR[2, j − 2] + NR[3, j − 1];
18. NR[2, j] ← NR[1, j − 2] + NR[3, j − 2] + NR[4, j − 1];
19. for i ranging 3 .. n − 2 do
20. NR[i, j] ← NR[i−2, j−1]+NR[i−1, j−2]+NR[i+1, j−2]+NR[i+2, j−1]
21. end for
22. end for;
23. write(the number of ways for moving from (1, 1) to (, n, , , m, ) is ,
NR[n, m])
24. end
Running this algorithm for n = 5 and m = 7 leads to the following array:

i i

i i
i i

i i

58 Mathematics and computer science: some useful notions

j 1 2 3 4 5 6 7
i=5 0 0 1 0 2 3 10
4 0 0 0 2 2 5 7
3 0 1 0 2 1 8 10
2 0 0 1 1 3 4 9
1 1 0 1 0 3 2 11

Answers to problem 16. How many partitions of n elements have p


blocks? The problem is on page 41.

16 - A 1 Answer 1. We have:
• one partition with one block: {{a, b, c, d}},
• seven partitions with two blocks: {{a, b}, {c, d}}, {{a, c}, {b, d}}, {{a, d}, {b, c}},
{{a}, {b, c, d}}, {{b}, {a, c, d}}, {{c}, {a, b, d}}, {{d}, {a, b, c}},
• six partitions with three blocks: {{a}, {b}, {c, d}}, {{a, b}, {c}, {d}}, {{a, c}, {b}, {d}},
{{a}, {c}, {b, d}}, {{a, d}, {b}, {c}}, {{a}, {d}, {b, c}},
• one partition with four blocks: {{a}, {b}, {c}, {d}}.

16 - A 2 Answer 2. The recurrence relation for S(p, n) is defined as follows:


Special cases For any n, there is a single partition with one block for a set having n ele-
ments, thus: S(1, n) = 1 for n ⩾ 1. Moreover, for any p > 1, when n < p, S(p, n) = 0,
since the number of blocks cannot exceed that of the elements in the set (let us remind
that no block can be empty). Last, for any p > 1, there is exactly one partition with p
elements for a p element set, and S(p, p) = 1.
General case When n increases by 1, the new element can constitute a new block (with
this single element), and there are S(p − 1, n) distinct possibilities, or added into one
of the p preexisting blocks, and there are p · S(p, n) possibilities.
The following recurrence formula can be deduced:

S(1, n) = 1 n⩾1
S(p, p) = 1 p>1
S(p, n) = 0 p>n
S(p, n) = p · S(p, n − 1) + S(p − 1, n − 1) n ⩾ 1 and p < n.

16 - A 3 Answer 3. The array S[1 .. p, 1 .. n] is used to compute the values associated with this
recurrence. Observing the recurrence, we can notice that, in the general case (fourth term),
the value of element S[i, j] depends on those of the two elements located in the preceding
column (j − 1), which makes it possible to proceed by increasing values of the column
index. Each column j is filled as follows: (i) cell S[1, j] is initialized to 1 (first term of the
recurrence), (ii) the general term is used for the calculation of any cell S[i, j] where i < j
and i ⩽ p, (iii) when the cell S[j, j] belongs to the array, it is set to 1, and finally (iv) any cell
S[i, j] where i > j is set to 0.
The corresponding algorithm is:

1. constants
2. n ∈ N1 and n = . . . and p ∈ N1 and p ⩽ n and p = . . .

i i

i i
i i

i i

Solutions 59

3. variables
4. S ∈ 1 .. p × 1 .. n → N
5. begin
6. S[1, 1] ← 1;
7. for i ranging 2 .. p do
8. S[i, 1] ← 0
9. end for;
10. for j ranging 2 .. n do
11. S[1, j] ← 1;
12. for i ranging 2 .. p do
13. if i < j then
14. S[i, j] ← i · S[i, j − 1] + S[i − 1, j − 1]
15. elsif i = j then
16. S[i, j] ← 1
17. else
18. S[i, j] ← 0
19. end if
20. end for
21. end for;
22. write(the number of partitions with , p, blocks of a set having , n,
elements
23. is , S[p, n])
24. end

Answer 4. For p = 5 and n = 7, the values obtained are reported in the array below: 16 - A 4

n 1 2 3 4 5 6 7
p=1 1 1 1 1 1 1 1
2 0 1 3 7 15 31 63
3 0 0 1 6 25 90 301
4 0 0 0 1 10 65 350
5 0 0 0 0 1 15 140

Answers to problem 17. Climbing a staircase The problem is on page 42.

Answer 1. Two possible sequences of jumps are ⟨5, 2, 5⟩ and ⟨2, 5, 5⟩, which shows that 17 - A 1
the order of the jumps matters (when they are different).
Answer 2. The recurrence relation is built according to the following observations: 17 - A 2
Special cases There is a single way to climb 0 steps with 0 jumps and therefore
nbCL(0, 0) = 1. Moreover, there is no way for jumping (at least one jump) without
climbing (at least one step) and nbCL(s, 0) = 0 for s ⩾ 1. Last, one has nbCL(0, m) = 0
for m > 0, since it is impossible to climb at least one step without jumping.
General case Let us suppose that we are on step m of the staircase after s jumps, with s
and m strictly positive. As s > 0, just before we made a jump (which led us to the step
m) from one of the steps from which step m can be reached with a single jump. The
count of ways to reach the step m with s jumps is thus equal to the sum of the ways
we had to reach these steps.

i i

i i
i i

i i

60 Mathematics and computer science: some useful notions

We end up with the recurrence given below:

nbCL(0, 0) = 1
nbCL(0, m) = 0 m>0
nbCL(s, 0) = 0 X s>0
nbCL(s, m) = nbCL(s − 1, m − ai ) s > 0 and m > 0.
i∈1..n and
(m−ai )⩾0

17 - A 3 Answer 3. To compute this recurrence, the array NBCL[0 .. s, 0 .. m] is used where the
cell NBCL[i, j] is associated with the element nbCL(i, j) of the recurrence. It can be ob-
served that the calculation of the cell NBCL(s, m) calls only on values whose first index is
immediately lower (s − 1). Hence, the calculation can progress by increasing values of row
indexes inasmuch as the first row (index 0) is initialized, which is performed by means of
the first two terms of the recurrence. Last, any row can be filled in from left to right after
setting the first element to 0, according to the third term of the recurrence.
The n values of the possible jumps (ai ) are stored in the array A[1 .. n], in increasing order
(without loss of generality). The corresponding algorithm is the following:

1. constants
2. n ∈ N1 and n = . . . and s ∈ N1 and s = . . . and m ∈ N1 and m = . . . and
3. A ∈ 1 .. n → N1 and A = [. . .]
4. variables
5. NBCL ∈ 0 .. s × 0 .. m → N
6. begin
7. NBCL[0, 0] ← 1;
8. for j ranging 1 .. m do
9. NBCL[0, j] ← 0
10. end for;
11. for i ranging 1 .. s do
12. NBCL[i, 0] ← 0;
13. for j ranging 1 .. m do
14. NBCL[i, j] ← 0;
15. for k ranging 1 .. n do
16. if j − A[k] ⩾ 0 then
17. NBCL[i, j] ← NBCL[i, j] + NBCL[i − 1, j − A[k]]
18. end if
19. end for
20. end for
21. end for;
22. write(the number of ways for climbing , m, steps with , s, jumps
23. is , NBCL[s, m])
24. end

A possible variant would consist in the suppression of lines 16 à 18 and the use of the array
NF whose column indexes range from −A[n] to m, NBCL[0..s, −A[n]..−1] being initialized
with 0’s.
17 - A 4 Answer 4. With the algorithm explicited above, for s = 6, m = 12, n = 2, a1 = 2 and
a2 = 5, the following array NF is produced:

i i

i i
i i

i i

Solutions 61

j 0 1 2 3 4 5 6 7 8 9 10 11 12
i=0 1 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 1 0 0 1 0 0 0 0 0 0 0
2 0 0 0 0 1 0 0 2 0 0 1 0 0
3 0 0 0 0 0 0 1 0 0 3 0 0 3
4 0 0 0 0 0 0 0 0 1 0 0 4 0
5 0 0 0 0 0 0 0 0 0 0 1 0 0
6 0 0 0 0 0 0 0 0 0 0 0 0 1

Answer 5. Using the array A whose values are increasing as previously stated, the 17 - A 5
number of steps reached with s jumps cannot be neither under s · A[1], nor above s · A[n],
which explains the 0’s appearing in the cells connected with these cases (for example,
columns with index j = 11 and j = 12 for i = 2 and the last ten columns for i = 5).
Consequently, we can envisage a variant of the initial algorithm where, after the initializa-
tion of any row with 0’s, the filling of row i is restricted to cells whose column index lies in
the interval i · A[1] .. max({m, i · A[n]}). Lines 11 to 21 of the previous algorithm are replaced
by:

1. for i ranging 1 .. s do
2. NBCL[i, 0] ← 0;
3. for j ranging 1 .. m do
4. NBCL[i, j] ← 0
5. end for;
6. for j ranging i · A[1] .. min({m, i · A[n]}) do
7. for k ranging 1 .. n do
8. if j − A[k] ⩾ 0 then
9. NBCL[i, j] ← NBCL[i, j] + NBCL[i − 1, j − A[k]]
10. end if
11. end for
12. end for
13. end for;

Answers to problem 18. The Patagon game The problem is on page 42.

Answer 1. Of course, several choices are possible, but the one looking like the best one 18 - A 1
(intuitively for the moment or after the evaluation of all legal choices) is the sequence ⟨23,
40, 42⟩, yielding the total amount 105.
Answer 2. 2n is the number of distinct subsets of a set having n elements, or the num- 18 - A 2
ber of distinct n sized binary vectors. This would be the number of unconstrained ways of
playing. But, for n > 1, there is at least one vector with two successive 1’s; therefore the
legal ways of playing are strictly less than 2n .
Answer 3. Any binary vector cannot contain two successive 1’s and a reasonable vec- 18 - A 3
tor cannot have three consecutive 0’s either (in such a case, that of the middle could be
replaced by 1). In addition, it can neither start, nor end with 00.
Answer 4. The first six expressions are established by enumeration. For a 1 sized 18 - A 4
game, the only reasonable possibility is to take its single object, and nbRWP0 (1) = 0
and nbRWP1 (1) = 1. For a 2 sized game, 01 and 10 only are reasonable choices, and
nbRWP0 (2) = nbRWP1 (2) = 1. Last, with a 3 sized game, the reasonable configurations

i i

i i
i i

i i

62 Mathematics and computer science: some useful notions

are: 010 et 101, therefore nbRWP0 (3) = nbRWP1 (3) = 1. The general term of the recurrence
is developed in studying the four exclusive exhaustive cases of n-sized reasonable vectors
with n > 3: V1 = [. . . , 0, 0, 1, 0], V2 = [. . . , 1, 0, 1, 0], V3 = [. . . , 1, 0, 0, 1], V4 = [. . . , 0, 1, 0, 1].
It can be remarked that when removing the final 0 in V1 and V2 , we obtain a reasonable
vector with 1 in position n − 1, thus nbRWP0 (n) = nbRWP1 (n − 1). It is not the case
when removing the final 1 in vectors V3 and V4 , since then, if V4′ = [. . . , 0, 1, 0] is clearly a
reasonable vector, V3′ = [. . . , 1, 0, 0] is not. It is necessary to study carefully what happens
when the last two elements of V3 are suppressed. We then get V3′′ = [. . . , 1, 0], which is a
reasonable vector and it can be deduced that:
nbRWP1 (n) = nbRWP0 (n−1)+nbRWP0 (n−2) = nbRWP1 (n−2)+nbRWP1 (n−
3)
using the definition of nbRWP0 established before.
18 - A 5 Answer 5. The values nbRWP(1), nbRWP(2) and nbRWP(3) are obtained by the cor-
responding values of nbRWP0 and nbRWP1 , i.e.:
nbRWP(1) = nbRWP0 (1) + nbRWP1 (1) = 0 + 1 = 1,
nbRWP(2) = nbRWP0 (2) + nbRWP1 (2) = 1 + 1 = 2,
nbRWP(3) = nbRWP0 (3) + nbRWP1 (3) = 1 + 1 = 2.
For n > 3, using the definition one gets:
nbRWP(n) = nbRWP0 (n) + nbRWP1 (n)
= nbRWPr1 (n − 3) + nbRWP1 (n − 4) + nbRWP1 (n − 2) + nbRWP1 (n − 3)
= nbRWP0 (n − 2) + nbRWP0 (n − 3) + nbRWP1 (n − 2) + nbRWP1 (n − 3)
= nbRWP(n − 2) + nbRWP(n − 3).
18 - A 6 Answer 6. The values of nbRWP0 (n), nbRWP1 (n) and nbRWP(n) for n varying from
1 to 15 are gathered in the array below:
n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
nfr0 0 1 1 1 2 2 3 4 5 7 9 12 16 21 28
nfr1 1 1 1 2 2 3 4 5 7 9 12 16 21 28 37
nfr 1 2 2 3 4 5 7 9 12 16 21 28 37 49 65

It can be observed that for n > 2: nbRWP1 (n) = nbRWP(n − 2). This is not surpris-
ing since: (i) the form of their recurrence is the same, nbRWP1 (3) = nbRWP(1) = 1 and
nbRWP1 (4) = nbRWP(2) = 2, (ii) in question 4:
nbRWP1 (n) = nbRWP0 (n − 1) + nbRWP0 (n − 2) = nbRWP1 (n − 2) + nbRWP0 (n − 2)
= nbRWP(n − 2).

Remark
As seen in page 10, the sequence whose general term is P(n) = P(n − 2) + P(n − 3) for
any n > 2 where P(0) = P(1) = P(2) = 1, defines the Padovan sequence. Its numbers are
exponentially increasing in the order of (1.324 · · · )n−1 . More precisely, the nth number is
the integer closest to (1.324 · · · )n−1 /1.045 · · · . For instance, P(20) = 200.
The number 1.324 · · · is sometimes called silver ratio , by analogy with the golden ratio
related to Fibonacci sequence.
18 - A 7 Answer 7. The calculation of nbRWP(i) requires only nbRWP(i−2) and nbRWP(i−3).
To compute nbRWP(n), the array T [1 .. 4] is used to keep the last four values of nbRWP,
thus the program:

i i

i i
i i

i i

Solutions 63

1. constants
2. n ∈ N1 and n = . . .
3. variables
4. T ∈ 1 .. 4 → N1
5. begin
6. T [1] ← 1; T [2] ← 2; T [3] ← 2;
7. for i ranging 4 .. n do
8. T [4] ← T [1] + T [2];
9. for j ranging 1 .. 3 do
10. T [j] ← T [j + 1]
11. end for
12. end for;
13. write(the number of reasonable ways for playing with a game
14. of size , n, is , T [4])
15. end

Answers to problem 19. The game of two stacks The problem is on page 44.
Answer 1. There is one and only one way to reach a winning state if one is already 19 - A 1
in this state: doing nothing. In the configuration p = 1, q = 1, it is no longer possible to
play, a winning state is unattainable and it is lost. When p ⩾ 2 and q ⩾ 2, two possible
ways of playing are open and the number of ways to reach a winning state is given by the
sum of the ways to win from the two configurations attained when playing (p − 2, q + 1 or
p + 1, q − 2). When p or q is less than 2, there is a single way of playing and the number of
ways to win from the configuration (p, q) equals that of the new configuration (p − 2, q + 1
when q < 2, p + 1, q − 2 when p < 2). The following recurrence can be derived, which
accounts for the symmetry of the problem:

nbWW(0, 1) = nfg(1, 0) = 1
nbWW(1, 1) = 0
nbWW(0, q) = nbWW(1, q − 2) q>1
nbWW(1, q) = nbWW(2, q − 2) q>1
nbWW(p, 0) = nbWW(p − 2, 1) p>1
nbWW(p, 1) = nbWW(p − 2, 2) p>1
nbWW(p, q) = nbWW(p − 2, q + 1) + nbWW(p + 1, q − 2) p > 1 and q > 1.

Answer 2. Due to the fact that the number p (respectively q) of tokens of stack P (re- 19 - A 2
spectively Q) may increase, the tabular structure cannot be reduced to an array with (p+1)
rows and (q + 1) columns (or the reverse). Strictly speaking, an array with (p + ⌊q/2⌋ + 1)
rows and (q + ⌊p/2⌋ + 1) columns would suffice, but for simplicity of the filling, a squared
tabular structure T [0 .. p + q, 0 .. p + q] is used where T [i, j] corresponds to nfWW(i, j). As
to the general case, this array can be filled in by increasing diagonals of equation (p + q),
since nbWW(p, q) is located on the diagonal of equation (p + q) and the two elements
required for its calculus are located on the diagonal of equation (p + q − 1). Diagonals
of equation 1, 2 et 3 (0 is meaningless) are first initialized using the appropriate terms of
the recurrence. Then, elements of a diagonal are filled in thanks to the general term of the
recurrence, except the extreme four terms for which the terms associated with p or q less
than 2 are used.
Answer 3. The algorithm below implements the above principles: 19 - A 3

i i

i i
i i

i i

64 Mathematics and computer science: some useful notions

1. constants
2. p ∈ N1 − {1} and p = . . . and q ∈ N1 − {1} and q = . . .
3. variables
4. T ∈ 0 .. p + q × 0 .. p + q → N
5. begin
6. T [0, 1] ← 1; T [1, 0] ← 1;
7. T [2, 0] ← 1; T [0, 2] ← 1; T [1, 1] ← 0;
8. T [3, 0] ← 0; T [1, 2] ← 1; T [2, 1] ← 1; T [0, 3] ← 0;
9. for k ranging 4 .. p + q do
10. T [0, k] ← T [1, k − 2];
11. T [1, k − 1] ← T [2, k − 3];
12. T [k, 0] ← T [k − 2, 1];
13. T [k − 1, 1] ← T [k − 3, 2];
14. for j ranging 2 .. k − 2 do
15. T [j, k − j] ← T [j − 2, k − j + 1] + T [j + 1, k − j − 2]
16. end for
17. end for;
18. write(the number of ways for winning with two stacks having, p,
and , q, tokens
19. is , T [p, q])
20. end

19 - A 4 Answer 4. The computation of nbWW(4, 2) is performed in filling in the following


array:
q 0 1 2 3 4 5 6
p=0 1 1 0 1 1 0
1 1 0 1 1 0 2
2 1 1 0 2 3
3 0 1 2 0
4 1 0 3
5 1 2
6 0
and it can be seen that nfWW(4, 2) = 3.
19 - A 5 Answer 5. The validity of the property mentioned in the statement can be observed
in the array above (cells (i, j) located on a diagonal of equation |i − j| multiple of 3 –
nbWW(0, 0) excepted – take a zero value). The proof is now performed by simple induc-
tion on n, the index of the diagonal of equation (i + j = n). The induction hypothesis is:
any element nbWW(i, j) such that |i − j| is a multiple of 3 and (i + j = n) takes a zero value,
cell nbWW(0, 0) excepted.
Initialization For n = 1, nbWW(0, 1) and nbWW(1, 0) are the only elements such that
(i + j) = n, but |i − j| = 1 is not multiple of 3. For n = 2, nbWW(0, 2), nbWW(2, 0)
and nbWW(1, 1) are such that (i+j) = n. The only element complying with |i−j| = 3k,
is nbWW(1, 1) whose value is 0 according to the second term of the recurrence. Thus,
the property holds for n = 1 and n = 2.
Induction Let us assume that the property holds for n ⩾ 2, using the previously estab-
lished recurrence, we will prove that any element nbWW(i, j) such that |i − j| is a
multiple of 3 and (i + j = n + 1) takes a zero value. We successively examine elements
such that (i + j = n + 1).

i i

i i
i i

i i

Solutions 65

nbWW(0, n + 1) and nbWW(n + 1, 0) We have nfWW(0, n + 1) = nbWW(1, n − 1)


(third term of the recurrence); the sum of the indexes of this latter element equals
n and we can use the induction hypothesis. When (|0 − (n + 1)| = n + 1) is a
multiple of 3, (|1 − (n − 1)| = n − 2) is also a multiple of 3 and nbWW(0, n + 1) =
nbWW(1, n − 1) = 0. The same reasoning applies to nbWW(n + 1, 0) due to the
symmetry of the terms of the recurrence.
nbWW(1, n) and nbWW(n, 1) According to the fourth term of the recurrence, we
have nbWW(1, n) = nbWW(2, n − 2). The fact that the sum of the indexes of
nbWW(2, n − 2) equals n allows to use the induction hypothesis. When (|1 − n| =
n − 1) is a multiple of 3, (|2 − (n − 2)| = |n − 4|) is also a multiple of 3 and
nbWW(1, n) = nbWW(2, n−2) = 0. The same reasoning applies to nbWW(n, 1)
due to the symmetry of the terms of the recurrence.
General case for nbWW(i, j) with i + j = n + 1, i > 1 and j > 1 Such an element is
the sum of nbWW(i − 2, j + 1) and nbWW(i + 1, j − 2), both such that the sum of
their indexes is n; the induction hypothesis can be used. When |i − j| is a multiple
of 3, (|i − 2 − (j + 1)| = |i − j − 3|) is also a multiple of 3, as well as (|i + 1 − (j − 2)| =
|i−j+3|). It follows that nbWW(i, j) = nbWW(i−2, j+1)+nbWW(i+1, j−2) = 0.
Conclusion Any element nbWW(i, j) such that |i − j| is a multiple of 3 takes a zero value –
nbWW(0, 0) excepted – for any pair (i, j) where i ⩾ 0 and j ⩾ 0.

Answers to problem 20. The yellow coins The problem is on page 44.

Answer 1. We have nbWF1E(1)(2) = 1 + nbWF1E(1)(1) = 2 and the suggested 20 - A 1


recurrence yields (i) nbWF1E(3) = nbWF1E(1) + nbWF1E(2) = 3 (whilst there are only
two ways for forming three cents), (ii) nbWF1E(4) = nbWF1E(3) + nbWF1E(2) = 5
(whilst there are only three ways for forming four cents). Giving initial val-
ues for nbWF1E(1) to nbWF1E(4) (1, 2, 2 et 3) would not change the story since
nbWF1E(5) = 1 + nbWF1E(4) + nbWF1E(3) = 6 would be false as there are only four
distinct ways for forming five cents.

The origin of the problem lies in the fact that some combinations of coins are counted more
than once. Thus, when we convert “To form the amount s of three cents, one takes a one
cent coin and the amount (s − 1) remains to be formed, or one takes a two cent coin and the
amount (s − 2) remains to be formed”, into nbWF1E(3) = nbWF1E(2) + nbWF1E(1), there
is no guarantee that distinct ways are counted. In this example, the combination made of
a one cent coin and a two cent coin is obtained (and counted) twice. In other words, the
recurrence suggested does not take into account exclusive situations leading to distinct
ways for forming the desired amount and in this respect this is not a valid recurrence.
Answer 2. Now, we envisage a double index recurrence and we denote by 20 - A 2
nbWF1E2(m, p) the number of distinct ways for forming the amount m with the coins
numbered from p to 6. We proceed as follows. To form the amount m with coins num-
bered from p to 6 (p < 6), we can: (i) take only coins ranked strictly over p (i.e. no coin of
value value v(p)), or (ii) take a single coin of value v(p) (if possible, i.e. if m ⩾ v(p)) and
the amount (m − v(p)) remains to be formed with the coins whose rank ranges from (p + 1)
to 6 according to the same mechanism, or (iii) if possible (i.e. if m ⩾ 2 · v(p)) take two coins
whose rank is p and the amount (m − 2 · v(p)) remains to be formed with coins whose rank
ranges from (p + 1) to 6 according to the same mechanism, (iv) and so on. In doing so, we
are ensured that the ways for forming the amount m are different by construction since, in

i i

i i
i i

i i

66 Mathematics and computer science: some useful notions

the first case the combination of coins involves no coin whose rank is p, in the second case
a single such coin is inserted, in the third case two such coins appear, etc. Therefore, when
m ⩾ v(p), one can write:

⌊ v(p)
m

X
nbWF1E2(m, p) = nbWF1E2(m − i · v(p), p + 1)
i=0
or even:
nbWF1E2(m, p)
= distinction of the first term
⌊ v(p)
m

X
nbWF1E2(m, p + 1) + nbWF1E2(m − i · v(p), p + 1)
i=1
= variable change, (i − 1) becomes j
⌊ m−v(p)
v(p) ⌋
X
nbWF1E2(m, p + 1) + nbWF1E2(m − v(p) − j · v(p), p + 1)
j=0
= definition of nbWF1E2
nbWF1E2(m, p + 1) + nbWF1E2(m − v(p), p).

When m is strictly less than v(p), the only way for forming the amount m is to ignore
coins of rank p and use those ranked from (p + 1) to 6. So, we end up with the recurrence
hereafter

nbWF1E2(0, p) = 1 1⩽p⩽6
nbWF1E2(m, 6) = 1 m is a multiple of v(6) and 1 ⩽ m ⩽ 100
nbWF1E2(m, 6) = 0 m is not a multiple of v(6) and 1 ⩽ m ⩽ 100
nbWF1E2(m, p) = nbWF1E2(m, p + 1) + nbWF1E2(m − v(p), p) m⩾
v(p) and 1 ⩽ p < 6 and 1 ⩽ m ⩽ 100 nbWF1E2(m, p) = nbWF1E2(m, p + 1)
m < v(p) and 1 ⩽ p < 6 and 1 ⩽ m ⩽ 100.

Remark 1
It is worth noticing that the order of the coins does not matter, the key point is to con-
sider all of them and to calculate nbWF1E2(100, 1). If it is assumed that the coins are
ordered increasingly on their values, the last term of the recurrence can be replaced by
nbWF1E2(m, p) = 0, since when m is less than v(p), it is less than v(p + 1) too.

Remark 2
One could consider nbWF1E2(m, p) the number of ways for forming the amount m with
coins 1 to p, in which case one would calculate nbWF1E2(100, 6).
20 - A 3 Answer 3. In the example aiming at forming three cents with yellow coins such that
v(1) = 20, v(2) = 5, v(3) = 10, v(4) = 1, v(5) = 50 and v(6) = 2 (but any other ordering of
the coins would be suitable as well), one has:
nbWF1E2(3, 1) = nbWF1E2(3, 2); nbWF1E2(3, 2) = nbWF1E2(3, 3); nbWF1E2(3, 3) =
nbWF1E2(3, 4);
nbWF1E2(3, 4) = nbWF1E2(3, 5) + nbWF1E2(2, 4).

i i

i i
i i

i i

Solutions 67

Yet:
nbWF1E2(2, 4) = nbWF1E2(2, 5) + nbWF1E2(1, 4) = nbWF1E2(2, 6) +
nbWF1E2(1, 5) + nbWF1E2(0, 4) = 1 + nbWF1E2(1, 6) + 1 = 1 + 0 + 1 = 2;
nbWF1E2(3, 5) = nbWF1E2(3, 6)+nbWF1E2(1, 5) = 0+nbWF1E2(1, 6) = 0+0 =
0.
Finally, nbWF1E2(3, 1) has the value 2, as expected.
Answer 4. The program performing the calculation uses the array T [0 .. 100, 1 .. 6] asso- 20 - A 4
ciated with nbWF1E2, and the result is T [100, 1]. The value of the yellow coins are stored in
the array V[1 .. 6] in any order a priori. The recurrence defined before leads to a progression
according to decreasing value of the column index. We start with column 6 for which sec-
ond and third terms are used. Then, each column is filled in according to increasing values
of row index: the cell of index 0 thanks to the first term, next elements using fourth and
fifth terms. This results in the following program:

1. constants
2. V ∈ 1 .. 6 → N1 and V = [1, 2, 5, 10, 20, 50]
3. variables
4. T ∈ 0 .. 100 × 1 .. 6 → N
5. begin
6. for i ranging 0 .. 100 do
7. T [i, 6] ← 0
8. end for;
100
9. for i ranging 0 .. ⌊ V[6] ⌋ do
10. T [V[6] · i, 6] ← 1
11. end for;
12. for p ranging inverse 1 .. 5 do
13. T [0, p] ← 1;
14. for m ranging 1 .. V[p] − 1 do
15. T [m, p] ← T [m, p + 1]
16. end for;
17. for m ranging V[p] .. 100 do
18. T [m, p] ← T [m, p + 1] + T [m − V[p], p]
19. end for
20. end for;
21. write(the number of ways for forming one euro with yellow coins
is , T [100, 1])
22. end

Answer 5. By running this program, it appears that there are 4562 distinct ways for 20 - A 5
forming one euro with yellow coins.
Answer 6. It has been seen that nbWF1E2(m, 1) does not depend on the order accord- 20 - A 6
ing to which yellow coins are taken into account, therefore on the order of values in V.
Hence, it is possible to work with the vector V = [1, 2, 5, 10, 20, 50]. In this context, for
m > 0, nbWF1E2(m, 1) is defined as the sum of nbWF1E2(m, 2) and nbWF1E2(m − 1, 1).
Since nbWF1E2(m, 2) ⩾ 0, one has:
nbWF1E2(m, 1) ⩾ nbWF1E2(m − 1, 1).
Another justification of this result can be found in realizing that the formation of the
amount m with the six yellow coins can begin with the formation of (m − 1) followed
by the addition of a one cent coin to get m.

i i

i i
i i

i i

68 Mathematics and computer science: some useful notions

Remark
When all the values of T are displayed, it turns out that, as a matter of fact, nbWF1E2(m, 1)
grows with m, non strictly for the first four values and strictly after. However, it can be
noted that, in general, nbWF1E2(m, p) where p ̸= 1 is not increasing.

Answers to problem 21. Shuffling words The problem is onpage 45.

21 - A 1 Answer 1. Let us denote by nbShuf(i, j) the number of distinct shuffles that can be
built from the prefixes u[1 .. i] and v[1 .. j] of the words u and v. In the general case w[i + j]
can be either u[i], or v[j]. In the first case, there are nbShuf(i − 1, j) possible shuffles ending
by u[i], and in the second one there are nbShuf(i, j − 1) possible shuffles ending with v[j].
When u (respectively v) is the empty word, there is a unique way for building the shuffle.
Thus, the following recurrence is obtained:

nbShuf(i, 0) = 1 0⩽i⩽m
nbShuf(0, j) = 1 0⩽j⩽n
nbShuf(i, j) = nbShuf(i − 1, j) + nbShuf(i, j − 1) 1 ⩽ i ⩽ m and 1 ⩽ j ⩽ n.

For example, for m = 5 and n = 4, nbShuf(5, 4) = 126 is calculated by means of the


following procedure which fills in an array:
• initialization of the first row (i = 0) using the second term of the recurrence,
• filling of the other rows in increasing order of their indexes,
• in a row cells are filled in increasing order of the column index, the first one using the
first term of the recurrence, the others with the third term.
The array below is then obtained:
j 0 1 2 3 4
i=0 1 1 1 1 1
1 1 2 3 4 5
2 1 3 6 10 15
3 1 4 10 20 35
4 1 5 15 35 70
5 1 6 21 56 126

Remark
It can be observed that the array is symmetric with respect to the diagonal of equation
i − j = 0, which is in coherence with the fact that the two indexes i and j play the same role
in the recurrence.
21 - A 2 Answer 2. For the proof by induction, the pattern given page 9 is used since it is well
suited for this situation and we let P(m, n) = (nbShuf(m, n) = (m + n)!/(m! ·n!)).
Initialization For any integer i, one has:

i!
nbShuf(i, 0) = 1 =
i! · 0!

i i

i i
i i

i i

Solutions 69

and for any integer j:


j!
nbShuf(0, j) = 1 = .
j! · 0!
Induction Let us assume (induction hypothesis) that for any pair (i, j) of positive integers:

(i + j − 1)! (i + j − 1)!
nbShuf(i − 1, j) = , nbShuf(i, j − 1) =
(i − 1)! · j! i! · (j − 1)!
it must be proven that:

(i + j)!
nbShuf(i, j) =
i! · j!
One has:
nbShuf(i, j)
= general term of the recurrence
nbShuf(i − 1, j) + nbShuf(i, j − 1)
= induction hypothesis
(i + j − 1)! (i + j − 1)!
+
(i − 1)! · j! i! · (j − 1)!
= arithmetics
i · (i + j − 1)! j · (i + j − 1)!
+
i! · j! i! · j!
= arithmetics
(i + j) · (i + j − 1)!
i! · j!
= definition of factorial
(i + j)!
.
i! · j!
 
(m + n)!
Conclusion ∀(m, n) · m ∈ N and n ∈ N ⇒ nbShuf(m, n) = .
m! · n!
The preceding result is rewritten:

(m + n)!
nbShuf(m, n) = = Cm n
m+n = Cm+n
m! · n!
in other words nbShuf(m, n) is the number of combinations of n (or m) elements out of
(m + n) or even the number of ways to choose n (or m) distinct letters out of (m + n). This
result can be established directly as follows. Let ML be an array with (m + n) cells. There
are Cn
m+n ways for taking m cells of this array to assign the letters of u in increasing order
of the index and in the order of the letters of u. For each way to place u, there is a single
way for the placement of the letters of v inside ML and therefore the number of shuffles of
u and v equals Cn m+n .

Answer 3. The requested decision algorithm is based on the recurrence isSHUF such 21 - A 3
that isSHUF(i, j) = true, if and only if w[1 .. i + j] is a shuffle of u[1 .. i] and v[1 .. j]. The
reasoning for establishing this recurrence is similar to that of the first question (w is a
shuffle of u and v only if its last letter is that of u or v). We get:

isSHUF(i, 0) = (w[1 .. i] = u[1 .. i]) 0⩽i⩽m


isSHUF(0, j) = (w[1 .. j] = v[1 .. j]) 0⩽j⩽n

i i

i i
i i

i i

70 Mathematics and computer science: some useful notions


  
(isSHUF(i − 1, j) and w[i + j] = u[i])  1⩽i⩽m
isSHUF(i, j) =  or  and .

(isSHUF(i, j − 1) and w[i + j] = v[j]) 1⩽j⩽n
The related program uses the Boolean array M[0..m, 0..n], filled as previously: increasingly
in rows and, for a row, increasingly in columns, once row 0 is initialized. The expected re-
sult is found in cell M[m, n]. The code of the program is given hereafter:

1. constants
2. u ∈ string and u = . . . and v ∈ string and v = . . .
3. and w ∈ string and w = . . . and m = |u| and n = |v|
4. variables
5. M ∈ 0 .. m × 0 .. n → B
6. begin
7. M[0, 0] ← true;
8. for j ranging 1 .. n do
9. M[0, j] ← M[0, j − 1] and w[j] = v[j]
10. end for;
11. for i ranging 1 .. m do
12. M[i, 0] ← M[i − 1, 0] and w[i] = u[i];
13. for j ranging 1 .. n do
14. M[i, j] ← (M[i − 1, j] and w[i + j] = u[i]) or (M[i, j − 1] and w[i + j] =
v[j])
15. end for
16. end for;
17. write(it is , M[m, n], to say that , w, is a shuffle of , u, and , v)
18. end
The handling of the example where u = abc, v = db, w = dabbc, leads to the array below:
j 0 1 2
ϵ d b
i=0 ϵ T T F
1 a F T T
2 b F T T
3 c F F T

Since the cell M[3, 2] contains the value true, it can be concluded that w =dabbc is a shuffle
of u =abc and v = db.

i i

i i
i i

i i

2
Complexity of an algorithm

Fools ignore complexity. Pragmatists


suffer it. Some can avoid it. Geniuses
remove it.

A. Perlis

2.1 Reminders
2.1.1 Algorithm
First, let us recall that an algorithm is defined as a set of rules intended for the resolution of
a problem with input data. This set of rules defines exactly a sequence of operations which
terminate in finite time.
For example, let us consider the multiplication of two positive integers written in base
10. We have learnt at school a certain algorithm to solve this problem, on the basis of a pre-
cise sequence of elementary operations, using multiplication of digits in base 10 and addi-
tion of numbers. We know that this algorithm allows to calculate the product of any pair of
numbers in a finite time, depending on the length of the numbers. There exists other algo-
rithms to solve this problem, sometimes founded on variations on the same principle (like
the abacus technique), but also quite different, as is the so-called Russian multiplication1
(see figure 2.1), which requires only multiplications and divisions by 2 (and additions).
These algorithms are simple enough to be learnt by most of people, and pretty efficient,
in the sense that they deliver the expected result quickly and they require neither a large
space, nor the writing of too numerous digits. At the contrary, observe the following naïve
algorithm: to multiply n by m, write n lines each with m crosses, one below the other, then
count the total number of crosses. This latter method requires only the ability to count, but
it is much more costly in time and space.

2.1.2 Algorithmics, complexity of an algorithm


We just saw several methods (or algorithms) to perform the multiplication of two num-
bers. It is very often the case for numerous problems and it is useful to be able to compare
the diverse algorithms which, equivalent from a functional point of view, can be very dif-
ferent in terms of performance. The main goal of algorithmics, the science for the design of
algorithms, is to find an algorithm as efficient as possible for a given problem.
1 Actually, it was already used in ancian Egypt.

DOI: 10.1201/b23251-2 71
i i

i i
i i

i i

72 Complexity of an algorithm

4 1 3 3
4 1 2 0 ̸6 ̸6
×
3 3 1 0 ̸1 ̸3 ̸2
1 2 3 5 2 6 4
+ 2 ̸5 ̸2 ̸8
1 2 3
1 1 0 5 6
1 3 5 3
1 3 5 3

Fig. 2.1 – Left: ordinary multiplication of 41 and 33. Right: Russian multiplication. On the left
column, from top to bottom, one writes the finite sequence of the integer divisions of 41 by 2. On
the right column, from top to bottom, one writes the sequence of the multiplications of 33 by 2. Line
by line, the parity of the left number is checked. If it is even (marked in grey), the right number in
the line is suppressed. Eventually, one adds all remaining numbers in the right column to obtain
41 × 31 = 33 + 264 + 1056.

Usually, the efficiency of an algorithm is measured as its time complexity (or temporal)
and its space complexity (or spatial). However, since the size of computer memories has
tremendously increased over the past years, space complexity is a less and less critical
criterion. That is why, in the remainder of this book, time complexity prevails.
On the basis of this remark, the goal of algorithmics becomes essentially the search
for an algorithm solving a given problem as quickly as possible. Hence, the key question
raised is that of the measurement of this speed. Of course, it is highly desirable to measure
the complexity of an algorithm independently of both the programming language used for
implementation and the computer onto which it will be run. Thus, complexity is analyzed
on the basis of one or several elementary operation(s) , which depend on the problem, but is
(are) representative of what the considered algorithm does. In that respect, for an algorithm
performing a search in an array, the elementary operation is the comparison, while for a
sort algorithm two elementary operations come into play: comparison and exchange of
data. Last, for the product of two matrices, the multiplication of (in general real) numbers
constitutes the elementary operation.
A second important point is that complexity is expressed according to the size of data
that are dealt with. This size is an integer characteristic of the problem. For an algorithm
searching in an array or sorting an array, it is the number of elements (or size) of the ar-
ray; for the product of two square matrices, it is the number of rows (or columns) of the
matrices. It is often impossible to give the exact complexity of an algorithm in terms of a
number of elementary operations depending on the size of the data. As a matter of fact,
most of time complexity depends on data themselves. For example, some sort algorithms
work very well when the array is already almost sorted and slowly if it is sorted backward.
For this reason, exact complexity is not the target and the considered notions are those of
minimum complexity (or best case) when data are supportive, and maximum complexity (or
worst case). It is tempting to define an average complexity, but this is hardy feasible in
general since statistical hypotheses about data distribution are required.
Another approach to time analysis is to use the notion of order of growth, which ex-
presses the behavior of complexity when data size becomes “huge” (asymptotic complex-
ity).
In the following two sections, we present the notions of minimum and maximum com-
plexity, then complexity analysis by order of growth.

i i

i i
i i

i i

Reminders 73

2.1.3 Minimum and maximum complexity of an algorithm


We present the concepts of maximum and minimum complexity through the example of the
search in a dictionary. Let us suppose that we are looking for a word in a dictionary to get
its definition if it is present, or to conclude that it is not in this dictionary. Let n be the size
of data, i.e. the number of words in the dictionary. Here, the elementary operation is the
comparison of two words2 and the searched word is denoted by x.
A first algorithm consists in browsing the dictionary from beginning to end until com-
pletion which can take two forms: either the word is found and the number of compar-
isons is less than or equal to n, or it is absent and the entire dictionary has been read. A
concrete technique for this latter case is the sentinel trick: the dictionary is extended with
the searched word x. Hence, x is necessarily found in the dictionary and when it is at the
(n + 1)th comparison we conclude that it is absent from the original dictionary. In the al-
gorithm RechDict1 below, the dictionary is the array DIC[1 .. n] (at this time, no hypothesis
is made about order over the words). When the word x is in DIC, the algorithm returns its
position, otherwise the value (n + 1).

1. constants
2. n ∈ N1 and n = . . . and x ∈ string and x = . . .
3. variables
4. DIC ∈ 1 .. n + 1 → string and DIC = [. . .]
5. begin
6. DIC[n + 1] ← x ; i ← 1;
7. while DIC[i] ̸= x do
8. i←i+1
9. end while;
10. if i < n + 1 then
11. write(the word , x, is in position , i, in the dictionary)
12. else
13. write(the word , x, is not in the dictionary)
14. end if
15. end

What is the complexity of this algorithm? We already know that in the worst case (when x
is not in the original dictionary), (n + 1) comparisons are performed. In the best case, only
one comparison is done, if luckily enough, x is the first word in the dictionary. The average
complexity can be calculated under simple statistical hypotheses and it turns out that it is
not n/2 (see problem 27, page 81).
If it is now assumed that the dictionary is sorted, obviously there is a quicker method
for searching a word: binary search. There are many variants (see for example problem 90,
page 427); we suggest the following iterative version. The word located “in the middle”
of the dictionary is compared to x. If x is greater than (respectively lower than or equal
to) the middle element according to the lexicographical order, the operation is repeated
in the upper (respectively lower) half dictionary until a portion of dictionary containing a
single word is reached. A positive decision is drawn if this word is the searched word x,
otherwise x is not in the dictionary.
2 Actually,a more elementary operation would be the comparison of letters, or even that of bits, but we keep
with this one for obvious reasons.

i i

i i
i i

i i

74 Complexity of an algorithm

The iterative program RechDict2 hereafter implements what is previously described:


1. constants
2. x ∈ string and x = . . . and n ∈ N1 and n = . . .
3. variables
4. beg ∈ N1 and end ∈ N1 and end ⩾ beg and mid ∈ N1 and mid ⩾ beg and
5. mid ⩽ end and DIC ∈ 1 .. n → string and DIC = [. . .]
6. begin
7. beg ← 1 ; end ← n;
8. while beg̸= end do 
beg + end
9. mid ← ;
2
10. if x > T [mid] then
11. beg ← mid + 1
12. else
13. end ← mid
14. end if
15. end while;
16. if x = T [beg] then
17. write(the word , x, is in position , beg, in the dictionary)
18. else
19. write(the word , x, is not in the dictionary)
20. end if
21. end

In the case of this algorithm, there are neither best, nor worst situations. As a matter of
fact, the number of comparisons (of words) depends only on the size n of the dictionary
DIC, not on its contents. The size of search area is repeatedly divided by two and we will
admit that the number of comparisons is in the order of ⌊log2 (n)⌋, the greatest integer
less than or equal to log2 (n) (we come back on this statement later). If we admit that the
average complexity of RechDict1 is linear, RechDict2 performing a logarithmic number of
comparisons is better, as expected.
For a dictionary of English language, n is close to 200 000 and the number of compar-
isons of RechDict2 (⌊log2 (n)⌋) is 16.
Let us remark that the variant of RechDict2 where the alternative distinguishes the
equality of x and T [mil] (and the program stops), may require a single comparison. How-
ever, it is convenient to notice that: (i) the favorable configuration differs from that for
RechDict1 and (ii) one more comparison is performed at each iteration step and in the
worst case the number of comparisons becomes 2 · ⌊log2 (n)⌋.

2.1.4 Orders of growth


The most usual way to deal with time analysis is to use the notion of order of growth (also
called complexity class). The function fA (n) expresses the maximum complexity of the al-
gorithm A in terms of the size n of data that are considered. The idea is to inflate fA (n) by
a function whose growth is (well) known. For this purpose, a certain number of functions
serve as a reference:

• 1 (constant complexity), • n · log2 (n) (quasi linear complexity),

• log2 (n) (logarithmic complexity),

• n (linear complexity), • n2 (quadratic complexity),

i i

i i
i i

i i

Reminders 75

• np (p > 2) (polynomial complexity), • n!,

• 2n (exponential complexity), • nn .

One could try to write formulas of type fA (n) ∈ O(n2 ) meaning (with some precautions
that will be explicited) that fA (n) does not grow more rapidly than n2 when n increases.
However, this first attempt would be very restrictive since, for instance, fA (n) = n2 /2 +
3n/2 + 1 or fA (n) = 2n2 − 1 would not comply with the definition. Hence, the meaning of
fA (n) ∈ O(n2 ) is revised so that the two preceding examples become acceptable. For the
first one, it will be said that fA (n) does not grow more quickly than the reference function
(here n2 ) when n increases, from a given rank n0 . Thus, it is possible to write (n2 /2 + 3n/2 +
1) ∈ O(n2 ), since from n0 = 4, it is true that (n2 /2 + 3n/2 + 1) < n2 . However, it is still
illegal to write (2n2 − 1) ∈ O(n2 ) since for any n > 1 : (2n2 − 1) > n2 . Yet, intuition tells
that the order of growth is the same for both (2n2 − 1) and n2 , and it seems consistent to
say (2n2 − 1) and n2 grow the same way. Last, we say that fA (n) ∈ O(n2 ), if there is a
constant C and an integer n0 from which the inequality fA (n) ⩽ C · n2 holds. Eventually,
the following definition is adopted. Let g be a function: N → R+ . We call maximum order of
growth O of g the set:
b {t : N → R+ | ∃(C, n0 ) · (C ∈ R+ and n0 ∈ N and ∀n·
O(g) =
((n ∈ N and n ⩾ n0 ) ⇒ t(n) ⩽ C · g(n)))}.
According to this definition, (n2 /2 + 3n/2 + 1) ∈ O(n2 ), as well as (2n2 − 1) ∈ O(n2 )
hold. Since (2n2 − 1) ∈ O(n2 ), (2n2 − 1) ∈ O(n3 ) also holds. In practice, we look for the
smallest reference function rf such that fA (n) ∈ O(rf(n)). Once the set O(g) of the functions
which grow at most as quickly as g (now with a precise meaning) has been defined, it is
legitimate to define similarly the set Ω(g) of the functions which grow at least as quickly
as g. The two notions O(g) and Ω(g) allow to provide upper and lower bounds for the
behavior of an algorithm.
We call minimum order of growth of g the set:

b {t : N → R+ | ∃(D, n0 ) · (D ∈ R+ and n0 ∈ N and ∀n·


Ω(g) =
(n ⩾ n0 ⇒ t(n) ⩾ D · g(n)))}.

Last, we call exact order of growth of g the set Θ(g) defined by the intersection of O(g)
and Ω(g):

b t ∈ O(g) and t ∈ Ω(g)


t ∈ Θ(g) =
or:

b {t : N → R+ | ∃(C, D, n0 ) · (C ∈ R+ and D ∈ R+ and n0 ∈ N and ∀n·


Θ(g) =
(n ⩾ n0 ⇒ D · g(n) ⩽ t(n) ⩽ C · g(n)))}.

f ∈ O(g) (respectively Ω(g), Θ(g)) is often read “f is in big o of g” (respectively in Ω of


g, in Θ of g).

Interesting result
Let A be an algorithm made of two consecutive parts A1 and A2 , whose respective
complexities are such that fA1 (n) ∈ O(f1 (n)) and fA2 (n) ∈ O(f2 (n)); then fA (n) ∈
max({O(f1 (n), O(f2 (n))}). In other words, the maximum order of growth of an algorithm is
given by that of its part of highest maximum order of growth (see problem 23, page 79).

i i

i i
i i

i i

76 Complexity of an algorithm

Remarks
1. f ∈ O(1) means that from a given rank n0 there is a constant C such that f(n) ⩽ C.
2. The complexity function fA (n) of any algorithm A is such that fA (n) ∈ Ω(1).

3. For any integer a ⩾ 2, one has: O(loga (n)) = O(log2 (n)) and Θ(loga (n)) = Θ(log2 (n))
since loga (n) = log2 (a) · log2 (n). In general, log2 (n) is taken as a reference function.
4. Stirling formula  n n

n! ≈ 2πn ·
e
allows to write (by taking the logarithm of each member) that log2 (n!) ∈ Θ(n ·log2 (n)).
5. An order of growth is not a limit. For instance, f(n) = n2 · (2 + sin2 (n)) ∈ Θ(n2 ) but it
does not have a limit when n tends toward infinity. Moreover, functions concerned by
orders of growth are not from R to R, but from N to R+ since the size of data manipu-
lated in a program is an integer and a complexity is positive by nature.

2.1.5 Some examples of complexity


In the forthcoming chapters, the complexity of the algorithms is studied systematically.
Hence, here, we restrict ourselves to a few examples on the basis of some of the algorithms
introduced so far. It is easy to deal with the following algorithms:

• factorial (see page 14) whose complexity in terms of multiplications is in Θ(n),


• the calculation of the number of binary trees having n nodes (see page 13) whose com-
plexity in terms of multiplications is given by:

X
n X
i−1
n · (n + 1)
1=
2
i=1 j=0

thus in Θ(n2 ),
• the calculation of a Delannoy number of order (m, n) given by the recurrence in page
14, whose complexity in terms of additions is expressed as:

X
n X
m
2=2·m·n
i=1 j=1

thus in Θ(m · n),


• the number of partitions with p blocks of a set having n elements (see problem 16,
page 41) whose complexity in terms of additions (or multiplications) is given by:

X
n X
j−1
(n − 1)(n − 2)
1=
2
j=2 i=2

thus in Θ(n2 ),
• algorithm RechDict1 which is in O(n) comparisons,

i i

i i
i i

i i

Reminders 77

• the naïve multiplication of two square matrices which is in Θ(n3 ) multiplications of


real numbers (more efficient algorithms exist).
For the variant of the algorithm RechDict2, we must compute nbStepMax(n), the max-
imum number of steps in the loop. It is given by the recurrence:

nbStepMax(1) = 1 j n k
nbStepMax(n) = 1 + nbStepMax n>1
2

whose solution is nbStepMax(n) = ⌊log2 (n)⌋. The maximum number of comparisons (of
words) is thus 2 · ⌊log2 (n)⌋ + 1; this algorithm is in O(log2 (n)).
This latter example highlights the central role (very often) of recurrence relations for
the evaluation of complexity. They are used intensively, in particular for the complexity of
recursive algorithms in chapters 4 and 8.

2.1.6 About elementary operations


In the remainder, notably in the problems, the focus is put on asymptotic time complexity
of algorithms and sometimes on exact complexity. Frequently, the very nature of the algo-
rithm leads to choose a unique elementary operation, but sometimes several elementary
operations come into play. Two situations can occur:
• They are correlated and one of them is chosen; it is the case for the product of matrices
where additions and multiplications are tied, but also for the computation of the sum
of the elements of an array where the number of additions (the heart of the sum) and
comparisons (related to the control of the loop) differ from only one unit,
• The operations are independent and, either they are counted separately or the one with
the maximum number of occurrences is taken into account.
In the problems proposed and/or dealt with, elementary operation(s) are most of time
made explicit in the statement. Sometimes, this aspect is willingly left in the dark and it
must be appropriately detailed in the answer.
There are numerous sorting algorithms which, generally, call on two elementary op-
erations: evaluation of condition and exchange (see for example problem 33 page 112). In
some problems, sorting is an initial step and it will be assumed that one of the most ef-
ficient at worst is used, whose asymptotic time complexity is quasi linear (n · log2 (n)) in
terms of comparisons and/or exchanges3 .
It may happen that we want to compare time complexity of several algorithms intended
to solve a same problem. It is then important to choose one (or several) elementary opera-
tion(s) common to each of them so that the comparison makes sense.
The evaluation of conditions, simple (called comparisons) or complex, explicit (condi-
tional statements or while loops) or implicit (for loops), play a prominent role in numerous
algorithms. Henceforth, it can be rightly chosen as elementary operation, all the more as
no other operation appears relevant for the considered algorithm.

2.1.7 Practical computing time


Each cell of the array below indicates the approximative size of data that can be dealt with
by an algorithm whose exact complexity appears in the columns and run-time in rows, for
3 see en.wikipedia.org/wiki/Sorting_algorithm

i i

i i
i i

i i

78 Complexity of an algorithm

an instruction computer run-time of 1µs. For example, in an hour, the size of the problem
that can be dealt with by an algorithm in n3 is 1 500. An “astronomic” size is greater than
the estimated number of atoms in the universe (1080 ).

size log10 (n) n n2 n3 2n n!


6
duration = 1 s astronomic: 1010 106 103 102 19 10
1 mn astronomic 6.107 8.103 4.102 25 11
1h astronomic 4.108 2.104 1 500 31 13
1j astronomic 9.1010 105 4 400 36 16

For the same instruction run-time (1µs), the following array gives time necessary for an al-
gorithm, whose exact complexity appears in columns, to with data whose size is indicated
in rows. For example, a program in n2 can deal with a problem of size 1 000 in one second.
An “astronomic” time is greater than one trillion years.

complexity log2 (n) n nlogn n2 2n


size = 10 3µs 10µs 30µs 100µs 1 000µs
100 7µs 100µs 700µs 1/100s 1014 centuries
1 000 10µs 1 000µs 1/100s 1s astronomic
10 000 13µs 1/100s 1/7s 1, 7mn astronomic
100 000 17µs 1/10s 2s 2, 8h astronomic

2.1.8 Pseudo-polynomial problems


Let us remind that the order of growth is evaluated as a function of the size n of the prob-
lem, which is independent of the data manipulated by the algorithm. In that respect, the
product of two matrices of real numbers (n×n) can be computed by an algorithm in Θ(n3 )
multiplications of real numbers, whatever the values of the matrices.
However, for some algorithms, complexity is evaluated considering data themselves.
Without going into the details (what will be done in Chapter 9), the problem titled currency
change (problem 148, page 689) aims at accumulate the amount N (cents) using a minimum
number of coins in the context of the European currency system. For example, for N = 6,
the best way is to take two coins: one cent and five cents, rather than – for example – three
two cent coins. If we are provided with n distinct types of coins (unlimited in quantity),
it turns out that no polynomial (in n) method is known which works for any currency
system, but only an exponential one (thus in O(2n )), called A1 .
In contrast, the algorithm (A2 ) computes the expected optimal in Θ(N · n). But beware,
N is some data, not the size of the problem. Consequently, run-time depends on charac-
teristics of each occurrence of the problem, which contradicts the principles and criteria of
algorithm complexity evaluation.
One might think that the expression Θ(N · n) shows that the problem is linear in n,
thanks to algorithm A2 . But this is false, since N is not a constant and cannot be upper
bounded a priori by a constant. For the amount N = 22 or n!, running A2 would be less
n

efficient than A1 to produce the desired result. In contrast, when N is a reasonable (i.e. a
rather small) amount (which is often the case in concrete applications), A2 is better than
A1 .
Algorithms like A2 , whose type of complexity is in Θ(N · P(n)), where P(n) is a poly-
nomial in n, and where N depends on the data, are said pseudo-polynomial. Of course, they
can be studied and used, but we must keep in mind that their run-time depends directly
and critically on the data of the considered problem.

i i

i i
i i

i i

Problems 79

Final remark
For some problems, data size can be evaluated as a function of several parameters, not a
single one. For example, in chapter 9 we will see the “Choosing skis” problem, where each
of the n skiers must receive the best pair of skis (among m). n and m are independent
values, except the condition m ⩾ n. The order of growth of the best algorithm known
for this problem is O(n · m). Therefore, it is impossible to characterize its complexity on
the basis of a single parameter: in such a case, the size of the problem is basically multi-
dimensional and the order of growth is expressed as a multiple variable polynomial.

2.2 Problems
Problem 22. About some reference functions ◦
◦ •

This problem aims at deciding whether “close” reference functions characterize (or not) the
same order of growth.

Let us consider the following claims (f is a function from N to R+ ):

1. 2n+1 ∈ O(2n )
2. (n + 1)! ∈ O(n!)
3. f(n) ∈ O(n) ⇒ (f(n))2 ∈ O(n2 )
4. f(n) ∈ O(n) ⇒ 2f(n) ∈ O(2n )
5. nn ∈ O(2n ).

Are these propositions true or not?


The solution is on page 83.

Problem 23. About orders of growth ◦


◦ •

In this problem, an interesting property is established. It is related to the sum of two functions
whose maximum or exact order of growth is known. This result is useful in practice to deter-
mine the maximum or exact order of growth of a program obtained by sequential composition
of several components.

Let f1 (n) and f2 (n) be two functions from N to R+ such that:

∀n · (n ⩾ n0 ⇒ f1 (n) ⩽ f2 (n)),

like f1 (n) = log2 (n) and f2 (n) = n, or f1 (n) = n2 and f2 (n) = 2n .

i i

i i
i i

i i

80 Complexity of an algorithm

23 - Q 1 Question 1. Demonstrate that if g(n) ∈ O(f1 (n)) and h(n) ∈ O(f2 (n)) then g(n) +
h(n) ∈ O(f2 (n)).
23 - Q 2 Question 2. Prove that if g(n) ∈ Θ(f1 (n)) and h(n) ∈ Θ(f2 (n)) then g(n) + h(n) ∈
Θ(f2 (n)).
The solution is on page 84.

Problem 24. Variations around the orders of growth ◦ •


The main objective of this problem is to prevent from drawing hasty conclusions when dealing
with orders of growth.

Are the following two claims true:

1. f ∈ Θ(s) and g ∈ Θ(s) ⇒ f − g ∈ Θ(s)


2. f ∈ O(s) and g ∈ O(r) ⇒ f − g ∈ O(s − r)?

The solution is on page 84.

Problem 25. Order of growth: polynomials ◦


◦ •

Very often, the order of growth of an algorithm is expressed as a polynomial. In this problem,
it is shown that a simplified version is sufficient to express the order of growth.

Let A be an algorithm whose complexity is expressed as a polynomial and we aim at


finding out a “simplified” expression. First, two special cases are considered before moving
to the general case.
25 - Q 1 Question 1. Let us consider f from N1 to R+ and g from D to R+ (where D = N − 0 .. 2)
the two following functions: a) f(n) = n3 + 3n2 + 6n + 9, b) g(n) = n3 − 3n2 + 6n − 9. Prove
that both f and g belong to Θ(n3 ).
25 - Q 2 Question 2. Let f(n) = ap · np + ap−1 · np−1 + · · · + a1 · n + a0 be a function from D
in R+ , with ai ∈ N and D the set N possibly deprived of its first elements for which f has
a nonpositive value. Prove that for ap > 0, f(n) ∈ Θ(np ).
25 - Q 3 Question 3. If a, b and k are integers, prove the inequality:
 k
a+b
a +b ⩾
k k
. (2.1)
2
Deduce that for k ∈ N and n ∈ N1 , one has:

f(n, k) = 1k + 2k + · · · + nk ∈ Θ(nk+1 ).

The solution is on page 85.

i i

i i
i i

i i

Problems 81

Problem 26. Order of growth: paradox? ◦ •

In problem 23, page 79, we have seen a property of the sum of two complexity functions. To
extend it to a multiple sum seems legitimate, but beware of confusing the image of a function
with the sum of functions.

Question 1. Prove that: 26 - Q 1

X
n
i = (1 + 2 + · · · + n) ∈ O(n2 ).
i=1

Question 2. Let us consider the following reasoning. It is known that: 26 - Q 2

X
n
n · (n + 1)
i= .
2
i=1

Yet:
X
n
i ∈ O(1 + 2 + · · · + n)
i=1

and
O(1 + 2 + · · · + n) = O(max({1, 2, . . . , n})) = O(n).
Hence:
n · (n + 1)
∈ O(n).
2
Where is the flaw?
The solution is on page 87.

Problem 27. Average complexity: an example ◦


◦ •

The objective of this problem is to proceed to an average complexity calculation. We highlight


a result which, without being unexpected, is not definitely intuitive.

The algorithm hereafter, close to that developed for the sequential search in a dictio-
nary, looks for the value x in the array T of integers where the first n elements are distinct,
the last one acting as a sentinel (its value is precisely x). The result returned is the rank of
x when x is in T [1 .. n], (n + 1) otherwise.
1. constants
2. x ∈ N1 and x = . . . and n ∈ N1 and n = . . .
3. variables
4. T ∈ 1 .. n + 1 → N1 and T = . . . and i ∈ N1
5. begin
6. i ← 1 ; T [n + 1] ← x;
7. while T [i] ̸= x do
8. i←i+1
9. end while;

i i

i i
i i

i i

82 Complexity of an algorithm

10. write(i)
11. end

27 - Q 1 Question 1. Give the minimum and maximum complexity of this algorithm, in terms
of comparisons.
27 - Q 2 Question 2. The following probabilistic hypothesis is made: (i) the integer values in
the array are drawn equi-probably between 1 and N, with N ⩾ n and (ii) x is drawn equi-
probably between 1 and N as well. What is the average complexity of the algorithm?
The solution is on page 87.

Problem 28. The ford in the fog ◦


◦ •

This problem shows how two strategies a priori analogous can produce algorithms of very
different complexity. Ultimately, a solution with linear complexity is expected, but also an
upper bound of the constant of proportionality, which is rather unusual.

We are in front of a river with a dense fog. We know that there is a ford in the neigh-
borhood, but we ignore if it is located on the left or on the right and at which distance
(unbounded a priori). With this fog, the entrance of the ford can be seen only when we are
just in front of it. How to proceed to cross the river?
We must successively explore left and right ways, while increasing the distance trav-
eled at each direction change. Starting on the left or on the right does not matter, but both
sides must be considered in a “balanced” fashion and the distance must be steadily in-
creased so as to avoid to walk too far in the wrong way (where there is no ford).
A first method consists in walking one step on the right, coming back to the starting
point, walking one step on the left, coming back to the starting point, walking two steps
on the right, coming back to the starting point, walking two steps on the left, coming back
to the starting point, walking three steps on the right, and so on until the ford is reached,
according to the following schema:

Let us suppose that the ford is situated 15 steps on the left. To reach it, the number of
steps walked in total is 465, more than 30 times the 15 strictly necessary steps.
More generally, let us denote by n the distance (in steps) between the starting point and
the ford, i.e. the minimum number of steps necessary to reach the ford.
28 - Q 1 Question 1. Give the number of steps walked with the proposed method when the
ford is located n steps on the left (respetively right) away from the starting point. What is
the class of complexity of this method in terms of steps traveled? One would like to find
a basically more efficient method (in the sense of class of complexity) ensuring that the
ford is reached with less than 9n steps. The shortcoming of the previous method lies in
a too “wise” increase in the number of steps. Adding a single step each time (arithmetic
progression) is finally costly and one imagines to double the number of steps (geometric
progression), which is reflected by the schema below:

i i

i i
i i

i i

Solutions 83

8 4 2 1 1 2 4 8 16

Question 2. Give the number of steps walked depending on whether the ford is lo- 28 - Q 2
cated 9 (respectively 15) steps away from the starting point on the left or on the right.
Conclude.
Question 3. Check that, with a progression according to the powers of 3 (instead of 2), 28 - Q 3
the objective (in terms of steps walked) is not met.
Question 4. Modify the method proposed in the second question, still progressing us- 28 - Q 4
ing the powers of 2, so that the constraint on the number of steps walked is met. It is asked
to give the maximum number of steps walked as well as the minimum one, depending on
n, the distance between the starting point and the ford.
The solution is on page 88.

2.3 Solutions
Answers to problem 22. About some reference functions
The problem is on page 79.

The five claims are successively studied.


1. 2n+1 = 2 · 2n , hence 2n+1 ∈ O(2n ) (for n0 = 0 and C = 2).
2. So that (n + 1) ∈ O(n!), there must be a constant K such that, from a given
rank n0 , one has (n + 1)! ⩽ K · n!. As (n + 1)! = (n + 1) · n!, this would mean
that, for any n greater than n0 , n + 1 ⩽ K, which is impossible. We deduce
that (n + 1)! ̸∈ O(n!).
3. If f(n) ∈ O(n), then f(n) ⩽ C · n from a given rank n0 and (f(n))2 = C2 · n2 ,
hence (f(n))2 ∈ O(n2 ) for n′0 = n0 and C′ = C2 .
4. We point out a counterexample to show the falsity of this proposition. Let us
take f(n) = 2n. Then, we have 2f(n) = 22n , and it is sufficient to prove that
there is no constant K such that for any n, 22n = K · 2n . Yet, 22n = 2n+n =
2n · 2n = K · 2n if 2n = K, which is impossible whatever the value of K. Thus,
the implication f(n) ∈ O(n) ⇒ 2f(n) ∈ O(2n ) is false.
5. So that nn ∈ O(2n ), we should have nn ⩽ C · 2n for a constant C and n sig-
nificantly large. Under these conditions, we should have (n/2)n ⩽ C, which
is impossible since the left member of this inequation increases with n. We
conclude that nn ̸∈ O(2n ).

i i

i i
i i

i i

84 Complexity of an algorithm

Answers to problem 23. About orders of growth The problem is on page 79.

23 - A 1 Answer 1. As g(n) ∈ O(f1 (n)):

∃(C1 , n1 ) · (C1 ∈ R+ and n1 ∈ N and ∀n · (n ⩾ n1 ⇒ g(n) ⩽ C1 · f1 (n))).

Similarly, as h(n) ∈ O(f2 (n)):

∃(C2 , n2 ) · (C2 ∈ R+ and n2 ∈ N and ∀n · (n ⩾ n2 ⇒ h(n) ⩽ C2 · f2 (n))).

It can be deduced that:

∀n · (n ⩾ max({n1 , n2 }) ⇒ (g(n) + h(n)) ⩽ (C1 · f1 (n) + C2 · f2 (n)))

∀n · (n ⩾ max({n1 , n2 }) ⇒ (g(n) + h(n)) ⩽ 2 · max({C1 , C2 }) · f2 (n)))


which characterizes the fact that:

g(n) + h(n) ∈ O(f2 (n)).

23 - A 2 Answer 2. As g(n) ∈ Θ(f1 (n)):


∃(C1 , D1 , n1 ) · (C1 ∈ R+ and D1 ∈ R+ and n1 ∈ N and ∀n·
(n ⩾ n1 ⇒ C1 · f1 (n) ⩽ g(n) ⩽ D1 · f1 (n))).
Similarly, since h(n) ∈ O(f2 (n)):
∃(C2 , D2 , n2 ) · (C2 ∈ R+ and D2 ∈ R+ and n2 ∈ N and ∀n·
(n ⩾ n2 ⇒ C2 · f2 (n) ⩽ h(n) ⩽ D2 · f2 (n))).
We deduce that:
∀n · (n ⩾ max({n1 , n2 })⇒
(C1 · f1 (n) + C2 · f2 (n)) ⩽ g(n) + h(n) ⩽ (D1 · f1 (n) + D2 · f2 (n)))
thus:
∀n · (n ⩾ max({n1 , n2 })⇒
C2 · f2 (n) ⩽ g(n) + h(n) ⩽ max({(D1 , D2 }) · (f1 (n) + f2 (n)))
and finally:
∀n · (n ⩾ max({n1 , n2 })⇒
C2 · f2 (n) ⩽ g(n) + h(n) ⩽ 2 · max({D1 , D2 }) · f2 (n))
which characterizes the fact that:

g(n) + h(n) ∈ Θ(f2 (n)).

Answers to problem 24. Variations around the orders of growth The


problem is on page 80.

The two claims are successively studied.


1. Let f(n) = n3 + 2n2 and g(n) = n3 + n2 . Then, f(n) − g(n) = n2 ∈ Θ(n2 ) and
not Θ(n3 ), which invalidates the first proposition.

i i

i i
i i

i i

Solutions 85

2. Let f(n) = 3n3 , s(n) = n3 + 2n2 , g(n) = n3 and r(n) = n3 + n2 . Obviously,


f(n) ∈ O(s(n)) and g(n) ∈ O(r(n)). One has: f(n) − g(n) = 2n3 and s(n) −
r(n) = n2 and thus f(n)−g(n) ̸∈ Θ(s(n)−r(n)), which contradicts the second
claim.
These two claims are proven to be false.

Answers to problem 25. Order of growth: polynomials The problem is on


page 80.
Answer 1. It must be proven that each of the functions f and g is upper and lower 25 - A 1
bounded by terms of the form K · n3 . Let us first consider f(n). One has:

∀n · (n ∈ N1 ⇒ (1 · n3 ⩽ f(n) ⩽ 18 · n3 ))
and thus f(n) ∈ Θ(n3 ).
As to g(n), 3n2 − 6n + 9 has a positive value for any n ∈ D (and even for any n ∈ N).
Therefore, for n ∈ D, g(n) ⩽ n3 . Moreover:

n3 n3
g ′ (n) = g(n) − =2· − 3n2 + 6n − 9
3 3
is a function taking positive values (not necessarily integers) for any n ∈ D, hence g(n) ⩾
n3 /3. Eventually, we have established that for n ⩾ 3:
1
· n3 ⩽ g(n) ⩽ 1 · n3
3
thereby g(n) ∈ Θ(n3 ).
Answer 2. Here again, we will try to under and over estimate f by a polynomial. Let- 25 - A 2
ting g(n) = ap /2 · np + ap−1 · np−1 + · · · + a1 · n + a0 , we can write:
ap
f(n) = · np + g(n).
2
Let us examine g(n). If c denotes the largest of the values |ai | for i ∈ 0 .. p − 1, one has:
g(n)
= definition
ap p p−1
· n + ap−1 · n + · · · + a1 · n + a0
2
⩾ arithmetics
ap p
· n − c · (np−1
+ · · · + n + 1)
2
⩾ value of the geometric series for n ̸= 1
ap c
p
·n − · (n − 1)
p
2 n−1
> arithmetics
ap p c p
·n − ·n
2 n−1
=   arithmetics
ap c
p
n · − .
2 n−1

i i

i i
i i

i i

86 Complexity of an algorithm

This latter expression is positive for n ⩾ n0 = 2 + (2c/ap ) and we can conclude that:
 ap 
∀n · n ∈ D and n ⩾ n0 ⇒ f(n) ⩾ · np .
2
Let us now try to find a polynomial overestimating f. Let b be the largest of the values |ai |,
for i ∈ 0 .. p. One has:

f(n) ⩽ b · (np + np−1 + · · · + n1 + 1) ⩽ b · (p + 1) · np .


For n ⩾ 2 + (2c/ap ), one has:
ap
· np ⩽ f(n) ⩽ b · (p + 1) · np
2
which proves that f(n) ∈ Θ(np ).
25 - A 3 Answer 3. As (a + b) ⩽ 2 · max({a, b}), we can write:

(a + b)k ⩽ (2 · max({a, b}))k .

Furthermore, one has:

(2 · max({a, b}))k = (max({2a, 2b}))k ⩽ (2a)k + (2b)k


and by combination:

(a + b)k ⩽ (2 · max({a, b}))k ⩽ (2a)k + (2b)k


which yields the expected inequality when replacing a (respectively b) by a/2 (respec-
tively b/2).
Now, let us prove that f(n, k) ∈ Θ(nk+1 ). One has:

f(n, k) = 1k + 2k + · · · + nk ⩽ n · nk = nk+1 .
Furthermore:

f(n, k) = 1k + 2k + · · · + (n − 1)k + nk
1k 1k 2k 2k (n − 1)k (n − 1)k nk nk
= + + + + ··· + + + +
2 2 2 2 2 2 2 2
1k + 1k + 2k + 2k + · · · + (n − 1)k + (n − 1)k + nk + nk
=
2
1 + n + 2 + (n − 1) + · · · + (n − 1)k + 2k + nk + 1k
k k k k
= .
2
Using formula 2.1, page 80, it comes:

 k  k !  n   n + 1 k
1 n+1 n+1
f(n, k) ⩾ + ··· + =
2 2 2 2 2
nk+1
⩾ .
2k+1

i i

i i
i i

i i

Solutions 87

Finally:
  
1
∀n · n ∈ N1 ⇒ ·nk+1
⩽ f(n, k) ⩽ 1 · nk+1
2k+1
which confirms that for k ∈ N and n ∈ N1 , one has:

f(n, k) ∈ Θ(nk+1 ).

Answers to problem 26. Order of growth: paradox? The problem is on page 81.
Answer 1. One has: 26 - A 1

X
n
n(n + 1) n2 n
= 1 + 2 + ··· + n = = +
2 2 2
i=1
Pn
therefore i=1 = 1 + 2 + · · · + n ∈ O(n2 ).

Remark
We could have used the result established in the third question of the preceding problem
by taking k = 1 for f(n, k).
Answer 2. The reasoning carried out operates on the image of the function and not 26 - A 2
on the function itself. As a matter of fact, the decomposition of the considered function in
terms of a sum of functions yields:

X
n ∞
X
f(n) = i= fi (n)
i=1 i=1

where the function fi is defined as fi (n) = i if n ⩾ i, 0 otherwise.


Indeed, here, we have an infinite sum, and the result established in problem 23, page 79,
does not apply.

Answers to problem 27. Average complexity: an example The problem is on


page 81.
Answer 1. The minimum complexity is 1, when T [1] = x. The maximum complexity is 27 - A 1
(n + 1), when x does not appear in T .
Answer 2. Now, we aim at establishing the average complexity of the search of x 27 - A 2
using the proposed algorithm. There are N!/(N − n)! distinct arrays which are drawn
equi-probably4 . There are (1/N) · (N!/(N − n)!) = (N − 1)!/(N − n)! arrays where x
is the head element. In such a case, a single comparison takes place. Thus, there are
N!/(N − n)! − (N − 1)!/(N − n)! = (N − 1)(N − 1)!/(N − n)! arrays which do not start
with x. Among those, 1 out of (N − 1) have x in second position, hence (N − 1)!/(N − n)!.
In such a case, two comparisons are performed. It is easy to observe that there are always
(N − 1)!/(N − n)! arrays with x in position i, leading to i comparisons, for i ∈ 1 .. n.
4 It is the number of arrangements of n objects out of N and not combinations, since the order according to which

objects come matters. For example, there are 60 distinct arrays when N = 5 and n = 3.

i i

i i
i i

i i

88 Complexity of an algorithm

(N − n)(N − 1)!/(N − n)! arrays remain where x cannot be found for which (n + 1) com-
parisons take place. Thus, the average number of comparisons is:
! !
1 Xn
(N − 1)! (N − n)(N − 1)!  n 
i + (n + 1) = (n + 1) 1 − .
N!
(N−n)!
(N − n)! (N − n)! 2N
i=1

In particular, for N = n, there are ((n+1)/2) comparisons in average. When N/n increases,
the number of comparisons tends to (n + 1).

Answers to problem 28. The ford in the fog The problem is on page 82.
28 - A 1 Answer 1. Generally speaking, when the ford is located n steps on the left away from
the starting point, the number of steps required by the suggested method is:
X
n−1
4· i + 3n = 4(n(n − 1))/2 + 3n = 2n2 + n.
i=1

If it is situated n n steps on the right, one must travel:


X
n−1
4· i + n = 4(n(n − 1))/2 + n = 2n2 − n
i=1

steps. In both cases, the number of steps is in Θ(n2 ).


28 - A 2 Answer 2. Using a geometric progression:
1. when the ford is 9 steps on the left away from the starting point, one does
1+(1+1)+(1+2)+(2+2)+(2+4)+(4+4)+(4+8)+(8+8)+(8+16)+(16+9) = 101
steps;
2. when the ford is 15 steps on the left away from the starting point, one does
1+(1+1)+(1+2)+(2+2)+(2+4)+(4+4)+(4+8)+(8+8)+(8+16)+(16+15) =
107 steps;
3. when the ford is 9 steps on the right away from the starting point, one does
1 + (1 + 1) + (1 + 2) + (2 + 2) + (2 + 4) + (4 + 4) + (4 + 8) + (8 + 8) + (8 + 9) = 69
steps;
4. when the ford is 15 steps on the right away from the starting point, one does
1 + (1 + 1) + (1 + 2) + (2 + 2) + (2 + 4) + (4 + 4) + (4 + 8) + (8 + 8) + (8 + 15) = 75
steps.
It can be observed that for the same distance, the ford is reached more quickly when it is on
the right (unsurprisingly since we walk on the right first). Moreover, in the last three cases,
the constraint bearing on the number of steps is met, since 107 < 9 · n (9 · 15 = 135), 69 <
9 · n (9 · 9 = 81), 75 < 9 · n (9 · 15 = 135), but not in the first case where 101 > 9 · n (9 · 9 = 81).
28 - A 3 Answer 3. The proposed strategy consists in walking one step on the right, (if needed)
coming back to the starting point and walking one step on the left, (if needed) coming
back to the starting point and walking three steps on the right, (if needed) coming back
to the starting point and walking three steps on the left, (if needed) coming back to the
starting point and walking three steps on the right, (if needed) coming back to the starting
point and walking three steps on the left, (if needed) coming back to the starting point and
walking nine steps on the right, (if needed) coming back to the starting point and walking
nine steps on the left, and so on. Thus, if the ford is located ten steps away from the starting
point on the left, we walk 1+(1+1)+(1+3)+(3+3)+(3+9)+(9+9)+(9+27)+(27+10) = 116
steps, therefore more then 9 · 10 = 90. Consequently, this strategy is not appropriate with
respect to the constraint imposed.

i i

i i
i i

i i

Solutions 89

Answer 4. The idea is to adopt the following schema, where the symmetry (left/right) 28 - A 4
is broken:

8 2 1 4 16
In contrast to the previous two methods, the actual position of the ford on the left side is
not a disadvantage. As a matter of fact, when the ford is 5 steps on the left, we have to
walk (1 + 1) + (2 + 2) + (4 + 4) + 5 = 19 steps, whereas when it is 5 steps on the right
(1 + 1) + (2 + 2) + (4 + 4) + (8 + 8) + 5 = 35 steps are necessary. In both cases, the number
of steps is less than 10 · 5 = 50, which bodes well.
Let us evaluate the number N of steps to walk when the ford is located on the left of the
starting point. When the ford is one (respectively two) steps on the left, it is reached with
three (respectively four) steps and the constraint is met since 3 < 10 · 1 and 4 < 10 · 1. When
it is located at a distance n greater than two steps, one has:

∃p · (p ∈ N1 and 22p−1 < n ⩽ 22p+1 )

yet:
22p−1
< 1. (2.2)
n
Relying on the schema describing the move strategy, the number of steps N is:

N = 2(20 + 21 + · · · + 22p ) + n. (2.3)

In effect, we walk back and forth alternatively on the left and on the right until the ford is
not reached. It comes:

N
= formula 2.3
2(20 + 21 + · · · + 22p ) + n
= sum of a geometric series
2(22p+1 − 1) + n
= arithmetics
8 · 22p−1 + n − 2
= arithmetics with n > 0
22p−1
n · (8 · + 1) − 2
n
< formula 2.2
9n − 2.

Let us study the values taken by N for n ∈ 22p−1 + 1 .. 22p+1 :


- if n = 22p+1 , N = 3 · 22p+1 − 2 = 3 · n − 2,
- if n = 22p+1 − 1, N = 3 · 22p+1 = 3 · n,
- if n = 22p+1 − 2, N = 3 · 22p+1 + 2 = 3 · n + 2,
- ...
- if n = 22p−1 + 2, N = 8 · 22p−1 + 22p−1 + 2 − 2 = 9 · n − 18
- if n = 22p−1 + 1, N = 8 · 22p−1 + 22p−1 + 1 − 2 = 9 · n − 10.

i i

i i
i i

i i

90 Complexity of an algorithm

It can be seen that, in the interval 22p−1 + 1 .. 22p+1 , we have: 3 · n − 2 ⩽ N ⩽ 9 · n − 10.


Since when the ford is only one step to the left, we have N = 1 (= 9n − 6), it appears that:
∀n ⩾ 1, 3n−2 ⩽ N ⩽ 9n−6. This shows that, on the one hand, the number of steps walked
is always less than 9n as requested, on the other hand, it varies in the proportion of 1 to 3.

The same result is obtained when the ford is located n steps to the right of the starting
point (we study the values of n between two even powers of 2 after treating the case n = 1
separately, for which we have N = 1).

If we now consider the framework of a geometric progression of reason 3, a reasoning


similar to the previous one shows that:
- when the ford is located one step to the left, N = 3,
- when the ford is located two steps to the left, N =4,
- when the ford is located at a distance n, such that 32p−1 ⩽ n ⩽ 32p+1 , with
p ⩾ 1, 2n − 1 ⩽ N ⩽ 10n − 10.
It can be deduced that the objective assigned is not met since the number of steps walked
can exceed 9n, but that its lower bound is decreased compared to that obtained with a
geometric progression of reason 2.

Complementary study
We will now show that, if we stick to geometric progressions, choosing the reason 2 is
optimal. To this end, we choose a continuous rather than discrete frame and we evaluate
distances, no longer in number of steps, but in divisible units, such as the meter. It is there-
fore considered that the ford is at a distance of n from the starting point, where n is this
time a positive real number. If we explore on the side of the ford and turn back after having
walked a length strictly less than n, the ford is by definition not yet reached.
Let us denote by E (real over 1.0) the reason for the geometric progression. So, the strategy
consists in making 1.0 meter on the right, E meters on the left, E2 meters on the right, etc.
We will assume that the ford is on the right at a distance of 2.0 meters or more, but it does
not matter as we have seen before. Let us look at the worst and the best cases, from the
point of view of the N/n ratio, where N is the distance (this time in meters) walked before
finding the ford.
For example, let E = 3.0 and n = 9.01. First we go one meter to the right, then we go
back to the starting point (another meter), then we go to the left at the distance E = 3.0,
we go back to the starting point (so far we have covered seven meters). We will now go
nine meters to the right and just miss the ford by one centimeter. We turn back on the
nine meters (provisional total: 25.0), we go back and forth to the left and we come back
to the starting point for a total of (25.0 + 2 · 27.0) = 79.0 meters. Only 9.01 meters to go
and we will reach the ford. We then covered a total distance of N = 88.01 meters, with a
ratio N/n = 9.768 · · · . Now imagine that the ford was not at n = 9.01 meters, but at ten
meters. We would have walked N = 89.0 meters, for a ratio N/n of 8.9, which would have
been better than the previous one. The further the ford would have been to the right, at a
distance less than or equal to 81.0 meters, the more this ratio would have decreased. The
ford is here on the right, at a distance n such that E2 < n ⩽ E4 . Generally speaking, if it is
on the right, there is an integer p such that E2p < n ⩽ E2p+2 and the worst case (the one
that maximizes the ratio N/n) is when n = E2p + ϵ with ϵ as small as desired. The best
case is when n = E2p+2 . The proof of validity of both statements is left to the reader.

i i

i i
i i

i i

Solutions 91

In the worst case, the distance walked is:

E2p (2E2 + E − 1) + E − 1 2
N = 2(1 + E + E2 + · · · + E2p+1 ) + E2p + ϵ = − + ϵ.
E−1 E−1
N can be rewritten as:
2E2 + E − 1 2p E2 + 1 2E2 + E − 1 E2 + 1
N= (E + ϵ) − 2ϵ = n − 2ϵ .
E−1 E−1 E−1 E−1
So we can see that N is linearly related to n.

What is the best value of E to minimize this distance in the worst case? Deriving the term
(2E2 + E − 1)/(E − 1), we see that it is minimum for E = 2.0 and in this case: N = 9n − 10ϵ.

We assume that the ford is on the right at a distance n ⩾ 2.0. In the best case (n = E2p ), the
number of steps is:
E+1 2
N = 2(1 + E + E2 + · · · + E2p−1 ) + E2p = n− .
E−1 E−1
We can see that N is also in linear relation with n and for E = 2 we have: N = 3n − 2.

Note that replacing E by E/(E−1) in the coefficient (2E2 +E−1)/(E−1) leaves this coefficient
unchanged. This results in identical limit values (L) of N/n, confirmed by the experiments
carried out by the authors, an excerpt of which is given in the table below:
E 1.2 1.25 1.4 1.5 1.8 2 2.25 3 3.5 5 6
L 15.4 13.5 10.8 10 9.1 9 9.1 10 10.8 13.5 15.4

i i

i i
Taylor & Francis
Taylor & Francis Group
http://taylorandfrancis.com
i i

i i

3
Specification, invariants, and iteration

Le bonheur est désir de répétition


(Happiness is a desire for repetition).

M. Kundera

This chapter illustrates the principle of reasoned development of loops. It could seem at
first sight that writing a loop is a straightforward task, but every programmer knows how
tricky it can be. The logical approach that we propose here applies to a variety of problems
and reveals the interest of its systematic and thorough nature. Several problems in Chapter
8 call also on loops and will supplement those proposed here. The main objective is to
equip the reader with strong bases about the construction of loops by invariant, however
without entering in too many sophisticated details.

3.1 Principle for the construction of loops by invariant


Generally speaking, the rational development of a program (algorithm) consists in con-
sidering it as a mechanism which transforms a “system” from an initial state called “pre-
condition” to a final state named “postcondition” or “goal”. This holds in particular for
loops which constitute the particular class of programs handled in this chapter. The pair
(precondition, postcondition) is called the specification of the program and we aim at the
development of a program on the basis of its specification. The notation prec prog postc,
used from now on, means that the program prog does come to an end and allows to go
from the situation prec to the situation postc. In other words, prog being a program, prec
and postc being predicates, prec prog postc means that if prog is run starting in a state
complying with prec then it finishes and the state reached meets the predicate postc.
In order to ease the reasoning underlying the development of the program prog, its
design is systematized by means of five components (in addition to precondition and post-
condition):
1. Invariant It is a predicate standing for a characteristic property of the problem
to be solved.
2. Stopping condition It is also a predicate.
3. Progression It is a piece of program/code.
4. Initialization It is a piece of program as well.
5. Termination This is an integer value expression1 .
1 The terms “bound function” or “variant” are also used by some authors.

DOI: 10.1201/b23251-3 93
i i

i i
i i

i i

94 Specification, invariants, and iteration

These components maintain the relationships described now.

1. First of all, the conjunction of the invariant and the stopping condition leads to the
desired goal, which can be formalized by:

(invariant and stopping condition) ⇒ postcondition.

2. Moreover, the progression must:

(a) preserve the invariant. More precisely, the progression is a fragment of program de-
fined by the precondition “invariant and not stopping condition” and the postcon-
dition “invariant”. Here, the assertion is that the invariant holds before and after
the progression is carried out. Of course, one must not conclude that the invariant
holds during the whole execution of the progression.
(b) strictly decrease the termination expression. More precisely, in looping situation
(i.e. when the predicate “invariant and not stopping condition” holds), the (inte-
ger) value of the termination expression after one progression step is positive or
zero and strictly less than its previous value. Thus, the stopping condition will be
met after a finite period of time, which ensures that the program finishes.
3. The initialization must establish the invariant. It is a piece of program whose precondi-
tion is that of the problem to be solved and whose postcondition is the invariant.
It is worth noticing that the first two components (invariant and stopping condition)
relate to situations while the next two (progression and initialization) are actions. Items 1, 2
and 3 clearly show that the invariant plays a central role since it appears in items 1, 2-a, 2-b
and 3. It constitutes the cornerstone of the construction of loops, in other terms the glue
which links the other components together. Hence, the development of a loop begins with
the identification of the invariant.
Figure 3.1 summarizes the aspects discussed earlier.
The encoding of the corresponding generic loop is as follows:

1. initialization;
2. while not stopping condition do
3. progression
4. end while
In this “minimal” notation, precondition, postcondition, invariant and termination ex-
pression do not appear. The last two elements are widely addressed in the design phase
and, in general, only the fist two are featured in the code as comments (introduced by the
keywords PRE and POST ).

The complexity of a loop is expressed in terms of either conditions to be evaluated (for


instance those related to its control), or sometimes an operation characteristic of the prob-
lem dealt with appearing in its body. Very often, loops have a linear complexity, but other
situations (e.g. logarithmic or polynomial) can be encountered as well.

i i

i i
i i

i i

An introductory example: the Euclidian division 95

precondition postcondition
of the loop of the loop

and
initialization

establishes
stopping
invariant
condition

and
not

progression
preserves

action situation entailment

Fig. 3.1 – Articulation invariant/stopping condition/progression/initialization.

3.2 An introductory example: the Euclidian division


We consider the classical problem of the Euclidian division. We are interested in the calcu-
lation of the quotient of the “integer” division of A by B (A ∈ N, B ∈ N1 ), knowing that we
are not provided with a division operation. The specification of the program to design is
given by the pair:

Precondition: (A ∈ N) and (B ∈ N1 ).
Postcondition: q is the quotient and r is the remainder of the division of A by B.

In order to make the postcondition “usable” (this point will be developed later), it is
reformulated on the basis of the definition of the Euclidian division by:

(A = B · q + r) and (0 ⩽ r < B).

From this expression, we take as invariant:

(A = B · q + r) and (0 ⩽ r)

and as stopping condition: r < B. The actions related to the progression and the initializa-
tion remain to be expressed, as well as the termination expression. As to the progression,
it suffices to increment q of 1 and to decrement r of the value of B to restore the invariant
(which is possible since the stopping condition is not met, hence r ⩾ B). The invariant is
established from the precondition by the assignments: 0 to q and A to r. Concerning the
termination expression, it can be observed that the expression (A − q · B) is equal to A
after the initialization takes place and diminishes of B whilst being positive after each step

i i

i i
i i

i i

96 Specification, invariants, and iteration

of the progression (it is possibly zero after the last iteration step). On the basis of the five
components pointed out on the one hand, and the generic code on the other hand, the fol-
lowing program is deduced:

1. constants
2. A ∈ N and A = . . . and B ∈ N1 and B = . . .
3. variables
4. q ∈ 0 .. A and r ∈ 0 .. B − 1
5. begin
6. /% PRE: (A ∈ N) and (B ∈ N1 ) %/
7. q ← 0; r ← A;
8. while not(r < B) do
9. q ← q + 1; r ← r − B
10. end while;
11. /% POST: (A = q · B + r) and (r ⩾ 0) and (r < B) %/
12. write(the quotient of the division of , A, by , B, is , q, and the remain-
der is , r)
13. end
It can be noticed that when A = 0, the “while” loop is not entered (it is the only case
indeed). Moreover, when A is a multiple of B, the remainder r is 0.

3.3 Useful techniques


In the previous example, the problem was fairly simple thus easily handled, but it is not
always so. Quite often, the precondition and/or the postcondition must be reformulated,
and this must be done so that the correctness of the program developed in fine is ensured.
We review some techniques allowing for legal transformations.

3.3.1 Sequential composition


We have seen that the construction of a program based on a loop is done in decompos-
ing the problem into five sub-problems. There is another type of decomposition frequently
used, namely that based on the sequentiality rule. It stipulates that if {P} prog1 {R} and
{R} prog2 {S} then {P} prog1 ; prog2 {S}. In this rule, the symbol “;” denotes the sequen-
tiality operator; {R} is called an intermediary situation. This rule can also apply to state
that if we look for a program specified by the pair (P, S), it suffices to find out an inter-
mediary situation R and two programs prog1 and prog2 such that: i) {P} prog1 {R}, and
ii) {R} prog2 {S}. The sequential composition of prog1 and prog2 is an answer to the initial
problem specified by (P, S).
Let us illustrate this process with the following example where we want to know if the
element of index K in the array T is its unique minimum. We want to develop the program
specified by:

Precondition: (T is a constant (non modifiable) array of N integers) and (N ⩾ 1) and (K


constant) and (K ∈ 1 .. N).
Postcondition: infk = (T [K] is strictly less than all other elements in T ).

i i

i i
i i

i i

Useful techniques 97

We want to elaborate a solution involving a single loop and where the array T is not nec-
essarily entirely read. A brief analysis shows that two cases may occur:

• the array T involves a single copy of its minimum which turns out to be T [K], which
requires the complete scan of T ,
• T [K] is not the minimum value of T (a value strictly less than T [K] is encountered and
the scan of T can stop), or T [K] is indeed the minimum of T and another value (T [i], i ̸=
K) equal to T [K] is encountered, and once again the scan of T can stop).

In order to facilitate the design of a solution, in a first time, the variable infk is ignored
and the following new postcondition is taken into consideration:

Postcondition: i is the lowest index of the interval 1 .. N different from K such that T [i] ⩽
T [K] if it does exist, (N + 1) otherwise

which stands for an intermediary situation (in the sense of sequential composition); the
following approach is thus envisaged:

1. We construct the loop (L OOP) specified by:

Precondition: (T is a constant array of N integers) and (N ⩾ 1) and (K


constant) and (K ∈ 1 .. N)
Postcondition: i is the index of 1 .. N different from K such that T [i] ⩽ T [K] (if such an
i exists), (N + 1) otherwise.

2. We build the complementary part (C OMP PART) specified by:

Precondition: i is the index of 1 .. N different from K such that T [i] ⩽ T [K] (if such an i
exists), (N + 1) otherwise.
Postcondition: infk = (T [K] is less than all other elements inT ).

The code related to C OMP PART consists in assigning the value of the relational expres-
sion (i = N + 1) to infk. As to that of L OOP, it relies on the following five components:

1. Invariant (i ∈ 1 .. N) and (∀j · (j ∈ ((1 .. i − 1) − {K}) ⇒ T [j] > T [K]))


2. Stopping condition (i = N + 1) or else ((i ̸= K) and (T [i] ⩽ T [K]))
3. Progression i ← i + 1
4. Initialization i ← 1
5. Termination N + 1 − i

It is easy to check that: (i) the conjunction of the invariant and the stopping condition en-
tails the postcondition, (ii) the progression preserves the invariant, (iii) the termination
expression decreases at each step whilst being nonnegative, and (iv) the initialization es-
tablishes the invariant, in other words that the relationships 1, 2-1, 2-2 and 3 are met. Even-
tually, the following program is built:

1. constants
2. N ∈ N1 and N = . . . and T ∈ 1 .. N → N and T = [. . .] and K ∈ 1 .. N and K =
...
3. variables

i i

i i
i i

i i

98 Specification, invariants, and iteration

4. i ∈ 1 .. N + 1 and infk ∈ B
5. begin
6. /% first part: L OOP %/
7. /% PRE: (T is a constant array of N integers) and (N ⩾ 1) and (K
constant) and (K ∈ 1 .. N) %/
8. i ← 1;
9. while not((i = N + 1) or else ((i ̸= K) and (T [i] ⩽ T [K]))) do
10. i←i+1
11. end while;
12. /% POST: i is the index of 1 .. N different from K such that T [i] ⩽ T [K] (if such
an i exists), (N + 1) otherwise %/
13. /% second part: C OMP PART %/
14. infk ← (i = N + 1);
15. if infk then
16. write(the element whose index is, K, in the array, T , is its unique
minimum)
17. else
18. write(the element whose index is, K, in the array, T , is not its unique
19. minimum)
20. end if
21. end

3.3.2 Predicate strengthening and weakening


The notion of strengthening of the predicate pred is often understood in a logical sense,
i.e. we consider the predicate pred′ (strengthening pred) since it complies with the prop-
erty: pred′ ⇒ pred. This approach must reveal to be of particular interest when facing the
specification (P, Q) it is easier to build the program prog′ such that {P} prog′ {Q′ } where
Q′ ⇒ Q (especially if Q′ is defined by the addition of a conjunct to Q), than the program
prog such that {P} prog {Q}. See for example the problem 42, page 122.
Conversely, we can talk about predicate weakening when considering a predicate
pred′′ (which weakens pred) meeting the property: pred ⇒ pred′′ . This approach is of
interest when in the presence of the specification (P, Q), it is easier to build the program
prog′′ such that {P′′ } prog′′ {Q} where P ⇒P′′ than the program prog such that {P} prog {Q}.
It is notably the case if P′′ if obtained by removing a conjunct from P.

3.3.3 Strengthening by the introduction of programming variables


Here, we consider a second type of predicate strengthening in which the state space of
the problem (the set of its variables) is enriched with (at least) one variable. For example,
let us consider the array T [1 .. N] (N ⩾ 1) of positive integers and the predicate P = b “s
stands for the sum of the elements of T ”. An equivalent formulation of P is P ′ =b “(s stands
for the sum of the first i elements of T ) and (i ∈ 1 .. N) and (i = N)”. A new variable
(i) is introduced and we have a strengthening of P, the initial predicate. The principal
interest of this approach lies in the fact that at least one conjunction is part of the new
predicate which will be exploited to find out an invariant for the considered problem. See
for example problem 31, page 111.

i i

i i
i i

i i

Heuristics for the discovery of invariants 99

3.4 Heuristics for the discovery of invariants


Programming is a goal-driven activity. The search for an invariant does not escape this rule,
and the three heuristics proposed hereafter are founded on the relationship between the
postcondition and the invariant. We successively review three concurrent basic techniques.
The first one, the breakup of the postcondition, assumes that the postcondition has the
form of a conjunction. As this case is seldom, it is frequently necessary to proceed to a
prior strengthening of the postcondition so as to display several conjuncts. The second
one, the hypothesis of the work carried out partly, leads (by its very nature) to an implicit
strengthening of the postcondition with the introduction of variables. The last heuristics is
the strengthening of the postcondition following that of the invariant.

3.4.1 Breakup of the postcondition


Due to the property associated with relationship A (see page 94), when the postcondition
is expressed as a conjunction, it may be convenient to identify one of the conjuncts as the
invariant and the other one to the stopping condition. The method applies as well when the
postcondition involves several conjunctions. On the one hand, one (or several) conjunct(s)
will form the invariant, on the other hand the stopping condition will be made with the
remaining conjunct(s), which is formalized as follows:
Postcondition: B1 and B2 and . . . and Bn
Stopping condition: Bi and . . . and Bj
Invariant: B1 and B2 and . . . and Bi−1 and Bj+1 and . . . and Bn
There is no systematic way for breaking up the postcondition. However, the following
suggestions can be useful:
• It is desirable that the stopping condition is syntactically expressed in a usual program-
ming language, so that its negation plays the role of a loop condition. This excludes
predicates with quantifiers such as ∀j · (j ∈ · · · ⇒ · · · ).
• It is preferable that the invariant is easy to establish from the precondition. Hence, once
the choice of the invariant made, the difficulty to establish it (the initialization phase)
must be assessed.
• All the variables of the postcondition must appear in the invariant (in other words, the
stopping condition must not contain “orphan” variables).
The approach is illustrated with the following example, where we look for the first zero
in an array of numbers. We want to develop the program specified by:
Precondition: (T is a constant array of N integers) and (there is at least one zero in T ).
Postcondition: The variable i indicates the zero of T whose index is the lowest (the “left-
most” zero).
Since there is at least one zero in T , it can be noted that N ⩾ 1. As this algorithm demands
the total or partial scan of the array, we will build an iteration. Moreover, the postcondition
is not under conjunctive form and it must be strengthened by replacing an expression exp
(here N) by a variable v (here i) and adding the conjunct (v = exp). In the remainder, this
type of transformation is called “transformation under constructive form”. We reformulate
the initial postcondition in:

i i

i i
i i

i i

100 Specification, invariants, and iteration

Postcondition: (i ∈ 1 .. N) and (T [1 .. i − 1] contains no zero) and (T [i] = 0).

It is then possible to breakup the postcondition and to apply the suggestions made above
to divide it into two parts, the first one being the invariant and the second one the stopping
condition:

1. Invariant The first two conjuncts are easy to establish and thus taken for the invariant:

(i ∈ 1 .. N) and (T [1 .. i − 1) contains no zero)

which can be graphically illustrated by:

1 i N
T

̸= 0

The conjunct (T [i] = 0) has been discarded. It is indeed a predicate which is difficult to
establish since it demands the localization of a zero!
2. Stopping condition The discarded conjunct is chosen, i.e. T [i] = 0. It can be noticed that
this predicate involves no quantifier which makes it possible to integrate its negation
into the loop condition.
3. Progression It is specified by:

Precondition: (i ∈ 1..N) and (T [1..i−1] contains no zero) and not (T [i] = 0)


P ROGRESSION
Postcondition: (i ∈ 1 .. N) and (T [1 .. i − 1] contains no zero).

A possible idea for the progression is to move i one position to the right by the assign-
ment: i ← i + 1. The invariant is fulfilled by the new situation since there is no zero in
T [1 .. i − 1] and that there is necessarily one after T [i − 1] (according to the precondition)
hence i ⩽ N and i ∈ 1 .. N.
4. Initialization It is specified by:

Precondition: (T is a constant array of N integers) and (there is at least one


zero in the array T )
I NITIALIZATION
Postcondition: (i ∈ 1 .. N) and (T [0 .. i − 1] contains no zero).

Moving from the precondition to the invariant, means that the following situation is
reached:

1/i N
T

where the invariant is fulfilled since, when i = 1, it is instantiated as: (1 ∈ 1 ..


N) and (T [1 .. 0] contains no zero). This can be obtained by the assignment: i ← 1.

i i

i i
i i

i i

Heuristics for the discovery of invariants 101

5. Termination The expression (N − i) is suitable, since it remains nonnegative and it di-


minishes at each step of the progression.

Eventually, we have built the following program:

1. constants
2. N ∈ N1 and T ∈ 1 .. N → N and T = [. . .]
3. variables
4. i ∈ 1 .. N
5. begin
6. /% PRE: (T is a constant array of N integers) and (there is at least one zero
in the array T ) %/
7. i ← 1;
8. while not(T [i] = 0) do
9. i←i+1
10. end while;
11. /% POST: (i ∈ 1 .. N) and (T [1 .. i − 1] contains no zero) and (T [i] = 0) %/
12. write(the index of the leftmost zero in , T , is , i)
13. end
In the best case, this algorithm is in Θ(1) and at worst it is in Θ(N) in terms of comparisons.

In section 3.7, several problems are proposed in which the initial postcondition is not
expressed in a conjunctive form. In such a situation that occurs very frequently in prac-
tice, the postcondition must first be turned into a “constructive” form, i.e. expressed as a
conjunction which is to be broken up.

3.4.2 Hypothesis of the work carried out partly


One of the characteristics of the invariant is that it is a property which holds at each step
of the loop. It is thus legitimate to exploit this specificity when looking for an invariant.
Assuming that a part of the work is already done, the question of interest is:

”What situation are we in?”

whose answer is often the expected invariant.


This technique is illustrated by the “classical” simple example called “the Monaco
flag”, whose statement is the following. The initial situation is the array T [1 .. N] (N ⩾ 0)
whose elements are either white or red and constitute the constant bag B. The final situa-
tion is the array forming the same bag B, inside which white (respectively red) elements
are on the left (respectively right) hand side. It is imposed to go from the initial situation
to the final one using a single loop, which scans the array from left to right. Changes in the
array T are done only by exchanges between two elements of index i and j (Exchange(i, j)),
which ensures the preservation of the initial values of the bag B.
We are searching for an invariant assuming that the work is carried out partly and that
the configuration depicted in figure 3.2 is reached:
Formally, this configuration is defined by the formula:

(∀u · (u ∈ 1 .. i − 1 ⇒ T [u] = White)) and (1 ⩽ i ⩽ k + 1 ⩽ N + 1) and


(∀u · (u ∈ k + 1 .. N ⇒ T [u] = Red))

This expression covers the following cases:

i i

i i
i i

i i

102 Specification, invariants, and iteration

1 i k N
T White ? Red

Fig. 3.2 – Situation in which the work is carried out partly.

• The initial situation where the content of T is unknown (neither white, nor red element
localized), with i = 1 and k = N. As a matter of fact, the above formula which thus
writes:

(∀u · (u ∈ 1 .. 0 ⇒ T [u] = White)) and (1 ⩽ 1 ⩽ N + 1 ⩽ N + 1) and


(∀u · (u ∈ N + 1 .. N ⇒ T [u] = Red))

is evaluated to true and it expresses that nothing is known about each of the elements
of T ,
• The final situation where all elements are localized (white elements on the left, red ones
on the right), with k = i − 1,
• A situation where there is at least one red element and no white one, with i = 1 and
0 ⩽ k < N,
• A situation where there is at least one white element and no red one, with 1 < i ⩽ N+1
and k = N,
• The case where T is empty (N = 0).

It reveals to be an invariant for the problem to solve.


From the starting situation (precondition) and the arrival situation (postcondition), we
now define the five elements of the loop.

1. Invariant We take the expression associated with figure 3.2, namely:

(∀u · (u ∈ 1 .. i − 1 ⇒ T [u] = White)) and (1 ⩽ i ⩽ k + 1 ⩽ N + 1) and


(∀u · (u ∈ k + 1 .. N ⇒ T [u] = Red)).

2. Stopping condition The loop terminates when k = i − 1. It has been pointed out (see
item 3.4.2) that then the conjunction of the invariant and the stopping condition entails
the postcondition.
3. Progression The action to undertake in the progression depends on the color of T [i]. If
T [i] is white, i is incremented by 1 (which extends the zone containing white elements)
and if T [i] is red, it is exchanged with T [k] and k is decremented by 1 (which enlarges
the zone involving red elements).
4. Initialization Operations related to the initialization have been evoked in item 3.4.2,
and they come down to two assignments: i ← 1 and k ← N.
5. Termination The expression (k−i+1) is suitable since it is equal to N after initialization,
it decreases by 1 at each iteration step and its value is zero when the stopping condition
is met.

i i

i i
i i

i i

Heuristics for the discovery of invariants 103

Finally, we have the program hereafter:


1. constants
2. N ∈ N and N = . . . and T ∈ 1 .. N → {White, Red} and T = [. . .]
3. variables
4. i ∈ 1 .. N and k ∈ 1 .. N
5. begin
6. /% PRE: T [1 .. N] is an array whose elements are either white, or red %/
7. i ← 1; k ← N;
8. while k ̸= i − 1 do
9. if T [i] = White then
10. i←i+1
11. else
12. Exchange(i, k); k ← k − 1
13. end if
14. end while;
15. /% POST: white (respectively red) elements in T are in the left (respectively
right) part of T %/
16. write(T )
17. end
This algorithm is in Θ(N) comparisons (N comparisons are about values of T and N for
the control of the loop). It demands as many exchanges as there are red elements (whatever
their initial position); hence, the algorithm is in O(N) exchanges.
As in most of problems, the invariant is not unique. The interested reader is invited
to elaborate about the invariant which derives from the situation of the work carried out
partly given in figure 3.3.

1 i k N
T White Red ?

Fig. 3.3 – Another situation related to the hypothesis of the work carried out partly.

3.4.3 Strengthening the invariant


We have seen that the conjunction of the invariant P and the stopping condition B must
entail the postcondition R:

(P and B) ⇒ R.
It has been suggested to reformulate the postcondition by introducing one (or sev-
eral) variable(s) in order to make a conjunction appear. In doing so, we have strengthened
the initial postcondition by an auxiliary postcondition which entails it. However, it may
happen that, for necessity reasons or by opportunity, the strengthening of the postcondi-
tion appears only during the development phase. In such cases, the strengthening of the
postcondition is often expressed indirectly by the strengthening of the invariant. Thus, an
additional conjunct P′ is associated with the “natural” invariant so as to either ensure the
progression, or express a stopping condition. More formally, we have:
(P and P′ and B) ⇒ (P and B)
⇒ one has either (P and B) = R, or at worst (P and B) ⇒ R
(P and P′ and B) ⇒ R.

i i

i i
i i

i i

104 Specification, invariants, and iteration

The approach adopted is made up of four parts:


1. The loop is first developed on the basis of the “natural” invariant.
2. It is observed that the value of an expression is missing to pursue the construction of
the loop.
3. This value is assumed to be available (thanks to the introduction of a variable). This
leads to add a new conjunct to the preexisting invariant.
4. The construction of the loop is resumed on the basis of the new invariant.
This approach is now illustrated to compute the sum of the elements located “on the
left” of the maximum value (assumed to be unique) of an array. We want to build the
program made up of a single loop and specified by:
Precondition: (T is a constant injective (all values in T are distinct) array of N
integers) and (N ⩾ 1).
Postcondition: m is the position of the maximum in T and s is the sum of the elements
T [1 .. m − 1].
The position of the maximum in T [1 .. N] being m, the situation at the end of the program
is expected to be the following:

T [m] = max (T [j])


j∈1..N

1 m N
T

X
m−1
s= T [j]
j=1

More formally, making the domain of the variables explicit, the postcondition is rewritten:
 
X
m−1
(m ∈ 1 .. N) and (T [m] = maxj∈1..N (T [j])) and (s ∈ Z) and s = T [j].
j=1

First attempt
The postcondition is strengthened so as to obtain a conjunction on the basis of the follow-
ing situation:

T [m] = maxj∈1..i−1 (T [j])

1 m i N
T

X
m−1
s= T [j]
j=1

i i

i i
i i

i i

Heuristics for the discovery of invariants 105

First, let us examine the variation domain of variables i, m and s. So that m takes a
value, the array T [1 .. i − 1] must be nonempty, which entails that i is not equal to 1. Hence,
i is varying in the interval 2 .. N + 1, whereas m ∈ 1 .. i − 1 and s ∈ Z. Adding this
information, we get:

Postcondition (version stemming from the strengthening of the previous postcondition):


(i ∈ 2 .. N + 1) and (m ∈ 1 .. i − 1) and (T [m] = max (T [j])) and (s ∈ Z) and (s =
j∈1..i−1
X
m−1
T [j]) and (i = N + 1).
j=1

This postcondition opens to a first breakup attempt.


1. Invariant The first five conjuncts are easy to establish and they constitute the invariant:

(i ∈ 2 .. N + 1)
 and (m ∈ 1 .. i − 1) and (T [m] = maxj∈1..i−1 (T [j])) and
X
m−1
(s ∈ Z) and s = T [j].
j=1

2. Stopping condition We keep the discarded conjunct: i = N + 1.


3. Progression How to move from a situation where the invariant holds, as well as not(i =
N + 1), to a situation where the invariant still holds, while advancing towards the
postcondition of the statement? Let us have a look at T [i]. If i is not the position of
the maximum of T [1 .. i] there is nothing else to do but increment i (by 1). Otherwise,
a solution is to compute (using a loop) and store (in s) the sum of the elements of
T [1 .. i − 1]. It is easy to guess that some of the sums will be calculated twice or more.
the idea is to take advantage of the calculations already performed, and to this end, to
consider that this sum is available in the variable v. Thus, the update of s demands no
loop, s takes the value of v. Making this assumption is a strengthening of the invariant
P
by the conjunct v = i−1 j=1 T [j]. It is now necessary to rebuild the loop on the basis of the
new invariant.

Second attempt
The invariant (and indirectly the postcondition) is strengthened by the addition of the
X
i−1
conjunct v = T [j].
j=1

1. Invariant It becomes:

(i ∈ 2 .. N + 1) and (m ∈ 1 .. i − 1) and (T [m] = max (T [j])) and


  j∈1..i−1 
X
m−1 X
i−1
(s ∈ Z) and s = T [j] and (v ∈ Z) and v = T [j]
j=1 j=1

i i

i i
i i

i i

106 Specification, invariants, and iteration

graphically:
 
X
i−1
(T [m] = max (T [j])) and v = T [j]
j∈1..i−1
j=1

1 m i N
T

X
m−1
s= T [j]
j=1

2. Stopping condition We keep the same stopping condition: i = N + 1.


3. Progression The progression is specified by:
Precondition: (i ∈ 2 .. N + 1) and (m ∈ 1 .. i − 1) and (T [m] = maxj∈1..i−1 (T [j])) and
P Pi−1
(s ∈ Z) and (s = m−1
j=1 T [j]) and (v ∈ Z) and (v = j=1 T [j]) and not(i = N + 1)
P ROGRESSION
Postcondition: (i ∈ 2 .. N + 1) and (m ∈ 1 .. i − 1) and (T [m] = maxj∈1..i−1 (T [j])) and
P Pi−1
(s ∈ Z) and (s = m−1
j=1 T [j]) and (v ∈ Z) and (v = j=1 T [j]).

If i is the position of the new maximum in T [1 .. i], s takes the value of v. The variables
m and v are then updated, T [i] is added to v and i is incremented by 1.
4. Initialization The initialization is specified by:
Precondition: (T is a constant injective array of N integers) and (N ⩾ 1).
I NITIALIZATION
Postcondition: (i ∈ 2 .. N + 1) and (m ∈ 1 .. i − 1) and (T [m] = maxj∈1..i−1 (T [j])) and
P Pi−1
(s ∈ Z) and (s = m−1
j=1 T [j]) and (v ∈ Z) and (v = j=1 T [j]).

The value 2 is assigned to i, which enforces other variables to comply with the follow-
ing constraints:
(s = T [1]) and (v = T [1]) and (m = 1).

4. Termination The variable i is incremented at each step of the progression. The expres-
sion (N + 1 − i) is suited to ensure the termination.

Eventually, the following program is built:

1. constants
2. N ∈ N1 and N = . . . and T ∈ 1 .. N → Z and T = [. . .]
3. variables
4. i ∈ 1 .. N + 1 and m ∈ 1 .. N and v ∈ Z and s ∈ Z
5. begin
6. /% PRE: T is a constant injective array of N integers) and (N ⩾ 1)) %/
7. i ← 2; s ← T [1]; v ← T [1]; m ← 1;
8. while not(i = N + 1) do

i i

i i
i i

i i

About bounded linear search 107

9. if T [i] > T [m] then


10. s ← v; m ← i
11. end if;
12. v ← v + T [i]; i ← i + 1
13. end while;
14. /% POST: m is the position of the maximum in T and s is the sum of the
elements T [1 .. m − 1] %/
15. write(the sum of the elements before that of index , m, is , s)
16. end
This solution demands at worst and at best N iterations and (2N + 1) comparisons.

3.5 About bounded linear search


Linear search is a class of algorithms looking for the smallest of the elements of a nonempty
set fulfilling a predicate P(i).
Bounded linear search is close to linear search, except that the set of solutions can be
empty. Generally, the result returned in case of failure is either a conventional value outside
the definition domain of P, or a Boolean.

3.5.1 An example
We want to know whether the sum of the elements of the constant array T [1 .. N] is greater
than a given value S, or not.
We want to build the program specified by:

Precondition: (T is an array of N natural numbers) and (N ⩾ 0) and (S constant) and (S ∈


N1 ).
P
Postcondition: sgs = ( N j=1 T [j] > S).

The postcondition is not in a constructive form, hence the expression (N + 1) is replaced


by the variable i and the postcondition becomes:
P
Postcondition: (i ∈ 1 .. N + 1) and (sgs = ( i−1
j=1 T [j] > S)) and (i = N + 1).

The presence of a quantification suggests that its evaluation as such will raise a difficulty
and we proceed to a second strengthening with the introduction of the variable ps calcu-
lating the partial sum of the first (i − 1) elements of T , hence:
Pi−1
Postcondition: (i ∈ 1 .. N + 1) and (ps = j=1 T [j]) and (sgs = (ps > S)) and (i = N + 1).

Now, the development of the algorithm can begin.

1. Invariant The first three conjuncts are easy to establish and they serve for the invariant:
 
X
i−1
(i ∈ 1 .. N + 1) and ps = T [j] and (sgs = (ps > S)).
j=1

2. Stopping condition We take the discarded conjunct: (i = N + 1).

i i

i i
i i

i i

108 Specification, invariants, and iteration

3. Progression The progression is specified by:


P
(i ∈ 1 .. N + 1) and (ps = i−1
j=1 T [j]) and (sgs = (ps > S)) and not(i = N + 1)
P ROGRESSION
Pi−1
(i ∈ 1 .. N + 1) and (ps = j=1 T [j]) and (sgs = (ps > S)).
A solution to this specification is:
1. ps ← ps + T [i];
2. sgs ← sgs or (ps > S);
3. i ← i + 1

4. Initialization The initialization is specified by:


Precondition: (T is an array of N natural numbers) and (N ⩾ 0) and (S constant) and (S ∈
N1 )
I NITIALIZATION
Pi−1
Postcondition: (i ∈ 1 .. N + 1) and (ps = j=1 T [j]) and (sgs = (ps > S)).
The three assignments 1 to i, 0 to ps and false to sgs answers this specification.
5. Termination (N + 1 − i) is a suitable termination expression.

We can observe that the algorithm could stop as soon as sgs turns to true, which could di-
minish the number of iterations, thus complexity at worst. This remark leads to the modi-
fication of both the stopping condition and the progression in the preceding development.
The stopping condition is modified accordingly and a new loop is built.

1. Invariant It remains unchanged.


2. Stopping condition We take: (i = N + 1) or sgs.
3. Progression The second assignment of the progression is (sgs or (ps > S)), whose eval-
uation is done in the context of the precondition of the progression (entailing that sgs
is false), hence:

sgs or (ps > S)


⇔ not(sgs) and propositional calculus
ps > S

4. Initialization It remains unchanged.


5. Termination It is unchanged.

The following program is obtained:

1. constants
2. N ∈ N and N = . . . and T ∈ 1 .. N → N and T = [. . .] and S ∈ N1 and S = . . .
3. variables
4. i ∈ 1 .. N + 1 and sgs ∈ B and ps ∈ N
5. begin
6. /% PRE: (T is an array of N natural numbers) and (N ⩾ 0) and (S constant) and (S ∈
N1 ) %/
7. i ← 1; sgs ← false; ps ← 0;

i i

i i
i i

i i

About bounded linear search 109

8. while not((i = N + 1) or sgs) do


9. ps ← ps + T [i]; sgs ← (ps > S); i ← i + 1
10. end while;  
XN
11. /% POST: sgs =  T [j] > S %/
j=1
12. write(sgs)
13. end
The complexity of this algorithm is in O(N) comparisons.

3.5.2 Special case and related pattern


Problems resembling the previous one occur frequently and the identification of a pro-
gramming pattern for bounded linear search is convenient. It provides the ability of in-
stantiation rather than a development ex nihilo.
We consider the search for the first element (whatever the structure used, set, bag, array,
etc.) among N for which a given property P is true; j contains the identity of this element or
(N + 1) if it does not exist. In addition, we assume that property P, denoted LP(j), is “local”
to element j, in the sense that its evaluation does not depend on the elements examined
before it. Last, it may happen that, in contrast to the previous example, the property LP
cannot be evaluated when j = N + 1. Consequently, the stopping condition uses a “short-
circuiting” disjunction. The resulting pattern, used in problems 34, page 113, and 41, page
121, is the following:
1. constants
2. N ∈ N and N = . . .
3. variables
4. j ∈ 1 .. N + 1 and LP ∈ B and . . .
5. begin
6. /% PRE: . . . %/
7. j ← 1; . . .
8. invariant
9. ...
10. termination
11. N+1−j
12. while not((j = N + 1) or else LP) do
13. j←j+1
14. end loop;
15. /% POST: . . . %/
16. if j = N + 1 then
17. write(no element . . . )
18. else
19. write(element , j, . . . )
20. end if
21. end

i i

i i
i i

i i

110 Specification, invariants, and iteration

3.6 Some key points to develop a loop


Building a loop starts with the search for an invariant which plays a central role for the
design of the other components of the loop: initialization, stopping condition, progression
and termination. The notion of invariant specifies the relationships between the variables
of the loop. There is no recipe ensuring that an invariant will be found out, but we recom-
mend to “derive” it from the postcondition of the program to build, which expresses the
situation expected at the end of the execution of the loop. The conjunction of the invariant
and the stopping condition must logically entail the postcondition. Therefore, a heuristics
for the discovery of an invariant consists in splitting the postcondition so as to identify
an invariant on the one hand and a stopping condition on the other hand. The postcondi-
tion may be strengthened by the introduction of new variables in order to facilitate such
a breakup. Insofar as the invariant is a property which holds at each step of the loop, it
can be discovered assuming that the work is carried out partly in formalizing the situation
attained.
As to the precondition of the loop, it specifies the situation before the beginning of the
loop. The role of the initialization is to establish the invariant, thus to move from precon-
dition to invariant. The progression must preserve the invariant whilst making “progress”
in the resolution of the problem. Last to ensure that the loop stops, a nonnegative integer
expression is connected with the evolution of the loop, which must decrease at each step.

3.7 Problems
Problem 29. White and red beans ◦
◦ •

This famous problem by D. Gries [15] highlights the fact that it is possible to reason about a
given algorithm (or program) by identifying its invariant.

A can contains a number W of white beans and R of red beans (W + R ⩾ 1). We are
provided with a reserve of red beans which suffices to perform the following operation
while it is possible:
Two beans are randomly taken from the can
if they have the same color then
they are thrown away and one red bean is put back into the can
else
the red bean is thrown away and the white bean is put back into the can
end if

29 - Q 1 Question 1. Why does this process stop?


29 - Q 2 Question 2. What can be said about the color of the last bean remaining in the can?
The solution is on page 127.

i i

i i
i i

i i

Problems 111

Problem 30. From a coder’s dustbin ◦


◦ •

This problem highlights the importance of a safe construction.

We have found the following text in a dustbin of a computer science school:

Precondition: (T is a constant array of N natural numbers) and (N ⩾ 1).

Postcondition: The variable sup contains the highest value in T .

1. Invariant: (i ∈ 1 .. N) and (∀j · (j ∈ 1 .. i − 1 ⇒ T [j] ⩽ sup)).

2. Stopping condition: (i = N).


3. Progression:
1. if T [i] > sup then
2. sup ← T [i]
3. end if;
4. i ← i + 1
4. Initialization: i ← 2; sup ← T [1]

5. Termination: (N + 1 − i)

Question 1. Which errors originate the rejection? 30 - Q 1

Question 2. Give a safe version. 30 - Q 2

The solution is on page 127.

Problem 31. Summing up the elements of an array ◦ •

This problem is a simple application of the postcondition splitting principle in order to find
out an invariant, once it is appropriately reformulated to be under constructive form.

Question 1. Build the program specified by: 31 - Q 1


Precondition: (T is a constant array of N natural numbers) and (N ⩾ 0).
Postcondition: s stands for the sum of the N elements of T .

Question 2. What is its time complexity in terms of additions? 31 - Q 2


The solution is on page 127.

Problem 32. Searching in a bidimensional array ◦


◦ •

This problem is dedicated to the “basic” problem of search of a value in a bidimensional array.
A “natural” solution makes use of two loops, but it is shown that it is easy and elegant to
proceed with a single one. The proposed approach can be easily extended to a higher number
of dimensions. We will use the hypothesis of the work carried out partly.

i i

i i
i i

i i

112 Specification, invariants, and iteration

Let us consider the following specification:

Precondition: (T is a constant array of natural numbers with R rows and C


columns) and (R > 0) and (C > 0) and (V is a natural number present
in T ).
Postcondition: (i, j) stands for an occurrence of V in T , i.e. T [i, j] = V.

32 - Q 1 Question 1. Propose the elements of a single loop answering this specification, on the
basis of the hypothesis of the work carried out partly.
32 - Q 2 Question 2. Write the corresponding program and give its complexity in terms of com-
parisons.

Remark
We invite the reader to build the equivalent program made of two loops so as to compare
it with the previous one, especially regarding the ease of design.
The solution is on page 129.

Problem 33. Sorting by straight selection ◦ •


A sort program is now presented. Although it is not among “efficient” sorts, it is interesting
from a pedagogic point of view. Moreover, in contrast to the previous problem, it relies on two
nested loops according to an approach both simple and progressive.

We want to develop the program specified by:

Precondition: (T is an array of N natural numbers) and (S is the constant bag of


the values in T ) and (N ⩾ 1).
Postcondition: (T is sorted in ascending order) and (S is the bag of the values in
T ).

The second conjunct of the postcondition expresses that the content of T does not
change but possibly the order of its elements. The exclusive use of the procedure Ex-
change(i, j) previously introduced (see section 3.4.2, page 101) guarantees the compliance
with this property. In this way, this conjunct can be definitely dropped.
The postcondition is not under constructive form and it must be strengthened:

Postcondition: (i ∈ 1 .. N + 1) and (T [1 .. i − 1] is sorted) and (i = N + 1).

Assuming that the work is carried out partly, we are in the situation represented here-
after:

1 i N
T

sorted

i i

i i
i i

i i

Problems 113

We can already glimpse that the progression will aim at doing so that T [1 .. i] is sorted.
We have two possible choices: i) to insert T [i] in T [1 .. i] at the right place, and ii) to keep
T [1 .. i − 1] unchanged assuming that all the values in T [i .. N] are greater than (or equal to)
those of T [1 .. i − 1]. The first option corresponds to the sort by insertion and we choose the
second one, called sort by selection, because it requires to select the smallest value in T [i .. N].
Question 1. Give the postcondition associated with this option, then specify the com- 33 - Q 1
ponents of the resulting loop, skipping the specification of the part related to the identifi-
cation of the position m of the minimum in T [i .. N].
Question 2. We have now to handle the loop corresponding to the identification of the 33 - Q 2
position m of the minimum in T [i .. N]. This fragment of program is specified by:

Precondition: (i constant) and (i ∈ 1 .. N) and (T [i .. N] is a nonempty array of


natural numbers)
IDENTIFICATION OF THE POSITION m OF THE MINIMUM IN T [i .. N]
Postcondition: (m ∈ i .. N) and (T [m] = minj∈i..N (T [j])).

The array T [i .. N] is nonempty since in the context of execution of this loop, we have:
i ∈ 1 .. N + 1 and i ̸= N + 1. So, we are sure to find a minimum value in T [i .. N].
The postcondition can be schematized by:
1 i m N
T

T [m] = minj∈i..N (T [j])


Propose a strengthening of this postcondition in order to put it under constructive form by
the introduction of the variable k in the quantification of the minimum in connection with
N.
Question 3. Develop the corresponding loop. 33 - Q 3

Question 4. Write the program achieving the sort by selection of the array T [1 .. N]. 33 - Q 4

Question 5. What is its complexity in terms of number of exchanges? 33 - Q 5

The solution is on page 131.

Problem 34. Was it a car or a cat I saw ◦ •

The use of the pattern proposed for bounded linear search (see section 3.5, page 107) is illus-
trated through a simple example.

Let T [1 .. N] (N ⩾ 0) be a given character string (a word). T is a palindrome if the word


(or sentence, spaces being ignored) it stands for, writes the same way from left to right and
conversely. That is, T is the mirror string of itself.

i i

i i
i i

i i

114 Specification, invariants, and iteration

34 - Q 1 Question 1. Prove that, when T represents a palindrome, the following property holds:

∀j · ((1 ⩽ j ⩽ N) ⇒ (T [j] = T [N + 1 − j])).

34 - Q 2 Question 2. Indicate why and how this problem can be solved with an adaption of the
pattern featured in section 3.5.2, page 109.
34 - Q 3 Question 3. Write the program which decides whether T stands or not for a palin-
drome.
34 - Q 4 Question 4. Give its complexity in terms of evaluated conditions.
The solution is on page 133.

Problem 35. The Dutch national flag (variant) ◦


◦ •

This problem illustrates the use of the hypothesis of the work carried out partly. The Dutch
flag is a classical problem, so named by its author, E.W. Dijkstra, because the original version
is aimed at replenishing the colors of the flag of his country. The version dealt with here is
slightly different since natural numbers are managed instead of colors. This algorithm is at
the heart of quicksort which makes one of its major interests.

We would like to build the program specified by:

Precondition: (T is an array of N natural numbers) and (S is the constant bag of


the values contained in T ) and (N ⩾ 1) and (V = T [1]).
Postcondition: (S is the bag of the values contained in T ) and (T is made of three
parts, on the left values less than V, on the right values greater than V and in
the middle all occurrences of V).

Roughly speaking, the postcondition appears as shown below (the middle zone is not
empty since it contains at least one copy of V):

1 p q N
<V =V >V q>p

All the modifications of T will be done through exchanges (procedure Exchange(i, j)


where i and j refer to indexes of elements of T ). Therefore, as in problem 33 page 112,
the first conjunct of the postcondition can be omitted from now on. The complexity of the
solution(s) is evaluated in terms of calls to procedure Exchange. First, let us formalize the
postcondition:

Postcondition (formalized version):


∃(p, q) · ((p ∈ 1 .. N) and (q ∈ p + 1 .. N + 1) and (∀j · (j ∈ 1 .. p − 1 ⇒ T [j] < V)) and
(∀j · (j ∈ p .. q − 1 ⇒ T [j] = V)) and (∀j · (j ∈ q .. N ⇒ T [j] > V))

i i

i i
i i

i i

Problems 115

This version of the postcondition cannot be used as such for a breakup. We will trans-
form it (strengthen): we replace the variables of existential quantification p and q by the
programming variables b and w (see section 3.3.3, page 98), hence:

Postcondition (second version):


(b ∈ 1 .. N) and (w ∈ b + 1 .. N + 1) and (∀j · (j ∈ 1 .. b − 1 ⇒ T [j] < V)) and
(∀j · (j ∈ b .. w − 1 ⇒ T [j] = V)) and (∀j · (j ∈ w .. N ⇒ T [j] > V)).

At this stage, there is no evidence for a breakup and we envisage the introduction of
the variable r in association with one of the identifiers b, w and N do that a new conjunct
appears.
Question 1. Give the expression of the postcondition resulting from the association of 35 - Q 1
r with w, then the invariant for which a graphical representation is asked.
Question 2. Pursue the construction of the loop while identifying the cases where no 35 - Q 2
exchange is needed and so that at most one exchange occurs for each step of the progres-
sion.
Question 3. Write the program stemming from this construction and specify its com- 35 - Q 3
plexity in terms of exchanges.
The solution is on page 134.

Problem 36. 7s and 23s ◦ •

This problem shows another example of use of the hypothesis of the work carried out partly.
Here, the stopping condition is worthy of a special attention.

Let T [1 .. N] be an array of integers, with N ⩾ 0. We want to design a program per-


forming a permutation of the values of T so that all 7s are located before the 23s. The final
content of T must differ from the initial configuration only in the position of values 7 and
23. Like in the previous problem, the procedure Exchange(i, j) is assumed to be available.
Question 1. Complement the schema hereafter in order to point out an invariant on 36 - Q 1
the basis of the hypothesis of the work carried out partly.
1 i j N

Question 2. What can be observed when i = j ? Can we take this predicate as the 36 - Q 2
stopping condition?
Question 3. Provide the three other components of the loop. 36 - Q 3

Question 4. Deduce the complexity of the associated program, in terms of both com- 36 - Q 4
parisons and exchanges.
The solution is on page 136.

i i

i i
i i

i i

116 Specification, invariants, and iteration

Problem 37. The Mth zero ◦ •


In this problem, we illustrate a situation where a strengthening of the postcondition is made


by the introduction of variables in the presence of a quantifier (count).

We wish to build the program specified by:

Precondition: (M constant) and (M ∈ N1 ) and (T is a constant array of N


integers) and (T contains at least M zeros).
Postcondition: i is the position of the Mth zero in T .

First of all, let us notice that the precondition entails that N ⩾ M. The quantifier #
denotes the count quantifier. Hence:

#j · ((j ∈ 1 .. N) and (T [j] = 0))


counts the number of zeros present in T . Then, the postcondition is formalized in this way:

Postcondition: (i ∈ 1 .. N) and (#j · ((j ∈ 1 .. i − 1) and (T [j] = 0)) = M − 1) and (T [i] = 0).

Although this postcondition is under a constructive form, we may think that the presence
of a quantification will be embarrassing for the identification of an efficient invariant.
37 - Q 1 Question 1. Propose a strengthened version of the postcondition in which the quanti-
fied expression calls on the variable p.
37 - Q 2 Question 2. Build the loop on the basis of this new postcondition.
37 - Q 3 Question 3. Deduce the program associated with the loop and give its complexity in
terms of comparisons.
The solution is on page 137.

Problem 38. Alternating odd and even ◦ •


This problem illustrates the breakup of the postcondition after a sequence of strengthenings.

Let us consider an array containing as many even as odd numbers. We would like to
place each of the even (respectively odd) numbers in a position with an even (respectively
odd) index. Let us notice that when all the even numbers are correctly placed, it is the same
for the odd numbers (and conversely), hence the following specification:

Precondition: (T is an array of 2N natural numbers) and (S is the constant bag of


values contained in T ) and (N ⩾ 0) and (T contains N even natural numbers
and N odd natural numbers).
Postcondition: (S is the bag of values contained inT ) and [(positions with even
indexes contain even values) or ( positions with odd indexes contain odd
values)].

As in the previous problem, evolutions of T are made via the procedure Exchange, which
gets us free from the first conjunct of the postcondition. The postcondition is not in a con-
junctive form, but it can be easily strengthened while preserving its symmetry:

i i

i i
i i

i i

Problems 117

Postcondition (second version which entails the first one): ((e ∈ 2 .. 2 · N + 2) and (e
is even) and (positions with even indexes in the interval 2 .. e − 2 contain even
values) and (e = 2 · N + 2)) or ((o ∈ 1 .. 2 · N + 1) and (o is odd) and (positions with
odd indexes in the interval 1 .. o − 2 contain odd values) and (o = 2 · N + 1)).

However, it is not yet a conjunctive form and we must proceed to a strengthening of this
version. To this aim, let:
 
(e ∈ 2 .. 2N + 2) and (e is even) and
P= b  (positions with even indexes of the interval 2 .. e − 2 
contain even values)
 
(o ∈ 1 .. 2N + 1) and (o is odd) and
Q= b  (positions with odd indexes of the interval 1 .. o − 2 
contain odd values)

which enables the rewriting of the postcondition hereafter:

Postcondition (rewritten second version): (P and (e = 2N)) or (Q and (o = 2N + 1)).

Question 1. Prove that: 38 - Q 1


A and B and (C or D) ⇒ (A and C) or (B and D).
Deduce a new version of the postcondition under constructive form entailing the second
version.
Question 2. Give the elements of the loop built from this new postcondition. 38 - Q 2

Question 3. Write the program solving the problem under consideration. 38 - Q 3

Question 4. What is its complexity in terms of evaluated conditions and exchanges? 38 - Q 4

Question 5. Justify the fact that it is also possible to build a loop from the following 38 - Q 5
postcondition:
(e ∈ 2 .. 2N) and (e is even) and (positions with even indexes of the interval 2 ..
e−2 contain even values) and (o ∈ 1..2N+1) and (o is odd) and (positions with
odd indexes of the interval 1 .. o − 2 contain odd values) and (e = 2N) and (o =
2N + 1).

Question 6. Specify the resulting progression. 38 - Q 6

The solution is on page 138.

Problem 39. The longest sequence of zeros ◦ •


This problem illustrates a case of a double strengthening, namely of the postcondition on the
one hand (which is traditional), of the invariant (imposed by the progression) on the other
hand. In addition, we highlight the fact that the approach proposed for the construction does
not conflict with modifications aiming at the efficiency of the resulting program.

We would like to build the program specified by:

Precondition: (T is a constant array of N integers) and (N ⩾ 0).


Postcondition: lg is the length of the longest sequence of consecutive zeros in T .

i i

i i
i i

i i

118 Specification, invariants, and iteration

The postcondition is not under conjunctive form; to achieve this, we introduce the variable
i in the following way:

Postcondition (version stemming from the strengthening of the previous one): (lg is the
length of the longest succession of zeros contained in the subarray T [1 .. i − 1]) and (i ∈
1 .. N + 1) and (i = N + 1).

First attempt
The preceding formulation suggests an invariant and a stopping condition:

1. Invariant The first two conjuncts are easy to establish and they are retained for the in-
variant:

(lg is the length of the longest succession of zeros contained in the subarray
T [1 .. i − 1]) and (i ∈ 1 .. N + 1).

In a graphical form, we get:

1 i N
T 0 ········· 0

lg

2. Stopping condition We take the discarded conjunct: (i = N + 1).


3. Progression We must look for a fragment of program specified by:
Precondition: (lg is the length of the longest succession of zeros contained in the sub-
array T [1 .. i − 1]) and (i ∈ 1 .. N + 1) and not(i = N + 1)
P ROGRESSION
Postcondition: (lg is the length of the longest succession of zeros contained in the sub-
array T [1 .. i − 1]) and (i ∈ 1 .. N + 1).
The value T [i] exists since i ̸= N + 1. If T [i] ̸= 0, i must be incremented. Otherwise
(T [i] = 0), we have to express that T [i] may be part of the longest string of zeros of the
subarray T [1 .. i] (before restoring the invariant), which can be achieved by the calcula-
tion (by means of a backward loop) of the length p of the longest string of consecutive
zeros ending in i. However, we can remark that all elements of T [1 .. i − 1] have already
been examined and that it would be damageable to scan them again (even partly). This
length p will be assumed to be known, which leads to a new invariant, derived from
the previous one by a strengthening which adds this hypothesis. The price to pay is the
reconstruction of the loop on the basis of the new invariant.

Second attempt
We make the construction founded on the previous suggestion.
39 - Q 1 Question 1. Specify the new invariant.
39 - Q 2 Question 2. Taking (i = N + 1) as the stopping condition, continue the construction of
the loop (progression, initialization and termination expression).

i i

i i
i i

i i

Problems 119

Question 3. Write the program. Give its complexity in terms of comparisons. 39 - Q 3

Question 4. Propose and justify another stopping condition likely to improve the effi- 39 - Q 4
ciency of the loop.
The solution is on page 142.

Problem 40. The majority element (iterative issue) ◦


◦ •

This problem about the search for a majority element in a bag is also addressed in chapter
“Divide and conquer” (see problem 105, page 445). The solution developed here relies on
an original technique. As a matter of fact, we often exploit the proven technique based on
the strengthening of the postcondition for efficiency purposes. Here, in contrast, we will
weaken the postcondition in order to get an algorithm which is simple but which provides
only a possible solution requiring a “confirmation”. The solution obtained is concise, efficient
and elegant.

If V is an array or a bag, the expression mult(x, V) represents the multiplicity (i.e. the
number of occurrences) of x in V. We consider the bag S of N (N ⩾ 1) strictly positive
integers. S is called majority if there is an integer x such that:
 
N
mult(x, S) ⩾ + 1;
2

x is called the majority element of S (it is unique). The problem posed is that of the search
for the majority element in S. We would like to build a program whose specification is:

Precondition: (S is a bag of N values) and (N ⩾ 1).


Postcondition: x contains the value of the majority element of S if it exists, −1
otherwise.

The identification of a candidate who got the absolute majority in an election or the
design of fault tolerant algorithms are possible applications of this problem.

A naïve algorithm
It is easy to specify a naïve algorithm, at best in Θ(N) and at worst in Θ(N2 ) comparisons
solving this problem (the comparison between two elements of S being the elementary
operation). An element of S is arbitrarily selected and its number of occurrences in S is
calculated. If it is not majority, another element of S is chosen, and so on until a majority
element is found or half of the elements of S are treated without finding any.

A second approach
So as to enhance complexity at worst, we envisage a three step solution: first S is refined
by the array T , then T is sorted, last a sequence of identical values of length greater than
⌊N/2⌋ is searched. The first step is in Θ(N), the second one in O(N · log2 (N)) and the last
one is linear, hence a complexity at worst in O(N · log2 (N)).

i i

i i
i i

i i

120 Specification, invariants, and iteration

An efficient iterative solution


The solution envisaged now is founded on an abstract data structure made of four bags.
After a proposal for an invariant of the iteration, some of its properties are pointed out
in order to build a “safe” program. Then, a refinement of the abstract data structure is
undertaken by suppressing three out of the four initial bags and using only a constant
array and scalar variables in the final algorithm.

Invariant
Let S be the bag of values for which a potential majority element is searched and its multi-
set partition (according to the hypothesis of the work carried out partly) made of:

• R the bag of values “remaining to be treated”,


• P a bag of pairs of values such that, the two values of any pair are different,

• C a bag called “ bag of bachelors” where all elements have the same value.

Example
Let S = J1, 3, 4, 1, 1, 3, 5, 2, 5, 1K and the possible configuration hereafter:

S
P R
× (1, 3) ×5 ×2
× (4, 1)
×5 ×1
× (1, 3)
C

The partition of S (in particular in the above situation) complies with the following
properties:

Property 2:
|S| = 2 · |P| + |C| + |R|.

This property is trivial and we do not prove it.

Property 3:
If the bags R and C are empty, then S is not majority.

Property 4:
If the bag R is empty but C is not (let us call c the value present in C) then:
1. if S has a majority element, it is c,

2. if S has no majority element, nothing can be said about c (not even that c is the element with
the largest multiplicity in S).

i i

i i
i i

i i

Problems 121

Question 1. Prove properties 3 and 4. 40 - Q 1

Question 2. We will build a loop whose invariant corresponds to a situation where S 40 - Q 2


is partitioned in P, C and R and in which the stopping condition occurs when R is empty.
Which conclusion can be then drawn?
Question 3. Specify the precondition as well as the postcondition of the abstract loop 40 - Q 3
built upon the proposed invariant. How to answer the initial problem on the basis of this
loop?
Question 4. Complete the construction of the abstract loop (progression, initialization, 40 - Q 4
termination).
Question 5. How to refine the data structure using only scalar variables and one array? 40 - Q 5
Derive an iterative algorithm solving the problem of the search for a majority element of a
bag S. What is its complexity in terms of comparisons?
The solution is on page 144.

Problem 41. The celebrity problem ◦


◦ •

In a way similar to the problem about the majority element (see problem 40, page 119), we
envisage a solution where the postcondition is weakened. The solution partly calls on the
bounded linear search (see section 3.5, page 107) and it turns out to be elegant and of linear
complexity.

In a group, a star is a person who is known by everyone and who knows nobody. We
consider a group of N (N ⩾ 1) people and we look for a star inside the group, if any.
By convention, a group made of a single person admits this person as a star. The only
authorized operation denoted by Knows(i, j) consists in choosing a person i who is asked
whether he/she knows the person j (i ̸= j) or not. The operation Knows(i, j) returns true
or false depending on the answer (mandatory and assumed to be truthful) of the person
who is questioned.
As there are N(N − 1)/2 pairs of persons, the problem can be solved, for sure, by at
most N(N − 1) operations Knows. However, we are interested in a solution requiring less
operations, if possible a (small) multiple of N.
Question 1. Prove that there is at most one star in any group. 41 - Q 1

Question 2. Prove that, in the absence of any additional information, when the oper- 41 - Q 2
ation Knows(i, j) is performed:
• if the answer is true, then j can be the star, but i cannot,
• if the answer is false, then i can be the star, but j cannot.

Question 3. Specify the precondition and the postcondition of the program solving the 41 - Q 3
problem posed.
Question 4. Specify the constituents of a loop identifying a person likely to be the star 41 - Q 4
of a group, called “potential” star.
Question 5. Specify the other components of the program determining the star of a 41 - Q 5
group or the fact that it involves no star. Write the program solving the initial problem.

i i

i i
i i

i i

122 Specification, invariants, and iteration

41 - Q 6 Question 6. What is its complexity when Knows (i, j) is taken as the elementary opera-
tion?
The solution is on page 145.

Problem 42. Weakening a precondition ◦ •


In this problem, we are interested in weakening the precondition. This approach which is
legitimate, consists in resolving a problem in reference to a more general one for which a
solution is known. The weakening is made by the elimination of an hypothesis and we study
the impact of this choice on the performances through two examples.

We have seen in section 3.3.2 that it is legal that, trying to solve the problem specified by
{P} prog {Q}, we solve the problem specified by {P′ } prog′ {Q} with P ⇒ P′ . In other terms,
the precondition is weakened and we can wonder about the impact of this approach on
performances. Two examples are dealt with to shine a light on this matter.

Sorting increasingly an array ordered decreasingly


We want to build the program specified by:

Precondition: (T is an array of N natural numbers) and (S is the constant bag of


values contained in T ) and (N ⩾ 1) and (T is decreasingly ordered).
Postcondition: (T is sorted increasingly) and (S is the bag of values contained in
T ).

Two strategies can be envisaged: (i) to develop a specific algorithm accounting for the fact
that T is decreasingly ordered or (ii) to weaken the precondition by suppressing the conjunct
related to the fact that the array is already ordered.
42 - Q 1 Question 1. Propose the principle of a solution of linear complexity in terms of ex-
changes in the context of the first option.
42 - Q 2 Question 2. Which complexity is obtained with the algorithm proposed in problem 33,
page 112? Can it be expected to do better with a “usual” sorting algorithm? Conclude.

Constrained variation array


We consider the program whose specification is:
Precondition: (T is a constant array of N natural numbers) and (there is at least
one zero in T ) and (the difference between two successive elements of T is
at most 1).
Postcondition: The variable i identifies the zero of T with the lowest index.
This specification differs from that of the example dealt with in page 99, since here, we
are provided with a property about the variation over the numbers contained in T . Once
again, two strategies are feasible: specific program or use of the algorithm proposed in
page 101. This second option corresponds to the weakening of the precondition of the
problem where the third conjunct is ignored.

i i

i i
i i

i i

Problems 123

Question 3. Prove that when T is such that the difference between two consecutive 42 - Q 3
elements of T is at most 1, then:

(T [i] > 0) ⇒ ∀j · (j ∈ i .. i + T [i] − 1 ⇒ T [j] > 0).

Question 4. Develop the specific solution based on a loop whose constituents will be 42 - Q 4
first explicited.
Question 5. What can be said about the impact of the choice in terms of complexity? 42 - Q 5

Question 6. We now consider the program specified by: 42 - Q 6

Precondition: (T is a constant array of N natural numbers) and (there is at least


one zero in T ) and (the difference between two successive elements of T is
at least 1).
Postcondition: The variable i identifies the zero of T with the lowest index.
Elaborate on the following weakening of the initial precondition:
Precondition: (T is a constant array of N natural numbers) and (there is at least one zero
in T ).

Question 7. Compare the three previous weakening situations. 42 - Q 7

The solution is on page 148.

Problem 43. Halving a polygon ◦ •


The problem dealt with here is a somewhat sophisticated variant of the sequential search. Usu-
ally, in this kind of problem, using the technique called “stop as early as possible” does not
impact asymptotic complexity. This is not what happens here, where this strategy is the back-
bone for the improvement of the efficiency obtained with respect to a naïve method. Moreover,
this problem has a formulation in a two-dimensional space generally solved by two nested
loops. Here, as in problem 32 page 111, the use of a single loop makes the design simpler.

We consider an arbitrary polygon of finite order N (N > 2) whose vertices are labelled
clockwise from 1 to N. We look for any arbitrary chord that separates (halves) the perime-
ter p of the polygon “as accurately as possible”, i.e. such that the absolute value of the
difference between the sum of the lengths of the sides bounded by the chord is minimum.
Complexity is evaluated in terms of the number of visited vertices.

Definitions – Notations – Representation


Further, |a| denotes the absolute value of a. The side which originates from vertex i is
denoted by (i). The chord connecting vertices i and j is denoted by (i, j). The arc going
y
from vertex i to vertex j is denoted by (i, j). The length of the arc a is denoted by kak.
A polygon of order N is represented by the array d (d ∈ 1 .. N → R+ ) such that d[i] is
the length of side (i). Figure 3.4 shows a polygon of order 9.
More formally, if the operator · denotes concatenation of adjacent arcs, a (nonempty)
arc is inductively defined as a sequence of sides the following way.

i i

i i
i i

i i

124 Specification, invariants, and iteration

4 1.6 5 d[1] = 2.2


• • 1.1 0.9
6 d[2] =

1.6
d[3] = 1.6
3 •

1.3
d[4] = 1.6
• 7 = 1.1

.9
d[5]
• d[6] = 1.3
2
1.8

1.8
2.2 d[7] =
• 0.7
• • .7 8 d[8] =
1 .6 9 d[9] = 0.6

Fig. 3.4 – Example of a polygon of order 9 and its representation by the array d.

Definition 1 (Arc):
Base
 case :
(i, i↷+ 1) = (i) i ∈ 1 .. N − 1
(N,

1) = (N).
Inductive
 ↷ case:
(i, j) = (i, i↷+ 1) · (i +↷1, j) j ̸= i + 1 and i ̸= N
(N, j)
↷ ↷ ↷
= (N, 1) · (1, j)) j ̸= 1.

Similarly, the length of an arc is defined as follows.

Definition 2 (Length of an arc):


Base
 case:
∥(i, i↷+ 1)∥ = d[i] i ∈ 1 .. N − 1
∥(N,

1)∥ = d[N].
Inductive
 ↷ case:
∥(i, j)∥ = d[i] + ∥(i +↷1, j)∥ j ̸= i + 1 and i ̸= N
∥(N,

j)∥ = d[N] + ∥(1, j))∥

j ̸= 1.

Definition 3 (Locally optimal chord):


The chord (j, k) is locally optimal with respect to its origin j if:
↷ ↷
 ↷ ↷

∥(j, k)∥ − ∥(k, j)∥ = min ∥(j, i)∥ − ∥(i, j)∥ .
i∈1..N−{j}

Definition 4 (Globally optimal chord):


The chord (j, k) is globally optimal if:
↷ ↷
 ↷ ↷

∥(j, k)∥ − ∥(k, j)∥ = min ∥(u, v)∥ − ∥(v, u)∥ . (3.1)
u ∈ 1 .. N and
v ∈ 1 .. N and
u ̸= v

i i

i i
i i

i i

Problems 125

The problem
The objective of the problem is to find out a globally optimal chord (the problem has at
least one solution). A method consists in the evaluation of formula 3.1 and keeping one of
the pairs of vertices which complies with it. The corresponding algorithm is in Θ(N2 ). It is
also possible to exploit the following identity so as to avoid useless calculations (p is the
perimeter of the polygon):
↷ ↷ ↷ p
∥(i, j)∥ − ∥(j, i)∥ = 2 · ∥(i, j)∥ − . (3.2)
2.0
The pairs of vertices (j, k) complying with formula 3.1 are also those which comply with:
↷ ↷
∥(j, k)∥ − ∥(k, j)∥ ↷ p
= min ∥(u, v)∥ − .
2.0 u ∈ 1 .. N and 2.0
v ∈ 1 .. N and
u ̸= v

But, since |a − b| = |b − a|, to visit all of the arcs, the variable v does not need to scan the
whole set 1 .. N − {u}. It is sufficient that it takes the values of the interval u + 1 .. N ∪ {1},
hence:
↷ ↷
∥(j, k)∥ − ∥(k, j)∥ ↷ p
= min ∥(u, v)∥ − .
2.0 u ∈ 1 .. N and 2.0
v ∈ u + 1 .. N ∪ {1}
 ↷

If (j, k) is a locally optimal chord issued from j, the value ∥(j, k)∥ − p/2.0 is denoted
δj . The lengths of the arcs intervening in the calculation can be gathered in the following
triangular matrix (called triangle of lengths):
↷ ↷ ↷
∥(1, 2)∥ ∥(1, 3)∥ ......... ∥(1, 1)∥
↷ ↷
∥(2, 3)∥ ......... ∥(2, 1)∥
..
.
↷ ↷
∥(i, i + 1)∥ . . . . ∥(i, 1)∥
.. ..
. .
.. ..
. .
.. ..
. .

∥(N, 1)∥

It can be noticed that the upper right corner of the triangle indicates the value of the

perimeter p = ∥(1, 1)∥ of the polygon. In the case of the polygon of figure 3.4, page 124,
p = 11.8, and this triangle is valued as follows:

i i

i i
i i

i i

126 Specification, invariants, and iteration

2 3 4 5 6 7 8 9 1
1 2.2 3.1 4.7 6.3 7.4 8.7 10.5 11.2 11.8
2 0.9 2.5 4.1 5.2 6.5 8.3 9.0 9.6
3 1.6 3.2 4.3 5.6 7.4 8.1 8.7
4 1.6 2.7 4.0 5.8 6.5 7.1
5 1.1 2.4 4.2 4.9 5.5
6 1.3 3.1 3.8 4.4
7 1.8 2.5 3.1
8 0.7 1.3
9 0.6

However, this type of triangle contains (N(N + 1))/2 elements and their exhaustive eval-
uation leads once again to a solution in Θ(N2 ). This result can be improved on the basis of
the following four observations:

1. For a given vertex j, there is either one, or two locally optimal chords.

2. If the chord (j, k) is the first2 locally optimal chord issued from j, then none of the
chords (j + 1, j + 2), (j + 1, j + 3),. . . ,(j + 1, k − 1) is globally as good as (j, k).

3. Let (j, k) be the first locally optimal chord issued from j. The chord (j + 1, k), if it exists,
may be better than (j, k).

4. When, for the vertex j, a locally optimal chord (j, k) is found out, it becomes useless to
test the optimality of (j, k + 1),. . . , (j, N + 1) (according to the usual principle “stop as
early as possible”).
As to observation 3, it is convenient to notice that other chords issued from the vertex
j + 1 can outperform the chord (j + 1, k).
43 - Q 1 Question 1. Demonstrate identity 3.2, page 125.
43 - Q 2 Question 2. In which situation are there two locally optimal chords issued from the
same vertex j ? Give an example.
43 - Q 3 Question 3. Prove the proposition related to the third above observation.
43 - Q 4 Question 4. In the example of figure 3.4, page 124, which are the arcs whose length
intervenes in the calculation? Which globally optimal chord is found out?
43 - Q 5 Question 5. Let us consider the following example:
5
1 • • 2
3 3

3
Specify (by means of a triangle of lengths) the arcs whose length intervenes in the calcula-
tion. What can be observed?
43 - Q 6 Question 6. We decide to build an algorithmic solution on the basis of a single loop.
Propose an invariant for this loop.

2 The first one encountered according to a clockwise scan.

i i

i i
i i

i i

Solutions 127

Question 7. Complement the construction of the loop (stopping condition, progres- 43 - Q 7


sion, initialization, termination) and derive the code associated with this solution. What is
its complexity (in terms of visited vertices)?
The solution is on page 149.

3.8 Solutions
Answers to problem 29. White and red beans The problem is on page 110.

Answer 1. It is easy to see that, whatever the result of a draw, the number of beans in 29 - A 1
the box decreases by 1. After a while, the can contains a single bean and the process stops.
Answer 2. Let us try to find an invariant in the procedure described in the statement of 29 - A 2
the problem. Let nbW (respectively nbR) be the number of white (respectively red) beans
present in the can before any draw. If two red beans are drawn, nbW does not change and
nbR diminishes by 1. If two white beans are drawn, nbW decreases by 2 and nbR increases
by 1. Last, if one white bean and one red bean are drawn, NBW remains unchanged and
nbR diminishes by 1. This shows a property of nbW about its parity which remains un-
changed over time whatever the result of the successive draws. This is an invariant of the
mechanism described in the statement. It makes it possible to deduce that, if the initial
number of white beans is odd (respectively even), the last bean is white (respectively red).

Answers to problem 30. From a coder’s dustbin The problem is on page 111.

Answer 1. A first mistake lies in the fact that the variable sup is used in the invariant 30 - A 1
without its prior definition. Another error impacts the stopping condition which prevents
the accounting for T [N] in the search of the maximum.
Answer 2. An acceptable version is based on the following invariant: 30 - A 2
(i ∈ 1 .. N + 1) and (sup ∈ N) and (∀j · (j ∈ 1 .. i − 1 ⇒ T [j] ⩽ sup))
as well as on the stopping condition: (i = N + 1).

It can be noticed that the initialization establishes the invariant since it holds for i = 2 and
sup = T [1] (T [j] ⩽ sup is true for j = 1 – indeed, case of equality).

Answers to problem 31. Summing up the elements of an array The problem


is on page 111.

P
Answer 1. The initial expression of the postcondition is: s = N j=1 T [j]. It is not under 31 - A 1
conjunctive form and it will be strengthened by the replacement of (N + 1) by the variable
i, and the adjunction of the conjunct (i = N + 1). Thus, the postcondition becomes:
Postcondition : (s is the sum of the first (i − 1) elements of T ) and (i ∈ 1 .. N + 1) and (i =
N + 1).
The heuristics of the breakup leads to separate the postcondition and to suggest:

i i

i i
i i

i i

128 Specification, invariants, and iteration

1. Invariant The first two conjuncts are easy to establish, so they are kept to form the in-
variant:
(s is the sum of the first (i − 1) elements of T ) and (i ∈ 1 .. N + 1)
graphically:

1 i N
T

 
X
i−1
s = T [j] and (i ∈ 1 .. N + 1)
j=1

2. Stopping condition The discarded conjunct is taken: i = N + 1.


3. Progression It is specified by:
 P 
Precondition: s = i−1 j=1 T [j] and (i ∈ 1 .. N + 1) and not (i = N + 1)
P ROGRESSION
 P 
Postcondition: s = i−1
j=1 T [j] and (i ∈ 1 .. N + 1)

In order to both “make the calculation progress” and restore the invariant, the pro-
gression chosen consists in the integration of T [i] into the sum and the increment of
i by 1. These two actions are possible since the formula ((i ∈ 1 .. N + 1) and not(i =
N+1)) ensures that both T [i] exists and i can be increased. We are thus in the following
situation:
0 i N−1
T

 
X
i−1
s = T [j] and (i ∈ 1 .. N + 1)
j=1

which is nothing but the invariant. So, we have built the progression: s ← s + T [i]; i ←
i + 1.
4. Initialization The initialization is specified by:
Precondition: (T is a constant array of N natural numbers) and (N ⩾ 0)
I NITIALIZATION
 P 
Postcondition: s = i−1
j=1 T [j] and (i ∈ 1 .. N + 1).
As usual when the initialization is designed, the postcondition of the specification is
the invariant of the loop under construction. Moving from the precondition to the
invariant can be done in attaining the following situation where i is identified to 1:

i i

i i
i i

i i

Solutions 129

1/i N
T
 
0
X
s = T [j] and (1 ∈ 1 .. N + 1)
j=1

situation which can be established by the assignments 1 to i and 0 to s.


5. Termination The expression (N + 1 − i) is appropriate: it remains nonnegative and de-
creases by 1 at each iteration step.
Finally, the following program is built:

1. constants
2. N ∈ N1 and N = . . . and T ∈ 1 .. N → N and T = [. . .]
3. variables
4. i ∈ 1 .. N + 1
5. begin
6. /% PRE: (T is a constant array of N natural numbers) and (N ⩾ 0) %/
7. i ← 1; s ← 0;
8. while not(i = N + 1) do
9. s ← s + T [i]; i ← i + 1
10. end while; 
X
N
11. /% POST: s = T [j] %/
j=1

12. write(the sum of the elements of the array , T , is , s)


13. end

Answer 2. In terms of additions as well as comparisons related to the control of the 31 - A 2


loop, this algorithm is in Θ(N) in the best and in the worst case.

Answers to problem 32. Searching in a bidimensional array The problem is


on page 111.

Answer 1. Let us assume that the work is carried out partly, which is schematized by: 32 - A 1

1 j C
1

i i

i i
i i

i i

130 Specification, invariants, and iteration

1. Invariant It matches the situation described above, namely:

(i ∈ 1 .. R) and (j ∈ 1 .. C) and (the value V is not in the rectangle T [1 .. i − 1, 1 ..


C]) and (the value V is not in row T [i, 1 .. j − 1]).
2. Stopping condition The loop terminates as soon as T [i, j] = V.
3. Progression It is specified by:
Precondition: (the value V is not in the rectangle T [1 .. i − 1, 1 .. C]) and (the value V
is not in the row T [i, 1 .. j − 1]) and not(T [i, j] = V)
P ROGRESSION
Postcondition: (the value V is not in the rectangle T [1 .. i − 1, 1 .. C]) and (the value V
is not in the row T [i, 1 .. j − 1]).

The progression of the indexes i and j is handled here in order to examine the next
element (which exists according to the precondition and the fact that the stopping
condition is not met): j is incremented by 1, and if it exceeds C, we move to the begin-
ning of next line.
4. Initialization It allows to move from the precondition to the invariant, which is done in
giving the value 1 to both variables i and j.
5. Termination We can take the area of the white zone of the schema as the termination
expression since it decreases by 1 at each step of the loop: (R − i) · C + (C + 1 − j).

32 - A 2 Answer 2. The corresponding program is:


1. constants
2. R ∈ N1 and R = . . . and C ∈ N1 and C = . . . and V ∈ N and V = . . . and
3. T ∈ 1 .. R × 1 .. C → N and T = [. . .]
4. variables
5. i ∈ 1 .. R and j ∈ 1 .. C + 1
6. begin
7. /% PRE: (T is a constant array of natural numbers with R rows and C
columns) and (R > 0) and (C > 0) and (V is a natural number present in
T ) %/
8. i ← 1; j ← 1;
9. while not(T [i, j] = V) do
10. j ← j + 1;
11. if j > C then
12. i ← i + 1; j ← 1
13. end if;
14. end while;
15. /% POST: (i, j) stands for an occurrence of, V , in, T , i.e. T [i, j] = V %/
16. write(an occurrence of , V, is in the cell (, i, , , j, ) of T )
17. end
The loop is completed between one and (R·C) times, and at each iteration two comparisons
take place (one for the control of the loop and one for testing j).

i i

i i
i i

i i

Solutions 131

Answers to problem 33. Sorting by straight selection The problem is on


page 112.

Answer 1. The postcondition stemming from the choice made is: 33 - A 1


Postcondition: (i ∈ 1 .. N + 1) and (T [1 .. i − 1] is sorted) and (∀j · (j ∈ 1 .. i − 1 ⇒ ∀k · (k ∈
i .. N ⇒ T [j] ⩽ T [k]))) and (i = N + 1).
We now identify the five components of the loop to construct.
1. Invariant The first three conjuncts are easy to establish and they are retained for the
invariant:
(i ∈ 1 .. N + 1) and (T [1 .. i − 1] is sorted) and ∀j · (j ∈ 1 .. i − 1 ⇒ ∀k · (k ∈
i .. N ⇒ T [j] ⩽ T [k]))
or graphically (omitting the variation domain of i):

∀j · (j ∈ 1 .. i − 1 ⇒ ∀k · (k ∈ i .. N ⇒ T [j] ⩽ T [k]))

1 i N
T

sorted

2. Stopping condition We take the last conjunct: (i = N + 1).


3. Progression It is specified by:
Precondition: (i ∈ 1 .. N + 1) and (T [1 .. i − 1] is sorted) and ∀j · (j ∈ 1 .. i − 1 ⇒ ∀k · (k ∈
i .. N ⇒ T [j] ⩽ T [k])) and not(i = N + 1)
P ROGRESSION
Postcondition: (i ∈ 1 .. N + 1) and (T [1 .. i − 1] is sorted) and ∀j · (j ∈ 1 .. i − 1 ⇒ ∀k · (k ∈
i .. N ⇒ T [j] ⩽ T [k])).
A possible solution is to identify the position m of the minimum (one of the minima)
in the subarray T [i .. N] before swapping elements in position i and m. The invariant
is then restored by the incrementation of i.
4. Initialization The initialization is specified by:
Precondition: (T is an array of N natural numbers) and (N ⩾ 1)
I NITIALIZATION
Postcondition: (i ∈ 1 .. N + 1) and (T [1 .. i − 1] is sorted) and ∀j · (j ∈ 1 .. i − 1 ⇒ ∀k · (k ∈
i .. N ⇒ T [j] ⩽ T [k])).
Assigning 1 to i answers this specification: T [1 : 0] is sorted; all the elements of this
subarray are less than (or equal to) those of T [1 .. N].
5. Termination If the search for the minimum in T [i .. N] comes to an end, it is the same
for the loop under construction. (N + 1 − i) is a suitable termination expression.

Answer 2. The strengthening envisaged consists in replacing (N + 1) by k. Henceforth, 33 - A 2


T [m] = minj∈i..N (T [j]) becomes T [m] = minj∈i..k−1 (T [j]) and it is necessary to specify the
variation domain of k on the one hand and to carry forward the substitution in the term
m ∈ i .. N. We get:
Postcondition: (k ∈ i+1..N+1) and (m ∈ i..k−1) and (T [m] = minj∈i..k−1 (T [j])) and (k =
N + 1).

i i

i i
i i

i i

132 Specification, invariants, and iteration

33 - A 3 Answer 3. The components of the loop for the identification of a minimum in T [i .. N]


are now proposed.
1. Invariant The first three conjuncts are easy to establish and they constitute the invariant:
(k ∈ i + 1 .. N + 1) and (m ∈ i .. k − 1) and (T [m] = minj∈i..k−1 (T [j])).
2. Stopping condition We take the remaining conjunct: (k = N + 1).
3. Progression It is specified as follows:
Precondition: (k ∈ i + 1 .. N + 1) and (m ∈ i .. k − 1) and (T [m] =
minj∈i..k−1 (T [j])) and not(k = N + 1)
P ROGRESSION
Postcondition: (k ∈ i + 1 .. N + 1) and (m ∈ i .. k − 1) and (T [m] = minj∈i..k−1 (T [j])).
Progressing towards the postcondition is done via the update of m if T [k] reveals to
be the smallest element over T [i .. k]; the restoration of the invariant is achieved by
incrementing k.
4. Initialization The initialization is specified by:
Precondition: (i constant) and (i ∈ 1..N) and (T [i..N] is an array of natural numbers)
I NITIALIZATION
Postcondition: (k ∈ i + 1 .. N + 1) and (m ∈ i .. k − 1) and (T [m] = minj∈i..k−1 (T [j])).
To be reached, the state (k = i + 1) compels the simultaneous attainment of the state
(m = i) which can be obtained (since i is considered constant) by the program:
1. k ← i + 1 ; m ← i.
5. Termination The variable k is incremented by 1 at each step of iteration. The expression
(N + 1 − k) is decreasing while being nonnegative, which ensures the termination.

33 - A 4 Answer 4. Eventually, we obtain the following program:


1. constants
2. N ∈ N1 and N = . . .
3. variables
4. T ∈ 1..N → N and T = [. . .] and i ∈ 1..N+1 and k ∈ 2..N+1 and m ∈ 1..N
5. begin
6. /% PRE: (T is an array of N natural numbers) and (N ⩾ 1) %/
7. i ← 1 ;
8. while not(i = N + 1) do
9. /% nested loop for the determination of m %/
10. k←i+1;m←i;
11. while not(k = N + 1) do
12. if T [k] < T [m] then
13. m←k
14. end if;
15. k←k+1
16. end while;
17. Exchange(i, m) ; i ← i + 1
18. end while;
19. /% POST: (T is increasingly sorted) %/
20. write(T )
21. end

i i

i i
i i

i i

Solutions 133

Answer 5. The outer loop is achieved for i varying from 1 to N and the inner loop, 33 - A 5
which contains the exchange operation, for k varying from (i + 1) to N. It can be deduced
that the number of exchanges is in Θ(N2 ).

Answers to problem 34. Was it a car or a cat I saw The problem is on page 113.

Answer 1. Let us make a proof by contradiction. Let us consider the kth character of T 34 - A 1
starting from its beginning and its end, respectively T [k] and T [N − k + 1]. Let us assume
that T is a palindrome and that these two elements are different, the word (or sentence,
spaces being ignored) represented by T does not read the same in both directions, hence
there is a contradiction.
Answer 2. Let us remind that the pattern proposed in page 109 consists in deciding 34 - A 2
whether there is (or not) an element j in a structure of size N, that fulfills a given predicate
LP that does not depend on the elements preceding j. The result returned is either j itself,
or the conventional value (N + 1) indicating that the structure has been exhausted without
finding an element for which property LP is met. For the problem of decision about a
(possible) palindrome, the approach can be used with:

b (T [j] ̸= T [N + 1 − j])
LP(j) =
detecting a bad match leading to deciding that the string T is not a palindrome. However,
it should be noted that k never takes the value N+1 since elements are pairwise examined.
Indeed, if T represents a palindrome, the algorithm comes to an end with a value of k equal
to (or exceeding by 1) that of (N + 1 − k). For the same reason, the termination expression
must be adapted (see next question), although the generic expression suits well.
Answer 3. Taking these adaptions into account, we get the program hereafter: 34 - A 3
1. constants
2. T ∈ string and T = . . . and N = |T |
3. variables
4. j ∈ 1 .. N
5. begin
6. /% PRE: (T is a constant string of N characters) and (N ⩾ 0) %/
7. j ← 1 ;
8. while not((j ⩾ N + 1 − j) or else (T [j] ̸= T [N + 1 − j))) do
9. j←j+1
10. end while;
11. /% POST: ((j ⩾ N + 1 − j) and (T represents a palindrome)) or ((j < N +
1 − j) and (T does not stand for a palindrome)) %/
12. if j ⩾ N + 1 − j then
13. write(the string , T , represents a palindrome)
14. else
15. write(the string , T , does not represent a palindrome)
16. end if
17. end

Remark
This solution allows for handling strings whatever the parity of their size (odd or even).

i i

i i
i i

i i

134 Specification, invariants, and iteration

34 - A 4 Answer 4. The number of conditions evaluated (for the control of the loop) is varying
from 1 (immediate stop in case of bad match or N = 0) to ⌈(N + 1)/2⌉ (T represents a
palindrome). Thus, complexity is in O(N).

Answers to problem 35. The Dutch national flag (variant) ◦


◦•• The problem is
on page 114.

35 - A 1 Answer 1. Replacing w by r in the second version of the postcondition, it yields:


Postcondition (new version):
(b ∈ 1 .. N) and (w ∈ b + 1 .. N + 1) and (r ∈ w .. N + 1) and
(∀j · (j ∈ 1 .. b − 1 ⇒ T [j] < V)) and (∀j · (j ∈ b .. w − 1 ⇒ T [j] = V)) and
(∀j · (j ∈ r .. N ⇒ T [j] > V)) and (r = w).
The invariant can be made of the first six components (easy to establish):
1. Invariant (b ∈ 1 .. N) and (w ∈ b + 1 .. N + 1) and (r ∈ w .. N + 1) and
(∀j · (j ∈ 1 .. b − 1 ⇒ T [j] < V)) and (∀j · (j ∈ b .. w − 1 ⇒ T [j] = V)) and
(∀j · (j ∈ r .. N ⇒ T [j] > V)).
It can be schematized by:
1 b w r N
T <V =V >V w>b

values to be ordered

35 - A 2 Answer 2. We continue the construction of the loop with the four remaining elements.
2. Stopping condition The conjunct previously discarded is taken: (r = w).
3. Progression It is specified by:
Precondition: (b ∈ 1 .. N) and (w ∈ b + 1 .. N + 1) and (r ∈ w .. N + 1) and
(∀j · (j ∈ 1 .. b − 1 ⇒ T [j] < V)) and (∀j · (j ∈ b .. w − 1 ⇒ T [j] = V)) and
(∀j · (j ∈ r .. N ⇒ T [j] > V)) and not(r = w)
P ROGRESSION
Postcondition: (b ∈ 1 .. N) and (w ∈ b + 1 .. N + 1) and (r ∈ w .. N + 1) and
(∀j · (j ∈ 1 .. b − 1 ⇒ T [j] < V)) and (∀j · (j ∈ b .. w − 1 ⇒ T [j] = V)) and
(∀j · (j ∈ r .. N ⇒ T [j] > V)).

The area containing the values not yet sorted has two variable endpoints (w and r−1),
which are exploited to fulfill the constraint of the statement related to exchanges. Let
us review the various cases likely to happen:
a) when T [r − 1] > V, no exchange is needed and the invariant is restored by
decrementing r by 1,
b) when T [w] = V, here again, no exchange is required to restore the invari-
ant, w is incremented by 1,
c) when T [w] < V, T [w] should be placed in the first area and the values at
positions w and b are exchanged before the restoration of the invariant
with the incrementation of these two variables by 1,

i i

i i
i i

i i

Solutions 135

d) when T [w] > V, T [w] should be placed in the right area and the values at
positions w and (r − 1) are exchanged before the restoration of the invari-
ant in decrementing r by 1.
Whatever the situation, it can be observed that at most one exchange takes place.
4. Initialization The initialization is specified by:
Precondition: (T is an array of N natural numbers) and (N ⩾ 1) and (V = T [1])
I NITIALIZATION
Postcondition: (b ∈ 1 .. N) and (w ∈ b + 1 .. N + 1) and (r ∈ w .. N + 1)
(∀j · (j ∈ 1 .. b − 1 ⇒ T [j] < V)) and (∀j · (j ∈ b .. w − 1 ⇒ T [j] = V)) and
(∀j · (j ∈ r .. N ⇒ T [j] > V)).

The following situation must be reached:

b/1 w/2 N r/N + 1


T V

values to be ordered

which is done by the assignments:


b ← 1; w ← 2; r ← N + 1
5. Termination The area of the values remaining to sort diminishes by 1 at each step of the
loop. (r − w) is thus a legal termination expression.

Answer 3. Ultimately, the following program is built: 35 - A 3


1. constants
2. N ∈ N1 and N = . . .
3. variables
4. T ∈ 1 .. N → N and T = [. . .] and V ∈ N and b ∈ 1 .. N and w ∈ 2 .. N +
1 and r ∈ 2 .. N + 1
5. begin
6. /% PRE: (T is an array of N natural numbers) and (N ⩾ 1) %/
7. V ← T [1]; b ← 1 ; w ← 2 ; r ← N + 1 ;
8. while not(w = r) do
9. if T [r − 1] > V then
10. r←r−1
11. else
12. if T [w] = V then
13. w←w+1
14. elsif T [w] < V then
15. Exchange(w, b) ; b ← b + 1 ; w ← w + 1
16. else
17. Exchange(w, r − 1) ; r ← r − 1
18. end if
19. end if
20. end while;

i i

i i
i i

i i

136 Specification, invariants, and iteration

21. /% POST: (S is the bag of the values contained in T ) and (T is made of


three parts, on the left values less than V, on the right values greater than
V and in the middle all occurrences of V) %/
22. write(array, T , where the occurrences of the value, V
23. are in the middle, those less than , V, on the left
24. and the others on the right)
25. end

35 - A 4 Answer 4. The length of the area containing the values remaining to sort diminishes
by 1 at each step of the progression, while at the same time at most one exchange takes
place. More precisely, the number of exchanges varies from 0 (if the array T contains a
single value or if ∀i · (i ∈ 2 .. N ⇒ T [i] > T [1])) to (N − 1) (if ∀i · (i ∈ 2 .. N ⇒ T [i] < T [1])).

Answers to problem 36. 7’s and 23’s The problem is on page 115.

36 - A 1 Answer 1. Let us assume that the work has been carried out partly, i.e. that the “left”
(respectively “right”) part of T contains no 23 (respectively no 7), which is graphically
represented below:
1 i j N

no 23 to be examined no 7
knowing that this array has been obtained by means of exchanges between pairs (7, 23) or
(23, 7). Hence, the following invariant can be retained:
(i ∈ 1 .. j + 1) and (j ∈ i − 1 .. N) and (T [1 .. i − 1] contains no 23) and (T [j + 1 .. N]
contains no 7).

36 - A 2 Answer 2. When i and j are equal, the grey area contains a unique element which,
whatever it is, is located at the right place (no exchange required). We could think of tak-
ing this predicate as the stopping condition, but if T is empty, we have i = 1 and j = 0
(according to the invariant) and the condition (i = j) is not met. Therefore, we adopt the
stopping condition (i ⩾ j) which covers the case of a empty area either empty or contain-
ing a single element.
36 - A 3 Answer 3. Now, we continue the design of the loop.
3. Progression It is specified by:
Precondition: (i ∈ 1 .. j + 1) and (j ∈ i − 1 .. N) and (T [1 .. i − 1] does not contain any
23) and (T [j + 1 .. N] does not contain any 7) and not(i ⩾ j)
P ROGRESSION
Postcondition: (i ∈ 1 .. j + 1) and (j ∈ i − 1 .. N) and (T [1 .. i − 1] does not contain any
23) and (T [j + 1 .. N] does not contain any 7)

The two indexes i and j will be managed simultaneously in the following synthesized
way:

i i

i i
i i

i i

Solutions 137

T [i] = 23 T [i] ̸= 23
Exchange(i, j);
T [j] = 7 i ← i + 1; i←i+1
j←j−1
j ← j − 1;
T [j] ̸= 7 j←j−1
i←i+1
4. Initialization To reach the invariant from the precondition, it is sufficient to make the
assignments: i ← 1 and j ← N.
5. Termination The expression (j − i + 1) decreases by 1 or 2 at each step and it remains
nonnegative.

Answer 4. The number of exchanges is at best zero (23’s are all located after 7’s) and 36 - A 4
at worst ⌊N/2⌋ (T contains a sequence of ⌊N/2⌋ (respectively ⌈N/2⌉) 23’s followed by a
sequence of ⌈N/2⌉ (respectively ⌊N/2⌋) 7’s). Three comparisons are performed at each
step of the loop (one for the control of the loop and two for the comparisons between T [i]
and T [j]). The number of steps is at best equal to ⌊N/2⌋ (when both indexes i and j evolve
always together) and at worst (N − 1) (when only one of the two indexes i and j changes).
Thus, complexity is in Θ(N) in terms of both comparisons and exchanges.

Answers to problem 37. The Mth zero The problem is on page 116.

Answer 1. A new expression of the postcondition is: 37 - A 1

Postcondition: (p ∈ 0 .. M − 1) and (i ∈ 1 .. N) and (p = (#j · ((j ∈ 1 .. i − 1) and (T [j] =


0))) and (p = M − 1) and (T [i] = 0).

Answer 2. We successively examine the five components of the loop. 37 - A 2


1. Invariant The invariant contains the first three conjuncts (including the quantified ex-
pression):
(p ∈ 0 .. M − 1) and (i ∈ 1 .. N) and (p = (#j · ((j ∈ 1 .. i − 1) and (T [j] = 0)))).
2. Stopping condition It is made of the two discarded conjuncts:
(p = M − 1) and (T [i] = 0).
3. Progression It is specified by:
Precondition: (p ∈ 0 .. M − 1) and (i ∈ 1 .. N) and (p = #j · (j ∈ 1 .. i − 1) and (T [j] =
0)) and not((p = M − 1) and (T [i] = 0))
P ROGRESSION
Postcondition: (p ∈ 0..M−1) and (i ∈ 1..N) and (p = #j·((j ∈ 1..i−1) and (T [j] = 0)).
The following fragment of code answers this specification:
1. if T [i] = 0 then
2. p ← p + 1
3. end if;
4. i ← i + 1

i i

i i
i i

i i

138 Specification, invariants, and iteration

4. Initialization The initialization must comply with the following specification:


Precondition: (M constant) and (M ∈ N1 ) and (T is a constant array of N
integers) and (T contains at least M zeros)
I NITIALIZATION
Postcondition: (p ∈ 0..M−1) and (i ∈ 1..N) and (p = #j·((j ∈ 1..i−1) and (T [j] = 0)).
When i is equal to 1, p must take the value 0. This situation is attained from the pre-
condition by the two assignments: i ← 1 and p ← 0.
5. Termination The expression (N − i) diminishes by 1 at each step of the progression,
while remaining nonnegative, which guarantees the termination.

37 - A 3 Answer 3. The program associated with the loop is:


1. constants
2. N ∈ N1 and N = . . . and M ∈ 1 .. N and M = . . . and T ∈ 1 ..
N → N and T = [. . .]
3. variables
4. p ∈ 0 .. M − 1 and i ∈ 1 .. N
5. begin
6. /% PRE: (M constant) and (M ∈ N1 ) and (T is a constant array of N
integers) and (T contains at least M zeros) %/
7. i ← 1 ; p ← 0 ;
8. while not((p = M − 1) and (T [i] = 0)) do
9. if T [i] = 0 then
10. p←p+1
11. end if;
12. i←i+1
13. end while;
14. /% POST: i is the position of the Mth zero in T %/
th
15. write(the M zero in , T , is located in position , i)
16. end
The loop is executed at most (respectively at least) N (respectively M) times. At each step,
two comparisons are made, hence the complexity is in Ω(M) and O(N) comparisons.

Answers to problem 38. Alternating odd and even The problem is on page 116.

38 - A 1 Answer 1. We have:

A and B and (C or D)
⇔ distributivity
(A and B and C) or (A and B and D)
⇒ (A and B) ⇒ A and (A and B) ⇒ B
(A and C) or (B and D).

Hence, we can deduce:


P and Q and ((e = 2N + 2) or (o = 2N + 1))

(P and (e = 2N + 2)) or (Q and (o = 2N + 1)).
Developing P and Q, the following postcondition is obtained:

i i

i i
i i

i i

Solutions 139

Postcondition (third version entailing the second one): (e ∈ 1 .. 2N + 2) and (e is


even) and (positions with even indexes of the interval 1 .. e − 2 contain even
values) and (o ∈ 1 .. 2N + 1) and (o is odd) and (positions with odd indexes of the
interval 1 .. o − 2 contain odd values) and [(e = 2N + 2) or (o = 2N + 1)].

Answer 2. We successively review the five components of the loop. 38 - A 2


1. Invariant The first six conjuncts of the postcondition are easy to establish and they are
retained for the invariant:
(e ∈ 1 .. 2N + 2) and (e is even) and (positions with even indexes of the interval
2 .. e − 2 contain even values) and (o ∈ 1 .. 2N + 1) and (o is odd) and (positions with
odd indexes of the interval 1 .. o − 2 contain odd values).
2. Stopping condition We take the discarded conjunct:
((e = 2N + 2) or (o = 2N + 1)).

3. Progression It is specified by:


Precondition: (e ∈ 1 .. 2N + 2) and (e is even) and (positions with even indexes of the
interval 2..e−2 contain even values) and (o ∈ 1..2N+1) and (o is odd) and (positions
with odd indexes of the interval 1 .. o − 2 contain odd values) and not[(e = 2N +
2) or (o = 2N + 1)]
P ROGRESSION
Postcondition: (e ∈ 2 .. 2N) and (e is even) and (positions with even indexes of the
interval 2..e−2 contain even values) and (o ∈ 1..2N+1) and (o is odd) and (positions
with odd indexes of the interval 1 .. o − 2 contain odd values).
Before the progression, we are either in the following situation:
values with odd indexes are correctly placed

1 e o 2N
T

values with even indexes are correctly placed

or in this one:
values with even indexes are correctly placed

1 o e 2N
T

values with odd indexes are correctly placed

The relative positions of o and e do not play any role and we can indifferently take
into consideration T [e] or T [o] (which, nevertheless, breaks the symmetry exploited
until now) to propose the progression:

i i

i i
i i

i i

140 Specification, invariants, and iteration

1. if odd(T [i]) then


2. o ← o + 2
3. else
4. Exchange(o, e) ; e ← e + 2
5. end if
assuming available the function odd(k) which returns true if k is odd, false otherwise.
The preservation of the symmetry would require the review of the four possible cases
(T [i] even and T [e] odd, T [o] odd and T [e] odd, etc.), which would lead to a somewhat
unsightly progression.
4. Initialization It obeys the following specification:
Precondition: (T is an array of 2N natural numbers) and (S is the constant bag of val-
ues contained in T ) and (N ⩾ 0) and (T contains N even integers and N odd integers)
I NITIALIZATION
Postcondition: (e ∈ 2..2N) and (e is even) and (positions with even indexes of the in-
terval 1 .. e − 2 contain even values) and (o ∈ 1 .. 2N + 1) and (o is odd) and (positions
with odd indexes of the interval 1 .. o − 2 contain odd values).

The following situation:

o/1 e/2 2N
T

complies with the postcondition and the transition from the precondition is obtained
with the assignments: o ← 1; e ← 2.
5. Termination One of the two variables o and e decreases by 2 at each step of the pro-
gression. In contrast, the following expression is nonnegative and it diminishes by 1
at each step of the progression:

(2N − e + 2N + 1 − o)/2.

38 - A 3 Answer 3. Finally, we have built the program hereafter:


1. constants
2. N ∈ N and N = . . .
3. variables
4. T ∈ 1 .. 2N → N and T = [. . .] and e ∈ 2 .. 2N + 2 and o ∈ 1 .. 2N + 1
5. begin
6. /% PRE: (T is an array of 2N natural numbers) and (N ⩾ 0) and (T con-
tains N even integers and N odd integers) %/
7. e ← 2 ; o ← 1 ;
8. while not((e = 2N + 2) or (o = 2N + 1)) do
9. if odd(T [i]) then
10. o←i+2
11. else
12. Exchange(o, e) ; e ← e + 2
13. end if
14. end while;
15. /% POST: (positions with even indexes contain even values) or (positions
with odd indexes contain odd values) %/

i i

i i
i i

i i

Solutions 141

16. write(T )
17. end

Answer 4. In terms of exchanges, this algorithm is in O(N). The number of evaluated 38 - A 4


conditions is in Θ(N) (one condition for the control of the loop and another one for testing
T [o] – odd or not).
Answer 5. We have: 38 - A 5

(e ∈ 2 .. 2N) and (e is even) and


(positions with even indexes of the interval 2 .. e − 2
contain even values) and (o ∈ 1 .. 2N + 1) and (o is odd) and
(positions with odd indexes of the interval 1 .. o − 2
contain odd values) and (e = 2N) and (o = 2N + 1)
⇒ A and B ⇒ A or B
(e ∈ 2 .. 2N) and (e is even) and
(positions with even indexes of the interval 2 .. e − 2
contain even values) and (o ∈ 1 .. 2N + 1) and (o is odd) and
(positions with odd indexes of the interval 1 .. o − 2
contain odd values) and ((e = 2N) or (o = 2N + 1)),

this latter expression being nothing but the postcondition used before. The newly proposed
postcondition is thus a (logical) strengthening of the initial postcondition; hence, it can
serve as a basis for the construction of a loop appropriate to solve the problem.
Answer 6. With this in mind, we can use the same invariant as before: 38 - A 6
(e ∈ 1 .. 2N + 2) and (e is even) and (positions with even indexes of the interval
2 .. e − 2 contain even values) and (o ∈ 1 .. 2N + 1) and (o is odd) and (positions
with odd indexes of the interval 1 .. o − 2 contain odd values)
and take the discarded conjunct as stopping condition:
((e = 2N + 2) and (o = 2N + 1)).
The progression is specified by:
Precondition: (e ∈ 1 .. 2N + 2) and (e is even) and (positions with even indexes of the
interval 2 .. e − 2 contain even values) and (o ∈ 1 .. 2N + 1) and (o is odd) and (positions
with odd indexes of the interval 1..o−2 contain odd values) and not((e = 2N+2) and (o =
2N + 1))
P ROGRESSION
Postcondition: (e ∈ 2..2N) and (e is even) and (positions with even indexes of the interval
2 .. e − 2 contain even values) and (o ∈ 1 .. 2N + 1) and (o is odd) and (positions with odd
indexes of the interval 1 .. o − 2 contain odd values).
Here again T [o] can be tested as to the fact that it is odd (or not), but since the stopping
condition is conjunctive, its negation is disjunctive. Therefore, we can be in the situation
where o = 2N + 1 (with e ̸= 2N + 2) which means that odd values are all well placed.
The exchange must not be done (2N + 1 being an invalid index for T ), but “force” the
variable p to its final value (2N + 2), since even values are necessarily well placed, hence
the progression:
1. if o ̸= 2N + 1 then
2. if odd(T [o]) then
3. o←i+2
4. else

i i

i i
i i

i i

142 Specification, invariants, and iteration

5. Exchange(o, e) ; e ← p + 2
6. end if
7. else
8. e ← 2N + 2
9. end if
It can be noticed that this progression is slightly more tricky to build than the previous
one. Moreover, it is easy to see that the complexity of the program is the same in terms of
exchanges, but that the number of evaluated conditions for each iteration is now 3 instead
of 2 formerly.

Answers to problem 39. The longest sequence of zeros The problem is on


page 117.

39 - A 1 Answer 1. The new invariant is:


(lg is the length of the longest succession of zeros contained in the subarray
T [1 .. i − 1]) and (i ∈ 1 .. N + 1) and (p ∈ 1 .. i) and (p is the length of the longest
succession of consecutive zeros finishing in (i − 1)),
which can be schematized the following way:

1 i N
T 0 ········· 0 0 ··· 0

lg p
Despite appearances suggested by this schema, the subarrays associated with lg and p
may effectively be confused.
39 - A 2 Answer 2. The progression is specified by:
Precondition: (lg is the length of the longest sequence of zeros contained in the
subarray T [1 .. i − 1]) and (i ∈ 1 .. N + 1) and (p ∈ 0 .. i − 1) and (p is the length of
the longest sequence of consecutive zeros finishing in i − 1) and not(i = N + 1)
P ROGRESSION
Postcondition: (lg is the length of the longest succession of zeros contained in
the subarray T [1 .. i − 1]) and (i ∈ 1 .. N + 1) and (p ∈ 0 .. i − 1) and (p is the
length of the longest sequence of consecutive zeros finishing in i − 1).
It can be asserted that T [i] exists and that the invariant holds. It follows that, if T [i] = 0 then
p increases by 1, while lg becomes the greatest value between p and lg. Otherwise, lg re-
mains unchanged whereas p is set to 0. Restoring the invariant is obtained by incrementing
i by 1.
Hence, we have the following progression:
1. if T [i] = 0 then
2. p ← p + 1 ; lg ← max({lg, p})
3. else
4. p ← 0
5. end if;
6. i ← i + 1

i i

i i
i i

i i

Solutions 143

The initialization is specified by:

Precondition: (T is a constant array of N integers) and (N ⩾ 0)


I NITIALIZATION
Postcondition: (lg is the length of the longest succession of zeros contained in
the subarray T [1 .. i − 1]) and (i ∈ 1 .. N + 1) and (p ∈ 0 .. i − 1) and (p is the
length of the longest succession of consecutive zeros finishing in i − 1).
Establishing the postcondition (the invariant of the loop) is achieved by the assignments:
i ← 1 ; lg ← 0 ; p ← 0.

As to the termination, the expression (N + 1 − i) is appropriate since it decreases by 1 at


each step of the progression while remaining nonnegative.
Answer 3. Eventually, we have built the following program: 39 - A 3
1. constants
2. N ∈ N and N = . . . and T ∈ 1 .. N → N and T = [. . .]
3. variables
4. p ∈ 0 .. N and i ∈ 1 .. N + 1
5. begin
6. /% PRE: (T is a constant array of N integers) and (N ⩾ 0) %/
7. i ← 1 ; lg ← 0 ; p ← 0 ;
8. while not(i = N + 1) do
9. if T [i] = 0 then
10. p ← p + 1 ; lg ← max({lg, p})
11. else
12. p←0
13. end if;
14. i←i+1
15. end while;
16. /% POST: (lg is the length of the longest succession of consecutive zeros
contained in the array T ) %/
17. write(the length of the longest succession of zeros in , T , is , lg)
18. end
This solution demands N iterations since i is increased by 1 at each step of the progression.
Thus, it is in Θ(N) comparisons (control of the loop and test of T [i]).
Answer 4. The variable lg contains continuously (in the sense of the invariant) the 39 - A 4
length of the longest sequence of zeros. Carrying on the execution of the loop is meaning-
ful only if the value of lg can evolve. However, the longest possible succession of zeros
involving T [i] is that which would encompass the p zeros situated before i and the (poten-
tial) (N + 1 − i) zeros located between the positions i and N. When (p + N + 1 − i) is less
than (or equal to) lg, the value of lg will not change and thus the loop can stop. We can
deduce that an alternative to the stopping condition (i = N + 1) is (p + N + 1 − i) ⩽ lg. This
latter enables an “early” termination, thus less iterations, hence a better efficiency. With
this solution, the number of comparisons is in O(N). It can be noticed that when the array
T contains no zero, the two stopping conditions are equivalent and lead to browse the loop
N times.

i i

i i
i i

i i

144 Specification, invariants, and iteration

Answers to problem 40. The majority element (iterative issue) The problem
is on page 119.

40 - A 1 Answer 1. Demonstration of property 3 page 120 The only possibility is that one element
of P is majority. But, any element of P is present at most |P|/2 times (which, in this case, is
equal to |S|/2 times) and thus S cannot be majority.

Demonstration of property 4 page 120, part 1 Letting maj(S) be the predicate stating that S is
majority and maj(v, S) the predicate stating that v is a majority element in S, proposition 1
can be expressed a:
maj(S) ⇒ (c ∈ C ⇒ maj(c, S)),
proposition which will be proven by contradiction as follows:

not(c ∈ C ⇒ maj(c, S)) ⇒ not maj(S),

or (applying rules of the propositional calculus):

(c ∈ C and not maj(c, S)) ⇒ not maj(S).


If c is not a majority element, is it possible that a random element x of P, different from c,
is majority? The answer is negative since this element has a multiplicity at most equal to
|P|/2, value which is less than ⌊|S|/2⌋ + 1. Therefore, there is no majority element in S.

Demonstration of property 4 page 120, part 2 It is enough to consider the schema in which the
bag R is empty: C contains the value 5, which is not a majority element, 1 is the value with
the highest multiplicity in S but it is not a majority element.
40 - A 2 Answer 2. When the loop stops, R is empty according to the stopping condition and:
• either C is also empty and according to property (3), page 120, it is known that
S is not majority,
• or C is nonempty and according to property (4), page 120, the value c con-
tained in C (in any number of occurrences) is the majority candidate of S, i.e.
the only potential majority element for S, but nothing is sure.

40 - A 3 Answer 3. The precondition and postcondition of the loop built with the proposed
invariant are:
Precondition: (S is a bag of N values) and (N ⩾ 1).
Postcondition: if C is nonempty, x contains the value of the majority candidate of S; if C
is empty, S is not majority.
Therefore, this loop has a weakened postcondition with respect to that of the initial prob-
lem. In order to solve it, in the case where a possible majority candidate has been identified,
it is necessary to check whether S is actually majority (or not).
40 - A 4 Answer 4. We now give the progression, the initialization and the termination func-
tion.
Progression We choose an arbitrary element t of R which is withdrawn from R, and:
(a) if C is empty, t is inserted in C,
(b) if t is already in C, it is added to C,
(c) if t is absent from C, t is paired with an arbitrary element of C (which is
suppressed from C) and the couple is moved to the bag P.

i i

i i
i i

i i

Solutions 145

Under the assumption of the negation of the stopping condition, this procedure is
feasible and it maintains the invariant.
Initialization The bag S is copied into R. The two bags P and C are emptied, which estab-
lishes the invariant.
Termination The value of |R| decreases by 1 at each step of the progression, which guar-
antees that the loop finishes.

Answer 5. The bag C is refined by the pair (x, nbx), where x is the value present in C 40 - A 5
and nbx is its multiplicity. The bag R is refined by the pair (T , i), where T is an array of N
elements and i is such that i ∈ 1 .. N. T [i .. N] materializes the bag R. Last, the bag P disap-
pears from the refinement since its components are never used. The following algorithm is
deduced:
1. constants
2. N ∈ N1 and N = . . . and T ∈ 1 .. N → N1 and T = [. . .]
3. variables
4. x ∈ N1 and nbx ∈ 0 .. N and i ∈ 1 .. N + 1
5. begin
6. /% PRE: (S is a bag of N values represented by the array T [1..N]) and (N ⩾
1) %/
7. nbx ← 0 ; i ← 1 ;
8. while i ̸= N + 1 do
9. if nbx = 0 then
10. x ← T [i] ; nbx ← 1
11. elsif T [i] = x then
12. nbx ← nbx + 1
13. else
14. nbx ← nbx − 1
15. end if;
16. i←i+1
17. end while;
18. /% POST: if C is nonempty (nbx > 0), x contains the value of the majority
candidate of S; if C is empty (nbx  =0), S is not majority %/
N
19. if nbx = 0 or else mult(x, T ) ⩽ then
2
20. x ← −1 ;
21. write(No majority element in the array , T )
22. else
23. write(x, is the majority element of the array , T )
24. end if
25. end
The expression mult(x, T ) requires a refinement using a loop over the array T , which is
not made explicit here. This algorithm refined a second time evaluates (N + 1) times the
stopping condition of the first loop and at most (N + 1) times that of the second loop; thus
it is in Θ(N) in terms of comparisons.

Answers to problem 41. The celebrity problem The problem is on page 121.

Answer 1. By convention, a group with a single person has a star, thus at most one 41 - A 1
star. The property is proven by contradiction for a group made of at least two people.

i i

i i
i i

i i

146 Specification, invariants, and iteration

Let us assume that i1 and i2 are two stars of a group. Since a star is known by everyone,
operations Knows(i1 , i2 ) and Knows(i2 , i1 ) both return true, which contradicts the fact that
a star knows nobody in the group.
41 - A 2 Answer 2. Let us assume that the operation Knows(i, j) is performed and that we are
only provided with the answer to rule on the existence of a star. If the answer is positive,
j can be the star of the group since he/she is known by i (who knows another member of
the group and thus cannot be the star). If the answer is negative, j cannot be the star since
he/she is not known by a member of the group, but i can be the star.
41 - A 3 Answer 3. The problem to solve is specified by:
Precondition: (We have group of N people) and (N ⩾ 1)
Postcondition: ((i is the star of the group) and (i ∈ 1 .. N)) or ((the group has no
star) and (i = N + 1)).

41 - A 4 Answer 4. The program allowing for the identification of a “potential” star has a post-
condition which is a weakened version of the initial problem, namely:
Postcondition: ((i is perhaps the star of the group) and (i ∈ 1 .. N)).
A “potential” star is identified by means of a loop whose specification is:
Precondition: (We have a group of N people) and (N ⩾ 1).
Postcondition: ((i is perhaps the star of the group) and (i ∈ 1 .. N)).
The components of the loop are as follows:
1. Invariant The postcondition is strengthened in:
Postcondition: (j ∈ 1 .. N + 1) and (i ∈ 1 .. N + 1) and (i is perhaps the star of
members 1 .. j − 1 of the group) and (j = N + 1).
The first three conjuncts are chosen for the invariant:
(j ∈ 1 .. N + 1) and (i ∈ 1 .. N + 1) and (i is perhaps the star of members 1 .. j − 1
of the group).
2. Stopping condition The discarded conjunct is taken: (j = N + 1).
3. Progression It is specified by:
Precondition: (j ∈ 1 .. N + 1) and (i ∈ 1 .. N + 1) and (i is perhaps the star of members
1 .. j − 1 of the group) and not(j = N + 1)
P ROGRESSION
Postcondition: (j ∈ 1 .. N + 1) and (i ∈ 1 .. N + 1) and (i is perhaps the star of members
1 .. j − 1 of the group).

The progression must deal with member number j of the group. We will use the op-
eration Knows(j, i), i being the “potential” star. From question 2, if the answer is true,
i keeps its status, otherwise it is replaced by j. Thus, we have the progression:
1. if not Knows(j, i) then
2. i ← j
3. end if;
4. j ← j + 1
4. Initialization In order to establish the invariant, it is sufficient to select person 1 as a
possible star (and therefore to assign 2 to j), i.e. to make the assignments: i ← 1 and
j ← 2.

i i

i i
i i

i i

Solutions 147

5. Termination The expression (N + 1 − j) is suitable since it decreases at each step of the


loop while remaining nonnegative.

Answer 5. At the end of the previous loop, i identifies a member of the group which 41 - A 5
may be the star. It remains to confirm that i is actually the star of the group, or that there is
no star inside it (thanks to the principle of sequential composition introduced page 96.
First of all, let us remark that we know that any member j, with j greater than i, knows the
“potential” star i. Member i is actually the star only if: i) any member j with j less than i is
such that Knows(j, i) is true, and ii) any member j other than i is such that not(Knows(i, j)). It
is easy to observe that each situation corresponds to the special case described in section
3.5.2, page 109. Therefore, we will adapt the pattern given in page 109.
In the first loop, the generic property LP is identified to not(Knows(j, i)) and variable N to
(i − 1). In the second one, LP is identified to ((j ̸= i) and Knows(i, j)), hence the program:
1. constants
2. N ∈ N1 and N = . . .
3. variables
4. i ∈ 1 .. N + 1 and j ∈ 1 .. N + 1
5. begin
6. /% first loop: identification of a “potential” star %/
7. /% PRE: (We have a group of N people) and (N ⩾ 1) %/
8. i ← 1 ; j ← 2 ;
9. while not(j = N + 1) do
10. if not Knows(j, i) then
11. i←j
12. end if;
13. j←j+1
14. end while;
15. /% POST: (j ∈ 1 .. N + 1) and (i ∈ 1 .. N) and (i is perhaps the star of
members 1 .. j − 1 of the group) and (j = N + 1) %/
16. /% second loop %/
17. /% PRE: (i is perhaps the star of the group) %/
18. j ← 1 ;
19. while not((j = i) or else not Knows(j, i)) do
20. j←j+1
21. end while;
22. /% POST: (i ∈ 1 .. N) and (j ∈ 1 .. i + 1) and ((j = i) and (i is perhaps the
star of members 1 .. j − 1 of the group)) or ((j ̸= i) and the group has no
star %/
23. if j ̸= i then
24. write(no star in the group)
25. else
26. /% third loop %/
27. /% PRE: (i is perhaps the star of the group) %/
28. j←1;
29. while not((j = N + 1) or else ((j ̸= i) and (Knows(i, j)))) do
30. j←j+1
31. end while;
32. /% POST: ((i is the star of the group) and (j = N + 1)) or ((the group
has no star) and (j ∈ 1 .. N)) %/
33. if j = N + 1 then
34. write(i, is the star of the group)

i i

i i
i i

i i

148 Specification, invariants, and iteration

35. else
36. write(no star in the group)
37. end if
38. end if
39. end

41 - A 6 Answer 6. The first step (identification of a “potential” star) requires exactly (N − 1)


operations Knows. The second one requires between one (when member 1 does not know
the “potential” star) and (N − 1) (when i = N and the first (N − 1) members know the
last one who is the “potential” star) operations Knows. The last step also needs between
one (when membre i knows member 1) and (N − 1) (when member i knows nobody in the
group) operations Knows. Thus, the complexity is linear as expected.

Remark
The complete presentation of this problem as well as its background can be found in [25].

Answers to problem 42. Weakening a precondition The problem is on page 122.

Sorting increasingly an array ordered decreasingly

42 - A 1 Answer 1. If the array T is ordered decreasingly, it can be transformed into an increas-


ingly ordered array by means of a loop whose progression is inspired from that used in
problem 34, page 113. Instead of testing the symmetry of the array, elements whose in-
dexes j and (N + 1 − j) are in “mirror” positions are exchanged. The stopping condition of
the loop is j ⩾ N + 1 − j. The solution obtained requires ⌊N/2⌋ exchanges and it is in Θ(N).
42 - A 2 Answer 2. The sort algorithm proposed in problem 33 page 112, is in Θ(N2 ) exchanges.
A lower asymptotic complexity (O(N · log2 (N))) can be reached with a more efficient sort
algorithm such as “quicksort”. However, whatever the choice of such an algorithm, if there
is a gain in terms of design and construction of the program, there is a loss in terms of
performances. It appears that weakening the precondition is not appropriate in this case.

Constrained variation array

42 - A 3 Answer 3. Let T [i] = k (k > 0). Since the difference between two consecutive elements
is at most 1, the most favorable case to find out a zero occurs with the program:
T [i] = k, T [i + 1] = k − 1, . . . , T [i + k − 1] = 1, T [i + k] = 0.
It appears that all the elements of T with indexes i to i + k − 1 (= i + T [i] − 1) are strictly
positive. When we have a longer sequence, to reach a zero the previous property over
elements with indexes i to (i + T [i] − 1) still holds. Formally, we have:

(T [i] > 0) ⇒ ∀j · (j ∈ i .. i + T [i] − 1 ⇒ T [j] > 0).

42 - A 4 Answer 4. We build the constituents of a loop in the spirit of those designed for the
search of the first zero, taking advantage of the result established in the previous question.
1. Invariant We take: (i ∈ 1 .. N) and (T [1 .. i − 1] contains no zero).
2. Stopping condition It is T [i] = 0.

i i

i i
i i

i i

Solutions 149

3. Progression From the property established previously, it is known that, since T [i] is not
equal to zero, it is possible to increment i by the value T [i] with the guarantee that no
zero is “missed” (T [i + T [i]] may be equal to 0), hence the progression: i ← i + T [i].
4. Initialization The initialization is restricted to the assignment i ← 1.
5. Termination The expression (N − i) is appropriate.

Answer 5. The specific algorithm which has been designed needs between one com- 42 - A 5
parison (if T [1] = 0) and N comparisons (if T [1] = . . . = T [N − 1] = 1 and T [N] = 0). It is the
same for the algorithm given in page 101. The two solutions are situated in the same class
of complexity O(N). However, in the specific algorithm the step of the loop is variable and
it is always greater than or equal to 1. Thus, it is preferable to use it since it never does
worse than the other one (even slightly better in general).
Answer 6. The discarded conjunct (the difference between two consecutive elements 42 - A 6
of T is at least 1) expresses the fact that it cannot exist two consecutive elements of T with
the same value, which does not help to resolve the problem of the search for the first zero.
As a consequence, there is no (obvious) specific program in this case. It is thus recom-
mended to use the program corresponding to the weakened precondition (see page 101),
choice solving ”at best” the problem in a performance perspective.
Answer 7. The three examples treated previously show that weakening the precondi- 42 - A 7
tion can lead to:
• a solution whose class of complexity is worse than that of a specific solution,
• a solution of same class of complexity, but after all less efficient,
• a good solution if the discarded conjunct cannot be exploited for building a
specific solution.

Answers to problem 43. Halving a polygon The problem is on page 123.

Answer 1. We have: 43 - A 1
↷ ↷
∥(i, j)∥ − ∥(j, i)∥
= arithmetics
↷ ↷ ↷
2 · ∥(i, j)∥ − (∥(j, i)∥ + ∥(i, j)∥)
= definition of p

2 · ∥(i, j)∥ − p
= arithmetics
↷ p
2 · ∥(i, j)∥ − .
2
Answer 2. When the semi-perimeter having its origin in vertex j has exactly its end in 43 - A 2
the middle of a side, there are two optimal chords issued from vertex j. It is the case of the
pentagon hereafter: there are two optimal chords issued from j: (j, k) and (j, k + 1). The
↷ ↷
first one separates the pentagon into ∥(j, k)∥ = 4 units, and ∥(k, j)∥ = 8 units, the second
↷ ↷
one separates it into ∥(j, k + 1)∥ = 8 units, and ∥(k + 1, j)∥ = 4 units.

i i

i i
i i

i i

150 Specification, invariants, and iteration

2
• •k

2
j• 4/8
4

×
8/
4

3
• •
1 k+1

43 - A 3 Answer 3. It is easy to prove that:


 ↷ ↷

∀l · l ∈ j + 2 .. k − 2 ⇒ ∥(j + 1, l)∥ − p/2.0 > ∥(j, l + 1)∥ − p/2.0 .

Consequently, it is sufficient to restrict the proof to the longest arc among the set of arcs
↷ ↷ ↷ ↷
(j + 1, j + 2), (j + 1, j + 3),. . . ,(j + 1, k − 1), or (j + 1, k − 1). Thus, we will demonstrate that
↷ ↷
∥(j + 1, k − 1)∥ − p/2.0 > ∥(j, k)∥ − p/2.0 (= δj ).
Denoting by q the extremity of the semi-perimeter issued from j, two situations must be
singled out:

j + 1• •k − 1 j + 1• •k − 1
q
×
j• •k j• •k
×q
(a) •k + 1 (b) •k + 1
In both cases, we have:
↷ p
∥(j + 1, k − 1)∥ −
2.0
p ↷
= > ∥(j + 1, k − 1)∥ and property of the absolute value
2.0
p ↷
− ∥(j + 1, k − 1)∥
2.0 p
= development of
↷ ↷ ↷ ↷
2.0
∥(j, j + 1)∥ + ∥(j + 1, k − 1)∥ + ∥(k − 1, q)∥ − ∥(j + 1, k − 1)∥
= arithmetics
↷ ↷
∥(j, j + 1)∥ + ∥(k − 1, q)∥.
↷ ↷
In the first case (schema (a)), ∥(k − 1, q)∥ > ∥(q, k)∥ since otherwise the chord (j, k − 1)
would be the first locally optimal chord for the vertex j. Therefore, it comes:
↷ ↷
∥(j, j + 1)∥ + ∥(k − 1, q)∥
> arithmetics

∥(k − 1, q)∥
> previous remark

∥(k, q)∥
= definition of δj
δj

i i

i i
i i

i i

Solutions 151

and finally:
↷ p
∥(j + 1, k − 1)∥ − > δj .
2.0
In the second case (schema (b)), we have:
↷ ↷
∥(j, j + 1)∥ + ∥(k − 1, q)∥

= development of ∥(k − 1, q)∥
↷ ↷ ↷
∥(j, j + 1)∥ + ∥(k − 1, k) + ∥(k, q)∥
> arithmetics

∥(k, q)∥
= definition of δj
δj
and we also have:
↷ p
∥(j + 1, k − 1)∥ − > δj .
2.0

Answer 4. First of all, let us notice that the chord (j + 1, k) may not exist and we will 43 - A 4
come back to this point later (see question 5). To prove that the chord (j + 1, k) may be
better than (j, k) the first optimal chord issued from j, an example suffices. Let us consider
the following pentagon:

5 6
j+1

• k
1


j
5 • 5

The chord (j, k) is locally optimal and it separates the perimeter into two parts of respective
lengths 12.0 and 10.0. The chord (j + 1, k) separates the perimeter into two equal parts of
length 11.0. This division is optimal since the value of δj+1 is 0.0 and it outperforms the
previous one for which δj = 12.0 − 11.0 = 1.0.
Answer 5. The value of the perimeter of the polygon is 11.8 and the value of its semi- 43 - A 5
perimeter is 5.9. The arcs whose length intervenes in the calculation are greyed-out as , as
or as in figure 3.5.
We will go into the details of the calculations in order to highlight the properties and mech-
↷ ↷ ↷
anisms used. In the case of the first line, the respective lengths of the arcs (1, 2), (1, 3), (1, 4)
↷ ↷
and (1, 5) are calculated. Their values are 2.2, 3.1, 4.7 and 6.3. The length of the arcs (1, 6)

to (1, 1) is not calculated (according to the heuristics “stop as early as possible”), since the

length of the arc (1, 5) is greater than that of the semi-perimeter. The chord (1, 5) associated
with this arc (cell greyed-out as in the schema) is retained as the (first) locally optimal

chord from the vertex 1, since the comparison with the previous arc (1, 4) is in favor of

(1, 5).
As for the arcs whose origin is vertex 2, it is useless calculating the length of the arcs
↷ ↷ ↷
(2, 3) and (2, 4) (see question 3). The evaluation begins with the arc (2, 5) whose length is
↷ ↷
∥(1, 5)∥ − ∥(1, 2)∥ (or, 6.3 − 2.2 = 4.1). As a matter of fact, according to the definition of the
length of an arc (definition 2 page 124, inductive case), if j ̸= i + 1 and i ̸= N,

i i

i i
i i

i i

152 Specification, invariants, and iteration

2 3 4 5 6 7 8 9 1
1 2.2 3.1 4.7 6.3 7.4 8.7 10.5 11.2 11.8
2 0.9 2.5 4.1 5.2 6.5 8.3 9.0 9.6
3 1.6 3.2 4.3 5.6 7.4 8.1 8.7
4 1.6 2.7 4.0 5.8 6.5 7.1
5 1.1 2.4 4.2 4.9 5.5
6 1.3 3.1 3.8 4.4
7 1.8 2.5 3.1
8 0.7 1.3
9 0.6

Fig. 3.5 – Example corresponding to figure 3.4, page 124, showing the arcs whose length is actually
calculated. The arcs greyed-out in are those corresponding to locally optimal chords. The arcs

correspond to those visited whose length is less than p/2.0. An arc (i, k) greyed-out as is, for a
given origin i, the first arc whose length is greater than or equal to p/2.0, but which is not a locally
optimal chord (whilst (i, k − 1) is). The arcs on a white background ( ) correspond to those not
visited.

↷ ↷
∥(i, j)∥ = d[i] + ∥(i + 1, j)∥
⇔ first base case, definition 2, page 124
↷ ↷ ↷
∥(i, j)∥ = ∥(i, i + 1)∥ + ∥(i + 1, j)∥
⇔ arithmetics
↷ ↷ ↷
∥(i + 1, j)∥ = ∥(i, j)∥ − ∥(i, i + 1)∥
⇒ substitution (i by 1 and j by 5) and arithmetics
↷ ↷ ↷
∥(2, 5)∥ = ∥(1, 5)∥ − ∥(1, 2)∥
⇔ numerical application
4.1 = 6.3 − 2.2.
↷ ↷
We pursue with the arcs (2, 6) of length 5.2 and (2, 7) of length 6.5. This latter value is
greater than the semi-perimeter, which leads to select (2, 7) as the locally optimal chord
↷ ↷ ↷
issued from vertex 2 (the length of the following arcs – (2, 8), (2, 9), (2, 1) – is not cal-
culated applying the heuristics “stop as early as possible”). For the arcs starting at ver-
↷ ↷ ↷
tex 3, only length of the arcs (3, 7) and (3, 8) are calculated: ∥(3, 7)∥ − p/2.0 = 0.3 and
↷ ↷
∥(3, 8)∥ − p/2.0 = 1.5. The comparison is in favor of (3, 7); the chord (3, 7) is thus de-
↷ ↷
clared to be locally optimal. The length of the arcs (3, 9) and (3, 1) is not calculated.
Vertex 7 is the starting point of the calculation related to arcs starting at vertex 4. We calcu-
↷ ↷ ↷
late the length of the chords (4, 7), (4, 8) and (4, 9), whose respective values are 4.0, 5.8 and
6.5, which leads to take (4, 8) as the locally optimal chord issued from vertex 4. The length

of (4, 1) is not calculated.
↷ ↷ ↷
As for vertex 5, we calculate the length of the arcs (5, 8), (5, 9) and (5, 1). Chord (5, 1) of
(maximum) value 5.5, is declared locally optimal.

i i

i i
i i

i i

Solutions 153

From now on, in vertue of observation 3 in the statement of the problem, for each vertex
↷ ↷ ↷ ↷
i of the interval 6 .. 9, there is a single candidate arc ((6, 1), (7, 1), (8, 1), (9, 1)); the related
chord ((6, 1), (7, 1), (8, 1), (9, 1)) is therefore locally optimal.
Eventually, the resulting global optimal chord is (4, 8). Figure 3.5, page 152 confirms this
result since, among all the values of the triangle of lengths, 5.8 is the one closest to 5.9,
which is the length of the semi-perimeter.
Answer 6. The perimeter of this polygon is 11.0. Therefore, the value of its semi- 43 - A 6

perimeter is 5.5. For the arcs issued from the vertex 1, we have ∥(1, 2)∥ = 5.0, value which
does not allow for stopping the search for the locally optimal chord. On the contrary, the

value ∥(1, 3)∥ = 8.0 exceeds the semi-perimeter and we can stop the search for arcs whose

origin is the vertex 1. Among these two values, ∥(1, 2)∥ is the best one and the chord (1, 2)
is the local optimum for vertex 1.
2 3 1
1 5.0 8.0 11
2 3.0 6.0
3 3.0
However, to account for the arc whose origin is vertex 2, according to observation 3 of the

statement, we should begin with the calculation of the arc ∥(2, 2)∥; yet, this one does not
exist in the triangle of lengths. This special case shall be taken into consideration in the
progression of the loop which will be built. It occurs when the row (i + 1) is dealt with and
the locally optimal chord of line i is (i, i + 1). So, this case is not specific to triangles, it is
also the case of the quadrangle below for which the calculation for the arcs whose origin is

the vertex 3 cannot be done from ∥(2, 3)∥ since the chord (2, 3) is of type (i, i + 1).

1• 2 • 2 2 3 4 1
1

4• 1 2 7 10 11
2 5 8 9
3 3 4
3

• 4 1
3

Answer 7. Obviously, it is excluded to permanently dispose of the triangle of lengths 43 - A 7


and even to calculate the length of all its elements (otherwise, complexity would be in
Θ(N2 )). We will take advantage of observations 2, 3 and 4 of the statement (as it was done
in the treatment of question 4, page 126) in order to avoid visiting some arcs in the course
of iterations.
Figure 3.6, page 154, represents the situation reached in the context of the hypothesis of the
work carried out partly with the graphic conventions of figure 3.5, page 152. Arcs hatched
( ) are those that remain to be treated.
The array D (respectively the scalar p) representing the length of the various sides (re-
spectively the perimeter of the polygon) are constants. As such, they are not part of the
invariant which is expressed as:
i ∈ 1 .. N + 1 and j ∈ i + 1 .. N + 2 and
the chord (o, e) is globally optimal over the portion of the triangle of lengths
covering entirely rows 1 to (i − 1) and columns 1 to (j − 1) of line i and

i i

i i
i i

i i

154 Specification, invariants, and iteration



the length of the related arc is lgo = ||(o, e)|| and

the length of the current chord is lgc = ||(i, j)||.

We know the globally op-


timal chord of origin o, ex-
tremity e and length lgo.

2 3 j N+1
1
2
The length lgc of 3

arc (i, j) is known.

i
i+1

Fig. 3.6 – An instance of the work carried out partly over the triangle of lengths.

43 - A 8 Answer 8. Let us finish the construction of the loop.


Stopping condition According to figure 3.6, page 154, the loop ceases as soon as i = N+1.
Progression Two situations must be envisaged. Either we must consider a new row (see
line 14 of the code hereafter), or we move forward on the same row (see line 31 of the
code hereafter). The first situation occurs when the semi-perimeter is passed over (it
is a first keypoint for the efficiency of the algorithm), or when j = N + 1. We must
↷ ↷
choose between the arcs (i, j) and (i, j − 1) comparing |lgc − p/2.0| and |lgc − d[j −

1] − p/2.0|. In the particular case where i = N and j = N + 1, arc (N, N) does not
exist. However, given that lgc = d[N] = d[j − 1], the comparison works well since it
leads to take (N, N + 1) as the locally optimal chord. Then, the best globally optimal
chord is updated if necessary. Line 25 of the code allows for updating the value of
lgc without recalculating it arc by arc. To do so, it is sufficient to subtract the value
of D[i] from the current value (it is the second keypoint concerning the efficiency of
the algorithm). Line 27 of the code is the algorithmic expression of the point raised
in question 5. Line 31 of the code deals with the case where we progress on the same
row and it does not require specific explanations.
Initialization The invariant is established by the code lines 10 to 12 of the algorithm below,
assigning the appropriate value to each of the variables o, e, i, j, lgc and lgo.
Termination In figure 3.6, the area of the surface occupied by zones bold outlined ( ou
) diminishes at each step of the progression while remaining positive. This area is
measured by
(N − i) · (N − i + 1)
+ N + 2 − j,
2
which makes a suitable termination expression.

i i

i i
i i

i i

Solutions 155

The code is as follows:


1. constants
2. N ∈  N1 and N > 2 and N = . . . and D ∈ 1 .. 
N → R+ and D = [. . .] and
X
3. ∀h · h ∈ 1 .. N ⇒ D[h] < D[k] and
k∈1..N and k̸=h
X
N
4. p ∈ R+ and p = D[k]
k=1
5. variables
6. lgo ∈ R+ and lgc ∈ R+ and o ∈ 1 .. N − 1 and e ∈ o .. N and
7. i ∈ 1 .. N + 1 and j ∈ i + 1 .. N + 2
8. begin
9. /% PRE: we have a polygon with N sides (N > 2) of lengths D[1], . . . , D[N]
%/
10. o ← 1 ; e ← 2 ;
11. i ← 1 ; j ← 2 ;
12. lgo ← D[1] ; lgc ← D[1] ;
13. while not(i = N + 1) do
p
14. if lgc ⩾ or j = N + 1 then
2.0
15. /% The following condition compares the two arcs located on both
sides of the semi-perimeter in order to choose the best one, including
when i = N, j = N + 1 %/
p p
16. if lgc − > lgc − D[j − 1] − then
2.0 2.0
17. lgc ← lgc − D[j − 1] ;
18. j←j−1
19. end if;
p p
20. if lgc − < lgo − then
2.0 2.0
21. lgo ← lgc ;
22. o←i;e←j
23. end if;
24. /% The new value of lgc is obtained from the old one, not summing
up the lengths of all its arcs %/
25. lgc ← lgc − D[i] ;
26. /% Treatment of the special case of question 5 %/
27. j ← max({j, i + 2}) ;
28. /% Following row/following vertex %/
29. i←i+1
30. else
31. lgc ← lgc + D[j] ; j ← j + 1
32. end if
33. end while;
34. /% POST: the chord (o, e) of length lgo separates the polygon at best %/
35. write(the chord connecting vertices, o, and, e, of length, lgo,
36. separates the polygon at best)
37. end
The precondition (line 3) specifies the constraint that must be met by D so that it is the rep-
resentation of a polygon (in fact, it is the extension to a polygon of the triangular inequality
in the Euclidian metrics).

i i

i i
i i

i i

156 Specification, invariants, and iteration

Complexity
The complexity, in terms of visited vertices, is in Θ(N). As a matter of fact, considering
two consecutive rows i and (i + 1) in the triangle of lengths (see for example, figure 3.5
page 152), visited vertices follow one another, with the possible exception of the overlap-
ping of one or two vertices. Finally, N vertices are visited once and at most (N − 2) are
visited twice, hence at most 3(N − 4) visited vertices. The calculation of the perimeter p,
present in the precondition, has no impact on the asymptotic complexity since it is per-
formed in Θ(N).

Remark
It can be observed that triangles of lengths are a kind of triangular saddle (see problem
102, page 439): rows (respectively columns) are increasingly (respectively decreasingly)
ordered. This property can be exploited to enhance the stopping condition of the loop and

stop it when the locally optimal arc of origin i is (i, 1), that its length is less than or equal to
the semi-perimeter and that it does not improve the globally optimal arc known so far. In
↷ ↷
the situation of figure 3.5, page 152, it is the case of (5, 1) which is such that ∥(5, 1)∥ = 5.5.

Yet, 5.5 is worse than the length (5.8) of the best arc known (4, 8) and less than the semi-
perimeter 5.9. It is useless evaluating all the arcs whose origin is a vertex greater than 5.
The expression of the new stopping condition is left to the reader. It has no incidence on
the asymptotic complexity since it is still necessary to reach the rightmost column of the
triangle of lengths, thus to visit at least N vertices.

i i

i i
i i

i i

4
Reduce and conquer, recursion

Le caméléon n’a la couleur du


caméléon que lorsqu’il est posé sur un
autre caméléon (The chameleon has the
color of the chameleon only when
placed over another chameleon).

F. Cavanna

4.1 A few reminders about recursion


Numerous problems have a solution expressible easily and efficiently in a recursive way. It
is important to make sure that the associated algorithms (programs) are correct and come
to an end. In the simplest cases, similarly to a simple recurrence including a terminal case
and a general term, a recursive procedure is written as a conditional statement with a stop-
ping case on the one hand and a recursive call on the other hand. However, if this type of
construction is desirable, it guarantees neither termination nor correctness of the proce-
dure. Let us consider the following function:

1. function Calc(n) result Z pre


2. n ∈ Z
3. begin
4. if n > 100 then
5. result n − 10
6. else
7. result Calc(Calc(n + 11))
8. end if
9. end

When the parameter is strictly greater than 100, termination is obvious, but what happens
otherwise? The reader can check in exercise 44, page 166, that, according to this hypothe-
sis, this function always ends and that the returned result is the value 91.

We now give an example of a problem for which a recursive approach allows to design
a simple elegant solution. Let us consider a series of positive integers terminated with a
marker, either −1, or −2. If the marker is −1, the objective is to compute the sum of the
preceding values, otherwise their product. The sequence of numbers must be read only
once and it must not be explicitly stored (for instance in an array). Indeed, recursion will

DOI: 10.1201/b23251-4 157


i i

i i
i i

i i

158 Reduce and conquer, recursion

be used to collect each of the numbers read in the local variable nb. The appropriate opera-
tion (sum or product) associated with the marker (global variable mark) will be performed
after the recursive call and, finally, the expected value (global variable res) is obtained by
means of the following procedure:

1. procedure SomProd pre


2. nb ∈ N1 ∪ {−1, −2}
3. begin
4. read(nb);
5. if nb > 0 then
6. SomProd;
7. if mark = −1 then
8. res ← res + nb
9. else
10. res ← res · nb
11. end if
12. else
13. mark ← nb;
14. if mark = −1 then
15. res ← 0
16. else
17. res ← 1
18. end if
19. end if
20. end

By doing so, no explicit storage is used for the numbers to be added or multiplied, those
being stored in the execution stack related to the handling of recursion. Clearly, no space
saving is achieved but this is not the objective in this case. It can be noticed that the pro-
cedure SomProd is not restricted to a conditional statement, although it involves one that
singles out the terminal case and the recursive one.

4.2 Recurrence relation and recursion


In Chapter 1, we have seen that the solution of certain problems calls on a recurrence
relation. The related implementation was expressed as an iterative procedure aiming at
filling in a tabular structure. An alternative choice would be to write a recursive procedure.
If such an approach is definitively legitimate, it is generally less efficient.
Let us take the example of the recurrence associated with the calculation of the number
of binary trees having n nodes:

nbBT (0) = 1
X
n−1
nbBT (n) = nbBT (i) · nbBT (n − i − 1) n ⩾ 1.
i=0

i i

i i
i i

i i

“Reduce and conquer” and its complexity 159

The associated recursive procedure nbBinTr(n) is:

1. function nbBinTr(n) result N1 pre


2. n ∈ N1 and sum ∈ N
3. begin
4. if n = 0 then
5. result 1
6. else
7. sum ← 0;
8. for i ranging 0 .. n − 1 do
9. sum ← sum + nbBinTr(i) · nbBinTr(n − 1 − i)
10. end for;
11. result sum
12. end if
13. end
and the computation of the number of binary trees with 15 nodes is made through:

1. constants
2. n = 15
3. begin
4. write(the number of binary trees having , n, nodes is , nbBinTr(n))
5. end
which delivers the same value as the one returned by the iterative program in page 13.
However, each number nbBT is computed several times. To realize this, it is sufficient
to observe what happens for n = 5. The call nbBinTr(5) causes two calls to nbBinTr(0),
nbBinTr(1), nbBinTr(2), nbBinTr(3) and nbBinTr(4). Except nbBinTr(0), these calls in turn
cause pairs of new calls (for example nbBinTr(4) calls nbBinTr(0), nbBinTr(1), nbBinTr(2)
and nbBinTr(3)), and so on. More precisely, nbMult(n) the number of multiplications re-
quired to calculate nbBT (n) is given by the recurrence:

nbMult(0) = 0
X
n−1
nbMult(n) = (1 + nbMult(i) + nbMult(n − i − 1)) = 1 + 2 · nbMult(n − 1)n ⩾ 1
i=0

whose solution is nbMult(n) = (3n − 1)/2 for any n ⩾ 1 (this result can be proven by
strong induction). The number of multiplications required by this algorithm is thus in
Θ(3n ), whereas that in page 13 is in Θ(n2 ).
Another illustration of the interest for an iterative implementation of the computation
of a value defined by a recurrence relation is given in exercice 45, page 167.

4.3 “Reduce and conquer” and its complexity


In this section, the focus is put on a specific family of recursive procedures resolving a
problem of size n, by calling on the resolution of identical problems of size (n−1). Chapter
8 deals with the more general case where the (sub-)problems can have different sizes.

i i

i i
i i

i i

160 Reduce and conquer, recursion

4.3.1 Presentation
We consider a one-dimensional problem of size n denoted by Pb(n). To resolve it, we call
on (i) a sub-problems of size (n − 1) (hence the term “reduce”) of the same nature as the
initial problem and (ii) the additional function f. This latter aims at the generation of the
sub-problems on the one hand and at the “combination” of their results in order to obtain
the final result on the other hand. There should be a size n0 (most often k = 0, i.e. f is a
function of constant complexity) for which the solution is known directly (the so-called ele-
mentary problem), i.e. without calling on sub-problems. So, we have the following generic
reduction resolution pattern (also called reduction model):

Pb(0) or Pb(1) elementary


Pb(n) → a · Pb(n − 1) + f(n) n > 0 or n > 1.

When a = 1, we have a “classical” recursion which, most often, can be easily transformed
into an iteration (see Chapter 1). In the general case, the structure of the program is:

1. procedure ReduceAndConquer(n) pre


2. n ∈ N1
3. begin
4. if n = . . . then
5. Resolve the elementary problem
6. else
7. ReduceAndConquer(n − 1);
8. ... /% a calling occurrences %/
9. ReduceAndConquer(n − 1);
10. Assemble
11. end if
12. end

were the generic procedure Assemble composes the final result from the partial results re-
turned by each of the invoked sub-problems. The initial call is made through the program:

1. constants
2. m ∈ N1 and m = . . .
3. begin
4. ReduceAndConquer(m)
5. end

The complexity of such a program is expressed in terms of an elementary operation rep-


resentative of the considered problem. This operation is part of the general case of the
reduction model (possibly inside function f) and/or in the elementary problem. Assum-
ing that the complexity of f is in Θ(nk ) (most often k = 0, i.e. a function f of constant
complexity), the complexity equation is written:

C(1) = d (d ∈ Θ(1))
C(n) = a · C(n − 1) + c · nk n>1

P
whose general solution is C(n) = an−1 · d + c · n−2
i=0 a · (n − i) ; this solution can be
i k

obtained by the summing factor method. As a matter of fact, we have:

i i

i i
i i

i i

“Reduce and conquer” and its complexity 161

C(n) = a · C(n − 1) + c · nk
C(n − 1) = a · C(n − 2) + c · (n − 1)k
C(n − 2) = a · C(n − 3) + c · (n − 2)k
...
C(2) = a · C(1) + c · (2)k
C(1) = d.

Multiplying the second line by a, the third one by a2 , . . . , the penultimate one by an−2 , the
last one by an−1 and summing up the left terms on the one hand and the right on the other
hand, it yields:

C(n) + a · C(n − 1) + a2 · C(n − 2) + · · · + an−2 · C(2) + an−1 · C(1) =


a · C(n − 1) + c · nk + a2 · C(n − 2) + a · c · (n − 1)k + a3 · C(n − 3) + a2 · c · (n −
2)k + · · · + an−1 · C(1) + an−2 · c · (2)k + an−1 · d.

By simplifying, it comes:

C(n) = c · nk + a · c · (n − 1)k + · · · + a2 · c · (n − 2)k + · · · + an−2 · c · (2)k + an−1 · d,

and finally:

X
n−2
C(n) = an−1 · d + c · ai · (n − i)k .
i=0

Some particular solutions can be deduced:


X
n−2
k = 0 and a = 1 −→ C(n) = d + c · 1, or C(n) ∈ Θ(n)
i=0
X
n−2
k = 0 and a > 1 −→ C(n) = a n−1
·d+c· ai , or C(n) ∈ Θ(an )
i=0
X
n−2
k = 1 and a = 1 −→ C(n) = d + c · (n − i), or C(n) ∈ Θ(n2 ).
i=0

In order to ensure the correctness of the proposed solution, we will systematically rely on
an inductive construction (most often a simple induction over N or N1 ) with three con-
stituents: (i) the base where the elementary case is made explicit together with its related
solution, (ii) the induction hypothesis where it is assumed that the problem of size (n − 1)
can be resolved for (n − 1) greater than or equal to the value of the base, and (iii) the in-
duction itself where it is demonstrated how to resolve the problem Pb(n) of size n using
the induction hypothesis. A fourth component of this type of proof will be omitted, the
termination, which is guaranteed here inasmuch as the size of the problem is an integer at
least equal to the value specified in the base (since starting with a positive integer greater
than or equal to that of the base, the value of the base is obtained by constant subtractions
of 1).

Through two examples, we now illustrate the cases a = 1 and a = 2 for k = 0.

i i

i i
i i

i i

162 Reduce and conquer, recursion


a
e α
α
e, f
f b
d
c, d

a, b
c

Fig. 4.1 – A spiral for n = 4.

4.3.2 Example 1: the spiral pattern


We want to make a “spiral” as illustrated in figure 4.1, using the approach “Reduce and
conquer”. Such a spiral is said to be of size n if the figure is composed of n nested “pseudo
squares” (n = 4 in figure 4.1). We set a = b, c = d = a−α, e = a−2α, with a given value of
α. Moreover, the drawing is made from the outside to the inside; therefore, it starts by the
upper horizontal segment of length a. Last, we have two primitives to make the drawing:
place(x, y) which puts the pen down at the point of coordinates (x, y), and draw(x, y) which
traces the segment from the current position of the pen to the point (x, y).
In order to continue the drawing, a first question is about the value of f (see figure 4.1).
Since in the first step we have a = b, c = d = a − α, so that the sub-problem being called
upon is of the same nature than the initial problem, we must have f = e = a − 2α.
Considering the nature of the drawing, n, a and α must meet a precondition so that the
trace of the drawing of the spiral of size n can be executed. Indeed, the trace imposes that
(n − 1) times 2α can be subtracted from a; hence, we must have: a > 2 · α · (n − 1).
These preliminaries being laid out, we first specify the reduction model for this prob-
lem, then we propose a recursive procedure performing this drawing, called SpiralDraw-
ing(n, x, y, a, α) where n is the number of “pseudo squares” to be drawn, x and y are the
coordinates of the starting point of the drawing, a and α correspond to the symbols de-
fined before. The construction of the drawing obeys the following inductive schema.

Base We know how to make the spiral of size 0 which consists in doing nothing.
Induction hypothesis We assume that, inasmuch as a is greater than 2 · α · (n − 1), we
know how to make the spiral of size (n − 1) (n − 1 ⩾ 0) having an upper horizontal
segment of length l equal to that of its right vertical segment and a lower horizontal
segment and a left vertical segment of length l − α.
Induction We specify how to make the spiral of size n assuming that a is greater than
2 · α · (n − 1). We begin with the trace of the upper horizontal segment of length a,
then the right vertical segment of the same length. Then, we trace the lower horizontal
segment of length (a − α), then the left vertical segment of the same length. Then, we
trace the spiral of size (n − 1) whose upper horizontal segment is of length (a − 2α),
which is feasible from the induction hypothesis since:

a > 2 · α · (n − 1) ⇒ a > 2 · α · (n − 2),

and we have achieved our goal.

i i

i i
i i

i i

“Reduce and conquer” and its complexity 163


Consequently, the reduction model for this problem is:

SpiralDraw(0, a) elementary
 (nothing to do)
 SpiralDraw(n − 1, a − 2α)
SpiralDraw(n, a) → + n > 0.

tracing of the outer pseudo-square

The drawing is performed by means of the procedure hereafter:

1. procedure SpiraleDrawing(n, x, y, a, α) pre


2. n ∈ N and x ∈ R∗+ and y ∈ R∗+ and a ∈ R and α ∈ R∗+ and a > 2 · α · (n − 1)
3. begin
4. if n > 0 then
5. draw(x + a, y);
6. draw(x + a, y − a);
7. draw(x + α, y − a);
8. draw(x + α, y − α);
9. SpiralDrawing(n − 1, x + α, y − α, a − 2α, α)
10. end if
11. end

which is called by:

1. constants
2. x0 ∈ R∗+ and x0 = . . . and y0 ∈ R∗+ and y0 = . . .
3. begin
4. place(x0 , y0 );
5. SpiralDrawing(7, x0 , y0 , 24.0, 1.5)
6. end

and traces the spiral of size 7 whose initial upper side of length 24 cm starts at the point
of coordinates (x0 , y0 ). This call complies with the precondition evoked previously since
24 > 2 · 1.5 · 6 (= 18).

Remark
Here, we have a tail-recursive procedure and the actual implementation can be an iterative
procedure rather than a recursive one (see Chapter 1).

Finally, we calculate the length of the trace depending on n, a and α assuming that the
precondition a > 2·α·(n−1) is met. The length of the trace is the solution of the recurrence:

LG(0, −, −) = 0
LG(n, a, α) = 2a + 2(a − α) + LG(n − 1, a − 2α, α) n>0

or, by summing up:


2n−1
X 2n−1
X 2n−1
X
LG(n, a, α) = 2(a − iα) = 2a − 2α i = 4an − 4αn2 + 2αn.
i=0 i=0 i=0

For n = 7, we get LG(7, a, α) = 28a − 182α, i.e. 98 cm for a = 10.0 cm and α = 1.0 cm.

i i

i i
i i

i i

164 Reduce and conquer, recursion

4.3.3 Example 2: Hanoi towers


The Hanoi towers problem involves “reconstructing” a tower (also called a “pagoda”)
composed of a stack of n disks of bottom-up decreasing diameters. We have three pillars:
(i) pi where the initial tower is, (ii) pf where the final tower shall be, and (iii) an auxiliary
pillar pa housing intermediate stacks of disks.

pi pa pf pi pa pf
(a) initial situation (b) final situation

Fig. 4.2 – Initial and final configurations for n = 6.

The following rules must be observed:

• we can move a single disk at a time thanks to the operation move(p1 , p2 ), where p1
designates the pillar from which the upper disk is extracted and p2 the pillar on top of
which this disk is placed,
• a disk can be placed either on an empty pillar or over a larger disk.

An example of initial and final configurations is given in figure 4.2, for n = 6. We will
build a solution to move any tower of n disks (n ⩾ 1) according to the inductive schema
hereafter.

Base We know how to move a tower made of a single disk from a pillar to an empty one.
Induction hypothesis We assume that we know how to move a tower of (n−1) (n−1 ⩾ 1)
disks of decreasing diameters from a pillar to either an empty one or to a pillar housing
the largest disk using the auxiliary one which is initially empty.
Induction We show that we can move a tower made up of n disks of decreasing diameters
from pillar pi to pillar pf (initially empty) using the auxiliary pillar pa . To do this: (i) we
move the tower made of the (n − 1) upper disks from pi to pa (see figure 4.3, page 164),
which is feasible according to the induction hypothesis since the auxiliary pillar pa is
initially empty, (ii) then we move the last disk (the largest one) from pi to pf (see figure
4.4), which corresponds to an elementary move that can be made legally since the pillar
pf is empty, (iii) last we move the tower made of the (n − 1) disks on the pillar pa to

−→

pi pa pf pi pa pf

Fig. 4.3 – The first step of the inductive process of move of a tower of Hanoi.

i i

i i
i i

i i

“Reduce and conquer” and its complexity 165

−→

pi pa pf pi pa pf

Fig. 4.4 – The second step of the inductive process of move of a tower of Hanoi.

−→

pi pa pf pi pa pf

Fig. 4.5 – The last step of the inductive process of move of a tower of Hanoi.

the pillar pf (see figure 4.5), which is feasible according to the induction hypothesis,
noticing that, although nonempty, the arrival pillar pf contains the largest disk at its
base.

The following reduction model can be deduced:

hanoi(1, pi , pf , pa ) elementary
 (move(pi , pf ))

 hanoi(n − 1, pi , pa , pf )


+
hanoi(n, pi , pf , pa ) → move(pi , pf ) n > 1.



 +

hanoi(n − 1, pa , pf , pi )

Here, the generic function f consists in moving the largest disk from pi to pf . Choosing
the move of a disk as the elementary operation, we calculate nbMV(n), the number of
moves of disks necessary to move a tower of n disks. The number nbMV(n) is given by
the recurrence:

nbMV(1) = 1
nbMV(n) = 2 · nbMV(n − 1) + 1 n>1

whose solution is nbMV(n) = 2n − 1; so, complexity is exponential.

We now show that this solution is optimal. Let minnbMV(n) be the minimum number of
disk moves required for a tower of n disks. The largest disk must be moved at least once.
To be “legally” moved, this disk must be alone on its pillar and the destination pillar must
be empty; all other disks must be placed, in right order, on the third pillar. Therefore, before

i i

i i
i i

i i

166 Reduce and conquer, recursion

the first move of the largest disk, a tower of size (n − 1) would have had to be moved. It is
the same after the last move of this disk. Thus, we have:

minnbMV(n) ⩾ 2 · minnbMV(n − 1) + 1.

Since the algorithm designed before yields a number of moves which meets:

nbMV(n) = 2 · nbMV(n − 1) + 1,

this algorithm is optimal.

4.4 What should be reminded for “Reduce and conquer”


Resolving a problem of size n by the approach “Reduce and conquer” first requires to
express it (in the general case) as the combination of several sub-problems of the same
nature than the initial problem, of size (n − 1). For the size 0 or 1, the problem must have
a direct solution, i.e. which does not call on sub-problems. In the pattern of resolution
thus identified, an additional function appears whose goal is both to generate the sub-
problems and to specify how the results of the sub-problems are combined to form that
of the initial problem. The proof of correctness of the schema of resolution envisaged is
made by induction. The base is the resolution of the case having a direct solution and
the induction hypothesis assumes that it is known how to resolve the sub-problem of size
(n − 1). Then, the temporal complexity of the associated algorithm can be established (it
may be linear, polynomial or even exponential) and the algorithm can be written in the
form of a recursive procedure modeled on the resolution pattern.

4.5 Problems
Problem 44. A doubly recursive function ◦ •

This problem focuses on recursion. Its interest lies in the way the termination of the considered
recursive procedure is proven.

We consider the function Calc whose code has been given at the beginning of this chap-
ter. We will show that this function delivers the value 91 for any call parameter value
strictly less than 102.
44 - Q 1 Question 1. Establish that Calc(100) = Calc(101) = 91.
44 - Q 2 Question 2. Prove by induction (simple induction over k ∈ N) that, for any n in the
interval (90 − 11k) .. (100 − 11k), the call Calc(n) returns the value 91.
44 - Q 3 Question 3. What can be concluded about the termination of this function?
The solution is on page 174.

i i

i i
i i

i i

Problems 167

Problem 45. Fibonacci sequence; recursive computation ◦ •

This problem aims mainly at the illustration of the soundness of a non-recursive implementa-
tion of a value defined by a recurrence relation.

We denote by F(n) the current term of the Fibonacci series defined for n strictly posi-
tive. By definition:

F(1) = 1
F(2) = 1
F(n) = F(n − 1) + F(n − 2) n ⩾ 2.

Question 1. Write the recursive function FiboR(n) modeled on this recursive definition 45 - Q 1
to compute F(n).
Question 2. Give the total number of additions performed for n = 6. 45 - Q 2

Question 3. Calculate the number of additions generated by the call FiboR(n). 45 - Q 3

The solution is on page 175.

Problem 46. Is this point inside the polygon? ◦ •

This problem takes place in the framework of the Euclidian geometry. It presents no significant
difficulties, except that the value associated with the base of the inductive reasoning used, is
neither 0 nor 1, cases announced as “regular” in the presentation of this chapter.

We want to determine whether or not a point is inside (broadly speaking) a convex


n-sided polygon (n ⩾ 3). A Cartesian coordinate system xOy of the plane is considered.
Question 1. Given two points A and B of coordinates (xA , yA ) and (xB , yB ), give the 46 - Q 1
principle of the Boolean function of header:

SameSide(xA , yA , xB , yB , xC , yC , xD , yD ) result B

deciding whether or not points C and D of coordinates (xC , yC ) and (xD , yD ), are located
on the same side of the line (AB). What is its complexity in terms of evaluated conditions?
Question 2. State an inclusion property of a point in an triangle and write the function: 46 - Q 2

InTriangle(xA , yA , xB , yB , xC , yC , xP , yP ) result B

deciding whether or not the point P of coordinates (xP , yP ) is inside (broadly speaking)
the triangle (ABC). What is its complexity in terms of evaluated conditions?
Question 3. Derive a function of type “Reduce and conquer”: 46 - Q 3

InPolygon(n, xP , yP ) result B

i i

i i
i i

i i

168 Reduce and conquer, recursion

deciding whether or not the point P is inside the convex polygon of n vertices of coordi-
nates (x1 , y1 ), (x2 , y2 ), . . ., (xn , yn ) with n ⩾ 3.
46 - Q 4 Question 4. Give its temporal complexity at worst in terms of evaluated conditions.
46 - Q 5 Question 5. Why does polygon convexity matter?
The solution is on page 176.

Problem 47. Drawing nested double squares ◦ •


The main interest of this problem lies in the design of the trace to be done, especially the
identification of its starting point.

We want to make the drawing presented in figure 4.6, inside which the base pattern is
made of two nested squares. We are provided with the two usual primitives place(x, y) and
draw(x, y) of example 4.3.2 page 162, and the drawing must be done under the following
constraints: