diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 24b4717..0a5b864 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: - id: docs name: pdoc - entry: poetry run pdoc --docformat markdown -o docs paddles + entry: poetry run pdoc -o docs paddles language: system pass_filenames: false types: [python] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..803e7f4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,128 @@ +# Contributing +This file documents how the library is developed, in case you want to contribute. + +By contributing code or documentation to this repository, +you agree to transfer the copyright of your contribution to The Open University, UK, +and that your contribution will be subject to the `paddles` [licence](README.md#Licence). + +## Environment +We use Python 3.10 and the [poetry](https://python-poetry.org) packaging and dependency manager. +To set up the environment: +- if you don't have Python 3.10, [install it](https://www.python.org/downloads/release/python-31011/) +- if you don't have `poetry`, [install it](https://python-poetry.org/docs/#installing-with-the-official-installer) +- clone this repository +- open a terminal and go to the folder to where you cloned this project +- enter `poetry install` + +This installs the software needed to develop `paddles`, in a new +[virtual environment](https://docs.python.org/3/glossary.html#term-virtual-environment), +in order to not interfere with your existing Python projects. + +To use the environment, while developing `paddles`, enter `poetry run C` +to execute command `C` in the virtual environment for `paddles`. + +Alternatively, you can enter `poetry shell` to activate the environment, and +then you can just enter `C` to execute the command. +To deactivate the environment, enter `exit`. + +In the rest of this document, the notation `[poetry run] C` means that you should enter +- `poetry run C` if you haven't activated the environment with `poetry shell` +- `C` if you have. + +To finish the setup, you may optionally enter `[poetry run] pre-commit install` +to install pre-commit hooks (scripts that are run when committing changes to a repository). +Our environment has configured hooks that test, check and format your code and +generate the documentation before you commit your changes to the repository. + +This project folder contains the following files and subfolders: + +- `README.md`: this file +- `LICENSE`: the code licence +- `pyproject.toml`: project configuration +- `poetry.lock`: list of the packages installed by `poetry install` +- `.pre-commit-config.yaml`: list of pre-commit hooks +- `paddles/`: subfolder with the library's code +- `tests/`: subfolder with the test code +- `docs/`: subfolder with the documentation generated from the library code + +## Testing + +We use [pytest](https://pytest.org) to test `paddles`. +The unit tests are in the `tests` subfolder, with one test file per library module. +There's at least one test function per creator or modifier method. +There are no test functions for inspector methods: they are indirectly tested by +using them for closed-box (black-box) testing of the modifiers. + +Each test file contains, in this order: +1. helper functions +1. fixtures (functions that generate test data) +1. tests for creator methods +1. tests for modifier methods, used separately, and finally +1. tests for combined use of modifiers. + +Additionally, there are simple interactive examples of how to use a class in that class's docstring, +in subfolder `paddles`. These are used as [doctests](https://docs.python.org/3.10/library/doctest.html). + +To run all tests, i.e. the doctests in `paddles` and the unit tests in `tests`, +enter `[poetry run] pytest`. + +This will produce a report of which tests passed, which failed, and which +library code lines weren't executed. (We aim for 100% coverage.) +If two implementations of the same ADT use different messages +for the same exception for the same method, the tests fail. + +## Linting + +We check and format all code (library and tests) with [ruff](https://astral.sh/ruff). + +To check the code against over 700 style rules, enter `[poetry run] ruff check`. +If `ruff` reports rule violations, open the [rules page](https://docs.astral.sh/ruff/rules), +search for the reported rule number (e.g. E101), and click on the rule name +(e.g. mixed-spaces-and-tabs) next to it in the page. +This will open a new page explaining the violated rule and its rationale, with an example, +like [this](https://docs.astral.sh/ruff/rules/mixed-spaces-and-tabs/). + +To automatically fix violations, when possible, +enter `[poetry run] ruff check --fix --unsafe-fixes` and double-check +the modifications made by `ruff`. + +To automatically ignore the flagged code lines for a particular file, +enter `[poetry run] ruff check path/to/file.py --add-noqa`. +This will add comments of the form `# noqa: ...` where `...` is the number of +the violated rule. + +This should be used sparingly. For example, in the test files, the fixtures +that generate classes are on purpose named with initial uppercase, as classes are, +which violates the rule that function names and arguments should be in lowercase. + +Finally, enter `[poetry run] ruff format` to format the code. + +## Type checking +We type check the code with [pytype](https://google.github.io/pytype). +Enter `[poetry run] pytype .` (note the dot) to type check all code. + +## Documenting +We use [pdoc](https://pdoc.dev) to generate the documentation from the docstrings. + +To check the documents during development, enter `[poetry run] pdoc paddles &` +to open a live site with the documentation. Any changes to the docstrings of +the library files are immediately reflected in the site, upon saving the files. + +## Comitting +If you installed the pre-commit hooks when setting up the [environment](#environment) +then every time you commit your code, +these steps are done automatically on the _staged_ files: +1. test the code with `pytest` +2. type check the code with `pytype` +3. check (but _don't_ fix) the code with `ruff` +4. format the code with `ruff` +5. generate the documentation with `pdoc`. + +If a test or check fails in steps 1–3 or if a file is modified in steps 4–5, +then the commit doesn't go ahead. +This allows you to review the errors and the automatically applied changes, +stage the modified files, and commit again. + +Due to the automated steps, each commit takes many seconds to complete. +But when it successfully completes, you know that your code hasn't broken existing tests, +isn't poorly formatted, and has up-to-date documentation. \ No newline at end of file diff --git a/README.md b/README.md index a638874..07479b1 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,21 @@ -`paddles` aims to be an algorithms and data structures library in Python that -- is thoroughly tested and documented -- is easy to install, use and understand -- adheres to good coding practices. +`paddles` is a pedagogical algorithms and data structures library that aims to +- be thoroughly tested and documented +- be easy to install, use and understand +- adhere to good Python coding practices. -To learn what the library provides and how to use it, see https://dsa-ou.github.io/paddles. +To install the library, type `pip install paddles` at the command line, +preferably after activating a virtual environment. +Your default Python version must be 3.10 or later. -The rest of this file documents how the library is developed, -in case you want to contribute. +This is version 0.1 of the library. It is a work in progress. +It currently implements the Stack, Queue and Deque abstract data types (ADTs). -## Licence -The code and text in this repository are Copyright © 2024 by The Open University, UK. -The code is licensed under a [BSD 3-clause licence](LICENSE.MD). -The text is licensed under a -[Creative Commons Attribution 4.0 International Licence](http://creativecommons.org/licenses/by/4.0). - -By contributing code or documentation to this repository, -you agree to transfer the copyright of your contribution to The Open University, UK, -and that your contribution will be subject to the above licence. - -## Environment -We use Python 3.10 and the [poetry](https://python-poetry.org) packaging and dependency manager. -To set up the environment: -- if you don't have Python 3.10, [install it](https://www.python.org/downloads/release/python-31011/) -- if you don't have `poetry`, [install it](https://python-poetry.org/docs/#installing-with-the-official-installer) -- clone this repository -- open a terminal and go to the folder to where you cloned this project -- enter `poetry install` - -This installs the software needed to develop `paddles`, in a new -[virtual environment](https://docs.python.org/3/glossary.html#term-virtual-environment), -in order to not interfere with your existing Python projects. - -To use the environment, while developing `paddles`, enter `poetry run C` -to execute command `C` in the virtual environment for `paddles`. - -Alternatively, you can enter `poetry shell` to activate the environment, and -then you can just enter `C` to execute the command. -To deactivate the environment, enter `exit`. - -In the rest of this document, the notation `[poetry run] C` means that you should enter -- `poetry run C` if you haven't activated the environment with `poetry shell` -- `C` if you have. - -To finish the setup, you may optionally enter `[poetry run] pre-commit install` -to install pre-commit hooks (scripts that are run when committing changes to a repository). -Our environment has configured hooks that test, check and format your code and -generate the documentation before you commit your changes to the repository. - -This project folder contains the following files and subfolders: - -- `README.md`: this file -- `LICENSE`: the code licence -- `pyproject.toml`: project configuration -- `poetry.lock`: list of the packages installed by `poetry install` -- `.pre-commit-config.yaml`: list of pre-commit hooks -- `paddles/`: subfolder with the library's code -- `tests/`: subfolder with the test code -- `docs/`: subfolder with the documentation generated from the library code - -## Testing - -We use [pytest](https://pytest.org) to test `paddles`. -The unit tests are in the `tests` subfolder, with one test file per library module. -There's at least one test function per creator or modifier method. -There are no test functions for inspector methods: they are indirectly tested by -using them for closed-box (black-box) testing of the modifiers. - -Each test file contains, in this order: -1. helper functions -1. fixtures (functions that generate test data) -1. tests for creator methods -1. tests for modifier methods, used separately, and finally -1. tests for combined use of modifiers. - -Additionally, there are simple interactive examples of how to use a class in that class's docstring, -in subfolder `paddles`. These are used as [doctests](https://docs.python.org/3.10/library/doctest.html). +The code repository is at https://github.com/dsa-ou/paddles. +The formatted documentation is at https://dsa-ou.github.io/paddles. -To run all tests, i.e. the doctests in `paddles` and the unit tests in `tests`, -enter `[poetry run] pytest`. - -This will produce a report of which tests passed, which failed, and which -library code lines weren't executed. (We aim for 100% coverage.) -If two implementations of the same ADT use different messages -for the same exception for the same method, the tests fail. - -## Linting - -We check and format all code (library and tests) with [ruff](https://astral.sh/ruff). - -To check the code against over 700 style rules, enter `[poetry run] ruff check`. -If `ruff` reports rule violations, open the [rules page](https://docs.astral.sh/ruff/rules), -search for the reported rule number (e.g. E101), and click on the rule name -(e.g. mixed-spaces-and-tabs) next to it in the page. -This will open a new page explaining the violated rule and its rationale, with an example, -like [this](https://docs.astral.sh/ruff/rules/mixed-spaces-and-tabs/). - -To automatically fix violations, when possible, -enter `[poetry run] ruff check --fix --unsafe-fixes` and double-check -the modifications made by `ruff`. - -To automatically ignore the flagged code lines for a particular file, -enter `[poetry run] ruff check path/to/file.py --add-noqa`. -This will add comments of the form `# noqa: ...` where `...` is the number of -the violated rule. - -This should be used sparingly. For example, in the test files, the fixtures -that generate classes are on purpose named with initial uppercase, as classes are, -which violates the rule that function names and arguments should be in lowercase. - -Finally, enter `[poetry run] ruff format` to format the code. - -## Type checking -We type check the code with [pytype](https://google.github.io/pytype). -Enter `[poetry run] pytype .` (note the dot) to type check all code. - -## Documenting -We use [pdoc](https://pdoc.dev) to generate the documentation from the docstrings. - -To check the documents during development, enter `[poetry run] pdoc paddles &` -to open a live site with the documentation. Any changes to the docstrings of -the library files are immediately reflected in the site, upon saving the files. - -## Comitting -If you installed the pre-commit hooks when setting up the [environment](#environment) -then every time you commit your code, -these steps are done automatically on the _staged_ files: -1. test the code with `pytest` -2. type check the code with `pytype` -3. check (but _don't_ fix) the code with `ruff` -4. format the code with `ruff` -5. generate the documentation with `pdoc`. - -If a test or check fails in steps 1–3 or if a file is modified in steps 4–5, -then the commit doesn't go ahead. -This allows you to review the errors and the automatically applied changes, -stage the modified files, and commit again. +## Licence -Due to the automated steps, each commit takes many seconds to complete. -But when it successfully completes, you know that your code hasn't broken existing tests, -isn't poorly formatted, and has up-to-date documentation. \ No newline at end of file +`paddles` is Copyright © 2024 by The Open University, UK. +The code is licensed under a [BSD 3-clause licence](https://github.com/dsa-ou/paddles/blob/main/LICENSE). +The documentation is licensed under a +[Creative Commons Attribution 4.0 International Licence](http://creativecommons.org/licenses/by/4.0). \ No newline at end of file diff --git a/docs/paddles.html b/docs/paddles.html index 0888d14..34bafb7 100644 --- a/docs/paddles.html +++ b/docs/paddles.html @@ -48,9 +48,20 @@

Submodules

paddles

-

paddles is a pedagogical algorithms and data structures library.

+

paddles is a pedagogical algorithms and data structures library that aims to

-

It currently implements the Stack, Queue and Deque abstract data types (ADTs).

+ + +

To install the library, type pip install paddles at the command line, +preferably after activating a virtual environment. +Your default Python version must be 3.10 or later.

+ +

This is version 0.1 of the library. It is a work in progress. +It currently implements the Stack, Queue and Deque abstract data types (ADTs).

The code repository is at https://github.com/dsa-ou/paddles. The formatted documentation is at https://dsa-ou.github.io/paddles.

@@ -58,7 +69,7 @@

Licence

paddles is Copyright © 2024 by The Open University, UK. -The code is licensed under a BSD-3-clause licence. +The code is licensed under a BSD 3-clause licence. The documentation is licensed under a Creative Commons Attribution 4.0 International Licence.

@@ -67,20 +78,9 @@

Licence

-
 1"""`paddles` is a pedagogical algorithms and data structures library.
- 2
- 3It currently implements the Stack, Queue and Deque abstract data types (ADTs).
- 4
- 5The code repository is at https://github.com/dsa-ou/paddles.
- 6The formatted documentation is at https://dsa-ou.github.io/paddles.
- 7
- 8## Licence
- 9
-10`paddles` is Copyright © 2024 by The Open University, UK.
-11The code is licensed under a [BSD-3-clause licence](https://github.com/dsa-ou/paddles/blob/main/LICENSE).
-12The documentation is licensed under a
-13[Creative Commons Attribution 4.0 International Licence](http://creativecommons.org/licenses/by/4.0).
-14"""
+                        
1"""
+2.. include:: ../README.md
+3"""  # noqa: D200, D400
 
diff --git a/docs/search.js b/docs/search.js index 8b6eb2c..8a6fcde 100644 --- a/docs/search.js +++ b/docs/search.js @@ -1,6 +1,6 @@ window.pdocSearch = (function(){ /** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();opaddles is a pedagogical algorithms and data structures library.

\n\n

It currently implements the Stack, Queue and Deque abstract data types (ADTs).

\n\n

The code repository is at https://github.com/dsa-ou/paddles.\nThe formatted documentation is at https://dsa-ou.github.io/paddles.

\n\n

Licence

\n\n

paddles is Copyright \u00a9 2024 by The Open University, UK.\nThe code is licensed under a BSD-3-clause licence.\nThe documentation is licensed under a\nCreative Commons Attribution 4.0 International Licence.

\n"}, {"fullname": "paddles.deque", "modulename": "paddles.deque", "kind": "module", "doc": "

This module implements the Deque ADT.

\n\n

Intuition

\n\n

The Deque ADT models a line of objects that can be accessed, added to and\nremoved from either end of the line.\nA deque can be used as a stack or as a queue.

\n\n

Definition

\n\n

A deque, pronounced 'deck' and short for 'double-ended queue', is a sequence\nwhere only the members at both ends of the sequence\n(called the front and the back of the queue) can be accessed and removed.\nNew members can only be added at the front or at the back.

\n\n

Operations

\n\n

The Deque ADT provides operations to:

\n\n
    \n
  • create a new empty deque
  • \n
  • add a new member to the front of the deque
  • \n
  • add a new member to the back of the deque
  • \n
  • remove the member at the front of the deque
  • \n
  • remove the member at the back of the deque
  • \n
  • access the member at the front of the deque without removing it
  • \n
  • access the member at the back of the deque without removing it
  • \n
  • compute the size of the deque (number of members).
  • \n
\n\n

Applications

\n\n

Consider using a deque when you need to simulate a queue where

\n\n
    \n
  • objects jump the queue (join at the front) or\nleave it from the back after waiting a certain time
  • \n
  • the direction of the queue changes, like cars on a ferry.
  • \n
\n\n

Implementations

\n\n

The Deque ADT can be implemented with circular dynamic arrays or doubly-linked lists.\nIn both cases, the operations listed above take constant time.\nA doubly-linked list uses much more memory than a static array of the same length,\nbut a dynamic array may have wasted capacity and requires resizing.\npaddles only provides a doubly-linked list implementation for the moment.

\n"}, {"fullname": "paddles.deque.LinkedListDeque", "modulename": "paddles.deque", "qualname": "LinkedListDeque", "kind": "class", "doc": "

An implementation of the Deque ADT, using a doubly-linked list.

\n\n

Besides the ADT's operations, this class provides two convenience operations:

\n\n
    \n
  • create a non-empty deque from a given sequence
  • \n
  • convert a deque to a string, to see its members listed from front to back.
  • \n
\n\n
\n
>>> from paddles.deque import LinkedListDeque\n>>> deque = LinkedListDeque("abc")          # create a non-empty deque\n>>> deque.size()                            # number of members\n3\n>>> deque.take_front()                      # remove and return the front member\n'a'\n>>> deque.take_back()                       # remove and return the back member\n'c'\n>>> deque.front() == deque.back() == 'b'    # return the front and back members\nTrue\n>>> deque.add_back("C")                     # add a new member at the back\n>>> deque.add_front("A")                    # add a new member at the front\n>>> print(deque)                            # str(deque) also possible\nLinkedListDeque(['A', 'b', 'C'])\n
\n
\n"}, {"fullname": "paddles.deque.LinkedListDeque.__init__", "modulename": "paddles.deque", "qualname": "LinkedListDeque.__init__", "kind": "function", "doc": "

Initialize the deque with the members of sequence.

\n\n

The members are added to the deque in the order they are in sequence.\nTo create an empty deque, call LinkedListDeque() or LinkedListDeque([]).

\n\n

Complexity: O(len(sequence))

\n", "signature": "(sequence: collections.abc.Sequence[typing.Any] = [])"}, {"fullname": "paddles.deque.LinkedListDeque.size", "modulename": "paddles.deque", "qualname": "LinkedListDeque.size", "kind": "function", "doc": "

Return how many members the deque has.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> int:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.front", "modulename": "paddles.deque", "qualname": "LinkedListDeque.front", "kind": "function", "doc": "

Return the item at the front of the deque, without removing it.

\n\n

Raise ValueError if the deque is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.back", "modulename": "paddles.deque", "qualname": "LinkedListDeque.back", "kind": "function", "doc": "

Return the item at the back of the deque, without removing it.

\n\n

Raise ValueError if the deque is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.add_front", "modulename": "paddles.deque", "qualname": "LinkedListDeque.add_front", "kind": "function", "doc": "

Put item at the front of the deque.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.add_back", "modulename": "paddles.deque", "qualname": "LinkedListDeque.add_back", "kind": "function", "doc": "

Put item at the back of the deque.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.take_front", "modulename": "paddles.deque", "qualname": "LinkedListDeque.take_front", "kind": "function", "doc": "

Remove and return the item at the front of the deque.

\n\n

Raise ValueError if the deque is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.take_back", "modulename": "paddles.deque", "qualname": "LinkedListDeque.take_back", "kind": "function", "doc": "

Remove and return the item at the back of the deque.

\n\n

Raise ValueError if the deque is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.queue", "modulename": "paddles.queue", "kind": "module", "doc": "

This module implements the Queue ADT.

\n\n

Intuition

\n\n

The Queue ADT models a line of objects, e.g. cars waiting to board a ferry.\nOnly the object at the front of the line can be accessed and removed.\nThe only way to add an object is to put it at the back of the line.

\n\n

Definition

\n\n

A queue is a sequence where members are added to one end of the sequence\n(the back of the queue) and removed from the other end (the front of the queue).

\n\n

A queue is a first-in, first-out (FIFO) sequence:\nthe members are removed in the same order they were added.

\n\n

A queue is a sequence ordered by age (time of addition).\nThe oldest member is at the front of the queue, and the youngest member is at the back.

\n\n

Operations

\n\n

The Queue ADT provides operations to:

\n\n
    \n
  • create a new empty queue
  • \n
  • add a new member, at the back of the existing ones
  • \n
  • remove the member at the front of the queue
  • \n
  • access the member at the front of the queue without removing it
  • \n
  • compute the size of the queue (number of members).
  • \n
\n\n

Applications

\n\n

Queues are used to implement breadth-first search.\nYou should consider using a queue when you need to:

\n\n
    \n
  • simulate a real-life queue, like travellers at passport control or\ndocuments in a printer queue
  • \n
  • process items in the same order they were added, like a to-do list.
  • \n
\n\n

Implementations

\n\n

The Queue ADT can be implemented with circular dynamic arrays or singly-linked lists.\nIn both cases, the operations listed above take constant time.\nA singly-linked list uses much more memory than a static array of the same length,\nbut a dynamic array may have wasted capacity and requires resizing.\npaddles only provides a singly-linked list implementation for the moment.

\n"}, {"fullname": "paddles.queue.LinkedListQueue", "modulename": "paddles.queue", "qualname": "LinkedListQueue", "kind": "class", "doc": "

An implementation of the Queue ADT, using a singly-linked list.

\n\n

Besides the ADT's operations, this class provides two convenience operations:

\n\n
    \n
  • create a non-empty queue from a given sequence
  • \n
  • convert a queue to a string, to see its members listed from front to back.
  • \n
\n\n
\n
>>> from paddles.queue import LinkedListQueue\n>>> q = LinkedListQueue("abc")  # create a non-empty queue\n>>> q.size()                    # number of members\n3\n>>> q.dequeue()                 # remove and return the front member\n'a'\n>>> q.front()                   # return but don't remove the front member\n'b'\n>>> q.enqueue("d")              # add a new member at the back\n>>> print(q)                    # str(q) also possible\nLinkedListQueue(['b', 'c', 'd'])\n
\n
\n"}, {"fullname": "paddles.queue.LinkedListQueue.__init__", "modulename": "paddles.queue", "qualname": "LinkedListQueue.__init__", "kind": "function", "doc": "

Initialize the queue with the members of sequence.

\n\n

The members are added to the queue in the order they are in sequence.\nTo create an empty queue, call LinkedListQueue() or LinkedListQueue([]).

\n\n

Complexity: O(len(sequence))

\n", "signature": "(sequence: collections.abc.Sequence[typing.Any] = [])"}, {"fullname": "paddles.queue.LinkedListQueue.size", "modulename": "paddles.queue", "qualname": "LinkedListQueue.size", "kind": "function", "doc": "

Return how many members the queue has.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> int:", "funcdef": "def"}, {"fullname": "paddles.queue.LinkedListQueue.front", "modulename": "paddles.queue", "qualname": "LinkedListQueue.front", "kind": "function", "doc": "

Return the member at the front of the queue, without removing it.

\n\n

Raise ValueError if the queue is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.queue.LinkedListQueue.enqueue", "modulename": "paddles.queue", "qualname": "LinkedListQueue.enqueue", "kind": "function", "doc": "

Put item at the back of the queue.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.queue.LinkedListQueue.dequeue", "modulename": "paddles.queue", "qualname": "LinkedListQueue.dequeue", "kind": "function", "doc": "

Remove and return the item at the front of the queue.

\n\n

Raise ValueError if the queue is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.stack", "modulename": "paddles.stack", "kind": "module", "doc": "

This module implements the Stack ADT.

\n\n

Intuition

\n\n

The Stack ADT models a pile of objects, e.g. a pile of storage boxes.\nOnly the object at the top of the pile can be accessed and removed.\nThe only way to add an object is to put it on top of the existing pile.

\n\n

Definition

\n\n

A stack is a sequence where members are removed from and added to\nthe same end of the sequence, called the top of the stack.

\n\n

A stack is a last-in, first-out (LIFO) sequence:\nthe next member to be removed is the one most recently added.

\n\n

A stack is a sequence ordered by age (time of addition).\nThe oldest member is at the bottom of the stack, and the youngest member is at the top.

\n\n

Operations

\n\n

The Stack ADT provides operations to:

\n\n
    \n
  • create a new empty stack
  • \n
  • add a new member, on top of the existing ones
  • \n
  • remove the member at the top of the stack
  • \n
  • access the member at the top of the stack without removing it
  • \n
  • compute the size of the stack (number of members).
  • \n
\n\n

Applications

\n\n

Stacks are used to implement function calls and depth-first search.\nYou should consider using a stack when you need to:

\n\n
    \n
  • simulate the handling of a pile of objects, like loading and unloading ship containers
  • \n
  • process nested structures, like brackets (e.g. print([1, {2, 3}])) or\nHTML tags (e.g. <p><b>text</b></p>)
  • \n
  • process items in the reverse order they were added, like undo operations\n(the next command to be undone is the most recently executed one).
  • \n
\n\n

Implementations

\n\n

The Stack ADT can be implemented with dynamic arrays or singly-linked lists.\nIn both cases, the operations listed above take constant time.\nA singly-linked list uses much more memory than a static array of the same length,\nbut a dynamic array may have wasted capacity and requires resizing.

\n"}, {"fullname": "paddles.stack.DynamicArrayStack", "modulename": "paddles.stack", "qualname": "DynamicArrayStack", "kind": "class", "doc": "

An implementation of the Stack ADT, using Python lists.

\n\n

Besides the ADT's operations, this class provides two convenience operations:

\n\n
    \n
  • create a non-empty stack from a given sequence
  • \n
  • convert a stack to a string, to see its members listed from bottom to top.
  • \n
\n\n
\n
>>> from paddles.stack import DynamicArrayStack\n>>> stack = DynamicArrayStack("abc")    # create a non-empty stack\n>>> stack.size()                        # number of members\n3\n>>> stack.pop()                         # remove and return the top member\n'c'\n>>> stack.peek()                        # return but don't remove the top member\n'b'\n>>> stack.push("C")                     # add a new member on top\n>>> print(stack)                        # str(stack) also possible\nDynamicArrayStack(['a', 'b', 'C'])\n
\n
\n"}, {"fullname": "paddles.stack.DynamicArrayStack.__init__", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.__init__", "kind": "function", "doc": "

Initialize the stack with the members of sequence.

\n\n

The members are added to the stack in the order they are in sequence.\nTo create an empty stack, call DynamicArrayStack() or DynamicArrayStack([]).

\n\n

Complexity: O(len(sequence))

\n", "signature": "(sequence: collections.abc.Sequence[typing.Any] = [])"}, {"fullname": "paddles.stack.DynamicArrayStack.size", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.size", "kind": "function", "doc": "

Return how many members the stack has.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> int:", "funcdef": "def"}, {"fullname": "paddles.stack.DynamicArrayStack.peek", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.peek", "kind": "function", "doc": "

Return the member at the top of the stack, without removing it.

\n\n

Raise ValueError if the stack is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.stack.DynamicArrayStack.push", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.push", "kind": "function", "doc": "

Put item on top of the stack.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.stack.DynamicArrayStack.pop", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.pop", "kind": "function", "doc": "

Remove and return the member at the top of the stack.

\n\n

Raise ValueError if the stack is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.stack.LinkedListStack", "modulename": "paddles.stack", "qualname": "LinkedListStack", "kind": "class", "doc": "

An implementation of the Stack ADT, using singly-linked lists.

\n\n

Besides the ADT's operations, this class provides two convenience operations:

\n\n
    \n
  • create a non-empty stack from a given sequence
  • \n
  • convert a stack to a string, to see its members listed from bottom to top.
  • \n
\n\n
\n
>>> from paddles.stack import LinkedListStack\n>>> stack = LinkedListStack("abc")      # create a non-empty stack\n>>> stack.size()                        # number of members\n3\n>>> stack.pop()                         # remove and return the top member\n'c'\n>>> stack.peek()                        # return but don't remove the top member\n'b'\n>>> stack.push("C")                     # add a new member on top\n>>> print(stack)                        # str(stack) also possible\nLinkedListStack(['a', 'b', 'C'])\n
\n
\n"}, {"fullname": "paddles.stack.LinkedListStack.__init__", "modulename": "paddles.stack", "qualname": "LinkedListStack.__init__", "kind": "function", "doc": "

Initialize the stack with the members of sequence.

\n\n

The members are added to the stack in the order they are in sequence.\nTo create an empty stack, call LinkedListStack() or LinkedListStack([]).

\n\n

Complexity: O(len(sequence))

\n", "signature": "(sequence: collections.abc.Sequence[typing.Any] = [])"}, {"fullname": "paddles.stack.LinkedListStack.size", "modulename": "paddles.stack", "qualname": "LinkedListStack.size", "kind": "function", "doc": "

Return how many members the stack has.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> int:", "funcdef": "def"}, {"fullname": "paddles.stack.LinkedListStack.push", "modulename": "paddles.stack", "qualname": "LinkedListStack.push", "kind": "function", "doc": "

Put item on top of the stack.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.stack.LinkedListStack.pop", "modulename": "paddles.stack", "qualname": "LinkedListStack.pop", "kind": "function", "doc": "

Remove and return the member at the top of the stack.

\n\n

Raise ValueError if the stack is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.stack.LinkedListStack.peek", "modulename": "paddles.stack", "qualname": "LinkedListStack.peek", "kind": "function", "doc": "

Return the member at the top of the stack.

\n\n

Raise ValueError if the stack is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}]; + /** pdoc search index */const docs = [{"fullname": "paddles", "modulename": "paddles", "kind": "module", "doc": "

paddles is a pedagogical algorithms and data structures library that aims to

\n\n
    \n
  • be thoroughly tested and documented
  • \n
  • be easy to install, use and understand
  • \n
  • adhere to good Python coding practices.
  • \n
\n\n

To install the library, type pip install paddles at the command line,\npreferably after activating a virtual environment.\nYour default Python version must be 3.10 or later.

\n\n

This is version 0.1 of the library. It is a work in progress.\nIt currently implements the Stack, Queue and Deque abstract data types (ADTs).

\n\n

The code repository is at https://github.com/dsa-ou/paddles.\nThe formatted documentation is at https://dsa-ou.github.io/paddles.

\n\n

Licence

\n\n

paddles is Copyright \u00a9 2024 by The Open University, UK.\nThe code is licensed under a BSD 3-clause licence.\nThe documentation is licensed under a\nCreative Commons Attribution 4.0 International Licence.

\n"}, {"fullname": "paddles.deque", "modulename": "paddles.deque", "kind": "module", "doc": "

This module implements the Deque ADT.

\n\n

Intuition

\n\n

The Deque ADT models a line of objects that can be accessed, added to and\nremoved from either end of the line.\nA deque can be used as a stack or as a queue.

\n\n

Definition

\n\n

A deque, pronounced 'deck' and short for 'double-ended queue', is a sequence\nwhere only the members at both ends of the sequence\n(called the front and the back of the queue) can be accessed and removed.\nNew members can only be added at the front or at the back.

\n\n

Operations

\n\n

The Deque ADT provides operations to:

\n\n
    \n
  • create a new empty deque
  • \n
  • add a new member to the front of the deque
  • \n
  • add a new member to the back of the deque
  • \n
  • remove the member at the front of the deque
  • \n
  • remove the member at the back of the deque
  • \n
  • access the member at the front of the deque without removing it
  • \n
  • access the member at the back of the deque without removing it
  • \n
  • compute the size of the deque (number of members).
  • \n
\n\n

Applications

\n\n

Consider using a deque when you need to simulate a queue where

\n\n
    \n
  • objects jump the queue (join at the front) or\nleave it from the back after waiting a certain time
  • \n
  • the direction of the queue changes, like cars on a ferry.
  • \n
\n\n

Implementations

\n\n

The Deque ADT can be implemented with circular dynamic arrays or doubly-linked lists.\nIn both cases, the operations listed above take constant time.\nA doubly-linked list uses much more memory than a static array of the same length,\nbut a dynamic array may have wasted capacity and requires resizing.\npaddles only provides a doubly-linked list implementation for the moment.

\n"}, {"fullname": "paddles.deque.LinkedListDeque", "modulename": "paddles.deque", "qualname": "LinkedListDeque", "kind": "class", "doc": "

An implementation of the Deque ADT, using a doubly-linked list.

\n\n

Besides the ADT's operations, this class provides two convenience operations:

\n\n
    \n
  • create a non-empty deque from a given sequence
  • \n
  • convert a deque to a string, to see its members listed from front to back.
  • \n
\n\n
\n
>>> from paddles.deque import LinkedListDeque\n>>> deque = LinkedListDeque("abc")          # create a non-empty deque\n>>> deque.size()                            # number of members\n3\n>>> deque.take_front()                      # remove and return the front member\n'a'\n>>> deque.take_back()                       # remove and return the back member\n'c'\n>>> deque.front() == deque.back() == 'b'    # return the front and back members\nTrue\n>>> deque.add_back("C")                     # add a new member at the back\n>>> deque.add_front("A")                    # add a new member at the front\n>>> print(deque)                            # str(deque) also possible\nLinkedListDeque(['A', 'b', 'C'])\n
\n
\n"}, {"fullname": "paddles.deque.LinkedListDeque.__init__", "modulename": "paddles.deque", "qualname": "LinkedListDeque.__init__", "kind": "function", "doc": "

Initialize the deque with the members of sequence.

\n\n

The members are added to the deque in the order they are in sequence.\nTo create an empty deque, call LinkedListDeque() or LinkedListDeque([]).

\n\n

Complexity: O(len(sequence))

\n", "signature": "(sequence: collections.abc.Sequence[typing.Any] = [])"}, {"fullname": "paddles.deque.LinkedListDeque.size", "modulename": "paddles.deque", "qualname": "LinkedListDeque.size", "kind": "function", "doc": "

Return how many members the deque has.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> int:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.front", "modulename": "paddles.deque", "qualname": "LinkedListDeque.front", "kind": "function", "doc": "

Return the item at the front of the deque, without removing it.

\n\n

Raise ValueError if the deque is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.back", "modulename": "paddles.deque", "qualname": "LinkedListDeque.back", "kind": "function", "doc": "

Return the item at the back of the deque, without removing it.

\n\n

Raise ValueError if the deque is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.add_front", "modulename": "paddles.deque", "qualname": "LinkedListDeque.add_front", "kind": "function", "doc": "

Put item at the front of the deque.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.add_back", "modulename": "paddles.deque", "qualname": "LinkedListDeque.add_back", "kind": "function", "doc": "

Put item at the back of the deque.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.take_front", "modulename": "paddles.deque", "qualname": "LinkedListDeque.take_front", "kind": "function", "doc": "

Remove and return the item at the front of the deque.

\n\n

Raise ValueError if the deque is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.deque.LinkedListDeque.take_back", "modulename": "paddles.deque", "qualname": "LinkedListDeque.take_back", "kind": "function", "doc": "

Remove and return the item at the back of the deque.

\n\n

Raise ValueError if the deque is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.queue", "modulename": "paddles.queue", "kind": "module", "doc": "

This module implements the Queue ADT.

\n\n

Intuition

\n\n

The Queue ADT models a line of objects, e.g. cars waiting to board a ferry.\nOnly the object at the front of the line can be accessed and removed.\nThe only way to add an object is to put it at the back of the line.

\n\n

Definition

\n\n

A queue is a sequence where members are added to one end of the sequence\n(the back of the queue) and removed from the other end (the front of the queue).

\n\n

A queue is a first-in, first-out (FIFO) sequence:\nthe members are removed in the same order they were added.

\n\n

A queue is a sequence ordered by age (time of addition).\nThe oldest member is at the front of the queue, and the youngest member is at the back.

\n\n

Operations

\n\n

The Queue ADT provides operations to:

\n\n
    \n
  • create a new empty queue
  • \n
  • add a new member, at the back of the existing ones
  • \n
  • remove the member at the front of the queue
  • \n
  • access the member at the front of the queue without removing it
  • \n
  • compute the size of the queue (number of members).
  • \n
\n\n

Applications

\n\n

Queues are used to implement breadth-first search.\nYou should consider using a queue when you need to:

\n\n
    \n
  • simulate a real-life queue, like travellers at passport control or\ndocuments in a printer queue
  • \n
  • process items in the same order they were added, like a to-do list.
  • \n
\n\n

Implementations

\n\n

The Queue ADT can be implemented with circular dynamic arrays or singly-linked lists.\nIn both cases, the operations listed above take constant time.\nA singly-linked list uses much more memory than a static array of the same length,\nbut a dynamic array may have wasted capacity and requires resizing.\npaddles only provides a singly-linked list implementation for the moment.

\n"}, {"fullname": "paddles.queue.LinkedListQueue", "modulename": "paddles.queue", "qualname": "LinkedListQueue", "kind": "class", "doc": "

An implementation of the Queue ADT, using a singly-linked list.

\n\n

Besides the ADT's operations, this class provides two convenience operations:

\n\n
    \n
  • create a non-empty queue from a given sequence
  • \n
  • convert a queue to a string, to see its members listed from front to back.
  • \n
\n\n
\n
>>> from paddles.queue import LinkedListQueue\n>>> q = LinkedListQueue("abc")  # create a non-empty queue\n>>> q.size()                    # number of members\n3\n>>> q.dequeue()                 # remove and return the front member\n'a'\n>>> q.front()                   # return but don't remove the front member\n'b'\n>>> q.enqueue("d")              # add a new member at the back\n>>> print(q)                    # str(q) also possible\nLinkedListQueue(['b', 'c', 'd'])\n
\n
\n"}, {"fullname": "paddles.queue.LinkedListQueue.__init__", "modulename": "paddles.queue", "qualname": "LinkedListQueue.__init__", "kind": "function", "doc": "

Initialize the queue with the members of sequence.

\n\n

The members are added to the queue in the order they are in sequence.\nTo create an empty queue, call LinkedListQueue() or LinkedListQueue([]).

\n\n

Complexity: O(len(sequence))

\n", "signature": "(sequence: collections.abc.Sequence[typing.Any] = [])"}, {"fullname": "paddles.queue.LinkedListQueue.size", "modulename": "paddles.queue", "qualname": "LinkedListQueue.size", "kind": "function", "doc": "

Return how many members the queue has.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> int:", "funcdef": "def"}, {"fullname": "paddles.queue.LinkedListQueue.front", "modulename": "paddles.queue", "qualname": "LinkedListQueue.front", "kind": "function", "doc": "

Return the member at the front of the queue, without removing it.

\n\n

Raise ValueError if the queue is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.queue.LinkedListQueue.enqueue", "modulename": "paddles.queue", "qualname": "LinkedListQueue.enqueue", "kind": "function", "doc": "

Put item at the back of the queue.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.queue.LinkedListQueue.dequeue", "modulename": "paddles.queue", "qualname": "LinkedListQueue.dequeue", "kind": "function", "doc": "

Remove and return the item at the front of the queue.

\n\n

Raise ValueError if the queue is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.stack", "modulename": "paddles.stack", "kind": "module", "doc": "

This module implements the Stack ADT.

\n\n

Intuition

\n\n

The Stack ADT models a pile of objects, e.g. a pile of storage boxes.\nOnly the object at the top of the pile can be accessed and removed.\nThe only way to add an object is to put it on top of the existing pile.

\n\n

Definition

\n\n

A stack is a sequence where members are removed from and added to\nthe same end of the sequence, called the top of the stack.

\n\n

A stack is a last-in, first-out (LIFO) sequence:\nthe next member to be removed is the one most recently added.

\n\n

A stack is a sequence ordered by age (time of addition).\nThe oldest member is at the bottom of the stack, and the youngest member is at the top.

\n\n

Operations

\n\n

The Stack ADT provides operations to:

\n\n
    \n
  • create a new empty stack
  • \n
  • add a new member, on top of the existing ones
  • \n
  • remove the member at the top of the stack
  • \n
  • access the member at the top of the stack without removing it
  • \n
  • compute the size of the stack (number of members).
  • \n
\n\n

Applications

\n\n

Stacks are used to implement function calls and depth-first search.\nYou should consider using a stack when you need to:

\n\n
    \n
  • simulate the handling of a pile of objects, like loading and unloading ship containers
  • \n
  • process nested structures, like brackets (e.g. print([1, {2, 3}])) or\nHTML tags (e.g. <p><b>text</b></p>)
  • \n
  • process items in the reverse order they were added, like undo operations\n(the next command to be undone is the most recently executed one).
  • \n
\n\n

Implementations

\n\n

The Stack ADT can be implemented with dynamic arrays or singly-linked lists.\nIn both cases, the operations listed above take constant time.\nA singly-linked list uses much more memory than a static array of the same length,\nbut a dynamic array may have wasted capacity and requires resizing.

\n"}, {"fullname": "paddles.stack.DynamicArrayStack", "modulename": "paddles.stack", "qualname": "DynamicArrayStack", "kind": "class", "doc": "

An implementation of the Stack ADT, using Python lists.

\n\n

Besides the ADT's operations, this class provides two convenience operations:

\n\n
    \n
  • create a non-empty stack from a given sequence
  • \n
  • convert a stack to a string, to see its members listed from bottom to top.
  • \n
\n\n
\n
>>> from paddles.stack import DynamicArrayStack\n>>> stack = DynamicArrayStack("abc")    # create a non-empty stack\n>>> stack.size()                        # number of members\n3\n>>> stack.pop()                         # remove and return the top member\n'c'\n>>> stack.peek()                        # return but don't remove the top member\n'b'\n>>> stack.push("C")                     # add a new member on top\n>>> print(stack)                        # str(stack) also possible\nDynamicArrayStack(['a', 'b', 'C'])\n
\n
\n"}, {"fullname": "paddles.stack.DynamicArrayStack.__init__", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.__init__", "kind": "function", "doc": "

Initialize the stack with the members of sequence.

\n\n

The members are added to the stack in the order they are in sequence.\nTo create an empty stack, call DynamicArrayStack() or DynamicArrayStack([]).

\n\n

Complexity: O(len(sequence))

\n", "signature": "(sequence: collections.abc.Sequence[typing.Any] = [])"}, {"fullname": "paddles.stack.DynamicArrayStack.size", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.size", "kind": "function", "doc": "

Return how many members the stack has.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> int:", "funcdef": "def"}, {"fullname": "paddles.stack.DynamicArrayStack.peek", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.peek", "kind": "function", "doc": "

Return the member at the top of the stack, without removing it.

\n\n

Raise ValueError if the stack is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.stack.DynamicArrayStack.push", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.push", "kind": "function", "doc": "

Put item on top of the stack.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.stack.DynamicArrayStack.pop", "modulename": "paddles.stack", "qualname": "DynamicArrayStack.pop", "kind": "function", "doc": "

Remove and return the member at the top of the stack.

\n\n

Raise ValueError if the stack is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.stack.LinkedListStack", "modulename": "paddles.stack", "qualname": "LinkedListStack", "kind": "class", "doc": "

An implementation of the Stack ADT, using singly-linked lists.

\n\n

Besides the ADT's operations, this class provides two convenience operations:

\n\n
    \n
  • create a non-empty stack from a given sequence
  • \n
  • convert a stack to a string, to see its members listed from bottom to top.
  • \n
\n\n
\n
>>> from paddles.stack import LinkedListStack\n>>> stack = LinkedListStack("abc")      # create a non-empty stack\n>>> stack.size()                        # number of members\n3\n>>> stack.pop()                         # remove and return the top member\n'c'\n>>> stack.peek()                        # return but don't remove the top member\n'b'\n>>> stack.push("C")                     # add a new member on top\n>>> print(stack)                        # str(stack) also possible\nLinkedListStack(['a', 'b', 'C'])\n
\n
\n"}, {"fullname": "paddles.stack.LinkedListStack.__init__", "modulename": "paddles.stack", "qualname": "LinkedListStack.__init__", "kind": "function", "doc": "

Initialize the stack with the members of sequence.

\n\n

The members are added to the stack in the order they are in sequence.\nTo create an empty stack, call LinkedListStack() or LinkedListStack([]).

\n\n

Complexity: O(len(sequence))

\n", "signature": "(sequence: collections.abc.Sequence[typing.Any] = [])"}, {"fullname": "paddles.stack.LinkedListStack.size", "modulename": "paddles.stack", "qualname": "LinkedListStack.size", "kind": "function", "doc": "

Return how many members the stack has.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> int:", "funcdef": "def"}, {"fullname": "paddles.stack.LinkedListStack.push", "modulename": "paddles.stack", "qualname": "LinkedListStack.push", "kind": "function", "doc": "

Put item on top of the stack.

\n\n

Complexity: O(1)

\n", "signature": "(self, item: Any) -> None:", "funcdef": "def"}, {"fullname": "paddles.stack.LinkedListStack.pop", "modulename": "paddles.stack", "qualname": "LinkedListStack.pop", "kind": "function", "doc": "

Remove and return the member at the top of the stack.

\n\n

Raise ValueError if the stack is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "paddles.stack.LinkedListStack.peek", "modulename": "paddles.stack", "qualname": "LinkedListStack.peek", "kind": "function", "doc": "

Return the member at the top of the stack.

\n\n

Raise ValueError if the stack is empty.

\n\n

Complexity: O(1)

\n", "signature": "(self) -> Any:", "funcdef": "def"}]; // mirrored in build-search-index.js (part 1) // Also split on html tags. this is a cheap heuristic, but good enough. diff --git a/paddles/__init__.py b/paddles/__init__.py index 2a87b56..0a70e64 100644 --- a/paddles/__init__.py +++ b/paddles/__init__.py @@ -1,14 +1,3 @@ -"""`paddles` is a pedagogical algorithms and data structures library. - -It currently implements the Stack, Queue and Deque abstract data types (ADTs). - -The code repository is at https://github.com/dsa-ou/paddles. -The formatted documentation is at https://dsa-ou.github.io/paddles. - -## Licence - -`paddles` is Copyright © 2024 by The Open University, UK. -The code is licensed under a [BSD-3-clause licence](https://github.com/dsa-ou/paddles/blob/main/LICENSE). -The documentation is licensed under a -[Creative Commons Attribution 4.0 International Licence](http://creativecommons.org/licenses/by/4.0). """ +.. include:: ../README.md +""" # noqa: D200, D400 diff --git a/pyproject.toml b/pyproject.toml index 8d859f1..2accca7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,19 @@ version = "0.1.0" description = "A pedagogical algorithms and data structures library" authors = ["Michel Wermelinger "] readme = "README.md" +license = "BDS-3-Clause" +homepage = "https://dsa-ou.github.io/paddles/" +repository = "https://github.com/dsa-ou/paddles" +keywords = ["algorithms", "data structures", "education"] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Education", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python :: 3.10", + "Topic :: Education", + "Topic :: Software Development :: Libraries :: Python Modules", + "Operating System :: OS Independent", + ] [tool.poetry.dependencies] python = "^3.10"