Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sanxsth/javascript-algorithms
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: linear-prime-sieve
Choose a base ref
...
head repository: trekhleb/javascript-algorithms
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.

Commits on Jul 3, 2020

  1. Add BACKERS.md.

    trekhleb committed Jul 3, 2020
    Copy the full SHA
    833f59b View commit details

Commits on Jul 6, 2020

  1. Create FUNDING.yml

    trekhleb authored Jul 6, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    503a76d View commit details

Commits on Jul 8, 2020

  1. Update FUNDING.yml

    trekhleb authored Jul 8, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    af09d4b View commit details
  2. Copy the full SHA
    247bc77 View commit details
  3. Copy the full SHA
    a35b776 View commit details
  4. Copy the full SHA
    87e74dd View commit details
  5. Copy the full SHA
    1294afc View commit details
  6. Copy the full SHA
    fd7cf58 View commit details
  7. Copy the full SHA
    7036729 View commit details

Commits on Jul 15, 2020

  1. Link error (trekhleb#511)

    imyangyong authored Jul 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    aa10ffe View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b3b8d4d View commit details
  3. Update README.pt-BR.md (trekhleb#490)

    Traduzido Trie > Árvore de prefixos
    alrtas authored Jul 15, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d43f9d8 View commit details
  4. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3bf94e5 View commit details
  5. Adjusting README.

    trekhleb committed Jul 15, 2020
    Copy the full SHA
    8d32c9f View commit details
  6. Copy the full SHA
    0fcea27 View commit details

Commits on Jul 26, 2020

  1. Upgrade dependencies.

    trekhleb committed Jul 26, 2020
    Copy the full SHA
    d227a33 View commit details
  2. Using Node v12 for Travis.

    trekhleb committed Jul 26, 2020
    Copy the full SHA
    0998483 View commit details
  3. Adding OS to Travis config.

    trekhleb committed Jul 26, 2020
    Copy the full SHA
    4d8baf8 View commit details
  4. Copy the full SHA
    63f5a27 View commit details
  5. Adding inequality conditions (trekhleb#489)

    A quick fix to add inequality conditions wherever needed.
    
    Co-authored-by: Oleksii Trekhleb <trehleb@gmail.com>
    surajhell88 and trekhleb authored Jul 26, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    194f213 View commit details
  6. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2ffb7b7 View commit details
  7. Fix ESLint issues.

    trekhleb committed Jul 26, 2020
    Copy the full SHA
    f42433e View commit details

Commits on Aug 8, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e54a3df View commit details
  2. Caeser cipher (trekhleb#517)

    * added ceaserCipher algorithm
    
    * added ceaserCipher algorithm
    
    * fixed a typo
    Gifted-s authored Aug 8, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bd7475e View commit details
  3. Copy the full SHA
    0024241 View commit details

Commits on Aug 9, 2020

  1. Add french translation for some chapters (trekhleb#520)

    * Create README.fr-FR.md
    
    * Translate to french "Priority Queue" module
    
    * Add english lang redirection
    
    * Update README.fr-FR.md
    
    * Update README.fr-FR.md
    
    * Add French lang version redir
    
    * Create README.fr-FR.md
    
    * Added french translation for Queue
    
    * Added French lang redir
    
    * Update README.md
    
    * Create README.fr-FR.md
    
    * Add french translation
    
    * Index french translation
    
    * Create README.fr-FR.md
    
    * Add french translation
    
    * Index french translation
    
    * Fix translation
    
    * Create README.fr-FR.md
    
    * Add french translation
    
    * Index french translation
    
    * Add wikipedia french reference
    
    * Add french wikipedia reference
    gsbm authored Aug 9, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    95641c8 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2444b97 View commit details
  3. Minor fixes.

    trekhleb committed Aug 9, 2020
    Copy the full SHA
    929b210 View commit details

Commits on Aug 21, 2020

  1. Update README.ru-RU.md (trekhleb#530)

    There is an error in deletion complexity
    LostSenSS authored Aug 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5a3806f View commit details
  2. Fix infinity loop with negative numbers (trekhleb#502)

    * Update countSetBits.js
    
    * Update countSetBits.test.js
    onicat authored Aug 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    be185ac View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c093fe4 View commit details
  4. Fix and Update README.zh-CN.md (trekhleb#469)

    * Update README.zh-CN.md
    
    * Update Translation
    aeilot authored Aug 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6af6323 View commit details
  5. Copy the full SHA
    07bc4a4 View commit details

Commits on Oct 5, 2020

  1. Chore(math-translation-FR-fr): a pack of translations for the math se…

    …ction (trekhleb#558)
    
    * chore(factorial): translation fr-FR
    
    * feat(math-translation-fr-FR): fast powering
    
    * feat(math-translation-fr-FR): fibonacci numbers
    
    * chore(math-translation-fr-FR): bits
    
    * chore(math-translation-fr-FR): complex number
    
    * chore(math-translation-fr-FR): euclidean algorithm
    
    * chore(math-translation-fr-FR): fibonacci number
    
    * chore(math-translation-fr-FR): fourier transform
    
    * chore(math-translation-fr-FR): fourier transform WIP
    
    * chore(math-translation-fr-FR): fourier transform done
    
    * chore(math-translation-fr-FR): fourier transform in menu
    ltruchot authored Oct 5, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d6b8dd3 View commit details
  2. Fix markup.

    trekhleb committed Oct 5, 2020
    Copy the full SHA
    477f30b View commit details

Commits on Nov 2, 2020

  1. Create README.tr-TR.md (trekhleb#574)

    Added Turkish language of README.md
    AykutSarac authored Nov 2, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    826055e View commit details
  2. Copy the full SHA
    ed52a80 View commit details

Commits on Nov 28, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    83978e9 View commit details
  2. Copy the full SHA
    2c74ced View commit details

Commits on Dec 4, 2020

  1. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    83251df View commit details
  2. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    fc1c2d8 View commit details
  3. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    63eebef View commit details
  4. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    922b3ae View commit details
  5. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    7155cfe View commit details
  6. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    e5baba4 View commit details
  7. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    c15e2ca View commit details
  8. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    47b4b68 View commit details
  9. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    f1de657 View commit details
  10. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    2c695b5 View commit details
  11. Update Backers.

    trekhleb committed Dec 4, 2020
    Copy the full SHA
    c919122 View commit details
Showing 351 changed files with 29,434 additions and 6,806 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# @see: https://editorconfig.org/
root = true

[*]
@@ -6,3 +7,5 @@ insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
quote_type = single
6 changes: 6 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -11,5 +11,11 @@
"class-methods-use-this": "off",
"arrow-body-style": "off",
"no-loop-func": "off"
},
"ignorePatterns": ["*.md", "*.png", "*.jpeg", "*.jpg"],
"settings": {
"react": {
"version": "18.2.0"
}
}
}
3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @see: https://docs.github.com/en/github/administering-a-repository/displaying-a-sponsor-button-in-your-repository
github: trekhleb
patreon: trekhleb
35 changes: 35 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: CI

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ 16.x ]

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
run: npm i

- name: Run linting
run: npm run lint

- name: Run tests
run: npm run coverage

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
1 change: 1 addition & 0 deletions .husky/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_
5 changes: 5 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run lint
# npm run test
5 changes: 0 additions & 5 deletions .huskyrc.json

This file was deleted.

1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v16.15.0
13 changes: 0 additions & 13 deletions .travis.yml

This file was deleted.

48 changes: 48 additions & 0 deletions BACKERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Project Backers

> You may support this project via ❤️️ [GitHub](https://github.com/sponsors/trekhleb) or ❤️️ [Patreon](https://www.patreon.com/trekhleb).
## `O(2ⁿ)` Backers

`null`

## `O(n²)` Backers

`null`

## `O(n×log(n))` Backers

`null`

<!--
<table>
<tr>
<td align="center">
<a href="[PROFILE_URL]">
<img
src="[PROFILE_IMG_SRC]"
width="50"
height="50"
/>
</a>
<br />
<a href="[PROFILE_URL]">[PROFILE_NAME]</a>
</td>
</tr>
</table>
-->

<!--
<ul>
<li>
<a href="[PROFILE_URL]">
<img
src="[PROFILE_IMG_SRC]"
width="30"
height="30"
/></a>
&thinsp;
<a href="[PROFILE_URL]">[PROFILE_NAME]</a>
</li>
</ul>
-->
328 changes: 328 additions & 0 deletions README.ar-AR.md

Large diffs are not rendered by default.

338 changes: 338 additions & 0 deletions README.de-DE.md

Large diffs are not rendered by default.

38 changes: 25 additions & 13 deletions README.es-ES.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Algoritmos y Estructuras de Datos en JavaScript

[![Build Status](https://travis-ci.org/trekhleb/javascript-algorithms.svg?branch=master)](https://travis-ci.org/trekhleb/javascript-algorithms)
[![CI](https://github.com/trekhleb/javascript-algorithms/workflows/CI/badge.svg)](https://github.com/trekhleb/javascript-algorithms/actions?query=workflow%3ACI+branch%3Amaster)
[![codecov](https://codecov.io/gh/trekhleb/javascript-algorithms/branch/master/graph/badge.svg)](https://codecov.io/gh/trekhleb/javascript-algorithms)

Este repositorio contiene ejemplos basados en JavaScript de muchos
algoritmos y estructuras de datos populares.

Cada algoritmo y estructura de datos tiene su propio LÉAME con explicaciones relacionadas y
Cada algoritmo y estructura de datos tiene su propio LÉAME con explicaciones relacionadas y
enlaces para lecturas adicionales (incluyendo algunas a vídeos de YouTube).

_Léelo en otros idiomas:_
@@ -17,7 +17,17 @@ _Léelo en otros idiomas:_
[_日本語_](README.ja-JP.md),
[_Polski_](README.pl-PL.md),
[_Français_](README.fr-FR.md),
[_Português_](README.pt-BR.md)
[_Português_](README.pt-BR.md),
[_Русский_](README.ru-RU.md),
[_Türk_](README.tr-TR.md),
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
[_Arabic_](README.ar-AR.md),
[_Tiếng Việt_](README.vi-VN.md),
[_Deutsch_](README.de-DE.md),
[_Uzbek_](README.uz-UZ.md)
[_עברית_](README.he-IL.md)

*☝ Nótese que este proyecto está pensado con fines de aprendizaje e investigación,
y **no** para ser usado en producción.*
@@ -51,7 +61,7 @@ los datos.

## Algoritmos

Un algoritmo es una especificación inequívoca de cómo resolver una clase de problemas. Es un conjunto de reglas que
Un algoritmo es una especificación inequívoca de cómo resolver una clase de problemas. Es un conjunto de reglas que
definen con precisión una secuencia de operaciones.

`P` - Principiante, `A` - Avanzado
@@ -61,7 +71,7 @@ definen con precisión una secuencia de operaciones.
* **Matemáticas**
* `P` [Manipulación de bits](src/algorithms/math/bits) - asignar/obtener/actualizar/limpiar bits, multiplicación/división por dos, hacer negativo, etc.
* `P` [Factorial](src/algorithms/math/factorial)
* `P` [Número de Fibonacci](src/algorithms/math/fibonacci)
* `P` [Sucesión de Fibonacci](src/algorithms/math/fibonacci)
* `P` [Prueba de primalidad](src/algorithms/math/primality-test) (método de división de prueba)
* `P` [Algoritmo de Euclides](src/algorithms/math/euclidean-algorithm) - calcular el Máximo común divisor (MCD)
* `P` [Mínimo común múltiplo](src/algorithms/math/least-common-multiple) (MCM)
@@ -72,7 +82,7 @@ definen con precisión una secuencia de operaciones.
* `P` [Radianes & Grados](src/algorithms/math/radian) - conversión de radianes a grados y viceversa
* `P` [Exponenciación rápida](src/algorithms/math/fast-powering)
* `A` [Partición entera](src/algorithms/math/integer-partition)
* `A` [Algortimo π de Liu Hui](src/algorithms/math/liu-hui) - aproximar el cálculo de π basado en polígonos de N lados
* `A` [Algoritmo π de Liu Hui](src/algorithms/math/liu-hui) - aproximar el cálculo de π basado en polígonos de N lados
* `A` [Transformada discreta de Fourier](src/algorithms/math/fourier-transform) - descomponer una función de tiempo (señal) en las frecuencias que la componen
* **Conjuntos**
* `P` [Producto cartesiano](src/algorithms/sets/cartesian-product) - producto de múltiples conjuntos
@@ -121,7 +131,7 @@ definen con precisión una secuencia de operaciones.
* `P` [Algoritmo de Kruskal](src/algorithms/graph/kruskal) - encontrar el árbol de cubrimiento mínimo (MST) para un grafo no dirigido ponderado
* `A` [Algoritmo de Dijkstra](src/algorithms/graph/dijkstra) - encontrar los caminos más cortos a todos los vértices del grafo desde un solo vértice
* `A` [Algoritmo de Bellman-Ford](src/algorithms/graph/bellman-ford) - encontrar los caminos más cortos a todos los vértices del grafo desde un solo vértice
* `A` [Algortimo de Floyd-Warshall](src/algorithms/graph/floyd-warshall) - encontrar los caminos más cortos entre todos los pares de vértices
* `A` [Algoritmo de Floyd-Warshall](src/algorithms/graph/floyd-warshall) - encontrar los caminos más cortos entre todos los pares de vértices
* `A` [Detectar ciclos](src/algorithms/graph/detect-cycle) - para grafos dirigidos y no dirigidos (versiones basadas en DFS y conjuntos disjuntos)
* `A` [Algoritmo de Prim](src/algorithms/graph/prim) - encontrar el árbol de cubrimiento mínimo (MST) para un grafo no dirigido ponderado
* `A` [Ordenamiento topológico](src/algorithms/graph/topological-sorting) - método DFS
@@ -131,7 +141,7 @@ definen con precisión una secuencia de operaciones.
* `A` [Ciclo hamiltoniano](src/algorithms/graph/hamiltonian-cycle) - visitar cada vértice exactamente una vez
* `A` [Componentes fuertemente conexos](src/algorithms/graph/strongly-connected-components) - algoritmo de Kosaraju
* `A` [Problema del viajante](src/algorithms/graph/travelling-salesman) - la ruta más corta posible que visita cada ciudad y vuelve a la ciudad de origen
* **Criptografia**
* **Criptografía**
* `P` [Hash polinomial](src/algorithms/cryptography/polynomial-hash) - función de hash rodante basada en polinomio
* **Sin categoría**
* `P` [Torre de Hanói](src/algorithms/uncategorized/hanoi-tower)
@@ -157,7 +167,7 @@ Es una abstracción superior a la noción de algoritmo, del mismo modo que un al
* `P` [Juego de los saltos](src/algorithms/uncategorized/jump-game)
* `A` [Problema de la mochila sin límite](src/algorithms/sets/knapsack-problem)
* `A` [Algoritmo de Dijkstra](src/algorithms/graph/dijkstra) - encontrar los caminos más cortos a todos los vértices del grafo desde un solo vértice
* `A` [Algortimo de Prim](src/algorithms/graph/prim) - encontrar el árbol de cubrimiento mínimo (MST) para un grafo no dirigido ponderado
* `A` [Algoritmo de Prim](src/algorithms/graph/prim) - encontrar el árbol de cubrimiento mínimo (MST) para un grafo no dirigido ponderado
* `A` [Algoritmo de Kruskal](src/algorithms/graph/kruskal) - encontrar el árbol de cubrimiento mínimo (MST) para un grafo no dirigido ponderado
* **Divide y Vencerás** - divide el problema en partes más pequeñas y luego resuelve esas partes
* `P` [Búsqueda binaria](src/algorithms/search/binary-search)
@@ -196,7 +206,7 @@ Es una abstracción superior a la noción de algoritmo, del mismo modo que un al
* `A` [Problema de las N Reinas](src/algorithms/uncategorized/n-queens)
* `A` [Problema del caballo (Knight tour)](src/algorithms/uncategorized/knight-tour)
* `A` [Suma combinada](src/algorithms/sets/combination-sum) - encuentra todas las combinaciones que forman una suma específica
* **Ramas y Limites** - recuerda la solución de menor costo encontrada en cada etapa de la búsqueda de rastreo, y utilizar el costo de la solución de menor costo encontrada hasta el momento como un límite inferior del costo de una solución de menor costo para el problema, a fin de descartar soluciones parciales con costos mayores que la solución de menor costo encontrada hasta el momento. Normalmente se utiliza un recorrido BFS en combinación con un recorrido DFS del árbol del espacio de estados.
* **Ramas y Límites** - recuerda la solución de menor costo encontrada en cada etapa de la búsqueda de rastreo, y utilizar el costo de la solución de menor costo encontrada hasta el momento como un límite inferior del costo de una solución de menor costo para el problema, a fin de descartar soluciones parciales con costos mayores que la solución de menor costo encontrada hasta el momento. Normalmente se utiliza un recorrido BFS en combinación con un recorrido DFS del árbol del espacio de estados.

## Cómo usar este repositorio

@@ -228,7 +238,7 @@ npm test -- 'LinkedList'

**Campo de juegos**

Puede jugar con estructuras de datos y algoritmos en el archivo `./src/playground/playground.js` y escribir
Puede jugar con estructuras de datos y algoritmos en el archivo `./src/playground/playground.js` y escribir
pruebas para ello en `./src/playground/__test__/playground.test.js`.

A continuación, simplemente ejecute el siguiente comando para comprobar si el código funciona como se espera:
@@ -239,7 +249,7 @@ npm test -- 'playground'

## Información útil

### Refrencias
### Referencias

[▶ Estructuras de datos y algoritmos en YouTube](https://www.youtube.com/playlist?list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)

@@ -251,7 +261,7 @@ Orden de crecimiento de los algoritmos especificados en la notación O grande.

Fuente: [Big O Cheat Sheet](http://bigocheatsheet.com/).

A continuación se muestra la lista de algunas de las notaciones de Big O más utilizadas y sus comparaciones de rendimiento
A continuación se muestra la lista de algunas de las notaciones de Big O más utilizadas y sus comparaciones de rendimiento
frente a diferentes tamaños de los datos de entrada.

| Notación O grande | Cálculos para 10 elementos | Cálculos para 100 elementos | Cálculos para 1000 elementos |
@@ -292,3 +302,5 @@ frente a diferentes tamaños de los datos de entrada.
| **Shellsort** | n&nbsp;log(n) | depende de la secuencia de huecos | n&nbsp;(log(n))<sup>2</sup> | 1 | No | |
| **Ordenamiento por cuentas** | n + r | n + r | n + r | n + r | Si | r - mayor número en el arreglo |
| **Ordenamiento Radix** | n \* k | n \* k | n \* k | n + k | Si | k - largo de la llave más larga |

> ℹ️ Algunos otros [proyectos](https://trekhleb.dev/projects/) y [artículos](https://trekhleb.dev/blog/) sobre JavaScript y algoritmos en [trekhleb.dev](https://trekhleb.dev)
392 changes: 205 additions & 187 deletions README.fr-FR.md

Large diffs are not rendered by default.

370 changes: 370 additions & 0 deletions README.he-IL.md

Large diffs are not rendered by default.

311 changes: 311 additions & 0 deletions README.id-ID.md

Large diffs are not rendered by default.

304 changes: 304 additions & 0 deletions README.it-IT.md

Large diffs are not rendered by default.

26 changes: 19 additions & 7 deletions README.ja-JP.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# JavaScriptアルゴリズムとデータ構造

[![Build Status](https://travis-ci.org/trekhleb/javascript-algorithms.svg?branch=master)](https://travis-ci.org/trekhleb/javascript-algorithms)
[![CI](https://github.com/trekhleb/javascript-algorithms/workflows/CI/badge.svg)](https://github.com/trekhleb/javascript-algorithms/actions?query=workflow%3ACI+branch%3Amaster)
[![codecov](https://codecov.io/gh/trekhleb/javascript-algorithms/branch/master/graph/badge.svg)](https://codecov.io/gh/trekhleb/javascript-algorithms)

このリポジトリには、JavaScriptベースの一般的なアルゴリズムとデータ構造に関する多数のサンプルが含まれています。


各アルゴリズムとデータ構造には独自のREADMEがあります。
関連する説明と、さらに読むためのリンク (関連YouTubeのビデオ)も含まれています。
関連する説明、そして参考資料 (YouTube動画)も含まれています。

_Read this in other languages:_
[_English_](https://github.com/trekhleb/javascript-algorithms/),
@@ -17,7 +17,17 @@ _Read this in other languages:_
[_Polski_](README.pl-PL.md),
[_Français_](README.fr-FR.md),
[_Español_](README.es-ES.md),
[_Português_](README.pt-BR.md)
[_Português_](README.pt-BR.md),
[_Русский_](README.ru-RU.md),
[_Türk_](README.tr-TR.md),
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
[_Arabic_](README.ar-AR.md),
[_Tiếng Việt_](README.vi-VN.md),
[_Deutsch_](README.de-DE.md),
[_Uzbek_](README.uz-UZ.md)
[_עברית_](README.he-IL.md)

## データ構造

@@ -57,7 +67,7 @@ _Read this in other languages:_

* **数学**
* `B` [ビット操作](src/algorithms/math/bits) - set/get/update/clear bits, 2つの乗算/除算, 否定的にする. 等
* `B` [因果関係](src/algorithms/math/factorial)
* `B` [因果関係](src/algorithms/math/factorial)
* `B` [フィボナッチ数](src/algorithms/math/fibonacci) - クラシックとクローズドフォームのバージョン
* `B` [素数性テスト](src/algorithms/math/primality-test) (trial division 方法)
* `B` [ユークリッドアルゴリズム](src/algorithms/math/euclidean-algorithm) - 最大公約数を計算する (GCD)
@@ -93,7 +103,7 @@ _Read this in other languages:_
* `A` [正規表現マッチング](src/algorithms/string/regular-expression-matching)
* **検索**
* `B` [リニアサーチ](src/algorithms/search/linear-search)
* `B` [ジャンプ検索](src/algorithms/search/jump-search) (or Block Search) - ソートされた配列で検索
* `B` [ジャンプ検索](src/algorithms/search/jump-search) (Jump Search) - ソートされた配列で検索
* `B` [バイナリ検索](src/algorithms/search/binary-search) - ソートされた配列で検索
* `B` [補間探索](src/algorithms/search/interpolation-search) - 一様分布のソート配列で検索する
* **並べ替え**
@@ -115,7 +125,7 @@ _Read this in other languages:_
* **グラフ**
* `B` [深度優先検索](src/algorithms/graph/depth-first-search) (DFS)
* `B` [幅優先検索](src/algorithms/graph/breadth-first-search) (BFS)
* `B` [Kruskalのアルゴリズム](src/algorithms/graph/kruskal) - 重み付き無向グラフの最小スパニングツリー(MST)の発見
* `B` [Kruskalのアルゴリズム](src/algorithms/graph/kruskal) - 重み付き無向グラフの最小スパニングツリー(MST)の発見
* `A` [Dijkstraアルゴリズム](src/algorithms/graph/dijkstra) - 単一の頂点からすべてのグラフ頂点への最短経路を見つける
* `A` [Bellman-Fordアルゴリズム](src/algorithms/graph/bellman-ford) - 単一の頂点からすべてのグラフ頂点への最短経路を見つける
* `A` [Floyd-Warshallアルゴリズム](src/algorithms/graph/floyd-warshall) - すべての頂点ペア間の最短経路を見つける
@@ -143,7 +153,7 @@ _Read this in other languages:_
### Paradigmによるアルゴリズム

アルゴリズムパラダイムは、あるクラスのアルゴリズムの設計の基礎をなす一般的な方法またはアプローチである。それは、アルゴリズムがコンピュータプログラムよりも高い抽象であるのと同様に、アルゴリズムの概念よりも高い抽象である。
* **ブルートフォース** - べての可能性を見て最適なソリューションを選択する
* **ブルートフォース** - すべての可能性を見て最適なソリューションを選択する
* `B` [線形探索](src/algorithms/search/linear-search)
* `B` [レインテラス](src/algorithms/uncategorized/rain-terraces) - 雨水問題
* `B` [Recursive Staircase](src/algorithms/uncategorized/recursive-staircase) - 先頭に到達する方法の数を数えます
@@ -289,3 +299,5 @@ npm test -- 'playground'
| **Shell sort** | n&nbsp;log(n) | depends on gap sequence | n&nbsp;(log(n))<sup>2</sup> | 1 | No | |
| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array |
| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key |

> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
30 changes: 21 additions & 9 deletions README.ko-KR.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# JavaScript 알고리즘 및 자료 구조

[![Build Status](https://travis-ci.org/trekhleb/javascript-algorithms.svg?branch=master)](https://travis-ci.org/trekhleb/javascript-algorithms)
[![CI](https://github.com/trekhleb/javascript-algorithms/workflows/CI/badge.svg)](https://github.com/trekhleb/javascript-algorithms/actions?query=workflow%3ACI+branch%3Amaster)
[![codecov](https://codecov.io/gh/trekhleb/javascript-algorithms/branch/master/graph/badge.svg)](https://codecov.io/gh/trekhleb/javascript-algorithms)

이 저장소에는 많이 알려진 알고리즘 및 자료 구조의 Javascript 기반 예제를 담고 있습니다.

각 알고리즘과 자료 구조에 대해 연관되어있는 설명이 README에 작성되어 있으며,
각 알고리즘과 자료 구조에 대해 연관되어 있는 설명이 README에 작성되어 있으며,
링크를 통해 더 자세한 설명을 만날 수 있습니다. (관련된 YouTube 영상도 포함).

_Read this in other languages:_
@@ -16,13 +16,23 @@ _Read this in other languages:_
[_Polski_](README.pl-PL.md),
[_Français_](README.fr-FR.md),
[_Español_](README.es-ES.md),
[_Português_](README.pt-BR.md)
[_Português_](README.pt-BR.md),
[_Русский_](README.ru-RU.md),
[_Türk_](README.tr-TR.md),
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
[_Arabic_](README.ar-AR.md),
[_Tiếng Việt_](README.vi-VN.md),
[_Deutsch_](README.de-DE.md),
[_Uzbek_](README.uz-UZ.md)
[_עברית_](README.he-IL.md)

## 자료 구조

자료 구조는 데이터를 특정 방식으로 구성하고 저장함으로써 더 효율적으로
접근하고 수정할 수 있게 해줍니다. 간단히 말해, 자료 구조는 데이터 값들,
데이터 간의 관계, 그리고 데이터를 다룰 수 있는 함수와 작업의 모임입니다.
데이터 간의 관계, 그리고 데이터를 다룰 수 있는 함수와 작업의 모임입니다.


`B` - 입문자, `A` - 숙련자
@@ -47,16 +57,16 @@ _Read this in other languages:_

## 알고리즘

알고리즘은 어떤 종류의 문제를 풀 수 있는 정확한 방법이며,
일련의 작업을 정확하게 정의해 놓은 규칙들입니다.
알고리즘은 어떤 종류의 문제를 풀 수 있는 정확한 방법이며,
일련의 작업을 정확하게 정의해 놓은 규칙들입니다.

`B` - 입문자, `A` - 숙련자

### 주제별 알고리즘

* **Math**
* `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, 2의 곱 / 나누기, 음수로 만들기 etc.
* `B` [팩토리얼](src/algorithms/math/factorial)
* `B` [팩토리얼](src/algorithms/math/factorial)
* `B` [피보나치 수](src/algorithms/math/fibonacci)
* `B` [소수 판별](src/algorithms/math/primality-test) (trial division 방식)
* `B` [유클리드 호제법](src/algorithms/math/euclidean-algorithm) - 최대공약수 (GCD)
@@ -123,15 +133,15 @@ _Read this in other languages:_
* **Uncategorized**
* `B` [하노이 탑](src/algorithms/uncategorized/hanoi-tower)
* `B` [정방 행렬 회전](src/algorithms/uncategorized/square-matrix-rotation) - 제자리(in-place) 알고리즘
* `B` [점프 게임](src/algorithms/uncategorized/jump-game) - 백트래킹, 동적계획법 (top-down + bottom-up), 탐욕 알고리즘 예제
* `B` [점프 게임](src/algorithms/uncategorized/jump-game) - 백트래킹, 동적계획법 (top-down + bottom-up), 탐욕 알고리즘 예제
* `B` [Unique 경로](src/algorithms/uncategorized/unique-paths) - 백트래킹, 동적계획법, 파스칼 삼각형에 기반한 예제
* `B` [빗물 담기 문제](src/algorithms/uncategorized/rain-terraces) - trapping rain water problem (동적계획법, 브루트포스 버전)
* `A` [N-Queens 문제](src/algorithms/uncategorized/n-queens)
* `A` [기사의 여행 문제](src/algorithms/uncategorized/knight-tour)

### 패러다임별 알고리즘

알고리즘 패러다임 이란, 알고리즘이 주어진 문제를 해결하기 위해 채택한 기초가 되는 일반적인 방법 혹은 접근법입니다. 알고리즘이 해결하는 문제나 알고리즘의 동작 방식이 완전히 다르더라도,알고리즘의 동작 원칙이 같으면 같은 패러다음을 사용했다고 말할 수 있으며, 주로 알고리즘을 구분하는 기준으로 쓰인다. 알고리즘이 일반적인 컴퓨터의 프로그램에 대한 개념보다 보다 더 추상적인 개념인 것처럼 알고리즘의 패러다임은 명확히 정의된 수학적 실체가 있는 것이 아니기 때문에 그 어떤 알고리즘의 개념보다도 훨씬 추상적인 개념이다.
알고리즘 패러다임 이란, 알고리즘이 주어진 문제를 해결하기 위해 채택한 기초가 되는 일반적인 방법 혹은 접근법입니다. 알고리즘이 해결하는 문제나 알고리즘의 동작 방식이 완전히 다르더라도,알고리즘의 동작 원칙이 같으면 같은 패러다음을 사용했다고 말할 수 있으며, 주로 알고리즘을 구분하는 기준으로 쓰인다. 알고리즘이 일반적인 컴퓨터의 프로그램에 대한 개념보다 보다 더 추상적인 개념인 것처럼 알고리즘의 패러다임은 명확히 정의된 수학적 실체가 있는 것이 아니기 때문에 그 어떤 알고리즘의 개념보다도 훨씬 추상적인 개념입니다.

* **브루트 포스(Brute Force)** - 가능한 모든 경우를 탐색한 뒤 최적을 찾아내는 방식입니다.
* `B` [선형 탐색](src/algorithms/search/linear-search)
@@ -270,3 +280,5 @@ Source: [Big O Cheat Sheet](http://bigocheatsheet.com/).
| **셸 정렬** | n&nbsp;log(n) | 간격 순서에 영향을 받습니다. | n&nbsp;(log(n))<sup>2</sup> | 1 | No | |
| **계수 정렬** | n + r | n + r | n + r | n + r | Yes | r - 배열내 가장 큰 수 |
| **기수 정렬** | n * k | n * k | n * k | n + k | Yes | k - 키값의 최대 길이 |

> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
146 changes: 110 additions & 36 deletions README.md

Large diffs are not rendered by default.

60 changes: 36 additions & 24 deletions README.pl-PL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# JavaScript Algorytmy i Struktury Danych

[![Build Status](https://travis-ci.org/trekhleb/javascript-algorithms.svg?branch=master)](https://travis-ci.org/trekhleb/javascript-algorithms)
[![CI](https://github.com/trekhleb/javascript-algorithms/workflows/CI/badge.svg)](https://github.com/trekhleb/javascript-algorithms/actions?query=workflow%3ACI+branch%3Amaster)
[![codecov](https://codecov.io/gh/trekhleb/javascript-algorithms/branch/master/graph/badge.svg)](https://codecov.io/gh/trekhleb/javascript-algorithms)

To repozytorium zawiera wiele przykładów JavaScript opartych na
To repozytorium zawiera wiele przykładów JavaScript opartych na
znanych algorytmach i strukturach danych.

Każdy algorytm i struktura danych zawiera osobny plik README
wraz z powiązanymi wyjaśnieniami i odnośnikami do dalszego czytania
wraz z powiązanymi wyjaśnieniami i odnośnikami do dalszego czytania
(włącznie z tymi do YouTube videos).

_Read this in other languages:_
@@ -18,14 +18,24 @@ _Read this in other languages:_
[_日本語_](README.ja-JP.md),
[_Français_](README.fr-FR.md),
[_Español_](README.es-ES.md),
[_Português_](README.pt-BR.md)
[_Português_](README.pt-BR.md),
[_Русский_](README.ru-RU.md),
[_Türk_](README.tr-TR.md),
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
[_Arabic_](README.ar-AR.md),
[_Tiếng Việt_](README.vi-VN.md),
[_Deutsch_](README.de-DE.md),
[_Uzbek_](README.uz-UZ.md)
[_עברית_](README.he-IL.md)

## Struktury Danych

Struktura danych to sposób uporządkowania i przechowywania informacji w
Struktura danych to sposób uporządkowania i przechowywania informacji w
komputerze żeby mogłaby być sprawnie dostępna i efektywnie zmodyfikowana.
Dokładniej, struktura danych jest zbiorem wartości danych, relacjami
pomiędzy nimi, zadaniami lub działaniami, które mogą dotyczyć danych.
Dokładniej, struktura danych jest zbiorem wartości danych, relacjami
pomiędzy nimi, zadaniami lub działaniami, które mogą dotyczyć danych.

`B` - Początkujący, `A` - Zaawansowany

@@ -49,8 +59,8 @@ pomiędzy nimi, zadaniami lub działaniami, które mogą dotyczyć danych.

## Algorytmy

Algorytm jest to skończony ciąg jasno zdefiniowanych czynności, koniecznych
do wykonania pewnego rodzaju zadań. Sposób postępowania prowadzący do
Algorytm jest to skończony ciąg jasno zdefiniowanych czynności, koniecznych
do wykonania pewnego rodzaju zadań. Sposób postępowania prowadzący do
rozwiązania problemu.

`B` - Początkujący, `A` - Zaawansowany
@@ -59,7 +69,7 @@ rozwiązania problemu.

* **Matematyka**
* `B` [Manipulacja Bitami](src/algorithms/math/bits) - ustaw / uzyskaj / aktualizuj / usuwaj bity, mnożenie / dzielenie przez dwa, tworzenie negatywów itp.
* `B` [Silna](src/algorithms/math/factorial)
* `B` [Silnia](src/algorithms/math/factorial)
* `B` [Ciąg Fibonacciego](src/algorithms/math/fibonacci)
* `B` [Test Pierwszorzędności](src/algorithms/math/primality-test) (metoda podziału na próby)
* `B` [Algorytm Euclideana](src/algorithms/math/euclidean-algorithm) - obliczyć Największy Wspólny Dzielnik (GCD)
@@ -78,9 +88,9 @@ rozwiązania problemu.
* `A` [Najdłuższa Wspólna Podsekwencja](src/algorithms/sets/longest-common-subsequence) (LCS)
* `A` [Najdłuższa Wzrostająca Podsekwencja](src/algorithms/sets/longest-increasing-subsequence)
* `A` [Najkrótsza Wspólna Supersekwencja](src/algorithms/sets/shortest-common-supersequence) (SCS)
* `A` [Problem Knapsacka](src/algorithms/sets/knapsack-problem) - "0/1" i "Rozwiązany"
* `A` [Problem Knapsacka](src/algorithms/sets/knapsack-problem) - "0/1" i "Rozwiązany"
* `A` [Maksymalna Podtablica](src/algorithms/sets/maximum-subarray) - "Metoda Siłowa" i "Dynamiczne Programowanie" (Kadane-a) wersje
* `A` [Suma Kombinacji](src/algorithms/sets/combination-sum) -
* `A` [Suma Kombinacji](src/algorithms/sets/combination-sum) -
znajdź wszystkie kombinacje, które tworzą określoną sumę
* **Łańcuchy**
* `B` [Odległość Hamminga](src/algorithms/string/hamming-distance) - liczba pozycji, w których symbole są różne
@@ -117,26 +127,26 @@ znajdź wszystkie kombinacje, które tworzą określoną sumę
* `A` [Algorytm Floyd-Warshalla](src/algorithms/graph/floyd-warshall) - znajdź najkrótsze ścieżki między wszystkimi parami wierzchołków
* `A` [Detect Cycle](src/algorithms/graph/detect-cycle) - zarówno dla wykresów skierowanych, jak i nieukierunkowanych(wersje oparte na DFS i Rozłączny Zestaw)
* `A` [Algorytm Prima](src/algorithms/graph/prim) - znalezienie Minimalnego Drzewa Opinającego (MST) dla ważonego nieukierunkowanego wykresu
* `A` [Sortowanie Topologiczne](src/algorithms/graph/topological-sorting) - metoda DFS
* `A` [Sortowanie Topologiczne](src/algorithms/graph/topological-sorting) - metoda DFS
* `A` [Punkty Artykulacji](src/algorithms/graph/articulation-points) - Algorytm Tarjana (oparty o DFS)
* `A` [Mosty](src/algorithms/graph/bridges) - Oparty na algorytmie DFS
* `A` [Mosty](src/algorithms/graph/bridges) - Oparty na algorytmie DFS
* `A` [Ścieżka Euleriana i Obwód Euleriana](src/algorithms/graph/eulerian-path) - Algorytm Fleurya - Odwiedź każdą krawędź dokładnie raz
* `A` [Cykl Hamiltoniana](src/algorithms/graph/hamiltonian-cycle) - Odwiedź każdy wierzchołek dokładnie raz
* `A` [Silnie Połączone Komponenty](src/algorithms/graph/strongly-connected-components) - Algorytm Kosaraja
* `A` [Silnie Połączone Komponenty](src/algorithms/graph/strongly-connected-components) - Algorytm Kosaraja
* `A` [Travelling Salesman Problem](src/algorithms/graph/travelling-salesman) - najkrótsza ścieżka która odwiedza każde miasto i wraca miasta początkującego
* **Niezkategorizowane**
* `B` [Wieża Hanoi](src/algorithms/uncategorized/hanoi-tower)
* `B` [Kwadratowa Matryca Obrotu](src/algorithms/uncategorized/square-matrix-rotation) - algorytm w miejscu
* `B` [Jump Game](src/algorithms/uncategorized/jump-game) - cofanie, dynamiczne programowanie (od góry do dołu + od dołu do góry) i przykłady chciwego
* `B` [Jump Game](src/algorithms/uncategorized/jump-game) - cofanie, dynamiczne programowanie (od góry do dołu + od dołu do góry) i przykłady chciwego
* `B` [Unikatowe Ścieżki](src/algorithms/uncategorized/unique-paths) - cofanie, dynamiczne programowanie i przykłady oparte na Trójkącie Pascala
* `A` [Problem N-Queens](src/algorithms/uncategorized/n-queens)
* `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour)

### Algorytmy według paradygmatu

Paradygmat algorytmiczny jest ogólną metodą lub podejściem, które jest
podstawą projektowania klasy algorytmów. Jest abstrakcją wyższą niż
pojęcie algorytmu, podobnie jak algorytm jest abstrakcją wyższą niż
Paradygmat algorytmiczny jest ogólną metodą lub podejściem, które jest
podstawą projektowania klasy algorytmów. Jest abstrakcją wyższą niż
pojęcie algorytmu, podobnie jak algorytm jest abstrakcją wyższą niż
program komputerowy.

* **Metoda Siłowa** - Sprawdza wszystkie możliwosci i wybiera najlepsze rozwiązanie.
@@ -146,7 +156,7 @@ program komputerowy.
* **Chciwy** - wybierz najlepszą opcję w obecnym czasie, bez względu na przyszłość
* `B` [Jump Game](src/algorithms/uncategorized/jump-game)
* `A` [Niezwiązany Problem Knapsacka ](src/algorithms/sets/knapsack-problem)
* `A` [Algorytm Dijkstry](src/algorithms/graph/dijkstra) -
* `A` [Algorytm Dijkstry](src/algorithms/graph/dijkstra) -
znalezienie najkrótszej ścieżki do wszystkich wierzchołków grafu
* `A` [Algorytm Prima](src/algorithms/graph/prim) - znalezienie Minimalnego Drzewa Opinającego (MST) dla ważonego nieukierunkowanego wykresu
* `A` [Algorytm Kruskala](src/algorithms/graph/kruskal) - znalezienie Minimalnego Drzewa Opinającego (MST) dla ważonego nieukierunkowanego wykresu
@@ -175,7 +185,7 @@ znalezienie najkrótszej ścieżki do wszystkich wierzchołków grafu
* `A` [Partycja Całkowita](src/algorithms/math/integer-partition)
* `A` [Maksymalne Podtablice](src/algorithms/sets/maximum-subarray)
* `A` [Algorytm Bellman-Forda](src/algorithms/graph/bellman-ford) - znalezienie najkrótszej ścieżki wszystkich wierzchołków wykresu
* `A` [Algorytm Floyd-Warshalla](src/algorithms/graph/floyd-warshall) -
* `A` [Algorytm Floyd-Warshalla](src/algorithms/graph/floyd-warshall) -
znajdź najkrótsze ścieżki między wszystkimi parami wierzchołków
* `A` [Dopasowanie Wyrażeń Regularnych](src/algorithms/string/regular-expression-matching)
* **Algorytm z nawrotami** - podobny do metody siłowej, próbuje wygenerować wszystkie możliwe rozwiązania, jednak za każdym razem generujesz następne rozwiązanie które testujesz
@@ -189,7 +199,7 @@ jeżeli zaspokaja wszystkie warunki, tylko wtedy generuje kolejne rozwiązania.
* **Metoda Podziału i Ograniczeń** - Pamięta o niskonakładowym rozwiązaniu znalezionym na każdym etapie szukania nawrotu,
używa kosztu niskonakładowego kosztu, które dotychczas zostało znalezione jako niska granica najmniejszego kosztu
do rozwiązanie problemu, aby odrzucić cząstkowe rozwiązania o kosztach większych niż niskonakładowe
rozwiązanie znalezione do tej pory.
rozwiązanie znalezione do tej pory.
Zazwyczan trajektoria BFS, w połączeniu z trajektorią Przeszukiwania W Głąb (DFS) drzewa przestrzeni stanów jest użyte.

## Jak używać repozytorium
@@ -222,7 +232,7 @@ npm test -- 'LinkedList'
Możesz pociwiczyć ze strukturą danych i algorytmami w `./src/playground/playground.js` zakartotekuj i napisz
testy do tego w `./src/playground/__test__/playground.test.js`.

Następnie uruchom następującą komendę w celu przetestowania czy twoje kod działa według oczekiwań:
Następnie uruchom następującą komendę w celu przetestowania czy twoje kod działa według oczekiwań:

```
npm test -- 'playground'
@@ -236,7 +246,7 @@ npm test -- 'playground'

### Big O Notacja

Kolejność wzrastania algorytmów według Big O notacji.
Kolejność wzrastania algorytmów według Big O notacji.

![Big O grafy](./assets/big-o-graph.png)

@@ -282,3 +292,5 @@ Poniżej umieszczamy listę najbardziej używanych Big O notacji i ich porównan
| **Sortowanie Shella** | n&nbsp;log(n) | zależy od luki w układzie | n&nbsp;(log(n))<sup>2</sup> | 1 | No | |
| **Sortowanie przez zliczanie** | n + r | n + r | n + r | n + r | Yes | r - największy numer w tablicy|
| **Sortowanie Radix** | n * k | n * k | n * k | n + k | Yes | k -długość najdłuższego klucza |

> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
279 changes: 149 additions & 130 deletions README.pt-BR.md

Large diffs are not rendered by default.

322 changes: 322 additions & 0 deletions README.ru-RU.md

Large diffs are not rendered by default.

325 changes: 325 additions & 0 deletions README.tr-TR.md

Large diffs are not rendered by default.

312 changes: 312 additions & 0 deletions README.uk-UA.md

Large diffs are not rendered by default.

359 changes: 359 additions & 0 deletions README.uz-UZ.md

Large diffs are not rendered by default.

329 changes: 329 additions & 0 deletions README.vi-VN.md

Large diffs are not rendered by default.

28 changes: 21 additions & 7 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# JavaScript 算法与数据结构

[![build status](https://travis-ci.org/trekhleb/javascript-algorithms.svg?branch=master)](https://travis-ci.org/trekhleb/javascript-algorithms)
[![CI](https://github.com/trekhleb/javascript-algorithms/workflows/CI/badge.svg)](https://github.com/trekhleb/javascript-algorithms/actions?query=workflow%3ACI+branch%3Amaster)
[![codecov](https://codecov.io/gh/trekhleb/javascript-algorithms/branch/master/graph/badge.svg)](https://codecov.io/gh/trekhleb/javascript-algorithms)

本仓库包含了多种基于 JavaScript 的算法与数据结构。
@@ -15,7 +15,17 @@ _Read this in other languages:_
[_Polski_](README.pl-PL.md),
[_Français_](README.fr-FR.md),
[_Español_](README.es-ES.md),
[_Português_](README.pt-BR.md)
[_Português_](README.pt-BR.md),
[_Русский_](README.ru-RU.md),
[_Türk_](README.tr-TR.md),
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
[_Arabic_](README.ar-AR.md),
[_Tiếng Việt_](README.vi-VN.md),
[_Deutsch_](README.de-DE.md),
[_Uzbek_](README.uz-UZ.md)
[_עברית_](README.he-IL.md)

*注意:这个项目仅用于学习和研究,**不是**用于生产环境。*

@@ -29,7 +39,7 @@ _Read this in other languages:_
* `B` [双向链表](src/data-structures/doubly-linked-list/README.zh-CN.md)
* `B` [队列](src/data-structures/queue/README.zh-CN.md)
* `B` [](src/data-structures/stack/README.zh-CN.md)
* `B` [哈希表](src/data-structures/hash-table/README.zh-CN.md)
* `B` [哈希表(散列)](src/data-structures/hash-table/README.zh-CN.md)
* `B` [](src/data-structures/heap/README.zh-CN.md) - 最大堆 & 最小堆
* `B` [优先队列](src/data-structures/priority-queue/README.zh-CN.md)
* `A` [字典树](src/data-structures/trie/README.zh-CN.md)
@@ -52,7 +62,7 @@ _Read this in other languages:_
### 算法主题

* **数学**
* `B` [Bit 操控](src/algorithms/math/bits) - set/get/update/clear 位、乘以/除以二进制位 、变负等
* `B` [位运算](src/algorithms/math/bits) - set/get/update/clear 位、乘以/除以二进制位 、变负等
* `B` [阶乘](src/algorithms/math/factorial/README.zh-CN.md)
* `B` [斐波那契数](src/algorithms/math/fibonacci) - `经典``闭式` 版本
* `B` [素数检测](src/algorithms/math/primality-test) (排除法)
@@ -83,7 +93,7 @@ _Read this in other languages:_
* `B` [汉明距离](src/algorithms/string/hamming-distance) - 符号不同的位置数
* `A` [莱温斯坦距离](src/algorithms/string/levenshtein-distance) - 两个序列之间的最小编辑距离
* `A` [Knuth–Morris–Pratt 算法](src/algorithms/string/knuth-morris-pratt) KMP 算法 - 子串搜索 (模式匹配)
* `A` [字符串快速查找](src/algorithms/string/rabin-karp) - 子串搜索 (模式匹配)
* `A` [字符串快速查找](src/algorithms/string/z-algorithm) - 子串搜索 (模式匹配)
* `A` [Rabin Karp 算法](src/algorithms/string/rabin-karp) - 子串搜索
* `A` [最长公共子串](src/algorithms/string/longest-common-substring)
* `A` [正则表达式匹配](src/algorithms/string/regular-expression-matching)
@@ -126,6 +136,8 @@ _Read this in other languages:_
* `A` [旅行推销员问题](src/algorithms/graph/travelling-salesman) - 尽可能以最短的路线访问每个城市并返回原始城市
* **加密**
* `B` [多项式 hash](src/algorithms/cryptography/polynomial-hash) - 基于多项式的 rolling hash 函数
* **机器学习**
* `B` [NanoNeuron](https://github.com/trekhleb/nano-neuron) -7个简单的JS函数,说明机器如何实际学习(向前/向后传播)
* **未分类**
* `B` [汉诺塔](src/algorithms/uncategorized/hanoi-tower)
* `B` [旋转矩阵](src/algorithms/uncategorized/square-matrix-rotation) - 原地算法
@@ -166,7 +178,7 @@ _Read this in other languages:_
* `B` [快速算次方](src/algorithms/math/fast-powering)
* `A` [排列](src/algorithms/sets/permutations) (有/无重复)
* `A` [组合](src/algorithms/sets/combinations) (有/无重复)
* **动态编程** - 使用以前找到的子解决方案构建解决方案
* **动态规划(Dynamic programming)** - 使用以前找到的子解决方案构建解决方案
* `B` [斐波那契数](src/algorithms/math/fibonacci)
* `B` [跳跃游戏](src/algorithms/uncategorized/jump-game)
* `B` [独特路径](src/algorithms/uncategorized/unique-paths)
@@ -223,7 +235,7 @@ npm test -- 'LinkedList'

你可以在 `./src/playground/playground.js` 文件中操作数据结构与算法,并在 `./src/playground/__test__/playground.test.js` 中编写测试。

然后,只需运行以下命令来测试你的 Playground 是否按无误:
然后,只需运行以下命令来测试你的 Playground 是否无误:

```
npm test -- 'playground'
@@ -283,3 +295,5 @@ npm test -- 'playground'
| **希尔排序** | n log(n) | 取决于差距序列 | n (log(n))^2 | 1 | No | |
| **计数排序** | n + r | n + r | n + r | n + r | Yes | r - 数组里最大的数 |
| **基数排序** | n * k | n * k | n * k | n + k | Yes | k - 最长 key 的升序 |

> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
18 changes: 15 additions & 3 deletions README.zh-TW.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# JavaScript 演算法與資料結構

[![build status](https://travis-ci.org/trekhleb/javascript-algorithms.svg?branch=master)](https://travis-ci.org/trekhleb/javascript-algorithms)
[![CI](https://github.com/trekhleb/javascript-algorithms/workflows/CI/badge.svg)](https://github.com/trekhleb/javascript-algorithms/actions?query=workflow%3ACI+branch%3Amaster)
[![codecov](https://codecov.io/gh/trekhleb/javascript-algorithms/branch/master/graph/badge.svg)](https://codecov.io/gh/trekhleb/javascript-algorithms)

這個知識庫包含許多 JavaScript 的資料結構與演算法的基礎範例。
@@ -14,7 +14,17 @@ _Read this in other languages:_
[_Polski_](README.pl-PL.md),
[_Français_](README.fr-FR.md),
[_Español_](README.es-ES.md),
[_Português_](README.pt-BR.md)
[_Português_](README.pt-BR.md),
[_Русский_](README.ru-RU.md),
[_Türk_](README.tr-TR.md),
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
[_Arabic_](README.ar-AR.md),
[_Tiếng Việt_](README.vi-VN.md),
[_Deutsch_](README.de-DE.md),
[_Uzbek_](README.uz-UZ.md)
[_עברית_](README.he-IL.md)

## 資料結構

@@ -208,10 +218,12 @@ npm test -- 'playground'

| 名稱 | 最佳 | 平均 | 最差 | 記憶體 | 穩定 |
| ---------------------- | :-------: | :-------: | :-----------: | :-------: | :-------: |
| **氣派排序** | n | n^2 | n^2 | 1 | Yes |
| **氣泡排序** | n | n^2 | n^2 | 1 | Yes |
| **插入排序** | n | n^2 | n^2 | 1 | Yes |
| **選擇排序** | n^2 | n^2 | n^2 | 1 | No |
| **Heap 排序** | n log(n) | n log(n) | n log(n) | 1 | No |
| **合併排序** | n log(n) | n log(n) | n log(n) | n | Yes |
| **快速排序** | n log(n) | n log(n) | n^2 | log(n) | No |
| **希爾排序** | n log(n) | 由gap sequence決定 | n (log(n))^2 | 1 | No |

> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
14 changes: 13 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -24,5 +24,17 @@ module.exports = {
// This option sets the URL for the jsdom environment.
// It is reflected in properties such as location.href.
// @see: https://github.com/facebook/jest/issues/6769
testURL: 'http://localhost/',
testEnvironmentOptions: {
url: 'http://localhost/',
},

// @see: https://jestjs.io/docs/en/configuration#coveragethreshold-object
coverageThreshold: {
global: {
statements: 100,
branches: 95,
functions: 100,
lines: 100,
},
},
};
19,997 changes: 14,336 additions & 5,661 deletions package-lock.json

Large diffs are not rendered by default.

43 changes: 24 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -2,12 +2,6 @@
"name": "javascript-algorithms-and-data-structures",
"version": "0.0.4",
"description": "Algorithms and data-structures implemented on JavaScript",
"main": "index.js",
"scripts": {
"lint": "eslint ./src/*",
"test": "jest",
"ci": "npm run lint && npm run test -- --coverage"
},
"repository": {
"type": "git",
"url": "git+https://github.com/trekhleb/javascript-algorithms.git"
@@ -26,24 +20,35 @@
"interview",
"interview-preparation"
],
"author": "Oleksii Trekhleb (https://www.linkedin.com/in/trekhleb/)",
"author": "Oleksii Trekhleb (https://trekhleb.dev)",
"license": "MIT",
"bugs": {
"url": "https://github.com/trekhleb/javascript-algorithms/issues"
},
"homepage": "https://github.com/trekhleb/javascript-algorithms#readme",
"main": "index.js",
"scripts": {
"lint": "eslint ./src/**",
"test": "jest",
"coverage": "npm run test -- --coverage",
"ci": "npm run lint && npm run coverage",
"prepare": "husky install"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/preset-env": "^7.4.5",
"@types/jest": "^24.0.15",
"eslint": "^6.0.1",
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-jest": "^22.7.1",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-react": "^7.14.2",
"husky": "^2.5.0",
"jest": "^24.8.0"
"@babel/cli": "7.20.7",
"@babel/preset-env": "7.20.2",
"@types/jest": "29.4.0",
"eslint": "8.33.0",
"eslint-config-airbnb": "19.0.4",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-jest": "27.2.1",
"eslint-plugin-jsx-a11y": "6.7.1",
"husky": "8.0.3",
"jest": "29.4.1",
"pngjs": "^7.0.0"
},
"dependencies": {}
"engines": {
"node": ">=16.15.0",
"npm": ">=8.5.5"
}
}
33 changes: 33 additions & 0 deletions src/algorithms/cryptography/caesar-cipher/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Caesar Cipher Algorithm

_Read this in other languages:_
[_Русский_](README.ru-RU.md)

In cryptography, a **Caesar cipher**, also known as **Caesar's cipher**, the **shift cipher**, **Caesar's code** or **Caesar shift**, is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For example, with a left shift of `3`, `D` would be replaced by `A`, `E` would become `B`, and so on. The method is named after Julius Caesar, who used it in his private correspondence.

![Caesar Cipher Algorithm](https://upload.wikimedia.org/wikipedia/commons/4/4a/Caesar_cipher_left_shift_of_3.svg)

## Example

The transformation can be represented by aligning two alphabets; the cipher alphabet is the plain alphabet rotated left or right by some number of positions. For instance, here is a Caesar cipher using a left rotation of three places, equivalent to a right shift of 23 (the shift parameter is used as the key):

```text
Plain: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Cipher: XYZABCDEFGHIJKLMNOPQRSTUVW
```

When encrypting, a person looks up each letter of the message in the "plain" line and writes down the corresponding letter in the "cipher" line.

```text
Plaintext: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
Ciphertext: QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD
```

## Complexity

- Time: `O(|n|)`
- Space: `O(|n|)`

## References

- [Caesar cipher on Wikipedia](https://en.wikipedia.org/wiki/Caesar_cipher)
29 changes: 29 additions & 0 deletions src/algorithms/cryptography/caesar-cipher/README.ru-RU.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Алгоритм шифра Цезаря

В криптографии **шифр Цезаря**, также известный как **шифр сдвига**, **код Цезаря** или **сдвиг Цезаря**, является одним из самых простых и широко известных методов шифрования. Это вид шифра подстановки, в котором каждый символ в открытом тексте заменяется символом, находящимся на некотором постоянном числе позиций левее или правее него в алфавите. Например, в шифре со сдвигом вправо на `3`, `D` была бы заменена на `A`, `E` станет `B`, и так далее. Метод назван в честь Юлия Цезаря, который использовал его в своей личной переписке.

![Алгоритм шифра Цезаря](https://upload.wikimedia.org/wikipedia/commons/4/4a/Caesar_cipher_left_shift_of_3.svg)

## Пример
Это преобразование можно представить как выравнивание двух алфавитов; алфавит шифра - это обычный алфавит, повёрнутый влево или вправо на некоторое количество позиций. Например, здесь приведен шифр Цезаря, использующий поворот влево на три позиции, что эквивалентно сдвигу вправо на 23 (параметр сдвига используется в качестве ключа):

```text
Обычный: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Шифрованный: XYZABCDEFGHIJKLMNOPQRSTUVW
```

При шифровании человек просматривает каждую букву сообщения в "открытой" строке и записывает соответствующую букву в "шифрованной" строке.

```text
Обычный текст: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
Шифрованный текст: QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD
```

## Сложность

- Время: `O(|n|)`
- Пространство: `O(|n|)`

## Ссылки

- [Шифр Цезаря на Wikipedia](https://ru.wikipedia.org/wiki/Шифр_Цезаря)
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { caesarCipherEncrypt, caesarCipherDecrypt } from '../caesarCipher';

describe('caesarCipher', () => {
it('should not change a string with zero shift', () => {
expect(caesarCipherEncrypt('abcd', 0)).toBe('abcd');
expect(caesarCipherDecrypt('abcd', 0)).toBe('abcd');
});

it('should cipher a string with different shifts', () => {
expect(caesarCipherEncrypt('abcde', 3)).toBe('defgh');
expect(caesarCipherDecrypt('defgh', 3)).toBe('abcde');

expect(caesarCipherEncrypt('abcde', 1)).toBe('bcdef');
expect(caesarCipherDecrypt('bcdef', 1)).toBe('abcde');

expect(caesarCipherEncrypt('xyz', 1)).toBe('yza');
expect(caesarCipherDecrypt('yza', 1)).toBe('xyz');
});

it('should be case insensitive', () => {
expect(caesarCipherEncrypt('ABCDE', 3)).toBe('defgh');
});

it('should correctly handle an empty strings', () => {
expect(caesarCipherEncrypt('', 3)).toBe('');
});

it('should not cipher unknown chars', () => {
expect(caesarCipherEncrypt('ab2cde', 3)).toBe('de2fgh');
expect(caesarCipherDecrypt('de2fgh', 3)).toBe('ab2cde');
});

it('should encrypt and decrypt full phrases', () => {
expect(caesarCipherEncrypt('THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG', 23))
.toBe('qeb nrfzh yoltk clu grjmp lsbo qeb ixwv ald');

expect(caesarCipherDecrypt('qeb nrfzh yoltk clu grjmp lsbo qeb ixwv ald', 23))
.toBe('the quick brown fox jumps over the lazy dog');
});
});
58 changes: 58 additions & 0 deletions src/algorithms/cryptography/caesar-cipher/caesarCipher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Create alphabet array: ['a', 'b', 'c', ..., 'z'].
const englishAlphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');

/**
* Generates a cipher map out of the alphabet.
* Example with a shift 3: {'a': 'd', 'b': 'e', 'c': 'f', ...}
*
* @param {string[]} alphabet - i.e. ['a', 'b', 'c', ... , 'z']
* @param {number} shift - i.e. 3
* @return {Object} - i.e. {'a': 'd', 'b': 'e', 'c': 'f', ..., 'z': 'c'}
*/
const getCipherMap = (alphabet, shift) => {
return alphabet
.reduce((charsMap, currentChar, charIndex) => {
const charsMapClone = { ...charsMap };
// Making the shift to be cyclic (i.e. with a shift of 1 - 'z' would be mapped to 'a').
let encryptedCharIndex = (charIndex + shift) % alphabet.length;
// Support negative shifts for creating a map for decryption
// (i.e. with shift -1 - 'a' would be mapped to 'z').
if (encryptedCharIndex < 0) {
encryptedCharIndex += alphabet.length;
}
charsMapClone[currentChar] = alphabet[encryptedCharIndex];
return charsMapClone;
}, {});
};

/**
* @param {string} str
* @param {number} shift
* @param {string[]} alphabet
* @return {string}
*/
export const caesarCipherEncrypt = (str, shift, alphabet = englishAlphabet) => {
// Create a cipher map:
const cipherMap = getCipherMap(alphabet, shift);
return str
.toLowerCase()
.split('')
.map((char) => cipherMap[char] || char)
.join('');
};

/**
* @param {string} str
* @param {number} shift
* @param {string[]} alphabet
* @return {string}
*/
export const caesarCipherDecrypt = (str, shift, alphabet = englishAlphabet) => {
// Create a cipher map:
const cipherMap = getCipherMap(alphabet, -shift);
return str
.toLowerCase()
.split('')
.map((char) => cipherMap[char] || char)
.join('');
};
96 changes: 96 additions & 0 deletions src/algorithms/cryptography/hill-cipher/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Hill Cipher

The **Hill cipher** is a [polygraphic substitution](https://en.wikipedia.org/wiki/Polygraphic_substitution) cipher based on linear algebra.

Each letter is represented by a number [modulo](https://en.wikipedia.org/wiki/Modular_arithmetic) `26`. Though this is not an essential feature of the cipher, this simple scheme is often used:

| **Letter** | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
| ------ | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| **Number** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |

## Encryption

To encrypt a message, each block of `n` letters (considered as an `n`-component vector) is multiplied by an invertible `n × n` matrix, against modulus `26`.

The matrix used for encryption is the _cipher key_, and it should be chosen randomly from the set of invertible `n × n` matrices (modulo `26`). The cipher can, of course, be adapted to an alphabet with any number of letters; all arithmetic just needs to be done modulo the number of letters instead of modulo `26`.

Consider the message `ACT`, and the key below (or `GYB/NQK/URP` in letters):

```
| 6 24 1 |
| 13 16 10 |
| 20 17 15 |
```

Since `A` is`0`, `C` is `2` and `T` is `19`, the message is the vector:

```
| 0 |
| 2 |
| 19 |
```

Thus, the enciphered vector is given by:

```
| 6 24 1 | | 0 | | 67 | | 15 |
| 13 16 10 | | 2 | = | 222 | ≡ | 14 | (mod 26)
| 20 17 15 | | 19 | | 319 | | 7 |
```

which corresponds to a ciphertext of `POH`.

Now, suppose that our message is instead `CAT` (notice how we're using the same letters as in `ACT` here), or:

```
| 2 |
| 0 |
| 19 |
```

This time, the enciphered vector is given by:

```
| 6 24 1 | | 2 | | 31 | | 5 |
| 13 16 10 | | 0 | = | 216 | ≡ | 8 | (mod 26)
| 20 17 15 | | 19 | | 325 | | 13 |
```

which corresponds to a ciphertext of `FIN`. Every letter has changed.

## Decryption

To decrypt the message, each block is multiplied by the inverse of the matrix used for encryption. We turn the ciphertext back into a vector, then simply multiply by the inverse matrix of the key matrix (`IFK/VIV/VMI` in letters). (See [matrix inversion](https://en.wikipedia.org/wiki/Matrix_inversion) for methods to calculate the inverse matrix.) We find that, modulo 26, the inverse of the matrix used in the previous example is:

```
-1
| 6 24 1 | | 8 5 10 |
| 13 16 10 | (mod 26) ≡ | 21 8 21 |
| 20 17 15 | | 21 12 8 |
```

Taking the previous example ciphertext of `POH`, we get:

```
| 8 5 10 | | 15 | | 260 | | 0 |
| 21 8 21 | | 14 | = | 574 | ≡ | 2 | (mod 26)
| 21 12 8 | | 7 | | 539 | | 19 |
```

which gets us back to `ACT`, as expected.

## Defining the encrypting matrix

Two complications exist in picking the encrypting matrix:

1. Not all matrices have an inverse. The matrix will have an inverse if and only if its [determinant](https://en.wikipedia.org/wiki/Determinant) is not zero.
2. The determinant of the encrypting matrix must not have any common factors with the modular base.

Thus, if we work modulo `26` as above, the determinant must be nonzero, and must not be divisible by `2` or `13`. If the determinant is `0`, or has common factors with the modular base, then the matrix cannot be used in the Hill cipher, and another matrix must be chosen (otherwise it will not be possible to decrypt). Fortunately, matrices which satisfy the conditions to be used in the Hill cipher are fairly common.

## References

- [Hill cipher on Wikipedia](https://en.wikipedia.org/wiki/Hill_cipher)
- [Matrix inversion on MathIsFun](https://www.mathsisfun.com/algebra/matrix-inverse.html)
- [GeeksForGeeks](https://www.geeksforgeeks.org/hill-cipher/)

46 changes: 46 additions & 0 deletions src/algorithms/cryptography/hill-cipher/_test_/hillCipher.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { hillCipherEncrypt, hillCipherDecrypt } from '../hillCipher';

describe('hillCipher', () => {
it('should throw an exception when trying to decipher', () => {
expect(hillCipherDecrypt).toThrowError('This method is not implemented yet');
});

it('should throw an error when message or keyString contains none letter character', () => {
const invalidCharacterInMessage = () => {
hillCipherEncrypt('hell3', 'helloworld');
};
const invalidCharacterInKeyString = () => {
hillCipherEncrypt('hello', 'hel12world');
};
expect(invalidCharacterInMessage).toThrowError(
'The message and key string can only contain letters',
);
expect(invalidCharacterInKeyString).toThrowError(
'The message and key string can only contain letters',
);
});

it('should throw an error when the length of the keyString has a square root which is not integer', () => {
const invalidLengthOfKeyString = () => {
hillCipherEncrypt('ab', 'ab');
};
expect(invalidLengthOfKeyString).toThrowError(
'Invalid key string length. The square root of the key string must be an integer',
);
});

it('should throw an error when the length of the keyString does not equal to the power of length of the message', () => {
const invalidLengthOfKeyString = () => {
hillCipherEncrypt('ab', 'aaabbbccc');
};
expect(invalidLengthOfKeyString).toThrowError(
'Invalid key string length. The key length must be a square of message length',
);
});

it('should encrypt passed message using Hill Cipher', () => {
expect(hillCipherEncrypt('ACT', 'GYBNQKURP')).toBe('POH');
expect(hillCipherEncrypt('CAT', 'GYBNQKURP')).toBe('FIN');
expect(hillCipherEncrypt('GFG', 'HILLMAGIC')).toBe('SWK');
});
});
87 changes: 87 additions & 0 deletions src/algorithms/cryptography/hill-cipher/hillCipher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import * as mtrx from '../../math/matrix/Matrix';

// The code of an 'A' character (equals to 65).
const alphabetCodeShift = 'A'.codePointAt(0);
const englishAlphabetSize = 26;

/**
* Generates key matrix from given keyString.
*
* @param {string} keyString - a string to build a key matrix (must be of matrixSize^2 length).
* @return {number[][]} keyMatrix
*/
const generateKeyMatrix = (keyString) => {
const matrixSize = Math.sqrt(keyString.length);
if (!Number.isInteger(matrixSize)) {
throw new Error(
'Invalid key string length. The square root of the key string must be an integer',
);
}
let keyStringIndex = 0;
return mtrx.generate(
[matrixSize, matrixSize],
// Callback to get a value of each matrix cell.
// The order the matrix is being filled in is from left to right, from top to bottom.
() => {
// A → 0, B → 1, ..., a → 32, b → 33, ...
const charCodeShifted = (keyString.codePointAt(keyStringIndex)) % alphabetCodeShift;
keyStringIndex += 1;
return charCodeShifted;
},
);
};

/**
* Generates a message vector from a given message.
*
* @param {string} message - the message to encrypt.
* @return {number[][]} messageVector
*/
const generateMessageVector = (message) => {
return mtrx.generate(
[message.length, 1],
// Callback to get a value of each matrix cell.
// The order the matrix is being filled in is from left to right, from top to bottom.
(cellIndices) => {
const rowIndex = cellIndices[0];
return message.codePointAt(rowIndex) % alphabetCodeShift;
},
);
};

/**
* Encrypts the given message using Hill Cipher.
*
* @param {string} message plaintext
* @param {string} keyString
* @return {string} cipherString
*/
export function hillCipherEncrypt(message, keyString) {
// The keyString and message can only contain letters.
const onlyLettersRegExp = /^[a-zA-Z]+$/;
if (!onlyLettersRegExp.test(message) || !onlyLettersRegExp.test(keyString)) {
throw new Error('The message and key string can only contain letters');
}

const keyMatrix = generateKeyMatrix(keyString);
const messageVector = generateMessageVector(message);

// keyString.length must equal to square of message.length
if (keyMatrix.length !== message.length) {
throw new Error('Invalid key string length. The key length must be a square of message length');
}

const cipherVector = mtrx.dot(keyMatrix, messageVector);
let cipherString = '';
for (let row = 0; row < cipherVector.length; row += 1) {
const item = cipherVector[row];
cipherString += String.fromCharCode((item % englishAlphabetSize) + alphabetCodeShift);
}

return cipherString;
}

// @TODO: Implement this method.
export const hillCipherDecrypt = () => {
throw new Error('This method is not implemented yet');
};
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ export default class PolynomialHash {
* @return {number}
*/
hash(word) {
const charCodes = Array.from(word).map(char => this.charToNumber(char));
const charCodes = Array.from(word).map((char) => this.charToNumber(char));

let hash = 0;
for (let charIndex = 0; charIndex < charCodes.length; charIndex += 1) {
28 changes: 28 additions & 0 deletions src/algorithms/cryptography/rail-fence-cipher/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Rail Fence Cipher

The **rail fence cipher** (also called a **zigzag cipher**) is a [transposition cipher](https://en.wikipedia.org/wiki/Transposition_cipher) in which the message is split across a set of rails on a fence for encoding. The fence is populated with the message's characters, starting at the top left and adding a character on each position, traversing them diagonally to the bottom. Upon reaching the last rail, the direction should then turn diagonal and upwards up to the very first rail in a zig-zag motion. Rinse and repeat until the message is fully disposed across the fence. The encoded message is the result of concatenating the text in each rail, from top to bottom.

From [wikipedia](https://en.wikipedia.org/wiki/Rail_fence_cipher), this is what the message `WE ARE DISCOVERED. FLEE AT ONCE` looks like on a `3`-rail fence:

```
W . . . E . . . C . . . R . . . L . . . T . . . E
. E . R . D . S . O . E . E . F . E . A . O . C .
. . A . . . I . . . V . . . D . . . E . . . N . .
-------------------------------------------------
WECRLTEERDSOEEFEAOCAIVDEN
```

The message can then be decoded by re-creating the encoded fence, with the same traversal pattern, except characters should only be added on one rail at a time. To illustrate that, a dash can be added on the rails that are not supposed to be populated yet. This is what the fence would look like after populating the first rail, the dashes represent positions that were visited but not populated.

```
W . . . E . . . C . . . R . . . L . . . T . . . E
. - . - . - . - . - . - . - . - . - . - . - . - .
. . - . . . - . . . - . . . - . . . - . . . - . .
```

It's time to start populating the next rail once the number of visited fence positions is equal to the number of characters in the message.

## References

- [Rail Fence Cipher on Wikipedia](https://en.wikipedia.org/wiki/Rail_fence_cipher)
- [Rail Fence Cipher Calculator](https://crypto.interactive-maths.com/rail-fence-cipher.html)
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { encodeRailFenceCipher, decodeRailFenceCipher } from '../railFenceCipher';

describe('railFenceCipher', () => {
it('encodes a string correctly for base=3', () => {
expect(encodeRailFenceCipher('', 3)).toBe('');
expect(encodeRailFenceCipher('12345', 3)).toBe(
'15243',
);
expect(encodeRailFenceCipher('WEAREDISCOVEREDFLEEATONCE', 3)).toBe(
'WECRLTEERDSOEEFEAOCAIVDEN',
);
expect(encodeRailFenceCipher('Hello, World!', 3)).toBe(
'Hoo!el,Wrdl l',
);
});

it('decodes a string correctly for base=3', () => {
expect(decodeRailFenceCipher('', 3)).toBe('');
expect(decodeRailFenceCipher('WECRLTEERDSOEEFEAOCAIVDEN', 3)).toBe(
'WEAREDISCOVEREDFLEEATONCE',
);
expect(decodeRailFenceCipher('Hoo!el,Wrdl l', 3)).toBe(
'Hello, World!',
);
expect(decodeRailFenceCipher('15243', 3)).toBe(
'12345',
);
});

it('encodes a string correctly for base=4', () => {
expect(encodeRailFenceCipher('', 4)).toBe('');
expect(encodeRailFenceCipher('THEYAREATTACKINGFROMTHENORTH', 4)).toBe(
'TEKOOHRACIRMNREATANFTETYTGHH',
);
});

it('decodes a string correctly for base=4', () => {
expect(decodeRailFenceCipher('', 4)).toBe('');
expect(decodeRailFenceCipher('TEKOOHRACIRMNREATANFTETYTGHH', 4)).toBe(
'THEYAREATTACKINGFROMTHENORTH',
);
});
});
242 changes: 242 additions & 0 deletions src/algorithms/cryptography/rail-fence-cipher/railFenceCipher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
/**
* @typedef {string[]} Rail
* @typedef {Rail[]} Fence
* @typedef {number} Direction
*/

/**
* @constant DIRECTIONS
* @type {object}
* @property {Direction} UP
* @property {Direction} DOWN
*/
const DIRECTIONS = { UP: -1, DOWN: 1 };

/**
* Builds a fence with a specific number of rows.
*
* @param {number} rowsNum
* @returns {Fence}
*/
const buildFence = (rowsNum) => Array(rowsNum)
.fill(null)
.map(() => []);

/**
* Get next direction to move (based on the current one) while traversing the fence.
*
* @param {object} params
* @param {number} params.railCount - Number of rows in the fence
* @param {number} params.currentRail - Current row that we're visiting
* @param {Direction} params.direction - Current direction
* @returns {Direction} - The next direction to take
*/
const getNextDirection = ({ railCount, currentRail, direction }) => {
switch (currentRail) {
case 0:
// Go down if we're on top of the fence.
return DIRECTIONS.DOWN;
case railCount - 1:
// Go up if we're at the bottom of the fence.
return DIRECTIONS.UP;
default:
// Continue with the same direction if we're in the middle of the fence.
return direction;
}
};

/**
* @param {number} targetRailIndex
* @param {string} letter
* @returns {Function}
*/
const addCharToRail = (targetRailIndex, letter) => {
/**
* Given a rail, adds a char to it if it matches a targetIndex.
*
* @param {Rail} rail
* @param {number} currentRail
* @returns {Rail}
*/
function onEachRail(rail, currentRail) {
return currentRail === targetRailIndex
? [...rail, letter]
: rail;
}
return onEachRail;
};

/**
* Hangs the characters on the fence.
*
* @param {object} params
* @param {Fence} params.fence
* @param {number} params.currentRail
* @param {Direction} params.direction
* @param {string[]} params.chars
* @returns {Fence}
*/
const fillEncodeFence = ({
fence,
currentRail,
direction,
chars,
}) => {
if (chars.length === 0) {
// All chars have been placed on a fence.
return fence;
}

const railCount = fence.length;

// Getting the next character to place on a fence.
const [letter, ...nextChars] = chars;
const nextDirection = getNextDirection({
railCount,
currentRail,
direction,
});

return fillEncodeFence({
fence: fence.map(addCharToRail(currentRail, letter)),
currentRail: currentRail + nextDirection,
direction: nextDirection,
chars: nextChars,
});
};

/**
* @param {object} params
* @param {number} params.strLen
* @param {string[]} params.chars
* @param {Fence} params.fence
* @param {number} params.targetRail
* @param {Direction} params.direction
* @param {number[]} params.coords
* @returns {Fence}
*/
const fillDecodeFence = (params) => {
const {
strLen, chars, fence, targetRail, direction, coords,
} = params;

const railCount = fence.length;

if (chars.length === 0) {
return fence;
}

const [currentRail, currentColumn] = coords;
const shouldGoNextRail = currentColumn === strLen - 1;
const nextDirection = shouldGoNextRail
? DIRECTIONS.DOWN
: getNextDirection(
{ railCount, currentRail, direction },
);
const nextRail = shouldGoNextRail ? targetRail + 1 : targetRail;
const nextCoords = [
shouldGoNextRail ? 0 : currentRail + nextDirection,
shouldGoNextRail ? 0 : currentColumn + 1,
];

const shouldAddChar = currentRail === targetRail;
const [currentChar, ...remainderChars] = chars;
const nextString = shouldAddChar ? remainderChars : chars;
const nextFence = shouldAddChar ? fence.map(addCharToRail(currentRail, currentChar)) : fence;

return fillDecodeFence({
strLen,
chars: nextString,
fence: nextFence,
targetRail: nextRail,
direction: nextDirection,
coords: nextCoords,
});
};

/**
* @param {object} params
* @param {number} params.strLen
* @param {Fence} params.fence
* @param {number} params.currentRail
* @param {Direction} params.direction
* @param {number[]} params.code
* @returns {string}
*/
const decodeFence = (params) => {
const {
strLen,
fence,
currentRail,
direction,
code,
} = params;

if (code.length === strLen) {
return code.join('');
}

const railCount = fence.length;

const [currentChar, ...nextRail] = fence[currentRail];
const nextDirection = getNextDirection(
{ railCount, currentRail, direction },
);

return decodeFence({
railCount,
strLen,
currentRail: currentRail + nextDirection,
direction: nextDirection,
code: [...code, currentChar],
fence: fence.map((rail, idx) => (idx === currentRail ? nextRail : rail)),
});
};

/**
* Encodes the message using Rail Fence Cipher.
*
* @param {string} string - The string to be encoded
* @param {number} railCount - The number of rails in a fence
* @returns {string} - Encoded string
*/
export const encodeRailFenceCipher = (string, railCount) => {
const fence = buildFence(railCount);

const filledFence = fillEncodeFence({
fence,
currentRail: 0,
direction: DIRECTIONS.DOWN,
chars: string.split(''),
});

return filledFence.flat().join('');
};

/**
* Decodes the message using Rail Fence Cipher.
*
* @param {string} string - Encoded string
* @param {number} railCount - The number of rows in a fence
* @returns {string} - Decoded string.
*/
export const decodeRailFenceCipher = (string, railCount) => {
const strLen = string.length;
const emptyFence = buildFence(railCount);
const filledFence = fillDecodeFence({
strLen,
chars: string.split(''),
fence: emptyFence,
targetRail: 0,
direction: DIRECTIONS.DOWN,
coords: [0, 0],
});

return decodeFence({
strLen,
fence: filledFence,
currentRail: 0,
direction: DIRECTIONS.DOWN,
code: [],
});
};
Original file line number Diff line number Diff line change
@@ -66,7 +66,7 @@ export default function articulationPoints(graph) {
// Get minimum low discovery time from all neighbors.
/** @param {GraphVertex} neighbor */
visitedSet[currentVertex.getKey()].lowDiscoveryTime = currentVertex.getNeighbors()
.filter(earlyNeighbor => earlyNeighbor.getKey() !== previousVertex.getKey())
.filter((earlyNeighbor) => earlyNeighbor.getKey() !== previousVertex.getKey())
/**
* @param {number} lowestDiscoveryTime
* @param {GraphVertex} neighbor
4 changes: 2 additions & 2 deletions src/algorithms/graph/breadth-first-search/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Breadth-First Search (BFS)

Breadth-first search (BFS) is an algorithm for traversing
or searching tree or graph data structures. It starts at
Breadth-first search (BFS) is an algorithm for traversing,
searching tree, or graph data structures. It starts at
the tree root (or some arbitrary node of a graph, sometimes
referred to as a 'search key') and explores the neighbor
nodes first, before moving to the next level neighbors.
2 changes: 1 addition & 1 deletion src/algorithms/graph/bridges/graphBridges.js
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ export default function graphBridges(graph) {

// Check if current node is connected to any early node other then previous one.
visitedSet[currentVertex.getKey()].lowDiscoveryTime = currentVertex.getNeighbors()
.filter(earlyNeighbor => earlyNeighbor.getKey() !== previousVertex.getKey())
.filter((earlyNeighbor) => earlyNeighbor.getKey() !== previousVertex.getKey())
.reduce(
/**
* @param {number} lowestDiscoveryTime
Original file line number Diff line number Diff line change
@@ -8,9 +8,9 @@ import DisjointSet from '../../../data-structures/disjoint-set/DisjointSet';
export default function detectUndirectedCycleUsingDisjointSet(graph) {
// Create initial singleton disjoint sets for each graph vertex.
/** @param {GraphVertex} graphVertex */
const keyExtractor = graphVertex => graphVertex.getKey();
const keyExtractor = (graphVertex) => graphVertex.getKey();
const disjointSet = new DisjointSet(keyExtractor);
graph.getAllVertices().forEach(graphVertex => disjointSet.makeSet(graphVertex));
graph.getAllVertices().forEach((graphVertex) => disjointSet.makeSet(graphVertex));

// Go trough all graph edges one by one and check if edge vertices are from the
// different sets. In this case joint those sets together. Do this until you find
16 changes: 16 additions & 0 deletions src/algorithms/graph/dijkstra/README.ko-KR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 다익스트라 알고리즘(Dijkstra's algorithm)

다익스트라 알고리즘은 도로 네트워크 등을 나타낼 수 있는 그래프에서 노드 간의 최단 경로를 찾는 알고리즘입니다.

이 알고리즘은 다양한 형태로 존재합니다. 다익스트라의 원래 형태는 두 노드 간의 최단 경로를 찾았지만, 더 일반적인 형태는 단일 노드를 "소스"노드로 수정하고 그래프의 소스에서 다른 모든 노드까지의 최단 경로를 찾아 최단 경로 트리(shortest-path tree)를 생성합니다.

![Dijkstra](https://upload.wikimedia.org/wikipedia/commons/5/57/Dijkstra_Animation.gif)

`a``b` 사이의 최단 경로를 찾는 다익스트라 알고리즘입니다.
가장 낮은 거리를 가지며 방문하지 않은 정점(vertex)를 선택하고, 이를 통해 방문하지 않은 각 이웃까지의 거리를 계산하며, 더 작은 경우 이웃의 거리를 업데이트합니다. 이웃에 대한 작업을 마치면 방문한 것으로 표시(빨간색으로 변경)합니다.

## 참조

- [Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)
- [On YouTube by Nathaniel Fan](https://www.youtube.com/watch?v=gdmfOwyQlcI&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
- [On YouTube by Tushar Roy](https://www.youtube.com/watch?v=lAXZGERcDf4&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
3 changes: 3 additions & 0 deletions src/algorithms/graph/dijkstra/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Dijkstra's Algorithm

_Read this in other languages:_
[_한국어_](README.ko-KR.md)

Dijkstra's algorithm is an algorithm for finding the shortest
paths between nodes in a graph, which may represent, for example,
road networks.
2 changes: 1 addition & 1 deletion src/algorithms/graph/eulerian-path/eulerianPath.js
Original file line number Diff line number Diff line change
@@ -75,7 +75,7 @@ export default function eulerianPath(graph) {
[edgeToDelete] = currentEdges;
} else {
// If there are many edges left then we need to peek any of those except bridges.
[edgeToDelete] = currentEdges.filter(edge => !bridges[edge.getKey()]);
[edgeToDelete] = currentEdges.filter((edge) => !bridges[edge.getKey()]);
}

// Detect next current vertex.
4 changes: 2 additions & 2 deletions src/algorithms/graph/hamiltonian-cycle/hamiltonianCycle.js
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ function isSafe(adjacencyMatrix, verticesIndices, cycle, vertexCandidate) {
}

// Check if vertexCandidate is being added to the path for the first time.
const candidateDuplicate = cycle.find(vertex => vertex.getKey() === vertexCandidate.getKey());
const candidateDuplicate = cycle.find((vertex) => vertex.getKey() === vertexCandidate.getKey());

return !candidateDuplicate;
}
@@ -61,7 +61,7 @@ function hamiltonianCycleRecursive({
cycle,
}) {
// Clone cycle in order to prevent it from modification by other DFS branches.
const currentCycle = [...cycle].map(vertex => new GraphVertex(vertex.value));
const currentCycle = [...cycle].map((vertex) => new GraphVertex(vertex.value));

if (vertices.length === currentCycle.length) {
// Hamiltonian path is found.
29 changes: 29 additions & 0 deletions src/algorithms/graph/kruskal/README.ko-KR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 크루스칼 알고리즘

크루스칼 알고리즘은 두 트리를 연결하는 최소 간선 가중치를 찾는 최소 신장 트리 알고리즘입니다.
각 단계에서 비용을 더하는 연결된 가중 그래프에 대한 최소 신장 트리를 찾기 때문에 그래프 이론에서의 그리디 알고리즘입니다. 즉, 트리의 모든 간선의 총 가중치가 최소화되는 모든 정점을 포함하는 트리를 형성하는 간선의 하위 집합을 찾습니다. 그래프가 연결되어 있지 않으면 최소 신장 포레스트(연결된 각 구성 요소의 최소 신장 트리)를 찾습니다.

![Kruskal Algorithm](https://upload.wikimedia.org/wikipedia/commons/5/5c/MST_kruskal_en.gif)

![Kruskal Demo](https://upload.wikimedia.org/wikipedia/commons/b/bb/KruskalDemo.gif)

유클리드 거리를 기반으로 한 크루스칼 알고리즘의 데모입니다.

## 최소 신장 트리

**최소 신장 트리(MST)** 또는 최소 가중치 신장 트리는 연결된 간선 가중치 무 방향 그래프의 간선의 하위 집합으로, 사이클 없이 가능한 최소 총 간선 가중치로 모든 정점을 연결합니다. 즉, 간선 가중치의 합이 가능한 작은 신장 트리입니다. 보다 일반적으로, 간선-가중치 비방향 그래프(꼭 연결되지는 않음)에는 연결된 구성 요소에 대한 최소 신장 트리의 결합인 최소 신장 포레스트(minimum spanning forest)가 있습니다.

![Minimum Spanning Tree](https://upload.wikimedia.org/wikipedia/commons/d/d2/Minimum_spanning_tree.svg)

평면 그래프와 해당 최소 신장 트리입니다. 각 간선은 가중치로 레이블이 지정되며, 이 값은 길이에 거의 비례합니다.

![Minimum Spanning Tree](https://upload.wikimedia.org/wikipedia/commons/c/c9/Multiple_minimum_spanning_trees.svg)

이 그림은 그래프에 최소 신장 트리가 두 개 이상 있을 수 있음을 보여 줍니다. 그림에서 그래프 아래의 두 트리는 주어진 그래프에서 최소 신장 트리가 될 수 있는 두 가지 경우입니다.

## 참조

- [Minimum Spanning Tree on Wikipedia](https://en.wikipedia.org/wiki/Minimum_spanning_tree)
- [Kruskal's Algorithm on Wikipedia](https://en.wikipedia.org/wiki/Kruskal%27s_algorithm)
- [Kruskal's Algorithm on YouTube by Tushar Roy](https://www.youtube.com/watch?v=fAuF0EuZVCk&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
- [Kruskal's Algorithm on YouTube by Michael Sambol](https://www.youtube.com/watch?v=71UQH7Pr9kU&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
3 changes: 3 additions & 0 deletions src/algorithms/graph/kruskal/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Kruskal's Algorithm

_Read this in other languages:_
[_한국어_](README.ko-KR.md)

Kruskal's algorithm is a minimum-spanning-tree algorithm which
finds an edge of the least possible weight that connects any two
trees in the forest. It is a greedy algorithm in graph theory
2 changes: 1 addition & 1 deletion src/algorithms/graph/kruskal/kruskal.js
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ export default function kruskal(graph) {
const sortedEdges = new QuickSort(sortingCallbacks).sort(graph.getAllEdges());

// Create disjoint sets for all graph vertices.
const keyCallback = graphVertex => graphVertex.getKey();
const keyCallback = (graphVertex) => graphVertex.getKey();
const disjointSet = new DisjointSet(keyCallback);

graph.getAllVertices().forEach((graphVertex) => {
509 changes: 509 additions & 0 deletions src/algorithms/image-processing/seam-carving/README.md

Large diffs are not rendered by default.

509 changes: 509 additions & 0 deletions src/algorithms/image-processing/seam-carving/README.ru-RU.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import fs from 'fs';
import { PNG } from 'pngjs';

import resizeImageWidth from '../resizeImageWidth';

const testImageBeforePath = './src/algorithms/image-processing/seam-carving/__tests__/test-image-before.png';
const testImageAfterPath = './src/algorithms/image-processing/seam-carving/__tests__/test-image-after.png';

/**
* Compares two images and finds the number of different pixels.
*
* @param {ImageData} imgA - ImageData for the first image.
* @param {ImageData} imgB - ImageData for the second image.
* @param {number} threshold - Color difference threshold [0..255]. Smaller - stricter.
* @returns {number} - Number of different pixels.
*/
function pixelsDiff(imgA, imgB, threshold = 0) {
if (imgA.width !== imgB.width || imgA.height !== imgB.height) {
throw new Error('Images must have the same size');
}

let differentPixels = 0;
const numColorParams = 4; // RGBA

for (let pixelIndex = 0; pixelIndex < imgA.data.length; pixelIndex += numColorParams) {
// Get pixel's color for each image.
const [aR, aG, aB] = imgA.data.subarray(pixelIndex, pixelIndex + numColorParams);
const [bR, bG, bB] = imgB.data.subarray(pixelIndex, pixelIndex + numColorParams);

// Get average pixel's color for each image (make them greyscale).
const aAvgColor = Math.floor((aR + aG + aB) / 3);
const bAvgColor = Math.floor((bR + bG + bB) / 3);

// Compare pixel colors.
if (Math.abs(aAvgColor - bAvgColor) > threshold) {
differentPixels += 1;
}
}

return differentPixels;
}

const pngLoad = (path) => new Promise((resolve) => {
fs.createReadStream(path)
.pipe(new PNG())
.on('parsed', function Parsed() {
/** @type {ImageData} */
const imageData = {
colorSpace: 'srgb',
width: this.width,
height: this.height,
data: this.data,
};
resolve(imageData);
});
});

describe('resizeImageWidth', () => {
it('should perform content-aware image width reduction', async () => {
const imgBefore = await pngLoad(testImageBeforePath);
const imgAfter = await pngLoad(testImageAfterPath);

const toWidth = Math.floor(imgBefore.width / 2);

const {
img: imgResized,
size: resizedSize,
} = resizeImageWidth({ img: imgBefore, toWidth });

expect(imgResized).toBeDefined();
expect(resizedSize).toBeDefined();

expect(resizedSize).toEqual({ w: toWidth, h: imgBefore.height });
expect(imgResized.width).toBe(imgAfter.width);
expect(imgResized.height).toBe(imgAfter.height);

const colorThreshold = 50;
const differentPixels = pixelsDiff(imgResized, imgAfter, colorThreshold);

// Allow 10% of pixels to be different
const pixelsThreshold = Math.floor((imgAfter.width * imgAfter.height) / 10);

expect(differentPixels).toBeLessThanOrEqual(pixelsThreshold);
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
253 changes: 253 additions & 0 deletions src/algorithms/image-processing/seam-carving/resizeImageWidth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import { getPixel, setPixel } from '../utils/imageData';

/**
* The seam is a sequence of pixels (coordinates).
* @typedef {PixelCoordinate[]} Seam
*/

/**
* Energy map is a 2D array that has the same width and height
* as the image the map is being calculated for.
* @typedef {number[][]} EnergyMap
*/

/**
* The metadata for the pixels in the seam.
* @typedef {Object} SeamPixelMeta
* @property {number} energy - the energy of the pixel.
* @property {PixelCoordinate} coordinate - the coordinate of the pixel.
* @property {?PixelCoordinate} previous - the previous pixel in a seam.
*/

/**
* Type that describes the image size (width and height)
* @typedef {Object} ImageSize
* @property {number} w - image width.
* @property {number} h - image height.
*/

/**
* @typedef {Object} ResizeImageWidthArgs
* @property {ImageData} img - image data we want to resize.
* @property {number} toWidth - final image width we want the image to shrink to.
*/

/**
* @typedef {Object} ResizeImageWidthResult
* @property {ImageData} img - resized image data.
* @property {ImageSize} size - resized image size.
*/

/**
* Helper function that creates a matrix (2D array) of specific
* size (w x h) and fills it with specified value.
* @param {number} w
* @param {number} h
* @param {?(number | SeamPixelMeta)} filler
* @returns {?(number | SeamPixelMeta)[][]}
*/
const matrix = (w, h, filler) => {
return new Array(h)
.fill(null)
.map(() => {
return new Array(w).fill(filler);
});
};

/**
* Calculates the energy of a pixel.
* @param {?PixelColor} left
* @param {PixelColor} middle
* @param {?PixelColor} right
* @returns {number}
*/
const getPixelEnergy = (left, middle, right) => {
// Middle pixel is the pixel we're calculating the energy for.
const [mR, mG, mB] = middle;

// Energy from the left pixel (if it exists).
let lEnergy = 0;
if (left) {
const [lR, lG, lB] = left;
lEnergy = (lR - mR) ** 2 + (lG - mG) ** 2 + (lB - mB) ** 2;
}

// Energy from the right pixel (if it exists).
let rEnergy = 0;
if (right) {
const [rR, rG, rB] = right;
rEnergy = (rR - mR) ** 2 + (rG - mG) ** 2 + (rB - mB) ** 2;
}

// Resulting pixel energy.
return Math.sqrt(lEnergy + rEnergy);
};

/**
* Calculates the energy of each pixel of the image.
* @param {ImageData} img
* @param {ImageSize} size
* @returns {EnergyMap}
*/
const calculateEnergyMap = (img, { w, h }) => {
// Create an empty energy map where each pixel has infinitely high energy.
// We will update the energy of each pixel.
const energyMap = matrix(w, h, Infinity);
for (let y = 0; y < h; y += 1) {
for (let x = 0; x < w; x += 1) {
// Left pixel might not exist if we're on the very left edge of the image.
const left = (x - 1) >= 0 ? getPixel(img, { x: x - 1, y }) : null;
// The color of the middle pixel that we're calculating the energy for.
const middle = getPixel(img, { x, y });
// Right pixel might not exist if we're on the very right edge of the image.
const right = (x + 1) < w ? getPixel(img, { x: x + 1, y }) : null;
energyMap[y][x] = getPixelEnergy(left, middle, right);
}
}
return energyMap;
};

/**
* Finds the seam (the sequence of pixels from top to bottom) that has the
* lowest resulting energy using the Dynamic Programming approach.
* @param {EnergyMap} energyMap
* @param {ImageSize} size
* @returns {Seam}
*/
const findLowEnergySeam = (energyMap, { w, h }) => {
// The 2D array of the size of w and h, where each pixel contains the
// seam metadata (pixel energy, pixel coordinate and previous pixel from
// the lowest energy seam at this point).
const seamPixelsMap = matrix(w, h, null);

// Populate the first row of the map by just copying the energies
// from the energy map.
for (let x = 0; x < w; x += 1) {
const y = 0;
seamPixelsMap[y][x] = {
energy: energyMap[y][x],
coordinate: { x, y },
previous: null,
};
}

// Populate the rest of the rows.
for (let y = 1; y < h; y += 1) {
for (let x = 0; x < w; x += 1) {
// Find the top adjacent cell with minimum energy.
// This cell would be the tail of a seam with lowest energy at this point.
// It doesn't mean that this seam (path) has lowest energy globally.
// Instead, it means that we found a path with the lowest energy that may lead
// us to the current pixel with the coordinates x and y.
let minPrevEnergy = Infinity;
let minPrevX = x;
for (let i = (x - 1); i <= (x + 1); i += 1) {
if (i >= 0 && i < w && seamPixelsMap[y - 1][i].energy < minPrevEnergy) {
minPrevEnergy = seamPixelsMap[y - 1][i].energy;
minPrevX = i;
}
}

// Update the current cell.
seamPixelsMap[y][x] = {
energy: minPrevEnergy + energyMap[y][x],
coordinate: { x, y },
previous: { x: minPrevX, y: y - 1 },
};
}
}

// Find where the minimum energy seam ends.
// We need to find the tail of the lowest energy seam to start
// traversing it from its tail to its head (from the bottom to the top).
let lastMinCoordinate = null;
let minSeamEnergy = Infinity;
for (let x = 0; x < w; x += 1) {
const y = h - 1;
if (seamPixelsMap[y][x].energy < minSeamEnergy) {
minSeamEnergy = seamPixelsMap[y][x].energy;
lastMinCoordinate = { x, y };
}
}

// Find the lowest energy energy seam.
// Once we know where the tail is we may traverse and assemble the lowest
// energy seam based on the "previous" value of the seam pixel metadata.
const seam = [];

const { x: lastMinX, y: lastMinY } = lastMinCoordinate;

// Adding new pixel to the seam path one by one until we reach the top.
let currentSeam = seamPixelsMap[lastMinY][lastMinX];
while (currentSeam) {
seam.push(currentSeam.coordinate);
const prevMinCoordinates = currentSeam.previous;
if (!prevMinCoordinates) {
currentSeam = null;
} else {
const { x: prevMinX, y: prevMinY } = prevMinCoordinates;
currentSeam = seamPixelsMap[prevMinY][prevMinX];
}
}

return seam;
};

/**
* Deletes the seam from the image data.
* We delete the pixel in each row and then shift the rest of the row pixels to the left.
* @param {ImageData} img
* @param {Seam} seam
* @param {ImageSize} size
*/
const deleteSeam = (img, seam, { w }) => {
seam.forEach(({ x: seamX, y: seamY }) => {
for (let x = seamX; x < (w - 1); x += 1) {
const nextPixel = getPixel(img, { x: x + 1, y: seamY });
setPixel(img, { x, y: seamY }, nextPixel);
}
});
};

/**
* Performs the content-aware image width resizing using the seam carving method.
* @param {ResizeImageWidthArgs} args
* @returns {ResizeImageWidthResult}
*/
const resizeImageWidth = ({ img, toWidth }) => {
/**
* For performance reasons we want to avoid changing the img data array size.
* Instead we'll just keep the record of the resized image width and height separately.
* @type {ImageSize}
*/
const size = { w: img.width, h: img.height };

// Calculating the number of pixels to remove.
const pxToRemove = img.width - toWidth;

let energyMap = null;
let seam = null;

// Removing the lowest energy seams one by one.
for (let i = 0; i < pxToRemove; i += 1) {
// 1. Calculate the energy map for the current version of the image.
energyMap = calculateEnergyMap(img, size);

// 2. Find the seam with the lowest energy based on the energy map.
seam = findLowEnergySeam(energyMap, size);

// 3. Delete the seam with the lowest energy seam from the image.
deleteSeam(img, seam, size);

// Reduce the image width, and continue iterations.
size.w -= 1;
}

// Returning the resized image and its final size.
// The img is actually a reference to the ImageData, so technically
// the caller of the function already has this pointer. But let's
// still return it for better code readability.
return { img, size };
};

export default resizeImageWidth;
39 changes: 39 additions & 0 deletions src/algorithms/image-processing/utils/imageData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @typedef {ArrayLike<number> | Uint8ClampedArray} PixelColor
*/

/**
* @typedef {Object} PixelCoordinate
* @property {number} x - horizontal coordinate.
* @property {number} y - vertical coordinate.
*/

/**
* Helper function that returns the color of the pixel.
* @param {ImageData} img
* @param {PixelCoordinate} coordinate
* @returns {PixelColor}
*/
export const getPixel = (img, { x, y }) => {
// The ImageData data array is a flat 1D array.
// Thus we need to convert x and y coordinates to the linear index.
const i = y * img.width + x;
const cellsPerColor = 4; // RGBA
// For better efficiency, instead of creating a new sub-array we return
// a pointer to the part of the ImageData array.
return img.data.subarray(i * cellsPerColor, i * cellsPerColor + cellsPerColor);
};

/**
* Helper function that sets the color of the pixel.
* @param {ImageData} img
* @param {PixelCoordinate} coordinate
* @param {PixelColor} color
*/
export const setPixel = (img, { x, y }, color) => {
// The ImageData data array is a flat 1D array.
// Thus we need to convert x and y coordinates to the linear index.
const i = y * img.width + x;
const cellsPerColor = 4; // RGBA
img.data.set(color, i * cellsPerColor);
};
4 changes: 4 additions & 0 deletions src/algorithms/linked-list/reverse-traversal/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Reversed Linked List Traversal

_Read this in other languages:_
[_中文_](README.zh-CN.md),
[_Português_](README.pt-BR.md)

The task is to traverse the given linked list in reversed order.

For example for the following linked list:
23 changes: 23 additions & 0 deletions src/algorithms/linked-list/reverse-traversal/README.pt-BR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Travessia de Lista Encadeada Reversa

_Leia isso em outros idiomas:_
[_中文_](README.zh-CN.md),
[_English_](README.md)

A tarefa é percorrer a lista encadeada fornecida em ordem inversa.

Por exemplo, para a seguinte lista vinculada:

![](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)

A ordem de travessia deve ser:

```texto
37 → 99 → 12
```

A complexidade de tempo é `O(n)` porque visitamos cada nó apenas uma vez.

## Referência

- [Wikipedia](https://en.wikipedia.org/wiki/Linked_list)
19 changes: 19 additions & 0 deletions src/algorithms/linked-list/reverse-traversal/README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 链表倒序遍历

我们的任务是倒序遍历给定的链表

比如下面的链表

![](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)

遍历的顺序应该是

```text
37 → 99 → 12
```

因为我们每个节点只访问一次,时间复杂度应该是`O(n)`

## 参考

- [Wikipedia](https://zh.wikipedia.org/wiki/%E9%93%BE%E8%A1%A8)
Original file line number Diff line number Diff line change
@@ -21,7 +21,6 @@ describe('reverseTraversal', () => {
});
});


// it('should reverse traversal the linked list with callback', () => {
// const linkedList = new LinkedList();
//
9 changes: 7 additions & 2 deletions src/algorithms/linked-list/traversal/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# Linked List Traversal

_Read this in other languages:_
[_Русский_](README.ru-RU.md),
[_中文_](README.zh-CN.md),
[_Português_](README.pt-BR.md)

The task is to traverse the given linked list in straight order.

For example for the following linked list:
For example for the following linked list:

![](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)
![Singly linked list](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)

The order of traversal should be:

24 changes: 24 additions & 0 deletions src/algorithms/linked-list/traversal/README.pt-BR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Travessia de Lista Encadeada

_Leia isso em outros idiomas:_
[_Русский_](README.ru-RU.md),
[_中文_](README.zh-CN.md),
[_English_](README.md)

A tarefa é percorrer a lista encadeada fornecida em ordem direta.

Por exemplo, para a seguinte lista vinculada:

![Singly linked list](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)

A ordem de travessia deve ser:

```texto
12 → 99 → 37
```

A complexidade de tempo é `O(n)` porque visitamos cada nó apenas uma vez.

## Referência

- [Wikipedia](https://en.wikipedia.org/wiki/Linked_list)
19 changes: 19 additions & 0 deletions src/algorithms/linked-list/traversal/README.ru-RU.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Обход связного списка

Задача состоит в том, чтобы обойти связный список в прямом порядке.

Например, для следующего связного списка:

![Singly linked list](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)

Порядок обхода будет такой:

```text
12 → 99 → 37
```

Временная сложность - `O(n)`, потому что мы посещаем каждый узел только один раз.

## Ссылки

- [Wikipedia](https://ru.wikipedia.org/wiki/%D0%A1%D0%B2%D1%8F%D0%B7%D0%BD%D1%8B%D0%B9_%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA)
19 changes: 19 additions & 0 deletions src/algorithms/linked-list/traversal/README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 链表遍历

我们的任务是顺序遍历给定的链表

比如下面的链表

![Singly linked list](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)

遍历的顺序应该是

```text
12 → 99 → 37
```

因为我们每个节点只访问一次,时间复杂度应该是`O(n)`

## 参考

- [Wikipedia](https://zh.wikipedia.org/wiki/%E9%93%BE%E8%A1%A8)
103 changes: 103 additions & 0 deletions src/algorithms/math/binary-floating-point/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Binary representation of floating-point numbers

Have you ever wondered how computers store the floating-point numbers like `3.1416` (𝝿) or `9.109 × 10⁻³¹` (the mass of the electron in kg) in the memory which is limited by a finite number of ones and zeroes (aka bits)?

It seems pretty straightforward for integers (i.e. `17`). Let's say we have 16 bits (2 bytes) to store the number. In 16 bits we may store the integers in a range of `[0, 65535]`:

```text
(0000000000000000)₂ = (0)₁₀
(0000000000010001)₂ =
(1 × 2⁴) +
(0 × 2³) +
(0 × 2²) +
(0 × 2¹) +
(1 × 2⁰) = (17)₁₀
(1111111111111111)₂ =
(1 × 2¹⁵) +
(1 × 2¹⁴) +
(1 × 2¹³) +
(1 × 2¹²) +
(1 × 2¹¹) +
(1 × 2¹⁰) +
(1 × 2⁹) +
(1 × 2⁸) +
(1 × 2⁷) +
(1 × 2⁶) +
(1 × 2⁵) +
(1 × 2⁴) +
(1 × 2³) +
(1 × 2²) +
(1 × 2¹) +
(1 × 2⁰) = (65535)₁₀
```

If we need a signed integer we may use [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) and shift the range of `[0, 65535]` towards the negative numbers. In this case, our 16 bits would represent the numbers in a range of `[-32768, +32767]`.

As you might have noticed, this approach won't allow you to represent the numbers like `-27.15625` (numbers after the decimal point are just being ignored).

We're not the first ones who have noticed this issue though. Around ≈36 years ago some smart folks overcame this limitation by introducing the [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) standard for floating-point arithmetic.

The IEEE 754 standard describes the way (the framework) of using those 16 bits (or 32, or 64 bits) to store the numbers of wider range, including the small floating numbers (smaller than 1 and closer to 0).

To get the idea behind the standard we might recall the [scientific notation](https://en.wikipedia.org/wiki/Scientific_notation) - a way of expressing numbers that are too large or too small (usually would result in a long string of digits) to be conveniently written in decimal form.

![Scientific number notation](images/03-scientific-notation.png)

As you may see from the image, the number representation might be split into three parts:

- **sign**
- **fraction (aka significand)** - the valuable digits (the meaning, the payload) of the number
- **exponent** - controls how far and in which direction to move the decimal point in the fraction

The **base** part we may omit by just agreeing on what it will be equal to. In our case, we'll be using `2` as a base.

Instead of using all 16 bits (or 32 bits, or 64 bits) to store the fraction of the number, we may share the bits and store a sign, exponent, and fraction at the same time. Depending on the number of bits that we're going to use to store the number we end up with the following splits:

| Floating-point format | Total bits | Sign bits | Exponent bits | Fraction bits | Base |
| :-------------------- | :--------: | :-------: | :-----------: | :--------------: | :--: |
| [Half-precision](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) | 16 | 1 | 5 | 10 | 2 |
| [Single-precision](https://en.wikipedia.org/wiki/Single-precision_floating-point_format) | 32 | 1 | 8 | 23 | 2 |
| [Double-precision](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) | 64 | 1 | 11 | 52 | 2 |

With this approach, the number of bits for the fraction has been reduced (i.e. for the 16-bits number it was reduced from 16 bits to 10 bits). It means that the fraction might take a narrower range of values now (losing some precision). However, since we also have an exponent part, it will actually increase the ultimate number range and also allow us to describe the numbers between 0 and 1 (if the exponent is negative).

> For example, a signed 32-bit integer variable has a maximum value of 2³¹ − 1 = 2,147,483,647, whereas an IEEE 754 32-bit base-2 floating-point variable has a maximum value of ≈ 3.4028235 × 10³⁸.
To make it possible to have a negative exponent, the IEEE 754 standard uses the [biased exponent](https://en.wikipedia.org/wiki/Exponent_bias). The idea is simple - subtract the bias from the exponent value to make it negative. For example, if the exponent has 5 bits, it might take the values from the range of `[0, 31]` (all values are positive here). But if we subtract the value of `15` from it, the range will be `[-15, 16]`. The number `15` is called bias, and it is being calculated by the following formula:

```
exponent_bias = 2 ^ (k−1) − 1
k - number of exponent bits
```

I've tried to describe the logic behind the converting of floating-point numbers from a binary format back to the decimal format on the image below. Hopefully, it will give you a better understanding of how the IEEE 754 standard works. The 16-bits number is being used here for simplicity, but the same approach works for 32-bits and 64-bits numbers as well.

![Half-precision floating point number format explained in one picture](images/02-half-precision-floating-point-number-explained.png)

> Checkout the [interactive version of this diagram](https://trekhleb.dev/blog/2021/binary-floating-point/) to play around with setting bits on and off, and seeing how it would influence the final result
Here is the number ranges that different floating-point formats support:

| Floating-point format | Exp min | Exp max | Range | Min positive |
| :-------------------- | :------ | :------ | :--------------- | :----------- |
| Half-precision | −14 | +15 | ±65,504 | 6.10 × 10⁻⁵ |
| Single-precision | −126 | +127 | ±3.4028235 × 10³⁸| 1.18 × 10⁻³⁸ |

Be aware that this is by no means a complete and sufficient overview of the IEEE 754 standard. It is rather a simplified and basic overview. Several corner cases were omitted in the examples above for simplicity of presentation (i.e. `-0`, `-∞`, `+∞` and `NaN` (not a number) values)

## Code examples

- See the [bitsToFloat.js](bitsToFloat.js) for the example of how to convert array of bits to the floating point number (the example is a bit artificial but still it gives the overview of how the conversion is going on)
- See the [floatAsBinaryString.js](floatAsBinaryString.js) for the example of how to see the actual binary representation of the floating-point number in JavaScript

## References

You might also want to check out the following resources to get a deeper understanding of the binary representation of floating-point numbers:

- [Interactive version of this article](https://trekhleb.dev/blog/2021/binary-floating-point/) (allows setting the bits manually and seeing the resulting floating number)
- [Here is what you need to know about JavaScript’s Number type](https://indepth.dev/posts/1139/here-is-what-you-need-to-know-about-javascripts-number-type)
- [Float Exposed](https://float.exposed/)
- [IEEE754 Visualization](https://bartaz.github.io/ieee754-visualization/)
Loading