Questions 3rd Edition Narasimha Karumanchi
Questions 3rd Edition Narasimha Karumanchi
com
https://ebookgate.com/product/coding-interview-
questions-3rd-edition-narasimha-karumanchi/
https://ebookgate.com/product/it-interview-questions-a-primer-
for-the-it-job-interviews-concepts-problems-and-interview-
questions-first-edition-karumanchi/
https://ebookgate.com/product/cracking-the-coding-interview-
fourth-edition-150-programming-interview-questions-and-solutions-
gayle-laakmann/
https://ebookgate.com/product/cracking-the-coding-
interview-150-programming-questions-and-solutions-5th-revised-
enlarged-edition-gayle-laakmann-mcdowell/
https://ebookgate.com/product/case-interview-questions-for-tech-
companies-155-real-interview-questions-and-answers-1st-edition-
lin/
Data structures and algorithms made easy in Java data
structure and algorithmic puzzles 2nd Edition Narasimha
Karumanchi
https://ebookgate.com/product/data-structures-and-algorithms-
made-easy-in-java-data-structure-and-algorithmic-puzzles-2nd-
edition-narasimha-karumanchi/
https://ebookgate.com/product/how-to-succeed-at-interviews-
includes-over-200-interview-questions-3rd-edition-rob-yeung/
https://ebookgate.com/product/software-testing-interview-
questions-computer-science-1st-edition-s-koirala/
https://ebookgate.com/product/coding-tricks-and-tips-3rd-edition/
https://ebookgate.com/product/96-great-interview-questions-to-
ask-before-you-hire-second-edition-paul-falcone/
Coding
Interview
Questions
By
Narasimha Karumanchi
Copyright ©2017 by CareerMonk.com
All rights reserved.
Designed by Narasimha Karumanchi
All rights reserved. No part of this book may be reproduced in any form or by any electronic or mechanical means, including
information storage and retrieval systems, without written permission from the publisher or author
Acknowledgements
Mother and Father, it is impossible to thank you adequately for everything you have done, from
loving me unconditionally to raising me in a stable household, where your persistent efforts and
traditional values taught your children to celebrate and embrace life. I could not have asked for
better parents or role-models. You showed me that anything is possible with faith, hard work and
determination.
This book would not have been possible without the help of many people. I would like to thank
them for their efforts in improving the end result. Before we do so, however, I should mention that
I have done my best to correct the mistakes that the reviewers have pointed out and to accurately
describe the protocols and mechanisms. I alone am responsible for any remaining errors.
First and foremost, I would like to express my gratitude to many people who saw me through this
book, to all those who provided support, talked things over, read, wrote, offered comments,
allowed me to quote their remarks and assisted in the editing, proofreading and design. In
particular, I would like to thank the following individuals:
• Mohan Mullapudi, IIT Bombay, Architect, dataRPM Pvt. Ltd.
• Navin Kumar Jaiswal, Senior Consultant, Juniper Networks Inc.
• A. Vamshi Krishna, IIT Kanpur, Mentor Graphics Inc.
• Ramanaiah, Lecturer, Nagarjuna Institute of Technology and Sciences, MLG
-Narasimha Karumanchi
M-Tech, IIT Bombay
Founder, CareerMonk.com
Preface
Dear Reader,
Please Hold on! I know many people do not read the preface. But I would strongly recommend
that you go through the preface of this book at least. The reason for this is that this preface
hassomething different to offer.
This book assumes you have some basic knowledge about computer science. The main objective
of the book is not to give you the theorems and proofs about Data Structures and Algorithms. I
have followed a pattern of improving the problem solutions with different complexities (for each
problem, you will find multiple solutions with different, and reduced complexities). Basically,
it’s an enumeration of possible solutions. With this approach, even if you get a new question it
will show you a way to think about all possible solutions. This book is very useful for interview
preparation, competitive exams preparation, and campus interview preparations.
As a job seeker if you read the complete book with good understanding, I am sure you will
challenge the interviewers and that is the objective of this book.
This book is very useful for the students of Engineering Degree and Masters during their
academic preparations. In all the chapters you will see that more importance has been given to
problems and their analysis instead of theory. For each chapter, first you will read about the basic
required theory and this will be followed by a section on problem sets. There are approximately
700 algorithmic problems and all of them are with solutions.
In most the chapters you will see more importance given to problems and analyzing them instead
of concentrating more on theory. For each chapter, first you will see the basic required theory and
then followed by problems.
For many problems, multiple solutions are provided with different levels of complexities. We
start with the brute force solution and slowly move towards the best solution possible for that
problem. For each problem we will try to understand how much time algorithm takes and how
much memory the algorithm uses.
It is recommended that the reader does at least one complete reading of this book to get full
understanding of all the topics that are covered. In subsequent readings you can skip directly to
any chapter to refer to a specific topic. Even though, enough readings have been done for the
purpose of correcting errors, there could be some minor typos in the book. If any such typos are
found, they will be updated at www.CareerMonk.com. I request that you frequently monitor this
site for any corrections, new problems and solutions. Also, please provide your valuable
suggestions at: [email protected].
Wish you all the best. I am sure that you will find this book useful.
-Narasimha Karumanchi
M-Tech, IIT Bombay
Founder, CareerMonk.com
Table of Contents
1. Programming Basics
1.1 Variables
1.2 Data types
1.3 Data Structure
1.4 Abstract Data Types (ADTs)
1.5 Memory and Variables
1.6 Pointers
1.7 Techniques of Parameter Passing
1.8 Binding
1.9 Scope
1.10 Storage Classes
1.11 Storage Organization
1.12 Programming Techniques
1.13 Basic Concepts of OOPS
2. Scripting Languages
2.1 Interpreter versus Compiler
2.2 What Are Scripting Languages?
2.3 Shell Scripting
2.4 PERL [Practical Extraction and Report Language]
2.5 Python
6. Database Concepts
6.1 Glossary
6.2 Questions on Database Concepts
7. Brain Teasers
7.1 Questions on Brain Teasers
8. Algorithms Introduction
8.1 What is an Algorithm?
8.2 Why the Analysis of Algorithms?
8.3 Goal of the Analysis of Algorithms
8.4 What is Running Time Analysis?
8.5 How to Compare Algorithms
8.6 What is Rate of Growth?
8.7 Commonly Used Rates of Growth
8.8 Types of Analysis
8.9 Asymptotic Notation
8.10 Big-O Notation
8.15 Omega-Ω Notation
8.16 Theta-Θ Notation
8.17 Why is it called Asymptotic Analysis?
8.18 Guidelines for Asymptotic Analysis
8.19 Simplyfying properties of asymptotic notations
8.20 Commonly used Logarithms and Summations
8.21 Master Theorem for Divide and Conquer Recurrences
8.22 Problems on Divide and Conquer Master Theorem
8.23 Master Theorem for Subtract and Conquer Recurrences
8.24 Variant of Subtraction and Conquer Master Theorem
8.25 Method of Guessing and Confirm
8.26 Amortized Analysis
8.27 Problems with Solutions on Algorithms Analysis
11. Stacks
11.1 What is a Stack?
11.2 How Stacks are used?
11.3 Stack ADT
11.4 Applications
11.5 Implementation
11.6 Comparison of Implementations
11.7 Problems with Solutions on Stacks
12. Queues
12.1 What is a Queue?
12.2 How are Queues Used?
12.3 Queue ADT
12.4 Exceptions
12.5 Applications
12.6 Implementation
12.7 Problems with Solutions on Queues
13. Trees
13.1 What is a Tree?
13.2 Glossary
13.3 Binary Trees
13.4 Types of Binary Trees
13.5 Properties of Binary Trees
13.6 Binary Tree Traversals
13.7 Generic Trees (N-ary Trees)
13.8 Threaded Binary Tree [Stack/Queue less] Traversals
13.9 Expression Trees
13.10 XOR Trees
13.11 Binary Search Trees (BSTs)
13.12 Balanced Binary Search Trees
13.13 AVL (Adelson-Velskii and Landis) Trees
13.14 Other Variations in Trees
17. Searching
17.1 What is Searching?
17.2 Why do we need Searching?
17.3 Types of Searching
17.4 Unordered Linear Search
17.5 Sorted/Ordered Linear Search
17.6 Binary Search
17.7 Interpolation Search
17.8 Comparing Basic Searching Algorithms
17.9 Symbol Tables and Hashing
17.10 String Searching Algorithms
17.11 Searching: Problems & Solutions
20. Hashing
20.1 What is Hashing?
20.2 Why Hashing?
20.3 HashTable ADT
20.4 Understanding Hashing
20.5 Components of Hashing
20.6 Hash Table
20.7 Hash Function
20.8 Load Factor
20.9 Collisions
20.10 Collision Resolution Techniques
20.11 Separate Chaining
20.12 Open Addressing
20.13 Comparison of Collision Resolution Techniques
20.14 How Hashing Gets O(1) Complexity?
20.15 Hashing Techniques
20.16 Problems for which Hash Tables are not suitable
20.17 Bloom Filters
20.18 Hashing: Problems & Solutions
IT Interview Questions
Elements of Computer Networking
Data Structures and Algorithms Made Easy (C/C++)
x2 + 2y – 2 = 1
We don’t have to worry about the use of this equation. The important thing that we need to
understand is that the equation has names (x and y), which hold values (data). That means the
names (x and y) are placeholders for representing data. Similarly, in computer science
programming we need something for holding data, and variables is the way to do that.
1.2 Data types
In the above-mentioned equation, the variables x and y can take any values such as integral
numbers (10, 20), real numbers (0.23, 5.5), or just 0 and 1. To solve the equation, we need to
relate them to the kind of values they can take, and data type is the name used in computer science
programming for this purpose. A data type in a programming language is a set of data with
predefined values. Examples of data types are: integer, floating point, unit number, character,
string, etc.
Computer memory is all filled with zeros and ones. If we have a problem and we want to code it,
it’s very difficult to provide the solution in terms of zeros and ones. To help users, programming
languages and compilers provide us with data types. For example, integer takes 2 bytes (actual
value depends on compiler), float takes 4 bytes, etc. This says that in memory we are combining
2 bytes (16 bits) and calling it an integer. Similarly, combining 4 bytes (32 bits) and calling it a
float. A data type reduces the coding effort. At the top level, there are two types of data types:
• System-defined data types (also called Primitive data types)
• User-defined data types.
System-defined data types (Primitive data types): Data types that are defined by system
are called primitive data types. The primitive data types provided by many programming
languages are: int, float, char, double, bool, etc. The number of bits allocated for each primitive
data type depends on the programming languages, the compiler and the operating system. For the
same primitive data type, different languages may use different sizes. Depending on the size of the
data types, the total available values (domain) will also change.
For example, “int” may take 2 bytes or 4 bytes. If it takes 2 bytes (16 bits), then the total possible
values are minus -32,768 to plus 32,767 (-215 to 215-1). If it takes 4 bytes (32 bits), then the
possible values are between -2,147,483,648 and +2,147,483,647 (-231 to 231-1). The same is the
case with other data types.
User defined data types: If the system-defined data types are not enough, then most programming
languages allow the users to define their own data types, called user – defined data types. Good
examples of user-defined data types are: structures in C/C + + and classes in Java. For example,
in the snippet below, we are combining many system-defined data types and calling the user-
defined data type by the name “newType”. This gives more flexibility and comfort in dealing with
computer memory.
1.3 Data Structure
Based on the discussion above, once we have data in variables, we need some mechanism for
manipulating that data to solve problems. Data structure is a particular way of storing and
organizing data in a computer so that it can be used efficiently. A data structure is a special
format for organizing and storing data. General data structure types include arrays, files, linked
lists, stacks, queues, trees, graphs and so on.
Depending on the organization of the elements, data structures are classified into two types:
1) Linear data structures: Elements are accessed in a sequential order but it is not
compulsory to store all elements sequentially (say, Linked Lists). Examples: Linked
Lists, Stacks and Queues.
2) Non – linear data structures: Elements of this data structure are stored / accessed in
a non-linear order. Examples: Trees and graphs.
1.4 Abstract Data Types (ADTs)
Before defining abstract data types, let us consider the different view of system-defined data
types. We all know that, by default, all primitive data types (int, float, etc.) support basic
operations such as addition and subtraction. The system provides the implementations for the
primitive data types. For user-defined data types we also need to define operations. The
implementation for these operations can be done when we want to actually use them. That means,
in general, user defined data types are defined along with their operations.
To simplify the process of solving problems, we combine the data structures with their operations
and we call this Abstract Data Types (ADTs). An ADT consists of two parts:
1. Declaration of data
2. Declaration of operations
Commonly used ADTs include: Linked Lists, Stacks, Queues, Priority Queues, Binary Trees,
Dictionaries, Disjoint Sets (Union and Find), Hash Tables, Graphs, and many others. For
example, stack uses a LIFO (Last-In-First-Out) mechanism while storing the data in data
structures. The last element inserted into the stack is the first element that gets deleted. Common
operations are: creating the stack, pushing an element onto the stack, popping an element from the
stack, finding the current top of the stack, finding the number of elements in the stack, etc.
While defining the ADTs do not worry about the implementation details. They come into the
picture only when we want to use them. Different kinds of ADTs are suited to different kinds of
applications, and some are highly specialized to specific tasks. By the end of this book, we will
go through many of them and you will be in a position to relate the data structures to the kind of
problems they solve.
1.5 Memory and Variables
First let’s understand the way memory is organized in a computer. We can treat the memory as an
array of bytes. Each location is identified by an address (index to array). In general, the address 0
is not a valid memory location. It is important to understand that the address of any byte (location)
in memory is an integer. In the diagram below n value depends on the main memory size of the
system.
To read or write any location, CPU accesses it by sending its address to the memory controller.
When we create a variable (for example, in C: int X), the compiler allocates a block of
contiguous memory locations and its size depends on the size of the variable.
The compiler also keeps an internal tag that associates the variable name X with the address of
the first byte allocated to it (sometimes called symbol table). So when we want to access that
variable like this: X = 10, the compiler knows where that variable is located and it writes the
value 10.
Size of a Variable: Sizeof operator is used to find size of the variable (how much memory a
variable occupies). For example, on some computers, sizeof (X) gives the value 4. This means an
integer needs 4 contiguous bytes in memory. If the address of X is 2000, then the actual memory
locations used by X are: 2001, 2002, 2003, and 2004.
Address of a Variable: In C language, we can get the address of a variable using address – of
operator (&). The code below prints the address of X variable. In general, addresses are printed
in hexadecimal as they are compact and also easy to understand if the addresses are big.
1.6 Pointers
Pointers are also variables which can hold the address of another variable.
To declare a pointer, we have to specify the type of the variable it will point to. That means we
need to specify the type of the variable whose address it is going to hold. The declaration is very
simple. Let us see some examples of pointer declarations below:
Here ptr1 is a pointer that can point to an int variable, ptr2 can point to a float, ptr3 to an
unsigned int, and ptr4 to a char. Finally ptr5 is a pointer that can point to anything. These
pointers are called void pointers, and there are some restrictions on what we can do with void
pointers.
As we said, pointers hold addresses. That means we can assign the address of a variable to it. Let
us consider the sample code below:
Here, we first declare an integer named X and initialize it to the value 10. Then we create a
pointer to int named ptr and assign the address of X to it. This is called, “making the pointer ptr
point to X.” A common operation is done with a pointer and is called indirection. It is a way to
access the contents of the memory that it points to. The indirection operator is represented by the
asterisk symbol. Do not confuse this operator with the use of the same asterisk symbol in the
declaration of pointers. They are not the same thing. If we would like to access the contents of the
memory where ptr points to, we will do it like this: * ptr. Let’s see a small code that shows
pointer indirections.
Here we first declare X and ptr just like before. Then we print X (which is10), followed by ptr,
i.e., the contents of the variable ptr which is an address; the address of X. And finally we print *
ptr, which is the value of the memory location where ptr points to (again 10, since it points to the
location occupied by the variable X in memory).
Finally we change the contents of the location where ptr points to by writing * ptr = 25. This
means assign the value 25 to wherever ptr is pointing to. Note that when we do that, what is
actually happening is that the value of X is being modified. This is because, ptr holds the address
of X, and changing the contents of the memory at that address changes the value of X.
One limitation of void pointers, i.e. pointers that can point to any type, is that they cannot be
dereferenced. This is because each variable type takes different amount of memory. On a 32-bit
computer for example usually an int needs 4 bytes, while a short 2 bytes. So in order to read the
actual value stored there, the compiler has to know how many consecutive memory locations to
read in order to get the full value.
Pointers are useful as they allow us to perform arithmetic operations on them. This might be
obvious to the careful reader, since we said that pointers are just integers. However, there are a
few small differences on pointer arithmetic that make their use even more intuitive and easy. Try
the following code:
We declare a pointer named cptr and assign the address 2 to it. We print the contents of the
pointer (i.e. the address 2), increment it, and print again. Sure enough the first time it prints 2 and
then 3, and that was exactly what we expected. However try this one as well:
Now the output, on my computer, is iptr before: 2 and after: 6! Why does this pointer point to the
address 6 after it is incremented by one and not to 3 as the previous pointer? The answer lies with
what we said about the size of variables. An int is 4 bytes on my computer. This means that if we
have an int at address 2, then that int occupies the memory locations 2, 3, 4 and 5.
In order to access the next int we have to look at the address 6, 7, 8 and 9. Thus when we add one
to a pointer, it is not the same as adding one to any integer; it means give me a pointer to the next
variable which for variables of type int, in this case, is 4 bytes ahead. The reason that in the first
example with the char pointer, the actual address after incrementing, was one more than the
previous address is because the size of char is exactly 1. So the next char can indeed be found on
the next address.
Another limitation of void pointers is that we cannot perform arithmetic on them, since the
compiler cannot know how many bytes ahead the next variable is located. So void pointers can
only be used to keep addresses that we have to convert later on to a specific pointer type, before
using them.
1.6.4 Arrays and Pointers
There is a strong connection between arrays and pointers. So strong in fact, that most of the time
we can treat them as one and the same. The name of an array can be considered just as a pointer
to the beginning of a memory block as big as the array. So for example, making a pointer point to
the beginning of an array is done in exactly the same way as assigning the contents of a pointer to
another:
And then we can access the contents of the array through the pointer as if the pointer itself was
that array. For example this: ptr[2] = 25 is perfectly legal. Furthermore, we can treat the array
itself as a pointer, for example, * array = 4 is equivalent to array[0] = 4. In general * {array + n)
is equivalent to array[n].
The only difference between an array, and a pointer to the beginning of an array, is that the
compiler keeps some extra information for the arrays, to keep track of their storage requirements.
For example if we get the size of both an array and a pointer using the sizeof operator, sizeof(ptr)
will give us how much space does the pointer itself occupies (4 on my computer), while sizeof
array will give us, the amount of space occupied by the whole array (on my computer 20,10
elements of 2 bytes each).
In the earlier sections, we have seen that pointers can hold addresses of other variables. There is
another use of pointers: pointers can hold addresses of memory locations that do not have a
specific compile-time variable name, but are allocated dynamically while the program runs
(sometimes such memory is called heap).
To allocate memory during runtime, C language provides us the facility interms of malloc
function. This function allocates the requested amount of memory, and returns a pointer to that
memory. To deallocate that block of memory, C supports it by providing free function.
This function takes the pointer as an argument. For example, in the code below, an array of 5
integers is allocated dynamically, and then deleted.
In this example, the count * sizeof (int) calculates the amount of bytes we need to allocate for the
array, by multiplying the number of elements, to the size of each element (i.e. the size of one
integer).
Like data, executable code (including functions) is also stored in memory. We can get the address
of a function. But the question is what type of pointers do we use for that purpose? In general, we
use function pointers and they store the address of functions. Using function pointers we can call
the function indirectly. But, function pointers manipulation has its limitation: it is limited to
assignment and indirection and cannot do arithmetic on function pointers. Because for function
pointers there is no ordering (functions can be stored anywhere in memory). The following
example illustrates how to create and use function pointers.
First we create a pointer that can point to functions accepting an int as an argument and returning
int, named fptr. Then we make fptr point to the function1, and proceed to call it through the fptr
pointer, to print the function1 of 5. Finally, we change fptr to point to function2, and call it again
in exactly the same manner, to print the function2 of 10.
1.7 Techniques of Parameter Passing
Before starting our discussion on parameter passing techniques, let us concentrate on the
terminology we use.
Let us assume that a function B() is called from another function A(). In this case, A is called the
caller function and B is called the called function or callee function. Also, the arguments which
A sends to B are called actual arguments and the parameters of B function are called formal
arguments. In the example below, the func is called from main function. main is the caller
function and func is the called function. Also, the func arguments param1 and param2 are formal
arguments and i,j of main function are actual arguments.
This method uses in-mode semantics. A formal parameter is like a new local variable that exists
within the scope of the procedure/function/subprogram. Value of actual parameter is used to
initialize the formal parameter. Changes made to formal parameter do not get transmitted back to
the caller.
If pass by value is used then the formal parameters will be allocated on stack like a normal local
variable. This method is sometimes called call by value. Advantage of this method is that, it
allows the actual arguments not to modify.
In general the pass by value technique is implemented by copy and it has the following
disadvantages:
• Inefficiency in storage allocation
• Inefficiency in copying value
• Costly copy semantics for objects and arrays
Example: In the following example, main passes func two values: 5 and 7. The function func
receives copies of these values and accesses them by the identifiers a and b. The function func
changes the value of a. When control passes back to main, the actual values of x and y are not
changed.
The output of the program is: In func, a = 12 b = 7. In main, x = 5 y = 7
This method uses out-mode semantics. A formal parameter is a new local variable that exists
within the scope of the function. No value is transmitted from actual arguments to formal
arguments. Just before control is transferred back to the caller, the value of the formal parameter
is transmitted back to the actual parameter.
This method is sometimes called call by result. Actual parameter must be a variable. foo(x) and
foo(a[1]) are fine but not foo(3) or foo(x * y).
Let us assume that there is a function write(p1,p1). If the two formal parameters in write had
different names, which value should go into p1? Order in which actual parameters are copied
determines their value. In general the pass by result technique is implemented by copy and it has
the following disadvantages:
• Inefficiency in storage allocation
• Inefficiency in copying value
• For objects and arrays, the copy semantics are costly
• We cannot use the value of actual argument for initializing the formal argument
Example: Since C does not support this technique, let us assume that the syntax below is not
specific to any language.
In the following example, main uses two variables x and y. They both were passed to func. Since
this is pass by result technique, the values of x and y will not be copied to formal arguments. As a
result, the variables a and b of func should be initialized. But in the function only b is initialized.
For this reason, the value of a is unknown, whereas the value of b is 5. After the function
execution, the values of a and b will be copied to x and y.
The output of the program is: In func, a = garbage value b = 5. In main, x = garbage value y = 5.
Pass by Value – Result shares with Pass – by – Value and Pass – by – Result. The disadvantage
is that it requires multiple storage parameters and time for copying values. Shares with Pass-by-
Result the problem associated with the order in which actual parameters are assigned. So this
technique has some advantages and some disadvantages.
Example: Since C does not support this technique, let us assume that the syntax below is not
specific to any language.
In the following example, main uses two variable x and y. They both were passed to func. Since
this is pass by value-result technique, the values of x and y will be copied to formal arguments.
As a result, the variables a and b of func will get 5 and 7 respectively.
In the func, the values a and b are modified to 10 and 5 respectively. After the function execution,
the values of a and b will be copied to x and y. The disadvantage of this method is that, for each
argument a new allocation is created.
The output of the program is: In func, a = 10 b = 5. In main, x = 10 y = 5
This technique uses inout-mode semantics. Formal parameter is an alias for the actual parameter.
Changes made to formal parameter do get transmitted back to the caller through parameter
passing. This method is sometimes called call by reference or aliasing. This method is efficient
in both time and space. Disadvantages of aliasing are:
• Many potential scenarios can occur
• Programs are not readable
Example: In C, the pointer parameters are initialized with pointer values when the function is
called. When the function swapnum() is called, the actual values of the variables a and b are
exchanged because they are passed by reference.
The output is: A is 20 and B is 10
Rather than using pass-by-reference for input/output parameters, Algol used the more powerful
mechanism of Pass – by – Name. In essence, you can pass in the symbolic “name”, of a variable,
which allows it both to be accessed and updated. For example, to double the value of C[j], you
can pass its name (not its value) into the following procedure.
Basically there are two types of bindings: static binding and dynamic binding.
Static binding occurs before runtime and doesn’t change during execution. This is sometimes
called early binding.
Examples:
• Bindings of values to constants in C
• Bindings of function calls to function definitions in C
Dynamic binding occurs or changes at runtime. This is sometimes called late binding.
Examples:
• Bindings of pointer variables to locations
• Bindings of member function calls to virtual member function definitions in C + +
1.9 Scope
A scope is a program section of maximal size in which no bindings change, or at least in which no
redeclarations are permitted. The scope rules of a language determine how references to names
are associated with variables. Basically there are two types of scoping techniques: static scoping
and dynamic scoping.
Static scope is defined in terms of the physical structure of the program. The determination of
scopes can be made by the compiler. That means, bindings are resolved by examining the program
text. Enclosing static scopes (to a specific scope) are called its static ancestors and the nearest
static ancestor is called a static parent. Variables can be hidden from a unit by having a “closer”
variable with the same name. Ada and C + + allow access to these (e.g. class_name∷ name).
Most compiled languages, C and Pascal included, use static scope rules.
Example-1: Static scope rules: Most closest nested rule used in blocks
To resolve a reference, we examine the local scope and statically enclosing scopes until a
binding is found.
Example-2: Static scope in nested function calls. In the code below, with static scoping, the count
variable of fun2 takes the value of global variable value (10).
1.9.2 Dynamic Scope
Dynamic scope rules are usually encountered in interpreted languages. Such languages do not
normally have type checking at compile time because type determination isn’t always possible
when dynamic scope rules are in effect.
In dynamic scoping, binding depends on the flow of control at run time and the order in which
functions are called, refers to the closest active binding. If we look at the second example of
static scoping, the count variable of fun2 takes the value of fun1 variable value (20). This is
because, during runtime the fun2 is called from fun1 which in turn called from main. That means
fund looks at the stack and starts searching in the back ward direction.
Let us take another example. In the code below, the count variable of func3 takes the count value
of funct1().
Note: For the above example, if we use static scope then the count variable of func3 takes the
value of global count variable (10).
1.10 Storage Classes
Let us now consider the storage classes in C. The storage class determines the part of memory
where storage is allocated for the variable or object and how long the storage allocation
continues to exist. It also determines the scope which specifies the part of the program over which
a variable name is visible, i.e. the variable is accessible by name. There are four storage classes
in C are automatic, register, external, and static.
This is the default storage class in C. Auto variables are declared inside a function in which they
are to be utilized. Also, keyword auto (e.g. auto int number;) is used for declaring the auto
variables. These are created when the function is called and destroyed automatically when the
function is exited. This variable is therefore private) local) to the function in which it is declared.
Variables declared inside a function without storage class specification is, by default, an
automatic variable.
Any variable local to main will normally live throughout the whole program, although it is active
only in main. During recursion, the nested variables are unique auto variables. Automatic
variables can also be defined within blocks. In that case they are meaningful only inside the
blocks where they are declared. If automatic variables are not initialized they will contain
garbage.
Example:
1.10.2 Extern storage class
These variables are declared outside any function. These variables are active and alive
throughout the entire program. Also known as global variables and default value is zero. Unlike
local variables they are accessed by any function in the program. In case local variable and
global variable have the same name, the local variable will have precedence over the global one.
Sometimes the keyword extern is used to declare this variable. It is visible only from the point of
declaration to the end of the program.
Example-1: The variable number and length are available for use in all three functions
Example-2: When the function references the variable count, it will be referencing only its local
variable, not the global
Example-3: On global variables: Once a variable has been declared global any function can use
it and change its value. The subsequent functions can then reference only that new value.
Example-4: External declaration: As far as main is concerned, y is not defined. So compiler
will issue an error message. There are two ways to solve this issue:
1 Define y before main.
2 Declare y with the storage class extern in main before using it.
Example-5: External declaration: Note that extern declaration does not allocate storage space
for variables
Example-6: If we declare any variable as extern variable then it searches that variable either it
has been initialized or not. If it has been initialized which may be either extern or static* then it is
ok otherwise compiler will show an error. For example:
Example-7: It will search any initialized variable i which may be static or extern.
Example-8: It will search any initialized variable i which may be static or extern.
Example-9: Variable i has been declared but not initialized.
Example-10: A particular extern variable can be declared many times but we can initialize at
only one time. For example:
Example-11:
Example-12: We cannot write any assignment statement globally.
Note: Assigning any value to the variable at the time of declaration is known as initialization
while assigning any value to variable not at the time of declaration is known as assignment.
Example-13:
These variables are stored in one of the machine’s registers and are declared using register
keyword, e.g. register int count;
Since register access is much faster than a memory access, keeping frequently accessed variables
in the register leads to faster execution of program. Since only few variables can be placed in the
register, it is important to carefully select the variables for this purpose. However, C will
automatically convert register variables into non-register variables once the limit is reached.
Don’t try to declare a global variable as register because the register will be occupied during the
lifetime of the program.
The value of static variables persists until the end of the program. It is declared using the
keyword static like:
It may be of external or internal type depending on the place of their declaration. Static variables
are initialized only once, when the program is compiled.
Are those which are declared inside a function? Scope of Internal static variables extends up to
the end of the program in which they are defined. Internal static variables are almost same as auto
variable except they remain in existence (alive) throughout the remainder of the program. Internal
static variables can be used to retain values between function calls. Example: Internal static
variable can be used to count the number of calls made to function.
An external static variable is declared outside of all functions and is available to all the functions
in the program. An external static variable is similar to simple external variable except that the
former is available only within the file where it is defined whereas simple external variable can
be accessed by other files.
Static declaration can also be used to control the scope of a function. If you want a particular
function to be accessible only to the functions in the file in which it is defined and not to any
function in other files, declare the function to be static.
1.11 Storage Organization
When we write a program and execute it, lot of things happen. Now, let us try to understand what
happens internally. Any program we run has some memory associated with it. That memory is
divided into 3 parts as shown below. Storage organization is the process of binding values to
memory locations.
Static Segment: As shown above, the static storage is divided into two parts:
• Code segment: In this part, the programs code is stored. This will not change
throughout the execution of the program. In general, this part is made read-only and
protected. Constants may also be placed in the static area depending on their type.
• Data segment: In simple terms, this part holds the global data. In this part, the
program’s static data (except code) is stored. In general, this part is editable (like
global variables and static variables come under this category). These includes the
following:
○ Global variables
○ Numeric and string-valued constant literals
○ Local variables that retain value between calls (e.g., static variables)
Stack Segment: If a language supports recursion, then the number of instances of a variable that
may exist at any time is unlimited (at least theoretically). In this case, static allocation is not
useful.
As an example, let us assume that a function B() is called from another function A(). In the code
below, the A() has a local variable count. After executing B(), if A() tries to get count, then it
should be able to get its old value. That means, it needs a mechanism for storing the current state
of the function, so that once it comes back from calling function it restores that context and uses its
variables.
To solve these kinds of issues, stack allocation is used. When we call a function, push a new
activation record (also called a frame) onto the run-time stack, which is particular to the function.
Each frame can occupy many consecutive bytes in the stack and may not be of a fixed size. When
the callee function returns to the caller, the activation record of the callee is popped out. In
general the activation record stores the following information:
• Local variables
• Formal parameters
• Any additional information needed for activation
• Temporary variables
• Return address
Heap Segment: If we want to dynamically increase the temporary space (say, through pointers in
C), then the static and stack allocation methods are not enough. We need a separate allocation
method for dealing with these kinds of requests. Heap allocation strategy addresses this issue.
Heap allocation method is required for dynamically allocated pieces of linked data structures and
for dynamically resized objects. Heap is an area of memory which is dynamically allocated. Like
a stack, it may grow and shrinks during runtime.
But unlike a stack it is not a LIFO (Last In First Out) which is more complicated to manage. In
general, all programming languages implementation we will have both heap-allocated and stack
allocated memory.
1.11.1 How do we allocate Memory for both?
One simple approach is to divide the available memory at the start of the program into two areas:
stack and heap.
Heap allocation is performed by searching the heap for available free space. Basically there are
two types of heap allocations.
• Implicit heap allocation: Allocations are done automatically. For example, Java/C#
class instances are placed on the heap. Scripting languages and functional languages
make extensive use of the heap for storing objects.
• Explicit heap allocation: In this method, we need to explicitly tell the system to
allocate the memory from heap. Examples include:
○ statements and/ or functions for allocation and deallocation
○ malloc/free, new/delete
1.11.1.2 Fragmentations
Sometimes the small free blocks will get wasted without allocating to any process and we call
this fragmentation. Basically there are two types of fragmentations:
• Internal heap fragmentation: If the block allocated is larger than required to hold a
given object and the extra space is unused.
• External heap fragmentation: If the unused space is composed of multiple blocks.
No one piece may be large enough to satisfy some future request. That means,
multiple unused blocks, but not one is large enough to be used.
In general, a linked list of free heap blocks is maintained and when a request is made for memory,
then it uses one of the techniques below and allocates the memory.
• First – fit: select the first block in the list that is large enough to satisfy the given
request
• Best – fit: search the entire list for the smallest free block that is large enough to
hold the object
If an object is smaller than the block, the extra space can be added to the list of free blocks. When
a block is freed, adjacent free blocks are merged.
Another random document with
no related content on Scribd:
FOOTNOTES:
[1] An East-Indian dancing girl.
ANATOLE FRANCE, FORMER MAN AND
NEW
The biographies of some great men of letters are little different from
their bibliographies. For many years this would seem to have been
true in the case of Anatole France, for the man of public import—
apart from his literary productions—came not into being until fifty-
three years after his physical birth.
Every book-lover who goes to Paris must visit the banks of the Seine
and revel among the riches of that vast exhibition of old books, art
objects, rare prints, and fascinating what-not, which for generations
have been the despair and the admiration of collectors. Over an old-
book mart on the Quai Malaquis, Jacques Anatole Thibault—now
everywhere known as Anatole France—was born April 16, 1844.
From that day to this he has never left as a residence that Paris
whose every paving-block he knows, as he himself says, and whose
every stone he loves. Year by year he has increasingly stood as a
type of Parisian literary life and thought.
His father was one of the prosperous booksellers of the Seine banks
—meditative, thoughtful, and even a maker of verses. He brought
with him from Anjou in western France all of the Vendéean’s passion
for monarchism and clericalism. Just how this harmonizes with the
assertion of one of our author’s biographers that the elder Thibault
was of Jewish blood, I do not pretend to say, but the statement may
pass on its face value. Certain it is that the father was concerned
that Anatole should be educated under the auspices of clerical
teachers, the priests of the old Collège Stanislas, and his son’s early
mastery of the classics and attainments in literary style amply
justified the choice. Indeed, the clerical schools of the period did
more to establish French letters than has since proven to be the
case under the public schools of present-day France.
Growing up in this bookish atmosphere, rich tokens of the past all
about him, inheriting his father’s scholarly tastes, trained under the
rigid system of classicists, and in the school that developed Paul
Bourget and François Coppée, Anatole France needed only one more
element to bring out in him the varied temperament his life and
works exhibit—the inspiration of the refined and tender mother
whose love for romantic fairy-tales charmed into being the first
fancy-creations of her gifted boy.
In 1868 M. France produced his first book—a study of Alfred de
Vigny. This made no great sensation, but his first volume of poems—
many French literary men, like Daudet, Maupassant, and Bourget,
have opened their literary careers with essays at verse—was
published in 1873, Les Poèmes dorés.
About this time M. France became reader for the publisher Lemerre,
and under his auspices brought out various of the thirty-some
volumes which stand to his credit. In 1876 he became an attaché of
the Senate library. Later, he was known as a regular contributor to
Le Temps and other Parisian journals, much of this review material
being now accessible in book-form.
That part of M. France’s work which covers the first twenty years of
his writing, ending with 1896, has largely fixed his place in the
average opinion, for two reasons: those years witnessed his largest
and most popular production, including nearly all of his novels and
stories; and, in consequence, the preponderance of published critical
estimates cover only those two decades.
The “first” Anatole France, then, must be considered almost as a
separate being, so far as we regard his spirit; his literary style,
however, changed scarcely at all with time. Classical training was
reflected in a passion for the Greek magic of words, Latin harmony
of phrasing, and the hedonistic philosophy; there was not even the
suggestion of his later direct appeal to reason and “the rights of
man.” His personal tone—for much of his writing is personal and
even autobiographical—was pessimistic, though untinged with
bitterness; and here again there was little to forecast his vigorous
appeal for a social better day. No thought of social uplift, no ray of
hope, appeared in his treatment of Thaïs, a study of the Egypt of the
Ptolemies; The Red Lily, a picture of present-day Florence; The
Opinions of M. Jérome Coignard, the modernization of sentiments
exploited in Rabelais, “Wilhelm Meister,” “Gil Blas,” and Montaigne;
The Garden of Epicurus, wherein the shades of great thinkers, from
Plato to Schopenhauer, hold converse, “while an Esquimaux refutes
Bossuet, a Polynesian develops his theory of the soul, and Cicero
and Cousin agree in their estimate of a future life.” In a word, the M.
France of those days viewed life as a spectacle, with dispassionate
yet pitying irony. Convinced, with the Preacher, that all is vanity, this
dilettante proposed no remedies for its ills, and was even frankly
skeptical that any such saving medicine existed. This is Anatole
France as most readers know him—the Anatole France who “died”
fifteen years ago, leaving only the stylist and the keen observer to
identify him with the decidedly living man of to-day.
Two important events in the life of our author took place respectively
in 1896 and 1897. In the former year he was elected on the first
ballot to a seat in the French Academy—the seat occupied by
Ferdinand de Lesseps, and on the occasion of his séance de
réception M. France delivered a tactful and altogether admirable
eulogy upon the unfortunate genius whom he succeeded.
This distinction coming after more than fifty years of life would have
been enough to mark an epoch in his career, but one year later he
issued L’Orme du Mail, a series of notable comments upon
contemporary literary and social life. This may be regarded as the
outgrowth of the social, political, and literary notes which he had
been contributing to the newspapers, and which have been gathered
in several volumes, forming probably the most brilliant commentary
upon things French which is available to-day.
Doubtless this daily observation of the current trend gave birth to a
new man, for now Anatole France is no longer the satirical and
lightly ironical dilettante making excursions into the field of
speculation, but a robust devotee of the rights of the people. His
powerful arraignments of the social and political condition of the
French common-people are not the only proofs of a new birth in M.
France. Trenchant, witty, and apostolic as are his social sermons—for
now and then a sermon may ring true to its word-origin and be a
thrust—they were not so amazing and, happily, not so significant, as
his brave championship of the cause of Captain Dreyfus when there
were few who dared to lift voice against rampant militarism and a
prejudiced, Jew-baiting military tribunal.
From this courageous stand it was only a single step to a
propagandum to abolish the many abuses which he feels weigh
heavily upon the masses—war, plutocracy, clericalism, militarism. I
have said that it was only a single step, yet it represents a long
journey for the son of a monarchist, a boy educated by priests, the
smiling literary experimenter, the speculative pupil of Rénan, to have
mounted the Socialistic rostrum and produced anti-military and anti-
clerical papers of no doubtful sound. Such is M. France to-day; and
though he still fails not in his literary appeal to the intellectuals, the
cry that deeply stirs his being is that of the proletariat in need of
intelligent, vigorous leadership. Whether or not one agrees with his
propagandum, one cannot ignore its significance.
Anatole France has attained distinction in several literary forms. His
early poems are not of sufficient merit to make him famous, but they
consist of a piquant combination—humor, history, and philosophy.
His critical introductions to delightful editions of famous books are
charmingly done and sufficiently discriminating. His tractates on
questions of the times are earnest, direct, and vigorous. But it is to
his novels and stories that we must look to find his most
characteristic writings.
To the English reader, his best-known novel is The Crime of Sylvestre
Bonnard (1881), which was crowned by the Academy. Like all of M.
France’s novels, it is practically plotless—a fictional framework for
the skeptical observations and good-natured ironies of the old
philosopher, whose name gives the book its title. A second novel of
distinction, if novel it may be called, is The Book of Friendship (le
Livre de Mon Ami). It is made up of two parts—The Book of Peter
and The Book of Suzanne. The former owes its interest not alone to
charm of style, childlikeness of recital, and subtle beauty, but also to
its autobiographical character—which M. France has frankly
admitted. Three other works immediately rise up for comparison
when one reads this keen, sympathetic, and understanding story—
Dickens’s David Copperfield, Daudet’s Little What’s-His-Name (le
Petit Chose), and Loti’s The Story of a Child; and the very fact of
such inevitable comparisons may sufficiently suggest its ingenuous
charm, its pseudo-naïvete, and its mingled humor and pathos. No
Frenchman, except Victor Hugo, quite entered into child-life as did
M. France in this notable compound of fiction and fact, and I am not
forgetting either Alphonse Daudet or Gustav Droz in making this
assertion.
The inheritance of his mother’s love for fantasy is beautifully
illustrated in M. France’s Abeille, a fairy story of perhaps twenty-
thousand words. The author’s name will vouch for its style; the
simple outline will show the pretty framework for the fictional
conception.
La Duchesse des Clarides brings up her daughter Abeille, together
with Georges, the only son of la Comtesse Blanchelande, who at her
death had confided him to the care of her friend.
The two children one day set out secretly to find the distant lake
which they have seen from the high tower of the castle of Clarides.
The lake is the home of the Ondines, and the woods surrounding it
the realm of the Gnomes. Georges, seeking water and food for
Abeille, is seized by the Ondines. Abeille, waiting for Georges’ return,
falls asleep, to be wakened by the Gnomes, who carry her to their
King Loc. They keep Abeille in order to teach her the wisdom and
secrets of their race and they make her their Princess. Loc loves
Abeille and offers her all the treasures of his kingdom if she will
become his wife. She refuses, asking only to be sent back to her
mother, whom she is allowed to see each night in a dream, as her
mother also sees her. Loc finally learns that Abeille loves Georges,
but that he has disappeared. The Gnome king discovers that the
youth is with the Ondines, held prisoner because he wishes to leave
the Ondine queen—who also loves him—in order to seek Abeille. Loc
magnanimously rescues Georges and sends him to Clarides, but still
cannot bring himself to free Abeille. The youth learns of the fate of
Abeille from his mother and his serving man, and goes to the Gnome
kingdom to rescue her.
Loc cannot keep Abeille longer because of a law allowing mortals,
prisoners of the Gnomes, to return to the world after seven years, so
he betroths Georges and Abeille and gives them rich gifts, among
which is a magic ring having power to bring Abeille and Georges at
any time to visit the Gnome realm, where they will be always
welcome.
In the volumes, Mother-of-Pearl (L’Etui de Nacre) and St. Clara’s Well
(Le Puits de Sainte-Claire), we find our author’s best short-story
work.
As has been noted in previous introductory papers of this series,
there is a marked tendency among French writers of little fictions to
affect the sketch form, and in this field they have wrought with great
delicacy and spirit. It is hardly to be expected of a writer whose
novels give so much play to epigram, philosophy, dialogue, and witty
comment, that he should seek to tell his shorter stories with the
compression of a Maupassant and the plot-structure of a Mérimée.
But other qualities of the first-rate story-teller he does display—his
narration is lively and witty, and his climaxes are satisfying.
Only two of his short-stories can be given attention in this limited
space, both found in the first-named volume, and one of them
reproduced here in translation.
“The Procurator of Judea” tells in the author’s leisurely, pellucid style
how L. Ælius Lamia, after eighteen years of exile by Tiberius Cæsar,
returns to Rome. During his years of sojourn in Asia, here and there,
he has met Pontius Pilate. Now they meet again, and the physical
bulk of the story is taken up by their reminiscences. Just when that
seems to be all, they fall to discussing the charms of Judæan
women, when Lamia recalls with especial warmth a dancing girl.
“‘Some months after,’” he goes on, “‘I lost sight of her. I learned by
chance that she had attached herself to a small company of men
and women who were followers of a young Galilean thaumaturgist.
His name was Jesus; he came from Nazareth, and he was crucified
for some crime, I don’t know what. Pontius, do you remember
anything about the man?’
“Pontius Pilate contracted his brows, and his hand rose to his
forehead in the attitude of one who probes the deeps of memory.
Then after a silence of some seconds—
“‘Jesus?’ he murmured. ‘Jesus of Nazareth? I cannot call him to
mind.’”
This dramatic episode, which exists only for its climax, is no more
poignant than the pathos of that simple-hearted juggler-monk who
imitated the Widow, in that he gave all that he had.
JUGGLER TO OUR-LADY
(LE JONGLEUR DE NOTRE-DAME)
By Anatole France
Done into English by the Editor
I.
In the time of King Louis, there lived in France a poor juggler, native
of Compiègne, named Barnabas, who went among the villages doing
feats of strength and skill. On market days he would spread out on
the public square an old carpet very much worn, and, after having
attracted the children and the gazing bumpkins by some suitable
pleasantries which he had adopted from an old juggler and which he
never changed at all, he would assume grotesque attitudes and
balance a plate on his nose.
The crowd at first looked at him with indifference. But when,
standing on his hands with his head downward, he tossed in the air
six copper balls which glittered in the sun, and caught them again
with his feet; or when, by bending backward until his neck touched
his heels, he gave his body the form of a perfect wheel, and in that
posture juggled with twelve knives, a murmur of admiration rose
from the onlookers, and pieces of money rained upon the carpet.
However, like the majority of those who live by their talents,
Barnabas of Compiègne had much difficulty in living. Earning his
bread by the sweat of his brow, he bore more than his part of the
miseries connected with the fall of Adam, our father. Moreover, he
was unable to work as much as he would have wished. In order to
show off his fine accomplishment, he needed the warmth of the sun
and the light of day, just as do the trees in order to produce their
blossoms and fruits.
In winter he was nothing more than a tree despoiled of its foliage
and to appearance dead. The frozen earth was hard for the juggler.
And, like the grasshopper of which Marie of France tells, he suffered
from cold and from hunger in the bad season. But, since he
possessed a simple heart, he bore his ills in patience.
He had never reflected upon the origin of riches, nor upon the
inequality of human conditions. He believed firmly that, if this world
is evil, the other cannot fail to be good, and this hope sustained him.
He did not imitate the thieving mountebanks and miscreants who
have sold their souls to the devil. He never blasphemed the name of
God; he lived honestly, and, although he had no wife, he did not
covet his neighbor’s, for woman is the enemy of strong men, as
appears from the history of Samson, which is reported in the
Scriptures.
In truth, he had not a spirit which turned to carnal desires, and it
would have cost him more to renounce the jugs than the women.
For, although without failing in sobriety, he loved to drink when it
was warm. He was a good man, fearing God and very devout toward
the Holy Virgin. He never failed, when he entered a church, to kneel
before the image of the Mother of God and address to her this
prayer:
“Madame, take care of my life until it may please God that I die, and
when I am dead, cause me to have the joys of paradise.”
II.
Well, then, on a certain evening after a day of rain, while he was
walking, sad and bent, carrying under his arm his balls and knives
wrapped up in his old carpet, and seeking for some barn in which he
might lie down supperless, he saw on the road a monk who was
travelling the same way, and saluted him decorously. As they were
walking at an equal pace, they began to exchange remarks.
“Comrade,” said the monk, “how comes it that you are habited all in
green? Is it not for the purpose of taking the character of a fool in
some mystery-play?”
“Not for that purpose, father,” responded Barnabas. “Such as you
see me, I am named Barnabas, and I am by calling a juggler. It
would be the most beautiful occupation in the world if one could eat
every day.”
“Friend Barnabas,” replied the monk, “take care what you say. There
is no more beautiful calling than the monastic state. Therein one
celebrates the praises of God, the Virgin, and the saints, and the life
of a monk is a perpetual canticle to the Lord.”
Barnabas answered:
“Father, I confess that I have spoken like an ignoramus. Your calling
may not be compared with mine, and, although there is some merit
in dancing while holding on the tip of the nose a coin balanced on a
stick, this merit does not approach yours. I should like very well to
sing every day, as you do, Father, the office of the most Holy Virgin,
to whom I have vowed a particular devotion. I would right willingly
renounce my calling, in which I am known from Soissons to
Beauvais, in more than six hundred towns and villages, in order to
embrace the monastic life.”
The monk was touched by the simplicity of the juggler, and, as he
did not lack discernment, he recognized in Barnabas one of those
men of good purpose whereof our Lord said: “Let peace abide with
them on earth!” This is why he replied to him:
“Friend Barnabas, come with me, and I will enable you to enter the
monastery of which I am the prior. He who conducted Mary the
Egyptian through the desert has placed me on your path to lead you
in the way of salvation.”
This is how Barnabas became a monk.
In the monastery where he was received, the brethren emulously
solemnized the cult of the Holy Virgin, and each one employed in her
service all the knowledge and all the ability which God had given
him.
The prior, for his part, composed books which, according to the rules
of scholasticism, treated of the virtues of the Mother of God.
Friar Maurice with a learned hand copied these dissertations on
leaves of vellum.
Friar Alexander painted fine miniatures, wherein one could see the
Queen of Heaven seated upon the throne of Solomon, at the foot of
which four lions kept vigil. Around her haloed head fluttered seven
doves, which are the seven gifts of the Holy Spirit: gifts of fear,
piety, science, might, counsel, intelligence, and wisdom. She had for
companions six golden-haired Virgins: Humility, Prudence,
Retirement, Respect, Virginity, and Obedience. At her feet two small
figures, nude and quite white, were standing in a suppliant attitude.
They were souls who implored her all-powerful intercession for their
salvation—and certainly not in vain.
On another page Friar Alexander represented Eve gazing upon Mary,
so that thus one might see at the same time the sin and the
redemption, the woman humiliated and the Virgin exalted.
Furthermore, in this book one might admire the Well of Living
Waters, the Fountain, the Lily, the Moon, the Sun, and the closed
Garden which is spoken of in the Canticle, the Gate of Heaven and
the Seat of God, and there were also several images of the Virgin.
Friar Marbode was, similarly, one of the most affectionate children of
Mary. He carved images in stone without ceasing, so that his beard,
his eyebrows, and his hair were white with dust, and his eyes were
perpetually swollen and tearful; but he was full of strength and joy
in his advanced age, and, visibly, the Queen of Paradise protected
the old age of her child. Marbode represented her seated on a
bishop’s throne, her brow encircled by a nimbus whose orb was of
pearls, and he took pains that the folds of her robe should cover the
feet of one of whom the prophet said: “My beloved is like a closed
garden.”
At times, also, he gave her the features of a child full of grace, and
she seemed to say: “Lord, thou art my Lord!”—“Dixi de ventre matris
meæ: Deus meus es tu.” (Psalm 21, 11.)
They had also in the monastery several poets, who composed, in
Latin, both prose and hymns in honor of the most happy Virgin Mary,
and there was even found one Picardian who set forth the miracles
of Our-Lady in ordinary language and in rhymed verses.
III.
Seeing such a concourse of praises and such a beautiful in-gathering
of works, Barnabas lamented to himself his ignorance and his
simplicity.
“Alas!” he sighed as he walked along in the little garden of the
convent, “I am very unfortunate not to be able, like my brothers, to
praise worthily the Holy Mother of God to whom I have pledged the
tenderness of my heart. Alas! Alas! I am a rude and artless man,
and I have for your service, Madam the Virgin, neither edifying
sermons, nor tracts properly divided according to the rules, nor fine
paintings, nor statues exactly sculptured, nor verses counted by feet
and marching in measure. I have nothing, alas!”
He moaned in this manner and abandoned himself to sadness.
One night that the monks were recreating by conversing, he heard
one of them relate the history of a religious who did not know how
to recite anything but the Ave Maria. This monk was disdained for
his ignorance; but, having died, there came forth from his lips five
roses in honor of the five letters in the name of Maria, and his
sanctity was thus manifested.
While listening to this recital Barnabas admired once again the
bounty of the Virgin; but he was not consoled by the example of
that happy death, for his heart was full of zeal, and he desired to
serve the glory of his Lady who was in Heaven. He sought the
means without being able to find them, and every day he grieved
the more.
One morning, however, having awakened full of joy, he ran to the
chapel and stayed there alone for more than an hour. He returned
there after dinner. And beginning from that moment he went every
day into the chapel at the hour when it was deserted, and there he
passed a large part of the time which the other monks consecrated
to the liberal and the mechanical arts. No more was he sad and no
longer did he complain.
A conduct so singular aroused the curiosity of the monks. They
asked themselves in the community why Friar Barnabas made his
retreats so frequent.
The Prior, whose duty it is to ignore nothing in the conduct of his
monks, resolved to observe Barnabas during his solitudes. One day
that he was closeted in the chapel as his custom was, Dom Prior
went, accompanied by two elders of the monastery, to observe
through the windows of the door what was going on in the interior.
They saw Barnabas, who—before the altar of the Holy Virgin, head
downward, feet in air—was juggling with six brass balls and twelve
knives. He was doing in honor of the Holy Mother of God the feats
which had brought to him the most applause. Not comprehending
that this simple man was thus placing his talent and his knowledge
at the service of the Holy Virgin, the two elders cried out at the
sacrilege.
The Prior understood that Barnabas had an innocent heart; but he
thought that he had fallen into dementia. All three were preparing to
drag him vigorously from the chapel when they saw the Holy Virgin
descend the steps of the altar in order to wipe with a fold of her blue
mantle the sweat which burst from the brow of her juggler.
Then the Prior, prostrating his face against the marble slabs, recited
these words:
“Blessed are the pure in heart, for they shall see God!”
“Amen,” responded the elders as they kissed the earth.
*** END OF THE PROJECT GUTENBERG EBOOK SHORT-STORY
MASTERPIECES, VOL. 2 ***
1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside
the United States, check the laws of your country in addition to
the terms of this agreement before downloading, copying,
displaying, performing, distributing or creating derivative works
based on this work or any other Project Gutenberg™ work. The
Foundation makes no representations concerning the copyright
status of any work in any country other than the United States.
1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if
you provide access to or distribute copies of a Project
Gutenberg™ work in a format other than “Plain Vanilla ASCII” or
other format used in the official version posted on the official
Project Gutenberg™ website (www.gutenberg.org), you must,
at no additional cost, fee or expense to the user, provide a copy,
a means of exporting a copy, or a means of obtaining a copy
upon request, of the work in its original “Plain Vanilla ASCII” or
other form. Any alternate format must include the full Project
Gutenberg™ License as specified in paragraph 1.E.1.
• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”
• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.
1.F.
Most people start at our website which has the main PG search
facility: www.gutenberg.org.