100% found this document useful (1 vote)
15 views59 pages

Competitive Programming in Python: 128 Algorithms to Develop your Coding Skills 1st Edition Christoph Dürr download

The document is about the book 'Competitive Programming in Python' by Christoph Dürr and Jill-Jênn Vie, which covers 128 algorithms essential for developing coding skills. It provides insights into algorithmic techniques, problem-solving frameworks, and includes Python code examples. The authors are experienced researchers and coaches in competitive programming, aiming to help readers excel in coding competitions and technical job interviews.

Uploaded by

ahtovxkdvg626
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 (1 vote)
15 views59 pages

Competitive Programming in Python: 128 Algorithms to Develop your Coding Skills 1st Edition Christoph Dürr download

The document is about the book 'Competitive Programming in Python' by Christoph Dürr and Jill-Jênn Vie, which covers 128 algorithms essential for developing coding skills. It provides insights into algorithmic techniques, problem-solving frameworks, and includes Python code examples. The authors are experienced researchers and coaches in competitive programming, aiming to help readers excel in coding competitions and technical job interviews.

Uploaded by

ahtovxkdvg626
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/ 59

Competitive Programming in Python: 128

Algorithms to Develop your Coding Skills 1st


Edition Christoph Dürr download

https://textbookfull.com/product/competitive-programming-in-
python-128-algorithms-to-develop-your-coding-skills-1st-edition-
christoph-durr/

Download full version ebook from https://textbookfull.com


We believe these products will be a great fit for you. Click
the link to download now, or visit textbookfull.com
to discover even more!

Algorithmic Thinking. Learn Algorithms...Your Coding


Skills 2ed 2024 Zingaro D.

https://textbookfull.com/product/algorithmic-thinking-learn-
algorithms-your-coding-skills-2ed-2024-zingaro-d/

Good Habits for Great Coding: Improving Programming


Skills with Examples in Python Michael Stueben

https://textbookfull.com/product/good-habits-for-great-coding-
improving-programming-skills-with-examples-in-python-michael-
stueben/

Good Habits for Great Coding: Improving Programming


Skills with Examples in Python 1st Edition Michael
Stueben

https://textbookfull.com/product/good-habits-for-great-coding-
improving-programming-skills-with-examples-in-python-1st-edition-
michael-stueben/

Algorithms For Competitive Programming 1st Edition


David Esparza Alba

https://textbookfull.com/product/algorithms-for-competitive-
programming-1st-edition-david-esparza-alba/
Basic Exercises for Competitive Programming Python 1st
Edition Jan Pol

https://textbookfull.com/product/basic-exercises-for-competitive-
programming-python-1st-edition-jan-pol/

Python Programming For Beginners: Python Mastery in 7


Days: Top-Secret Coding Tips with Hands-On Exercises
for Your Dream Job 1st Edition Oswald Thornton

https://textbookfull.com/product/python-programming-for-
beginners-python-mastery-in-7-days-top-secret-coding-tips-with-
hands-on-exercises-for-your-dream-job-1st-edition-oswald-
thornton/

Guide to Competitive Programming: Learning and


Improving Algorithms Through Contests (Undergraduate
Topics in Computer Science) Antti Laaksonen

https://textbookfull.com/product/guide-to-competitive-
programming-learning-and-improving-algorithms-through-contests-
undergraduate-topics-in-computer-science-antti-laaksonen/

Python: 3 books in 1: Beginner’s guide, Data science


and Machine learning. The easiest guide to start Python
programming. Unlock your programmer potential and
develop your project in just 30 days First Edition
William Dimick
https://textbookfull.com/product/python-3-books-in-1-beginners-
guide-data-science-and-machine-learning-the-easiest-guide-to-
start-python-programming-unlock-your-programmer-potential-and-
develop-your-project-in-just-30-d/

Coding Games in Python 1st Edition Carol Vorderman

https://textbookfull.com/product/coding-games-in-python-1st-
edition-carol-vorderman/
Competitive Programming in Python

Want to kill it at your job interview in the tech industry? Want to win that coding
competition? Learn all the algorithmic techniques and programming skills you need
from two experienced coaches, problem-setters, and judges for coding competitions.
The authors highlight the versatility of each algorithm by considering a variety of
problems and show how to implement algorithms in simple and efficient code. What
to expect:
* Master 128 algorithms in Python.
* Discover the right way to tackle a problem and quickly implement a solution of low
complexity.
* Understand classic problems like Dijkstra’s shortest path algorithm and
Knuth–Morris–Pratt’s string matching algorithm, plus lesser-known data structures
like Fenwick trees and Knuth’s dancing links.
* Develop a framework to tackle algorithmic problem solving, including: Definition,
Complexity, Applications, Algorithm, Key Information, Implementation, Variants,
In Practice, and Problems.
* Python code included in the book and on the companion website.

Christoph Dürr is a senior researcher at the French National Center for Scientific
Research (CNRS), affiliated with the Sorbonne University in Paris. After a PhD in
1996 at Paris-Sud University, he worked for one year as a postdoctoral researcher at
the International Computer Science Institute in Berkeley and one year in the School
of Computer Science and Engineering in the Hebrew University of Jerusalem in
Israel. He has worked in the fields of quantum computation, discrete tomography and
algorithmic game theory, and his current research activity focuses on algorithms and
optimisation. From 2007 to 2014, he taught a preparation course for programming
contests at the engineering school École Polytechnique, and acts regularly as a
problem setter, trainer, or competitor for various coding competitions. In addition, he
loves carrot cake.

Jill-Jênn Vie is a research scientist at Inria in machine learning. He is an alumnus


from École normale supérieure Paris-Saclay, where he founded the algorithmic club
of Paris-Saclay (CAPS) and coached several teams for the International Collegiate
Programming Contest (ICPC). He published a book in theoretical computer science
to help students prepare for prestigious French competitive exams such as Grandes
Écoles or agrégation, and directed a television show “Blame the Algorithm” about
the algorithms that govern our lives. He is part of the advisory board of the French
Computer Science Society (SIF), itself a member of the International Federation for
Information Processing (IFIP).
Competitive Programming
in Python
128 Algorithms to Develop Your Coding Skills

CHRISTOPH DÜRR
CNRS, Sorbonne University

JILL-JÊNN VIE
Inria

Translated by Greg Gibbons and Danièle Gibbons


University Printing House, Cambridge CB2 8BS, United Kingdom
One Liberty Plaza, 20th Floor, New York, NY 10006, USA
477 Williamstown Road, Port Melbourne, VIC 3207, Australia
314–321, 3rd Floor, Plot 3, Splendor Forum, Jasola District Centre, New Delhi – 110025, India
79 Anson Road, #06–04/06, Singapore 079906

Cambridge University Press is part of the University of Cambridge.


It furthers the University’s mission by disseminating knowledge in the pursuit of
education, learning, and research at the highest international levels of excellence.

www.cambridge.org
Information on this title: www.cambridge.org/9781108716826
DOI: 10.1017/9781108591928
© Cambridge University Press 2021
Translation from the French language edition:
Programmation efficace - 128 algorithmes qu’il faut avoir compris et codés en Python au cour de sa vie
By Christoph Dürr & Jill-Jênn Vie
Copyright © 2016 Edition Marketing S.A.
www.editions-ellipses.fr
All Rights Reserved
This publication is in copyright. Subject to statutory exception
and to the provisions of relevant collective licensing agreements,
no reproduction of any part may take place without the written
permission of Cambridge University Press.
First published 2021
Printed in the United Kingdom by TJ Books Limited, Padstow Cornwall
A catalogue record for this publication is available from the British Library.
Library of Congress Cataloging-in-Publication Data
Names: Dürr, Christoph, 1969– author. | Vie, Jill-Jênn, 1990– author. |
Gibbons, Greg, translator. | Gibbons, Danièle, translator.
Title: Competitive programming in Python : 128 algorithms to develop your
coding skills / Christoph Dürr, Jill-Jênn Vie ; translated by Greg
Gibbons, Danièle Gibbons.
Other titles: Programmation efficace. English
Description: First edition. | New York : Cambridge University Press, 2020.
| Includes bibliographical references and index.
Identifiers: LCCN 2020022774 (print) | LCCN 2020022775 (ebook) |
ISBN 9781108716826 (paperback) | ISBN 9781108591928 (epub)
Subjects: LCSH: Python (Computer program language) | Algorithms.
Classification: LCC QA76.73.P98 D8713 2020 (print) | LCC QA76.73.P98
(ebook) | DDC 005.13/3–dc23
LC record available at https://lccn.loc.gov/2020022774
LC ebook record available at https://lccn.loc.gov/2020022775
ISBN 978-1-108-71682-6 Paperback
Cambridge University Press has no responsibility for the persistence or accuracy of
URLs for external or third-party internet websites referred to in this publication
and does not guarantee that any content on such websites is, or will remain,
accurate or appropriate.
Contents

Preface page ix

1 Introduction 1
1.1 Programming Competitions 1
1.2 Python in a Few Words 5
1.3 Input-Output 13
1.4 Complexity 17
1.5 Abstract Types and Essential Data Structures 20
1.6 Techniques 28
1.7 Advice 37
1.8 A Problem: ‘Frosting on the Cake’ 39

2 Character Strings 42
2.1 Anagrams 42
2.2 T9—Text on 9 Keys 43
2.3 Spell Checking with a Lexicographic Tree 46
2.4 Searching for Patterns 48
2.5 Maximal Boundaries—Knuth–Morris–Pratt 49
2.6 Pattern Matching—Rabin–Karp 56
2.7 Longest Palindrome of a String—Manacher 59

3 Sequences 62
3.1 Shortest Path in a Grid 62
3.2 The Levenshtein Edit Distance 63
3.3 Longest Common Subsequence 65
3.4 Longest Increasing Subsequence 68
3.5 Winning Strategy in a Two-Player Game 70

4 Arrays 72
4.1 Merge of Sorted Lists 73
4.2 Sum Over a Range 74
4.3 Duplicates in a Range 74
4.4 Maximum Subarray Sum 75
vi Contents

4.5 Query for the Minimum of a Range—Segment Tree 75


4.6 Query the Sum over a Range—Fenwick Tree 77
4.7 Windows with k Distinct Elements 80

5 Intervals 82
5.1 Interval Trees 82
5.2 Union of Intervals 85
5.3 The Interval Point Cover Problem 85

6 Graphs 88
6.1 Encoding in Python 88
6.2 Implicit Graphs 90
6.3 Depth-First Search—DFS 91
6.4 Breadth-First Search—BFS 93
6.5 Connected Components 94
6.6 Biconnected Components 97
6.7 Topological Sort 102
6.8 Strongly Connected Components 105
6.9 2-Satisfiability 110

7 Cycles in Graphs 113


7.1 Eulerian Tour 113
7.2 The Chinese Postman Problem 116
7.3 Cycles with Minimal Ratio of Weight to Length—Karp 117
7.4 Cycles with Minimal Cost-to-Time Ratio 120
7.5 Travelling Salesman 120
7.6 Full Example: Menu Tour 121

8 Shortest Paths 124


8.1 Composition Property 124
8.2 Graphs with Weights 0 or 1 126
8.3 Graphs with Non-negative Weights—Dijkstra 127
8.4 Graphs with Arbitrary Weights—Bellman–Ford 130
8.5 All Source–Destination paths—Floyd–Warshall 132
8.6 Grid 133
8.7 Variants 135

9 Matchings and Flows 138


9.1 Maximum Bipartite Matching 139
9.2 Maximal-Weight Perfect Matching—Kuhn–Munkres 145
9.3 Planar Matching without Crossings 151
9.4 Stable Marriages—Gale–Shapley 153
Contents vii

9.5 Maximum Flow by Ford–Fulkerson 155


9.6 Maximum Flow by Edmonds–Karp 158
9.7 Maximum Flow by Dinic 159
9.8 Minimum s − t Cut 162
9.9 s − t Minimum Cut for Planar Graphs 163
9.10 A Transport Problem 165
9.11 Reductions between Matchings and Flows 165
9.12 Width of a Partial Order—Dilworth 167

10 Trees 171
10.1 Huffman Coding 172
10.2 Lowest Common Ancestor 174
10.3 Longest Path in a Tree 178
10.4 Minimum Weight Spanning Tree—Kruskal 179

11 Sets 182
11.1 The Knapsack Problem 182
11.2 Making Change 184
11.3 Subset Sum 185
11.4 The k-sum Problem 187

12 Points and Polygons 189


12.1 Convex Hull 190
12.2 Measures of a Polygon 193
12.3 Closest Pair of Points 195
12.4 Simple Rectilinear Polygon 198

13 Rectangles 200
13.1 Forming Rectangles 200
13.2 Largest Square in a Grid 201
13.3 Largest Rectangle in a Histogram 202
13.4 Largest Rectangle in a Grid 204
13.5 Union of Rectangles 205
13.6 Union of Disjoint Rectangles 212

14 Numbers and Matrices 214


14.1 GCD 214
14.2 Bézout Coefficients 214
14.3 Binomial Coefficients 215
14.4 Fast Exponentiation 216
14.5 Prime Numbers 217
14.6 Evaluate an Arithmetical Expression 218
viii Contents

14.7 System of Linear Equations 221


14.8 Multiplication of a Matrix Sequence 225

15 Exhaustive Search 227


15.1 All Paths for a Laser 227
15.2 The Exact Cover Problem 231
15.3 Problems 237
15.4 Sudoku 238
15.5 Enumeration of Permutations 240
15.6 Le Compte est Bon 243

16 Conclusion 245
16.1 Combine Algorithms to Solve a Problem 245
16.2 For Further Reading 245
16.3 Rendez-vous on tryalgo.org 246

Debugging tool 247


References 248
Index 251
Preface

Algorithms play an important role in our society, solving numerous mathematical


problems which appear in a broad spectrum of situations. To give a few examples,
think of planning taxi routes given a set of reservations (see Section 9.12); assigning
students to schools in a large urban school district, such as New York (see Section
9.4); or identifying a bottleneck in a transportation network (see Section 9.8). This
is why job interviews in the IT (Information Technology) industry test candidates for
their problem-solving skills. Many programming contests are organised by companies
such as Google, Facebook and Microsoft to spot gifted candidates and then send
them job offers. This book will help students to develop a culture of algorithms and
data structures, so that they know how to apply them properly when faced with new
mathematical problems.
Designing the right algorithm to solve a given problem is only half of the work;
to complete the job, the algorithm needs to be implemented efficiently. This is why
this book also emphasises implementation issues, and provides full source code for
most of the algorithms presented. We have chosen Python for these implementations.
What makes this language so enticing is that it allows a particularly clear and refined
expression, illustrating the essential steps of the algorithm, without obscuring things
behind burdensome notations describing data structures. Surprisingly, it is actually
possible to re-read code written several months ago and even understand it!
We have collected here 128 algorithmic problems, indexed by theme rather than
by technique. Many are classic, whereas certain are atypical. This work should
prove itself useful when preparing to solve the wide variety of problems posed in
programming contests such as ICPC, Google Code Jam, Facebook Hacker Cup,
Prologin, France-ioi, etc. We hope that it could serve as a basis for an advanced
course in programming and algorithms, where even certain candidates for the
‘agrégation de mathématiques option informatique’ (French competitive exam for
the highest teacher’s certification) will find a few original developments. The website
tryalgo.org, maintained by the authors, contains links to the code of this book, as
well as to selected problems at various online contests. This allows readers to verify
their freshly acquired skills.
This book would never have seen the light of day without the support of the
authors’ life partners. Danke, Hương. Merci, 智子. The authors would also like to
thank the students of the École polytechnique and the École normale supérieure
of Paris-Saclay, whose practice, often nocturnal, generated a major portion of the
x Preface

material of this text. Thanks to all those who proofread the manuscript, especially
René Adad, Evripidis Bampis, Binh-Minh Bui-Xuan, Stéphane Henriot, Lê Thành
Dũng Nguyễn, Alexandre Nolin and Antoine Pietri. Thanks to all those who improved
the programs on GitHub: Louis Abraham, Lilian Besson, Ryan Lahfa, Olivier Marty,
Samuel Tardieu and Xavier Carcelle. One of the authors would especially like to thank
his past teacher at the Lycée Thiers, Monsieur Yves Lemaire, for having introduced
him to the admirable gem of Section 2.5 on page 52.
We hope that the reader will pass many long hours tackling algorithmic problems
that at first glance appear insurmountable, and in the end feel the profound joy when
a solution, especially an elegant solution, suddenly becomes apparent.
Finally, we would like to thank Danièle and Greg Gibbons for their translation of
this work, even of this very phrase.
Attention, it’s all systems go!
1 Introduction

You, my young friend, are going to learn to program the algorithms of this book,
and then go on to win programming contests, sparkle during your job interviews,
and finally roll up your sleeves, get to work, and greatly improve the gross national
product!

Mistakenly, computer scientists are still often considered the magicians of modern
times. Computers have slowly crept into our businesses, our homes and our machines,
and have become important enablers in the functioning of our world. However, there
are many that use these devices without really mastering them, and hence, they do not
fully enjoy their benefits. Knowing how to program provides the ability to fully exploit
their potential to solve problems in an efficient manner. Algorithms and programming
techniques have become a necessary background for many professions. Their mastery
allows the development of creative and efficient computer-based solutions to problems
encountered every day.
This text presents a variety of algorithmic techniques to solve a number of classic
problems. It describes practical situations where these problems arise, and presents
simple implementations written in the programming language Python. Correctly
implementing an algorithm is not always easy: there are numerous traps to avoid and
techniques to apply to guarantee the announced running times. The examples in the
text are embellished with explanations of important implementation details which
must be respected.
For the last several decades, programming competitions have sprung up at every
level all over the world, in order to promote a broad culture of algorithms. The prob-
lems proposed in these contests are often variants of classic algorithmic problems,
presented as frustrating enigmas that will never let you give up until you solve them!

1.1 Programming Competitions

In a programming competition, the candidates must solve several problems in a


fixed time. The problems are often variants of classic problems, such as those
addressed in this book, dressed up with a short story. The inputs to the problems
are called instances. An instance can be, for example, the adjacency matrix of a graph
for a shortest path problem. In general, a small example of an instance is provided,
along with its solution. The source code of a solution can be uploaded to a server via
2 Introduction

a web interface, where it is compiled and tested against instances hidden from the
public. For some problems the code is called for each instance, whereas for others the
input begins with an integer indicating the number of instances occurring in the input.
In the latter case, the program must then loop over each instance, solve it and display
the results. A submission is accepted if it gives correct results in a limited time, on the
order of a few seconds.

Figure 1.1 The logo of the ICPC nicely shows the steps in the resolution of a problem.
A helium balloon is presented to the team for each problem solved.

To give here a list of all the programming competitions and training sites is quite
impossible, and such a list would quickly become obsolete. Nevertheless, we will
review some of the most important ones.

ICPC The oldest of these competitions was founded by the Association for
Computing Machinery in 1977 and supported by them up until 2017. This
contest, known as the ICPC, for International Collegiate Programming Contest,
is organised in the form of a tournament. The starting point is one of the regional
competitions, such as the South-West European Regional Contest (SWERC),
where the two best teams qualify for the worldwide final. The particularity of
this contest is that each three-person team has only a single computer at their
disposal. They have only 5 hours to solve a maximum number of problems
among the 10 proposed. The first ranking criterion is the number of submitted
solutions accepted (i.e. tested successfully against a set of unknown instances).
The next criterion is the sum over the submitted problems of the time between
the start of the contest and the moment of the accepted submission. For each
erroneous submission, a penalty of 20 minutes is added.
There are several competing theories on what the ideal composition of a
team is. In general, a good programmer and someone familiar with algorithms
is required, along with a specialist in different domains such as graph theory,
dynamic programming, etc. And, of course, the team members need to get along
together, even in stressful situations!
For the contest, each team can bring 25 pages of reference code printed in an
8-point font. They can also access the online documentation of the Java API and
the C++ standard library.
Google Code Jam In contrast with the ICPC contest, which is limited to students
up to a Master’s level, the Google Code Jam is open to everyone. This more
recent annual competition is for individual contestants. Each problem comes in
1.1 Programming Competitions 3

general with a deck of small instances whose resolution wins a few points, and
a set of enormous instances for which it is truly important to find a solution
with the appropriate algorithmic complexity. The contestants are informed of
the acceptance of their solution for the large instances only at the end of the
contest. However, its true strong point is the possibility to access the solutions
submitted by all of the participants, which is extremely instructive.
The competition Facebook Hacker Cup is of a similar nature.
Prologin The French association Prologin organises each year a competition
targeted at students up to twenty years old. Their capability to solve algorithmic
problems is put to test in three stages: an online selection, then regional
competitions and concluding with a national final. The final is atypically an
endurance test of 36 hours, during which the participants are confronted with a
problem in Artificial Intelligence. Each candidate must program a “champion”
to play a game whose rules are defined by the organisers. At the end of the
day, the champions are thrown in the ring against each other in a tournament to
determine the final winner.
The website https://prologin.org includes complete archives of past
problems, with the ability to submit algorithms online to test the solutions.
France-IOI Each year, the organisation France-IOI prepares junior and senior
high school students for the International Olympiad in Informatics. Since
2011, they have organised the ‘Castor Informatique’ competition, addressed at
students from Grade 4 to Grade 12 (675,000 participants in 2018). Their website
http://france-ioi.org hosts a large number of algorithmic problems (more
than 1,000).

Numerous programming contests organised with the goal of selecting candidates


for job offers also exist. The web site www.topcoder.com, for example, also includes
tutorials on algorithms, often very well written.
For training, we particularly recommend https://codeforces.com, a well-
respected web site in the community of programming competitions, as it proposes
clear and well-prepared problems.

1.1.1 Training Sites


A number of websites propose problems taken from the annals of competitions, with
the possibility to test solutions as a training exercise. This is notably the case for
Google Code Jam and Prologin (in French). The collections of the annals of the ICPC
contests can be found in various locations.
Traditional online judges The following sites contain, among others, many
problems derived from the ICPC contests.
uva http://uva.onlinejudge.org
icpcarchive http://icpcarchive.ecs.baylor.edu, http://livearchive
.onlinejudge.org
4 Introduction

Chinese online judges Several training sites now exist in China. They tend to
have a purer and more refined interface than the traditional judges. Nevertheless,
sporadic failures have been observed.
poj http://poj.org
tju http://acm.tju.edu.cn (Shut down since 2017)
zju http://acm.zju.edu.cn
Modern online judges Sphere Online Judge http://spoj.com and Kattis
http://open.kattis.com have the advantage of accepting the submission
of solutions in a variety of languages, including Python.
spoj http://spoj.com
kattis http://open.kattis.com
zju http://acm.zju.edu.cn
Other sites
codechef http://codechef.com
codility http://codility.com
gcj http://code.google.com/codejam
prologin http://prologin.org
slpc http://cs.stanford.edu/group/acm
Throughout this text, problems are proposed at the end of each section in rela-
tion to the topic presented. They are accompanied with their identifiers to a judge
site; for example [spoj:CMPLS] refers to the problem ‘Complete the Sequence!’ at
the URL www.spoj.com/problems/CMPLS/. The site http://tryalgo.org contains
links to all of these problems. The reader thus has the possibility to put into practice
the algorithms described in this book, testing an implementation against an online
judge.
The languages used for programming competitions are principally C++ and Java.
The SPOJ judge also accepts Python, while the Google Code Jam contest accepts
many of the most common languages. To compensate for the differences in execution
speed due to the choice of language, the online judges generally adapt the time limit
to the language used. However, this adaptation is not always done carefully, and it is
sometimes difficult to have a solution in Python accepted, even if it is correctly written.
We hope that this situation will be improved in the years to come. Also, certain judges
work with an ancient version of Java, in which such useful classes as Scanner are
not available.

1.1.2 Responses of the Judges


When some code for a problem is submitted to an online judge, it is evaluated via a set
of private tests and a particularly succinct response is returned. The principal response
codes are the following:
1.2 Python in a Few Words 5

Accepted Your program provides the correct output in the allotted time. Congrat-
ulations!
Presentation Error Your program is almost accepted, but the output contains
extraneous or missing blanks or end-of-lines. This message occurs rarely.
Compilation Error The compilation of your program generates errors. Often,
clicking on this message will provide the nature of the error. Be sure to compare
the version of the compiler used by the judge with your own.
Wrong Answer Re-read the problem statement, a detail must have been over-
looked. Are you sure to have tested all the limit cases? Might you have left
debugging statements in your code?
Time Limit Exceeded You have probably not implemented the most efficient
algorithm for this problem, or perhaps have an infinite loop somewhere. Test
your loop invariants to ensure loop termination. Generate a large input instance
and test locally the performance of your code.
Runtime Error In general, this could be a division by zero, an access beyond the
limits of an array, or a pop() on an empty stack. However, other situations can
also generate this message, such as the use of assert in Java, which is often not
accepted.
The taciturn behaviour of the judges nevertheless allows certain information to be
gleaned from the instances. Here is a trick that was used during an ICPC / SWERC
contest. In a problem concerning graphs, the statement indicated that the input con-
sisted of connected graphs. One of the teams doubted this, and wrote a connectivity
test. In the positive case, the program entered into an infinite loop, while in the negative
case, it caused a division by zero. The error code generated by the judge (Time Limit
Exceeded ou Runtime Error) allowed the team to detect that certain graphs in the input
were not connected.

1.2 Python in a Few Words

The programming language Python was chosen for this book, for its readability and
ease of use. In September 2017, Python was identified by the website https://
stackoverflow.com as the programming language with the greatest growth in high-
income countries, in terms of the number of questions seen on the website, notably
thanks to the popularity of machine learning.1 Python is also the language retained
for such important projects as the formal calculation system SageMath, whose critical
portions are nonetheless implemented in more efficient languages such as C++ or C.
Here are a few details on this language. This chapter is a short introduction to
Python and does not claim to be exhaustive or very formal. For the neophyte reader
we recommend the site python.org, which contains a high-quality introduction as
well as exceptional documentation. A reader already familiar with Python can profit

1 https://stackoverflow.blog/2017/09/06/incredible-growth-python/
6 Introduction

enormously by studying the programs of David Eppstein, which are very elegant and
highly readable. Search for the keywords Eppstein PADS.
Python is an interpreted language. Variable types do not have to be declared, they
are simply inferred at the time of assignment. There are neither keywords begin/end
nor brackets to group instructions, for example in the blocks of a function or a loop.
The organisation in blocks is simply based on indentation! A typical error, difficult
to identify, is an erroneous indentation due to spaces used in some lines and tabs
in others.

Basic Data Types


In Python, essentially four basic data types exist: Booleans, integers, floating-point
numbers and character strings. In contrast with most other programming languages,
the integers are not limited to a fixed number of bits (typically 64), but use an arbi-
trary precision representation. The functions—more precisely the constructors: bool,
int, float, str—allow the conversion of an object to one of these basic types. For
example, to access the digits of a specific integer given its decimal representation,
it can be first transformed into a string, and then the characters of the string can be
accessed. However, in contrast with languages such as C, it is not possible to directly
modify a character of a string: strings are immutable. It is first necessary to convert to
a list representation of the characters; see below.

Data Structures
The principal complex data structures are dictionaries, sets, lists and n-tuples. These
structures are called containers, as they contain several objects in a structured manner.
Once again, there are functions dict, set, list and tuple that allow the conversion of
an object into one of these structures. For example, for a string s, the function list(s)
returns a list L composed of the characters of the string. We could then, for example,
replace certain elements of the list L and then recreate a string by concatenating the ele-
ments of L with the expression ‘’.join(L). Here, the empty string could be replaced
by a separator: for example, ‘-’.join([’A’,’B’,’C’]) returns the string “A-B-C”.

1.2.1 Manipulation of Lists, n-tuples, Dictionaries


Note that lists in Python are not linked lists of cells, each with a pointer to its successor
in the list, as is the case in many other languages. Instead, lists are arrays of elements
that can be accessed and modified using their index into the array. A list is written by
enumerating its elements between square brackets [ and ], with the elements separated
by commas.

Lists The indices of a list start with 0. The last element can also be accessed with
the index −1, the second last with −2 and so on. Here are some examples of
operations to extract elements or sublists of a list. This mechanism is known as
slicing, and is also available for strings.
1.2 Python in a Few Words 7

The following expressions have a complexity linear in the length of L, with


the exception of the first, which is in constant time.
L[i] the ith element of L
L[i:j] the list of elements with indices starting at i and up to
(but not including) j
L[:j] the first j elements
L[i:] all the elements from the ith onwards
L[-3:] the last three elements of L
L[i:j:k] elements from the ith up to (but not including) the jth,
taking only every kth element
L[::2] the elements of L with even indices
L[::-1] a reverse copy of L
The most important methods of a list for our usage are listed below. Their
complexity is expressed in terms of n, the length of the list L. A function has
constant amortised complexity if, for several successive calls to it, the average
complexity is constant, even if some of these calls take a time linear in n.
len(L) returns the number of elements of the list L O(1)
sorted(L) returns a sorted copy of the list L O(n log n)
L.sort() sorts L in place O(n log n)
L.count(c) the number of occurrences of c in L O(n)
c in L is the element c found in L? O(n)
L.append(c) append c to the end of L amortised O(1)
L.pop() extracts and returns the last element of L amortised O(1)
Thus a list has all the functionality of a stack, defined in Section 1.5.1 on
page 20.
n-tuple An n-tuple behaves much like a list, with a difference in the usage
of parentheses to describe it, as in (1, 2) or (left, ’X’, right). A 1-tuple,
composed of only one element, requires the usage of a comma, as in (2,).
A 0-tuple, empty, can be written as (), or as tuple(), no doubt more readable.
The main difference with lists is that n-tuples are immutable, just like strings.
This is why an n-tuple can serve as a key in a dictionary.
Dictionaries Dictionaries are used to associate objects with values, for example
the words of a text with their frequency. A dictionary is constructed as
comma-separated key:value pairs between curly brackets, such as {’the’: 4,
’bread’: 1, ’is’: 6}, where the keys and values are separated by a colon.
An empty dictionary is obtained with {}. A membership test of a key x in a
dictionary dic is written x in dic. Behind a dictionary there is a hash table,
hence the complexity of the expressions x in dic, dic[x], dic[x] = 42
is in practice constant time, even if the worst-case complexity is linear,
a case obtained in the improbable event of all keys having the same hash
value.
If the keys of a dictionary are all the integers between 0 and n − 1, the use of
a list is much more efficient.
8 Introduction

A loop in Python is written either with the keyword for or with while. The nota-
tion for the loop for is for x in S:, where the variable x successively takes on the
values of the container S, or of the keys of S in the case of a dictionary. In contrast,
while L: will loop as long as the list L is non-empty. Here, an implicit conversion of
a list to a Boolean is made, with the convention that only the empty list converts to
False.
At times, it is necessary to handle at the same time the values of a list along with
their positions (indices) within the list. This can be implemented as follows:

for index in range(len(L)):


value = L[index]
# ... handling of index and value

The function enumerate allows a more compact expression of this loop:

for index, value in enumerate(L):


# ... handling of index and value

For a dictionary, the following loop iterates simultaneously over the keys and
values:

for key, value in dic.items():


# ... handling of key and value

1.2.2 Specificities: List and Dictionary Comprehension, Iterators


List and Dictionary Comprehension
The language Python provides a syntax close to the notation used in mathematics for
certain objects. To describe the list of squares from 0 to n2 , it is possible to use a list
comprehension:

>>> n = 5
>>> squared_numbers = [x ** 2 for x in range(n + 1)]
>>> squared_numbers
[0, 1, 4, 9, 16, 25]

which corresponds to the set {x 2 |x = 0, . . . ,n} in mathematics.


This is particularly useful to initialise a list of length n:

>>> t = [0 for _ in range(n)]


>>> t
[0, 0, 0, 0, 0]
1.2 Python in a Few Words 9

or to initialise counters for the letters in a string:

>>> my_string = "cowboy bebop"


>>> nb_occurrences = {letter: 0 for letter in my_string}
>>> nb_occurrences
{’c’: 0, ’o’: 0, ’w’: 0, ’b’: 0, ’y’: 0, ’ ’: 0, ’e’: 0, ’p’: 0}

The second line, a dictionary comprehension, is equivalent to the following:

nb_occurrences = {}
for letter in my_string:
nb_occurrences[letter] = 0

Ranges and Other Iterators


To loop over ranges of integers, the code for i in range(n): can be used to run over
the integers from 0 to n − 1. Several variants exist:

range(k, n) from k to n − 1
range(k, n, 2) from k to n − 1 two by two
range(n - 1, -1, -1) from n − 1 to 0 (−1 excluded) in decreasing order.

In early versions of Python, range returned a list. Nowadays, for efficiency, it


returns an object known as an iterator, which produces integers one by one, if and
when the for loop claims a value. Any function can serve as an iterator, as long
as it can produce elements at different moments of its execution using the keyword
yield. For example, the following function iterates over all pairs of elements of a
given list:.

def all_pairs(L):
n = len(L)
for i in range(n):
for j in range(i + 1, n):
yield (L[i], L[j])

1.2.3 Useful Modules and Packages


Modules
Certain Python objects must be imported from a module or a package with the
command import. A package is a collection of modules. Two methods can be used;
the second avoids potential naming collisions between the methods in different
modules:
10 Introduction

>>> from math import sqrt


>>> sqrt(4)
2
>>> import math
>>> math.sqrt(4)
2

math This module contains mathematical functions and constants such as log,
sqrt, pi, etc. Python operates on integers with arbitrary precision, thus there
is no limit on their size. As a consequence, there is no integer equivalent to
represent −∞ or +∞. For floating point numbers on the other hand, float(’-
inf’) and float(’inf’) can be used. Beginning with Python 3.5, math.inf (or
from math import inf) is equivalent to float(’inf’).
fractions This module exports the class Fraction, which allows computations
with fractions without the loss of precision of floating point calculations. For
example, if f is an instance of the class Fraction, then str(f) returns a string
similar to the form “3/2”, expressing f as an irreducible fraction.
bisect Provides binary (dichotomous) search functions on a sorted list.
heapq Provides functions to manipulate a list as a heap, thus allowing an element
to be added or the smallest element removed in time logarithmic in the size of
the heap; see Section 1.5.4 on page 22.
string This module provides, for example, the function ascii_lowercase, which
returns its argument converted to lowercase characters. Note that the strings
themselves already provide numerous useful methods, such as strip, which
removes whitespace from the beginning and end of a string and returns the
result, lower, which converts all the characters to lowercase, and especially
split, which detects the substrings separated by spaces (or by another separa-
tor passed as an argument). For example, “12/OCT/2018”.split(“/”) returns
[“12”, “OCT”, “2018”].

Packages
One of the strengths of Python is the existence of a large variety of code packages.
Some are part of the standard installation of the language, while others must be
imported with the shell command pip. They are indexed and documented at the web
site pypi.org. Here is a non-exhaustive list of very useful packages.

tryalgo All the code of the present book is available in a package called tryalgo
and can be imported in the following manner: pip install tryalgo.

>>> import tryalgo


>>> help(tryalgo) # for the list of modules
>>> help(tryalgo.arithm) # for a particular module

collections To simplify life, the class from collections import Counter can
be used. For an object c of this class, the expression c[x] will return 0 if x is not
1.2 Python in a Few Words 11

a key in c. Only modification of the value associated with x will create an entry
in c, such as, for example, when executing the instruction c[x] += 1. This is
thus slightly more practical than a dictionary, as is illustrated below.

>>> c = {} # dictionary
>>> c[’a’] += 1 # the key does not exist
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ’a’
>>> c[’a’] = 1
>>> c[’a’] += 1 # now it does
>>> c
{’a’: 2}
>>> from collections import Counter
>>> c = Counter()
>>> c[’a’] += 1 # the key does not exist, so it is created
Counter({’a’: 1})
>>> c = Counter(’cowboy bebop’)
Counter({’o’: 3, ’b’: 3, ’c’: 1, ’w’: 1, ’y’: 1, ’ ’: 1, ’e’: 1, ’p’: 1})

The collections package also provides the class deque, for double-ended
queue, see Section 1.5.3 on page 21. With this structure, elements can be added
or removed either from the left (head) or from the right (tail) of the queue. This
helps implement Dijkstra’s algorithm in the case where the edges have only
weights 0 or 1, see Section 8.2 on page 126.
This package also provides the class defaultdict, which is a dictionary that
assigns default values to keys that are yet in the dictionary, hence a generalisa-
tion of the class Counter.

>>> from collections import defaultdict


>>> g = defaultdict(list)
>>> g[’paris’].append(’marseille’) # ’paris’ key is created on the fly
>>> g[’paris’].append(’lyon’)
>>> g
defaultdict(<class ’list’>, {’paris’: [’marseille’, ’lyon’]})
>>> g[’paris’] # behaves like a dict
[’marseille’, ’lyon’]

See also Section 1.3 on page 13 for an example of reading a graph given as
input.
numpy This package provides general tools for numerical calculations involving
manipulations of large matrices. For example, numpy.linalg.solve solves
a linear system, while numpy.fft.fft calculates a (fast) discrete Fourier
transform.

While writing the code of this book, we have followed the norm PEP8, which
provides precise recommendations on the usage of blanks, the choice of names for
variables, etc. We advise the readers to also follow these indications, using, for exam-
ple, the tool pycodestyle to validate the structure of their code.
12 Introduction

1.2.4 Interpreters Python, PyPy, and PyPy3


We have chosen to implement our algorithms in Python 3, which is already over
12 years old,2 while ensuring backwards compatibility with Python 2. The principal
changes affecting the code appearing in this text concern print and division between
integers. In Python 3, 5 / 2 is equal to 2.5, whereas it gives 2 in Python 2. The integer
division operator // gives the same result for both versions. As for print, in Python 2
it is a keyword, whereas in Python 3 it is a function, and hence requires the parameters
to be enclosed by parentheses.
The interpreter of reference is CPython, and its executable is just called python.
According to your installation, the interpreter of Python 3 could be called python or
python3. Another much more efficient interpreter is PyPy, whose executable is called
pypy in version 2 and pypy3 in version 3. It implements a subset of the Python
language, called RPython, with quite minimal restrictions, which essentially allow the
inference of the type of a variable by an analysis of the source code. The inconvenience
is that pypy is still under development and certain modules are not yet available. But
it can save your life during a contest with time limits!

1.2.5 Frequent Errors


Copy
An error often made by beginners in Python concerns the copying of lists. In the
following example, the list B is in fact just a reference to A. Thus a modification of
B[0] results also in a modification of A[0].

A = [1, 2, 3]
B = A # Beware! Both variables refer to the same object

For B to be a distinct copy of A, the following syntax should be used:

A = [1, 2, 3]
B = A[:] # B becomes a distinct copy of A

The notation [:] can be used to make a copy of a list. It is also possible to make a
copy of all but the first element, A[1 :], or all but the last element, A[: −1], or even
in reverse order A[:: −1]. For example, the following code creates a matrix M, all of
whose rows are the same, and the modification of M[0][0] modifies the whole of the
first column of M.

M = [[0] * 10] * 10 # Do not write this!

2 Python 3.0 final was released on 3 December, 2008.


1.3 Input-Output 13

A square matrix can be correctly initialised using one of the following expressions:

M1 = [[0] * 10 for _ in range(10)]


M2 = [[0 for j in range(10)] for i in range(10)]

The module numpy permits easy manipulations of matrices; however, we have cho-
sen not to profit from it in this text, in order to have generic code that is easy to translate
to Java or C++.

Ranges
Another typical error concerns the use of the function range. For example, the follow-
ing code processes the elements of a list A between the indices 0 and 9 inclusive, in
order.

for i in range(0, 10): # 0 included, 10 excluded


process(A[i])

To process the elements in descending order, it is not sufficient to just swap the
arguments. In fact, range(10, 0, -1)—the third argument indicates the step—is the
list of elements with indices 10 (included) to 0 (excluded). Thus the loop must be
written as:

for i in range(9, -1, -1): # 9 included, -1 excluded


process(A[i])

1.3 Input-Output

1.3.1 Read the Standard Input


For most problems posed by programming contests, the input data are read from
standard input, and the responses displayed on standard output. For example, if the
input file is called test.in, and your program is prog.py, the contents of the input
file can be directed to your program with the following command, launched from a
command window:

python prog.py < test.in

In general, under Mac OS X, a command window can be obtained


by typing Command-Space Terminal, and under Windows, via
>_
Start → Run → cmd.
If you are running Linux, the keyboard shortcut is generally Alt-
F2, but that you probably already knew. . .
14 Introduction

If you wish to save the output of your program to a file called test.out, type:

python prog.py < test.in > test.out

A little hint: if you want to display the output at the same time as it is being written
to a file test.out, use the following (the command tee is not present by default in
Windows):

python prog.py < test.in | tee test.out

The inputs can be read line by line via the command input(), which returns the
next input line in the form of a string, excluding the end-of-line characters.3 The
module sys contains a similar function stdin.readline(), which does not suppress
the end-of-line characters, but according to our experience has the advantage of being
four times as fast!
If the input line is meant to contain an integer, we can convert the string with the
function int (if it is a floating point number, then we must use float instead). In
the case of a line containing several integers separated by spaces, the string can first be
cut into different substrings using split(); these can then be converted into integers
with the method map. For example, in the case of two integers height and width to be
read on the same line, separated by a space, the following command suffices:

import sys

height, width = map(int, sys.stdin.readline().split())

If your program exhibits performance problems while reading the inputs, our expe-
rience shows that a factor of two can be gained by reading the whole of the inputs with
a single system call. The following code fragment assumes that the inputs are made
up of only integers, eventually on multiple lines. The parameter 0 in the function
os.read means that the read is from standard input, and the constant M must be an
upper bound on the size of the file. For example, if the file contains 107 integers,
each between 0 and 109 , then as each integer is written with at most 10 characters
and there are at most 2 characters separating the integers (\n and \r), we can choose
M = 12 · 107 .

3 According to the operating system, the end-of-line is indicated by the characters \r, \n, or both, but this
is not important when reading with input(). Note that in Python 2 the behaviour of input() is
different, so it is necessary to use the equivalent function raw_input().
1.3 Input-Output 15

import os

instance = list(map(int, os.read(0, M).split()))

Example – Read a Graph on Input


If the inputs are given in the form:

3
paris tokyo 9471
paris new-york 5545
new-york singapore 15344

where 3 is the number of edges of a graph and each edge is represented by


<departure> <arrival> <distance>, then the following code, using defaultdict
to initialise the new keys in an empty dictionary, allows the construction of
the graph:

from collections import defaultdict

nb_edges = int(input())

g = defaultdict(dict)
for _ in range(nb_edges):
u, v, weight = input().split()
g[u][v] = int(weight)
# g[v][u] = int(weight) # For an undirected graph

Example—read three matrices A,B,C and test if AB = C


In this example, the inputs are in the following form: the first line contains a single
integer n. It is followed by 3n lines each containing n integers separated by spaces,
coding the values contained in three n × n matrices A,B,C, given row by row. The
goal is to test if the product A times B is equal to the matrix C. A direct approach
by matrix multiplication would have a complexity O(n3 ). However, a probabilistic
solution exists in O(n2 ), which consists in randomly choosing a vector x and testing
whether A(Bx) = Cx. This is the Freivalds test (1979). What is the probability that
the algorithm outputs equality even if AB = C? Whenever the computations are
made modulo d, the probability of error is at most 1/d. This error probability can
be made arbitrarily small by repeating the test several times. The following code has
an error probability bounded above by 10−6 .
Exploring the Variety of Random
Documents with Different Content
oogenblik, een helder brandend vuur kunnen ontsteken, dat voldoende licht
zou verspreiden.

Te vijf uren begaf men zich op weg. Jan Machielsz had allen, die aan den
tocht deelnamen, in de schuur, die het middelpunt was der kleine kolonie,
verzameld en Gods zegen op de onderneming afgesmeekt. Een traan
biggelde langs de gerimpelde wangen van Pieter de Welle, toen de
predikant zijn Mieke aan God opdroeg, bij Wien veel verlossing was, en
Hem smeekte, de onschuldigen te rukken uit de klauwen van den wreeden
Titelman. Ook Daniël had ontroerd het hoofd gebogen.

Niemand lette op den monnik, die nog altijd gebonden in de schuur lag en
wiens armen slechts werden losgemaakt, als men hem eten en drinken
bracht. Niemand zag, hoe hij met half gesloten oogen loerde naar den
biddenden predikant en de forsche, gewapende mannen, die ontroerd naar
zijne woorden luisterden.

Na het gebed begaven zich allen op weg, ook Jan Machielsz, die niet in het
kamp had willen blijven. De plaats, waar men zich in hinderlaag zou
leggen, was ongeveer twee uren van de kolonie verwijderd. Alle weerbare
mannen gingen mede, want voor een aanval op het kamp behoefde men niet
te vreezen: er waren geen soldaten in de buurt gelegerd en de afgelegen
plek was slechts aan weinigen bekend, en die weinigen—eenvoudige
lieden, die in het bosch of het veen woonden—waren vrienden van de
vluchtelingen, en zouden hen niet verraden.

De bewaking van het kamp was opgedragen aan Peerke, een stevigen kerel
uit Diest, die te Watrelos een kogelwond in het been had gekregen, welke
nog niet geheel genezen was. Voor lange tochten was hij ongeschikt en hij
moest zich dus met den post van portier tevreden stellen, dien hij al
grommende waarnam.

Nu was Peerke een trouw makker, op wien men in alle opzichten kon
rekenen, zoolang hij niet in de buurt van een kanne biers was. Jan
Machielsz en Daniël wisten dat zeer goed; maar daar er op dat oogenblik op
het eiland niets was dan een ton dun bier, die men van een brouwer te Diest
had gekregen, meenden zij van dien kant veilig te zijn: aan dat dunne,
scherpe vocht zou Peerke zich zeker niet bedrinken. Wat de aanvoerders
echter niet wisten, was, dat Peerke van een van de Geuzen, die geholpen
had bij de plundering van een klooster, een vaatje zoete malvesye had
gekocht, dat hij zorgvuldig in den grond had begraven, met de bedoeling er
zich te gelegener tijd eens rustig aan te goed te doen.

Die gelegen tijd scheen Peerke thans gekomen. Het zou uren duren, eer de
bende haar schuilhoek weder kon bereiken, en hij had dus den tijd aan zich.
De vrouwen waren met haar kinderen in de hutten en hij was met den
gevangen monnik alleen in de schuur.

Nu was Peerke op zijn manier een man van geweten en hij wou zich niet
bedrinken, vóór hij wist, dat alles veilig was. Toen het geluid van de
voetstappen zijner makkers was weggestorven, begon hij den monnik stevig
de handen op den rug te binden. Daarop nam hij zijn hellebaard en
strompelde het eiland om, om zich te overtuigen, dat er inderdaad geen
gevaar dreigde. Toen had hij, naar hij meende, zijn plicht volbracht; hij
groef het kostbaar vaatje op en torste het naar de schuur, sloeg de stop uit
het spongat en terwijl hij met welgevallen den geur van den wijn opsnoof,
verzekerde hij den monnik, dat dit nu een patersvaatje was, dat hij, Peerke,
op de gezondheid van den paus en van alle papen zou gaan leegdrinken.

Toen nam hij zijn tinnen kroes, zette zich in een gemakkelijke houding bij
de ruw opgemetselde schouw en begon met lange teugen te drinken, terwijl
hij van tijd tot tijd ophield, om zijn gevangene mede te deelen, dat het
kostelijk smaakte en dat de paters wel wisten, wat goed was.

De monnik zat roerloos, met gesloten oogen, tegen den paal geleund, waar
Peerke hem had neergekwakt. Hij gaf geen enkel teeken, dat hij de
spotternijen van den Geus verstond.

Maar de krachtige wijn bleek te sterk voor het hoofd van Peerke, die slechts
aan het zware, Vlaamsche bier gewend was. Weldra werd hij bijzonder
vroolijk; hij begon te zingen: een zonderling mengelmoes van psalmen en
luchtige liedjes en hij werd eindelijk zoo welgemutst, dat hij een kroes van
den wijn nam en daarmee op den monnik toewaggelde.

—„Ik breng ’t je, paap,” zei hij met dubbelslaande tong. „Jij kunt het ook
niet helpen, dat je een papist bent.”

De monnik had even het hoofd omgewend, maar hij bedacht zich en dronk
met gretige teugen.

—„Dat smaakt anders dan slootwater, hè?” zei Peerke. „Weet je wat?” ging
hij voort, op goedigen dronkemanstoon, „je moet niet teruggaan naar dat
vermaledijde klooster. Als je tegen de jongens zegt, dat je geen papist meer
wilt zijn, dan zullen ze je losmaken en dan kon je bij ons een goed leven
hebben. Dan zal ik een sneege deern voor je opschommelen, en Jan
Machielsz zal jelui trouwen. Dat is beter voor een flinken borst.”

De Dominicaan antwoordde niet.

—„Je bent een stuursche compaan,” zei Peerke boos, „en je laat mij maar
alleen kallen. Ik krijg weer dorst, maar jij krijgt niets meer, als je niet praten
wilt.”

Hij waggelde weer naar zijn vaatje en vulde zijn kroes. Hij werd steeds
luidruchtiger en zijn goede luim van zooeven was weldra geheel voorbij.
Hij werd twistziek en eischte, dat de monnik met hem mee zou zingen.

—„Komaan, paap,” schreeuwde hij; „dat ’s je voor en als ze je niet


meezingt, sla ik je de ribben kapot. Komaan!”

„Wie wil hooren een nieu liet!


„Luystert toe, ik salt u singen,
„Wat daer t’ Antwerpen is gesciet.”

—„Je, je z... zingt niet mee, verdoemde paap? Wacht, ik z... zal je l...
leeren!”
Hij stond op, maar struikelde over het vaatje en viel met een slag op den
grond. Een paar malen beproefde hij op te staan, maar tevergeefs; zijn
schelden werd een onverstaanbaar gemompel en weldra bewees een zwaar
gesnork, dat de dronkaard zijn roes uitsliep.

Nu kwam er beweging in de roerlooze gestalte van den monnik. Zijn felle


zwarte oogen keken schichtig rond en vlogen toen van den slaper naar het
vuur.

Loopen kon hij niet, want zijne voeten waren stijf bijeengebonden, maar hij
liet zich op zijne zijde vallen, wentelde zich om en om en rolde zoo naar het
vuur. Hij koos een plek uit, waar een groote turf geheel was doorgebrand,
toen draaide hij zich nogmaals om, met den rug naar den vuurhaard, en,
achteruitschuivende, hield hij zonder aarzelen zijn gebonden handen tegen
het brandende stuk veen. De reuk van het brandende touw, gepaard met een
afschuwelijken stank van het geschroeide vel en vleesch vervulde de
schuur. De monnik was vaalbleek; het angstzweet parelde op zijn voorhoofd
en hij liet een dof gekreun hooren, maar hij liet niet af, al klemde hij de
dunne lippen tusschen de tanden, om het niet uit te brullen van de pijn.

Nog een oogenblik en met inspanning van alle krachten rukte de monnik
het half doorgebrande touw los en wikkelde haastig de smeulende einden
van zijn polsen. Kreunend bleef hij liggen, terwijl hij de armen langzaam
heen en weer bewoog, om den bloedsomloop te herstellen. De rest was
gemakkelijk. Het zakmes van Peerke stak in de lederen scheede uit den zak
van den wijden broek en was binnen het bereik van de hand van den
monnik. In een oogenblik had hij het touw doorgesneden, waarmede zijne
voeten waren geboeid. Zijn eerste werk was nu naar de deur der schuur te
strompelen, en die te sluiten met den zwaren boom, zoodat hij niet kon
worden overvallen. Toen liep hij langzaam heen en weder, tot ook zijn
beenen weer hun vroegere kracht en lenigheid hadden terug gekregen en
ondertusschen verslond hij gretig het brood en het spek, dat voor het
avondeten van zijn bewaker was bestemd, en dronk nog eenige teugen van
den krachtigen wijn. Hij doopte een paar lappen in een pot met melk, dien
hij vond, en wikkelde die om zijn verschroeide polsen. Toen was hij gereed
om te vluchten.
Hij ging naar Peerke en nam het mes, dat hij had laten liggen. Een
oogenblik stond hij besluiteloos bij den snorkenden dronkaard. Het mes
trilde in zijne hand en een wreede, woeste trek kwam op het bleeke gezicht.
Daar viel zijn oog op den kroes, dien de slaper hem goedhartig had
toegereikt en het strakke gezicht werd zachter.

—„Libera nos a malo!”1 prevelde de monnik, terwijl hij het mes wegstak.

Hij ging naar de deur, nam den boom weg en tuurde even voorzichtig naar
buiten. Toen liep hij vastbesloten het smalle pad af, dat van de schuur naar
de gracht voerde. Een paar kinderen, die hij tegenkwam, gingen
schreeuwend op de vlucht.

De monnik snelde voort. Achter zich hoorde hij de schelle stemmen der
vrouwen en hij begreep, dat hij zich moest haasten. De knuisten dier kloeke
Vlaamsche wijven waren niet te verachten en zij waren zeer wel in staat,
hem tegen te houden. Hij kwam aan de breede gracht. Zonder te aarzelen
sprong hij in het water en met een paar slagen had hij den overkant bereikt.
Toen, zonder zich om de scheldwoorden der hem vervolgende vrouwen te
bekommeren, sloeg hij den weg in, die de uitgetrokken bende had genomen,
wier breed spoor gemakkelijk te volgen was. Zoo kwam hij veilig door het
moeras. Hij was doornat en rilde van de koude in de vochtige
voorjaarslucht, doch hij draafde verder, steeds het spoor der Geuzen
volgende, tot hij in de verte de hooge boomen zag, die langs den karreweg
naar Poperingen stonden. Toen sloeg hij rechtsaf en springend en soms
wadend door de plassen van den broekigen grond bereikte hij den weg.
Eenige oogenblikken rustte hij uit, om op adem te komen en zijn doornatte
kleederen zoo goed mogelijk uit te wringen. Toen stapte hij ijlings voort in
de richting van de stad.

Intusschen was de bende, onder aanvoering van de Welle en Daniël Tistz op


de plaats aangekomen, waar men, volgens afspraak, de gevangenen met hun
geleide zou opwachten. De jongens, die vooruitgezonden waren, hadden
niets verdachts bespeurd. Zij hadden zich ijverig geweerd: aan beide kanten
van den hollen weg hadden zij een mutsaard gemaakt van stroo en droge
takken, die in een oogenblik kon worden aangestoken.
De Welle en Daniël begonnen nu hunne mannen hun posten aan te wijzen.
Twee handbusschutters werden met smeulende lonten bij de mijten
geplaatst, met den last om die, op een bepaald sein, aan te steken. De andere
Geuzen, die met bussen, handbogen en armborsten gewapend waren,
werden op de hellingen ter weerszijden van den hollen weg verdekt
opgesteld, om de hellebaardiers van het escorte in bedwang te houden,
terwijl de met pieken en zeisen gewapenden zich in twee partijen
verdeelden, en post vatten in de laagte, waar zij zich in greppels en achter
boomen verscholen. De bedoeling was om den wagen aan te houden in het
laagste gedeelte van den hollen weg, waar de paarden moeite zouden
hebben, de zware huifkar door de modder te trekken. Bij het licht der
ontstoken houtvuren zou men de bewakers achteruitdringen en ontwapenen.
Wie zich verzette, zou worden neergestooten. Dan zou men de gevangenen
bevrijden en met hen, langs de welbekende sluipwegen, vluchten naar den
schuilhoek der Geuzen, aan den boschrand, waar men voorloopig in
veiligheid zou zijn. Dan wilde de Welle met zijn dochter uitwijken naar
Engeland en Jacob had besloten, hem te vergezellen.

Een oogenblik was het rumoerig geweest in het bosch, toen de Geuzen
hunne posten bezetten, maar weldra was alles stil, want de leiders hadden
hun mannen de grootste omzichtigheid aanbevolen. Schildwachten waren
uitgezet aan beide zijden van het pad, hoewel men geen verraad te duchten
had, en een paar kloeke jongens waren een eind den weg op gezonden, om
de nadering van den wagen te berichten.

Jacob stond met de Welle en Daniël Tistz dicht bij een der mutsaarden. Het
was reeds zeer donker, want de lucht was nog steeds betrokken. Men zag
maan noch sterren heenschemeren door het jonge lentegroen der boomen. ’t
Was stil in het bosch. Men hoorde niets dan dat eigenaardig murmelen van
den wind in de boomtoppen, de eigen stem der wouden, die de stilte nog
schijnt te vermeerderen. Het naargeestig krassen van een boschuil klonk uit
de takken boven hun hoofd.

Daniël huiverde.
—„Een kwaad voorteeken,” mompelde hij; „als ik nog een papist was, zou
ik een kruis slaan.”

—„Wees stil, ongeluksprofeet!” beet hem de Welle toe, die zenuwachtiger


werd, naarmate het oogenblik naderde, waarop men den wagen kon
verwachten, en die ongeduldig heen en weer liep. Ook Jacob had moeite
rustig te blijven; telkens meende hij eenig gerucht te hooren op den weg,
het kraken der raderen of het klappen van de zweep en dan betastte hij
zenuwachtig de kolf van zijn pistolen. De angst van de Welle en de
gedachte aan het lot, dat de arme Mieke te wachten stond, als het opzet
mislukte, misten ook op hem hunne uitwerking niet.

Het was nu zeer donker. Hier en daar zag men een vurig punt: de smeulende
lont van een busschieter. Jacob kon de gestalte van Daniël, die toch vlak
naast hem stond, nauwelijks onderscheiden.

Plotseling boog de strooper zich voorover en luisterde aandachtig. Zijn


geoefend oor had iets vernomen, dat Jacob was ontgaan. Een oogenblik
later hoorde men haastige voetstappen.

—„Hier!” riep de Welle.

Een gedaante dook uit de duisternis op; ’t was een van de jongens, die als
spionnen waren uitgezonden. Hijgend vertelde de knaap, dat de wagen er
aankwam.

—„Zijn er soldaten bij, jongen?” vraagde de Welle.

—„Veel!” verzekerde de knaap, „wel vijftig!”

—„Onmogelijk!” zei Daniël ongeloovig. „Je hebt ze niet kunnen tellen,


Tist. ’t Is te donker!”

Neen, geteld had de knaap ze niet. Maar hij was den wagen tegemoet
geloopen tot buiten het dorp, waar geen boomen stonden en daar was het
zoo donker niet. Hij was zeker, dat er een groot aantal soldaten, vijftig of
zestig wel, bij de kar waren.
—„De jongen is gek,” meende de strooper. „Waar zou de schout van
Poperingen opeens zooveel soldaten vandaan halen?”

—„Je hebt je toch niet vergist, jonker?” vraagde de Welle met een licht
trillende stem.

—„Zeker niet,” antwoordde Jacob. „Die schoutendienaar sprak van een


twaalftal hellebaardiers. Meer waren er niet!”

—„Ik begrijp het niet,” zei de oude boschwachter heesch. „Als die jongen
gelijk heeft...”

Hij voltooide zijn zin niet en ook de beide anderen zeiden niets. Zij wisten,
wat hij bedoelde: hun geheele bende was slechts een twintigtal mannen
sterk.

Maar nu hoorde men flauw in de verte de klets van de zweep van den
voerman. Een zacht fluiten, dat hier en daar herhaald werd, gaf aan de in
hinderlaag liggende Geuzen het teeken, om zich gereed te houden.

Het kraken van de wielen van de huifkar, het klotsen van zware
voetstappen, het kletteren van wapenen, eerst flauw, dan duidelijker en
duidelijker aankomend door het donkere bosch. Op den weg een flikkerend
licht, op en neer dansend, zwaaiend en schokkend: de lantaarn van de kar,
die aan den disselboom opgehangen, den weg voor het tweespan verlichtte.

Het beslissend oogenblik was daar.

In ademlooze spanning zag Jacob het zwaaiende licht nader en nader


komen, en, terwijl hij staarde, meende hij op de hellingen boven zich een
onverklaarbaar gedruisch te hooren, het kraken van takken, het ritselen van
dorre blaren. Een paar nachtvogels vlogen krijschend op.

Hij had geen tijd, om zich rekenschap te geven van die geheimzinnige
geluiden, want de wagen had nu het laagste punt van den weg bereikt en de
pooten der paarden klotsten in het modderige water. De Welle bracht den
koehoorn, die aan een koord om zijn hals hing, aan den mond en het holle
geluid klonk door het bosch. Een rood vlammetje verscheen aan den kant,
waar de mutsaard stond. Het droge stroo vatte vuur; roode en gele vlammen
lekten naar boven en een rossige gloed verlichtte de donkere stammen en
wierp zijn schijnsel op den wagen en de mannen, die hem begeleidden.

—„Vive le Geus!” klonk het uit twintig schorre kelen en een troep mannen,
met pieken en omgesmede zeisen gewapend, sprong van achter de boomen
te voorschijn en versperde den weg.

Maar wat was dat?

Een zware losbranding op de helling boven hen, donderend voortrollend


door de boschlanen, nog een—en nog een! Roode vuurtongen, uitschietende
uit de duisternis—en een paar van de schutters der Geuzen, die, door den
gloed der opvlammende houtmijten beschenen, een voortreffelijk mikpunt
aanboden, zonken ineen. Op den weg klonk een luid commando en de
verbijsterde aanvoerders zagen een half vendel soldaten, die zich in goede
orde met gevelde pieken om den wagen schaarden.

—„Vive le Roy! Slaet dood de Geuzen!” klonk het uitdagend.

Het toeval was den monnik gunstig geweest. Hij had niet alleen den wagen
met zijn escorte kunnen ophouden, maar hij had ook een half vendel van het
voetvolk van Egmond ontmoet, dat zich van Rijssel naar zijne kwartieren in
Zeeuwsch-Vlaanderen begaf. Toen de jonge luitenant, die den troep
commandeerde, hoorde wat er gaande was, had hij niet alleen terstond
aangeboden, den wagen met de gevangenen veilig naar Rousselaere te
geleiden, maar hij had zelfs een plan gemaakt, om de Geuzen in hun eigen
strik te vangen, en hun een geduchten slag toe te brengen.

De monnik had goed geluisterd. Hij kende het plan, want men had het in
zijn bijzijn besproken, en niemand had er aan gedacht, zich in acht te nemen
voor den hulpeloozen gevangene. De schoutendienaars uit Poperingen
kenden de plek, door den Dominicaner beschreven, en de luitenant had de
zes arquebusiers, die zich bij zijn troep bevonden, de helling doen
beklimmen, zoodat zij op het beslissende oogenblik met hun vuurroeren de
aanvallers in den rug konden bestoken.
Eén oogenblik stond de Welle het tooneel beneden hem met verwilderden
blik aan te staren. Hij werd door het volle licht van een der mutsaards
beschenen en een kogel snorde hem langs het hoofd, uit een der Spaansche
vuurroeren. Maar de gevangenen in den wagen konden hem daar ook zien
en herkennen. Een schreeuw klonk van de kar, de huik van een der
ineengedoken gestalten viel af en Mieke stond rechtop, met uitgestrekte
armen, naast den voerman.

—„Vader!” gilde zij; „vader! hulp!”...

Het meisje maakte een beweging, als wilde zij van de kar springen, maar
een donkere gedaante kwam achter uit den wagen te voorschijn, een lange,
magere arm werd om haar heen geslagen, en dwong haar terug op haar
bank. Een bleek, vertrokken gezicht keek hoonlachend op naar de Geuzen.

—„Hel en verdoemenis! De monnik!” siste Daniël. „Wacht, Judas!”

Met een ruk had hij den armborst aan den schouder, de pees klonk, en met
een bout in de keel tuimelde de monnik achterover. Niemand dan de
schutterkoning van Poperingen had, bij dit onzekere licht, het schot kunnen
wagen, zonder gevaar te loopen het jonge meisje te treffen.

Maar de hulpschreeuw van zijn dochter had de Welle gewekt uit zijn
verbijstering, die hem een oogenblik had doen weifelen, toen hij zich zoo
onverwachts geplaatst zag tegenover een zoo geduchte overmacht.

—„Vive le Geus! Slaet dood!” schreeuwde hij, en door Jacob en Daniël


gevolgd, sprong hij in den hollen weg, om zich aan het hoofd der zijnen te
stellen.

En nu volgde er een verwoed gevecht. De soldaten namen den wagen in


hun midden en maakten met gevelde speren front tegen de aanvallers,
terwijl de Geuzen hen van twee kanten bestookten, en door verwoede
aanvallen trachtten door hunne gelederen heen te breken.

Het woeste geschreeuw der vechtende mannen, het wapengekletter, soms


overstemd door den doffen knal van een pistool of een bus, het gegil en
geschrei der gevangen vrouwen en het kermen der gekwetsten, vervulden
het bosch met een woest rumoer.

Zonder orde, maar met woeste dapperheid, drongen de Geuzen telkens


weder op en trachtten den wagen te bereiken, maar telkens werden zij
teruggeslagen, terwijl de musketiers, op de hellingen geposteerd, hunne
vuurwapenen weder hadden geladen en door eene onverwachte losbranding
een paar der aanvallers buiten gevecht stelden.

De strijd in den hollen weg was kort maar hevig, en de uitslag kon niet
twijfelachtig zijn. De Geuzen werden teruggedrongen; een achttal hunner
was dood of gewond.

Daar zonk de Welle, die in de voorste rij met den moed der wanhoop had
gevochten en met zijn gepinde kodde reeds drie soldaten had neergeveld,
door een kogel getroffen, neer. Op het gezicht van den val van hun
aanvoerder, ontzonk den Geuzen de moed. Zij deinsden achteruit.

—„De gewonden, mannen! Neemt de gewonden mee!” riep Jacob Martens,


die begreep, dat de aanslag mislukt was.

Een paar zeisdragers volgden hem, en, met hunne wapens zwaaiende,
maakten zij een oogenblik ruim baan. De Welle en nog twee anderen
werden haastig opgenomen en weggedragen. Toen vluchtten de Geuzen en
waren weldra buiten het schijnsel der vlammen en in het donkere bosch,
waar zij alle paden kenden en waar de soldaten hen niet durfden volgen.

Allen waren gevlucht, behalve Daniël. Even buiten den lichtkring, half
verborgen achter een beukenstam, stond de strooper en staarde naar de
huifkar, waar een paar der stadshellebaardiers zich thans bezig hielden met
het lijk van den monnik, die tusschen de verschrikte gevangenen was
neergezegen. Op de voorste bank zat Mieke. Toen zij de Welle had zien
vallen, had zij een gil gegeven. Thans keek zij met strakke, wanhopige
blikken naar het donkere geboomte, waarin zij hem had zien wegdragen.

Een siddering ging door het lichaam van den strooper.


Wild keek hij om zich heen. Achter zich hoorde hij de stemmen der
aftrekkende Geuzen, die hem toeriepen te vluchten. Vóór zich zag hij de
huifkar, waar thans de soldaten zich om verdrongen, die zoo goed mogelijk
hun gewonde makkers verzorgden, en het doodsbleeke meisje, dat hij en
zijn makkers aan haar lot moesten overlaten—Mieke in de handen van
Titelman!

Vaster omklemde Daniël zijn gespannen armborst, er kwam een woeste blik
in zijn starende oogen en hij klemde de lippen op elkander.

—„Nooit!” steunde hij. „Dan liever...”

Hij bracht den kruisboog aan den schouder.

—„Mieke!” schreeuwde hij. Het meisje zag om.

Het staal van den armborst klonk. Met een flauwen kreet, dwars door het
hoofd geschoten, zonk Mieke achterover.

Een paar soldaten, die den schreeuw hadden gehoord, drongen het bosch in,
maar zij hoorden slechts een akeligen lach uit het donkere geboomte
opklinken.

De wildstrooper was verdwenen.

1 „Verlos ons van den booze!” ↑


XII.

West-Vlaanderen sluimert rustig in den stillen zomernacht.

De eindelooze korenvelden golven en ruischen zacht in den nachtwind, de


boomgaarden van Dixmuiden wiegen hunne met jong fruit beladen takken,
de hopvelden van Poperingen geuren en zwaaien als groetend met hunne
lange slingers. De dorpen slapen in het starrelicht, een donkere boomgroep,
midden tusschen de velden, wijst de ligging aan van een eenzame hofstede
en ver in het Westen, breed langs den duinrand, liggen de zwarte schaduwen
der bosschen.

Een kalm, welvarend landschap in ruste! Alleen het geblaf van een
werfhond verstoort nu en dan de groote stilte.

Dan wordt de donkere nachthemel in het Westen eensklaps verlicht door


een vreemden rossen gloed, dat rosse wordt vlammend rood en vuurtongen
lekken door de duisternis. Tegelijk klinkt een schel, dun klokgelui met kort,
haastig geklep over de velden, nog eenige oogenblikken en twee, drie
kerktorens antwoorden met jammerend noodgelui en van Hondecoeter naar
Killem en Oostcappel, van Winnezeele en Oudezeele naar Reynighelst,
Lokeren en Kemmele, tot Dracoultre in het Fransche toe kleppen en beieren
de klokken en waarschuwen de Roomsche landlieden, maar vooral de
geestelijken en kloosterlingen, die niet geborgen zijn binnen de veilige
wallen der steden, lijf en goed te bergen in haastige vlucht.

De Wilde Geuzen komen!

In de bosschen en moerassen van West-Vlaanderen hebben zij een veilige


schuilplaats gevonden, de vluchtelingen van Austruweel en Watrelos, de
Gereformeerden uit Valenciennes en Doornik, die de beulen van
Noircarmes ontkomen zijn, allen, die vreezen voor hun vrijheid of hun
leven, nu de Regeering heeft gezegevierd en bittere wraak neemt op de
overwonnen Geuzen voor de doorgestane angsten. Ze leven er in de open
lucht of in inderhaast opgeslagen schuren en loodsen van hetgeen hunne
geestverwanten in geheel Vlaanderen en Brabant hun heimelijk doen
toekomen, of wat zij de Roomsche bevolking afpersen door vrees of door
geweld. Zij hebben hun predikanten en onderhouden zoo goed mogelijk het
godsdienstig leven, waaraan zij gehecht zijn. Maar door het ongeregelde,
avontuurlijke leven, dat zij leiden, verwilderen zij maar al te ras. Van
vervolgden worden zij bloedige vervolgers, de schrik en de vloek van de
streek, waar zij huizen.

En het zijn niet alleen vluchtelingen en vervolgden, die zich ophouden in


hunne geheime en moeilijk toegankelijke schuilhoeken. Zooals elke groote
beweging, heeft ook deze haar zelfkant. Tal van landloopers en vaganten,
waaraan de 16e eeuw zoo rijk is, hebben zich onder allerlei voorwendsels
bij hen aangesloten en men heeft de vreemde elementen niet altijd kunnen
weren. En al spoedig wilde men het niet meer. Naarmate de strooptochten
stouter werden, de daden bloediger, werd ook de tegenstand heviger. Er
werden door Egmond en Bakkerzeele soldaten gezonden, om de woeste
benden, als ’t mogelijk was, uit te roeien en weldra was elk stoutmoedig
man, die de wapenen kon voeren, hun welkom, zonder dat men naar zijn
verleden of belijdenis vraagde.

De Wilde Geuzen komen!

’t Is een stroop- en plundertocht, zooals ze dien telkens ondernemen, want


hun aantal groeit steeds aan, geregelden arbeid hebben zij niet en hetgeen
hunne vrienden hun doen toekomen, of wat zij de Roomsche bevolking in
de nabijheid hunner schuilplaatsen weten af te dwingen, is dikwijls
ontoereikend. Dan moeten de verder gelegen dorpen, vooral de kloosters en
geestelijke gestichten, het ontgelden. Ze worden zonder genade geplunderd
en in brand gestoken en dikwijls worden de kloosterlingen mishandeld en
vermoord. Want een woeste haat tegen de Roomsche geestelijkheid vooral
bezielt hen en menig onschuldige moet boeten voor Noircarmes’ wreedheid
te Valenciennes.

En daarom klinkt het noodgeklep der dorpsklokken over de velden,


waarschuwend al wie hun wrake te vreezen heeft.
De Wilde Geuzen komen!

Ze zijn hun tocht begonnen met het overvallen van de hoeve van een rijken,
Roomschen boer, die meende hen te kunnen trotseeren. Ze hebben het huis
geplunderd en in brand gestoken, het vee door de vrouwen en jongens laten
wegdrijven naar hunne schuilhoeken en den huisman en zijn van angst
sidderend gezin, onder woeste spotternij het veld in gejaagd, „om hulp te
gaan zoeken bij zijne Santen”, zooals zij hem najouwen. Thans gaat het
verder, dieper landwaarts in. Reeds hebben ze, weinige weken te voren, de
dorpen Herzeele en Houtkerke overvallen en er de kerken verwoest en in
brand gestoken. Thans geldt het Oostcappel.

De Wilde Geuzen komen!

Snel rukken zij voort bij het licht van enkele toortsen en pekkransen, want
in hun onverwachten overval, hun snelle bewegingen schuilt hun kracht.
Een gedeelte, de kern van den troep, bewaart een soort ruwe, militaire
marschorde. Zij hebben aanvoerders, die zij erkennen en gehoorzamen en
zijn onderworpen aan een zekere krijgstucht. Dat zijn de vluchtelingen uit
het Geuzenleger en de Gereformeerden, uitgewekenen uit de door de
troepen der Regeering verwoeste steden.

Maar met hen mede, in den tros van den troep, trekken een aantal havelooze
en verwilderde gestalten, die doen wat goed is in hun oogen en wier
bandeloosheid de beter gezinden niet kunnen bedwingen of misschien maar
al te gemakkelijk verontschuldigen. Allen zijn gewapend, maar ieder heeft
zich van een wapen voorzien, zoo goed hij kon. De vluchtelingen uit het
Geuzenleger hebben hunne hand- en haakbussen, hunne pieken en rapieren,
de jagers en boschwachters hunne armborsten en kodden, maar anderen
dragen rechtgesmede zeisen, hooi- en mestvorken, zware knuppels met
ijzeren pinnen, bijlen en messen, dorschvlegels—het vreedzaam gerei van
den landbouw wordt tot moordwapen in de handen der wanhopende,
verwilderde benden.

Achter hen volgt een wagen, met een paar kloeke Vlaamsche paarden
bespannen. Die zal straks dienen om den buit mee te voeren, den
mondvoorraad, waaraan de ballingen behoefte hebben, ook de gewonden,
indien er tegenstand mocht worden geboden. Thans dient hij tot vervoer van
een, dien niets kon weerhouden om aan den strooptocht deel te nemen,
maar wiens zwak lichaam den snellen marsch der Geuzen niet kon volgen.

’t Is Jan Machielsz, de kreupele predikant.

Sinds hij predikte in ’t Spaansche Dal bij Poperingen is er veel met hem
gebeurd. Van Bakkerzeele, Egmont’s stadhouder, had gedaan wat hij kon,
om de deelnemers aan den stouten aanslag in den hollen weg naar
Poperingen in handen te krijgen, en de Geuzen, die zich in hun schuilhoek
niet veilig achtten, hadden zich naar alle richtingen verstrooid.
Verscheidenen waren uitgeweken naar Engeland en hun broeders in de
visschersdorpen langs de kust hadden hen gaarne de behulpzame hand
geboden om te vluchten. Ook Jan Machielsz was door een Duinkerker
visscher in Engeland aan wal gezet. Hij had er kennis gemaakt met andere
ballingen, die veilig waren in het vreemde land en er hun God konden
dienen naar hun geweten, maar die toch terug hunkerden naar het schoone,
bloeiende Vlaanderen, naar hunne vrienden en magen, die zij er hadden
moeten achterlaten. En er waren geestdrijvers onder, die gaarne luisterden
naar de gloeiende woorden van den kreupelen prediker, voor hen de taal van
een vast en krachtig geloof. „Zou de arm des Heeren verkort zijn?” „Was
het niet in de hand van den Heer der heirscharen, verlossing te geven door
de hand van velen of weinigen?” „Had niet Gideon met een handvol volks
het leger der Midianieten verslagen?” Zoo sprak Jan Machielsz, en zijne
hoorders, mannen met bleeke, vastberaden gezichten, stemden er mee in.
Zoo God vóór hen was, wie zou tegen hen zijn? En zij hadden zich
heimelijk gewapend, een vijftigtal slechts en in twee visschersbooten waren
zij de zee overgestoken en, in West-Vlaanderen geland, waren zij moedig
voortgetrokken, zonder bepaald plan, met de vage bedoeling, Gods volk te
verlossen uit de hand der Philistijnen en de ware Kerke te stichten op de
puinhoopen der valsche, in de stellige verwachting, dat de Heere met hen
zou strijden en hen door een wonder van Zijn machtige hand de zege zou
doen behalen.
Zij hadden een paar kerken en kloosters verwoest en in de asch gelegd, toen
zij door een vendel van Egmont’s krijgsvolk werden overvallen en
verstrooid. Zij, die den dood door het staal of den strop waren ontkomen,
waren Jan Machielsz gevolgd naar de ontoegankelijke schuilhoeken in het
Zuid-Westen, waar de Wilde Geuzen huisden. De kreupele prediker was er
met blijdschap ontvangen, want zijne prediking was naar het hart der wilde
gezellen en de man, die eens de martelares een woord van troost en
bemoediging had toegeroepen, werd meer en meer de starre dweper, die niet
meer wist van het Evangelie der liefde, maar wiens hartstochtelijke
predikaties, meestal aan woorden uit het Oude Testament ontleend,
aanhitsten tot wraak en verdelging, tot wreede vervolging van priesters en
kloosterlingen en tot verwoesting van alle kerken en kloosters in den
omtrek.

De besten onder de Boschgeuzen beschouwden hun strijd als de laatste,


wanhopige worsteling tegen de zegevierende Regeering, van wie zij geen
genade hadden te hopen. Maar de groote meerderheid, weldra aan het
avontuurlijke leven gewend, had smaak gekregen in den guerilla-oorlog,
dien zij tot nog toe vrijwel straffeloos hadden kunnen voeren en dachten
niet aan de toekomst.

Aan het hoofd van de geregeld voortmarcheerende kern van den troep
schreed Pieter de Welle met Jacob Martens. Zij waren gedwongen geweest
een toevlucht bij de Wilde Geuzen te zoeken, wachtende op den
volksopstand, waarop sommigen in die dagen nog hoopten. Spoedig waren
zij als aanvoerders bekend, voor zoover de tuchtelooze bende geneigd was,
aan eenig gezag te gehoorzamen. De oude boschwachter trok gaarne op aan
het hoofd van zijn woeste gezellen. Sinds den dood van zijn dochter
behoorde hij tot de ijverige aanhangers van Jan Machielsz. Hij haatte de
„papen”, en het „verbannen der Amalekieten”, waartoe de kreupele
predikant aanspoorde, scheen den verbitterden man een godgevallig werk.
En zoo de door de ballingen gepleegde wreedheden Jacob al tegen de borst
stuitten, het ruwe krijgsleven der laatste maanden, de doorgestane ellende
en de geheele toon en denkwijze van de omgeving, waarin hij leefde,
maakten, dat hij zich spoedig aan de onvermijdelijke gruwelen van den
guerilla-krijg begon te gewennen. Dat hij streed voor en met de Geuzen, bij
wie hij een schuilplaats had gezocht en gevonden, sprak, naar hij meende,
vanzelf. En dikwijls genoeg hadden de ballingen zich te verweren tegen de
troepen van den stadhouder, die hun den terugtocht naar hunne
schuilplaatsen zochten af te snijden en hun den behaalden buit afhandig
wilden maken.

Aan de spits van den troep, dicht achter de Welle en Jacob Martens, liep een
der Geuzen, met een stalen armborst en een lang kruismes gewapend, zacht
in zichzelf mompelend, alleen. Zijne metgezellen weken bijna allen schuw
ter zijde, wanneer zij in zijne nabijheid kwamen. Niemand zou in de
magere, gebogen gestalte, met het bleek gelaat, de ingevallen wangen en de
groote, strak voor zich uit starende oogen, den vroolijken, luchthartigen
Daniël, den koenen wildstrooper, hebben herkend. Na den noodlottigen
nacht, toen hij Mieke de Welle had doorschoten, om haar niet levend in de
macht van den inquisiteur te laten vallen, was de jonge man geheel
veranderd. Uren lang zat hij voor zich uit te staren, steeds voor zich heen
woorden prevelend, die niemand verstond. Hij bemoeide zich met niemand
en gaf geen antwoord, als men hem iets vroeg. Het eenige, wat hij deed,
was het maken van bouten voor zijn kruisboog en het slijpen van zijn lang
mes. De overige ballingen hielden hem voor krankzinnig of bezeten door
een boozen geest en ontweken hem schuw. Slechts als een strooptocht werd
ondernomen, ontwaakte Daniël uit zijn droomtoestand. Dan was hij in de
voorste gelederen te vinden en hij vocht met woede en verbittering. Aan de
plundering van de hoeven der Roomschgezinden of der geestelijke
gestichten nam hij nimmer deel, al had men hem dikwijls met een woesten
trek op het gelaat zien staren in de vlammen der brandende gebouwen.
Maar wee den priester, wee den monnik vooral, die zich bij het naderen der
Geuzen niet had weten te bergen, wanneer hij onder schot van Daniëls
kruisboog kwam. Dan werd de stalen kruisboog naar den schouder
gebracht, het strakke oog zocht het doel en de nimmer falende bout
doorboorde het hoofd van het slachtoffer, altijd op dezelfde plaats, daar,
waar hij Mieke had getroffen.

De bende marcheerde snel voorwaarts. De hoeve, die zij in brand hadden


gestoken, behoorde aan dien Roomschen boer, die, omdat er geruchten
liepen, dat de Regeering aan de buitensporigheden der Boschgeuzen
voorgoed een einde zou maken, het had durven wagen, de hem opgelegde
schatting van levensmiddelen niet te betalen. Maar het doel van den tocht
ligt verder.

En van alle zijden klinkt over de slapende velden het angstig jagend
kleppen van de stormklok, waarmede de dorpen elkander waarschuwen.

De Wilde Geuzen komen!

De bewoners der verspreide hoeven en der dorpen, in de nabijheid van de


schuilplaatsen der vermetele gasten, zien hen voorbij trekken met verbeten
woede of met een glimlach van geheime voldoening, al naar dat ze goed
Roomsch zijn, of, zij ’t ook in ’t geheim, tot de vele Gereformeerden
behooren. Zij hebben niets te vreezen. Hetzij vrijwillig, hetzij gedwongen,
allen betalen op de een of andere wijze schatting aan hunne gevaarlijke
buren, en zoo „zitten zij op veylighe waernis” en ze behoeven niet bevreesd
te zijn voor plundering of overlast, want de Geuzen weten, dat zij van die
schatting moeten leven en komen de gesloten overeenkomst getrouw na. En
de West-Vlaamsche boeren koopen zich veiligheid voor leven, hof en have
door dien onderstand, in ’t geheim gegeven, uit vrees voor de Regeering.

Daar klinkt van den wagen een schelle stem. ’t Is die van Jan Machielsz. De
predikant-aanvoerder wekt zijne mannen op, een lied te zingen, een der
psalmen Davids. En allen kennen ze de psalmen van Petrus Dathenus,
misschien de vloekpsalmen nog het best, maar ook de strijdzangen, ook de
smeekbeden, de liederen van hope en vertrouwen.

Maar thans is ’t een der lievelingspsalmen van den kreupelen prediker in de


woestijn, die worden aangeheven. ’t Zijn verzen van psalm 109: Gods toorn
wordt afgebeden over den vijand, den verdrukker van Gods volk.

„Hij heeft den vloeck gewenscht alommen,”

klinkt het rauw over de velden,

„Laet dien nu, Heer, over hem kommen;


„Hij begeerde nooit gheenen zegen,
„Dies geef hem dien in gheenen wegen.
„Laet hem met ongeluck en leet
„Als met eenen rock sijn gekleet.

„Gelijck men ’t water pleegt te drincken,


„Wil hem also den vloeck toeschinken;
„So d’ olie de beenen doordringet,
„Laet hem oock so wezen omringet,
„En als met een rieme seer snel,
„Omgegort zijn met vloecken fel.

„Dit sij ’t loon in allen landen


„Mijner moedwillige vijanden;
„Laet sulcks de kwade tong beërven,
„Die met list soecken mijn verderven.
„Maar Gij, o Heer, in desen noot,
„Help mij om Uws Naams wille groot.”

Het psalmgezang der Geuzen klinkt als dreigend antwoord op het


waarschuwend geroep der kerkklokken. Dan verstomt het, want in de
schemering van den zomernacht doemen de eerste hoeven van Oostcappel
op: het doel van den tocht. De oude toren steekt als een donkere massa af
tegen de starre lucht. ’t Is of de kerkklok haastiger, dringender roept en
jammert, naarmate de bende het dorp nadert. Maar als de Geuzen de eerste
huizen hebben bereikt, zwijgt het noodgelui: de koster, die het touw trok, is
met de andere dorpelingen gevlucht.

Naarmate de bende Oostcappel naderde en de bewoners begrepen, dat het


onwelkome bezoek hen gold, was het levendig geworden in het stille dorp.
Rondom de donkere hoeven bewogen zich dwalende lichten; bij het
schijnsel der stallantaarns werd het vee uit de weiden gedreven, om het zoo
gauw mogelijk in veiligheid te brengen, en het geloei der runderen
vermengde zich met het woedend geblaf der werfhonden, het geroep der
drijvers en het angstgeschreeuw van vrouwen en kinderen. De meesten, die
wat te verliezen hadden, verlieten huis en have en vluchtten langs de
donkere landwegen, noordwaarts op.

Heer Henricus Turck, de oude pastoor van Oostcappel, was uit zijn slaap
opgeschrikt door zijn koster, die hem verlof kwam vragen, de noodklok te
luiden. De man zelf was door de ontstelde boeren gewekt; hij had in de
verte het stormgelui gehoord en begrepen, dat het zaak was, het
waarschuwingssein verder door te geven.

Pastoor Turck had de gewenschte vergunning verleend. Toen had hij zich
haastig aangekleed en was naar buiten gegaan, om zijn verschrikte
parochianen gerust te stellen, terwijl boven hunne hoofden de klok in den
ouden, verweerden toren haastig en zenuwachtig klepte. Men moest zich
niet noodeloos ongerust maken, men wist niet welk gevaar er dreigde, noch
wien het gold. Men moest liever vlijtig zijn rozenkrans bidden en den
bijstand inroepen van Sint Servaes, den patroon van het dorp, den heiligen
martelaar, wiens beeltenis op het altaarstuk prijkte.

En inmiddels zond hij een rappen boerenknaap naar den torentrans, om te


zien, van waar het onheil dreigde.

De verkenner kwam weldra terug met verontrustende berichten. Hij had den
brand in de verte gezien en ook de toortsen der benden, die voortrukten in
de richting van het dorp. Weldra, eerst flauw nog, maar allengs duidelijker,
hoorde men het psalmgezang van den naderenden troep. Nu was er geen
twijfel meer mogelijk! Zij waren het, de vermaledijde ketters, de Wilde
Geuzen,—en het gold hun dorp, het gold Oostcappel.

En onder luide verwenschingen, gejammer en geweeklaag werd het


kostbaarste inderhaast bijeengepakt en op de haastig ingespannen kar
geladen, de knapen dreven het vee uit de naastbij liggende weiden den weg
op en de verschrikte bevolking vluchtte, om veiligheid te zoeken binnen de
sterke wallen van Yperen.

Toen de Geuzen de eerste boerenerven van het dorp bereikten, vonden zij
die ledig en verlaten. Zulk eene Vlaamsche hoeve, alleen staande in het
wijde land te midden van haar hoog geboomte, was anders een niet te
minachten versterking en zeer wel in staat, den aanval van een stroopende
bende landloopers te weerstaan. Het steenen woonhuis vormde met de
schuren en stallen één geheel, dat de ruime binnenplaats omgaf en dikwijls
nog door een gracht of breede sloot was omgeven. Was de brug over die
sloot opgehaald, dan was het niet gemakkelijk zich toegang tot de boerderij
te verschaffen, vooral als die toegang betwist werd door den boer en zijn
stevige knechts. Maar thans dacht niemand aan verzet. In korten tijd hadden
de Boschgeuzen zich een geduchten naam weten te verwerven. Het
landvolk sidderde voor de woeste, vermetele avonturiers en alleen de
geregelde troepen der Regeering, die soms tegen hen werden uitgezonden,
waren in staat, hen naar hunne ontoegankelijke schuilhoeken terug te jagen.

Tot eere der Boschgeuzen zij het gezegd, dat zij zich nergens als gewone
roovers gedroegen. Zij waren geen brandstichters en plunderaars, en de
buitensporigheden, waaraan de mindere elementen onder hen zich vaak
schuldig maakten, werden door de betergezinden zooveel mogelijk belet.

Maar zij waren wanhopigen, vogelvrij verklaarden in hun eigen vaderland.


De laatste strijders voor een verloren zaak. Sedert de zegepraal der
Regeering durfden hun eigen geestverwanten hen slechts tersluiks eenige
hulp verschaffen. En zij moesten leven, de ballingen, die door hun eigen
land waren uitgeworpen. En daarom drongen zij de grootste hoeven binnen,
om zich meester te maken van de levensmiddelen, die zij er vonden. De
ovens werden geplunderd en de zware brooden werden, met zakken meel,
kazen, hammen en zijden spek en wat er verder eetbaars gevonden werd, op
de kar geladen. De kippen, eenden en ganzen, die men in hunne hokken
aantrof, moesten het mede ontgelden. En toen de wagen volgeladen was,
zetten de paarden aan, sterke vuisten hielpen de raderen in beweging
brengen, en door het grootste gedeelte der bende begeleid, verdween de kar
in het halfduister van den zomernacht, onder het gejoel der Geuzen, die
juichten om den goed gelukten strooptocht.

Maar een ander deel was achtergebleven. Dat waren de dwepers, wien het
niet te doen was om den buit, de verbitterden, die eigen leed en dat van de
vermoorde broederen te Valenciennes en elders, wilden wreken op de
Roomsche geestelijkheid, op de kerken en kloosters. En zij gaven er weinig
om, of hun wraak ook de onschuldigen trof.

Nu drongen zij, weer luide hun vloekpsalmen aanheffend, door de verlaten


dorpsstraat, naar de oude dorpskerk. Daar moesten de beelden neergerukt en
vertrapt, daar moest de „broodgod”, zooals zij schimpend de hostie
noemden, bevuild en besmeurd gestrooid op de trappen van het gehavende
altaar. En de roode haan moest kraaien op het dak!

Wat heeft Heer Henricus Turck, die met zijn parochianen was gevlucht,
bewogen om terug te keeren? Voelde de oude man zich een onwaardig
herder, een onwaardig priester, omdat hij het heiligdom, dat aan zijne
zorgen was toevertrouwd, zonder weerstand aan de ruwe gasten overliet?
Wilde hij het Allerheiligste, de hostie, voor hem het lichaam zijns Heeren,
redden en bewaren voor ontwijding? Dit laatste is wel het waarschijnlijkste.
Pastoor Turck was althans teruggekeerd, door de groote deur onder den
toren, die de koster bij zijn vlucht verzuimd had te sluiten, was hij de kerk
binnengetreden, en toen de Geuzen er binnen drongen, zagen zij bij het
flauwe licht der altaarkaarsen den grijsaard, die juist den monstrans uit den
tabernakel had genomen.

Een wild geroep van „slaat dood den paap! slaat dood den baälspriester!”
ging uit de bende op.

Bij het roode licht der fakkels ziet pastoor Turck wilde gestalten naar het
altaar dringen, hij hoort bedreigingen en scheldwoorden, wapens flikkeren
in het licht der gewijde kaarsen.

Begreep de oude man, dat hij in doodsgevaar verkeerde? Meende hij de


woeste bende te kunnen bedwingen, door hen voor te houden wat voor hem
het Allerheiligste was? Hoe het zij, hij bleef staan op de bovenste trap van
het altaar en hield de aanstormende Geuzen den met beide handen hoog
opgeheven monstrans voor.

Dat was zijn doodvonnis. Een gehuil van woede ging op uit de dweepzieke
bende. „Slaat dood den paap!” klonk het opnieuw. Een der Geuzen, die met
een vuurroer gewapend was, vloog de trappen van het altaar op en sloeg
met de kolf van het zware wapen den grijsaard neder, zoodat hij naar
beneden tuimelde. Hij slaakte een kreet van pijn en ontzetting. Hij had de
patena laten vallen, en de hostiën rolden over den grond en werden met
voeten getreden, terwijl de grijsaard jammerend ineenkromp, onder de
slagen en stooten, die hem meedoogenloos werden toegebracht.

Jacob Martens was met de Geuzen mede geloopen naar de kerk, omdat hij
zich niet van de Welle wilde scheiden. Hij was er echter niet binnen gegaan.
Hij wist, wat de mannen er gingen doen, en hij wist ook, dat hij het niet
verhinderen kon, al zeide zijn beter gevoel hem, dat die daden van geweld,
die brandstichting en vernieling van beelden, af te keuren waren en de
goede zaak niet dienden.

Daar hoorde hij den noodkreet van den ouden priester. Wat was dat? Weer
mishandeling? Weer moorden misschien. Jacob Martens snelde de kerk
binnen, den degen in de vuist. De mishandeling van weerloozen zou hij
beletten!

Aan den voet van het altaar zag hij bij het onzekere licht der walmende
toortsen een verwarde menschenmassa. Hij zag wapens blinken in
opgeheven vuisten. Door het woest gelach en geschreeuw der Geuzen klonk
een oogenblik nog een luid gejammer, dat weldra overging in een kermend
steunen.

Hij wilde op de groep toeijlen, maar een ijzeren hand greep hem bij den arm
en hield hem tegen.

—„Halt, jonker! Ge kunt dat niet keeren!” gromde de Welle, die, op zijn
kodde geleund, het tooneel had gadegeslagen en die nu uit de schaduw van
het kerkportaal naar voren trad.

—„Wat moet dat, de Welle?” hijgde Jacob.

—„Ze geven den paap de rest. Wat deed hij ook in de kerk?” antwoordde de
ander onverschillig.
—„Weer een moord op een onnoozele! Laat mij los, de Welle!” En Jacob
wilde zich losrukken, maar de oude boschwachter hield hem stevig vast.

—„’t Is te laat, jonker! De paap is al stil! Mieke was ook onnoozel en de


godzalige Guido de Bray en zoovele broeders in Valencijn waren ook geen
roffianen of kwaaddoeners. Kom mede, naar buiten, jonker. Ze steken de
kerk aan.”

Zoo was het. Het altaardoek brandde reeds, en aan den voet der
altaartrappen lag, wonderlijk klein in het roode licht, het lijk van Heer
Henricus Turck, in zijn zwarten toog. Eenige van de Geuzen stapelden de
houten banken op tot een reuzenmutsaard, terwijl anderen met bossen stroo
en rijshout kwamen aanzeulen, die zij in de naburige boerderijen hadden
gevonden. De toortsen van oud geteerd touw werden in het stroo geworpen
en weldra sloegen de vlammen uit de ramen.1

En terwijl de verschrikte dorpelingen uit de verte den brand hunner kerk


stonden aan te zien, klonk over de stille velden het psalmgezang der
aftrekkende Geuzen:

Dit sij de loon in allen landen


Mijner moedwillige vianden;
Laet sulcks de kwade tong beërven,
Die met list soecken mijn verderven.
Maar Gij, o Heer, in desen noot,
Help mij om Uws naems wille groot.

1 In de jaren 1567 en 1568 werden door de Boschgeuzen in West-Vlaanderen de kerken


verwoest te Herzeele, Houtkerken, Hondschoten, Killem, Oost-cappel, Winnezeele,
Oudezeelen, Reynighelst, Lokeren, Kemmele en Dracoultre.
De namen der door hen in die jaren vermoorde dorpsgeestelijken zijn: Henricus Turck,
pastoor van Oostcappel, Martinus Necrosius, pastoor van Hondschoten, Franciscus de la
Fosse, pastoor van Rexspoede, Antonius van den Clyte, pastoor van Ruebrouck, Petrus
Famelast, pastoor van Richebourg (Wynckius, Histoire des Gueux-des-Bois). ↑
XIII.

Op een van de hoogste toppen aan de landzijde van het breede en woeste
duin tusschen Nieuwpoort en Duinkerken stond op een fraaien
Septembermorgen Jacob Martens, op zijn vuurroer geleund, en liet zijn
oogen weiden over het schoone landschap van West-Vlaanderen, dat hij van
zijn hooge standplaats uren in de rondte kon overzien.

Hij stond daar als schildwacht. In een duinpan, aan den voet van den top,
waar hij post had gevat, zat een kleine troep gewapenden om de glimmende
kolen van het houtvuur, waarbij zij den nacht hadden doorgebracht. ’t Was
een wachtpost der Wilde Geuzen, die hier was geplaatst om de wegen in ’t
oog te houden, die van Yperen en Rousselaere naar het duin en dan langs de
zandsporen naar Nieuwpoort en Duinkerken voerden. Sinds eenigen tijd
hield de groote bende der Boschgeuzen zich op in de woeste duinstreek,
waar zij een toevluchtsoord hadden moeten zoeken, toen zij door de troepen
der Regeering uit hunne schuilhoeken in de bosschen en moerassen bij
Yperen verdreven waren. De naderende komst van Alva had de
bevelhebbers van de vendels der Landvoogdes tot nieuwe werkzaamheid
geprikkeld. De geduchte en gestrenge aanvoerder zou zeker rekenschap
vorderen van hen, die niet hadden gedaan wat zij konden, om het land van
de pest der plunderende Geuzenbenden te verlossen. Troepen waren
aangerukt uit Yperen en Gent en hadden de vluchtelingen in hunne
schuilhoeken opgezocht. Verbitterd hadden de ballingen gevochten, maar de
overmacht was te groot. Zij hadden moeten wijken. Sommigen waren naar
Frankrijk gevlucht, maar de meesten hadden zich verborgen in het woeste
duin, waar zij veilig waren. Velen van hen waren uit die streken; zij kenden
de verborgen paden, de diepe valleien, de verborgen duinpannen. Er zou
een betrekkelijk groote macht noodig zijn geweest, om hen daar op te
zoeken en uiteen te jagen, en werd die op hen afgezonden, dan konden zij
gemakkelijk vluchten voor een vijand, die het terrein niet kende.
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like