2023-06-30
This commit is contained in:
parent
fdcd2e4591
commit
8ed24b365e
30 changed files with 2154 additions and 0 deletions
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -0,0 +1,2 @@
|
|||
jekyll_site/ru/** linguist-language=Java
|
||||
jekyll_site/en/** linguist-language=Java
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,2 +1,5 @@
|
|||
.idea
|
||||
*.iml
|
||||
*.zip
|
||||
_site*
|
||||
.repo_*.sh
|
||||
|
|
57
DIRECTORY-TREE.md
Normal file
57
DIRECTORY-TREE.md
Normal file
|
@ -0,0 +1,57 @@
|
|||
## Дерево каталогов
|
||||
|
||||
<pre>
|
||||
.
|
||||
├─ <a href='jekyll_site'>jekyll_site</a>
|
||||
│ ├─ <a href='jekyll_site/_includes'>_includes</a>
|
||||
│ │ ├─ <a href='jekyll_site/_includes/counters_body.html'>counters_body.html</a>
|
||||
│ │ └─ <a href='jekyll_site/_includes/counters_head.html'>counters_head.html</a>
|
||||
│ ├─ <a href='jekyll_site/en'>en</a>
|
||||
│ │ ├─ <a href='jekyll_site/en/2021'>2021</a>
|
||||
│ │ │ ├─ <a href='jekyll_site/en/2021/09'>09</a>
|
||||
│ │ │ │ ├─ <a href='jekyll_site/en/2021/09/07'>07</a>
|
||||
│ │ │ │ │ └─ <a href='jekyll_site/en/2021/09/07/cartesian-product-of-sets.md'>cartesian-product-of-sets.md</a>
|
||||
│ │ │ │ ├─ <a href='jekyll_site/en/2021/09/10'>10</a>
|
||||
│ │ │ │ │ └─ <a href='jekyll_site/en/2021/09/10/pascals-triangle-in-java.md'>pascals-triangle-in-java.md</a>
|
||||
│ │ │ │ ├─ <a href='jekyll_site/en/2021/09/14'>14</a>
|
||||
│ │ │ │ │ └─ <a href='jekyll_site/en/2021/09/14/combinations-by-columns.md'>combinations-by-columns.md</a>
|
||||
│ │ │ │ └─ <a href='jekyll_site/en/2021/09/22'>22</a>
|
||||
│ │ │ │ └─ <a href='jekyll_site/en/2021/09/22/combinations-of-sequence-elements.md'>combinations-of-sequence-elements.md</a>
|
||||
│ │ │ └─ <a href='jekyll_site/en/2021/10'>10</a>
|
||||
│ │ │ └─ <a href='jekyll_site/en/2021/10/05'>05</a>
|
||||
│ │ │ └─ <a href='jekyll_site/en/2021/10/05/cartesian-product-parallel-streams.md'>cartesian-product-parallel-streams.md</a>
|
||||
│ │ └─ <a href='jekyll_site/en/index.md'>index.md</a>
|
||||
│ ├─ <a href='jekyll_site/img'>img</a>
|
||||
│ │ ├─ <a href='jekyll_site/img/arrangement-formula.svg'>arrangement-formula.svg</a>
|
||||
│ │ ├─ <a href='jekyll_site/img/arrangements-quantity.gif'>arrangements-quantity.gif</a>
|
||||
│ │ └─ <a href='jekyll_site/img/three-elements-sequence.svg'>three-elements-sequence.svg</a>
|
||||
│ ├─ <a href='jekyll_site/ru'>ru</a>
|
||||
│ │ ├─ <a href='jekyll_site/ru/2021'>2021</a>
|
||||
│ │ │ ├─ <a href='jekyll_site/ru/2021/09'>09</a>
|
||||
│ │ │ │ ├─ <a href='jekyll_site/ru/2021/09/06'>06</a>
|
||||
│ │ │ │ │ └─ <a href='jekyll_site/ru/2021/09/06/cartesian-product-of-sets.md'>cartesian-product-of-sets.md</a>
|
||||
│ │ │ │ ├─ <a href='jekyll_site/ru/2021/09/09'>09</a>
|
||||
│ │ │ │ │ └─ <a href='jekyll_site/ru/2021/09/09/pascals-triangle-in-java.md'>pascals-triangle-in-java.md</a>
|
||||
│ │ │ │ ├─ <a href='jekyll_site/ru/2021/09/13'>13</a>
|
||||
│ │ │ │ │ └─ <a href='jekyll_site/ru/2021/09/13/combinations-by-columns.md'>combinations-by-columns.md</a>
|
||||
│ │ │ │ └─ <a href='jekyll_site/ru/2021/09/20'>20</a>
|
||||
│ │ │ │ └─ <a href='jekyll_site/ru/2021/09/20/combinations-of-sequence-elements.md'>combinations-of-sequence-elements.md</a>
|
||||
│ │ │ └─ <a href='jekyll_site/ru/2021/10'>10</a>
|
||||
│ │ │ └─ <a href='jekyll_site/ru/2021/10/04'>04</a>
|
||||
│ │ │ └─ <a href='jekyll_site/ru/2021/10/04/cartesian-product-parallel-streams.md'>cartesian-product-parallel-streams.md</a>
|
||||
│ │ └─ <a href='jekyll_site/ru/index.md'>index.md</a>
|
||||
│ ├─ <a href='jekyll_site/Gemfile_color'>Gemfile_color</a>
|
||||
│ ├─ <a href='jekyll_site/Gemfile_older'>Gemfile_older</a>
|
||||
│ ├─ <a href='jekyll_site/_config_color.yml'>_config_color.yml</a>
|
||||
│ ├─ <a href='jekyll_site/_config_older.yml'>_config_older.yml</a>
|
||||
│ └─ <a href='jekyll_site/robots.txt'>robots.txt</a>
|
||||
├─ <a href='CONTRIBUTING.md'>CONTRIBUTING.md</a>
|
||||
├─ <a href='DIRECTORY-TREE.md'>DIRECTORY-TREE.md</a>
|
||||
├─ <a href='LICENSE.md'>LICENSE.md</a>
|
||||
├─ <a href='OPEN_LICENSE.txt'>OPEN_LICENSE.txt</a>
|
||||
├─ <a href='README.en.md'>README.en.md</a>
|
||||
├─ <a href='README.md'>README.md</a>
|
||||
├─ <a href='build.sh'>build.sh</a>
|
||||
├─ <a href='package.sh'>package.sh</a>
|
||||
└─ <a href='serve.sh'>serve.sh</a>
|
||||
</pre>
|
17
README.en.md
Normal file
17
README.en.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
## Website pages
|
||||
|
||||
- [Cartesian product in parallel streams](https://pomodoro2.mircloud.ru/en/2021/10/05/cartesian-product-parallel-streams.html) — 05.10.2021.
|
||||
- [Combinations of sequence elements](https://pomodoro2.mircloud.ru/en/2021/09/22/combinations-of-sequence-elements.html) — 22.09.2021.
|
||||
- [Combinations of elements by columns](https://pomodoro2.mircloud.ru/en/2021/09/14/combinations-by-columns.html) — 14.09.2021.
|
||||
- [Pascal's Triangle in Java](https://pomodoro2.mircloud.ru/en/2021/09/10/pascals-triangle-in-java.html) — 10.09.2021.
|
||||
- [Cartesian product of sets](https://pomodoro2.mircloud.ru/en/2021/09/07/cartesian-product-of-sets.html) — 07.09.2021.
|
||||
|
||||
## [Source texts](README.md)
|
||||
|
||||
- Series of the static websites [«Pomodori»](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.en.md).
|
||||
- Used formats — Markdown, Liquid, YAML.
|
||||
- Build tool — Jekyll with tomato design themes.
|
||||
- Automation of processes — Bash scripts for command line.
|
||||
- [build.sh](build.sh) — Building a site in two tomato themes and optimizing the results.
|
||||
- [serve.sh](serve.sh) — Local deployment to verify the correctness of the build.
|
||||
- [package.sh](package.sh) — Preparing an archive for subsequent deployment.
|
17
README.md
Normal file
17
README.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
## Страницы вёб-сайта
|
||||
|
||||
- [Декартово произведение в параллельных потоках](https://pomodoro2.mircloud.ru/ru/2021/10/04/cartesian-product-parallel-streams.html) — 04.10.2021.
|
||||
- [Комбинации элементов последовательности](https://pomodoro2.mircloud.ru/ru/2021/09/20/combinations-of-sequence-elements.html) — 20.09.2021.
|
||||
- [Комбинации элементов по столбцам](https://pomodoro2.mircloud.ru/ru/2021/09/13/combinations-by-columns.html) — 13.09.2021.
|
||||
- [Треугольник Паскаля на Java](https://pomodoro2.mircloud.ru/ru/2021/09/09/pascals-triangle-in-java.html) — 09.09.2021.
|
||||
- [Декартово произведение множеств](https://pomodoro2.mircloud.ru/ru/2021/09/06/cartesian-product-of-sets.html) — 06.09.2021.
|
||||
|
||||
## [Исходные тексты](README.en.md)
|
||||
|
||||
- Серия статических вёб-сайтов [«Помидоры»](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.md).
|
||||
- Используемые форматы — Markdown, Liquid, YAML.
|
||||
- Инструмент сборки — Jekyll с помидорными темами оформления.
|
||||
- Автоматизация процессов — Bash скрипты для командной строки.
|
||||
- [build.sh](build.sh) — Сборка сайта в двух помидорных темах и оптимизация результатов.
|
||||
- [serve.sh](serve.sh) — Локальное развёртывание для проверки корректности сборки.
|
||||
- [package.sh](package.sh) — Подготовка архива для последующего развёртывания.
|
51
build.sh
Executable file
51
build.sh
Executable file
|
@ -0,0 +1,51 @@
|
|||
#!/bin/bash
|
||||
echo "Сборка сайта в двух помидорных темах и оптимизация результатов."
|
||||
milliseconds=$(date '+%s%3N')
|
||||
rm -rf _site
|
||||
rm -rf _site_older
|
||||
rm -rf _site_color
|
||||
echo "Сборка старого помидора."
|
||||
mkdir -p _site_older
|
||||
cp -r jekyll_site/_includes _site_older
|
||||
cp -r jekyll_site/ru _site_older
|
||||
cp -r jekyll_site/en _site_older
|
||||
cp -r jekyll_site/ru/index.md _site_older
|
||||
cp -r jekyll_site/_config_older.yml _site_older/_config.yml
|
||||
cp -r jekyll_site/Gemfile_older _site_older/Gemfile
|
||||
cd _site_older || exit
|
||||
jekyll build
|
||||
cp -r _site ..
|
||||
cd ..
|
||||
echo "Сборка цветного помидора."
|
||||
mkdir -p _site_color
|
||||
cp -r jekyll_site/_includes _site_color
|
||||
cp -r jekyll_site/ru _site_color
|
||||
cp -r jekyll_site/en _site_color
|
||||
cp -r jekyll_site/ru/index.md _site_color
|
||||
cp -r jekyll_site/_config_color.yml _site_color/_config.yml
|
||||
cp -r jekyll_site/Gemfile_color _site_color/Gemfile
|
||||
cd _site_color || exit
|
||||
jekyll build
|
||||
cp -r _site ../_site/color
|
||||
cd ..
|
||||
echo "Копирование без сборки."
|
||||
cp -r jekyll_site/img _site
|
||||
cp -r jekyll_site/robots.txt _site
|
||||
echo "Оптимизация собранного контента."
|
||||
cd _site || exit
|
||||
cp -r assets/* .
|
||||
rm -r assets
|
||||
rm -r color/assets/favicon.ico
|
||||
cp -r color/assets/* .
|
||||
rm -r color/assets
|
||||
rm -r color/404.html
|
||||
find . -type f -name '*.html' | sort -r | while read -r file; do
|
||||
sed -i 's/layout-padding=""/layout-padding/g' "$file"
|
||||
sed -i 's/ class="language-plaintext highlighter-rouge"//g' "$file"
|
||||
sed -i 's/ class="language-java highlighter-rouge"//g' "$file"
|
||||
sed -i 's/<div><div class="highlight"><pre class="highlight">/<div class="highlight"><pre class="highlight">/g' "$file"
|
||||
sed -i 's/<\/code><\/pre><\/div><\/div>/<\/code><\/pre><\/div>/g' "$file"
|
||||
sed -i 's/<hr \/>/<hr>/g' "$file"
|
||||
sed -i -r 's/<img(.+) \/>/<img\1>/g' "$file"
|
||||
done
|
||||
echo "Время выполнения сборки: $(("$(date '+%s%3N')" - "$milliseconds")) мс."
|
3
jekyll_site/Gemfile_color
Normal file
3
jekyll_site/Gemfile_color
Normal file
|
@ -0,0 +1,3 @@
|
|||
source "https://rubygems.org"
|
||||
gem "jekyll"
|
||||
gem "color-tomato-theme"
|
3
jekyll_site/Gemfile_older
Normal file
3
jekyll_site/Gemfile_older
Normal file
|
@ -0,0 +1,3 @@
|
|||
source "https://rubygems.org"
|
||||
gem "jekyll"
|
||||
gem "older-tomato-theme"
|
20
jekyll_site/_config_color.yml
Normal file
20
jekyll_site/_config_color.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
# site parameters
|
||||
name: "Код с комментариями"
|
||||
name_translated: "Code with comments"
|
||||
url: "https://pomodoro2.mircloud.ru"
|
||||
baseurl: "/color"
|
||||
homepage_url: "https://git.org.ru/pomodoro/2"
|
||||
homepage_name: "GIT.ORG.RU"
|
||||
older_tomato_baseurl: ""
|
||||
timezone: "Europe/Moscow"
|
||||
author: "Головин Г.Г."
|
||||
author_translated: "Golovin G.G."
|
||||
translation_caption: "translation from Russian"
|
||||
# build parameters
|
||||
disable_disk_cache: true
|
||||
theme: color-tomato-theme
|
||||
defaults:
|
||||
- scope:
|
||||
path: ""
|
||||
values:
|
||||
layout: default
|
20
jekyll_site/_config_older.yml
Normal file
20
jekyll_site/_config_older.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
# site parameters
|
||||
name: "Код с комментариями"
|
||||
name_translated: "Code with comments"
|
||||
url: "https://pomodoro2.mircloud.ru"
|
||||
baseurl: ""
|
||||
homepage_url: "https://git.org.ru/pomodoro/2"
|
||||
homepage_name: "GIT.ORG.RU"
|
||||
color_tomato_baseurl: "/color"
|
||||
timezone: "Europe/Moscow"
|
||||
author: "Головин Г.Г."
|
||||
author_translated: "Golovin G.G."
|
||||
translation_caption: "translation from Russian"
|
||||
# build parameters
|
||||
disable_disk_cache: true
|
||||
theme: older-tomato-theme
|
||||
defaults:
|
||||
- scope:
|
||||
path: ""
|
||||
values:
|
||||
layout: default
|
2
jekyll_site/_includes/counters_body.html
Normal file
2
jekyll_site/_includes/counters_body.html
Normal file
|
@ -0,0 +1,2 @@
|
|||
<noscript><div><img src="https://mc.yandex.ru/watch/85876478" style="position:absolute; left:-9999px;" alt=""></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
16
jekyll_site/_includes/counters_head.html
Normal file
16
jekyll_site/_includes/counters_head.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-209134013-2"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'UA-209134013-2');
|
||||
</script>
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script>
|
||||
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
||||
m[i].l=1*new Date();for(var j=0;j<document.scripts.length;j++){if(document.scripts[j].src===r){return;}}
|
||||
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
||||
(window,document,"script","https://mc.yandex.ru/metrika/tag.js","ym");
|
||||
ym(85876478,"init",{clickmap:true,trackLinks:true,accurateTrackBounce:true,webvisor:true});
|
||||
</script>
|
213
jekyll_site/en/2021/09/07/cartesian-product-of-sets.md
Normal file
213
jekyll_site/en/2021/09/07/cartesian-product-of-sets.md
Normal file
|
@ -0,0 +1,213 @@
|
|||
---
|
||||
title: Cartesian product of sets
|
||||
description: Consider an algorithm for obtaining a Cartesian product of multiple sets using three nested loops. The number of sets and their elements can be arbitrary.
|
||||
sections: [Combinatorics,Direct product]
|
||||
tags: [java,combinatorics,algorithms,cartesian product,combinations,set,list,array,loops,nested loops]
|
||||
canonical_url: /en/2021/09/07/cartesian-product-of-sets.html
|
||||
url_translated: /ru/2021/09/06/cartesian-product-of-sets.html
|
||||
title_translated: Декартово произведение множеств
|
||||
date: 2021.09.07
|
||||
lang: en
|
||||
---
|
||||
|
||||
Consider an algorithm for obtaining a *Cartesian product* of multiple sets using three nested
|
||||
loops. The number of sets and their elements can be arbitrary. We multiply the sets sequentially
|
||||
and accumulate the result. The order does not matter, since the product does not change due to the
|
||||
permutation of the multipliers. As a result, the order will be different, but the combinations will
|
||||
be the same.
|
||||
|
||||
For clarity, let's take several *ordered* sets:
|
||||
|
||||
```
|
||||
a = [A,B,C,D]
|
||||
b = [E,F,G]
|
||||
c = [H,I]
|
||||
d = [J]
|
||||
```
|
||||
|
||||
The number of possible combinations is the product of the number of elements of all sets:
|
||||
|
||||
```
|
||||
4 * 3 * 2 * 1 = 24
|
||||
```
|
||||
|
||||
Let's write a method in Java to solve such issues, we will use three nested `for` loops.
|
||||
|
||||
First, we prepare a *list of lists* `List<List<T>>`, filled with one empty value.
|
||||
We will use it as an intermediate result and as a final result.
|
||||
|
||||
Then we pass through the received lists and sequentially supplement the intermediate
|
||||
result with their elements. At each step, we get a new intermediate result and move on.
|
||||
Thus, we consistently multiply pairs of lists and step-by-step accumulate the result.
|
||||
|
||||
Schematically, this process looks like this:
|
||||
|
||||
```
|
||||
result0: [[]]
|
||||
list1: [A,B,C,D]
|
||||
--------
|
||||
result1: [[A],[B],[C],[D]]
|
||||
list2: [E,F,G]
|
||||
--------
|
||||
result2: [[A,E],[A,F],[A,G],[B,E],[B,F],...[D,G]]
|
||||
list3: [H,I]
|
||||
--------
|
||||
result3: [[A,E,H],[A,E,I],[A,F,H],[A,F,I],[A,G,H],...[D,G,I]]
|
||||
list4: [J]
|
||||
--------
|
||||
result4: [[A,E,H,J],[A,E,I,J],[A,F,H,J],[A,F,I,J],[A,G,H,J],...[D,G,I,J]]
|
||||
```
|
||||
|
||||
### Combinations by columns {#combinations-by-columns}
|
||||
|
||||
```
|
||||
Number of combinations: 24
|
||||
[A, E, H, J] [B, E, H, J] [C, E, H, J] [D, E, H, J]
|
||||
[A, E, I, J] [B, E, I, J] [C, E, I, J] [D, E, I, J]
|
||||
[A, F, H, J] [B, F, H, J] [C, F, H, J] [D, F, H, J]
|
||||
[A, F, I, J] [B, F, I, J] [C, F, I, J] [D, F, I, J]
|
||||
[A, G, H, J] [B, G, H, J] [C, G, H, J] [D, G, H, J]
|
||||
[A, G, I, J] [B, G, I, J] [C, G, I, J] [D, G, I, J]
|
||||
```
|
||||
|
||||
## Cartesian product of lists {#cartesian-product-of-lists}
|
||||
|
||||
The list can contain a *modifiable number* of elements. This simplifies the code.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param lists an arbitrary number of lists
|
||||
* @param <T> the type of elements in lists
|
||||
* @return the Cartesian product of the passed lists
|
||||
*/
|
||||
public static <T> List<List<T>> cartesianProduct(List<List<T>> lists) {
|
||||
// incoming data is not null
|
||||
if (lists == null) return Collections.emptyList();
|
||||
// intermediate result, contains one empty value
|
||||
List<List<T>> cp = Collections.singletonList(Collections.<T>emptyList());
|
||||
// pass through the received lists
|
||||
for (List<T> list : lists) {
|
||||
// non-null and non-empty lists
|
||||
if (list == null || list.size() == 0) continue;
|
||||
// next intermediate result
|
||||
List<List<T>> next = new ArrayList<>();
|
||||
// rows of the current intermediate result
|
||||
for (List<T> row : cp) {
|
||||
// elements of the current list
|
||||
for (T el : list) {
|
||||
// a new row for the next intermediate
|
||||
// result, copy of the current row
|
||||
List<T> nRow = new ArrayList<>(row);
|
||||
// add the current element
|
||||
nRow.add(el);
|
||||
// add to the next intermediate result
|
||||
next.add(nRow);
|
||||
}
|
||||
}
|
||||
// update the intermediate result
|
||||
cp = next;
|
||||
}
|
||||
// the final result
|
||||
return cp;
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// start the program and output the result
|
||||
public static void main(String[] args) {
|
||||
// an arbitrary number of lists and their elements
|
||||
List<String> a = Arrays.asList("A", "B", "C", "D");
|
||||
List<String> b = Arrays.asList("E", "F", "G");
|
||||
List<String> c = Arrays.asList("H", "I");
|
||||
List<String> d = Arrays.asList("J");
|
||||
// cartesian product
|
||||
List<List<String>> cp = cartesianProduct(Arrays.asList(a, b, c, d));
|
||||
// output
|
||||
System.out.println("Number of combinations: " + cp.size());
|
||||
// combinations by columns
|
||||
int rows = 6;
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cp.size(); j++)
|
||||
if (j % rows == i)
|
||||
System.out.print(" " + cp.get(j));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The output for this and the following code is the same, see above: [combinations by columns](#combinations-by-columns).
|
||||
|
||||
## Cartesian product of arrays {#cartesian-product-of-arrays}
|
||||
|
||||
The array contains a *fixed number* of elements. The code looks a little more complicated.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param arrays an arbitrary number of arrays
|
||||
* @param clazz the class of elements in arrays
|
||||
* @param <T> the type of elements in arrays
|
||||
* @return the Cartesian product of the passed arrays
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[][] cartesianProduct(Class<T> clazz, T[]... arrays) {
|
||||
// incoming data is not null
|
||||
if (clazz == null || arrays == null)
|
||||
return (T[][]) Array.newInstance(clazz, 0, 0);
|
||||
// intermediate result, contains one empty value
|
||||
T[][] cp = (T[][]) Array.newInstance(clazz, 1, 0);
|
||||
// pass through the received arrays
|
||||
for (int a = 0; a < arrays.length; a++) {
|
||||
// current array
|
||||
T[] arr = arrays[a];
|
||||
// non-null and non-empty array
|
||||
if (arr == null || arr.length == 0) continue;
|
||||
// next intermediate result, specify the number of rows
|
||||
T[][] next = (T[][]) Array.newInstance(clazz,cp.length*arr.length,0);
|
||||
// rows of the current intermediate result
|
||||
for (int r = 0; r < cp.length; r++) {
|
||||
// current row
|
||||
T[] row = cp[r];
|
||||
// elements of the current array
|
||||
for (int e = 0; e < arr.length; e++) {
|
||||
// current element
|
||||
T el = arr[e];
|
||||
// copy the current row into the new array [length + 1]
|
||||
T[] nRow = Arrays.copyOf(row, row.length + 1);
|
||||
// add the current element
|
||||
nRow[row.length] = el;
|
||||
// add to the next intermediate result
|
||||
next[r * arr.length + e] = nRow;
|
||||
}
|
||||
}
|
||||
// update the intermediate result
|
||||
cp = next;
|
||||
}
|
||||
// the final result
|
||||
return cp;
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// start the program and output the result
|
||||
public static void main(String[] args) {
|
||||
// an arbitrary number of arrays and their elements
|
||||
String[] a = {"A", "B", "C", "D"};
|
||||
String[] b = {"E", "F", "G"};
|
||||
String[] c = {"H", "I"};
|
||||
String[] d = {"J"};
|
||||
// cartesian product
|
||||
String[][] cp = cartesianProduct(String.class, a, b, c, d);
|
||||
// output
|
||||
System.out.println("Number of combinations: " + cp.length);
|
||||
// combinations by columns
|
||||
int rows = 6;
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cp.length; j++)
|
||||
if (j % rows == i)
|
||||
System.out.print(" " + Arrays.toString(cp[j]));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The output for this and the previous code is the same, see above: [combinations by columns](#combinations-by-columns).
|
72
jekyll_site/en/2021/09/10/pascals-triangle-in-java.md
Normal file
72
jekyll_site/en/2021/09/10/pascals-triangle-in-java.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
title: Pascal's Triangle in Java
|
||||
description: Consider a variant of the implementation of Pascal's triangle in Java. For the simplicity of storing and processing data, we represent the triangle as...
|
||||
sections: [Two-dimensional array,Binomial coefficients]
|
||||
tags: [java,algorithms,array,two-dimensional array,loops,nested loops]
|
||||
canonical_url: /en/2021/09/10/pascals-triangle-in-java.html
|
||||
url_translated: /ru/2021/09/09/pascals-triangle-in-java.html
|
||||
title_translated: Треугольник Паскаля на Java
|
||||
date: 2021.09.10
|
||||
lang: en
|
||||
---
|
||||
|
||||
Consider a variant of the implementation of *Pascal's triangle* in Java. For the simplicity
|
||||
of storing and processing data, we represent the triangle as a two-dimensional array, in which
|
||||
the elements of the first row and column are equal to one, and all other elements are the sum
|
||||
of the two previous elements in the row and column.
|
||||
|
||||
```
|
||||
A[i][j] = A[i][j-1] + A[i-1][j];
|
||||
```
|
||||
|
||||
For example, if {`n = 8`} then the array will look like this:
|
||||
|
||||
```
|
||||
1 1 1 1 1 1 1 1
|
||||
1 2 3 4 5 6 7
|
||||
1 3 6 10 15 21
|
||||
1 4 10 20 35
|
||||
1 5 15 35
|
||||
1 6 21
|
||||
1 7
|
||||
1
|
||||
```
|
||||
|
||||
Create and fill a two-dimensional array with decreasing row length:
|
||||
|
||||
```java
|
||||
int n = 8;
|
||||
// array of 'n' rows
|
||||
int[][] arr = new int[n][];
|
||||
// iterate through the rows of the array
|
||||
for (int i = 0; i < n; i++) {
|
||||
// row of 'n-i' elements
|
||||
arr[i] = new int[n - i];
|
||||
// iterate through the elements of the row
|
||||
for (int j = 0; j < n - i; j++) {
|
||||
if (i == 0 || j == 0) {
|
||||
// elements of the first row
|
||||
// and column are equal to one
|
||||
arr[i][j] = 1;
|
||||
} else {
|
||||
// all other elements are the sum of the two
|
||||
// previous elements in the row and column
|
||||
arr[i][j] = arr[i][j - 1] + arr[i - 1][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output the array row-wise:
|
||||
|
||||
```java
|
||||
// iterate through the array rows
|
||||
for (int[] row : arr) {
|
||||
// iterate through the row elements
|
||||
for (int el : row)
|
||||
// space and two-digit number
|
||||
System.out.printf(" %2d", el);
|
||||
// line separator
|
||||
System.out.println();
|
||||
}
|
||||
```
|
155
jekyll_site/en/2021/09/14/combinations-by-columns.md
Normal file
155
jekyll_site/en/2021/09/14/combinations-by-columns.md
Normal file
|
@ -0,0 +1,155 @@
|
|||
---
|
||||
title: Combinations of elements by columns
|
||||
description: In a two-dimensional array, data is stored row-wise. Consider an algorithm for obtaining a Cartesian product by columns using three nested loops. The...
|
||||
sections: [Combinatorics,Direct product]
|
||||
tags: [java,combinatorics,algorithms,cartesian product,combinations,columns,set,list,array,loops,nested loops]
|
||||
canonical_url: /en/2021/09/14/combinations-by-columns.html
|
||||
url_translated: /ru/2021/09/13/combinations-by-columns.html
|
||||
title_translated: Комбинации элементов по столбцам
|
||||
date: 2021.09.14
|
||||
lang: en
|
||||
---
|
||||
|
||||
In a two-dimensional array, data is stored row-wise. Consider an algorithm for obtaining
|
||||
a *Cartesian product* by columns using three nested loops. The number of rows and columns
|
||||
of the table can be arbitrary. We multiply the columns sequentially and accumulate the
|
||||
result. The values do not necessarily have to be populated — we discard the null elements.
|
||||
|
||||
For example, let's take a partially filled *jagged two-dimensional array*:
|
||||
|
||||
```java
|
||||
| col1 | col2 | col3 | col4
|
||||
-----|------|------|------|------
|
||||
row1 | "A1" | "B1" | "C1" | "D1"
|
||||
row2 | "A2" | "B2" | null | "D2"
|
||||
row3 | "A3" | null | null | "D3"
|
||||
row4 | "A4" | null |
|
||||
```
|
||||
|
||||
The number of possible combinations is the product of the number of elements of all columns:
|
||||
|
||||
```
|
||||
4 * 2 * 1 * 3 = 24
|
||||
```
|
||||
|
||||
Let's write a method in Java to solve such issues, we will use three nested `for` loops.
|
||||
|
||||
First, we prepare a *list of lists* `List<List<T>>`, filled with one empty value. We will
|
||||
use it as an intermediate result and as a final result.
|
||||
|
||||
Then we pass through the table columns, while they are present, — we consider the last
|
||||
column is the one after which all the elements are null. At each step, we supplement the
|
||||
intermediate result with the elements of the current column and get a new intermediate
|
||||
result. Thus, we consistently multiply columns and step-by-step accumulate the result.
|
||||
|
||||
Schematically, this process looks like this:
|
||||
|
||||
```
|
||||
res0 * col1 = res1 * col2 = res2 * col3 = res3 * col4 = res4
|
||||
-----|------|------|------|-------|------|----------|------|------------
|
||||
[] * A1 = A1 * B1 = A1,B1 * C1 = A1,B1,C1 * D1 = A1,B1,C1,D1
|
||||
* A2 = A2 * B2 = A1,B2 * = A1,B2,C1 * D2 = A1,B1,C1,D2
|
||||
* A3 = A3 * = A2,B1 * = A2,B1,C1 * D3 = A1,B1,C1,D3
|
||||
* A4 = A4 * = A2,B2 * = A2,B2,C1 * = A1,B2,C1,D1
|
||||
* = * = A3,B1 * = A3,B1,C1 * = A1,B2,C1,D2
|
||||
* = * = A3,B2 * = A3,B2,C1 * = A1,B2,C1,D3
|
||||
* = * = A4,B1 * = A4,B1,C1 * = A2,B1,C1,D1
|
||||
* = * = A4,B2 * = A4,B2,C1 * = A2,B1,C1,D2
|
||||
* = * = * = * = A2,B1,C1,D3
|
||||
* = * = * = * = A2,B2,C1,D1
|
||||
* = * = * = * = ...........
|
||||
* = * = * = * = ...........
|
||||
* = * = * = * = A4,B2,C1,D3
|
||||
-----|------|------|------|-------|------|----------|------|------------
|
||||
1 * 4 = 4 * 2 = 8 * 1 = 8 * 3 = 24
|
||||
```
|
||||
|
||||
### Combinations by columns {#combinations-by-columns}
|
||||
|
||||
```
|
||||
Number of combinations: 24
|
||||
[A1, B1, C1, D1] [A2, B1, C1, D1] [A3, B1, C1, D1] [A4, B1, C1, D1]
|
||||
[A1, B1, C1, D2] [A2, B1, C1, D2] [A3, B1, C1, D2] [A4, B1, C1, D2]
|
||||
[A1, B1, C1, D3] [A2, B1, C1, D3] [A3, B1, C1, D3] [A4, B1, C1, D3]
|
||||
[A1, B2, C1, D1] [A2, B2, C1, D1] [A3, B2, C1, D1] [A4, B2, C1, D1]
|
||||
[A1, B2, C1, D2] [A2, B2, C1, D2] [A3, B2, C1, D2] [A4, B2, C1, D2]
|
||||
[A1, B2, C1, D3] [A2, B2, C1, D3] [A3, B2, C1, D3] [A4, B2, C1, D3]
|
||||
```
|
||||
|
||||
## Cartesian product by columns {#cartesian-product-by-columns}
|
||||
|
||||
The code will look simpler if you first *transpose* an array of arrays, but if
|
||||
this cannot be done, then in the outer loop, pass through the table columns as
|
||||
long as they are still exist.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param table the two-dimensional list
|
||||
* @param <T> the type of elements in list
|
||||
* @return the Cartesian product of the elements by columns
|
||||
*/
|
||||
public static <T> List<List<T>> cartesianProduct(List<List<T>> table) {
|
||||
// incoming data is not null
|
||||
if (table == null) return Collections.emptyList();
|
||||
// intermediate result, contains one empty value
|
||||
List<List<T>> cp = Collections.singletonList(Collections.<T>emptyList());
|
||||
// columns are still present
|
||||
boolean notLast = true;
|
||||
// pass through the table columns, while they are present
|
||||
for (int i = 0; notLast; i++) {
|
||||
// there are no more columns
|
||||
notLast = false;
|
||||
// next intermediate result
|
||||
List<List<T>> next = new ArrayList<>();
|
||||
// pass through the combinations of the current intermediate result
|
||||
for (List<T> comb : cp) {
|
||||
// pass through the rows of the table
|
||||
for (List<T> row : table) {
|
||||
// if the column is still present and its value is also present
|
||||
if (row != null && i < row.size() && row.get(i) != null) {
|
||||
// a new combination, copy the current combination
|
||||
List<T> nComb = new ArrayList<>(comb);
|
||||
// add the value from the column
|
||||
nComb.add(row.get(i));
|
||||
// add to the next intermediate result
|
||||
next.add(nComb);
|
||||
// columns are still present
|
||||
notLast = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if the columns are still present, then we update the intermediate
|
||||
// result and go to the next iteration, otherwise we exit the loop
|
||||
if (notLast) cp = next;
|
||||
}
|
||||
// the final result
|
||||
return cp;
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// start the program and output the result
|
||||
public static void main(String[] args) {
|
||||
// an arbitrary number of rows and their elements
|
||||
List<String> row1 = Arrays.asList("A1", "B1", "C1", "D1");
|
||||
List<String> row2 = Arrays.asList("A2", "B2", null, "D2");
|
||||
List<String> row3 = Arrays.asList("A3", null, null, "D3");
|
||||
List<String> row4 = Arrays.asList("A4", null);
|
||||
// jagged two-dimensional list
|
||||
List<List<String>> table = Arrays.asList(row1, row2, row3, row4);
|
||||
// cartesian product
|
||||
List<List<String>> cp = cartesianProduct(table);
|
||||
// output
|
||||
System.out.println("Number of combinations: " + cp.size());
|
||||
// combinations by columns
|
||||
int rows = 6;
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cp.size(); j++)
|
||||
if (j % rows == i)
|
||||
System.out.print(" " + cp.get(j));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The output for this code see above: [combinations by columns](#combinations-by-columns).
|
240
jekyll_site/en/2021/09/22/combinations-of-sequence-elements.md
Normal file
240
jekyll_site/en/2021/09/22/combinations-of-sequence-elements.md
Normal file
|
@ -0,0 +1,240 @@
|
|||
---
|
||||
title: Combinations of sequence elements
|
||||
description: Consider a problem where you need to get all possible combinations of sequence elements, in which the number of elements in the combination does not exceed...
|
||||
sections: [Combinatorics,Arrangements,Permutations]
|
||||
tags: [java,combinatorics,algorithms,arrangement,permutation,combinations,sequence,set,list,loops,nested loops]
|
||||
canonical_url: /en/2021/09/22/combinations-of-sequence-elements.html
|
||||
url_translated: /ru/2021/09/20/combinations-of-sequence-elements.html
|
||||
title_translated: Комбинации элементов последовательности
|
||||
date: 2021.09.22
|
||||
lang: en
|
||||
---
|
||||
|
||||
Consider a problem where you need to get all possible combinations of sequence elements, in which
|
||||
the number of elements in the combination does not exceed a given maximum, and let's write a method
|
||||
in Java with the appropriate filter for the minimum and maximum number of elements.
|
||||
|
||||
*[Table setting problem](#table-setting-problem) • [Method for solving in Java](#combinations-of-length)*
|
||||
|
||||
An *arrangement* is an ordered set of {`k`} distinct elements from a set of distinct {`n`} elements,
|
||||
where {<code>k ≤ n</code>}. If {<code>k = n</code>}, then this ordered set
|
||||
is a *permutation*. For the universality of the solution, we'll also consider *permutations* as
|
||||
a special case of *arrangement*.
|
||||
|
||||
## Number of possible combinations {#number-of-possible-combinations}
|
||||
|
||||
For clarity, we'll take a sequence of three elements {`XYZ`}, draw all possible subsets
|
||||
of this set, add permutations to them and calculate the number of combinations.
|
||||
|
||||
{% include picture.html src="/img/arrangements-quantity.gif" size100=true background=true
|
||||
alt="We get the number of all possible arrangements of the sequence elements"
|
||||
caption="We get the number of all possible arrangements of the sequence elements" %}
|
||||
|
||||
Formula for the number of arrangements:
|
||||
|
||||
{% include image_svg.html src="/img/arrangement-formula.svg" style="width: 83pt; height: 46pt;"
|
||||
alt="\sum_{k=0}^{n} {n! \over (n-k)!}" %}
|
||||
|
||||
Sequence of three elements:
|
||||
|
||||
{% include image_svg.html src="/img/three-elements-sequence.svg" style="width: 375pt; height: 48pt;"
|
||||
alt="\sum_{k=0}^{3} {3! \over (3-k)!} = {3! \over 3!} + {3! \over 2!} + {3! \over 1!} + {3! \over 0!} = 1+3+6+6 = 16." %}
|
||||
|
||||
Implementation in Java:
|
||||
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
// number of sequence elements
|
||||
int n = 3;
|
||||
// number of possible combinations
|
||||
int sum = 0;
|
||||
// bypass the possible numbers of elements
|
||||
for (int k = 0; k <= n; k++)
|
||||
// add up the numbers of arrangements
|
||||
sum += factorial(n) / factorial(n - k);
|
||||
// output
|
||||
System.out.println(sum); // 16
|
||||
}
|
||||
// factorial of a number
|
||||
static int factorial(int n) {
|
||||
int fact = 1;
|
||||
for (int i = 2; i <= n; i++)
|
||||
fact *= i;
|
||||
return fact;
|
||||
}
|
||||
```
|
||||
|
||||
## Combinations of three elements {#combinations-of-elements}
|
||||
|
||||
Let's compare two sequences of three elements: digits {`123`} and letters {`XYZ`}.
|
||||
The type of elements is different — combinations are the same, because the sequence
|
||||
numbers of the elements are the same.
|
||||
|
||||
```
|
||||
number of variants: 16
|
||||
[][1][2][3][12][13][21][23][31][32][123][132][213][231][312][321]
|
||||
[][X][Y][Z][XY][XZ][YX][YZ][ZX][ZY][XYZ][XZY][YXZ][YZX][ZXY][ZYX]
|
||||
```
|
||||
|
||||
Let's compare sequences of [`1..12`] elements: the number of variants grows rapidly and
|
||||
soon goes beyond the `Integer`, then for {<code>n > 12</code>} you will need
|
||||
to use `Long`, and when {<code>n > 20</code>} — already `BigInteger`.
|
||||
|
||||
```
|
||||
n number of variants
|
||||
1 2
|
||||
2 5
|
||||
3 16
|
||||
4 65
|
||||
5 326
|
||||
6 1957
|
||||
7 13700
|
||||
8 109601
|
||||
9 986410
|
||||
10 9864101
|
||||
11 108505112
|
||||
12 1302061345
|
||||
```
|
||||
|
||||
Consider a problem where you need to limit the possible variants
|
||||
by the maximum number of elements contained in them.
|
||||
|
||||
## Table setting problem {#table-setting-problem}
|
||||
|
||||
Four guests are invited to dinner {<code>n = 4</code>}, of whom it is known
|
||||
that no more than two people will arrive {<code>k = 2</code>}, and the order
|
||||
of their appearance is important, since the table setting depends on it. It is also
|
||||
known that when the first one arrives, this person will say who will be the second and
|
||||
whether this person will arrive. Calculate the possible variants for table setting.
|
||||
|
||||
### Solution approach {#solution-approach}
|
||||
|
||||
Let's write a method in Java for solving such problems, which will take three
|
||||
parameters as input: sequence size, minimum and maximum number of elements in
|
||||
a combination. The method will return a list of combinations of specified length.
|
||||
|
||||
```java
|
||||
static List<Set<Integer>> combinationsOfElements(int size, int min, int max)
|
||||
```
|
||||
|
||||
We call the method with the selection {<code>min=0; max=2</code>}
|
||||
and get a list of combinations of specified length.
|
||||
|
||||
```java
|
||||
// table setting problem
|
||||
public static void main(String[] args) {
|
||||
// four guests are invited
|
||||
int[] arr = {1, 2, 3, 4};
|
||||
// n - number of elements in a sequence
|
||||
// k - maximum number of elements in a combination
|
||||
int n = 4, k = 2;
|
||||
// combinations of elements of specified length [0..2]
|
||||
List<Set<Integer>> list = combinationsOfElements(n, 0, k);
|
||||
// output
|
||||
System.out.println("number of variants: " + list.size());
|
||||
for (Set<Integer> set : list) {
|
||||
System.out.print("[");
|
||||
for (int i : set)
|
||||
System.out.print(arr[i]);
|
||||
System.out.print("]");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
number of variants: 17
|
||||
[][1][2][3][4][12][13][14][21][23][24][31][32][34][41][42][43]
|
||||
```
|
||||
|
||||
## Combinations of elements of specified length {#combinations-of-length}
|
||||
|
||||
We write a method in Java using three nested `for` loops. Next, to check, we
|
||||
call this method without selection {<code>min=0; max=size</code>} and get
|
||||
all possible combinations. For example, let's take two sequences of three
|
||||
elements: digits {`123`} and letters {`XYZ`}.
|
||||
|
||||
### Method description {#method-description}
|
||||
|
||||
We prepare two lists of combinations: the resulting list and the current list.
|
||||
In the current list, the number of elements in all combinations will be the same.
|
||||
The maximum number of elements in a combination is the size of the sequence.
|
||||
We start with one empty combination and gradually increase the number of elements.
|
||||
|
||||
We bypass the possible number of elements and supplement the current combinations
|
||||
with those indices that are not yet included. At each step, we increase the current
|
||||
number of elements in the combinations by one and, if it gets into selection, then
|
||||
we add these combinations to the result.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param size the sequence size (0 ≤ min ≤ max ≤ size)
|
||||
* @param min minimum number of elements in a combination
|
||||
* @param max maximum number of elements in a combination
|
||||
* @return combinations of elements of specified length
|
||||
*/
|
||||
static List<Set<Integer>> combinationsOfElements(int size, int min, int max) {
|
||||
// invalid incoming data, return an empty list of combinations
|
||||
if (0 > min || min > max || max > size) return Collections.emptyList();
|
||||
// resulting list of combinations
|
||||
List<Set<Integer>> result = new ArrayList<>();
|
||||
// current list of combinations, number of elements in all
|
||||
// combinations is the same, start with one empty combination
|
||||
List<Set<Integer>> sublist = Arrays.asList(Collections.<Integer>emptySet());
|
||||
// bypass the possible number of elements in a combination
|
||||
for (int l = 0; l < Math.min(size, max); l++) {
|
||||
// if current number of elements gets into selection,
|
||||
// then add these combinations to the result
|
||||
if (l >= min) result.addAll(sublist);
|
||||
// next list of combinations
|
||||
List<Set<Integer>> nSublist = new ArrayList<>();
|
||||
// bypass the current list of combinations
|
||||
for (Set<Integer> comb : sublist) {
|
||||
// bypass the indexes of the sequence elements
|
||||
for (int i = 0; i < size; i++) {
|
||||
// skip those indexes that already present
|
||||
if (comb.contains(i)) continue;
|
||||
// new combination, copy the current one
|
||||
Set<Integer> nComb = new LinkedHashSet<>(comb);
|
||||
// adding the current index
|
||||
nComb.add(i);
|
||||
// add in a new list of combinations
|
||||
nSublist.add(nComb);
|
||||
}
|
||||
}
|
||||
// update the current list of combinations
|
||||
sublist = nSublist;
|
||||
}
|
||||
// add the current list of combinations to the result
|
||||
result.addAll(sublist);
|
||||
// return the final result
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// start the program and output the result
|
||||
public static void main(String[] args) {
|
||||
// two sequences of three elements
|
||||
Integer[] arr1 = {1, 2, 3};
|
||||
String[] arr2 = {"X", "Y", "Z"};
|
||||
// number of sequence elements
|
||||
int n = 3;
|
||||
// all possible combinations of elements [0..n]
|
||||
List<Set<Integer>> list = combinationsOfElements(n, 0, n);
|
||||
// output
|
||||
System.out.println("number of variants: " + list.size());
|
||||
for (Object[] arr : Arrays.asList(arr1, arr2)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Set<Integer> set : list) {
|
||||
sb.append("[");
|
||||
for (int i : set) sb.append(arr[i]);
|
||||
sb.append("]");
|
||||
}
|
||||
System.out.println(sb);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The output for this code see above: [combinations of three elements](#combinations-of-elements).
|
173
jekyll_site/en/2021/10/05/cartesian-product-parallel-streams.md
Normal file
173
jekyll_site/en/2021/10/05/cartesian-product-parallel-streams.md
Normal file
|
@ -0,0 +1,173 @@
|
|||
---
|
||||
title: Cartesian product in parallel streams
|
||||
description: Consider an algorithm for obtaining a Cartesian product using Java Streams. This solution is similar to three nested for loops, with the difference that...
|
||||
sections: [Multithreading,Combinatorics,Direct product]
|
||||
tags: [java,multithreading,combinatorics,algorithms,cartesian product]
|
||||
canonical_url: /en/2021/10/05/cartesian-product-parallel-streams.html
|
||||
url_translated: /ru/2021/10/04/cartesian-product-parallel-streams.html
|
||||
title_translated: Декартово произведение в параллельных потоках
|
||||
date: 2021.10.05
|
||||
lang: en
|
||||
---
|
||||
|
||||
Consider an algorithm for obtaining a *Cartesian product* using Java Streams. This solution is similar
|
||||
to three nested `for` loops, with the difference that the outer loop is replaced with a stream for the
|
||||
convenience of subsequent parallelization. We’ll use the `reduce` method with three parameters:
|
||||
`identity`, `accumulator` and `combiner`.
|
||||
|
||||
*Algorithm with three nested loops:
|
||||
[Cartesian product of sets]({{ '/en/2021/09/07/cartesian-product-of-sets.html' | relative_url }}).*
|
||||
|
||||
The incoming data is an arbitrary number of lists and their elements.
|
||||
|
||||
```
|
||||
a = [A1,B1,C1,D1]
|
||||
b = [A2,B2,C2]
|
||||
c = [A3,B3]
|
||||
d = [A4]
|
||||
```
|
||||
|
||||
The number of possible combinations is the product of the number of elements in all lists:
|
||||
|
||||
```
|
||||
4 * 3 * 2 * 1 = 24
|
||||
```
|
||||
|
||||
We get a *stream of lists* `Stream<List<T>>` from the input data and call the `reduce` method:
|
||||
|
||||
{% capture md_list_into_div %}
|
||||
- `identity` — in our case it is a *list of lists* `List<List<T>>`, filled with
|
||||
one empty value. We will use it as an intermediate result and as a final result.
|
||||
|
||||
- `accumulator` — for each step of *reduction*, we define a method with two parameters:
|
||||
intermediate result and current list. We supplement the intermediate result with elements
|
||||
from the current list.
|
||||
|
||||
- `combiner` — is used in parallel mode, combines the results of the work of streams,
|
||||
obtains the *Cartesian product* of the results.
|
||||
{% endcapture %}
|
||||
<div>
|
||||
{{- md_list_into_div | markdownify -}}
|
||||
</div>
|
||||
|
||||
The step-by-step process of accumulating a *Cartesian product* looks like this:
|
||||
|
||||
```
|
||||
result0: [[]]
|
||||
list1: [A1,B1,C1,D1]
|
||||
--------
|
||||
result1: [[A1],[B1],[C1],[D1]]
|
||||
list2: [A2,B2,C2]
|
||||
--------
|
||||
result2: [[A1,A2],[A1,B2],[A1,C2],[B1,A2],[B1,B2],...[D1,C2]]
|
||||
list3: [A3,B3]
|
||||
--------
|
||||
result3: [[A1,A2,A3],[A1,A2,B3],[A1,B2,A3],[A1,B2,B3],[A1,C2,A3],...[D1,C2,B3]]
|
||||
list4: [A4]
|
||||
--------
|
||||
result4: [[A1,A2,A3,A4],[A1,A2,B3,A4],[A1,B2,A3,A4],[A1,B2,B3,A4],...[D1,C2,B3,A4]]
|
||||
```
|
||||
|
||||
### Combinations by columns {#combinations-by-columns}
|
||||
|
||||
```
|
||||
Number of combinations: 24
|
||||
[A1, A2, A3, A4] [B1, A2, A3, A4] [C1, A2, A3, A4] [D1, A2, A3, A4]
|
||||
[A1, A2, B3, A4] [B1, A2, B3, A4] [C1, A2, B3, A4] [D1, A2, B3, A4]
|
||||
[A1, B2, A3, A4] [B1, B2, A3, A4] [C1, B2, A3, A4] [D1, B2, A3, A4]
|
||||
[A1, B2, B3, A4] [B1, B2, B3, A4] [C1, B2, B3, A4] [D1, B2, B3, A4]
|
||||
[A1, C2, A3, A4] [B1, C2, A3, A4] [C1, C2, A3, A4] [D1, C2, A3, A4]
|
||||
[A1, C2, B3, A4] [B1, C2, B3, A4] [C1, C2, B3, A4] [D1, C2, B3, A4]
|
||||
```
|
||||
|
||||
## Combinations of elements in parallel streams {#combinations-of-elements-in-parallel-streams}
|
||||
|
||||
In parallel mode, the speed of the algorithm increases when multiplying a *large number of small lists*,
|
||||
for example, 20 lists of 2 elements or 15 lists of 3 elements. The computation time reduces by *one and
|
||||
a half to two* times. In other cases, the computation time is about the same as for three nested `for`
|
||||
loops.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param lists an arbitrary number of lists
|
||||
* @param <T> the type of elements in lists
|
||||
* @return the Cartesian product of the passed lists
|
||||
*/
|
||||
public static <T> List<List<T>> cartesianProduct(List<List<T>> lists) {
|
||||
// incoming data is not null
|
||||
if (lists == null) return Collections.emptyList();
|
||||
// stream of lists Stream<List<T>>
|
||||
return lists.stream()
|
||||
// enable parallel mode
|
||||
.parallel()
|
||||
// discard null and empty lists
|
||||
.filter(list -> list != null && list.size() > 0)
|
||||
// reduce the stream of lists into one list, get a Cartesian product
|
||||
// reduce(identity, accumulator, combiner)
|
||||
.reduce( // intermediate result, contains one empty value
|
||||
Collections.singletonList(Collections.emptyList()),
|
||||
// bypass the received lists and supplement the intermediate result
|
||||
// with their elements, at each step obtain a new intermediate result
|
||||
(result, list) -> {
|
||||
// next intermediate result
|
||||
List<List<T>> nResult = new ArrayList<>(result.size() * list.size());
|
||||
// rows of the current intermediate result
|
||||
for (List<T> row : result) {
|
||||
// elements of the current list
|
||||
for (T el : list) {
|
||||
// a new row for the next intermediate result
|
||||
List<T> nRow = new ArrayList<>(row.size() + 1);
|
||||
// add the current row
|
||||
nRow.addAll(row);
|
||||
// add the current element
|
||||
nRow.add(el);
|
||||
// add to the next intermediate result
|
||||
nResult.add(nRow);
|
||||
}
|
||||
}
|
||||
// pass to the next iteration
|
||||
return nResult;
|
||||
},
|
||||
// is used in parallel mode, combines the results of the work
|
||||
// of streams, obtains the Cartesian product of the results
|
||||
(result1, result2) -> {
|
||||
// combined result
|
||||
List<List<T>> result = new ArrayList<>(result1.size() * result2.size());
|
||||
// bypass the results
|
||||
for (List<T> comb1 : result1) {
|
||||
for (List<T> comb2 : result2) {
|
||||
// add up the combinations
|
||||
List<T> comb = new ArrayList<>(comb1.size() + comb2.size());
|
||||
comb.addAll(comb1);
|
||||
comb.addAll(comb2);
|
||||
result.add(comb);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// start the program and output the result
|
||||
public static void main(String[] args) {
|
||||
// an arbitrary number of lists and their elements
|
||||
List<String> a = Arrays.asList("A1", "B1", "C1", "D1");
|
||||
List<String> b = Arrays.asList("A2", "B2", "C2");
|
||||
List<String> c = Arrays.asList("A3", "B3");
|
||||
List<String> d = Collections.singletonList("A4");
|
||||
// cartesian product
|
||||
List<List<String>> cp = cartesianProduct(Arrays.asList(a, b, c, d));
|
||||
// output
|
||||
System.out.println("Number of combinations: " + cp.size());
|
||||
// combinations by columns
|
||||
int rows = 6;
|
||||
IntStream.range(0, rows).forEach(i -> System.out.println(
|
||||
IntStream.range(0, cp.size())
|
||||
.filter(j -> j % rows == i)
|
||||
.mapToObj(j -> cp.get(j).toString())
|
||||
.collect(Collectors.joining(" "))));
|
||||
}
|
||||
```
|
||||
|
||||
The output for this code see above: [combinations by columns](#combinations-by-columns).
|
63
jekyll_site/en/index.md
Normal file
63
jekyll_site/en/index.md
Normal file
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
title: Code with comments
|
||||
description: Notes about programming with code snippets and comments. Problem solutions and solution descriptions.
|
||||
sections: [Problem solutions and solution descriptions]
|
||||
tags: [java,combinatorics,algorithms,implementation,sets,subsets,lists,arrays,loops,nested loops]
|
||||
canonical_url: /en/
|
||||
url_translated: /ru/
|
||||
title_translated: Код с комментариями
|
||||
lang: en
|
||||
---
|
||||
|
||||
{%- assign articles = "" | split: "" %}
|
||||
{%- assign articles = articles | push: "Cartesian product in parallel streams" %}
|
||||
{%- capture article_brief %}
|
||||
Consider an algorithm for obtaining a *Cartesian product* using Java Streams. This solution is similar
|
||||
to three nested `for` loops, with the difference that the outer loop is replaced with a stream for the
|
||||
convenience of subsequent parallelization. We’ll use the `reduce` method with three parameters:
|
||||
`identity`, `accumulator` and `combiner`.
|
||||
|
||||
In parallel mode, the speed of the algorithm increases when multiplying a *large number of small lists*,
|
||||
for example, 20 lists of 2 elements or 15 lists of 3 elements. The computation time reduces by *one and
|
||||
a half to two* times. In other cases, the computation time is about the same as for three nested `for`
|
||||
loops.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- assign articles = articles | push: "Combinations of sequence elements" %}
|
||||
{%- capture article_brief %}
|
||||
Consider a problem where you need to get all possible combinations of sequence elements, in which
|
||||
the number of elements in the combination does not exceed a given maximum, and let's write a method
|
||||
in Java with the appropriate filter for the minimum and maximum number of elements.
|
||||
|
||||
An *arrangement* is an ordered set of {`k`} distinct elements from a set of distinct {`n`} elements,
|
||||
where {<code>k ≤ n</code>}. If {<code>k = n</code>}, then this ordered set
|
||||
is a *permutation*. For the universality of the solution, we'll also consider *permutations* as
|
||||
a special case of *arrangement*.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- assign articles = articles | push: "Combinations of elements by columns" %}
|
||||
{%- capture article_brief %}
|
||||
In a two-dimensional array, data is stored row-wise. Consider an algorithm for obtaining
|
||||
a *Cartesian product* by columns using three nested loops. The number of rows and columns
|
||||
of the table can be arbitrary. We multiply the columns sequentially and accumulate the
|
||||
result. The values do not necessarily have to be populated — we discard the null elements.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- assign articles = articles | push: "Pascal's Triangle in Java" %}
|
||||
{%- capture article_brief %}
|
||||
Consider a variant of the implementation of *Pascal's triangle* in Java. For the simplicity
|
||||
of storing and processing data, we represent the triangle as a two-dimensional array, in which
|
||||
the elements of the first row and column are equal to one, and all other elements are the sum
|
||||
of the two previous elements in the row and column.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- assign articles = articles | push: "Cartesian product of sets" %}
|
||||
{%- capture article_brief %}
|
||||
Consider an algorithm for obtaining a *Cartesian product* of multiple sets using three nested
|
||||
loops. The number of sets and their elements can be arbitrary. We multiply the sets sequentially
|
||||
and accumulate the result. The order does not matter, since the product does not change due to the
|
||||
permutation of the multipliers. As a result, the order will be different, but the combinations will
|
||||
be the same.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- include main_page.html articles = articles -%}
|
32
jekyll_site/img/arrangement-formula.svg
Normal file
32
jekyll_site/img/arrangement-formula.svg
Normal file
|
@ -0,0 +1,32 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="82.312663pt" height="44.923737pt" viewBox="-.239051 -.233566 82.312663 44.923737">
|
||||
<defs>
|
||||
<path id="g3-33" d="M2.6397-9.583259C2.6397-10.042337 2.252353-10.25753 1.951083-10.25753S1.20508-10.056683 1.248119-9.454143L1.764582-2.883585C1.778928-2.6397 1.807621-2.582315 1.936736-2.582315C2.080198-2.582315 2.108891-2.625354 2.123237-2.883585L2.6397-9.583259ZM2.6397-.702964C2.6397-1.075965 2.324084-1.391581 1.951083-1.391581C1.549389-1.391581 1.248119-1.075965 1.248119-.688617C1.248119-.315616 1.563735 0 1.936736 0C2.33843 0 2.6397-.315616 2.6397-.702964Z"/>
|
||||
<path id="g3-40" d="M4.662514 3.486126C4.662514 3.443087 4.662514 3.414395 4.418628 3.170509C2.984009 1.721543 2.180622-.645579 2.180622-3.572203C2.180622-6.355365 2.854893-8.751179 4.519052-10.44403C4.662514-10.573146 4.662514-10.601839 4.662514-10.644877C4.662514-10.730954 4.590783-10.759647 4.533398-10.759647C4.346897-10.759647 3.170509-9.726721 2.467546-8.320793C1.73589-6.871828 1.405927-5.336785 1.405927-3.572203C1.405927-2.295391 1.606774-.588194 2.352776 .946849C3.199202 2.668392 4.37559 3.600895 4.533398 3.600895C4.590783 3.600895 4.662514 3.572203 4.662514 3.486126Z"/>
|
||||
<path id="g3-41" d="M4.045627-3.572203C4.045627-4.662514 3.902165-6.441442 3.098778-8.105601C2.252353-9.827144 1.075965-10.759647 .918157-10.759647C.860772-10.759647 .789041-10.730954 .789041-10.644877C.789041-10.601839 .789041-10.573146 1.032926-10.329261C2.467546-8.880295 3.270933-6.513173 3.270933-3.586549C3.270933-.803387 2.596661 1.592428 .932503 3.285279C.789041 3.414395 .789041 3.443087 .789041 3.486126C.789041 3.572203 .860772 3.600895 .918157 3.600895C1.104657 3.600895 2.281045 2.567969 2.984009 1.162042C3.715665-.30127 4.045627-1.850659 4.045627-3.572203Z"/>
|
||||
<path id="g2-107" d="M4.031281-9.597605C4.045627-9.65499 4.07432-9.741067 4.07432-9.812798C4.07432-9.95626 3.930858-9.95626 3.902165-9.95626C3.887819-9.95626 3.371356-9.913221 3.113124-9.884529C2.869239-9.870183 2.654046-9.84149 2.395815-9.827144C2.051506-9.798452 1.951083-9.784105 1.951083-9.525874C1.951083-9.382412 2.094545-9.382412 2.238007-9.382412C2.969663-9.382412 2.969663-9.253296 2.969663-9.109834C2.969663-9.052449 2.969663-9.023757 2.897932-8.765526L.846426-.559502C.789041-.344309 .789041-.315616 .789041-.229539C.789041 .086077 1.032926 .143462 1.176388 .143462C1.578082 .143462 1.664159-.172154 1.778928-.616886L2.453199-3.299625C3.486126-3.184855 4.103012-2.75447 4.103012-2.065852C4.103012-1.979775 4.103012-1.92239 4.059973-1.707197C4.002589-1.492004 4.002589-1.31985 4.002589-1.248119C4.002589-.41604 4.547744 .143462 5.2794 .143462C5.939325 .143462 6.283634-.459078 6.398403-.659925C6.699673-1.190734 6.886174-1.994121 6.886174-2.051506C6.886174-2.123237 6.828789-2.180622 6.742712-2.180622C6.613596-2.180622 6.59925-2.123237 6.541865-1.893698C6.341018-1.147696 6.039748-.143462 5.308092-.143462C5.021168-.143462 4.834668-.286924 4.834668-.832079C4.834668-1.104657 4.892053-1.420273 4.949438-1.635466C5.006822-1.893698 5.006822-1.908044 5.006822-2.080198C5.006822-2.926624 4.246474-3.400048 2.926624-3.572203C3.443087-3.887819 3.95955-4.447321 4.160397-4.662514C4.97813-5.58067 5.537632-6.039748 6.197557-6.039748C6.527519-6.039748 6.613596-5.953671 6.71402-5.867594C6.18321-5.810209 5.982364-5.437208 5.982364-5.150284C5.982364-4.805976 6.254941-4.691206 6.455788-4.691206C6.843135-4.691206 7.187444-5.021168 7.187444-5.480247C7.187444-5.896286 6.857482-6.326672 6.211903-6.326672C5.422862-6.326672 4.777283-5.767171 3.758703-4.619475C3.615241-4.447321 3.084432-3.902165 2.553623-3.701318L4.031281-9.597605Z"/>
|
||||
<path id="g2-110" d="M2.955316-4.203435C2.984009-4.289513 3.342664-5.006822 3.873473-5.465901C4.246474-5.810209 4.734245-6.039748 5.293746-6.039748C5.867594-6.039748 6.068441-5.609363 6.068441-5.035515C6.068441-4.217782 5.480247-2.582315 5.193323-1.807621C5.064207-1.463312 4.992476-1.276811 4.992476-1.01858C4.992476-.373001 5.437208 .143462 6.125826 .143462C7.460022 .143462 7.962139-1.965429 7.962139-2.051506C7.962139-2.123237 7.904754-2.180622 7.818677-2.180622C7.689561-2.180622 7.675215-2.137583 7.603484-1.893698C7.273521-.71731 6.728366-.143462 6.168864-.143462C6.025402-.143462 5.795863-.157808 5.795863-.616886C5.795863-.975541 5.953671-1.405927 6.039748-1.606774C6.326672-2.395815 6.929213-4.002589 6.929213-4.820322C6.929213-5.681093 6.427096-6.326672 5.336785-6.326672C4.059973-6.326672 3.385702-5.422862 3.127471-5.064207C3.084432-5.88194 2.496238-6.326672 1.865005-6.326672C1.405927-6.326672 1.090311-6.054095 .846426-5.566324C.588194-5.049861 .387347-4.189089 .387347-4.131704S.444732-4.002589 .545155-4.002589C.659925-4.002589 .674271-4.016935 .760348-4.346897C.989888-5.222015 1.248119-6.039748 1.821967-6.039748C2.151929-6.039748 2.266699-5.810209 2.266699-5.379823C2.266699-5.064207 2.123237-4.504705 2.022814-4.059973L1.62112-2.510584C1.563735-2.238007 1.405927-1.592428 1.334196-1.334196C1.233773-.961195 1.075965-.286924 1.075965-.215193C1.075965-.014346 1.233773 .143462 1.448966 .143462C1.62112 .143462 1.821967 .057385 1.936736-.157808C1.965429-.229539 2.094545-.731656 2.166276-1.01858L2.481892-2.309738L2.955316-4.203435Z"/>
|
||||
<path id="g1-0" d="M9.454143-3.299625C9.698028-3.299625 9.95626-3.299625 9.95626-3.586549S9.698028-3.873473 9.454143-3.873473H1.692851C1.448966-3.873473 1.190734-3.873473 1.190734-3.586549S1.448966-3.299625 1.692851-3.299625H9.454143Z"/>
|
||||
<path id="g5-48" d="M4.582814-3.188045C4.582814-3.985056 4.533001-4.782067 4.184309-5.519303C3.726027-6.475716 2.909091-6.635118 2.49066-6.635118C1.892902-6.635118 1.165629-6.37609 .757161-5.449564C.438356-4.762142 .388543-3.985056 .388543-3.188045C.388543-2.440847 .428394-1.544209 .836862-.787049C1.265255 .019925 1.992528 .219178 2.480697 .219178C3.01868 .219178 3.775841 .009963 4.214197-.936488C4.533001-1.62391 4.582814-2.400996 4.582814-3.188045ZM2.480697 0C2.092154 0 1.504359-.249066 1.325031-1.205479C1.215442-1.803238 1.215442-2.719801 1.215442-3.307597C1.215442-3.945205 1.215442-4.60274 1.295143-5.140722C1.484433-6.326276 2.231631-6.41594 2.480697-6.41594C2.809465-6.41594 3.466999-6.236613 3.656289-5.250311C3.755915-4.692403 3.755915-3.935243 3.755915-3.307597C3.755915-2.560399 3.755915-1.882939 3.646326-1.24533C3.496887-.298879 2.929016 0 2.480697 0Z"/>
|
||||
<path id="g5-61" d="M6.844334-3.257783C6.993773-3.257783 7.183064-3.257783 7.183064-3.457036S6.993773-3.656289 6.854296-3.656289H.886675C.747198-3.656289 .557908-3.656289 .557908-3.457036S.747198-3.257783 .896638-3.257783H6.844334ZM6.854296-1.325031C6.993773-1.325031 7.183064-1.325031 7.183064-1.524284S6.993773-1.723537 6.844334-1.723537H.896638C.747198-1.723537 .557908-1.723537 .557908-1.524284S.747198-1.325031 .886675-1.325031H6.854296Z"/>
|
||||
<path id="g0-88" d="M18.162284 20.084674L19.898173 15.493891H19.539518C18.980017 16.985896 17.45932 17.961437 15.809508 18.391823C15.508238 18.463554 14.10231 18.836555 11.347841 18.836555H2.697085L9.999298 10.271876C10.099722 10.157107 10.128414 10.114068 10.128414 10.042337C10.128414 10.013645 10.128414 9.970606 10.027991 9.827144L3.342664 .688617H11.204379C13.126769 .688617 14.432273 .889464 14.561389 .918157C15.336083 1.032926 16.584202 1.276811 17.717552 1.994121C18.076207 2.22366 19.051748 2.869239 19.539518 4.031281H19.898173L18.162284 0H1.20508C.875118 0 .860772 .014346 .817733 .100423C.803387 .143462 .803387 .41604 .803387 .573848L8.392524 10.960493L.961195 19.668634C.817733 19.840789 .817733 19.91252 .817733 19.926866C.817733 20.084674 .946849 20.084674 1.20508 20.084674H18.162284Z"/>
|
||||
<path id="g4-107" d="M2.859278-6.804483C2.859278-6.814446 2.859278-6.914072 2.729763-6.914072C2.500623-6.914072 1.77335-6.834371 1.514321-6.814446C1.43462-6.804483 1.325031-6.794521 1.325031-6.615193C1.325031-6.495641 1.414695-6.495641 1.564134-6.495641C2.042341-6.495641 2.062267-6.425903 2.062267-6.326276L2.032379-6.127024L.587796-.388543C.547945-.249066 .547945-.229141 .547945-.169365C.547945 .059776 .747198 .109589 .836862 .109589C.966376 .109589 1.115816 .019925 1.175592-.099626C1.225405-.18929 1.673724-2.032379 1.733499-2.281445C2.072229-2.251557 2.889166-2.092154 2.889166-1.43462C2.889166-1.364882 2.889166-1.325031 2.859278-1.225405C2.839352-1.105853 2.819427-.986301 2.819427-.876712C2.819427-.288917 3.217933 .109589 3.73599 .109589C4.034869 .109589 4.303861-.049813 4.523039-.418431C4.772105-.856787 4.881694-1.404732 4.881694-1.424658C4.881694-1.524284 4.79203-1.524284 4.762142-1.524284C4.662516-1.524284 4.652553-1.484433 4.622665-1.344956C4.423412-.617684 4.194271-.109589 3.755915-.109589C3.566625-.109589 3.437111-.219178 3.437111-.577833C3.437111-.747198 3.476961-.976339 3.516812-1.135741C3.556663-1.305106 3.556663-1.344956 3.556663-1.444583C3.556663-2.092154 2.929016-2.381071 2.082192-2.49066C2.391034-2.669988 2.709838-2.988792 2.938979-3.227895C3.417186-3.755915 3.875467-4.184309 4.363636-4.184309C4.423412-4.184309 4.433375-4.184309 4.4533-4.174346C4.572852-4.154421 4.582814-4.154421 4.662516-4.094645C4.682441-4.084682 4.682441-4.07472 4.702366-4.054795C4.224159-4.024907 4.134496-3.636364 4.134496-3.516812C4.134496-3.35741 4.244085-3.16812 4.513076-3.16812C4.772105-3.16812 5.061021-3.387298 5.061021-3.775841C5.061021-4.07472 4.83188-4.403487 4.383562-4.403487C4.104608-4.403487 3.646326-4.323786 2.929016-3.526775C2.590286-3.148194 2.201743-2.749689 1.823163-2.600249L2.859278-6.804483Z"/>
|
||||
<path id="g4-110" d="M.876712-.587796C.846824-.438356 .787049-.209215 .787049-.159402C.787049 .019925 .926526 .109589 1.075965 .109589C1.195517 .109589 1.374844 .029888 1.444583-.169365C1.454545-.18929 1.574097-.657534 1.633873-.9066L1.853051-1.803238C1.912827-2.022416 1.972603-2.241594 2.022416-2.470735C2.062267-2.6401 2.141968-2.929016 2.15193-2.968867C2.30137-3.277709 2.82939-4.184309 3.775841-4.184309C4.224159-4.184309 4.313823-3.815691 4.313823-3.486924C4.313823-2.86924 3.825654-1.594022 3.666252-1.165629C3.576588-.936488 3.566625-.816936 3.566625-.707347C3.566625-.239103 3.915318 .109589 4.383562 .109589C5.32005 .109589 5.688667-1.344956 5.688667-1.424658C5.688667-1.524284 5.599004-1.524284 5.569116-1.524284C5.469489-1.524284 5.469489-1.494396 5.419676-1.344956C5.220423-.667497 4.891656-.109589 4.403487-.109589C4.234122-.109589 4.164384-.209215 4.164384-.438356C4.164384-.687422 4.254047-.926526 4.343711-1.145704C4.533001-1.673724 4.951432-2.769614 4.951432-3.337484C4.951432-4.004981 4.523039-4.403487 3.805729-4.403487C2.909091-4.403487 2.420922-3.765878 2.251557-3.536737C2.201743-4.094645 1.793275-4.403487 1.334994-4.403487S.687422-4.014944 .587796-3.835616C.428394-3.496887 .288917-2.909091 .288917-2.86924C.288917-2.769614 .388543-2.769614 .408468-2.769614C.508095-2.769614 .518057-2.779577 .577833-2.998755C.747198-3.706102 .946451-4.184309 1.305106-4.184309C1.504359-4.184309 1.613948-4.054795 1.613948-3.726027C1.613948-3.516812 1.58406-3.407223 1.454545-2.889166L.876712-.587796Z"/>
|
||||
</defs>
|
||||
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.13 0 0 1.13 -63.986043 -62.517865)">
|
||||
<use x="63.784475" y="59.522336" xlink:href="#g4-110"/>
|
||||
<use x="56.413267" y="63.826203" xlink:href="#g0-88"/>
|
||||
<use x="57.659296" y="94.65519" xlink:href="#g4-107"/>
|
||||
<use x="63.159516" y="94.65519" xlink:href="#g5-61"/>
|
||||
<use x="70.908264" y="94.65519" xlink:href="#g5-48"/>
|
||||
<use x="98.845683" y="67.749844" xlink:href="#g2-110"/>
|
||||
<use x="107.230806" y="67.749844" xlink:href="#g3-33"/>
|
||||
<rect x="80.722118" y="73.581689" height=".573822" width="48.534214"/>
|
||||
<use x="80.722118" y="87.295916" xlink:href="#g3-40"/>
|
||||
<use x="86.184907" y="87.295916" xlink:href="#g2-110"/>
|
||||
<use x="97.758026" y="87.295916" xlink:href="#g1-0"/>
|
||||
<use x="112.104214" y="87.295916" xlink:href="#g2-107"/>
|
||||
<use x="119.89161" y="87.295916" xlink:href="#g3-41"/>
|
||||
<use x="125.354398" y="87.295916" xlink:href="#g3-33"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
BIN
jekyll_site/img/arrangements-quantity.gif
Normal file
BIN
jekyll_site/img/arrangements-quantity.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
75
jekyll_site/img/three-elements-sequence.svg
Normal file
75
jekyll_site/img/three-elements-sequence.svg
Normal file
|
@ -0,0 +1,75 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="374.279367pt" height="47.44548pt" viewBox="-.239051 -.233139 374.279367 47.44548">
|
||||
<defs>
|
||||
<path id="g2-58" d="M2.6397-.688617C2.6397-1.104657 2.295391-1.391581 1.951083-1.391581C1.535043-1.391581 1.248119-1.047272 1.248119-.702964C1.248119-.286924 1.592428 0 1.936736 0C2.352776 0 2.6397-.344309 2.6397-.688617Z"/>
|
||||
<path id="g2-107" d="M4.031281-9.597605C4.045627-9.65499 4.07432-9.741067 4.07432-9.812798C4.07432-9.95626 3.930858-9.95626 3.902165-9.95626C3.887819-9.95626 3.371356-9.913221 3.113124-9.884529C2.869239-9.870183 2.654046-9.84149 2.395815-9.827144C2.051506-9.798452 1.951083-9.784105 1.951083-9.525874C1.951083-9.382412 2.094545-9.382412 2.238007-9.382412C2.969663-9.382412 2.969663-9.253296 2.969663-9.109834C2.969663-9.052449 2.969663-9.023757 2.897932-8.765526L.846426-.559502C.789041-.344309 .789041-.315616 .789041-.229539C.789041 .086077 1.032926 .143462 1.176388 .143462C1.578082 .143462 1.664159-.172154 1.778928-.616886L2.453199-3.299625C3.486126-3.184855 4.103012-2.75447 4.103012-2.065852C4.103012-1.979775 4.103012-1.92239 4.059973-1.707197C4.002589-1.492004 4.002589-1.31985 4.002589-1.248119C4.002589-.41604 4.547744 .143462 5.2794 .143462C5.939325 .143462 6.283634-.459078 6.398403-.659925C6.699673-1.190734 6.886174-1.994121 6.886174-2.051506C6.886174-2.123237 6.828789-2.180622 6.742712-2.180622C6.613596-2.180622 6.59925-2.123237 6.541865-1.893698C6.341018-1.147696 6.039748-.143462 5.308092-.143462C5.021168-.143462 4.834668-.286924 4.834668-.832079C4.834668-1.104657 4.892053-1.420273 4.949438-1.635466C5.006822-1.893698 5.006822-1.908044 5.006822-2.080198C5.006822-2.926624 4.246474-3.400048 2.926624-3.572203C3.443087-3.887819 3.95955-4.447321 4.160397-4.662514C4.97813-5.58067 5.537632-6.039748 6.197557-6.039748C6.527519-6.039748 6.613596-5.953671 6.71402-5.867594C6.18321-5.810209 5.982364-5.437208 5.982364-5.150284C5.982364-4.805976 6.254941-4.691206 6.455788-4.691206C6.843135-4.691206 7.187444-5.021168 7.187444-5.480247C7.187444-5.896286 6.857482-6.326672 6.211903-6.326672C5.422862-6.326672 4.777283-5.767171 3.758703-4.619475C3.615241-4.447321 3.084432-3.902165 2.553623-3.701318L4.031281-9.597605Z"/>
|
||||
<path id="g3-33" d="M2.6397-9.583259C2.6397-10.042337 2.252353-10.25753 1.951083-10.25753S1.20508-10.056683 1.248119-9.454143L1.764582-2.883585C1.778928-2.6397 1.807621-2.582315 1.936736-2.582315C2.080198-2.582315 2.108891-2.625354 2.123237-2.883585L2.6397-9.583259ZM2.6397-.702964C2.6397-1.075965 2.324084-1.391581 1.951083-1.391581C1.549389-1.391581 1.248119-1.075965 1.248119-.688617C1.248119-.315616 1.563735 0 1.936736 0C2.33843 0 2.6397-.315616 2.6397-.702964Z"/>
|
||||
<path id="g3-40" d="M4.662514 3.486126C4.662514 3.443087 4.662514 3.414395 4.418628 3.170509C2.984009 1.721543 2.180622-.645579 2.180622-3.572203C2.180622-6.355365 2.854893-8.751179 4.519052-10.44403C4.662514-10.573146 4.662514-10.601839 4.662514-10.644877C4.662514-10.730954 4.590783-10.759647 4.533398-10.759647C4.346897-10.759647 3.170509-9.726721 2.467546-8.320793C1.73589-6.871828 1.405927-5.336785 1.405927-3.572203C1.405927-2.295391 1.606774-.588194 2.352776 .946849C3.199202 2.668392 4.37559 3.600895 4.533398 3.600895C4.590783 3.600895 4.662514 3.572203 4.662514 3.486126Z"/>
|
||||
<path id="g3-41" d="M4.045627-3.572203C4.045627-4.662514 3.902165-6.441442 3.098778-8.105601C2.252353-9.827144 1.075965-10.759647 .918157-10.759647C.860772-10.759647 .789041-10.730954 .789041-10.644877C.789041-10.601839 .789041-10.573146 1.032926-10.329261C2.467546-8.880295 3.270933-6.513173 3.270933-3.586549C3.270933-.803387 2.596661 1.592428 .932503 3.285279C.789041 3.414395 .789041 3.443087 .789041 3.486126C.789041 3.572203 .860772 3.600895 .918157 3.600895C1.104657 3.600895 2.281045 2.567969 2.984009 1.162042C3.715665-.30127 4.045627-1.850659 4.045627-3.572203Z"/>
|
||||
<path id="g3-43" d="M5.724132-3.313971H9.683682C9.884529-3.313971 10.14276-3.313971 10.14276-3.572203C10.14276-3.84478 9.898875-3.84478 9.683682-3.84478H5.724132V-7.80433C5.724132-8.005177 5.724132-8.263409 5.465901-8.263409C5.193323-8.263409 5.193323-8.019523 5.193323-7.80433V-3.84478H1.233773C1.032926-3.84478 .774695-3.84478 .774695-3.586549C.774695-3.313971 1.01858-3.313971 1.233773-3.313971H5.193323V.645579C5.193323 .846426 5.193323 1.104657 5.451554 1.104657C5.724132 1.104657 5.724132 .860772 5.724132 .645579V-3.313971Z"/>
|
||||
<path id="g3-48" d="M6.427096-4.590783C6.427096-5.781517 6.355365-6.943559 5.838902-8.03387C5.250708-9.224604 4.217782-9.54022 3.514818-9.54022C2.682739-9.54022 1.664159-9.12418 1.133349-7.933446C.731656-7.029636 .588194-6.140172 .588194-4.590783C.588194-3.199202 .688617-2.151929 1.20508-1.133349C1.764582-.043039 2.75447 .30127 3.500472 .30127C4.748591 .30127 5.465901-.444732 5.88194-1.276811C6.398403-2.352776 6.427096-3.758703 6.427096-4.590783ZM3.500472 .014346C3.041393 .014346 2.108891-.243885 1.836313-1.807621C1.678505-2.668392 1.678505-3.758703 1.678505-4.762937C1.678505-5.939325 1.678505-7.000943 1.908044-7.847369C2.151929-8.808564 2.883585-9.253296 3.500472-9.253296C4.045627-9.253296 4.877707-8.923334 5.150284-7.689561C5.336785-6.871828 5.336785-5.738478 5.336785-4.762937C5.336785-3.801742 5.336785-2.711431 5.178977-1.836313C4.906399-.258232 4.002589 .014346 3.500472 .014346Z"/>
|
||||
<path id="g3-49" d="M4.131704-9.195911C4.131704-9.525874 4.131704-9.54022 3.84478-9.54022C3.500472-9.152873 2.783162-8.622064 1.305504-8.622064V-8.206024C1.635466-8.206024 2.352776-8.206024 3.141817-8.579025V-1.104657C3.141817-.588194 3.098778-.41604 1.836313-.41604H1.391581V0C1.778928-.028692 3.170509-.028692 3.643934-.028692S5.494593-.028692 5.88194 0V-.41604H5.437208C4.174743-.41604 4.131704-.588194 4.131704-1.104657V-9.195911Z"/>
|
||||
<path id="g3-50" d="M6.312326-2.410161H5.99671C5.953671-2.166276 5.838902-1.377235 5.69544-1.147696C5.595016-1.01858 4.777283-1.01858 4.346897-1.01858H1.692851C2.080198-1.348542 2.955316-2.266699 3.328317-2.611008C5.508939-4.619475 6.312326-5.365477 6.312326-6.785751C6.312326-8.435563 5.006822-9.54022 3.342664-9.54022S.702964-8.119947 .702964-6.886174C.702964-6.154518 1.334196-6.154518 1.377235-6.154518C1.678505-6.154518 2.051506-6.369711 2.051506-6.828789C2.051506-7.230483 1.778928-7.50306 1.377235-7.50306C1.248119-7.50306 1.219427-7.50306 1.176388-7.488714C1.448966-8.464255 2.22366-9.12418 3.156163-9.12418C4.37559-9.12418 5.121592-8.105601 5.121592-6.785751C5.121592-5.566324 4.418628-4.504705 3.600895-3.586549L.702964-.344309V0H5.939325L6.312326-2.410161Z"/>
|
||||
<path id="g3-51" d="M2.6397-5.150284C2.395815-5.135938 2.33843-5.121592 2.33843-4.992476C2.33843-4.849014 2.410161-4.849014 2.668392-4.849014H3.328317C4.547744-4.849014 5.092899-3.84478 5.092899-2.467546C5.092899-.588194 4.117358-.086077 3.414395-.086077C2.725777-.086077 1.549389-.41604 1.133349-1.362889C1.592428-1.291158 2.008467-1.549389 2.008467-2.065852C2.008467-2.481892 1.707197-2.768816 1.305504-2.768816C.961195-2.768816 .588194-2.567969 .588194-2.022814C.588194-.746002 1.865005 .30127 3.457433 .30127C5.16463 .30127 6.427096-1.004234 6.427096-2.453199C6.427096-3.773049 5.365477-4.805976 3.988242-5.049861C5.236361-5.408516 6.039748-6.455788 6.039748-7.574791C6.039748-8.708141 4.86336-9.54022 3.471779-9.54022C2.03716-9.54022 .975541-8.665102 .975541-7.61783C.975541-7.043982 1.420273-6.929213 1.635466-6.929213C1.936736-6.929213 2.281045-7.144405 2.281045-7.574791C2.281045-8.03387 1.936736-8.234716 1.62112-8.234716C1.535043-8.234716 1.506351-8.234716 1.463312-8.22037C2.008467-9.195911 3.35701-9.195911 3.428741-9.195911C3.902165-9.195911 4.834668-8.980718 4.834668-7.574791C4.834668-7.302214 4.791629-6.498827 4.37559-5.88194C3.945204-5.250708 3.457433-5.207669 3.070086-5.193323L2.6397-5.150284Z"/>
|
||||
<path id="g3-54" d="M1.764582-4.992476C1.764582-8.622064 3.529164-9.195911 4.303859-9.195911C4.820322-9.195911 5.336785-9.038103 5.609363-8.607717C5.437208-8.607717 4.892053-8.607717 4.892053-8.019523C4.892053-7.703907 5.107246-7.431329 5.480247-7.431329C5.838902-7.431329 6.082787-7.646522 6.082787-8.062562C6.082787-8.808564 5.537632-9.54022 4.289513-9.54022C2.481892-9.54022 .588194-7.689561 .588194-4.533398C.588194-.588194 2.309738 .30127 3.529164 .30127C5.092899 .30127 6.427096-1.061618 6.427096-2.926624C6.427096-4.834668 5.092899-6.111479 3.65828-6.111479C2.381468-6.111479 1.908044-5.006822 1.764582-4.605129V-4.992476ZM3.529164-.086077C2.625354-.086077 2.194968-.889464 2.065852-1.190734C1.936736-1.563735 1.793274-2.266699 1.793274-3.270933C1.793274-4.404282 2.309738-5.824555 3.600895-5.824555C4.389936-5.824555 4.805976-5.293746 5.021168-4.805976C5.250708-4.275166 5.250708-3.557857 5.250708-2.94097C5.250708-2.209314 5.250708-1.563735 4.97813-1.01858C4.619475-.329963 4.103012-.086077 3.529164-.086077Z"/>
|
||||
<path id="g3-61" d="M9.683682-4.648167C9.884529-4.648167 10.14276-4.648167 10.14276-4.906399C10.14276-5.178977 9.898875-5.178977 9.683682-5.178977H1.233773C1.032926-5.178977 .774695-5.178977 .774695-4.920745C.774695-4.648167 1.01858-4.648167 1.233773-4.648167H9.683682ZM9.683682-1.979775C9.884529-1.979775 10.14276-1.979775 10.14276-2.238007C10.14276-2.510584 9.898875-2.510584 9.683682-2.510584H1.233773C1.032926-2.510584 .774695-2.510584 .774695-2.252353C.774695-1.979775 1.01858-1.979775 1.233773-1.979775H9.683682Z"/>
|
||||
<path id="g4-107" d="M2.859278-6.804483C2.859278-6.814446 2.859278-6.914072 2.729763-6.914072C2.500623-6.914072 1.77335-6.834371 1.514321-6.814446C1.43462-6.804483 1.325031-6.794521 1.325031-6.615193C1.325031-6.495641 1.414695-6.495641 1.564134-6.495641C2.042341-6.495641 2.062267-6.425903 2.062267-6.326276L2.032379-6.127024L.587796-.388543C.547945-.249066 .547945-.229141 .547945-.169365C.547945 .059776 .747198 .109589 .836862 .109589C.966376 .109589 1.115816 .019925 1.175592-.099626C1.225405-.18929 1.673724-2.032379 1.733499-2.281445C2.072229-2.251557 2.889166-2.092154 2.889166-1.43462C2.889166-1.364882 2.889166-1.325031 2.859278-1.225405C2.839352-1.105853 2.819427-.986301 2.819427-.876712C2.819427-.288917 3.217933 .109589 3.73599 .109589C4.034869 .109589 4.303861-.049813 4.523039-.418431C4.772105-.856787 4.881694-1.404732 4.881694-1.424658C4.881694-1.524284 4.79203-1.524284 4.762142-1.524284C4.662516-1.524284 4.652553-1.484433 4.622665-1.344956C4.423412-.617684 4.194271-.109589 3.755915-.109589C3.566625-.109589 3.437111-.219178 3.437111-.577833C3.437111-.747198 3.476961-.976339 3.516812-1.135741C3.556663-1.305106 3.556663-1.344956 3.556663-1.444583C3.556663-2.092154 2.929016-2.381071 2.082192-2.49066C2.391034-2.669988 2.709838-2.988792 2.938979-3.227895C3.417186-3.755915 3.875467-4.184309 4.363636-4.184309C4.423412-4.184309 4.433375-4.184309 4.4533-4.174346C4.572852-4.154421 4.582814-4.154421 4.662516-4.094645C4.682441-4.084682 4.682441-4.07472 4.702366-4.054795C4.224159-4.024907 4.134496-3.636364 4.134496-3.516812C4.134496-3.35741 4.244085-3.16812 4.513076-3.16812C4.772105-3.16812 5.061021-3.387298 5.061021-3.775841C5.061021-4.07472 4.83188-4.403487 4.383562-4.403487C4.104608-4.403487 3.646326-4.323786 2.929016-3.526775C2.590286-3.148194 2.201743-2.749689 1.823163-2.600249L2.859278-6.804483Z"/>
|
||||
<path id="g0-88" d="M18.162284 20.084674L19.898173 15.493891H19.539518C18.980017 16.985896 17.45932 17.961437 15.809508 18.391823C15.508238 18.463554 14.10231 18.836555 11.347841 18.836555H2.697085L9.999298 10.271876C10.099722 10.157107 10.128414 10.114068 10.128414 10.042337C10.128414 10.013645 10.128414 9.970606 10.027991 9.827144L3.342664 .688617H11.204379C13.126769 .688617 14.432273 .889464 14.561389 .918157C15.336083 1.032926 16.584202 1.276811 17.717552 1.994121C18.076207 2.22366 19.051748 2.869239 19.539518 4.031281H19.898173L18.162284 0H1.20508C.875118 0 .860772 .014346 .817733 .100423C.803387 .143462 .803387 .41604 .803387 .573848L8.392524 10.960493L.961195 19.668634C.817733 19.840789 .817733 19.91252 .817733 19.926866C.817733 20.084674 .946849 20.084674 1.20508 20.084674H18.162284Z"/>
|
||||
<path id="g1-0" d="M9.454143-3.299625C9.698028-3.299625 9.95626-3.299625 9.95626-3.586549S9.698028-3.873473 9.454143-3.873473H1.692851C1.448966-3.873473 1.190734-3.873473 1.190734-3.586549S1.448966-3.299625 1.692851-3.299625H9.454143Z"/>
|
||||
<path id="g5-48" d="M4.582814-3.188045C4.582814-3.985056 4.533001-4.782067 4.184309-5.519303C3.726027-6.475716 2.909091-6.635118 2.49066-6.635118C1.892902-6.635118 1.165629-6.37609 .757161-5.449564C.438356-4.762142 .388543-3.985056 .388543-3.188045C.388543-2.440847 .428394-1.544209 .836862-.787049C1.265255 .019925 1.992528 .219178 2.480697 .219178C3.01868 .219178 3.775841 .009963 4.214197-.936488C4.533001-1.62391 4.582814-2.400996 4.582814-3.188045ZM2.480697 0C2.092154 0 1.504359-.249066 1.325031-1.205479C1.215442-1.803238 1.215442-2.719801 1.215442-3.307597C1.215442-3.945205 1.215442-4.60274 1.295143-5.140722C1.484433-6.326276 2.231631-6.41594 2.480697-6.41594C2.809465-6.41594 3.466999-6.236613 3.656289-5.250311C3.755915-4.692403 3.755915-3.935243 3.755915-3.307597C3.755915-2.560399 3.755915-1.882939 3.646326-1.24533C3.496887-.298879 2.929016 0 2.480697 0Z"/>
|
||||
<path id="g5-51" d="M2.889166-3.506849C3.706102-3.775841 4.283935-4.473225 4.283935-5.260274C4.283935-6.07721 3.407223-6.635118 2.450809-6.635118C1.444583-6.635118 .687422-6.03736 .687422-5.280199C.687422-4.951432 .9066-4.762142 1.195517-4.762142C1.504359-4.762142 1.703611-4.98132 1.703611-5.270237C1.703611-5.768369 1.235367-5.768369 1.085928-5.768369C1.39477-6.256538 2.052304-6.386052 2.410959-6.386052C2.819427-6.386052 3.367372-6.166874 3.367372-5.270237C3.367372-5.150685 3.347447-4.572852 3.088418-4.134496C2.789539-3.656289 2.450809-3.626401 2.201743-3.616438C2.122042-3.606476 1.882939-3.58655 1.8132-3.58655C1.733499-3.576588 1.663761-3.566625 1.663761-3.466999C1.663761-3.35741 1.733499-3.35741 1.902864-3.35741H2.34122C3.158157-3.35741 3.526775-2.67995 3.526775-1.703611C3.526775-.348692 2.839352-.059776 2.400996-.059776C1.972603-.059776 1.225405-.229141 .876712-.816936C1.225405-.767123 1.534247-.986301 1.534247-1.364882C1.534247-1.723537 1.265255-1.92279 .976339-1.92279C.737235-1.92279 .418431-1.783313 .418431-1.344956C.418431-.438356 1.344956 .219178 2.430884 .219178C3.646326 .219178 4.552927-.687422 4.552927-1.703611C4.552927-2.520548 3.92528-3.297634 2.889166-3.506849Z"/>
|
||||
<path id="g5-61" d="M6.844334-3.257783C6.993773-3.257783 7.183064-3.257783 7.183064-3.457036S6.993773-3.656289 6.854296-3.656289H.886675C.747198-3.656289 .557908-3.656289 .557908-3.457036S.747198-3.257783 .896638-3.257783H6.844334ZM6.854296-1.325031C6.993773-1.325031 7.183064-1.325031 7.183064-1.524284S6.993773-1.723537 6.844334-1.723537H.896638C.747198-1.723537 .557908-1.723537 .557908-1.524284S.747198-1.325031 .886675-1.325031H6.854296Z"/>
|
||||
</defs>
|
||||
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.13 0 0 1.13 -63.986043 -62.403623)">
|
||||
<use x="64.283777" y="61.653246" xlink:href="#g5-51"/>
|
||||
<use x="56.413267" y="65.957113" xlink:href="#g0-88"/>
|
||||
<use x="57.659296" y="96.7861" xlink:href="#g4-107"/>
|
||||
<use x="63.159516" y="96.7861" xlink:href="#g5-61"/>
|
||||
<use x="70.908264" y="96.7861" xlink:href="#g5-48"/>
|
||||
<use x="98.845683" y="69.880754" xlink:href="#g3-51"/>
|
||||
<use x="105.869268" y="69.880754" xlink:href="#g3-33"/>
|
||||
<rect x="80.722118" y="75.712599" height=".573822" width="47.172666"/>
|
||||
<use x="80.722118" y="89.426826" xlink:href="#g3-40"/>
|
||||
<use x="86.184907" y="89.426826" xlink:href="#g3-51"/>
|
||||
<use x="96.396488" y="89.426826" xlink:href="#g1-0"/>
|
||||
<use x="110.742676" y="89.426826" xlink:href="#g2-107"/>
|
||||
<use x="118.530072" y="89.426826" xlink:href="#g3-41"/>
|
||||
<use x="123.99286" y="89.426826" xlink:href="#g3-33"/>
|
||||
<use x="133.075293" y="79.586059" xlink:href="#g3-61"/>
|
||||
<use x="149.181379" y="69.880754" xlink:href="#g3-51"/>
|
||||
<use x="156.204965" y="69.880754" xlink:href="#g3-33"/>
|
||||
<rect x="149.181379" y="75.712599" height=".573822" width="10.925551"/>
|
||||
<use x="149.181379" y="89.426826" xlink:href="#g3-51"/>
|
||||
<use x="156.204965" y="89.426826" xlink:href="#g3-33"/>
|
||||
<use x="164.490441" y="79.586059" xlink:href="#g3-43"/>
|
||||
<use x="179.799528" y="69.880754" xlink:href="#g3-51"/>
|
||||
<use x="186.823113" y="69.880754" xlink:href="#g3-33"/>
|
||||
<rect x="179.799528" y="75.712599" height=".573822" width="10.925551"/>
|
||||
<use x="179.799528" y="89.426826" xlink:href="#g3-50"/>
|
||||
<use x="186.823113" y="89.426826" xlink:href="#g3-33"/>
|
||||
<use x="195.108589" y="79.586059" xlink:href="#g3-43"/>
|
||||
<use x="210.417676" y="69.880754" xlink:href="#g3-51"/>
|
||||
<use x="217.441262" y="69.880754" xlink:href="#g3-33"/>
|
||||
<rect x="210.417676" y="75.712599" height=".573822" width="10.925551"/>
|
||||
<use x="210.417676" y="89.426826" xlink:href="#g3-49"/>
|
||||
<use x="217.441262" y="89.426826" xlink:href="#g3-33"/>
|
||||
<use x="225.726738" y="79.586059" xlink:href="#g3-43"/>
|
||||
<use x="241.035825" y="69.880754" xlink:href="#g3-51"/>
|
||||
<use x="248.05941" y="69.880754" xlink:href="#g3-33"/>
|
||||
<rect x="241.035825" y="75.712599" height=".573822" width="10.925551"/>
|
||||
<use x="241.035825" y="89.426826" xlink:href="#g3-48"/>
|
||||
<use x="248.05941" y="89.426826" xlink:href="#g3-33"/>
|
||||
<use x="257.141885" y="79.586059" xlink:href="#g3-61"/>
|
||||
<use x="272.052458" y="79.586059" xlink:href="#g3-49"/>
|
||||
<use x="282.264039" y="79.586059" xlink:href="#g3-43"/>
|
||||
<use x="296.377613" y="79.586059" xlink:href="#g3-51"/>
|
||||
<use x="306.589194" y="79.586059" xlink:href="#g3-43"/>
|
||||
<use x="320.702767" y="79.586059" xlink:href="#g3-54"/>
|
||||
<use x="330.914349" y="79.586059" xlink:href="#g3-43"/>
|
||||
<use x="345.027922" y="79.586059" xlink:href="#g3-54"/>
|
||||
<use x="356.036503" y="79.586059" xlink:href="#g3-61"/>
|
||||
<use x="370.947075" y="79.586059" xlink:href="#g3-49"/>
|
||||
<use x="377.970661" y="79.586059" xlink:href="#g3-54"/>
|
||||
<use x="384.994246" y="79.586059" xlink:href="#g2-58"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 17 KiB |
7
jekyll_site/robots.txt
Normal file
7
jekyll_site/robots.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
User-agent: *
|
||||
Disallow: *404*
|
||||
|
||||
Sitemap: https://pomodoro2.mircloud.ru/pagesmap.xml
|
||||
Sitemap: https://pomodoro2.mircloud.ru/color/pagesmap.xml
|
||||
|
||||
Host: https://pomodoro2.mircloud.ru
|
212
jekyll_site/ru/2021/09/06/cartesian-product-of-sets.md
Normal file
212
jekyll_site/ru/2021/09/06/cartesian-product-of-sets.md
Normal file
|
@ -0,0 +1,212 @@
|
|||
---
|
||||
title: Декартово произведение множеств
|
||||
description: Рассмотрим алгоритм получения декартова произведения нескольких множеств с использованием трёх вложенных циклов. Количество множеств и их элементов может...
|
||||
sections: [Комбинаторика,Прямое произведение]
|
||||
tags: [java,комбинаторика,алгоритмы,декартово произведение,комбинации,множество,список,массив,циклы,вложенные циклы]
|
||||
canonical_url: /ru/2021/09/06/cartesian-product-of-sets.html
|
||||
url_translated: /en/2021/09/07/cartesian-product-of-sets.html
|
||||
title_translated: Cartesian product of sets
|
||||
date: 2021.09.06
|
||||
---
|
||||
|
||||
Рассмотрим алгоритм получения *декартова произведения* нескольких множеств с использованием
|
||||
трёх вложенных циклов. Количество множеств и их элементов может быть произвольным. Последовательно
|
||||
перемножаем множества и накапливаем результат. Порядок значения не имеет, так как от перестановки
|
||||
множителей произведение не меняется. В результате порядок будет отличаться, но комбинации будут
|
||||
те же самые.
|
||||
|
||||
Для наглядности возьмём несколько *упорядоченных* множеств:
|
||||
|
||||
```
|
||||
a = [A,B,C,D]
|
||||
b = [E,F,G]
|
||||
c = [H,I]
|
||||
d = [J]
|
||||
```
|
||||
|
||||
Количество возможных комбинаций — это произведение количеств элементов всех множеств:
|
||||
|
||||
```
|
||||
4 * 3 * 2 * 1 = 24
|
||||
```
|
||||
|
||||
Напишем метод на Java для решения подобных задач, будем использовать три вложенных цикла `for`.
|
||||
|
||||
Сначала подготавливаем *список списков* `List<List<T>>`, заполненный одним пустым значением.
|
||||
Будем использовать его как промежуточный результат и как финальный результат.
|
||||
|
||||
Затем обходим переданные списки и последовательно дополняем промежуточный результат
|
||||
их элементами. На каждом шаге получаем новый промежуточный результат и двигаемся дальше.
|
||||
Таким образом последовательно перемножаем пары списков и постепенно накапливаем результат.
|
||||
|
||||
Схематически этот процесс выглядит следующим образом:
|
||||
|
||||
```
|
||||
result0: [[]]
|
||||
list1: [A,B,C,D]
|
||||
--------
|
||||
result1: [[A],[B],[C],[D]]
|
||||
list2: [E,F,G]
|
||||
--------
|
||||
result2: [[A,E],[A,F],[A,G],[B,E],[B,F],...[D,G]]
|
||||
list3: [H,I]
|
||||
--------
|
||||
result3: [[A,E,H],[A,E,I],[A,F,H],[A,F,I],[A,G,H],...[D,G,I]]
|
||||
list4: [J]
|
||||
--------
|
||||
result4: [[A,E,H,J],[A,E,I,J],[A,F,H,J],[A,F,I,J],[A,G,H,J],...[D,G,I,J]]
|
||||
```
|
||||
|
||||
### Комбинации по столбцам {#combinations-by-columns}
|
||||
|
||||
```
|
||||
Количество комбинаций: 24
|
||||
[A, E, H, J] [B, E, H, J] [C, E, H, J] [D, E, H, J]
|
||||
[A, E, I, J] [B, E, I, J] [C, E, I, J] [D, E, I, J]
|
||||
[A, F, H, J] [B, F, H, J] [C, F, H, J] [D, F, H, J]
|
||||
[A, F, I, J] [B, F, I, J] [C, F, I, J] [D, F, I, J]
|
||||
[A, G, H, J] [B, G, H, J] [C, G, H, J] [D, G, H, J]
|
||||
[A, G, I, J] [B, G, I, J] [C, G, I, J] [D, G, I, J]
|
||||
```
|
||||
|
||||
## Декартово произведение списков {#cartesian-product-of-lists}
|
||||
|
||||
Список может содержать *изменяемое количество* элементов. Это упрощает код.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param lists произвольное количество списков
|
||||
* @param <T> тип элементов списков
|
||||
* @return декартово произведение переданных списков
|
||||
*/
|
||||
public static <T> List<List<T>> cartesianProduct(List<List<T>> lists) {
|
||||
// входящие данные не равны null
|
||||
if (lists == null) return Collections.emptyList();
|
||||
// промежуточный результат, содержит одно пустое значение
|
||||
List<List<T>> cp = Collections.singletonList(Collections.<T>emptyList());
|
||||
// обходим переданные списки
|
||||
for (List<T> list : lists) {
|
||||
// ненулевые и непустые списки
|
||||
if (list == null || list.size() == 0) continue;
|
||||
// следующий промежуточный результат
|
||||
List<List<T>> next = new ArrayList<>();
|
||||
// строки текущего промежуточного результата
|
||||
for (List<T> row : cp) {
|
||||
// элементы текущего списка
|
||||
for (T el : list) {
|
||||
// новая строка для следующего промежуточного
|
||||
// результата, копируем текущую строку
|
||||
List<T> nRow = new ArrayList<>(row);
|
||||
// добавляем текущий элемент
|
||||
nRow.add(el);
|
||||
// помещаем в следующий промежуточный результат
|
||||
next.add(nRow);
|
||||
}
|
||||
}
|
||||
// обновляем промежуточный результат
|
||||
cp = next;
|
||||
}
|
||||
// возвращаем итоговый результат
|
||||
return cp;
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// запускаем программу и выводим результат
|
||||
public static void main(String[] args) {
|
||||
// произвольное количество списков и их элементов
|
||||
List<String> a = Arrays.asList("A", "B", "C", "D");
|
||||
List<String> b = Arrays.asList("E", "F", "G");
|
||||
List<String> c = Arrays.asList("H", "I");
|
||||
List<String> d = Arrays.asList("J");
|
||||
// декартово произведение
|
||||
List<List<String>> cp = cartesianProduct(Arrays.asList(a, b, c, d));
|
||||
// вывод
|
||||
System.out.println("Количество комбинаций: " + cp.size());
|
||||
// комбинации по столбцам
|
||||
int rows = 6;
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cp.size(); j++)
|
||||
if (j % rows == i)
|
||||
System.out.print(" " + cp.get(j));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Вывод для этого и следующего кода одинаковый, см. выше: [комбинации по столбцам](#combinations-by-columns).
|
||||
|
||||
## Декартово произведение массивов {#cartesian-product-of-arrays}
|
||||
|
||||
Массив содержит *фиксированное количество* элементов. Код выглядит немного сложнее.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param arrays произвольное количество массивов
|
||||
* @param clazz класс элементов массивов
|
||||
* @param <T> тип элементов массивов
|
||||
* @return декартово произведение переданных массивов
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[][] cartesianProduct(Class<T> clazz, T[]... arrays) {
|
||||
// входящие данные не равны null
|
||||
if (clazz == null || arrays == null)
|
||||
return (T[][]) Array.newInstance(clazz, 0, 0);
|
||||
// промежуточный результат, содержит одну пустую строку
|
||||
T[][] cp = (T[][]) Array.newInstance(clazz, 1, 0);
|
||||
// обходим переданные массивы
|
||||
for (int a = 0; a < arrays.length; a++) {
|
||||
// текущий массив
|
||||
T[] arr = arrays[a];
|
||||
// ненулевой и непустой массив
|
||||
if (arr == null || arr.length == 0) continue;
|
||||
// следующий промежуточный результат, указываем количество строк
|
||||
T[][] next = (T[][]) Array.newInstance(clazz,cp.length*arr.length,0);
|
||||
// строки текущего промежуточного результата
|
||||
for (int r = 0; r < cp.length; r++) {
|
||||
// текущая строка
|
||||
T[] row = cp[r];
|
||||
// элементы текущего массива
|
||||
for (int e = 0; e < arr.length; e++) {
|
||||
// текущий элемент
|
||||
T el = arr[e];
|
||||
// копируем текущую строку в новый массив [длина + 1]
|
||||
T[] nRow = Arrays.copyOf(row, row.length + 1);
|
||||
// добавляем текущий элемент
|
||||
nRow[row.length] = el;
|
||||
// помещаем в следующий промежуточный результат
|
||||
next[r * arr.length + e] = nRow;
|
||||
}
|
||||
}
|
||||
// обновляем промежуточный результат
|
||||
cp = next;
|
||||
}
|
||||
// возвращаем итоговый результат
|
||||
return cp;
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// запускаем программу и выводим результат
|
||||
public static void main(String[] args) {
|
||||
// произвольное количество массивов и их элементов
|
||||
String[] a = {"A", "B", "C", "D"};
|
||||
String[] b = {"E", "F", "G"};
|
||||
String[] c = {"H", "I"};
|
||||
String[] d = {"J"};
|
||||
// декартово произведение
|
||||
String[][] cp = cartesianProduct(String.class, a, b, c, d);
|
||||
// вывод
|
||||
System.out.println("Количество комбинаций: " + cp.length);
|
||||
// комбинации по столбцам
|
||||
int rows = 6;
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cp.length; j++)
|
||||
if (j % rows == i)
|
||||
System.out.print(" " + Arrays.toString(cp[j]));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Вывод для этого и предыдущего кода одинаковый, см. выше: [комбинации по столбцам](#combinations-by-columns).
|
70
jekyll_site/ru/2021/09/09/pascals-triangle-in-java.md
Normal file
70
jekyll_site/ru/2021/09/09/pascals-triangle-in-java.md
Normal file
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
title: Треугольник Паскаля на Java
|
||||
description: Рассмотрим вариант реализации треугольника Паскаля на Java. Для простоты хранения и обработки данных представим треугольник в виде двухмерного массива...
|
||||
sections: [Двухмерный массив,Биномиальные коэффициенты]
|
||||
tags: [java,алгоритмы,массив,двухмерный массив,циклы,вложенные циклы]
|
||||
canonical_url: /ru/2021/09/09/pascals-triangle-in-java.html
|
||||
url_translated: /en/2021/09/10/pascals-triangle-in-java.html
|
||||
title_translated: Pascal's Triangle in Java
|
||||
date: 2021.09.09
|
||||
---
|
||||
|
||||
Рассмотрим вариант реализации *треугольника Паскаля* на Java. Для простоты хранения и обработки
|
||||
данных представим треугольник в виде двухмерного массива, в котором элементы первой строки и колонки
|
||||
равны единице, а все остальные элементы — есть сумма двух предыдущих элементов в строке и в колонке.
|
||||
|
||||
```
|
||||
A[i][j] = A[i][j-1] + A[i-1][j];
|
||||
```
|
||||
|
||||
Например, при {`n = 8`} массив будет выглядеть следующим образом:
|
||||
|
||||
```
|
||||
1 1 1 1 1 1 1 1
|
||||
1 2 3 4 5 6 7
|
||||
1 3 6 10 15 21
|
||||
1 4 10 20 35
|
||||
1 5 15 35
|
||||
1 6 21
|
||||
1 7
|
||||
1
|
||||
```
|
||||
|
||||
Создаём и заполняем двухмерный массив с убывающей длиной строки:
|
||||
|
||||
```java
|
||||
int n = 8;
|
||||
// массив из 'n' строк
|
||||
int[][] arr = new int[n][];
|
||||
// обходим строки массива
|
||||
for (int i = 0; i < n; i++) {
|
||||
// строка из 'n-i' элементов
|
||||
arr[i] = new int[n - i];
|
||||
// обходим элементы строки
|
||||
for (int j = 0; j < n - i; j++) {
|
||||
if (i == 0 || j == 0) {
|
||||
// элементы первой строки
|
||||
// и колонки равны единице
|
||||
arr[i][j] = 1;
|
||||
} else {
|
||||
// все остальные элементы — есть сумма двух
|
||||
// предыдущих элементов в строке и в колонке
|
||||
arr[i][j] = arr[i][j - 1] + arr[i - 1][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Выводим массив построчно:
|
||||
|
||||
```java
|
||||
// обходим строки массива
|
||||
for (int[] row : arr) {
|
||||
// обходим элементы строки
|
||||
for (int el : row)
|
||||
// пробел и двузначное число
|
||||
System.out.printf(" %2d", el);
|
||||
// переход на новую строку
|
||||
System.out.println();
|
||||
}
|
||||
```
|
153
jekyll_site/ru/2021/09/13/combinations-by-columns.md
Normal file
153
jekyll_site/ru/2021/09/13/combinations-by-columns.md
Normal file
|
@ -0,0 +1,153 @@
|
|||
---
|
||||
title: Комбинации элементов по столбцам
|
||||
description: В двухмерном массиве данные хранятся построчно. Рассмотрим алгоритм получения декартова произведения по столбцам с использованием трёх вложенных циклов.
|
||||
sections: [Комбинаторика,Прямое произведение]
|
||||
tags: [java,комбинаторика,алгоритмы,декартово произведение,комбинации,колонки,множество,список,массив,циклы,вложенные циклы]
|
||||
canonical_url: /ru/2021/09/13/combinations-by-columns.html
|
||||
url_translated: /en/2021/09/14/combinations-by-columns.html
|
||||
title_translated: Combinations of elements by columns
|
||||
date: 2021.09.13
|
||||
---
|
||||
|
||||
В двухмерном массиве данные хранятся построчно. Рассмотрим алгоритм получения *декартова
|
||||
произведения* по столбцам с использованием трёх вложенных циклов. Количество строк и
|
||||
колонок таблицы может быть произвольным. Последовательно перемножаем колонки и накапливаем
|
||||
результат. Значения необязательно должны быть заполнены — нулевые элементы отбрасываем.
|
||||
|
||||
Для примера возьмём частично заполненный *зубчатый двухмерный массив*:
|
||||
|
||||
```java
|
||||
| col1 | col2 | col3 | col4
|
||||
-----|------|------|------|------
|
||||
row1 | "A1" | "B1" | "C1" | "D1"
|
||||
row2 | "A2" | "B2" | null | "D2"
|
||||
row3 | "A3" | null | null | "D3"
|
||||
row4 | "A4" | null |
|
||||
```
|
||||
|
||||
Количество возможных комбинаций — это произведение количеств элементов во всех колонках:
|
||||
|
||||
```
|
||||
4 * 2 * 1 * 3 = 24
|
||||
```
|
||||
|
||||
Напишем метод на Java для решения подобных задач, будем использовать три вложенных цикла `for`.
|
||||
|
||||
Сначала подготавливаем *список списков* `List<List<T>>`, заполненный одним пустым значением.
|
||||
Будем использовать его как промежуточный результат и как финальный результат.
|
||||
|
||||
Затем обходим колонки таблицы, пока они ещё есть, — последней считаем ту колонку, за которой
|
||||
все элементы нулевые. На каждом шаге дополняем промежуточный результат элементами текущей
|
||||
колонки и получаем новый промежуточный результат. Таким образом последовательно перемножаем
|
||||
колонки и постепенно накапливаем результат.
|
||||
|
||||
Схематически этот процесс выглядит следующим образом:
|
||||
|
||||
```
|
||||
res0 * col1 = res1 * col2 = res2 * col3 = res3 * col4 = res4
|
||||
-----|------|------|------|-------|------|----------|------|------------
|
||||
[] * A1 = A1 * B1 = A1,B1 * C1 = A1,B1,C1 * D1 = A1,B1,C1,D1
|
||||
* A2 = A2 * B2 = A1,B2 * = A1,B2,C1 * D2 = A1,B1,C1,D2
|
||||
* A3 = A3 * = A2,B1 * = A2,B1,C1 * D3 = A1,B1,C1,D3
|
||||
* A4 = A4 * = A2,B2 * = A2,B2,C1 * = A1,B2,C1,D1
|
||||
* = * = A3,B1 * = A3,B1,C1 * = A1,B2,C1,D2
|
||||
* = * = A3,B2 * = A3,B2,C1 * = A1,B2,C1,D3
|
||||
* = * = A4,B1 * = A4,B1,C1 * = A2,B1,C1,D1
|
||||
* = * = A4,B2 * = A4,B2,C1 * = A2,B1,C1,D2
|
||||
* = * = * = * = A2,B1,C1,D3
|
||||
* = * = * = * = A2,B2,C1,D1
|
||||
* = * = * = * = ...........
|
||||
* = * = * = * = ...........
|
||||
* = * = * = * = A4,B2,C1,D3
|
||||
-----|------|------|------|-------|------|----------|------|------------
|
||||
1 * 4 = 4 * 2 = 8 * 1 = 8 * 3 = 24
|
||||
```
|
||||
|
||||
### Комбинации по столбцам {#combinations-by-columns}
|
||||
|
||||
```
|
||||
Количество комбинаций: 24
|
||||
[A1, B1, C1, D1] [A2, B1, C1, D1] [A3, B1, C1, D1] [A4, B1, C1, D1]
|
||||
[A1, B1, C1, D2] [A2, B1, C1, D2] [A3, B1, C1, D2] [A4, B1, C1, D2]
|
||||
[A1, B1, C1, D3] [A2, B1, C1, D3] [A3, B1, C1, D3] [A4, B1, C1, D3]
|
||||
[A1, B2, C1, D1] [A2, B2, C1, D1] [A3, B2, C1, D1] [A4, B2, C1, D1]
|
||||
[A1, B2, C1, D2] [A2, B2, C1, D2] [A3, B2, C1, D2] [A4, B2, C1, D2]
|
||||
[A1, B2, C1, D3] [A2, B2, C1, D3] [A3, B2, C1, D3] [A4, B2, C1, D3]
|
||||
```
|
||||
|
||||
## Декартово произведение по столбцам {#cartesian-product-by-columns}
|
||||
|
||||
Код будет выглядеть проще, если предварительно *транспонировать* массив массивов, но если этого
|
||||
нельзя сделать, тогда во внешнем цикле обходим колонки массива до тех пор, пока они ещё есть.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param table двухмерный список
|
||||
* @param <T> тип элементов списка
|
||||
* @return декартово произведение элементов по столбцам
|
||||
*/
|
||||
public static <T> List<List<T>> cartesianProduct(List<List<T>> table) {
|
||||
// входящие данные не равны null
|
||||
if (table == null) return Collections.emptyList();
|
||||
// промежуточный результат, содержит одно пустое значение
|
||||
List<List<T>> cp = Collections.singletonList(Collections.<T>emptyList());
|
||||
// колонки ещё есть
|
||||
boolean notLast = true;
|
||||
// обходим колонки таблицы, пока они ещё есть
|
||||
for (int i = 0; notLast; i++) {
|
||||
// колонок больше нет
|
||||
notLast = false;
|
||||
// следующий промежуточный результат
|
||||
List<List<T>> next = new ArrayList<>();
|
||||
// обходим комбинации текущего промежуточного результата
|
||||
for (List<T> comb : cp) {
|
||||
// обходим строки таблицы
|
||||
for (List<T> row : table) {
|
||||
// если колонка ещё есть и значение в ней тоже есть
|
||||
if (row != null && i < row.size() && row.get(i) != null) {
|
||||
// новая комбинация, копируем текущую комбинацию
|
||||
List<T> nComb = new ArrayList<>(comb);
|
||||
// добавляем значение из колонки
|
||||
nComb.add(row.get(i));
|
||||
// помещаем в новый промежуточный результат
|
||||
next.add(nComb);
|
||||
// колонки ещё есть
|
||||
notLast = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// если колонки ещё есть, то обновляем промежуточный результат
|
||||
// и переходим на следующую итерацию, иначе выходим из цикла
|
||||
if (notLast) cp = next;
|
||||
}
|
||||
// возвращаем итоговый результат
|
||||
return cp;
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// запускаем программу и выводим результат
|
||||
public static void main(String[] args) {
|
||||
// произвольное количество строк и их элементов
|
||||
List<String> row1 = Arrays.asList("A1", "B1", "C1", "D1");
|
||||
List<String> row2 = Arrays.asList("A2", "B2", null, "D2");
|
||||
List<String> row3 = Arrays.asList("A3", null, null, "D3");
|
||||
List<String> row4 = Arrays.asList("A4", null);
|
||||
// зубчатый двухмерный список
|
||||
List<List<String>> table = Arrays.asList(row1, row2, row3, row4);
|
||||
// декартово произведение
|
||||
List<List<String>> cp = cartesianProduct(table);
|
||||
// вывод
|
||||
System.out.println("Количество комбинаций: " + cp.size());
|
||||
// комбинации по столбцам
|
||||
int rows = 6;
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cp.size(); j++)
|
||||
if (j % rows == i)
|
||||
System.out.print(" " + cp.get(j));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Вывод для этого кода см. выше: [комбинации по столбцам](#combinations-by-columns).
|
235
jekyll_site/ru/2021/09/20/combinations-of-sequence-elements.md
Normal file
235
jekyll_site/ru/2021/09/20/combinations-of-sequence-elements.md
Normal file
|
@ -0,0 +1,235 @@
|
|||
---
|
||||
title: Комбинации элементов последовательности
|
||||
description: Рассмотрим задачу, в которой нужно получить все возможные комбинации элементов последовательности, где количество элементов в комбинации не превышает...
|
||||
sections: [Комбинаторика,Размещения,Перестановки]
|
||||
tags: [java,комбинаторика,алгоритмы,размещения,перестановки,комбинации,последовательность,множество,список,циклы,вложенные циклы]
|
||||
canonical_url: /ru/2021/09/20/combinations-of-sequence-elements.html
|
||||
url_translated: /en/2021/09/22/combinations-of-sequence-elements.html
|
||||
title_translated: Combinations of sequence elements
|
||||
date: 2021.09.20
|
||||
---
|
||||
|
||||
Рассмотрим задачу, в которой нужно получить все возможные комбинации элементов последовательности,
|
||||
где количество элементов в комбинации не превышает заданного максимума, и напишем метод на Java
|
||||
с соответствующим отбором по минимальному и максимальному количеству элементов.
|
||||
|
||||
*[Задача о сервировке стола](#table-setting-problem) • [Метод для решения на Java](#combinations-of-length)*
|
||||
|
||||
*Размещением* называется упорядоченный набор {`k`} различных элементов из множества различных
|
||||
{`n`} элементов, где {<code>k ≤ n</code>}. Если {<code>k = n</code>}, то
|
||||
такой упорядоченный набор называется *перестановкой*. Для универсальности решения *перестановки*
|
||||
тоже будем учитывать как частный случай *размещения*.
|
||||
|
||||
## Количество возможных комбинаций {#number-of-possible-combinations}
|
||||
|
||||
Для наглядности возьмём последовательность из трёх элементов {`XYZ`}, нарисуем все возможные
|
||||
подмножества этого множества, добавим к ним перестановки и подсчитаем количество комбинаций.
|
||||
|
||||
{% include picture.html src="/img/arrangements-quantity.gif" size100=true background=true
|
||||
alt="Получаем количество всех возможных размещений элементов последовательности"
|
||||
caption="Получаем количество всех возможных размещений элементов последовательности" %}
|
||||
|
||||
Формула количества размещений:
|
||||
|
||||
{% include image_svg.html src="/img/arrangement-formula.svg" style="width: 83pt; height: 46pt;"
|
||||
alt="\sum_{k=0}^{n} {n! \over (n-k)!}" %}
|
||||
|
||||
Последовательность из трёх элементов:
|
||||
|
||||
{% include image_svg.html src="/img/three-elements-sequence.svg" style="width: 375pt; height: 48pt;"
|
||||
alt="\sum_{k=0}^{3} {3! \over (3-k)!} = {3! \over 3!} + {3! \over 2!} + {3! \over 1!} + {3! \over 0!} = 1+3+6+6 = 16." %}
|
||||
|
||||
Способ реализации на Java:
|
||||
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
// количество элементов последовательности
|
||||
int n = 3;
|
||||
// количество возможных комбинаций
|
||||
int sum = 0;
|
||||
// обходим возможные количества элементов
|
||||
for (int k = 0; k <= n; k++)
|
||||
// складываем количества размещений
|
||||
sum += factorial(n) / factorial(n - k);
|
||||
// вывод
|
||||
System.out.println(sum); // 16
|
||||
}
|
||||
// получаем факториал числа
|
||||
static int factorial(int n) {
|
||||
int fact = 1;
|
||||
for (int i = 2; i <= n; i++)
|
||||
fact *= i;
|
||||
return fact;
|
||||
}
|
||||
```
|
||||
|
||||
## Комбинации из трёх элементов {#combinations-of-elements}
|
||||
|
||||
Сравним две последовательности из трёх элементов: цифр {`123`} и букв {`XYZ`}. Тип элементов
|
||||
разный — комбинации одинаковые, потому что порядковые номера у элементов те же самые.
|
||||
|
||||
```
|
||||
Количество вариантов: 16
|
||||
[][1][2][3][12][13][21][23][31][32][123][132][213][231][312][321]
|
||||
[][X][Y][Z][XY][XZ][YX][YZ][ZX][ZY][XYZ][XZY][YXZ][YZX][ZXY][ZYX]
|
||||
```
|
||||
|
||||
Сравним последовательности из [`1..12`] элементов: количество вариантов быстро растёт
|
||||
и вскоре выходит за пределы `Integer`, далее при {<code>n > 12</code>} нужно
|
||||
будет использовать `Long`, а при {<code>n > 20</code>} — уже `BigInteger`.
|
||||
|
||||
```
|
||||
n Кол-во вариантов
|
||||
1 2
|
||||
2 5
|
||||
3 16
|
||||
4 65
|
||||
5 326
|
||||
6 1957
|
||||
7 13700
|
||||
8 109601
|
||||
9 986410
|
||||
10 9864101
|
||||
11 108505112
|
||||
12 1302061345
|
||||
```
|
||||
|
||||
Рассмотрим задачу, где нужно ограничить возможные варианты
|
||||
по максимальному количеству входящих в них элементов.
|
||||
|
||||
## Задача о сервировке стола {#table-setting-problem}
|
||||
|
||||
На ужин приглашено четверо гостей {<code>n = 4</code>}, из которых известно, что
|
||||
приедут не более двух человек {<code>k = 2</code>}, причём порядок их появления
|
||||
важен, поскольку от этого зависит сервировка стола. Известно также, что когда приедет первый,
|
||||
то он скажет, кто будет второй и приедет ли он. Рассчитать возможные варианты сервировки стола.
|
||||
|
||||
### Способ решения {#solution-approach}
|
||||
|
||||
Напишем метод на Java для решения подобных задач, который будет принимать на вход три параметра:
|
||||
размер последовательности, минимальное и максимальное количество элементов в комбинации.
|
||||
Возвращать метод будет список комбинаций указанной длины.
|
||||
|
||||
```java
|
||||
static List<Set<Integer>> combinationsOfElements(int size, int min, int max)
|
||||
```
|
||||
|
||||
Вызываем метод с отбором {<code>min=0; max=2</code>}
|
||||
и получаем список комбинаций указанной длины.
|
||||
|
||||
```java
|
||||
// задача о сервировке стола
|
||||
public static void main(String[] args) {
|
||||
// приглашено четверо гостей
|
||||
int[] arr = {1, 2, 3, 4};
|
||||
// n - количество элементов последовательности
|
||||
// k - максимальное количество элементов в комбинации
|
||||
int n = 4, k = 2;
|
||||
// комбинации элементов указанной длины [0..2]
|
||||
List<Set<Integer>> list = combinationsOfElements(n, 0, k);
|
||||
// вывод
|
||||
System.out.println("Количество вариантов: " + list.size());
|
||||
for (Set<Integer> set : list) {
|
||||
System.out.print("[");
|
||||
for (int i : set)
|
||||
System.out.print(arr[i]);
|
||||
System.out.print("]");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Вывод:
|
||||
|
||||
```
|
||||
Количество вариантов: 17
|
||||
[][1][2][3][4][12][13][14][21][23][24][31][32][34][41][42][43]
|
||||
```
|
||||
|
||||
## Комбинации элементов указанной длины {#combinations-of-length}
|
||||
|
||||
Пишем метод на Java с использованием трёх вложенных циклов `for`. Далее для проверки вызываем
|
||||
этот метод без отбора {<code>min=0; max=size</code>} и получаем все возможные комбинации.
|
||||
Для примера возьмём две последовательности из трёх элементов: цифр {`123`} и букв {`XYZ`}.
|
||||
|
||||
### Описание метода {#method-description}
|
||||
|
||||
Подготавливаем два списка комбинаций: результирующий список и текущий список. В текущем списке
|
||||
количество элементов во всех комбинациях будет одинаковым. Максимальное количество элементов
|
||||
в комбинации — это размер последовательности. Начинаем с одной пустой комбинации и постепенно
|
||||
увеличиваем количество элементов.
|
||||
|
||||
Обходим возможные количества элементов и дополняем текущие комбинации теми индексами, которых
|
||||
в них ещё нет. На каждом шаге увеличиваем текущее количество элементов в комбинациях на единицу
|
||||
и, если оно попадает в отбор, тогда добавляем эти комбинации к результату.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param size размер последовательности (0 ≤ min ≤ max ≤ size)
|
||||
* @param min минимальное количество элементов в комбинации
|
||||
* @param max максимальное количество элементов в комбинации
|
||||
* @return комбинации элементов указанной длины
|
||||
*/
|
||||
static List<Set<Integer>> combinationsOfElements(int size, int min, int max) {
|
||||
// некорректные входящие данные, возвращаем пустой список комбинаций
|
||||
if (0 > min || min > max || max > size) return Collections.emptyList();
|
||||
// результирующий список комбинаций
|
||||
List<Set<Integer>> result = new ArrayList<>();
|
||||
// текущий список комбинаций, количество элементов во всех
|
||||
// комбинациях одинаковое, начинаем с одной пустой комбинации
|
||||
List<Set<Integer>> sublist = Arrays.asList(Collections.<Integer>emptySet());
|
||||
// обходим возможные количества элементов в комбинации
|
||||
for (int l = 0; l < Math.min(size, max); l++) {
|
||||
// если текущее количество элементов входит в отбор,
|
||||
// тогда добавляем эти комбинации к результату
|
||||
if (l >= min) result.addAll(sublist);
|
||||
// следующий список комбинаций
|
||||
List<Set<Integer>> nSublist = new ArrayList<>();
|
||||
// обходим текущий список комбинаций
|
||||
for (Set<Integer> comb : sublist) {
|
||||
// обходим индексы элементов последовательности
|
||||
for (int i = 0; i < size; i++) {
|
||||
// пропускаем те индексы, которые уже есть
|
||||
if (comb.contains(i)) continue;
|
||||
// новая комбинация, копируем текущую
|
||||
Set<Integer> nComb = new LinkedHashSet<>(comb);
|
||||
// добавляем текущий индекс
|
||||
nComb.add(i);
|
||||
// помещаем в новый список комбинаций
|
||||
nSublist.add(nComb);
|
||||
}
|
||||
}
|
||||
// обновляем текущий список комбинаций
|
||||
sublist = nSublist;
|
||||
}
|
||||
// добавляем текущий список комбинаций к результату
|
||||
result.addAll(sublist);
|
||||
// возвращаем результат
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// запускаем программу и выводим результат
|
||||
public static void main(String[] args) {
|
||||
// две последовательности из трёх элементов
|
||||
Integer[] arr1 = {1, 2, 3};
|
||||
String[] arr2 = {"X", "Y", "Z"};
|
||||
// количество элементов последовательности
|
||||
int n = 3;
|
||||
// все возможные комбинации элементов [0..n]
|
||||
List<Set<Integer>> list = combinationsOfElements(n, 0, n);
|
||||
// вывод
|
||||
System.out.println("Количество вариантов: " + list.size());
|
||||
for (Object[] arr : Arrays.asList(arr1, arr2)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Set<Integer> set : list) {
|
||||
sb.append("[");
|
||||
for (int i : set) sb.append(arr[i]);
|
||||
sb.append("]");
|
||||
}
|
||||
System.out.println(sb);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Вывод для этого кода см. выше: [комбинации из трёх элементов](#combinations-of-elements).
|
173
jekyll_site/ru/2021/10/04/cartesian-product-parallel-streams.md
Normal file
173
jekyll_site/ru/2021/10/04/cartesian-product-parallel-streams.md
Normal file
|
@ -0,0 +1,173 @@
|
|||
---
|
||||
title: Декартово произведение в параллельных потоках
|
||||
description: Рассмотрим алгоритм получения декартова произведения с помощью потоков Java Stream. Это решение похоже на три вложенных цикла for с тем отличием, что...
|
||||
sections: [Многопоточность,Комбинаторика,Прямое произведение]
|
||||
tags: [java,многопоточность,комбинаторика,алгоритмы,декартово произведение]
|
||||
canonical_url: /ru/2021/10/04/cartesian-product-parallel-streams.html
|
||||
url_translated: /en/2021/10/05/cartesian-product-parallel-streams.html
|
||||
title_translated: Cartesian product in parallel streams
|
||||
date: 2021.10.04
|
||||
---
|
||||
|
||||
Рассмотрим алгоритм получения *декартова произведения* с помощью потоков Java Stream. Это решение
|
||||
похоже на три вложенных цикла `for` с тем отличием, что здесь внешний цикл заменён на поток для
|
||||
удобства последующего распараллеливания. Будем использовать метод `reduce` с тремя параметрами:
|
||||
`identity`, `accumulator` и `combiner`.
|
||||
|
||||
*Алгоритм с тремя вложенными циклами:
|
||||
[Декартово произведение множеств]({{ '/ru/2021/09/06/cartesian-product-of-sets.html' | relative_url }}).*
|
||||
|
||||
Входящие данные — это произвольное количество списков и их элементов.
|
||||
|
||||
```
|
||||
a = [A1,B1,C1,D1]
|
||||
b = [A2,B2,C2]
|
||||
c = [A3,B3]
|
||||
d = [A4]
|
||||
```
|
||||
|
||||
Количество возможных комбинаций — это произведение количеств элементов всех списков:
|
||||
|
||||
```
|
||||
4 * 3 * 2 * 1 = 24
|
||||
```
|
||||
|
||||
Получаем *поток списков* `Stream<List<T>>` из входящих данных и вызываем метод `reduce`:
|
||||
|
||||
{% capture md_list_into_div %}
|
||||
- `identity` — сущность. В нашем случае это *список списков* `List<List<T>>`,
|
||||
заполненный одним пустым значением. Будем использовать его как промежуточный
|
||||
результат и как финальный результат.
|
||||
|
||||
- `accumulator` — накопитель. Для каждого шага *редукции* описываем метод с двумя
|
||||
параметрами: промежуточный результат и текущий список. Дополняем промежуточный
|
||||
результат значениями из текущего списка.
|
||||
|
||||
- `combiner` — объединитель. Используется в многопоточном режиме, объединяем
|
||||
результаты работы потоков, получаем *декартово произведение* результатов.
|
||||
{% endcapture %}
|
||||
<div>
|
||||
{{- md_list_into_div | markdownify -}}
|
||||
</div>
|
||||
|
||||
Пошагово процесс накопления *декартова произведения* выглядит следующим образом:
|
||||
|
||||
```
|
||||
result0: [[]]
|
||||
list1: [A1,B1,C1,D1]
|
||||
--------
|
||||
result1: [[A1],[B1],[C1],[D1]]
|
||||
list2: [A2,B2,C2]
|
||||
--------
|
||||
result2: [[A1,A2],[A1,B2],[A1,C2],[B1,A2],[B1,B2],...[D1,C2]]
|
||||
list3: [A3,B3]
|
||||
--------
|
||||
result3: [[A1,A2,A3],[A1,A2,B3],[A1,B2,A3],[A1,B2,B3],[A1,C2,A3],...[D1,C2,B3]]
|
||||
list4: [A4]
|
||||
--------
|
||||
result4: [[A1,A2,A3,A4],[A1,A2,B3,A4],[A1,B2,A3,A4],[A1,B2,B3,A4],...[D1,C2,B3,A4]]
|
||||
```
|
||||
|
||||
### Комбинации по столбцам {#combinations-by-columns}
|
||||
|
||||
```
|
||||
Количество комбинаций: 24
|
||||
[A1, A2, A3, A4] [B1, A2, A3, A4] [C1, A2, A3, A4] [D1, A2, A3, A4]
|
||||
[A1, A2, B3, A4] [B1, A2, B3, A4] [C1, A2, B3, A4] [D1, A2, B3, A4]
|
||||
[A1, B2, A3, A4] [B1, B2, A3, A4] [C1, B2, A3, A4] [D1, B2, A3, A4]
|
||||
[A1, B2, B3, A4] [B1, B2, B3, A4] [C1, B2, B3, A4] [D1, B2, B3, A4]
|
||||
[A1, C2, A3, A4] [B1, C2, A3, A4] [C1, C2, A3, A4] [D1, C2, A3, A4]
|
||||
[A1, C2, B3, A4] [B1, C2, B3, A4] [C1, C2, B3, A4] [D1, C2, B3, A4]
|
||||
```
|
||||
|
||||
## Комбинации элементов в параллельных потоках {#combinations-of-elements-in-parallel-streams}
|
||||
|
||||
В параллельном режиме скорость работы алгоритма увеличивается при перемножении *большого количества
|
||||
маленьких списков*, например 20 списков по 2 элемента или 15 списков по 3 элемента. Время вычислений
|
||||
уменьшается в *полтора-два* раза. В остальных случаях время работы примерно такое же, как у трёх
|
||||
вложенных циклов `for`.
|
||||
|
||||
```java
|
||||
/**
|
||||
* @param lists произвольное количество списков
|
||||
* @param <T> тип элементов списков
|
||||
* @return декартово произведение переданных списков
|
||||
*/
|
||||
public static <T> List<List<T>> cartesianProduct(List<List<T>> lists) {
|
||||
// входящие данные не равны null
|
||||
if (lists == null) return Collections.emptyList();
|
||||
// поток списков Stream<List<T>>
|
||||
return lists.stream()
|
||||
// включаем параллельный режим
|
||||
.parallel()
|
||||
// отбрасываем нулевые и пустые списки
|
||||
.filter(list -> list != null && list.size() > 0)
|
||||
// сводим поток списков в один список, получаем декартово произведение
|
||||
// reduce(identity, accumulator, combiner)
|
||||
.reduce( // промежуточный результат, содержит одно пустое значение
|
||||
Collections.singletonList(Collections.emptyList()),
|
||||
// обходим переданные списки и дополняем промежуточный результат их
|
||||
// элементами, на каждом шаге получаем новый промежуточный результат
|
||||
(result, list) -> {
|
||||
// следующий промежуточный результат
|
||||
List<List<T>> nResult = new ArrayList<>(result.size() * list.size());
|
||||
// строки текущего промежуточного результата
|
||||
for (List<T> row : result) {
|
||||
// элементы текущего списка
|
||||
for (T el : list) {
|
||||
// новая строка для следующего промежуточного результата
|
||||
List<T> nRow = new ArrayList<>(row.size() + 1);
|
||||
// добавляем текущую строку
|
||||
nRow.addAll(row);
|
||||
// добавляем текущий элемент
|
||||
nRow.add(el);
|
||||
// помещаем в следующий промежуточный результат
|
||||
nResult.add(nRow);
|
||||
}
|
||||
}
|
||||
// передаём на следующую итерацию
|
||||
return nResult;
|
||||
},
|
||||
// используется в многопоточном режиме, объединяем результаты
|
||||
// работы потоков, получаем декартово произведение результатов
|
||||
(result1, result2) -> {
|
||||
// объединённый результат
|
||||
List<List<T>> result = new ArrayList<>(result1.size() * result2.size());
|
||||
// обходим результаты
|
||||
for (List<T> comb1 : result1) {
|
||||
for (List<T> comb2 : result2) {
|
||||
// складываем комбинации
|
||||
List<T> comb = new ArrayList<>(comb1.size() + comb2.size());
|
||||
comb.addAll(comb1);
|
||||
comb.addAll(comb2);
|
||||
result.add(comb);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// запускаем программу и выводим результат
|
||||
public static void main(String[] args) {
|
||||
// произвольное количество списков и их элементов
|
||||
List<String> a = Arrays.asList("A1", "B1", "C1", "D1");
|
||||
List<String> b = Arrays.asList("A2", "B2", "C2");
|
||||
List<String> c = Arrays.asList("A3", "B3");
|
||||
List<String> d = Collections.singletonList("A4");
|
||||
// декартово произведение
|
||||
List<List<String>> cp = cartesianProduct(Arrays.asList(a, b, c, d));
|
||||
// вывод
|
||||
System.out.println("Количество комбинаций: " + cp.size());
|
||||
// комбинации по столбцам
|
||||
int rows = 6;
|
||||
IntStream.range(0, rows).forEach(i -> System.out.println(
|
||||
IntStream.range(0, cp.size())
|
||||
.filter(j -> j % rows == i)
|
||||
.mapToObj(j -> cp.get(j).toString())
|
||||
.collect(Collectors.joining(" "))));
|
||||
}
|
||||
```
|
||||
|
||||
Вывод для этого кода см. выше: [комбинации по столбцам](#combinations-by-columns).
|
61
jekyll_site/ru/index.md
Normal file
61
jekyll_site/ru/index.md
Normal file
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
title: Код с комментариями
|
||||
description: Заметки на тему программирования с примерами кода и комментариями. Решения задач и описания решений.
|
||||
sections: [Решения задач и описания решений]
|
||||
tags: [java,комбинаторика,алгоритмы,реализация,множества,подмножества,списки,массивы,циклы,вложенные циклы]
|
||||
canonical_url: /
|
||||
url_translated: /en/
|
||||
title_translated: Code with comments
|
||||
---
|
||||
|
||||
{%- assign articles = "" | split: "" %}
|
||||
{%- assign articles = articles | push: "Декартово произведение в параллельных потоках" %}
|
||||
{%- capture article_brief %}
|
||||
Рассмотрим алгоритм получения *декартова произведения* с помощью потоков Java Stream. Это решение
|
||||
похоже на три вложенных цикла `for` с тем отличием, что здесь внешний цикл заменён на поток для
|
||||
удобства последующего распараллеливания. Будем использовать метод `reduce` с тремя параметрами:
|
||||
`identity`, `accumulator` и `combiner`.
|
||||
|
||||
В параллельном режиме скорость работы алгоритма увеличивается при перемножении *большого количества
|
||||
маленьких списков*, например 20 списков по 2 элемента или 15 списков по 3 элемента. Время вычислений
|
||||
уменьшается в *полтора-два* раза. В остальных случаях время работы примерно такое же, как у трёх
|
||||
вложенных циклов `for`.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- assign articles = articles | push: "Комбинации элементов последовательности" %}
|
||||
{%- capture article_brief %}
|
||||
Рассмотрим задачу, в которой нужно получить все возможные комбинации элементов последовательности,
|
||||
где количество элементов в комбинации не превышает заданного максимума, и напишем метод на Java
|
||||
с соответствующим отбором по минимальному и максимальному количеству элементов.
|
||||
|
||||
*Размещением* называется упорядоченный набор {`k`} различных элементов из множества различных
|
||||
{`n`} элементов, где {<code>k ≤ n</code>}. Если {<code>k = n</code>}, то
|
||||
такой упорядоченный набор называется *перестановкой*. Для универсальности решения *перестановки*
|
||||
тоже будем учитывать как частный случай *размещения*.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- assign articles = articles | push: "Комбинации элементов по столбцам" %}
|
||||
{%- capture article_brief %}
|
||||
В двухмерном массиве данные хранятся построчно. Рассмотрим алгоритм получения *декартова
|
||||
произведения* по столбцам с использованием трёх вложенных циклов. Количество строк и
|
||||
колонок таблицы может быть произвольным. Последовательно перемножаем колонки и накапливаем
|
||||
результат. Значения необязательно должны быть заполнены — нулевые элементы отбрасываем.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- assign articles = articles | push: "Треугольник Паскаля на Java" %}
|
||||
{%- capture article_brief %}
|
||||
Рассмотрим вариант реализации *треугольника Паскаля* на Java. Для простоты хранения и обработки
|
||||
данных представим треугольник в виде двухмерного массива, в котором элементы первой строки и колонки
|
||||
равны единице, а все остальные элементы — есть сумма двух предыдущих элементов в строке и в колонке.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- assign articles = articles | push: "Декартово произведение множеств" %}
|
||||
{%- capture article_brief %}
|
||||
Рассмотрим алгоритм получения *декартова произведения* нескольких множеств с использованием
|
||||
трёх вложенных циклов. Количество множеств и их элементов может быть произвольным. Последовательно
|
||||
перемножаем множества и накапливаем результат. Порядок значения не имеет, так как от перестановки
|
||||
множителей произведение не меняется. В результате порядок будет отличаться, но комбинации будут
|
||||
те же самые.
|
||||
{%- endcapture %}
|
||||
{%- assign articles = articles | push: article_brief %}
|
||||
{%- include main_page.html articles = articles -%}
|
5
package.sh
Executable file
5
package.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
echo "Подготовка архива для последующего развёртывания."
|
||||
cd _site || exit
|
||||
rm -rf ../pomodoro2.zip
|
||||
7z a ../pomodoro2.zip ./*
|
4
serve.sh
Executable file
4
serve.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
echo "Локальное развёртывание для проверки корректности сборки."
|
||||
jekyll serve --skip-initial-build --disable-disk-cache --host localhost
|
||||
echo "Адрес сервера: http://localhost:4000"
|
Loading…
Add table
Reference in a new issue