text:
babili (babel-minify)

  An ES6+ aware minifier based on the Babel toolchain.

- NOTE: We are in a [feature freeze](https://github.com/babel/babili/issues/71) as we're trying to hammer out all the bugs to get to beta release. The best way to contribute is to test, report bugs, and add test cases.

- Checkout our [CONTRIBUTING.md](/CONTRIBUTING.md) if you want to help out!

- babili is consumable via API, CLI, or babel preset.

- Try it online - [babeljs.io/repl](http://babeljs.io/repl/#?babili=true&evaluate=false&lineWrap=false&presets=react%2Cstage-2&code=%2F%2F%20Example%20ES2015%20Code%0Aclass%20Mangler%20%7B%0A%20%20constructor(program)%20%7B%0A%20%20%20%20this.program%20%3D%20program%3B%0A%20%20%7D%0A%7D%0Anew%20Mangler()%3B%20%2F%2F%20without%20this%20it%20would%20just%20output%20nothing%20since%20Mangler%20isn%27t%20used)

## Why

Current tools don't support targeting the latest version of ECMAScript. (yet)
- Babili can because it is just a set of Babel plugins, and Babel already understands new syntax with our parser [Babylon](https://github.com/babel/babylon).
- When it's possible to only target browsers that support newer ES features, code sizes can be smaller because you don't have to transpile and then minify.

Check out our [blog post](http://babeljs.io/blog/2016/08/30/babili) for more info!

```js
// Example ES2015 Code
class Mangler {
  constructor(program) {
    this.program = program;
  }
}
new Mangler(); // without this it would just output nothing since Mangler isn't used
```

Before
```js
// ES2015+ code -> Babel -> Babili/Uglify -> Minified ES5 Code
var a=function a(b){_classCallCheck(this,a),this.program=b};new a;
```

After

```js
// ES2015+ code -> Babili -> Minified ES2015+ Code
class a{constructor(b){this.program=b}}new a;
```

## [CLI](http://babeljs.io/docs/usage/cli/)

| Package | Version | Dependencies |
|--------|-------|------------|
| [`babili`](/packages/babili) | [![npm](https://img.shields.io/npm/v/babili.svg?maxAge=86400)](https://www.npmjs.com/package/babili) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babili)](https://david-dm.org/babel/babili?path=packages/babili) |

This is simple wrapper around the regular `babel-cli` and thus takes in the same [cli options](http://babeljs.io/docs/usage/cli/#options) as running babel on its own. You can use this if you don't already use babel or want to run it standalone.

### Usage

`babili src -d lib`

Equivalent to:
`babel src -d lib --presets=babili --no-babelrc`

## [Babel preset](http://babeljs.io/docs/plugins/#presets)

| Package | Version | Dependencies |
|--------|-------|------------|
| [`babel-preset-babili`](/packages/babel-preset-babili) | [![npm](https://img.shields.io/npm/v/babel-preset-babili.svg?maxAge=86400)](https://www.npmjs.com/package/babel-preset-babili) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-preset-babili)](https://david-dm.org/babel/babili?path=packages/babel-preset-babili) |

It's a Babel preset (like `babel-preset-es2015`).

### Usage

You'll most likely want to use it only in the production environment. Check out the [env docs](http://babeljs.io/docs/usage/babelrc/#env-option) for more help.

> Options specific to a certain environment are merged into and overwrite non-env specific options.

`.babelrc`:

```
{
  "presets": ["es2015"],
  "env": {
    "production": {
      "presets": ["babili"]
    }
  }
}
```

Then you'll need to set the env variable which could be something like `BABEL_ENV=production npm run build`

## [Plugins](http://babeljs.io/docs/plugins/) (in `babel-preset-babili`)

The `babili` repo is comprised of many npm packages. It is a [lerna](https://github.com/lerna/lerna) monorepo similar to [babel](https://github.com/babel/babel) itself.

The npm package `babel-preset-babili` is at the path `packages/babel-preset-babili`

| Package | Version | Dependencies |
|--------|-------|------------|
| [`babel-plugin-minify-constant-folding`](/packages/babel-plugin-minify-constant-folding) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-constant-folding.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-constant-folding) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-constant-folding)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-constant-folding) |
| [`babel-plugin-minify-dead-code-elimination`](/packages/babel-plugin-minify-dead-code-elimination) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-dead-code-elimination.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-dead-code-elimination) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-dead-code-elimination)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-dead-code-elimination) |
| [`babel-plugin-minify-flip-comparisons`](/packages/babel-plugin-minify-flip-comparisons) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-flip-comparisons.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-flip-comparisons) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-flip-comparisons)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-flip-comparisons) |
| [`babel-plugin-minify-guarded-expressions`](/packages/babel-plugin-minify-guarded-expressions) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-guarded-expressions.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-guarded-expressions) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-guarded-expressions)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-guarded-expressions) |
| [`babel-plugin-minify-infinity`](/packages/babel-plugin-minify-infinity) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-infinity.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-infinity) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-infinity)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-infinity) |
| [`babel-plugin-minify-mangle-names`](/packages/babel-plugin-minify-mangle-names) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-mangle-names.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-mangle-names) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-mangle-names)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-mangle-names) |
| [`babel-plugin-minify-replace`](/packages/babel-plugin-minify-replace) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-replace.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-replace) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-replace)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-replace) |
| [`babel-plugin-minify-simplify`](/packages/babel-plugin-minify-simplify) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-simplify.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-simplify) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-simplify)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-simplify) |
| [`babel-plugin-minify-type-constructors`](/packages/babel-plugin-minify-type-constructors) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-type-constructors.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-type-constructors) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-type-constructors)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-type-constructors) |
| [`babel-plugin-transform-member-expression-literals`](/packages/babel-plugin-transform-member-expression-literals) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-member-expression-literals.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-member-expression-literals) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-member-expression-literals)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-member-expression-literals) |
| [`babel-plugin-transform-merge-sibling-variables`](/packages/babel-plugin-transform-merge-sibling-variables) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-merge-sibling-variables.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-merge-sibling-variables) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-merge-sibling-variables)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-merge-sibling-variables) |
| [`babel-plugin-transform-minify-booleans`](/packages/babel-plugin-transform-minify-booleans) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-minify-booleans.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-minify-booleans) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-minify-booleans)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-minify-booleans) |
| [`babel-plugin-transform-property-literals`](/packages/babel-plugin-transform-property-literals) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-property-literals.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-property-literals) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-property-literals)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-property-literals) |
| [`babel-plugin-transform-simplify-comparison-operators`](/packages/babel-plugin-transform-simplify-comparison-operators) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-simplify-comparison-operators.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-simplify-comparison-operators) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-simplify-comparison-operators)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-simplify-comparison-operators) |
| [`babel-plugin-transform-undefined-to-void`](/packages/babel-plugin-transform-undefined-to-void) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-undefined-to-void.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-undefined-to-void) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-undefined-to-void)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-undefined-to-void) |

### Usage

> Normally you wouldn't be consuming the plugins directly since the preset is available.

Add to your `.babelrc`'s plugins array.

```
{
  "plugins": ["babel-plugin-transform-undefined-to-void"]
}
```

## Other

| Package | Version | Dependencies |
|--------|-------|------------|
| [`babel-plugin-minify-empty-function`](/packages/babel-plugin-minify-empty-function) | [![npm](https://img.shields.io/npm/v/babel-plugin-minify-empty-function.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-minify-empty-function) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-minify-empty-function)](https://david-dm.org/babel/babili?path=packages/babel-plugin-minify-empty-function) |
| [`babel-plugin-transform-inline-environment-variables`](/packages/babel-plugin-transform-inline-environment-variables) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-inline-environment-variables.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-inline-environment-variables) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-inline-environment-variables)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-inline-environment-variables) |
| [`babel-plugin-transform-node-env-inline`](/packages/babel-plugin-transform-node-env-inline) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-node-env-inline.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-node-env-inline) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-node-env-inline)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-node-env-inline) |
| [`babel-plugin-transform-remove-console`](/packages/babel-plugin-transform-remove-console) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-remove-console.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-remove-console) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-remove-console)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-remove-console) |
| [`babel-plugin-transform-remove-debugger`](/packages/babel-plugin-transform-remove-debugger) | [![npm](https://img.shields.io/npm/v/babel-plugin-transform-remove-debugger.svg?maxAge=86400)](https://www.npmjs.com/package/babel-plugin-transform-remove-debugger) | [![Dependency Status](https://david-dm.org/babel/babili.svg?path=packages/babel-plugin-transform-remove-debugger)](https://david-dm.org/babel/babili?path=packages/babel-plugin-transform-remove-debugger) |

## Benchmarks
> Bootstrap: `npm run bootstrap`

> Build:  `npm run build`

> Running the benchmarks: `./scripts/benchmark.js file.js`

Backbone.js:
```
           raw     raw win gzip   gzip win parse time run
uglify     21.79kB 221%    7.29kB 169%     1ms        247ms
closure    21.67kB 223%    7.37kB 167%     2ms        1223ms
babili     21.9kB  219%    7.46kB 164%     2ms        722ms
closure js 24.01kB 191%    8.04kB 144%     2ms        3301ms
```

Run with: `./scripts/benchmark.js ./scripts/fixtures/backbone.js`

React:
```
          raw      raw win gzip    gzip win parse time run
closure    171.46kB 265%    52.97kB 168%     14ms       2457ms
uglify     176.36kB 255%    53.13kB 167%     12ms       1367ms
closure js 173.95kB 260%    53.53kB 165%     12ms       11846ms
babili     177.87kB 252%    55.41kB 156%     13ms       3059ms
```

Run with: `./scripts/benchmark.js ./scripts/fixtures/react.js`

jQuery:
```
           raw      raw win gzip    gzip win parse time run
uglify     94.27kB  218%    32.78kB 158%     6ms        955ms
closure    94.23kB  218%    33.38kB 153%     18ms       1760ms
closure js 95.64kB  213%    33.78kB 150%     8ms        9295ms
babili     102.74kB 192%    35.3kB  139%     8ms        2912ms
```

Run with: `./scripts/benchmark.js ./scripts/fixtures/jquery.js`


text:
# Playing Card UI

A simple meteor template for displaying playing cards.

Example:
```html
{{> playingCard rank="A" suit="H" text="textOnCard"}}
```
![Alt text](https://github.com/kaamodt/meteor-playing-cards-ui/blob/screenshots/screenshots/singleCard.png?raw=true "Single Card")

The template can take 3 arguments, rank, suit and text. In reality there is no restrictions on the rank argument, but it is meant to work with values A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q and K. The suit argument takes the strings C, D, H and S. The text argument is optional and added if you want some text on the card. E.g, denoting the player of a card in a multiplayer game.

For displaying back of a card use only the argument back=true.

Example:
```html
{{> playingCard back=true}}
```
![Alt text](https://github.com/kaamodt/meteor-playing-cards-ui/blob/screenshots/screenshots/cardBack.png?raw=true "Card Back")

## Laying out cards

The template has defined two css classes for laying out the cards. The first, .cardsContainer, will lay out the cards next to each other with full width. E.g, as they would be on a table. The configuration support max 10 cards displayed in a row this way.

Example:
```HTML
<div class="cardsContainer">
  {{> playingCard rank="A" suit="H" text="textOnCard"}}
  {{> playingCard rank="A" suit="D" text="textOnCard"}}
  {{> playingCard rank="A" suit="S" text="textOnCard"}}
  {{> playingCard rank="A" suit="C" text="textOnCard"}}
</div>
```
![Alt text](https://github.com/kaamodt/meteor-playing-cards-ui/blob/screenshots/screenshots/tableLayout.png?raw=true "Table Layout")
Adding the other, .cardsInHand, will lay out the card overlapping. As you would normally stack card in your hand when playing cards. The configuration support max 13 cards displayed in a row this way.

Example:
```HTML
<div class="cardsContainer cardsInHand">
  {{> playingCard rank="A" suit="H" text="textOnCard"}}
  {{> playingCard rank="A" suit="D" text="textOnCard"}}
  {{> playingCard rank="A" suit="S" text="textOnCard"}}
  {{> playingCard rank="A" suit="C" text="textOnCard"}}
</div>
```
![Alt text](https://github.com/kaamodt/meteor-playing-cards-ui/blob/screenshots/screenshots/handLayout.png?raw=true "Hand Layout")

The number of cards you can display with these classes can easily be extended by adding your own css with the following structure for .cardsContainer:

```css
.card:nth-of-type(n) { left: ((n-1)*7)em; }
```
Where n is a number above 10.

And similar for the .cardsInHand class:

```css
.cardsInHand .card:nth-of-type(n) { left: (n-1)em; }
```
Where n is a number above 13.

## Scaling

The size is based out of the css property font-size. By default this is 14px. Add a class/id with a font-size defined to a wrapper div in order to scale the cards as wanted. Example:

```css
.size-20 {
  font-size: 20px;
}
```
```html
<div class="cardsContainer cardsInHand size-20">
  {{> playingCard rank="A" suit="H" text="textOnCard"}}
  {{> playingCard rank="A" suit="D" text="textOnCard"}}
  {{> playingCard rank="A" suit="S" text="textOnCard"}}
  {{> playingCard rank="A" suit="C" text="textOnCard"}}
</div>
```

## Acknowledgement

The css in this package is heavily based on the css explained in this guide: http://spin.atomicobject.com/2013/02/22/css-sprite-semantics-scaleability/

license: MIT

repository: kaamodt/meteor-playing-cards-ui

branch_name: refs/heads/master

extension: md

license_type: permissive

repo_name: kaamodt/meteor-playing-cards-ui


text:
---
hrs_structure:
  division: '2'
  volume: '10'
  title: '25'
  chapter: '442'
  section: 442-14
type: hrs_section
tags:
  - Business
menu:
  hrs:
    identifier: HRS_0442-0014
    parent: HRS0442
    name: 442-14 Change of residence
weight: 29070
title: Change of residence
full_title: 442-14 Change of residence
---
**§442-14 Change of residence.** Every holder of a license who leaves to reside outside the State, shall immediately notify the board of chiropractic examiners of the change in writing and the change shall be noted in the board records. Failure to do so constitutes a violation and results in a forfeiture of the license, and it shall not be restored except upon the written application therefor and a payment to the board of a penalty fee. [L 1955, c 229, pt of §1(d); RL 1955, §60-10.4; [HRS §442-14](/title-25/chapter-442/section-442-14/); am L 1984, c 7, §22; am L 1992, c 150, §6]

repository: SamMade/BlueAndKrabby

repo_name: SamMade/BlueAndKrabby


text:
# aguaclara_research

[![Build Status](https://travis-ci.org/AguaClara/aguaclara_research.svg?branch=master)](https://travis-ci.org/AguaClara/aguaclara_research)
[![codecov.io](https://codecov.io/github/hbetts/orbitalpy/coverage.svg?branch=master)](https://codecov.io/github/AguaClara/aguaclara_research?branch=master)

This project contains code helpful to those conducting research for AguaClara. The functions included help to parse data from ProCoDA files and then analyze it. Additional scripts help to determine the correct stock concentrations, tubing, and other useful information for experimental setup.

## Installation

### Pip
You will probably want to install from pip, where we host the latest production package. If you downloaded Anaconda, you'll already have pip installed. The following is how to install with pip:
- If you'd like to install across your whole machine, you can open the cmd (Windows) or teminal (mac) and type ```$pip install aguaclara_research``` (where $ signifies the beginning of the command.) If you get a permission denied error, you probably want to install it instead to your particular user with ```$pip install aguaclara_research -U```.
- Once you've installed the package once, you can simply use: ```$pip install --upgrade aguaclara_research```. And if you don't want to update dependencies then use: ```$pip install aguaclara_research -U --no-deps```.

### Installing as a developer
If you want to be able to edit the source code, you need to clone this repo with git, then go into the top level directory with pip: ```pip install . -U```. Now you should be able to import your local version of aguaclara_research into python: ```import aguaclara_research```.

## Contributing

Read [CONTRIBUTING](CONTRIBUTING.md).


text:
[![DockerPulls](https://img.shields.io/docker/pulls/imperialgenomicsfacility/scanpy-notebook-image.svg)](https://registry.hub.docker.com/r/imperialgenomicsfacility/scanpy-notebook-image)
[![DockerStars](https://img.shields.io/docker/stars/imperialgenomicsfacility/scanpy-notebook-image.svg)](https://registry.hub.docker.com/r/imperialgenomicsfacility/scanpy-notebook-image)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/imperial-genomics-facility/scanpy-notebook-image/master?urlpath=lab)
[![nbviewer](https://img.shields.io/badge/launch-nbviewer-coral)](https://nbviewer.jupyter.org/github/imperial-genomics-facility/scanpy-notebook-image/tree/master/)
# Notebook container image for running single cell data analysis using scanpy
A repository for keeping conda env and docker image file for running single cell analysis using scanpy. Example notebooks are kept at `examples` dir and template notebooks are kept in `templates` dir.

## Before using examples notebooks

List of prerequisites for using these example notebooks:

* [JupyterLab Documentation](https://jupyterlab.readthedocs.io/en/latest/index.html)
* [Single cell analysis using Cellranger (10X genomics)](https://support.10xgenomics.com/single-cell-gene-expression/software/pipelines/latest/what-is-cell-ranger)
* [Scanpy package for single cell data analysis](https://icb-scanpy.readthedocs-hosted.com/en/stable/)

## List of example notebooks:

* [Preprocessing and clustering 3k PBMCs from a Healthy Donor (10x Genomics) v0.0.5 :](https://nbviewer.jupyter.org/github/imperial-genomics-facility/scanpy-notebook-image/blob/master/examples/Clustering_3K_PBMCs_v0.0.5.ipynb) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/imperial-genomics-facility/scanpy-notebook-image/master?urlpath=lab%2Ftree%2Fexamples%2FClustering_3K_PBMCs_v0.0.5.ipynb)

* [RNA Velocity Basics v 0.0.1:](https://nbviewer.jupyter.org/github/imperial-genomics-facility/scanpy-notebook-image/blob/master/examples/VelocityBasics_v0.0.1.ipynb) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/imperial-genomics-facility/scanpy-notebook-image/master?urlpath=lab%2Ftree%2Fexamples%2FVelocityBasics_v0.0.1.ipynb)

## Installed packages

Please check the `Dockerfile` and `environment.yml` file for all the detail.

## Explore notebooks

Explore the example notebooks from this repo in `examples` dir using nbviewer:

  [![nbviewer](https://img.shields.io/badge/launch-nbviewer-coral)](https://nbviewer.jupyter.org/github/imperial-genomics-facility/scanpy-notebook-image/tree/master/)

## Run notebooks

### Using binder

Launce notebooks in binder for exploratory analysis:

[![binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/imperial-genomics-facility/scanpy-notebook-image/master?urlpath=lab)

### Using Docker

* Install Docker following these instructions: [Docker Engine overview](https://docs.docker.com/install/)
* Use the following command to pull docker image from Docker hub

  * Pull the latest image

docker pull imperialgenomicsfacility/scanpy-notebook-image

  * Pull a specific release

docker pull imperialgenomicsfacility/scanpy-notebook-image:release-xyz

* Run notebook container in docker

docker run
  -p 8888:8888
  -v /path/:/tmp
  imperialgenomicsfacility/scanpy-notebook-image:tag

### Using Singularity

* Build singularity image

singularity
  build
  scanpy-notebook-image.sif
  docker://imperialgenomicsfacility/scanpy-notebook-image

* Run jupyter notebook or nbconvert from singularity container

singularity
  run
  --bind /path:/tmp
  scanpy-notebook-image.sif
    jupyter nbconvert /tmp/notebook.ipynb --execute


text:
# Code Signal CGA Sprint Resources

{% embed<EMAIL_ADDRESS>%}

```python
"""
GCA Practice
"""

"""
Mutate the array
----------------
Given an integer n and an array a of length n, your task is to apply the following mutation to a:

Array a mutates into a new array b of length n.
For each i from 0 to n - 1, b[i] = a[i - 1] + a[i] + a[i + 1].
If some element in the sum a[i - 1] + a[i] + a[i + 1] does not exist, it should be set to 0. For example, b[0] should be equal to 0 + a[0] + a[1].
Example

For n = 5 and a = [4, 0, 1, -2, 3], the output should be mutateTheArray(n, a) = [4, 5, -1, 2, 1].

b[0] = 0 + a[0] + a[1] = 0 + 4 + 0 = 4
b[1] = a[0] + a[1] + a[2] = 4 + 0 + 1 = 5
b[2] = a[1] + a[2] + a[3] = 0 + 1 + (-2) = -1
b[3] = a[2] + a[3] + a[4] = 1 + (-2) + 3 = 2
b[4] = a[3] + a[4] + 0 = (-2) + 3 + 0 = 1
So, the resulting array after the mutation will be [4, 5, -1, 2, 1]
"""
a = [4, 0, 1, -2, 3]
n = 5

# passing
def mutateTheArray(n, a):
    if len(a) < 2:
        return a
    result = []
    for i in range(len(a)):
        # if i = 0 then i - 1 does not exist so [i-1] becomes 0 and we can
        # just leave it off
        if i == 0:
            result.append(a[i] + a[i + 1])
        # if i is pointing to the last element then [i + 1] does not exist so
        # it becomes 0 and we can just leave that off
        elif i == len(a) - 1:
            result.append((a[i - 1] + a[i]))
        # for all other cases just do the normal equation
        else:
            result.append(a[i - 1] + a[i] + a[i + 1])

    return result

# print(mutateTheArray(n, a))

"""
Alternating sort
You are given an array of integers a. A new array b is generated by rearranging the elements of a in the following way:

b[0] is equal to a[0];
b[1] is equal to the last element of a;
b[2] is equal to a[1];
b[3] is equal to the second-last element of a;
b[4] is equal to a[2];
b[5] is equal to the third-last element of a;
and so on.
Here is how this process works:

Your task is to determine whether the new array b is sorted in strictly ascending order or not.

Example

For a = [1, 3, 5, 6, 4, 2], the output should be alternatingSort(a) = true.

The new array b will look like [1, 2, 3, 4, 5, 6], which is in strictly ascending order, so the answer is true.

For a = [1, 4, 5, 6, 3], the output should be alternatingSort(a) = false.

The new array b will look like [1, 3, 4, 6, 5], which is not in strictly ascending order, so the answer is false.
"""
a = [1, 3, 5, 6, 4, 2]
# a = [1, 4, 5, 6, 3]
# a = [-92, -23, 0, 45, 89, 96, 99, 95, 89, 41, -17, -48]
a = [-91, -84, -67, -44, 9, 70, 88, 37, -11, -67, -72, -87]
a = [-99, -29, -7, 17, 28, 71, 98, 86, 42, 22, 0, -29, -86]

# passing
from collections import deque

def alternatingSort(a):
    a = deque(a)
    if len(a) < 2:
        return True
    if a == []:
        return False
    # array to hold result
    b = []
    # sorted a without duplicates to check against result array to see if
    # result is sorted or not
    match = sorted(set(a))
    # while a still has numbers to sort into result array
    while len(a) > 0:
        # if there is an even number of items left
        if len(b) % 2 == 0:
            # remove first element and add to result
            b.append(a.popleft())
        # else if there is an odd number of items left
        else:
            # remove last element and add it to the result
            b.append(a.pop())
    # if result == the original array sorted then return True else return False
    if b == match:
        return True
    return False

# print(alternatingSort(a))

"""
Tiny pairs
----------
You are given two arrays of integers a and b of the same length, and an integer k. We will be iterating through array a from left to right, and simultaneously through array b from right to left, and looking at pairs (x, y), where x is from a and y is from b. Such a pair is called tiny if the concatenation xy is strictly less than k.

Your task is to return the number of tiny pairs that you'll encounter during the simultaneous iteration through a and b.

Example

For a = [1, 2, 3], b = [1, 2, 3], and k = 31, the output should be
countTinyPairs(a, b, k) = 2.

We're considering the following pairs during iteration:

(1, 3). Their concatenation equals 13, which is less than 31, so the pair is tiny;
(2, 2). Their concatenation equals 22, which is less than 31, so the pair is tiny;
(3, 1). Their concatenation equals 31, which is not less than 31, so the pair is not tiny.
As you can see, there are 2 tiny pairs during the iteration, so the answer is 2.

For a = [16, 1, 4, 2, 14], b = [7, 11, 2, 0, 15], and k = 743, the output should be
countTinyPairs(a, b, k) = 4.

We're considering the following pairs during iteration:

(16, 15). Their concatenation equals 1615, which is greater than 743, so the pair is not tiny;
(1, 0). Their concatenation equals 10, which is less than 743, so the pair is tiny;
(4, 2). Their concatenation equals 42, which is less than 743, so the pair is tiny.
(2, 11). Their concatenation equals 211, which is less than 743, so the pair is tiny;
(14, 7). Their concatenation equals 147, which is less than 743, so the pair is tiny.
There are 4 tiny pairs during the iteration, so the answer is 4.
"""

a = [16, 1, 4, 2, 14]
b = [7, 11, 2, 0, 15]
k = 743

# passing
def countTinyPairs(a, b, k):
    # variable to hold the number of tiny pairs we've encountered
    pairs = 0
    # index of the last number in the array
    b_index = len(b) - 1
    # iterate the array
    for i in range(len(a)):
        # if the integer value of the string concatenation of the number at
        # the first index and the number at the last index is less than K
        # we found a tiny pair and can increment the pairs value + 1
        if int(str(a[i]) + str(b[b_index])) < k:
            pairs += 1
        # decrement the last index to check the next to last number
        b_index -= 1
    # return the number of pairs found
    return pairs

# print('pairs', countTinyPairs(a, b, k))

"""
Merging Strings
---------------
You are implementing your own programming language and you've decided to add support for merging strings. A typical merge function would take two strings s1 and s2, and return the lexicographically smallest result that can be obtained by placing the symbols of s2 between the symbols of s1 in such a way that maintains the relative order of the characters in each string.

For example, if s1 = "super" and s2 = "tower", the result should be merge(s1, s2) = "stouperwer".

You'd like to make your language more unique, so for your merge function, instead of comparing the characters in the usual lexicographical order, you'll compare them based on how many times they occur in their respective strings (fewer occurrences means the character is considered smaller). If the number of occurrences are equal, then the characters should be compared in the usual lexicographical way. If both number of occurences and characters are equal, you should take the characters from the first string to the result.

Given two strings s1 and s2, return the result of the special merge function you are implementing.

Example

For s1 = "dce" and s2 = "cccbd", the output should be
mergeStrings(s1, s2) = "dcecccbd".
All symbols from s1 goes first, because all of them have only 1 occurrence in s1 and c has 3 occurrences in s2.

For s1 = "super" and s2 = "tower", the output should be
mergeStrings(s1, s2) = "stouperwer".
Because in both strings all symbols occur only 1 time, strings are merged as usual. You can find explanation for this example on the image in the description.

Input/Output

[execution time limit] 4 seconds (py3)

[input] string s1

A string consisting only of lowercase English letters.

Guaranteed constraints:
1 ≤ s1.length ≤ 104.

[input] string s2

A string consisting only of lowercase English letters.

Guaranteed constraints:
1 ≤ s2.length ≤ 104.

[output] string

The string that results by merging s1 and s2 using your special merge function.
"""

s1 = "super"
s2 = "tower"

s1 = "dce"
s2 = "cccbd"

s1 = "kkihj"
s2 = "jbsmfoftph"
expected = "jbsmfoftphkkihj"

s1 = "ougtaleegvrabhugzyx"
s2 = "wvieaqgaegbxg"
output = "owvieaqugaegbxggtaleegvrabhugzyx"
expected = "owvieaqugtaleegvrabhugzyxgaegbxg"

# fully passing
def mergeStrings(s1, s2):
    # variable to hold the result
    result = ''
    # variable to hold the current index of the longer of the two strings
    s2_index = 0
    # variable to hold the current index of the shorter of the two strings
    s1_index = 0
    # variables for the s2 string and the s1 string
    # s2 = ''
    # s1 = ''
    # logic to find the s2 and s1 strings from the given strings
    # if len(s1) > len(s2):
    #     s2 = s1
    #     s1 = s2
    # else:
    #     s2 = s2
    #     s1 = s1
    # hash maps for each string to hold the number of occurrences of each
    # letter
    s1_map = {}
    s2_map = {}
    # logic creating the hash maps
    for letter in s1:
        if letter not in s1_map:
            s1_map[letter] = 0
        s1_map[letter] += 1

    for letter in s2:
        if letter not in s2_map:
            s2_map[letter] = 0
        s2_map[letter] += 1
    # print('s1 map:', s1_map)
    # print('s2 map:', s2_map)
    # while the s1 string current index is less than the s1 string length
    # and the s2 string index is shorter than the s2 string length
    # (keeps us from index out of bounds error)
    while s1_index < len(s1) and s2_index < len(s2):
        # print('s1', s1)
        # print('s2', s2)
        # print('result:', result)
        # print('compare', 's1', s1[s1_index], 's2', s2[s2_index])
        # my print statements for debugging
        # print('i', i)
        # print('s2_index', s2_index)
        # print(chr(max(ord(s1[i]), ord(s2[s2_index]))))
        # if the letter count for the s1 string letter at current s1
        # string index is less than the letter count for the s2 string
        # letter at current s2 string index
        if s1_map[s1[s1_index]] < s2_map[s2[s2_index]]:

            # print('s1 i', s1[i])
            # print('count', s1_map[s1[i]])
            # print('s2 i', s2[s2_index])
            # print('count', s2_map[s2[s2_index]])
            # add the letter from the s1 string at the current index to
            # the result
            result += s1[s1_index]
            # increment the s1 string current index
            s1_index += 1
        # if the letter count for the s1 string letter at the current
        # index is greater than the letter count for the s2 string letter
        # at current s2 string index
        elif s1_map[s1[s1_index]] > s2_map[s2[s2_index]]:
            # add the letter from the s2 string at the current index to the
            # result
            result += s2[s2_index]
            # increment the s2 string current index
            s2_index += 1
        # if both letter have the same number of occurrences in their
        # respective strings
        else:
            if ord(s1[s1_index]) == ord(s2[s2_index]):
                result += s1[s1_index]
                s1_index += 1
            else:
                # add the letter that comes first sequentially
                result += chr(min(ord(s1[s1_index]), ord(s2[s2_index])))
                # if the s2 string letter was added
                if ord(s1[s1_index]) > ord(s2[s2_index]):
                    # increment the s2 string current index
                    s2_index += 1
                # else if the s1 string letter was added
                else:
                    # increment the s1 string current index
                    s1_index += 1
    # if the s1 string index is at the end of the string
    # we have added all the letters in that string and can just add the rest
    # of the letters in the s2 string to the result in the order they are in
    if s1_index == len(s1):
        # add rest of the s2 string from the current index to the end of
        # the string
        result += s2[s2_index:]
    # if the s2 string index is at the end of the string
    # we have added all the letters in that string and can just add the rest
    # of the letters in the s1 string to the result in the order they are in
    if s2_index >= len(s2):
        # add rest of the s1 string from the current index to the end of
        # the string
        result += s1[s1_index:]
    # return the result
    return result

# print('merge strings', mergeStrings(s1, s2))

"""
Concatenations Sum
------------------
Given an array of positive integers a, your task is to calculate the sum of every possible a[i] ∘ a[j], where a[i] ∘ a[j] is the concatenation of the string representations of a[i] and a[j] respectively.

Example

For a = [10, 2], the output should be concatenationsSum(a) = 1344.

a[0] ∘ a[0] = 10 ∘ 10 = 1010,
a[0] ∘ a[1] = 10 ∘ 2 = 102,
a[1] ∘ a[0] = 2 ∘ 10 = 210,
a[1] ∘ a[1] = 2 ∘ 2 = 22.
So the sum is equal to 1010 + 102 + 210 + 22 = 1344.

For a = [8], the output should be concatenationsSum(a) = 88.

There is only one number in a, and a[0] ∘ a[0] = 8 ∘ 8 = 88, so the answer is 88.

For a = [1, 2, 3], the output should be concatenationsSum(a) = 198.

a[0] ∘ a[0] = 1 ∘ 1 = 11,
a[0] ∘ a[1] = 1 ∘ 2 = 12,
a[0] ∘ a[2] = 1 ∘ 3 = 13,
a[1] ∘ a[0] = 2 ∘ 1 = 21,
a[1] ∘ a[1] = 2 ∘ 2 = 22,
a[1] ∘ a[2] = 2 ∘ 3 = 23,
a[2] ∘ a[0] = 3 ∘ 1 = 31,
a[2] ∘ a[1] = 3 ∘ 2 = 32,
a[2] ∘ a[2] = 3 ∘ 3 = 33.
The total result is 11 + 12 + 13 + 21 + 22 + 23 + 31 + 32 + 33 = 198.
"""

a = [8]

a = [1, 2, 3]

# a = [0, 0]

# needs to be optimized to pass all tests currently 250/300
# def concatenationsSum(a):
#     # variable for the result of the integer addition of concatenated strings
#     result = 0
#     # variables for the current index and the index of the number being added
#     front_index = 0
#     back_index = 0
#     # iterate the array
#     while front_index < len(a):
#         # if the number being added is the last one
#         if back_index == len(a) - 1:
#             # do the concatenation
#             result += int(str(a[front_index]) + str(a[back_index]))
#             # increment the current index
#             front_index += 1
#             # reset the sum index to 0
#             back_index = 0
#         # otherwise just do the concatenation and increase the index of
#         # number being added
#         else:
#             result += int(str(a[front_index]) + str(a[back_index]))
#             back_index += 1
#
#     # return the result
#     return result
def concatenationsSum(a):
    # UPER
    # Understand:
    # we're going to need to return an int after concatenating strings --> int(str() ...)

    # Need a sum: start it at 0
    concatentations_sum = 0
    # "every possible a[i] and a[j]" --> 2 indices, or 2 nested for loops
        # iterate over the array
        # for each index front_index:
    for front_index in range(len(a)):
        # front_index is the index of the first element (front of the concatenation)
        # visit every other index to hit the possible combinations
        # for each front_index, we want to visit _every_ j / back_index (even if j == i, or j < i)
        for back_index in range(len(a)):
            # back_index is the index of the second / back of the concatenation
            # how do we concatenate?
            # we need to convert to strings using str
            # # str(a[front_index]), str(a[back_index])
            # front_string = str(a[front_index])
            # back_string = str(a[back_index])
            # concatenate the strings using +
            concatenated_string = str(front_string) + str(back_string)
            # convert back to int using int()
            concatenated_int = int(concatenated_string)
            # add the result of ^ to sum
            concatentations_sum += concatenated_int

    return concatentations_sum
    #

test_cases = [
    ([10, 2], 1344),
    ([8], 88),
    ([1, 2, 3], 198),
]

for input, output in test_cases:
    print(f"For input: {input} expecting {output}")
    actual_output = concatenationsSum(input)
    print(f"Actual output: {actual_output}")
    print("----")

# print(concatenationsSum(a))

"""
HashMap
You've created a new programming language, and now you've decided to add hashmap support to it. Actually you are quite disappointed that in common programming languages it's impossible to add a number to all hashmap keys, or all its values. So you've decided to take matters into your own hands and implement your own hashmap in your new language that has the following operations:

insert x y - insert an object with key x and value y.
get x - return the value of an object with key x.
addToKey x - add x to all keys in map.
addToValue y - add y to all values in map.
To test out your new hashmap, you have a list of queries in the form of two arrays: queryTypes contains the names of the methods to be called (eg: insert, get, etc), and queries contains the arguments for those methods (the x and y values).

Your task is to implement this hashmap, apply the given queries, and to find the sum of all the results for get operations.

Example

For queryType = ["insert", "insert", "addToValue", "addToKey", "get"] and query = [[1, 2], [2, 3], [2], [1], [3]], the output should be hashMap(queryType, query) = 5.

The hashmap looks like this after each query:

1 query: {1: 2}
2 query: {1: 2, 2: 3}
3 query: {1: 4, 2: 5}
4 query: {2: 4, 3: 5}
5 query: answer is 5
The result of the last get query for 3 is 5 in the resulting hashmap.

For queryType = ["insert", "addToValue", "get", "insert", "addToKey", "addToValue", "get"] and query = [[1, 2], [2], [1], [2, 3], [1], [-1], [3]], the output should be hashMap(queryType, query) = 6.

The hashmap looks like this after each query:

1 query: {1: 2}
2 query: {1: 4}
3 query: answer is 4
4 query: {1: 4, 2: 3}
5 query: {2: 4, 3: 3}
6 query: {2: 3, 3: 2}
7 query: answer is 2
The sum of the results for all the get queries is equal to 4 + 2 = 6.

Input/Output

[execution time limit] 4 seconds (py3)

[input] array.string queryType

Array of query types. It is guaranteed that each queryType[i] is either "addToKey", "addToValue", "get", or "insert".

Guaranteed constraints:
1 ≤ queryType.length ≤ 105.

[input] array.array.integer query

Array of queries, where each query is represented either by two numbers for insert query or by one number for other queries. It is guaranteed that during all queries all keys and values are in the range [-109, 109].

Guaranteed constraints:
query.length = queryType.length,
1 ≤ query[i].length ≤ 2.

[output] integer64

The sum of the results for all get queries.
"""

queryType = ["insert", "addToValue", "get", "insert", "addToKey", "addToValue",
             "get"]
query = [[1, 2], [2], [1], [2, 3], [1], [-1], [3]]

queryType = ["insert", "insert", "addToValue", "addToKey", "get"]
query = [[1, 2], [2, 3], [2], [1], [3]]

# this is not currently passing all tests but most
def hashMap(queryType, query):
    # we want to build on top of pythons built in {}
    # we need our hashmap {}
    hash_map = {}
    # make helper functions for the different queries (get, insert, addToValue, addToKey)
    sum_of_gets = 0
    # iterate through queryType and query and call the corresponding helper functions
    for i in range(len(queryType)):
        method_name = queryType[i]
        parameters = query[i]
        # print(method_name, parameters)
        if method_name == "insert":
            hash_map = handle_insert(hash_map, parameters)
        elif method_name == "get":
            value = handle_get(hash_map, parameters)
            sum_of_gets += value
        elif method_name == "addToKey":
            hash_map = handle_add_to_key(hash_map, parameters)
        elif method_name == "addToValue":
            hash_map = handle_add_to_value(hash_map, parameters)

    return sum_of_gets
# keep track of the sum of get queries

def handle_insert(hash_map, parameters):
    key = parameters[0]
    value = parameters[1]
    hash_map[key] = value
    return hash_map

def handle_get(hash_map, parameters):
    key = parameters[0]
    return hash_map[key]

def handle_add_to_key(hash_map, parameters):
    offset = parameters[0]
    # add `offset` to every key in hash_map
    # safer to create a new dictionary
    new_hash_map = {}
    # iterate through the keys and values in the old dictionary
    for key, value in hash_map.items():
        # add `offset` to the key and put it into the new dictionary
        new_key = key + offset
        new_hash_map[new_key] = value
    return new_hash_map

def handle_add_to_value(hash_map, parameters):
    offset = parameters[0]
    # we want to add offset to every value in hash_map
    for key, value in hash_map.items():
        new_value = value + offset
        hash_map[key] = new_value
    return hash_map

test_cases = [
    {"queryType": ["insert", "insert", "addToValue", "addToKey", "get"],
     "query": [[1, 2], [2, 3], [2], [1], [3]],
     "expected_output": 5},
    {"queryType": ["insert", "addToValue", "get", "insert", "addToKey",
                   "addToValue", "get"],
     "query": [[1, 2], [2], [1], [2, 3], [1], [-1], [3]],
     "expected_output": 6},
    {"queryType": ["addToKey", "addToKey", "insert", "addToValue", "addToValue",
                   "get", "addToKey", "insert",
                   "addToKey", "addToValue"],
     "query": [[-3], [-1], [0, -3], [3], [-1], [0], [-1], [-4, -5], [-1], [-4]],
     "expected_output": -1},
    {"queryType": ["insert", "insert", "addToKey", "addToKey", "addToKey",
                   "insert", "addToValue", "addToKey",
                   "addToKey", "get"],
     "query": [[-5, -2], [2, 4], [-1], [-3], [1], [3, -2], [-4], [-2], [2],
               [-8]],
     "expected_output": -6},
    {"queryType": ["insert", "get", "insert", "addToValue", "addToValue",
                   "addToValue", "insert", "addToKey", "get",
                   "insert"],
     "query": [[2, 1], [2], [1, 3], [-1], [0], [3], [4, -5], [3], [4], [1, 1]],
     "expected_output": 6},
    {"queryType": ["addToValue", "addToValue", "insert", "get", "addToKey",
                   "insert", "insert", "insert", "addToValue",
                   "addToKey"],
     "query": [[-5], [3], [3, -3], [3], [0], [-4, 2], [0, -3], [-2, 4], [2],
               [2]],
     "expected_output": -3},
    {"queryType": ["addToKey", "addToKey", "insert", "addToKey", "addToValue",
                   "addToKey", "addToValue", "insert", "get",
                   "insert"],
     "query": [[-1], [-3], [4, 3], [2], [2], [-2], [0], [-5, 3], [-5], [3, -4]],
     "expected_output": 3},
    {"queryType": ["insert", "insert", "insert", "get", "insert", "insert",
                   "insert", "addToKey", "insert", "insert"],
     "query": [[3, -4], [-4, 3], [4, -3], [4], [-5, 0], [-2, -5], [2, 2], [1],
               [-5, -2], [1, 3]],
     "expected_output": -3},
    {"queryType": ["addToValue", "addToKey", "addToKey", "insert", "addToValue",
                   "addToValue", "insert", "get", "get", "insert"],
     "query": [[-2], [-3], [0], [-3, 1], [-2], [-4], [2, -4], [2], [2],
               [3, -1]],
     "expected_output": -8}
]

for test_case in test_cases:
    query_type = test_case['queryType']
    query = test_case['query']
    print(
        f"Input:\nqueryType: {query_type}\nquery: {query}\nexpected_output: {test_case['expected_output']}")
    actual_output = hashMap(query_type, query)
    print(f"Actual output: {actual_output}")
    print("-----")
"""
Mean Groups
-----------
You are given an array of arrays a. Your task is to group the arrays a[i] by their mean values, so that arrays with equal mean values are in the same group, and arrays with different mean values are in different groups.

Each group should contain a set of indices (i, j, etc), such that the corresponding arrays (a[i], a[j], etc) all have the same mean. Return the set of groups as an array of arrays, where the indices within each group are sorted in ascending order, and the groups are sorted in ascending order of their minimum element.

Example

For

a = [[3, 3, 4, 2],
     [4, 4],
     [4, 0, 3, 3],
     [2, 3],
     [3, 3, 3]]
the output should be

meanGroups(a) = [[0, 4],
                 [1],
                 [2, 3]]
mean(a[0]) = (3 + 3 + 4 + 2) / 4 = 3;
mean(a[1]) = (4 + 4) / 2 = 4;
mean(a[2]) = (4 + 0 + 3 + 3) / 4 = 2.5;
mean(a[3]) = (2 + 3) / 2 = 2.5;
mean(a[4]) = (3 + 3 + 3) / 3 = 3.
There are three groups of means: those with mean 2.5, 3, and 4. And they form the following groups:

Arrays with indices 0 and 4 form a group with mean 3;
Array with index 1 forms a group with mean 4;
Arrays with indices 2 and 3 form a group with mean 2.5.
Note that neither

meanGroups(a) = [[0, 4],
                 [2, 3],
                 [1]]
nor

meanGroups(a) = [[0, 4],
                 [1],
                 [3, 2]]
will be considered as a correct answer:

In the first case, the minimal element in the array at index 2 is 1, and it is less then the minimal element in the array at index 1, which is 2.
In the second case, the array at index 2 is not sorted in ascending order.
For

a = [[-5, 2, 3],
     [0, 0],
     [0],
     [-100, 100]]
the output should be

meanGroups(a) = [[0, 1, 2, 3]]
The mean values of all of the arrays are 0, so all of them are in the same group.
"""
a = [[0, 4],
     [2, 3],
     [1]]
a = [[3, 3, 4, 2],
     [4, 4],
     [4, 0, 3, 3],
     [2, 3],
     [3, 3, 3]]

# passing all tests
def meanGroups(a):
    # create dict to hold mean and arrays w that mean
    means = {}
    # iterate outer array
    for i in range(len(a)):
        # get the mean for each inner array
        sum = 0
        for num in a[i]:
            sum += num
        mean = sum / len(a[i])
        # hold array and mean in dictionary
        if mean not in means:
            means[mean] = []
        means[mean].append(i)
    # return the set of each unique mean with first occurring inner array listed first
    result = []
    for mean in means:
        result.append(means[mean])
    return result

# print(meanGroups(a))

```

gha_license_id: MIT


text:
### Description

This problem was asked by Google.

Suppose we represent our file system by a string in the following manner:

The string `"dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext"` represents:

```
dir
    subdir1
    subdir2
        file.ext
```

The directory `dir` contains an empty sub-directory `subdir1` and a sub-directory `subdir2` containing a file `file.ext`.

The string `"dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"` represents:

```
dir
    subdir1
        file1.ext
        subsubdir1
    subdir2
        subsubdir2
            file2.ext
```

The directory `dir` contains two sub-directories `subdir1` and `subdir2`. `subdir1` contains a file `file1.ext` and an empty second-level sub-directory `subsubdir1`. `subdir2` contains a second-level sub-directory `subsubdir2` containing a file `file2.ext`.

We are interested in finding the longest (number of characters) absolute path to a file within our file system. For example, in the second example above, the longest absolute path is `"dir/subdir2/subsubdir2/file2.ext"`, and its length is 32 (not including the double quotes).

Given a string representing the file system in the above format, return the length of the longest absolute path to a file in the abstracted file system. If there is no file in the system, return 0.

Note:

The name of a file contains at least a period and an extension.

The name of a directory or sub-directory will not contain a period.

### Solution

```swift
struct FileSystem {
    var root: Item? = nil

    init() {
        self.root = nil
    }

    mutating func buildFileSystemFromString(_ string: String) {
        var rootVal = ""
        var string = string
            .replacingOccurrences(of: "\n", with: "\\n")
            .replacingOccurrences(of: "\t", with: "\\t")

        print(string)

        if string.isEmpty {
            root = Item(parent: nil, name: "", level: 1)
            return
        }

        while string.first! != "\\" {
            rootVal += String(string.first!)
            string = String(string.dropFirst())

            if string.isEmpty {
                root = Item(parent: nil, name: rootVal, level: 1)
                return
            }
        }

        root = Item(parent: nil, name: rootVal, level: 1)
        root!.buildChildren(withString: string)
    }

    func longestPath() -> String {

        if let root = root {
            return root.longestPath(true)
        }

        return ""
    }
}

class Item {
    var parent: Item? = nil
    var name: String
    var level: Int
    var children: [Item] = []

    init(parent: Item?, name: String, level: Int) {
        self.parent = parent
        self.name = name
        self.level = level
    }

    func buildChildren(withString string: String) {
        var string = string
        var previous = self

        if string.isEmpty {
            return
        }

        while !string.isEmpty {
            if String(string.prefix(2 + 2 * previous.level)) != "\\n\(String(repeating: "\\t", count: previous.level))" {

                if let parent = previous.parent {
                    previous = parent
                    continue
                } else {
                    fatalError("could not identify parent")
                }
            } else {
                string = String(string.dropFirst(2 + 2 * previous.level))

                var rest = string.split(separator: "\\", maxSplits: 1, omittingEmptySubsequences: true)

                let item = Item(parent: previous, name: String(rest[0]), level: previous.level + 1)
                previous.children.append(item)
                previous = item

                string = String(string.dropFirst(rest[0].count))
            }
        }
    }

    func longestPath(_ isRoot: Bool) -> String {
        if !children.isEmpty {
            var possibilities: [String] = []
            for child in children {
                possibilities.append("\((isRoot ? "" : "/"))\(name)\(child.longestPath(false))")
            }

            possibilities.sort{ $0.count > $1.count }
            return possibilities.first!
        }

        return "\((isRoot ? "" : "/"))\(name)"
    }
}
```

#### Tests

```swift
class Problem_17Tests: XCTestCase {

    func testExample() {
        let input = "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext"
        var fileSystem = FileSystem()
        fileSystem.buildFileSystemFromString(input)

        XCTAssert(fileSystem.longestPath() == "dir/subdir2/file.ext")
    }

    func testExample2() {
        let input = "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
        var fileSystem = FileSystem()
        fileSystem.buildFileSystemFromString(input)

        XCTAssert(fileSystem.longestPath() == "dir/subdir2/subsubdir2/file2.ext")
    }

}
```

repository: Krisloveless/daily-coding-challenges

path: /swift/Problem 17/README.md

repo_name: Krisloveless/daily-coding-challenges


text:
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fionic-team%2Fionic-storage%2Fbadge%3Fref%3Dmain&style=flat)](https://actions-badge.atrox.dev/ionic-team/ionic-storage/goto?ref=main)

# Ionic Storage

A simple key-value Storage module for Ionic apps. This utility uses the best storage engine available on the platform without having to interact with it directly (some configuration required, see docs below).

As of 3.x, this library now supports any JavaScript project (old versions only supported Angular), and Angular-specific functionality has been moved to a new `@ionic/storage-angular` package.

Out of the box, Ionic Storage will use `IndexedDB` and `localstorage` where available. To use SQLite for native storage, see the [SQLite Installation](#sqlite-installation) instructions.

For teams building security sensitive applications requiring encryption, 3.x now supports encryption through Ionic Secure Storage, see [Encryption Support](#encryption-support) for instructions on using it.

## Installation

```shell
npm install @ionic/storage
```

If using Angular, install the `@ionic/storage-angular` library instead:

```shell
npm install @ionic/storage-angular
```

If you'd like to use SQLite as a storage engine, see the [SQLite Installation](#sqlite-installation) instructions.

## Usage

### With React, Vue, Vanilla JavaScript

```typescript
import { Storage } from '@ionic/storage';

const store = new Storage();
await store.create();
```

See the [API](#api) section below for an overview of the supported methods on the storage instance.

### With Angular

Usage in Angular using Services and Dependency Injection requires importing the `IonicStorageModule` and then injecting the `Storage` class.

First, edit your NgModule declaration in `src/app/app.module.ts` or in the module for the component you'll use the storage library in, and add  `IonicStorageModule` as an import:

```typescript
import { IonicStorageModule } from '@ionic/storage-angular';

@NgModule({
  imports: [
    IonicStorageModule.forRoot()
  ]
})
export class AppModule { }
```

Next, inject `Storage` into a component. Note: this approach is meant for usage in a single component (such as `AppComponent`). In this case, `create()` should only be called once. For use in multiple components, we recommend creating a service (see next example).

```typescript
import { Component } from '@angular/core';
import { Storage } from '@ionic/storage-angular';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html'
})
export class AppComponent {

  constructor(private storage: Storage) {
  }

  async ngOnInit() {
    // If using a custom driver:
    // await this.storage.defineDriver(MyCustomDriver)
    await this.storage.create();
  }
}
```

For more sophisticated usage, an Angular Service should be created to manage all database operations in your app and constrain all configuration and database initialization to a single location. When doing this, don't forget to register this service in a `providers` array in your `NgModule` if not using `providedIn: 'root'`, and ensure that the `IonicStorageModule` has been initialized in that `NgModule` as shown above. Here's an example of what this service might look like:

```typescript
import { Injectable } from '@angular/core';

import { Storage } from '@ionic/storage-angular';

@Injectable({
  providedIn: 'root'
})
export class StorageService {
  private _storage: Storage | null = null;

  constructor(private storage: Storage) {
    this.init();
  }

  async init() {
    // If using, define drivers here: await this.storage.defineDriver(/*...*/);
    const storage = await this.storage.create();
    this._storage = storage;
  }

  // Create and expose methods that users of this service can
  // call, for example:
  public set(key: string, value: any) {
    this._storage?.set(key, value);
  }
}
```

Then, inject the `StorageService` into your pages and other components that need to interface with the Storage engine.

## API

The Storage API provides ways to set, get, and remove a value associated with a key, along with clearing the database, accessing the stored keys and their quantity, and enumerating the values in the database.

To set an item, use `set(key, value)`:

```javascript
await storage.set('name', 'Mr. Ionitron');
```

To get the item back, use `get(name)`:

```javascript
const name = await storage.get('name');
```

To remove an item:

```javascript
await storage.remove(key);
```

To clear all items:

```javascript
await storage.clear();
```

To get all keys stored:

```javascript
await storage.keys()
```

To get the quantity of key/value pairs stored:

```javascript
await storage.length()
```

To enumerate the stored key/value pairs:
```javascript
storage.forEach((key, value, index) => {
});
```

To enable encryption when using the [Ionic Secure Storage](https://ionic.io/docs/secure-storage) driver:

```javascript
storage.setEncryptionKey('mykey');
```

See [Encryption Support](#encryption-support) below for more information.

## Configuration

The Storage engine can be configured both with specific storage engine priorities, or custom configuration
options to pass to localForage. See the localForage config docs for possible options: https://github.com/localForage/localForage#configuration

### In React/Vue/Vanilla JavaScript configuration

Pass configuration options in the `Storage` constructor:

```typescript
const storage = new Storage({
  name: '__mydb',
  driverOrder: [Drivers.IndexedDB, Drivers.LocalStorage]
});
```

### Angular configuration

```typescript
import { Drivers, Storage } from '@ionic/storage';
import { IonicStorageModule } from '@ionic/storage-angular';

@NgModule({
  //...
  imports: [
   IonicStorageModule.forRoot({
     name: '__mydb',
     driverOrder: [Drivers.IndexedDB, Drivers.LocalStorage]
   })
 ],
 //...
})
export class AppModule { }
```

## SQLite Installation

The 2.x version of this plugin hard coded in the [localForage-cordovaSQLiteDriver](https://github.com/thgreasi/localForage-cordovaSQLiteDriver). This driver has been removed from the core code as of 3.x to provide more options for SQLite storage engines.

In 3.x there are at least two good options for SQLite usage:

1) For non-enterprise apps, the old `localForage-cordovaSQLiteDriver` is still a fine choice but does not support encryption and is community maintained. See below for installation instructions.

2) For enterprise apps, we strongly recommend [Ionic Secure Storage](https://ionic.io/docs/secure-storage) which is an enterprise SQLite engine with full encryption support out of the box and is fully supported and maintained by the Ionic team.

### Using `localForage-CordovaSQLiteDriver`

#### Installation

```
# If using Cordova, install the plugin using
ionic cordova plugin add cordova-sqlite-storage
# If using Capacitor, install the plugin using
npm install cordova-sqlite-storage

# Then, install the npm library
npm install localforage-cordovasqlitedriver
```

#### Adding driver to configuration

For non-Angular projects, pass the `CordovaSQLiteDriver._driver` to the `driverOrder` config option:

```typescript
import CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';

const store = new Storage({
  driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB, Drivers.LocalStorage]
});
```

In Angular, pass the same configuration when importing the `IonicStorageModule` in your page or app `NgModule`:

```typescript
import CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';

@NgModule({
  imports: [
    // ...,
    IonicStorageModule.forRoot({
      driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB]
    })
  ],
  // ...
})
export class MyPageModule { }
```

#### Registering Driver

Finally, to register the driver, run `defineDriver()` on the storage instance to register the driver, making sure to call this before any data operations:

```typescript
import CordovaSQLiteDriver from 'localforage-cordovasqlitedriver'

const store = new Storage({
  driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB, Drivers.LocalStorage]
});

await this.storage.defineDriver(CordovaSQLiteDriver);
```

### Using Ionic Secure Storage

[Ionic Secure Storage](https://ionic.io/docs/secure-storage) is an enterprise-ready, high-performance data store with SQL or key/value support and offering 256-bit AES encryption. When used in tandem with [Ionic Identity Vault](https://ionic.io/products/identity-vault), developers can securely manage encryption keys and build fully offline-enabled apps with biometric authentication using the fullest security capabilities available on modern mobile devices and operating systems.

Ionic Secure Storage is an enterprise product and requires an active enterprise subscription or trial. To learn more and request a demo, visit the [Secure Storage product page](https://ionic.io/products/offline-storage).

#### Installation

Follow the [official installation guide](https://ionic.io/docs/secure-storage) to set up and install `@ionic-enterprise/secure-storage`.

### Usage

#### With React, Vue, Vanilla JavaScript

```typescript
import { Drivers } from '@ionic/storage';
import IonicSecureStorageDriver from '@ionic-enterprise/secure-storage/driver';

const store = new Storage({
  driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
});

await store.defineDriver(IonicSecureStorageDriver);
```

#### With Angular

Usage in Angular using Services and Dependency Injection requires importing the `IonicStorageModule` and then injecting the `Storage` class.

First, edit your NgModule declaration in `src/app/app.module.ts` or in the module for the page you'll use the storage library in, and add  `IonicStorageModule` as an import:

```typescript
import { Drivers } from '@ionic/storage';
import { IonicStorageModule } from '@ionic/storage-angular';

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    IonicStorageModule.forRoot({
      driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
    })
  ],
  // ...
})
export class AppModule { }
```

Then register the driver in your component:

```typescript

  async ngOnInit() {
    await this.storage.defineDriver(IonicSecureStorageDriver);
    await this.storage.create();
  }
```

Then follow the instructions below to configure encryption support:

## Encryption Support

3.x adds a new method `setEncryptionKey` to support encryption when using with [Ionic Secure Storage](https://ionic.io/docs/secure-storage) (see instructions above).

This is an enterprise feature for teams with high security needs and provides the ability to use the simple `@ionic/storage` key-value API, or drop down to SQL for more powerful query and relational data support, all with full encryption. When paired with [Ionic Identity Vault](https://ionic.io/docs/identity-vault) teams can safely manage encryption keys and provide biometric authentication when on or offline.

Visit the [Secure Storage](https://ionic.io/products/secure-storage) product page to learn more about Secure Storage and inquire about a trial.

### Encrypting an Existing SQLite Database

A one-time migration must be performed to move to a new, encrypted database powered by [Ionic Secure Storage](https://ionic.io/docs/secure-storage).

First, follow the installation steps above to update to Ionic Storage v3, install the `localForage-CordovaSQLiteDriver` SQLite driver, and integrate Ionic Secure Storage.

Next, remove the database name and drivers, if used, from `app.module.ts`:

```typescript
@NgModule({
  imports: [
    // ...,
    IonicStorageModule.forRoot()
  ],
  // ...
})
export class MyPageModule { }
```

Finally, in the service class, create a one time migration function that migrates data to an encrypted database. Execute this function on app load.

```typescript
async migrateDatabase() {
  const origStore = new Storage({
    name: 'originalDB', // the original database name
    driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB, Drivers.LocalStorage]
  });
  await origStore.defineDriver(CordovaSQLiteDriver);

  const newStore = new Storage({
    name: 'encryptedDB', // pick a new db name for the encrypted db
    driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
  });
  await newStore.defineDriver(IonicSecureStorageDriver);
  newStore.setEncryptionKey('mykey');

  if (await origStore.length() > 0) {
    // copy existing data into new, encrypted format
    await origStore.forEach((key, value, index) => {
      newStore.set(key, value);
    });

    // remove old data
    await origStore.clear();
  }

  this._storage = newStore;
}
```

repository: ionic-team/ionic-storage

branch_name: refs/heads/main

gha_language: TypeScript

repo_name: ionic-team/ionic-storage


text:
# 简介

笔者在LeetCode上的算法题解，使用kotlin语言，持续更新中。

力扣(LeetCode)中国官网：[https://leetcode-cn.com/](https://leetcode-cn.com/)

# 题解格式

#### 一、题目（带题目链接）

```kotlin
// kotlin语言的解题代码
// xxxxxxx
```

####  二、解题思路

解题思路的文字描述：xxxxxxx

# Bug反馈

如果您有任何问题或反馈，请提交到[Github Issues](https://github.com/wkxjc/Kotlin-leetcode/issues).

# LICENSE

    Copyright (c) 2019-present, Alpinist Wang Contributors.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

repository: wkxjc/kotlin-leetcode

repo_name: wkxjc/kotlin-leetcode


text:
[//000000001]: # (clay \- Clay Framework)
[//000000002]: # (Generated from file 'clay\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright © 2018 Sean Woods<EMAIL_ADDRESS>[//000000004]: # (clay\(n\) 0\.8\.6 tcllib "Clay Framework")

 [ Main Table Of Contents | Table Of Contents | Keyword Index | Categories | Modules | Applications ]

# NAME

clay \- A minimalist framework for large scale OO Projects

# Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

      - [Structured Data](#subsection1)

      - [Clay Dialect](#subsection2)

      - [Method Delegation](#subsection3)

  - [Commands](#section2)

  - [Classes](#section3)

      - [Class clay::class](#subsection4)

      - [Class clay::object](#subsection5)

  - [AUTHORS](#section4)

  - [Bugs, Ideas, Feedback](#section5)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# SYNOPSIS

package require Tcl 8\.6
package require uuid
package require oo::dialect

[proc __clay::PROC__ *name* *arglist* *body* ?*ninja* ____?](#1)
[proc __clay::\_ancestors__ *resultvar* *class*](#2)
[proc __clay::ancestors__ ?*args*?](#3)
[proc __clay::args\_to\_dict__ ?*args*?](#4)
[proc __clay::args\_to\_options__ ?*args*?](#5)
[proc __clay::dynamic\_arguments__ *ensemble* *method* *arglist* ?*args*?](#6)
[proc __clay::dynamic\_wrongargs\_message__ *arglist*](#7)
[proc __clay::is\_dict__ *d*](#8)
[proc __clay::is\_null__ *value*](#9)
[proc __clay::leaf__ ?*args*?](#10)
[proc __clay::K__ *a* *b*](#11)
[proc __clay::noop__ ?*args*?](#12)
[proc __clay::cleanup__](#13)
[proc __clay::object\_create__ *objname* ?*class* ____?](#14)
[proc __clay::object\_rename__ *object* *newname*](#15)
[proc __clay::object\_destroy__ ?*args*?](#16)
[proc __clay::path__ ?*args*?](#17)
[proc __clay::putb__ ?*map*? *text*](#18)
[proc __clay::script\_path__](#19)
[proc __clay::NSNormalize__ *qualname*](#20)
[proc __clay::uuid\_generate__ ?*args*?](#21)
[proc __clay::uuid::generate\_tcl\_machinfo__](#22)
[proc __clay::uuid::tostring__ *uuid*](#23)
[proc __clay::uuid::fromstring__ *uuid*](#24)
[proc __clay::uuid::equal__ *left* *right*](#25)
[proc __clay::uuid__ *cmd* ?*args*?](#26)
[proc __clay::tree::sanitize__ *dict*](#27)
[proc __clay::tree::\_sanitizeb__ *path* *varname* *dict*](#28)
[proc __clay::tree::storage__ *rawpath*](#29)
[proc __clay::tree::dictset__ *varname* ?*args*?](#30)
[proc __clay::tree::dictmerge__ *varname* ?*args*?](#31)
[proc __clay::tree::merge__ ?*args*?](#32)
[proc __dictargs::proc__ *name* *argspec* *body*](#33)
[proc __dictargs::method__ *name* *argspec* *body*](#34)
[proc __clay::dialect::Push__ *class*](#35)
[proc __clay::dialect::Peek__](#36)
[proc __clay::dialect::Pop__](#37)
[proc __clay::dialect::create__ *name* ?*parent* ____?](#38)
[proc __clay::dialect::NSNormalize__ *namespace* *qualname*](#39)
[proc __clay::dialect::DefineThunk__ *target* ?*args*?](#40)
[proc __clay::dialect::Canonical__ *namespace* *NSpace* *class*](#41)
[proc __clay::dialect::Define__ *namespace* *class* ?*args*?](#42)
[proc __clay::dialect::Aliases__ *namespace* ?*args*?](#43)
[proc __clay::dialect::SuperClass__ *namespace* ?*args*?](#44)
[proc __clay::dynamic\_methods__ *class*](#45)
[proc __clay::dynamic\_methods\_class__ *thisclass*](#46)
[proc __clay::define::Array__ *name* ?*values* ____?](#47)
[proc __clay::define::Delegate__ *name* *info*](#48)
[proc __clay::define::constructor__ *arglist* *rawbody*](#49)
[proc __clay::define::Class\_Method__ *name* *arglist* *body*](#50)
[proc __clay::define::class\_method__ *name* *arglist* *body*](#51)
[proc __clay::define::clay__ ?*args*?](#52)
[proc __clay::define::destructor__ *rawbody*](#53)
[proc __clay::define::Dict__ *name* ?*values* ____?](#54)
[proc __clay::define::Option__ *name* ?*args*?](#55)
[proc __clay::define::Method__ *name* *argstyle* *argspec* *body*](#56)
[proc __clay::define::Option\_Class__ *name* ?*args*?](#57)
[proc __clay::define::Variable__ *name* ?*default* ____?](#58)
[proc __clay::ensemble\_methodbody__ *ensemble* *einfo*](#59)
[proc __clay::define::Ensemble__ *rawmethod* ?*args*?](#60)
[proc __clay::event::cancel__ *self* ?*task* __\*__?](#61)
[proc __clay::event::generate__ *self* *event* ?*args*?](#62)
[proc __clay::event::nextid__](#63)
[proc __clay::event::Notification\_list__ *self* *event* ?*stackvar* ____?](#64)
[proc __clay::event::notify__ *rcpt* *sender* *event* *eventinfo*](#65)
[proc __clay::event::process__ *self* *handle* *script*](#66)
[proc __clay::event::schedule__ *self* *handle* *interval* *script*](#67)
[proc __clay::event::subscribe__ *self* *who* *event*](#68)
[proc __clay::event::unsubscribe__ *self* ?*args*?](#69)
[proc __clay::singleton__ *name* *script*](#70)
[method __clay ancestors__](#71)
[method __clay dump__](#72)
[method __clay find__ *path* ?__path\.\.\.__?](#73)
[method __clay get__ *path* ?__path\.\.\.__?](#74)
[method __clay GET__ *path* ?__path\.\.\.__?](#75)
[method __clay merge__ *dict* ?__dict\.\.\.__?](#76)
[method __clay replace__ *dictionary*](#77)
[method __clay search__ *path* ?__path\.\.\.__?](#78)
[method __clay set__ *path* ?__path\.\.\.__? *value*](#79)
[method __clay ancestors__](#80)
[method __clay cache__ *path* *value*](#81)
[method __clay cget__ *field*](#82)
[method __clay delegate__ ?*stub*? ?*object*?](#83)
[method __clay dump__](#84)
[method __clay ensemble\_map__](#85)
[method __clay eval__ *script*](#86)
[method __clay evolve__](#87)
[method __clay exists__ *path* ?__path\.\.\.__?](#88)
[method __clay flush__](#89)
[method __clay forward__ *method* *object*](#90)
[method __clay get__ *path* ?__path\.\.\.__?](#91)
[method __clay leaf__ *path* ?__path\.\.\.__?](#92)
[method __clay merge__ *dict* ?__dict\.\.\.__?](#93)
[method __clay mixin__ *class* ?__class\.\.\.__?](#94)
[method __clay mixinmap__ ?*stub*? ?*classes*?](#95)
[method __clay provenance__ *path* ?__path\.\.\.__?](#96)
[method __clay replace__ *dictionary*](#97)
[method __clay search__ *path* *valuevar* *isleafvar*](#98)
[method __clay source__ *filename*](#99)
[method __clay set__ *path* ?__path\.\.\.__? *value*](#100)
[method __InitializePublic__](#101)

# DESCRIPTION

Clay introduces a method ensemble to both __oo::class__ and
__oo::object__ called clay\. This ensemble handles all of the high level
interactions within the framework\. Clay stores structured data\. Clan manages
method delegation\. Clay has facilities to manage the complex interactions that
come about with mixins\.

The central concept is that inside of every object and class \(which are actually
objects too\) is a dict called clay\. What is stored in that dict is left to the
imagination\. But because this dict is exposed via a public method, we can share
structured data between object, classes, and mixins\.

## Structured Data

Clay uses a standardized set of method interactions and introspection that TclOO
already provides to perform on\-the\-fly searches\. On\-the\-fly searches mean that
the data is never stale, and we avoid many of the sorts of collisions that would
arise when objects start mixing in other classes during operation\.

The __clay__ methods for both classes and objects have a get and a set
method\. For objects, get will search through the local clay dict\. If the
requested leaf is not found, or the query is for a branch, the system will then
begin to poll the clay methods of all of the class that implements the object,
all of that classes’ ancestors, as well as all of the classes that have been
mixed into this object, and all of their ancestors\.

Intended branches on a tree end with a directory slash \(/\)\. Intended leaves are
left unadorned\. This is a guide for the tool that builds the search results to
know what parts of a dict are intended to be branches and which are intended to
be leaves\. For simple cases, branch marking can be ignored:

    ::oo::class create ::foo { }
    ::foo clay set property/ color blue
    ::foo clay set property/ shape round

    set A [::foo new]
    $A clay get property/
    {color blue shape round}

    $A clay set property/ shape square
    $A clay get property/
    {color blue shape square}

But when you start storing blocks of text, guessing what field is a dict and
what isn’t gets messy:

    ::foo clay set description {A generic thing of designated color and shape}

    $A clay get description
    {A generic thing of designated color and shape}

    Without a convention for discerning branches for leaves what should have been a value can be accidentally parsed as a dictionary, and merged with all of the other values that were never intended to be merge. Here is an example of it all going wrong:
    ::oo::class create ::foo { }
    # Add description as a leaf
    ::foo clay set description  {A generic thing of designated color and shape}
    # Add description as a branch
    ::foo clay set description/  {A generic thing of designated color and shape}

    ::oo::class create ::bar {
      superclass foo
    }
    # Add description as a leaf
    ::bar clay set description  {A drinking establishment of designated color and shape and size}
    # Add description as a branch
    ::bar clay set description/  {A drinking establishment of designated color and shape and size}

    set B [::bar new]
    # As a leaf we get the value verbatim from he nearest ancestor
    $B clay get description
      {A drinking establishment of designated color and shape and size}
    # As a branch we get a recursive merge
    $B clay get description/
    {A drinking establishment of designated color and size thing of}

## Clay Dialect

Clay is built using the oo::dialect module from Tcllib\. oo::dialect allows you
to either add keywords directly to clay, or to create your own metaclass and
keyword set using Clay as a foundation\. For details on the keywords and what
they do, consult the functions in the ::clay::define namespace\.

## Method Delegation

Method Delegation It is sometimes useful to have an external object that can be
invoked as if it were a method of the object\. Clay provides a delegate ensemble
method to perform that delegation, as well as introspect which methods are
delegated in that manner\. All delegated methods are marked with html\-like tag
markings \(< >\) around them\.

    ::clay::define counter {
      Variable counter 0
      method incr {{howmuch 1}} {
        my variable counter
        incr counter $howmuch
      }
      method value {} {
        my variable counter
        return $counter
      }
      method reset {} {
        my variable counter
        set counter 0
      }
    }
    ::clay::define example {
      variable buffer
      constructor {} {
        # Build a counter object
        set obj [namespace current]::counter
        ::counter create $obj
        # Delegate the counter
        my delegate <counter> $obj
      }
      method line {text} {
        my <counter> incr
        append buffer $text
      }
    }

    set A [example new]
    $A line {Who’s line is it anyway?}
    $A <counter> value
    1

# Commands

  - proc __clay::PROC__ *name* *arglist* *body* ?*ninja* ____?

    Because many features in this package may be added as commands to future tcl
    cores, or be provided in binary form by packages, I need a declaritive way
    of saying *Create this command if there isn't one already*\. The *ninja*
    argument is a script to execute if the command is created by this mechanism\.

  - proc __clay::\_ancestors__ *resultvar* *class*

  - proc __clay::ancestors__ ?*args*?

  - proc __clay::args\_to\_dict__ ?*args*?

  - proc __clay::args\_to\_options__ ?*args*?

  - proc __clay::dynamic\_arguments__ *ensemble* *method* *arglist* ?*args*?

  - proc __clay::dynamic\_wrongargs\_message__ *arglist*

  - proc __clay::is\_dict__ *d*

  - proc __clay::is\_null__ *value*

  - proc __clay::leaf__ ?*args*?

  - proc __clay::K__ *a* *b*

  - proc __clay::noop__ ?*args*?

    Perform a noop\. Useful in prototyping for commenting out blocks of code
    without actually having to comment them out\. It also makes a handy default
    for method delegation if a delegate has not been assigned yet\.

  - proc __clay::cleanup__

    Process the queue of objects to be destroyed

  - proc __clay::object\_create__ *objname* ?*class* ____?

  - proc __clay::object\_rename__ *object* *newname*

  - proc __clay::object\_destroy__ ?*args*?

    Mark an objects for destruction on the next cleanup

  - proc __clay::path__ ?*args*?

  - proc __clay::putb__ ?*map*? *text*

    Append a line of text to a variable\. Optionally apply a string mapping\.

  - proc __clay::script\_path__

  - proc __clay::NSNormalize__ *qualname*

  - proc __clay::uuid\_generate__ ?*args*?

  - proc __clay::uuid::generate\_tcl\_machinfo__

  - proc __clay::uuid::tostring__ *uuid*

  - proc __clay::uuid::fromstring__ *uuid*

    Convert a string representation of a uuid into its binary format\.

  - proc __clay::uuid::equal__ *left* *right*

    Compare two uuids for equality\.

  - proc __clay::uuid__ *cmd* ?*args*?

    uuid generate \-> string rep of a new uuid uuid equal uuid1 uuid2

  - proc __clay::tree::sanitize__ *dict*

    Output a dictionary removing any \. entries added by
    __clay::tree::merge__

  - proc __clay::tree::\_sanitizeb__ *path* *varname* *dict*

    Helper function for ::clay::tree::sanitize Formats the string representation
    for a dictionary element within a human readable stream of lines, and
    determines if it needs to call itself with further indentation to express a
    sub\-branch

  - proc __clay::tree::storage__ *rawpath*

    Return the path as a storage path for clay::tree with all branch terminators
    removed\. This command will also break arguments up if they contain /\.

    Example:

    > clay::tree::storage {foo bar baz bang}
    foo bar baz bang
    > clay::tree::storage {foo bar baz bang/}
    foo bar baz bang
    > clay::tree::storage {foo bar baz bang:}
    foo bar baz bang:
    > clay::tree::storage {foo/bar/baz bang:}
    foo bar baz bang:
    > clay::tree::storage {foo/bar/baz/bang}
    foo bar baz bang

  - proc __clay::tree::dictset__ *varname* ?*args*?

    Set an element with a recursive dictionary, marking all branches on the way
    down to the final element\. If the value does not exists in the nested
    dictionary it is added as a leaf\. If the value already exists as a branch
    the value given is merged if the value is a valid dict\. If the incoming
    value is not a valid dict, the value overrides the value stored, and the
    value is treated as a leaf from then on\.

    Example:

    > set r {}
    > ::clay::tree::dictset r option color default Green
    . {} option {. {} color {. {} default Green}}
    > ::clay::tree::dictset r option {Something not dictlike}
    . {} option {Something not dictlike}
    # Note that if the value is not a dict, and you try to force it to be
    # an error with be thrown on the merge
    > ::clay::tree::dictset r option color default Blue
    missing value to go with key

  - proc __clay::tree::dictmerge__ *varname* ?*args*?

    A recursive form of dict merge, intended for modifying variables in place\.

    Example:

    > set mydict {sub/ {sub/ {description {a block of text}}}}
    > ::clay::tree::dictmerge mydict {sub/ {sub/ {field {another block of text}}}}]
    > clay::tree::print $mydict
    sub/ {
      sub/ {
        description {a block of text}
        field {another block of text}
      }
    }

  - proc __clay::tree::merge__ ?*args*?

    A recursive form of dict merge

    A routine to recursively dig through dicts and merge adapted from
    http://stevehavelka\.com/tcl\-dict\-operation\-nested\-merge/

    Example:

    > set mydict {sub/ {sub/ {description {a block of text}}}}
    > set odict [clay::tree::merge $mydict {sub/ {sub/ {field {another block of text}}}}]
    > clay::tree::print $odict
    sub/ {
      sub/ {
        description {a block of text}
        field {another block of text}
      }
    }

  - proc __dictargs::proc__ *name* *argspec* *body*

    Named Procedures as new command

  - proc __dictargs::method__ *name* *argspec* *body*

  - proc __clay::dialect::Push__ *class*

  - proc __clay::dialect::Peek__

  - proc __clay::dialect::Pop__

  - proc __clay::dialect::create__ *name* ?*parent* ____?

    This proc will generate a namespace, a "mother of all classes", and a
    rudimentary set of policies for this dialect\.

  - proc __clay::dialect::NSNormalize__ *namespace* *qualname*

    Support commands; not intended to be called directly\.

  - proc __clay::dialect::DefineThunk__ *target* ?*args*?

  - proc __clay::dialect::Canonical__ *namespace* *NSpace* *class*

  - proc __clay::dialect::Define__ *namespace* *class* ?*args*?

    Implementation of the languages' define command

  - proc __clay::dialect::Aliases__ *namespace* ?*args*?

  - proc __clay::dialect::SuperClass__ *namespace* ?*args*?

  - proc __clay::dynamic\_methods__ *class*

  - proc __clay::dynamic\_methods\_class__ *thisclass*

  - proc __clay::define::Array__ *name* ?*values* ____?

    New OO Keywords for clay

  - proc __clay::define::Delegate__ *name* *info*

    An annotation that objects of this class interact with delegated methods\.
    The annotation is intended to be a dictionary, and the only reserved key is
    *description*, a human readable description\.

  - proc __clay::define::constructor__ *arglist* *rawbody*

  - proc __clay::define::Class\_Method__ *name* *arglist* *body*

    Specify the a method for the class object itself, instead of for objects of
    the class

  - proc __clay::define::class\_method__ *name* *arglist* *body*

    And alias to the new Class\_Method keyword

  - proc __clay::define::clay__ ?*args*?

  - proc __clay::define::destructor__ *rawbody*

  - proc __clay::define::Dict__ *name* ?*values* ____?

  - proc __clay::define::Option__ *name* ?*args*?

    Define an option for the class

  - proc __clay::define::Method__ *name* *argstyle* *argspec* *body*

  - proc __clay::define::Option\_Class__ *name* ?*args*?

    Define a class of options All field / value pairs will be be inherited by an
    option that specify *name* as it class field\.

  - proc __clay::define::Variable__ *name* ?*default* ____?

    This keyword can also be expressed:

    property variable NAME {default DEFAULT}

    Variables registered in the variable property are also initialized \(if
    missing\) when the object changes class via the *morph* method\.

  - proc __clay::ensemble\_methodbody__ *ensemble* *einfo*

    Produce the body of an ensemble's public dispatch method ensemble is the
    name of the the ensemble\. einfo is a dictionary of methods for the ensemble,
    and each value is a script to execute on dispatch

    Example:

    ::clay::ensemble_methodbody foo {
      bar {tailcall my Foo_bar {*}$args}
      baz {tailcall my Foo_baz {*}$args}
      clock {return [clock seconds]}
      default {puts "You gave me $method"}
    }

  - proc __clay::define::Ensemble__ *rawmethod* ?*args*?

  - proc __clay::event::cancel__ *self* ?*task* __\*__?

    Cancel a scheduled event

  - proc __clay::event::generate__ *self* *event* ?*args*?

    Generate an event Adds a subscription mechanism for objects to see who has
    recieved this event and prevent spamming or infinite recursion

  - proc __clay::event::nextid__

  - proc __clay::event::Notification\_list__ *self* *event* ?*stackvar* ____?

    Called recursively to produce a list of who recieves notifications

  - proc __clay::event::notify__ *rcpt* *sender* *event* *eventinfo*

    Final delivery to intended recipient object

  - proc __clay::event::process__ *self* *handle* *script*

    Evaluate an event script in the global namespace

  - proc __clay::event::schedule__ *self* *handle* *interval* *script*

    Schedule an event to occur later

  - proc __clay::event::subscribe__ *self* *who* *event*

    Subscribe an object to an event pattern

  - proc __clay::event::unsubscribe__ *self* ?*args*?

    Unsubscribe an object from an event pattern

  - proc __clay::singleton__ *name* *script*

    An object which is intended to be it's own class\.

# Classes

## Class  clay::class

__Methods__

  - method __clay ancestors__

    Return this class and all ancestors in search order\.

  - method __clay dump__

    Return a complete dump of this object's clay data, but only this object's
    clay data\.

  - method __clay find__ *path* ?__path\.\.\.__?

    Pull a chunk of data from the clay system\. If the last element of *path*
    is a branch, returns a recursive merge of all data from this object and it's
    constituent classes of the data in that branch\. If the last element is a
    leaf, search this object for a matching leaf, or search all constituent
    classes for a matching leaf and return the first value found\. If no value is
    found, returns an empty string\. If a branch is returned the topmost \. entry
    is omitted\.

  - method __clay get__ *path* ?__path\.\.\.__?

    Pull a chunk of data from the class's clay system\. If no value is found,
    returns an empty string\. If a branch is returned the topmost \. entry is
    omitted\.

  - method __clay GET__ *path* ?__path\.\.\.__?

    Pull a chunk of data from the class's clay system\. If no value is found,
    returns an empty string\.

  - method __clay merge__ *dict* ?__dict\.\.\.__?

    Recursively merge the dictionaries given into the object's local clay
    storage\.

  - method __clay replace__ *dictionary*

    Replace the contents of the internal clay storage with the dictionary given\.

  - method __clay search__ *path* ?__path\.\.\.__?

    Return the first matching value for the path in either this class's clay
    data or one of its ancestors

  - method __clay set__ *path* ?__path\.\.\.__? *value*

    Merge the conents of __value__ with the object's clay storage at
    __path__\.

## Class  clay::object

clay::object This class is inherited by all classes that have options\.

__Methods__

  - method __clay ancestors__

    Return the class this object belongs to, all classes mixed into this object,
    and all ancestors of those classes in search order\.

  - method __clay cache__ *path* *value*

    Store VALUE in such a way that request in SEARCH for PATH will always return
    it until the cache is flushed

  - method __clay cget__ *field*

    Pull a value from either the object's clay structure or one of its
    constituent classes that matches the field name\. The order of search us:

    1\. The as a value in local dict variable config

    2\. The as a value in local dict variable clay

    3\. As a leaf in any ancestor as a root of the clay tree

    4\. As a leaf in any ancestor as __const__ *field*

    5\. As a leaf in any ancestor as __option__ *field* __default__

  - method __clay delegate__ ?*stub*? ?*object*?

    Introspect or control method delegation\. With no arguments, the method will
    return a key/value list of stubs and objects\. With just the *stub*
    argument, the method will return the object \(if any\) attached to the stub\.
    With a *stub* and an *object* this command will forward all calls to the
    method *stub* to the *object*\.

  - method __clay dump__

    Return a complete dump of this object's clay data, as well as the data from
    all constituent classes recursively blended in\.

  - method __clay ensemble\_map__

    Return a dictionary describing the method ensembles to be assembled for this
    object

  - method __clay eval__ *script*

    Evaluated a script in the namespace of this object

  - method __clay evolve__

    Trigger the __InitializePublic__ private method

  - method __clay exists__ *path* ?__path\.\.\.__?

    Returns 1 if *path* exists in either the object's clay data\. Values
    greater than one indicate the element exists in one of the object's
    constituent classes\. A value of zero indicates the path could not be found\.

  - method __clay flush__

    Wipe any caches built by the clay implementation

  - method __clay forward__ *method* *object*

    A convenience wrapper for

    oo::objdefine [self] forward {*}$args

  - method __clay get__ *path* ?__path\.\.\.__?

    Pull a chunk of data from the clay system\. If the last element of *path*
    is a branch \(ends in a slash /\), returns a recursive merge of all data from
    this object and it's constituent classes of the data in that branch\. If the
    last element is a leaf, search this object for a matching leaf, or search
    all constituent classes for a matching leaf and return the first value
    found\. If no value is found, returns an empty string\.

  - method __clay leaf__ *path* ?__path\.\.\.__?

    A modified get which is tailored to pull only leaf elements

  - method __clay merge__ *dict* ?__dict\.\.\.__?

    Recursively merge the dictionaries given into the object's local clay
    storage\.

  - method __clay mixin__ *class* ?__class\.\.\.__?

    Perform \[oo::objdefine \[self\] mixin\] on this object, with a few additional
    rules: Prior to the call, for any class was previously mixed in, but not in
    the new result, execute the script registered to mixin/ unmap\-script \(if
    given\.\) For all new classes, that were not present prior to this call, after
    the native TclOO mixin is invoked, execute the script registered to mixin/
    map\-script \(if given\.\) Fall all classes that are now present and “mixed in”,
    execute the script registered to mixin/ react\-script \(if given\.\)

  - method __clay mixinmap__ ?*stub*? ?*classes*?

    With no arguments returns the map of stubs and classes mixed into the
    current object\. When only stub is given, returns the classes mixed in on
    that stub\. When stub and classlist given, replace the classes currently on
    that stub with the given classes and invoke clay mixin on the new matrix of
    mixed in classes\.

  - method __clay provenance__ *path* ?__path\.\.\.__?

    Return either __self__ if that path exists in the current object, or
    return the first class \(if any\) along the clay search path which contains
    that element\.

  - method __clay replace__ *dictionary*

    Replace the contents of the internal clay storage with the dictionary given\.

  - method __clay search__ *path* *valuevar* *isleafvar*

    Return true, and set valuevar to the value and isleafar to true for false if
    PATH was found in the cache\.

  - method __clay source__ *filename*

    Source the given filename within the object's namespace

  - method __clay set__ *path* ?__path\.\.\.__? *value*

    Merge the conents of __value__ with the object's clay storage at
    __path__\.

  - method __InitializePublic__

    Instantiate variables\. Called on object creation and during clay mixin\.

# AUTHORS

Sean Woods

[mailto:<yoda<EMAIL_ADDRESS>
# Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *oo* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of
__diff \-u__\.

Note further that *attachments* are strongly preferred over inlined patches\.
Attachments can be made by going to the __Edit__ form of the ticket
immediately after its creation, and then using the left\-most button in the
secondary navigation bar\.

# KEYWORDS

[TclOO](\.\./\.\./\.\./\.\./index\.md\#tcloo), [oo](\.\./\.\./\.\./\.\./index\.md\#oo)

# CATEGORY

Programming tools

# COPYRIGHT

Copyright © 2018 Sean Woods<EMAIL_ADDRESS>

repository: markemer/macports-base

gha_language: Tcl

repo_name: markemer/macports-base


text:
---
title: "[React Native] How to Create a New RN Project"
date: 2021-01-15 14:29:28 -0400
categories: react-native
---

Welcome to `React Native` world! This post provides simple and fast guide to start the react native proejct. Skip the description and get the codes when you don't have seconds to read the details. :)

### Install expo
You can choose one of two codes below.
```
npm i -g expo-cli //for npm users
```
```
yarn global add expo-cli //for yarn users
```

### Create a project
```
expo init {projectName}
```
and select one template when you see the options on screen.

### start the proejct
```
yarn start
```
```
npm start
```
Press `i`(ios) or `a`(android) or `w`(web).

### Check mobile screen
#### android
If you want to have a look at it through your mobile phone, then just download `expo` app on your phone and read the QR code that you can find on `localhost:19002`. How simple! Of course, you can check the mobile screen on the website with the default emulator.
#### IOS
You have to login in expo With the code below to check the screen on your phone.
```
expo login
```

### How to check the change on screen
Why is React Native awesome? Because you can check the change as soon as you edit the file. With a few weeks with `android studio`,it was so annoying that I had to wait a few seconds to minutes for a single change. That is one of the reasons why I started to study this lovely react native.

Go to `App.js` file and edit some text and save. Amazingly, you will see the screen is changed. Test now!

```js
//sample App.js code
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Hello world</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
```