Get e-book Notes On Data Structures And Algorithms in Ruby

Free download. Book file PDF easily for everyone and every device. You can download and read online Notes On Data Structures And Algorithms in Ruby file PDF Book only if you are registered here. And also you can download or read online all Book PDF file that related with Notes On Data Structures And Algorithms in Ruby book. Happy reading Notes On Data Structures And Algorithms in Ruby Bookeveryone. Download file Free Book PDF Notes On Data Structures And Algorithms in Ruby at Complete PDF Library. This Book have some digital formats such us :paperbook, ebook, kindle, epub, fb2 and another formats. Here is The CompletePDF Book Library. It's free to register here to get Book file PDF Notes On Data Structures And Algorithms in Ruby Pocket Guide.
Concise Notes on Data. Structures and Algorithms 1 INTRODUCTION. 1. What Are Data Structures and Algorithms? The Ruby Programming Language.
Table of contents

Although this makes the language easier to learn and use,it also opens up many opportunities for errors. Careful attention to types and mechanisms to help detecttype errors early, fully understanding preconditions for executing methods, and thoughtful use of classhierarchies are important for novice programmers, so we will pay close attention to these matters inour discussion of data structures and algorithms and we will, when possible, incorporate this materialinto Ruby code.

This sometimes results in code that does not conform to the style prevalent in the Rubycommunity. What are the carrier set and some operations of the Character ADT? How might the concatenation operation of the Bit String ADT be realized using the carrier set representation you devised for question two above?

What do your answers to questions two and three above have to do with data structures and algorithms? Describe the carrier sets and some operations for the following ADTs: For each of the ADTs in exercise one, either indicate how the ADT is realized in some programming language, or describe how the values in the carrier set might be realized using the facilities of some programming language, and sketch how the operations of the ADT might be implemented.

Some operations of this ADT might be those to change character case from lower to upper and the reverse, classification operations to determine whether a character is a letter, a digit, whitespace, punctuation, a printable character, and so forth, and operations to convert between integers and characters. Bit String ADT values could be represented in many ways. They might be represented by arrays or lists of characters, Booleans, or integers.

If bit strings are represented as characters strings, then the bit string concatenation operation is realized by the character string concatenation operation. If bit strings are represented by arrays or lists, then the concatenation of two bit strings is a new array or list whose size is the sum of the sizes of the argument data structures consisting of the bits from the first bit string copied into the initial portion of the result array or list, followed by the bits from the second bit string copied into the remaining portion.

The carrier set representations described in the answer to question two are data structures, and the implementations of the concatenation operation described in the answer to question three are sketches of algorithms. We distinguishtwo sorts of built-in types: The values of the carrier set are atomic, that is, they cannot be divided into parts. Common examples of simple types are integer, Boolean, character, floating point, and enumerations.

Some languages also provide string as a built-in simple type. The values of the carrier set are not atomic, consisting instead of several atomic values arranged in some way. Common examples of structured types are arrays, records, classes, and sets. Some languages treat strings as a built-in structured types. Note that both simple and structured types are implementations of ADTs, it is simply a question of howthe programming language treats the values of the carrier set of the ADT in its implementation.

Theremainder of this chapter considers some Ruby simple and structured types to illustrate these ideas. This has several consequences for the way values can bemanipulated that may seem odd to programmers familiar with languages that have values that arenot objects. For example, values in Ruby respond to method calls: Ruby has many built-in types because it has many built-in classes. Here we only consider a few Rubytypes to illustrate how they realize ADTs. One unusual and interesting simple type is Symbol, which we consider in more detailto illustrate how a type in a programming language realizes an ADT.

Ruby has a String class whose instances are mutable sequences of Unicode characters. Symbol classinstances are character sequences that are not mutable, and consequently the Symbol class has farfewer operations than the String class. The carrier set of the Symbol ADT is the set of all finite sequences of characters over the Unicodecharacters set Unicode is a standard character set of over , characters from 93 scripts. Hencethis carrier set includes the string of zero characters the empty string , all strings of one character, allstrings of two characters, and so forth.

This carrier set is infinite. The operations of the Symbol ADT are the following. If there is no match, the result is undefined. If a contains characters or letters, the successor of a is found by incrementing the right-most letter or digit according to the Unicode collating sequence, carrying leftward if necessary when the last digit or letter in the collating sequence is encountered. If a has no letters or digits, then the right-most character of a is incremented, with carries to the left as necessary.

The Symbol ADT has no concatenation operations, but assuming we have a full-featured String ADT,symbols can be concatenated by converting them to strings, concatenating the strings, then convertingthe result back to a symbol. Similarly, String ADT operations can be used to do other manipulations.

This explains why the Symbol ADT has a rather odd mix of operations: The Symbol ADT models theSymbol class in Ruby, and this class only has operations often used for Symbols, with most stringoperations appearing in the String class. This alsoguarantees that only a single Symbol instance will exist corresponding to any sequence of characters,which is an important characteristic of the Ruby Symbol class that is not required by the Symbol ADT,and distinguishes it from the String class.

All Symbol ADT operations listed above are implemented in the Symbol class, except toSymbol , whichis implemented in classes such as String , that can generate a Symbol instance. When a result isundefined in the ADT, the result of the corresponding Symbol class method is nil. Ruby is written in C, so carrier set members that is, individual symbols are implemented as fixed-size arraysof characters which is how C represents strings inside the Symbol class.

Concise Notes on Data Structures and Algorithms

The empty symbol is an array oflength 0, symbols of length one are arrays with a single element, symbols of length two are arrays with twoelements, and so forth. Symbol class operations are either written to use these arrays directly, or to generatea String instance, do the operation on the string, and convert the result back into a Symbol instance. Excellent Economics and Business programmes at: A Structured Type in RubyRuby has a several structured types, including arrays, hashes, sets, classes, streams, and ranges.

In thissection we will only discuss ranges briefly as an example of a structured type. The start value is a value of type T that sets the lower bound of a range, and the end value is a value oftype T that sets the upper bound of a range.

  • Третья карта (Russian Edition)?
  • Assertions: introduction, types of assertions, data types,;
  • Kindle Feature Spotlight.

The range itself is the set of values of type T between thelower and upper bounds. A range can be inclusive, meaning that it includes the end value, or exclusive, meaning that it does notinclude the end value. Inclusive ranges are written with two dots between the extremes, and exclusiveranges with three dots.

A type can be a range base type only if it supports order comparisons. For example, the Integer, Real,and String types support order comparisons and so may be range base types, but Sets and Arrays donot, so they cannot be range base types. For example, the carrier set of the Range of Integer isthe set of all sequences of contiguous integers. The carrier set of the Range of Real is the set of all setsof real number greater than or equal to a given number, and either less than or equal to another, or lessthan another.

These sets are called intervals in mathematics. The result is undefined if r is the empty range. The result is undefined if r has no largest value for example, the Range of Real 0…3 has no largest value because there is no largest Real number less than 3. The Range of T ADT is a structured type because the values in its carrier set are composed of values ofsome other type, in this case, sets of value of the base type T. Elements of the carrier set are representedin Range instances by recording internally the type, start, and end values of the range, along with anindication of whether the range is inclusive or exclusive.

Ruby implements all the operations above,returning nil when the ADT operations are undefined. It is quite easy to see how to implement theseoperations given the representation elements of the carrier set. In addition, the Range class providesoperations for accessing the begin and end values defining the range, which are easily accessible becausethey are recorded. Finally, the Range class has an include? This gives slightly different results from cover? What is the difference between a simple and a structured type? What is a pure object-oriented language?

Name two ways that Symbol instances differ from String instances in Ruby. Is String a simple or structured type in Ruby? What is max 1…3? Choose a language that you know well and list its simple and structures types. Choose a language that you know well and compare its simple and structured types to those of Ruby. Does one language have a type that is simple while the corresponding type in the other language is structured? Which language has more simple types or more structured types? Every Ruby type is a class, and every Ruby value is an instance of a class. What advantage and disadvantages do you see with this approach?

Write pseudocode to implement the cover? Give an example of a Ruby String range r and String instance v such that r. The values of a simple type cannot be divided into parts, while the values of a structured type can be. For example, the values of the Integer type in Ruby cannot be broken into parts, while the values of a Range in Ruby can be the parts are the individual elements of the ranges. A pure object-oriented language is one whose types are all classes.

Smalltalk and Ruby are pure object- oriented languages because they have no such types. Symbol instances in Ruby are immutable while String instances are mutable.

Ruby Data Structures : Hashes - A closer look at Ruby’s Built in Hash Methods

Symbol instances consisting of a particular sequence of characters are unique, while there may be arbitrarily many String instances with the same sequence of characters. String is a simple type in Ruby because strings are not composed of other values—in Ruby there is no character type, so a String value cannot be broken down into parts composed of characters. If s is a String instance, then s[0] is not a character, but another String instance.

A fixed length, ordered collection of values of the same type stored in contiguous memory locations; the collection may be ordered in several dimensions. The values stored in an array are called elements. Elements are accessed by indexing into the array: For example, if a is an array with20 elements, then a[6] is the element of a with ordinal value 6. Indexing may start at any number, butgenerally it starts at 0.

Data Structures & Algorithms with Ruby

In the example above a[6] is the seventh value in a when indexing start at 0. Arrays are important because they allow many values to be stored in a single data structure whileproviding very fast access to each value. This is made possible by the fact that a all values in an arrayare the same type, and henokce require the same amount of memory to store, and that b elements arestored in contiguous memory locations. Accessing element a[i] requires finding the location where theelement is stored. This computation is obviously very fast. Furthermore, access to all theelements of the array can be done by starting a counter at b and incrementing it by m, thus yielding thelocation of each element in turn, which is also very fast.

Arrays are not abstract data types because their arrangement in the physical memory of a computer isan essential feature of their definition, and abstract data types abstract from all details of implementationon a computer. The definition above abstracts away the details about how elements are storedin contiguous locations which indeed does vary somewhat among languages.

Also, arrays are typicallytypes in procedural programming languages, so they are treated like realizations of abstract data typeseven though they are really not. In this book, we will treat arrays as implementation mechanisms and not as ADTs. Such arrays are called static arrays.

A chunk of memory big enough to holdall the values in the array is allocated when the array is created, and thereafter elements are accessed usingthe fixed base location of the array. Static arrays are the fundamental array type in most older procedurallanguages, such as Fortran, Basic, and C, and in many newer object-oriented languages as well, such as Java. Concise Notes on Data Structures and Algorithms ArraysSome languages provide arrays whose sizes are established at run-time and can change during execution.

Want to add to the discussion?

These dynamic arrays have an initial size used as the basis for allocating a segment of memory forelement storage. Thereafter the array may shrink or grow. If the array shrinks during execution, thenonly an initial portion of allocated memory is used. But if the array grows beyond the space allocatedfor it, a more complex reallocation procedure must occur, as follows: A new segment of memory large enough to store the elements of the expanded array is allocated.

All elements of the original unexpanded array are copied into the new memory segment.

  1. Bonamy & Clyde.
  2. Welcome to Reddit,.
  3. Stretching: Exercises Bible - Learn How To Stretch With Dynamic Stretching And Flexibility Exercises (stretching exercises, stretches, stretching, yoga ... back pain, anti aging, flexibility Book 1);
  4. Green Light Your Life: Awakening Your Higher Self.
  5. What other items do customers buy after viewing this item??
  6. Ayn Rand Contra Human Nature.
  7. The memory used initially to store array values is freed and the newly allocated memory is associated with the array variable or reference. This reallocation procedure is computationally expensive, so systems are usually designed to minimizeits frequency of use. For example, when an array expands beyond its memory allocation, its memoryallocation might be doubled even if space for only a single additional element is needed. The hope is thatproviding a lot of extra space will avoid many expensive reallocation procedures if the array expandsover time.

    Dynamic arrays are convenient for programmers because they can never be too small—whenever morespace is needed in a dynamic array, it can simply be expanded. One drawback of dynamic arrays is thatimplementing language support for them is more work for the compiler or interpreter writer. A potentiallymore serious drawback is that the expansion procedure is expensive, so there are circumstances whenusing a dynamic array can be dangerous.

    For example, if an application must respond in real time toevents in its environment, and a dynamic array must be expanded when the application is in the midstof a response, then the response may be delayed too long, causing problems. To the programmer, it is as if arrays are unbounded and as manylocations as are needed are available. Locations not assigned a value in an expanded array are initializedto nil by default.

    Data Structures and Algorithms in Ruby? : ruby

    Ruby also has an interesting indexing mechanism for arrays. Array indices begin at0 so, for example, a[13] is the value in the 14th position of the array. Negative numbers are the indicesof elements counting from the current end of the array, so a[-1] is the last element, a[-2] is thesecond to last element, and so forth. Array references that use an out-of-bound index return nil. Thesefeatures combine to make it difficult to write an array reference that causes an indexing error.

    This isapparently a great convenience to the programmer, but actually it is not because it makes it so hard tofind bugs: The ability to assign arbitrary values to arrays that automatically grow arbitrarily large makes Ruby arraysbehave more like lists than arrays in other languages. We will discuss the List ADT later on. Concise Notes on Data Structures and Algorithms ArraysAnother interesting feature of Ruby arrays has to do with the fact that Ruby is a pure object-orientedlanguage.

    This means in part that every value in Ruby is an object, and hence every value in Ruby is aninstance of Object, the super-class of all classes, or one of its sub-classes. Arrays hold Object values,so any value can be stored in any array! For example, an array can store some strings, some integers, somefloats, and so forth. This appears to be a big advantage for programmers, but again this freedom has aprice: For example, in Java, mistakenly assigning a string value to an arrayholding integers is flagged by the compiler as an error, but in Ruby, the interpreter does not complain.

    Ruby arrays have many interesting and powerful methods. Besides indexing operations that go wellbeyond those discussed above, arrays have operations based on set operations membership, intersection,union, and relative complement , string operations concatenation, searching, and replacement , stackoperations push and pop , and queue operations shift and append , as well as more traditional array-based operations sorting, reversing, removing duplicates, and so forth. If an array holds integers, each of which is four bytes long, how many bytes from the base location of the array is the location of the fifth element?

    Is the formula for finding the location of an element in a dynamic array different from the formula for finding the location of an element in a static array? If a Ruby array a has n elements, which element is a[n-1]? Which is element a[-1]? How many array values must be moved from one memory location to another to complete this assignment statement? Memory could be freed when a dynamic array shrinks. What advantages or disadvantages might this have? To use a static array, data must be recorded about the base location of the array, the size of the elements for indexing , and the number of elements in the array to check that indexing is within bounds.

    What information must be recorded to use a dynamic array? State a formula to determine how far from the base location of a Ruby array an element with index i is when i is a negative number. Give an example of a Ruby array reference that will cause an indexing error at run time. What are the values of the following Ruby expressions? You can check your answers with the Ruby interpreter. Suppose that the following Ruby statement are executed in order. What is the value of array a after each statement?

    If an array holds integers, each of which is four bytes long, then the fifth element is 16 bytes past the base location of the array. The formula for finding the location of an element in a dynamic array is the same as the formula for finding the location of an element in a static array. The only difference is what happens when a location is beyond the end of the array. For a static array, trying to access or assign to an element beyond the end of the array is an indexing error. For a dynamic array, it may mean that the array needs to be expanded, depending on the language.

    The memory allocated for an array almost always has memory allocated for other data structures after it, so it cannot simply be increased without clobbering other data structures. A new chunk of memory must be allocated from the free memory store sufficient to hold the expanded array, and the old memory returned to the free memory store so it can be used later for other smaller data structures. If a Ruby array a has n elements, then element a[n-1] and element a[-1] are both the last element in the array.

    Common Data Structures and Algorithms

    In general, a[n-i] and a[-i] both access the same element. For example, if a certain variable is supposed to record a count of how manychanges have been made to a file, this variable should never be negative. It helps human readers to knowabout these constraints. Furthermore, if a program checks these constraints as it executes, it may finderrors almost as soon as they occur.

    For both these reasons, it is advisable to record constraints aboutprogram state in assertions. A statement that must be true at a designated point in a program. Preconditions—A precondition is an assertion that must be true at the initiation of an operation. For example, a square root operation cannot accept a negative argument, so a precondition of this operation is that its argument be non-negative.

    Preconditions most often specify restrictions on parameters, but they may also specify that other conditions have been established, such as a file having been created or a device having been initialized. Often an operation has no preconditions, meaning that it can be executed under any circumstances. Post conditions—A post condition is an assertion that must be true at the completion of an operation. For example, a post condition of the square root operation is that its result, when squared, is within a small amount of its argument.

    Post conditions usually specify relationships between the arguments and the results, or restrictions on the results. Sometimes they specify that the arguments do not change, or that they change in certain ways. This section contains helpful links to other content. Introduction The basic idea of a data structure is to store data in a way that meets the needs of your particular application. Learning Outcomes Look through these now and then use them to test yourself after doing the assignment: What is a data structure?

    What is a stack? What is a queue? What is a stack useful for? What is a queue useful for? Why bother having many different search algorithms? The Boolean array keeps track of whether a locker is rented. Use this class for the following exercises. Write a class invariant comment for the Storage class. Write precondition comments and Ruby code for all the operations that need them in the Storage class.

    The precondition code may use other operations in the class. Write post condition comments for all operations that need them in the Storage class. The post condition comments may use other operations in the class. Concise Notes on Data Structures and Algorithms. Assertions Introduction At each point in a program, there are usually constraints on the computational state that must hold for the program to be correct.

    A statement that must be true at a designated point in a program. Assertions and Abstract Data Types Although we have defined assertions in terms of programs, the notion can be extended to abstract data types which are mathematical entities. Using Assertions When writing code, programmer should state pre- and subtle post conditions for public operations, state class invariants, and insert unreachable code assertions and loop invariants wherever appropriate.

    Assertions in Ruby Ruby provides no support for assertions whatever. Checking a Precondition in Ruby Ruby has many predefined exceptions classes such as ArgumentError and new ones can be created easily by sub-classing StandardError, so it is easy to raise appropriate exceptions. Review Questions Name and define in your own words three kinds of assertions. What is an axiom? How can programmers check preconditions of an operation in a language that does not support assertions?

    Should a program attempt to catch assertion exceptions? Can assertion checking be turned off easily in Ruby programs as it can in Eiffel or D programs? Write preconditions for those operations that need them, post conditions for all operations, and at least four axioms. Consider the following fragment of a class declaration in Ruby. Implement the operations in the Storage class in Ruby. Review Question Answers A precondition is an assertion that must be true when an operation begins to execute.

    A post condition is an assertion that must be true when an operation completes execution. A class invariant in an assertion that must be true between executions of the operations that a class makes available to clients. An unreachable code assertion is an assertion stating that execution should never reach the place where it occurs.

    A loop invariant is an assertion true whenever execution reaches the top of the loop where it occurs. An axiom is a statement about the operations of an abstract data type that must always be true. Preconditions can be checked in a language that does not support assertions by using conditionals to check the preconditions, and then throwing an exception, returning an error code, calling a special error or exception operation to deal with the precondition violation, or halting execution of the program when preconditions are not met.

    Programs should not attempt to catch assertion exceptions because they indicate errors in the design and implementation of the program, so it is better that the program fail than that it continue to execute and produce possibly incorrect results. Assertion checking cannot be turned off easily in Ruby programs because it is completely under the control of the programmer.