From 5eb80b6c5e5c45e185f425753240c6560a1e7e27 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 19:27:15 +0000 Subject: [PATCH] deploy: 075b4a89adba72c424023e469a58834e89becfad --- 404.html | 2 +- .../postcondition-ambiguity/index.html | 2 +- .../algorithms-and-correctness/index.html | 2 +- .../index.html | 2 +- algorithms/category/graphs/index.html | 2 +- algorithms/category/hash-tables/index.html | 2 +- algorithms/category/recursion/index.html | 2 +- .../category/red-black-trees/index.html | 2 +- algorithms/graphs/bfs-tree/index.html | 2 +- .../graphs/iterative-and-iterators/index.html | 2 +- algorithms/hash-tables/breaking/index.html | 2 +- .../breaking/mitigations/index.html | 2 +- .../hash-tables/breaking/python/index.html | 6 +++--- algorithms/index.html | 4 ++-- algorithms/rb-trees/applications/index.html | 2 +- algorithms/rb-trees/rules/index.html | 2 +- algorithms/recursion/karel-1/index.html | 2 +- .../recursion/pyramid-slide-down/index.html | 4 ++-- algorithms/tags/applications/index.html | 2 +- algorithms/tags/backtracking/index.html | 2 +- algorithms/tags/balanced-trees/index.html | 2 +- algorithms/tags/bfs/index.html | 2 +- algorithms/tags/bottom-up-dp/index.html | 2 +- algorithms/tags/c/index.html | 2 +- algorithms/tags/cpp/index.html | 2 +- algorithms/tags/csharp/index.html | 2 +- algorithms/tags/dynamic-array/index.html | 2 +- .../tags/dynamic-programming/index.html | 2 +- algorithms/tags/exponential/index.html | 2 +- algorithms/tags/graphs/index.html | 2 +- algorithms/tags/greedy/index.html | 2 +- algorithms/tags/hash-tables/index.html | 2 +- algorithms/tags/index.html | 2 +- algorithms/tags/iterative/index.html | 2 +- algorithms/tags/iterators/index.html | 2 +- algorithms/tags/java/index.html | 2 +- algorithms/tags/karel/index.html | 2 +- algorithms/tags/postconditions/index.html | 2 +- algorithms/tags/python/index.html | 2 +- algorithms/tags/recursion/index.html | 2 +- algorithms/tags/red-black-trees/index.html | 2 +- algorithms/tags/sorting/index.html | 2 +- algorithms/tags/testing/index.html | 2 +- algorithms/tags/time-complexity/index.html | 2 +- algorithms/tags/top-down-dp/index.html | 2 +- algorithms/time-complexity/extend/index.html | 2 +- ...5ede8.550c1ca8.js => 1535ede8.2f775329.js} | 2 +- ...c7293.4258c254.js => 595c7293.8e9a4314.js} | 2 +- ...5d476.f7c213ae.js => 5fe5d476.73f34dd7.js} | 2 +- ...2c0bc.beae1b38.js => 7052c0bc.7402024f.js} | 2 +- ...ef108.ed8ed4b7.js => 794ef108.166aea3d.js} | 2 +- ...1e0d8.2391d00c.js => 84d1e0d8.7240ea58.js} | 2 +- assets/js/aa24fd5d.143c547f.js | 1 + assets/js/aa24fd5d.a1be9355.js | 1 - ...88602.9d3ae1e4.js => b1288602.2548704d.js} | 2 +- ...e838c.1b2f4a74.js => d05e838c.ac17e06f.js} | 2 +- ...n.f17742ff.js => runtime~main.306284ce.js} | 2 +- blog/2023/08/02/copr/index.html | 2 +- blog/aoc-2022/1st-week/index.html | 2 +- blog/aoc-2022/2nd-week/index.html | 2 +- blog/aoc-2022/3rd-week/index.html | 2 +- blog/aoc-2022/4th-week/index.html | 2 +- blog/aoc-2022/intro/index.html | 2 +- blog/archive/index.html | 2 +- blog/index.html | 2 +- blog/leetcode/sort-diagonally/index.html | 2 +- blog/tags/admin/index.html | 2 +- blog/tags/advent-of-code-2022/index.html | 2 +- blog/tags/advent-of-code/index.html | 2 +- blog/tags/copr/index.html | 2 +- blog/tags/cpp/index.html | 2 +- blog/tags/index.html | 2 +- blog/tags/iterators/index.html | 2 +- blog/tags/leetcode/index.html | 2 +- blog/tags/red-hat/index.html | 2 +- blog/tags/rust/index.html | 2 +- blog/tags/vps/index.html | 2 +- blog/tags/🏭/index.html | 2 +- c/bonuses/seminar-03/index.html | 2 +- c/bonuses/seminar-04/index.html | 2 +- c/bonuses/seminar-05-06/index.html | 4 ++-- c/bonuses/seminar-08/index.html | 4 ++-- c/bonuses/seminar-10/index.html | 4 ++-- c/category/bonuses/index.html | 2 +- c/category/practice-exams/index.html | 2 +- c/index.html | 4 ++-- c/mr/index.html | 4 ++-- c/pexam/cams/index.html | 2 +- c/pexam/garbage_collect/index.html | 2 +- contributions/index.html | 2 +- cpp/category/exceptions-and-raii/index.html | 2 +- cpp/environment/index.html | 2 +- .../placeholders/index.html | 2 +- cpp/index.html | 4 ++-- .../graphs/iterative-and-iterators.tar.bz2 | Bin 1939 -> 1933 bytes .../graphs/iterative-and-iterators.tar.gz | Bin 1955 -> 1956 bytes files/algorithms/recursion/karel-1.tar.bz2 | Bin 5876 -> 5877 bytes files/algorithms/recursion/karel-1.tar.gz | Bin 6583 -> 6583 bytes .../recursion/pyramid-slide-down.tar.bz2 | Bin 1546 -> 1547 bytes .../recursion/pyramid-slide-down.tar.gz | Bin 1423 -> 1422 bytes .../algorithms/time-complexity/extend.tar.bz2 | Bin 4070 -> 4083 bytes .../algorithms/time-complexity/extend.tar.gz | Bin 3913 -> 3912 bytes files/c/bonuses/03.tar.bz2 | Bin 2647 -> 2651 bytes files/c/bonuses/03.tar.gz | Bin 2339 -> 2336 bytes files/c/bonuses/04.tar.bz2 | Bin 2531 -> 2534 bytes files/c/bonuses/04.tar.gz | Bin 2499 -> 2500 bytes files/c/bonuses/05-06.tar.bz2 | Bin 3639 -> 3637 bytes files/c/bonuses/05-06.tar.gz | Bin 3488 -> 3485 bytes files/c/bonuses/08.tar.bz2 | Bin 73473 -> 73476 bytes files/c/bonuses/08.tar.gz | Bin 103303 -> 103304 bytes files/c/bonuses/10.tar.bz2 | Bin 234820 -> 234845 bytes files/c/bonuses/10.tar.gz | Bin 230102 -> 230109 bytes index.html | 2 +- search/index.html | 2 +- talks/index.html | 2 +- 115 files changed, 106 insertions(+), 106 deletions(-) rename assets/js/{1535ede8.550c1ca8.js => 1535ede8.2f775329.js} (99%) rename assets/js/{595c7293.4258c254.js => 595c7293.8e9a4314.js} (99%) rename assets/js/{5fe5d476.f7c213ae.js => 5fe5d476.73f34dd7.js} (99%) rename assets/js/{7052c0bc.beae1b38.js => 7052c0bc.7402024f.js} (95%) rename assets/js/{794ef108.ed8ed4b7.js => 794ef108.166aea3d.js} (95%) rename assets/js/{84d1e0d8.2391d00c.js => 84d1e0d8.7240ea58.js} (97%) create mode 100644 assets/js/aa24fd5d.143c547f.js delete mode 100644 assets/js/aa24fd5d.a1be9355.js rename assets/js/{b1288602.9d3ae1e4.js => b1288602.2548704d.js} (99%) rename assets/js/{d05e838c.1b2f4a74.js => d05e838c.ac17e06f.js} (99%) rename assets/js/{runtime~main.f17742ff.js => runtime~main.306284ce.js} (94%) diff --git a/404.html b/404.html index 3f8cd22..a536c3f 100644 --- a/404.html +++ b/404.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/algorithms-correctness/postcondition-ambiguity/index.html b/algorithms/algorithms-correctness/postcondition-ambiguity/index.html index c1e6705..ba4751f 100644 --- a/algorithms/algorithms-correctness/postcondition-ambiguity/index.html +++ b/algorithms/algorithms-correctness/postcondition-ambiguity/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/category/algorithms-and-correctness/index.html b/algorithms/category/algorithms-and-correctness/index.html index 9d8adf6..b22d093 100644 --- a/algorithms/category/algorithms-and-correctness/index.html +++ b/algorithms/category/algorithms-and-correctness/index.html @@ -18,7 +18,7 @@ correctness. - + diff --git a/algorithms/category/asymptotic-notation-and-time-complexity/index.html b/algorithms/category/asymptotic-notation-and-time-complexity/index.html index 0d8091f..871b66d 100644 --- a/algorithms/category/asymptotic-notation-and-time-complexity/index.html +++ b/algorithms/category/asymptotic-notation-and-time-complexity/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/category/graphs/index.html b/algorithms/category/graphs/index.html index 9ea7c89..8825a08 100644 --- a/algorithms/category/graphs/index.html +++ b/algorithms/category/graphs/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/category/hash-tables/index.html b/algorithms/category/hash-tables/index.html index dde2a7a..e38c8d3 100644 --- a/algorithms/category/hash-tables/index.html +++ b/algorithms/category/hash-tables/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/category/recursion/index.html b/algorithms/category/recursion/index.html index 331e15d..0685682 100644 --- a/algorithms/category/recursion/index.html +++ b/algorithms/category/recursion/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/category/red-black-trees/index.html b/algorithms/category/red-black-trees/index.html index 68ffe87..4e7a532 100644 --- a/algorithms/category/red-black-trees/index.html +++ b/algorithms/category/red-black-trees/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/graphs/bfs-tree/index.html b/algorithms/graphs/bfs-tree/index.html index d5f0f1c..7289178 100644 --- a/algorithms/graphs/bfs-tree/index.html +++ b/algorithms/graphs/bfs-tree/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/graphs/iterative-and-iterators/index.html b/algorithms/graphs/iterative-and-iterators/index.html index 4e70387..239d57a 100644 --- a/algorithms/graphs/iterative-and-iterators/index.html +++ b/algorithms/graphs/iterative-and-iterators/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/hash-tables/breaking/index.html b/algorithms/hash-tables/breaking/index.html index ab7770f..d0a4ae0 100644 --- a/algorithms/hash-tables/breaking/index.html +++ b/algorithms/hash-tables/breaking/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/hash-tables/breaking/mitigations/index.html b/algorithms/hash-tables/breaking/mitigations/index.html index 29f0ab8..7d5f661 100644 --- a/algorithms/hash-tables/breaking/mitigations/index.html +++ b/algorithms/hash-tables/breaking/mitigations/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/hash-tables/breaking/python/index.html b/algorithms/hash-tables/breaking/python/index.html index de6ee32..da3c26e 100644 --- a/algorithms/hash-tables/breaking/python/index.html +++ b/algorithms/hash-tables/breaking/python/index.html @@ -16,11 +16,11 @@ - + -
Skip to main content

Breaking Python

Breaking the Hash Table in Python

+

Breaking the Hash Table in Python

Our language of choice for bringing the worst out of the hash table is Python.

Let's start by talking about the hash function and why we've chosen Python for this. Hash function for integers in Python is simply identity, as you might've @@ -137,6 +137,6 @@ will collide).

Arbitrary-sized integers, they can get as big as your memory allows.

-
+
\ No newline at end of file diff --git a/algorithms/index.html b/algorithms/index.html index 20bb4f2..4e76449 100644 --- a/algorithms/index.html +++ b/algorithms/index.html @@ -14,7 +14,7 @@ - + @@ -23,6 +23,6 @@ course of teaching Algorithms and data structures I.

It is a various mix of stuff that may have been produced as a follow-up on some question asked at the seminar or spontanously.

If you have some ideas for posts, please do not hesitate to submit them as issues -in the linked GitLab.

+in the linked GitLab.

\ No newline at end of file diff --git a/algorithms/rb-trees/applications/index.html b/algorithms/rb-trees/applications/index.html index 4a7b5d2..c0d702d 100644 --- a/algorithms/rb-trees/applications/index.html +++ b/algorithms/rb-trees/applications/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/rb-trees/rules/index.html b/algorithms/rb-trees/rules/index.html index be5e1a7..80f8747 100644 --- a/algorithms/rb-trees/rules/index.html +++ b/algorithms/rb-trees/rules/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/recursion/karel-1/index.html b/algorithms/recursion/karel-1/index.html index 7e0f048..b1027fe 100644 --- a/algorithms/recursion/karel-1/index.html +++ b/algorithms/recursion/karel-1/index.html @@ -16,7 +16,7 @@ - + diff --git a/algorithms/recursion/pyramid-slide-down/index.html b/algorithms/recursion/pyramid-slide-down/index.html index 6a18ea6..3ec821c 100644 --- a/algorithms/recursion/pyramid-slide-down/index.html +++ b/algorithms/recursion/pyramid-slide-down/index.html @@ -16,7 +16,7 @@ - + @@ -304,6 +304,6 @@ successor and represents the way we can enhance the existing implementation.

one was not correct, thus the quotes

-
+
\ No newline at end of file diff --git a/algorithms/tags/applications/index.html b/algorithms/tags/applications/index.html index 6a73f20..8b336f3 100644 --- a/algorithms/tags/applications/index.html +++ b/algorithms/tags/applications/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/backtracking/index.html b/algorithms/tags/backtracking/index.html index e556d29..1282d61 100644 --- a/algorithms/tags/backtracking/index.html +++ b/algorithms/tags/backtracking/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/balanced-trees/index.html b/algorithms/tags/balanced-trees/index.html index 3dfdd90..95de2c5 100644 --- a/algorithms/tags/balanced-trees/index.html +++ b/algorithms/tags/balanced-trees/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/bfs/index.html b/algorithms/tags/bfs/index.html index 8d05e8f..1eb865c 100644 --- a/algorithms/tags/bfs/index.html +++ b/algorithms/tags/bfs/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/bottom-up-dp/index.html b/algorithms/tags/bottom-up-dp/index.html index bbce80d..e216ee1 100644 --- a/algorithms/tags/bottom-up-dp/index.html +++ b/algorithms/tags/bottom-up-dp/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/c/index.html b/algorithms/tags/c/index.html index e0fb054..bf42e15 100644 --- a/algorithms/tags/c/index.html +++ b/algorithms/tags/c/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/cpp/index.html b/algorithms/tags/cpp/index.html index b31d8d0..e4c2abe 100644 --- a/algorithms/tags/cpp/index.html +++ b/algorithms/tags/cpp/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/csharp/index.html b/algorithms/tags/csharp/index.html index 4a580df..d22449b 100644 --- a/algorithms/tags/csharp/index.html +++ b/algorithms/tags/csharp/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/dynamic-array/index.html b/algorithms/tags/dynamic-array/index.html index 2d015a2..a9cb7e1 100644 --- a/algorithms/tags/dynamic-array/index.html +++ b/algorithms/tags/dynamic-array/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/dynamic-programming/index.html b/algorithms/tags/dynamic-programming/index.html index 97cddf4..d57a5a4 100644 --- a/algorithms/tags/dynamic-programming/index.html +++ b/algorithms/tags/dynamic-programming/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/exponential/index.html b/algorithms/tags/exponential/index.html index 2cec0ae..10d92c3 100644 --- a/algorithms/tags/exponential/index.html +++ b/algorithms/tags/exponential/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/graphs/index.html b/algorithms/tags/graphs/index.html index a0db273..8a487e8 100644 --- a/algorithms/tags/graphs/index.html +++ b/algorithms/tags/graphs/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/greedy/index.html b/algorithms/tags/greedy/index.html index d3dbd55..ccb1797 100644 --- a/algorithms/tags/greedy/index.html +++ b/algorithms/tags/greedy/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/hash-tables/index.html b/algorithms/tags/hash-tables/index.html index 2f63c74..09789e5 100644 --- a/algorithms/tags/hash-tables/index.html +++ b/algorithms/tags/hash-tables/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/index.html b/algorithms/tags/index.html index 99ff2ca..0c92216 100644 --- a/algorithms/tags/index.html +++ b/algorithms/tags/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/iterative/index.html b/algorithms/tags/iterative/index.html index 270f187..364f32b 100644 --- a/algorithms/tags/iterative/index.html +++ b/algorithms/tags/iterative/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/iterators/index.html b/algorithms/tags/iterators/index.html index 9fc7813..74e66df 100644 --- a/algorithms/tags/iterators/index.html +++ b/algorithms/tags/iterators/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/java/index.html b/algorithms/tags/java/index.html index 698f15b..dd3005a 100644 --- a/algorithms/tags/java/index.html +++ b/algorithms/tags/java/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/karel/index.html b/algorithms/tags/karel/index.html index 474e655..c0fea66 100644 --- a/algorithms/tags/karel/index.html +++ b/algorithms/tags/karel/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/postconditions/index.html b/algorithms/tags/postconditions/index.html index b773359..cb401c9 100644 --- a/algorithms/tags/postconditions/index.html +++ b/algorithms/tags/postconditions/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/python/index.html b/algorithms/tags/python/index.html index 731be28..cbe3591 100644 --- a/algorithms/tags/python/index.html +++ b/algorithms/tags/python/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/recursion/index.html b/algorithms/tags/recursion/index.html index 813a5b3..1216514 100644 --- a/algorithms/tags/recursion/index.html +++ b/algorithms/tags/recursion/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/red-black-trees/index.html b/algorithms/tags/red-black-trees/index.html index 41456a7..23e95cd 100644 --- a/algorithms/tags/red-black-trees/index.html +++ b/algorithms/tags/red-black-trees/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/sorting/index.html b/algorithms/tags/sorting/index.html index 802a423..922e62a 100644 --- a/algorithms/tags/sorting/index.html +++ b/algorithms/tags/sorting/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/testing/index.html b/algorithms/tags/testing/index.html index 690f592..16194c1 100644 --- a/algorithms/tags/testing/index.html +++ b/algorithms/tags/testing/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/time-complexity/index.html b/algorithms/tags/time-complexity/index.html index 5f6707d..cd1d0b8 100644 --- a/algorithms/tags/time-complexity/index.html +++ b/algorithms/tags/time-complexity/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/tags/top-down-dp/index.html b/algorithms/tags/top-down-dp/index.html index 8e3e815..07e2038 100644 --- a/algorithms/tags/top-down-dp/index.html +++ b/algorithms/tags/top-down-dp/index.html @@ -14,7 +14,7 @@ - + diff --git a/algorithms/time-complexity/extend/index.html b/algorithms/time-complexity/extend/index.html index b6ca43b..e222f92 100644 --- a/algorithms/time-complexity/extend/index.html +++ b/algorithms/time-complexity/extend/index.html @@ -16,7 +16,7 @@ - + diff --git a/assets/js/1535ede8.550c1ca8.js b/assets/js/1535ede8.2f775329.js similarity index 99% rename from assets/js/1535ede8.550c1ca8.js rename to assets/js/1535ede8.2f775329.js index f483cf2..0442ac3 100644 --- a/assets/js/1535ede8.550c1ca8.js +++ b/assets/js/1535ede8.2f775329.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[5376],{44969:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var s=t(85893),i=t(11151);const r={id:"seminar-10",title:"10th seminar",description:"Finding bugs in a hangman.\n"},o=void 0,a={id:"bonuses/seminar-10",title:"10th seminar",description:"Finding bugs in a hangman.\n",source:"@site/c/bonuses/10.md",sourceDirName:"bonuses",slug:"/bonuses/seminar-10",permalink:"/c/bonuses/seminar-10",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/bonuses/10.md",tags:[],version:"current",lastUpdatedAt:1701196739,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{id:"seminar-10",title:"10th seminar",description:"Finding bugs in a hangman.\n"},sidebar:"autogeneratedBar",previous:{title:"8th seminar",permalink:"/c/bonuses/seminar-08"},next:{title:"Practice Exams",permalink:"/c/category/practice-exams"}},c={},l=[{value:"Introduction",id:"introduction",level:2},{value:"Project",id:"project",level:2},{value:"Summary of the gameplay",id:"summary-of-the-gameplay",level:3},{value:"Suggested workflow",id:"suggested-workflow",level:2},{value:"Tasks",id:"tasks",level:2},{value:"Dictionary",id:"dictionary",level:2},{value:"Submitting",id:"submitting",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:(0,s.jsx)(n.a,{href:"pathname:///files/c/bonuses/10.tar.gz",children:"Source"})}),"\n",(0,s.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)(n.p,{children:"For this bonus you are given almost finished project - The Hangman Game. Your\ntask is to try the game, in case you find any bugs point them out and cover as\nmuch of the game as possible with tests."}),"\n",(0,s.jsx)(n.p,{children:"For this bonus you can get at maximum 2 K\u20a1."}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Item"}),(0,s.jsx)(n.th,{children:"Bonus"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Fixing bugs from failing tests"}),(0,s.jsx)(n.td,{children:"0.25"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"word_guessed"})}),(0,s.jsx)(n.td,{children:"0.50"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Hidden bug"}),(0,s.jsx)(n.td,{children:"0.50"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Extending tests, undetectable bugs or evil bug"}),(0,s.jsx)(n.td,{children:"0.37"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Refactor"}),(0,s.jsx)(n.td,{children:"0.38"})]})]})]}),"\n",(0,s.jsx)(n.h2,{id:"project",children:"Project"}),"\n",(0,s.jsxs)(n.p,{children:["Project consists of 2 source files - ",(0,s.jsx)(n.code,{children:"hangman.c"})," and ",(0,s.jsx)(n.code,{children:"main.c"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"main.c"})," is quite short and concise, there is nothing for you to do."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"hangman.c"})," contains implementation of the game. In case you feel lost, consult\nthe documentation in ",(0,s.jsx)(n.code,{children:"hangman.h"})," that represents an interface that can be used\nfor implementing the game."]}),"\n",(0,s.jsxs)(n.p,{children:["Apart from those sources this project is a bit more complicated. ",(0,s.jsx)(n.em,{children:"Game loop"})," is\nrealised via single encapsulated function that complicates the testing. Because\nof that, there are 2 kinds of tests:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.em,{children:"Unit tests"})," - that are present in ",(0,s.jsx)(n.code,{children:"test_hangman.c"})," and can be run via:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ make check-unit\n"})}),"\n",(0,s.jsx)(n.p,{children:"They cover majorly functions that can be tested easily via testing framework."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.em,{children:"Functional tests"})," - same as in ",(0,s.jsx)(n.code,{children:"seminar-08"})," and are focused on testing the\nprogram as whole. Basic smoke test is already included in ",(0,s.jsx)(n.code,{children:"usage"})," test case."]}),"\n",(0,s.jsx)(n.p,{children:"They can be run via:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ make check-functional\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When testing ",(0,s.jsx)(n.code,{children:"hangman"})," function (the game loop), it is suggested to create\nfunctional tests."]}),"\n",(0,s.jsx)(n.p,{children:"When submitting the files for review, please leave out functional tests that\nwere given as a part of the assignment, so that it is easier to navigate, I\nwill drag the common files myself. :)"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"Whole test suite can be run via:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ make check\n"})}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"summary-of-the-gameplay",children:"Summary of the gameplay"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Secret word gets chosen from the file that's path is given as an argument."}),"\n",(0,s.jsx)(n.li,{children:"You get 8 guesses."}),"\n",(0,s.jsx)(n.li,{children:"Invalid characters don't count."}),"\n",(0,s.jsx)(n.li,{children:"Already guessed characters don't count, even if not included in the secret."}),"\n",(0,s.jsxs)(n.li,{children:["You can guess the whole word at once","\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"If you get it right, you won, game ends."}),"\n",(0,s.jsx)(n.li,{children:"If you don't get it right, you get to see the secret, game ends."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:"In case of end of input, game finishes via force."}),"\n",(0,s.jsx)(n.li,{children:"In case of invalid input, no guesses are subtracted, game carries on."}),"\n",(0,s.jsx)(n.li,{children:"Letters and words are not case sensitive."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"suggested-workflow",children:"Suggested workflow"}),"\n",(0,s.jsxs)(n.p,{children:["As we have talked about on the seminar, I suggest you to follow\n",(0,s.jsx)(n.em,{children:"Test-Driven Development"}),"\nin this case."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"TDD workflow",src:t(27420).Z+"",width:"2814",height:"1652"})}),"\n",(0,s.jsx)(n.p,{children:"In our current scenario we are already in the stage of refactoring and fixing the\nbugs. Therefore try to follow this succession of steps:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Try to reproduce the bug."}),"\n",(0,s.jsx)(n.li,{children:"Create a test that proves the presence of the bug."}),"\n",(0,s.jsx)(n.li,{children:"Fix the bug."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["In case you are submitting the bonus via GitLab, it is helpful to commit tests\nbefore commiting the fixes, so that it is apparent that the bug is manifested.\nExample of ",(0,s.jsx)(n.code,{children:"git log"})," (notice that the first line represents latest commit):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"feat: Implement fizz_buzzer\ntest: Add tests for fizz_buzzer\nfix: Fix NULL-check in print_name\ntest: Add test for NULL in print_name\n"})}),"\n",(0,s.jsx)(n.h2,{id:"tasks",children:"Tasks"}),"\n",(0,s.jsx)(n.p,{children:"As to your tasks, there are multiple things wrong in this project."}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'There are 2 "bugs" that cannot be detected via tests, i.e. they are not bugs\nthat affect functionality of the game.'}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["There is one evil bug in ",(0,s.jsx)(n.code,{children:"get_word"}),". It is not required to be fixed ;) Assign\nit the lowest priority."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"There are some tests failing. Please try to figure it out, so you have green\ntests for the rest :)"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["We have gotten a bug report for ",(0,s.jsx)(n.code,{children:"word_guessed"}),", all we got is"]}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsxs)(n.p,{children:["doesn't work when there are too many ",(0,s.jsx)(n.code,{children:"a"}),"s"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Please try to replicate the bug and create a tests, so we don't get any\nregression later on."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"One hidden bug :) Closely non-specified, we cannot reproduce it and we were\ndrunk while playing the game, so we don't remember a thing. :/"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Try to cover as much code via the tests as possible. We are not going to look\nat the metrics, but DRY is violated a lot, so as a last task try to remove as\nmuch of the duplicit code as possible."}),"\n",(0,s.jsx)(n.p,{children:"Tests should help you a lot in case there are some regressions."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsxs)(n.p,{children:["In case you wonder why there are always 3 same words in the file with words, it\nis because of the ",(0,s.jsx)(n.code,{children:"get_word"})," bug. It is not a bug that can be easily fixed, so\nit is a not requirement at all and you can still get all points for the bonus ;)"]}),"\n",(0,s.jsx)(n.h2,{id:"dictionary",children:"Dictionary"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Functional_testing",children:"Functional tests"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Smoke_testing_%28software%29",children:"Smoke test"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself",children:"DRY"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"submitting",children:"Submitting"}),"\n",(0,s.jsx)(n.p,{children:"In case you have any questions, feel free to reach out to me."}),"\n",(0,s.jsx)(n.hr,{})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},27420:(e,n,t)=>{t.d(n,{Z:()=>s});const s=t.p+"assets/images/tdd_lifecycle-327ad9ee0ed8318ed11e19a28e02b2cc.png"},11151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>o});var s=t(67294);const i={},r=s.createContext(i);function o(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[5376],{44969:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var s=t(85893),i=t(11151);const r={id:"seminar-10",title:"10th seminar",description:"Finding bugs in a hangman.\n"},o=void 0,a={id:"bonuses/seminar-10",title:"10th seminar",description:"Finding bugs in a hangman.\n",source:"@site/c/bonuses/10.md",sourceDirName:"bonuses",slug:"/bonuses/seminar-10",permalink:"/c/bonuses/seminar-10",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/bonuses/10.md",tags:[],version:"current",lastUpdatedAt:1701199517,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{id:"seminar-10",title:"10th seminar",description:"Finding bugs in a hangman.\n"},sidebar:"autogeneratedBar",previous:{title:"8th seminar",permalink:"/c/bonuses/seminar-08"},next:{title:"Practice Exams",permalink:"/c/category/practice-exams"}},c={},l=[{value:"Introduction",id:"introduction",level:2},{value:"Project",id:"project",level:2},{value:"Summary of the gameplay",id:"summary-of-the-gameplay",level:3},{value:"Suggested workflow",id:"suggested-workflow",level:2},{value:"Tasks",id:"tasks",level:2},{value:"Dictionary",id:"dictionary",level:2},{value:"Submitting",id:"submitting",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:(0,s.jsx)(n.a,{href:"pathname:///files/c/bonuses/10.tar.gz",children:"Source"})}),"\n",(0,s.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)(n.p,{children:"For this bonus you are given almost finished project - The Hangman Game. Your\ntask is to try the game, in case you find any bugs point them out and cover as\nmuch of the game as possible with tests."}),"\n",(0,s.jsx)(n.p,{children:"For this bonus you can get at maximum 2 K\u20a1."}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Item"}),(0,s.jsx)(n.th,{children:"Bonus"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Fixing bugs from failing tests"}),(0,s.jsx)(n.td,{children:"0.25"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"word_guessed"})}),(0,s.jsx)(n.td,{children:"0.50"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Hidden bug"}),(0,s.jsx)(n.td,{children:"0.50"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Extending tests, undetectable bugs or evil bug"}),(0,s.jsx)(n.td,{children:"0.37"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"Refactor"}),(0,s.jsx)(n.td,{children:"0.38"})]})]})]}),"\n",(0,s.jsx)(n.h2,{id:"project",children:"Project"}),"\n",(0,s.jsxs)(n.p,{children:["Project consists of 2 source files - ",(0,s.jsx)(n.code,{children:"hangman.c"})," and ",(0,s.jsx)(n.code,{children:"main.c"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"main.c"})," is quite short and concise, there is nothing for you to do."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"hangman.c"})," contains implementation of the game. In case you feel lost, consult\nthe documentation in ",(0,s.jsx)(n.code,{children:"hangman.h"})," that represents an interface that can be used\nfor implementing the game."]}),"\n",(0,s.jsxs)(n.p,{children:["Apart from those sources this project is a bit more complicated. ",(0,s.jsx)(n.em,{children:"Game loop"})," is\nrealised via single encapsulated function that complicates the testing. Because\nof that, there are 2 kinds of tests:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.em,{children:"Unit tests"})," - that are present in ",(0,s.jsx)(n.code,{children:"test_hangman.c"})," and can be run via:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ make check-unit\n"})}),"\n",(0,s.jsx)(n.p,{children:"They cover majorly functions that can be tested easily via testing framework."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.em,{children:"Functional tests"})," - same as in ",(0,s.jsx)(n.code,{children:"seminar-08"})," and are focused on testing the\nprogram as whole. Basic smoke test is already included in ",(0,s.jsx)(n.code,{children:"usage"})," test case."]}),"\n",(0,s.jsx)(n.p,{children:"They can be run via:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ make check-functional\n"})}),"\n",(0,s.jsxs)(n.p,{children:["When testing ",(0,s.jsx)(n.code,{children:"hangman"})," function (the game loop), it is suggested to create\nfunctional tests."]}),"\n",(0,s.jsx)(n.p,{children:"When submitting the files for review, please leave out functional tests that\nwere given as a part of the assignment, so that it is easier to navigate, I\nwill drag the common files myself. :)"}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"Whole test suite can be run via:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ make check\n"})}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"summary-of-the-gameplay",children:"Summary of the gameplay"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Secret word gets chosen from the file that's path is given as an argument."}),"\n",(0,s.jsx)(n.li,{children:"You get 8 guesses."}),"\n",(0,s.jsx)(n.li,{children:"Invalid characters don't count."}),"\n",(0,s.jsx)(n.li,{children:"Already guessed characters don't count, even if not included in the secret."}),"\n",(0,s.jsxs)(n.li,{children:["You can guess the whole word at once","\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"If you get it right, you won, game ends."}),"\n",(0,s.jsx)(n.li,{children:"If you don't get it right, you get to see the secret, game ends."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:"In case of end of input, game finishes via force."}),"\n",(0,s.jsx)(n.li,{children:"In case of invalid input, no guesses are subtracted, game carries on."}),"\n",(0,s.jsx)(n.li,{children:"Letters and words are not case sensitive."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"suggested-workflow",children:"Suggested workflow"}),"\n",(0,s.jsxs)(n.p,{children:["As we have talked about on the seminar, I suggest you to follow\n",(0,s.jsx)(n.em,{children:"Test-Driven Development"}),"\nin this case."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"TDD workflow",src:t(27420).Z+"",width:"2814",height:"1652"})}),"\n",(0,s.jsx)(n.p,{children:"In our current scenario we are already in the stage of refactoring and fixing the\nbugs. Therefore try to follow this succession of steps:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Try to reproduce the bug."}),"\n",(0,s.jsx)(n.li,{children:"Create a test that proves the presence of the bug."}),"\n",(0,s.jsx)(n.li,{children:"Fix the bug."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["In case you are submitting the bonus via GitLab, it is helpful to commit tests\nbefore commiting the fixes, so that it is apparent that the bug is manifested.\nExample of ",(0,s.jsx)(n.code,{children:"git log"})," (notice that the first line represents latest commit):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"feat: Implement fizz_buzzer\ntest: Add tests for fizz_buzzer\nfix: Fix NULL-check in print_name\ntest: Add test for NULL in print_name\n"})}),"\n",(0,s.jsx)(n.h2,{id:"tasks",children:"Tasks"}),"\n",(0,s.jsx)(n.p,{children:"As to your tasks, there are multiple things wrong in this project."}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'There are 2 "bugs" that cannot be detected via tests, i.e. they are not bugs\nthat affect functionality of the game.'}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["There is one evil bug in ",(0,s.jsx)(n.code,{children:"get_word"}),". It is not required to be fixed ;) Assign\nit the lowest priority."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"There are some tests failing. Please try to figure it out, so you have green\ntests for the rest :)"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["We have gotten a bug report for ",(0,s.jsx)(n.code,{children:"word_guessed"}),", all we got is"]}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsxs)(n.p,{children:["doesn't work when there are too many ",(0,s.jsx)(n.code,{children:"a"}),"s"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Please try to replicate the bug and create a tests, so we don't get any\nregression later on."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"One hidden bug :) Closely non-specified, we cannot reproduce it and we were\ndrunk while playing the game, so we don't remember a thing. :/"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Try to cover as much code via the tests as possible. We are not going to look\nat the metrics, but DRY is violated a lot, so as a last task try to remove as\nmuch of the duplicit code as possible."}),"\n",(0,s.jsx)(n.p,{children:"Tests should help you a lot in case there are some regressions."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsxs)(n.p,{children:["In case you wonder why there are always 3 same words in the file with words, it\nis because of the ",(0,s.jsx)(n.code,{children:"get_word"})," bug. It is not a bug that can be easily fixed, so\nit is a not requirement at all and you can still get all points for the bonus ;)"]}),"\n",(0,s.jsx)(n.h2,{id:"dictionary",children:"Dictionary"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Functional_testing",children:"Functional tests"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Smoke_testing_%28software%29",children:"Smoke test"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself",children:"DRY"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"submitting",children:"Submitting"}),"\n",(0,s.jsx)(n.p,{children:"In case you have any questions, feel free to reach out to me."}),"\n",(0,s.jsx)(n.hr,{})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},27420:(e,n,t)=>{t.d(n,{Z:()=>s});const s=t.p+"assets/images/tdd_lifecycle-327ad9ee0ed8318ed11e19a28e02b2cc.png"},11151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>o});var s=t(67294);const i={},r=s.createContext(i);function o(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/595c7293.4258c254.js b/assets/js/595c7293.8e9a4314.js similarity index 99% rename from assets/js/595c7293.4258c254.js rename to assets/js/595c7293.8e9a4314.js index 62f26cc..baabd65 100644 --- a/assets/js/595c7293.4258c254.js +++ b/assets/js/595c7293.8e9a4314.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[5634],{58396:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>l});var i=t(85893),s=t(11151);const r={id:"seminar-08",title:"8th seminar",description:"Manipulating with files only char-by-char and a magic tree.\n"},o="8th seminar bonus assignment",c={id:"bonuses/seminar-08",title:"8th seminar",description:"Manipulating with files only char-by-char and a magic tree.\n",source:"@site/c/bonuses/08.md",sourceDirName:"bonuses",slug:"/bonuses/seminar-08",permalink:"/c/bonuses/seminar-08",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/bonuses/08.md",tags:[],version:"current",lastUpdatedAt:1701196739,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{id:"seminar-08",title:"8th seminar",description:"Manipulating with files only char-by-char and a magic tree.\n"},sidebar:"autogeneratedBar",previous:{title:"5th and 6th seminar",permalink:"/c/bonuses/seminar-05-06"},next:{title:"10th seminar",permalink:"/c/bonuses/seminar-10"}},a={},l=[{value:"Introduction",id:"introduction",level:2},{value:"Warning",id:"warning",level:2},{value:"Testing",id:"testing",level:2},{value:"Task no. 1: Counting (0.75 K\u20a1)",id:"task-no-1-counting-075-k",level:2},{value:"Requirements",id:"requirements",level:3},{value:"Bonus part (0.75 K\u20a1)",id:"bonus-part-075-k",level:3},{value:"Task no. 2: Weird trees (1 K\u20a1)",id:"task-no-2-weird-trees-1-k",level:2},{value:"Submitting",id:"submitting",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"8th-seminar-bonus-assignment",children:"8th seminar bonus assignment"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"pathname:///files/c/bonuses/08.tar.gz",children:"Source"})}),"\n",(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.p,{children:"In this bonus you can implement two tasks, one of them has a bonus part with generic\nsolution."}),"\n",(0,i.jsx)(n.p,{children:"One is focused on counting ananas or in case of generic version any substring in\nthe file, but with a restriction on the function you use."}),"\n",(0,i.jsx)(n.p,{children:"Other one has a more algorithmic spirit."}),"\n",(0,i.jsx)(n.p,{children:"For this bonus you can get at maximum 2.5 K\u20a1."}),"\n",(0,i.jsx)(n.h2,{id:"warning",children:"Warning"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"DO NOT COMMIT test data"})," to your own git repository, since the tests include\nfiles that exceed 10MB by themselves. Even if they are on separate branch, they\ntake up the space."]}),"\n",(0,i.jsx)(n.h2,{id:"testing",children:"Testing"}),"\n",(0,i.jsxs)(n.p,{children:["For testing you are provided with python script (requires ",(0,i.jsx)(n.code,{children:"click"})," to be installed:\n",(0,i.jsx)(n.code,{children:"pip3 install --user click"}),") and ",(0,i.jsx)(n.code,{children:"Makefile"})," that provides following targets:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"check-counting"})," - runs the ",(0,i.jsx)(n.code,{children:"counting"})," tests"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"check-counting-bonus"})," - runs the ",(0,i.jsx)(n.code,{children:"counting"})," tests with bonus implemented"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"check"})," - runs both ",(0,i.jsx)(n.code,{children:"counting"})," and ",(0,i.jsx)(n.code,{children:"counting-bonus"})," tests"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"clean"})," - removes output files from the test runs"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"task-no-1-counting-075-k",children:"Task no. 1: Counting (0.75 K\u20a1)"}),"\n",(0,i.jsx)(n.p,{children:"Your first task is to make smallish program that counts occurences of specific\n(or given) word from file and writes the number to other file."}),"\n",(0,i.jsx)(n.p,{children:"Usage of the program is:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"Usage: ./counting [string-to-be-counted]\n"})}),"\n",(0,i.jsx)(n.p,{children:"Arguments that are passed to the program represent:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:""})," - path to the file where we count the words"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:""})," - path to the file where we output the count"]}),"\n",(0,i.jsxs)(n.li,{children:["(optional argument) ",(0,i.jsx)(n.code,{children:"[string-to-be-counted]"})," - in case you implement bonus,\notherwise we default to word ",(0,i.jsx)(n.code,{children:"ananas"})," ;)"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"In skeleton you are given 3 empty, but documented, functions to implement."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"count_anything"})," - function accepts input file and substring to be counted in\nthe file, returns the count."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"count_ananas"})," - same as ",(0,i.jsx)(n.code,{children:"count_anything"}),", but specialized for ananases, the\ndefault implementation from the skeleton expects you to implement ",(0,i.jsx)(n.code,{children:"count_anything"}),"\nand therefore it just calls the other function."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"write_number"})," - function that writes the number to the file, why would you\nneed the function is explained later :)"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"requirements",children:"Requirements"}),"\n",(0,i.jsxs)(n.p,{children:["For manipulation with the files you are only allowed to use ",(0,i.jsx)(n.code,{children:"fopen"}),", ",(0,i.jsx)(n.code,{children:"fclose"}),",\n",(0,i.jsx)(n.code,{children:"fgetc"})," and ",(0,i.jsx)(n.code,{children:"fputc"}),". Functions like ",(0,i.jsx)(n.code,{children:"fprintf"})," (except for ",(0,i.jsx)(n.code,{children:"stderr"})," or logging) and\n",(0,i.jsx)(n.code,{children:"fscanf"})," are ",(0,i.jsx)(n.strong,{children:"forbidden"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"In case you struggle and want to use one of those functions, the solution will be\npenalized by 50% of points."}),"\n",(0,i.jsx)(n.h3,{id:"bonus-part-075-k",children:"Bonus part (0.75 K\u20a1)"}),"\n",(0,i.jsxs)(n.p,{children:["Bonus part of this assignment is to implement ",(0,i.jsx)(n.code,{children:"count_anything"})," rather than ",(0,i.jsx)(n.code,{children:"count_ananas"}),"."]}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Smaller hint: This task does not need dynamic allocation :) You just need one\ngood helper function and the right idea ;)"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"task-no-2-weird-trees-1-k",children:"Task no. 2: Weird trees (1 K\u20a1)"}),"\n",(0,i.jsxs)(n.p,{children:["In this task we are crossing our paths with ",(0,i.jsx)(n.em,{children:"algorithms and data structures"}),".\nYour task is to write a program that constructs tree from the file that is given\nas an argument and pretty-prints it."]}),"\n",(0,i.jsxs)(n.p,{children:["Input file consists of lines, that include ",(0,i.jsx)(n.code,{children:"key"})," and ",(0,i.jsx)(n.code,{children:"rank"})," in form ",(0,i.jsx)(n.code,{children:"key;rank"}),"\nor ",(0,i.jsx)(n.code,{children:"nil"}),". Why would we have ",(0,i.jsx)(n.code,{children:"nil"})," in a file? The file represents pre-order iteration\nthrough the tree. Leaves never have rank different than 0, so you can safely assume\n2 non-existing ",(0,i.jsx)(n.code,{children:"nil"}),"s in the input after you read such node ;)"]}),"\n",(0,i.jsxs)("table",{children:[(0,i.jsxs)("tr",{children:[(0,i.jsx)("th",{children:"Example input file"}),(0,i.jsx)("th",{children:"Tree it represents"})]}),(0,i.jsxs)("tr",{children:[(0,i.jsx)("td",{children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"8;4\n5;3\n3;2\n2;1\n1;0\nnil\n4;0\n7;1\n6;0\nnil\n11;2\n10;1\n9;0\nnil\n12;0\n"})})}),(0,i.jsx)("td",{children:(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"tree",src:t(30073).Z+"",width:"633",height:"684"})})})]})]}),"\n",(0,i.jsxs)(n.p,{children:["In this task you are only provided with different trees in the ",(0,i.jsx)(n.code,{children:"test-trees"})," directory.\nImplementation and format of the pretty-print is totally up to you. :)"]}),"\n",(0,i.jsx)(n.p,{children:"Example of mine for the tree above:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"8 (rank = 4)\n+-- 5 (rank = 3)\n| +-- 3 (rank = 2)\n| | +-- 2 (rank = 1)\n| | | +-- 1 (rank = 0)\n| | +-- 4 (rank = 0)\n| +-- 7 (rank = 1)\n| +-- 6 (rank = 0)\n+-- 11 (rank = 2)\n +-- 10 (rank = 1)\n | +-- 9 (rank = 0)\n +-- 12 (rank = 0)\n"})}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Can you find out what are those trees? :)"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"submitting",children:"Submitting"}),"\n",(0,i.jsx)(n.p,{children:"In case you have any questions, feel free to reach out to me."}),"\n",(0,i.jsx)(n.hr,{})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},30073:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/tree-c9e37f87f9095c00fad33ea034485ce6.png"},11151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>o});var i=t(67294);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[5634],{58396:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>l});var i=t(85893),s=t(11151);const r={id:"seminar-08",title:"8th seminar",description:"Manipulating with files only char-by-char and a magic tree.\n"},o="8th seminar bonus assignment",c={id:"bonuses/seminar-08",title:"8th seminar",description:"Manipulating with files only char-by-char and a magic tree.\n",source:"@site/c/bonuses/08.md",sourceDirName:"bonuses",slug:"/bonuses/seminar-08",permalink:"/c/bonuses/seminar-08",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/bonuses/08.md",tags:[],version:"current",lastUpdatedAt:1701199517,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{id:"seminar-08",title:"8th seminar",description:"Manipulating with files only char-by-char and a magic tree.\n"},sidebar:"autogeneratedBar",previous:{title:"5th and 6th seminar",permalink:"/c/bonuses/seminar-05-06"},next:{title:"10th seminar",permalink:"/c/bonuses/seminar-10"}},a={},l=[{value:"Introduction",id:"introduction",level:2},{value:"Warning",id:"warning",level:2},{value:"Testing",id:"testing",level:2},{value:"Task no. 1: Counting (0.75 K\u20a1)",id:"task-no-1-counting-075-k",level:2},{value:"Requirements",id:"requirements",level:3},{value:"Bonus part (0.75 K\u20a1)",id:"bonus-part-075-k",level:3},{value:"Task no. 2: Weird trees (1 K\u20a1)",id:"task-no-2-weird-trees-1-k",level:2},{value:"Submitting",id:"submitting",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"8th-seminar-bonus-assignment",children:"8th seminar bonus assignment"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"pathname:///files/c/bonuses/08.tar.gz",children:"Source"})}),"\n",(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.p,{children:"In this bonus you can implement two tasks, one of them has a bonus part with generic\nsolution."}),"\n",(0,i.jsx)(n.p,{children:"One is focused on counting ananas or in case of generic version any substring in\nthe file, but with a restriction on the function you use."}),"\n",(0,i.jsx)(n.p,{children:"Other one has a more algorithmic spirit."}),"\n",(0,i.jsx)(n.p,{children:"For this bonus you can get at maximum 2.5 K\u20a1."}),"\n",(0,i.jsx)(n.h2,{id:"warning",children:"Warning"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"DO NOT COMMIT test data"})," to your own git repository, since the tests include\nfiles that exceed 10MB by themselves. Even if they are on separate branch, they\ntake up the space."]}),"\n",(0,i.jsx)(n.h2,{id:"testing",children:"Testing"}),"\n",(0,i.jsxs)(n.p,{children:["For testing you are provided with python script (requires ",(0,i.jsx)(n.code,{children:"click"})," to be installed:\n",(0,i.jsx)(n.code,{children:"pip3 install --user click"}),") and ",(0,i.jsx)(n.code,{children:"Makefile"})," that provides following targets:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"check-counting"})," - runs the ",(0,i.jsx)(n.code,{children:"counting"})," tests"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"check-counting-bonus"})," - runs the ",(0,i.jsx)(n.code,{children:"counting"})," tests with bonus implemented"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"check"})," - runs both ",(0,i.jsx)(n.code,{children:"counting"})," and ",(0,i.jsx)(n.code,{children:"counting-bonus"})," tests"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"clean"})," - removes output files from the test runs"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"task-no-1-counting-075-k",children:"Task no. 1: Counting (0.75 K\u20a1)"}),"\n",(0,i.jsx)(n.p,{children:"Your first task is to make smallish program that counts occurences of specific\n(or given) word from file and writes the number to other file."}),"\n",(0,i.jsx)(n.p,{children:"Usage of the program is:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"Usage: ./counting [string-to-be-counted]\n"})}),"\n",(0,i.jsx)(n.p,{children:"Arguments that are passed to the program represent:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:""})," - path to the file where we count the words"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:""})," - path to the file where we output the count"]}),"\n",(0,i.jsxs)(n.li,{children:["(optional argument) ",(0,i.jsx)(n.code,{children:"[string-to-be-counted]"})," - in case you implement bonus,\notherwise we default to word ",(0,i.jsx)(n.code,{children:"ananas"})," ;)"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"In skeleton you are given 3 empty, but documented, functions to implement."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"count_anything"})," - function accepts input file and substring to be counted in\nthe file, returns the count."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"count_ananas"})," - same as ",(0,i.jsx)(n.code,{children:"count_anything"}),", but specialized for ananases, the\ndefault implementation from the skeleton expects you to implement ",(0,i.jsx)(n.code,{children:"count_anything"}),"\nand therefore it just calls the other function."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"write_number"})," - function that writes the number to the file, why would you\nneed the function is explained later :)"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"requirements",children:"Requirements"}),"\n",(0,i.jsxs)(n.p,{children:["For manipulation with the files you are only allowed to use ",(0,i.jsx)(n.code,{children:"fopen"}),", ",(0,i.jsx)(n.code,{children:"fclose"}),",\n",(0,i.jsx)(n.code,{children:"fgetc"})," and ",(0,i.jsx)(n.code,{children:"fputc"}),". Functions like ",(0,i.jsx)(n.code,{children:"fprintf"})," (except for ",(0,i.jsx)(n.code,{children:"stderr"})," or logging) and\n",(0,i.jsx)(n.code,{children:"fscanf"})," are ",(0,i.jsx)(n.strong,{children:"forbidden"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"In case you struggle and want to use one of those functions, the solution will be\npenalized by 50% of points."}),"\n",(0,i.jsx)(n.h3,{id:"bonus-part-075-k",children:"Bonus part (0.75 K\u20a1)"}),"\n",(0,i.jsxs)(n.p,{children:["Bonus part of this assignment is to implement ",(0,i.jsx)(n.code,{children:"count_anything"})," rather than ",(0,i.jsx)(n.code,{children:"count_ananas"}),"."]}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Smaller hint: This task does not need dynamic allocation :) You just need one\ngood helper function and the right idea ;)"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"task-no-2-weird-trees-1-k",children:"Task no. 2: Weird trees (1 K\u20a1)"}),"\n",(0,i.jsxs)(n.p,{children:["In this task we are crossing our paths with ",(0,i.jsx)(n.em,{children:"algorithms and data structures"}),".\nYour task is to write a program that constructs tree from the file that is given\nas an argument and pretty-prints it."]}),"\n",(0,i.jsxs)(n.p,{children:["Input file consists of lines, that include ",(0,i.jsx)(n.code,{children:"key"})," and ",(0,i.jsx)(n.code,{children:"rank"})," in form ",(0,i.jsx)(n.code,{children:"key;rank"}),"\nor ",(0,i.jsx)(n.code,{children:"nil"}),". Why would we have ",(0,i.jsx)(n.code,{children:"nil"})," in a file? The file represents pre-order iteration\nthrough the tree. Leaves never have rank different than 0, so you can safely assume\n2 non-existing ",(0,i.jsx)(n.code,{children:"nil"}),"s in the input after you read such node ;)"]}),"\n",(0,i.jsxs)("table",{children:[(0,i.jsxs)("tr",{children:[(0,i.jsx)("th",{children:"Example input file"}),(0,i.jsx)("th",{children:"Tree it represents"})]}),(0,i.jsxs)("tr",{children:[(0,i.jsx)("td",{children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"8;4\n5;3\n3;2\n2;1\n1;0\nnil\n4;0\n7;1\n6;0\nnil\n11;2\n10;1\n9;0\nnil\n12;0\n"})})}),(0,i.jsx)("td",{children:(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"tree",src:t(30073).Z+"",width:"633",height:"684"})})})]})]}),"\n",(0,i.jsxs)(n.p,{children:["In this task you are only provided with different trees in the ",(0,i.jsx)(n.code,{children:"test-trees"})," directory.\nImplementation and format of the pretty-print is totally up to you. :)"]}),"\n",(0,i.jsx)(n.p,{children:"Example of mine for the tree above:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"8 (rank = 4)\n+-- 5 (rank = 3)\n| +-- 3 (rank = 2)\n| | +-- 2 (rank = 1)\n| | | +-- 1 (rank = 0)\n| | +-- 4 (rank = 0)\n| +-- 7 (rank = 1)\n| +-- 6 (rank = 0)\n+-- 11 (rank = 2)\n +-- 10 (rank = 1)\n | +-- 9 (rank = 0)\n +-- 12 (rank = 0)\n"})}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Can you find out what are those trees? :)"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"submitting",children:"Submitting"}),"\n",(0,i.jsx)(n.p,{children:"In case you have any questions, feel free to reach out to me."}),"\n",(0,i.jsx)(n.hr,{})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},30073:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/tree-c9e37f87f9095c00fad33ea034485ce6.png"},11151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>o});var i=t(67294);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5fe5d476.f7c213ae.js b/assets/js/5fe5d476.73f34dd7.js similarity index 99% rename from assets/js/5fe5d476.f7c213ae.js rename to assets/js/5fe5d476.73f34dd7.js index 85bbcb9..efef806 100644 --- a/assets/js/5fe5d476.f7c213ae.js +++ b/assets/js/5fe5d476.73f34dd7.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[2619],{14457:(s,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>t,default:()=>o,frontMatter:()=>l,metadata:()=>r,toc:()=>m});var a=n(85893),i=n(11151);const l={id:"pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",tags:["java","recursion","exponential","greedy","dynamic-programming","top-down-dp","bottom-up-dp"],last_updated:{date:new Date("2023-08-17T00:00:00.000Z")}},t=void 0,r={id:"recursion/pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",source:"@site/algorithms/04-recursion/2023-08-17-pyramid-slide-down.md",sourceDirName:"04-recursion",slug:"/recursion/pyramid-slide-down",permalink:"/algorithms/recursion/pyramid-slide-down",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/algorithms/04-recursion/2023-08-17-pyramid-slide-down.md",tags:[{label:"java",permalink:"/algorithms/tags/java"},{label:"recursion",permalink:"/algorithms/tags/recursion"},{label:"exponential",permalink:"/algorithms/tags/exponential"},{label:"greedy",permalink:"/algorithms/tags/greedy"},{label:"dynamic-programming",permalink:"/algorithms/tags/dynamic-programming"},{label:"top-down-dp",permalink:"/algorithms/tags/top-down-dp"},{label:"bottom-up-dp",permalink:"/algorithms/tags/bottom-up-dp"}],version:"current",lastUpdatedAt:1701196739,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{id:"pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",tags:["java","recursion","exponential","greedy","dynamic-programming","top-down-dp","bottom-up-dp"],last_updated:{date:"2023-08-17T00:00:00.000Z"}},sidebar:"autogeneratedBar",previous:{title:"Recursion and backtracking with Robot Karel",permalink:"/algorithms/recursion/karel-1"},next:{title:"Red-Black Trees",permalink:"/algorithms/category/red-black-trees"}},c={},m=[{value:"Problem",id:"problem",level:2},{value:"Solving the problem",id:"solving-the-problem",level:2},{value:"Na\xefve solution",id:"na\xefve-solution",level:2},{value:"Time complexity",id:"time-complexity",level:3},{value:"Greedy solution",id:"greedy-solution",level:2},{value:"Time complexity",id:"time-complexity-1",level:3},{value:"Running the tests",id:"running-the-tests",level:3},{value:"Top-down DP",id:"top-down-dp",level:2},{value:"Time complexity",id:"time-complexity-2",level:3},{value:"Memory complexity",id:"memory-complexity",level:3},{value:"Bottom-up DP",id:"bottom-up-dp",level:2},{value:"Time complexity",id:"time-complexity-3",level:3},{value:"Memory complexity",id:"memory-complexity-1",level:3},{value:"Summary",id:"summary",level:2}];function h(s){const e={a:"a",admonition:"admonition",annotation:"annotation",code:"code",em:"em",h2:"h2",h3:"h3",hr:"hr",li:"li",math:"math",mdxAdmonitionTitle:"mdxAdmonitionTitle",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",mspace:"mspace",mstyle:"mstyle",msub:"msub",msup:"msup",mtable:"mtable",mtd:"mtd",mtext:"mtext",mtr:"mtr",munderover:"munderover",ol:"ol",p:"p",pre:"pre",section:"section",semantics:"semantics",span:"span",strong:"strong",sup:"sup",...(0,i.a)(),...s.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(e.p,{children:"In this post we will try to solve one problem in different ways."}),"\n",(0,a.jsx)(e.h2,{id:"problem",children:"Problem"}),"\n",(0,a.jsxs)(e.p,{children:["The problem we are going to solve is one of ",(0,a.jsx)(e.em,{children:"CodeWars"})," katas and is called\n",(0,a.jsx)(e.a,{href:"https://www.codewars.com/kata/551f23362ff852e2ab000037",children:"Pyramid Slide Down"}),"."]}),"\n",(0,a.jsxs)(e.p,{children:["We are given a 2D array of integers and we are to find the ",(0,a.jsx)(e.em,{children:"slide down"}),".\n",(0,a.jsx)(e.em,{children:"Slide down"})," is a maximum sum of consecutive numbers from the top to the bottom."]}),"\n",(0,a.jsx)(e.p,{children:"Let's have a look at few examples. Consider the following pyramid:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 3\n 7 4\n 2 4 6\n8 5 9 3\n"})}),"\n",(0,a.jsx)(e.p,{children:"This pyramid has following slide down:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" *3\n *7 4\n 2 *4 6\n8 5 *9 3\n"})}),"\n",(0,a.jsxs)(e.p,{children:["And its value is ",(0,a.jsx)(e.code,{children:"23"}),"."]}),"\n",(0,a.jsxs)(e.p,{children:["We can also have a look at a ",(0,a.jsx)(e.em,{children:"bigger"})," example:"]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 75\n 95 64\n 17 47 82\n 18 35 87 10\n 20 4 82 47 65\n 19 1 23 3 34\n 88 2 77 73 7 63 67\n 99 65 4 28 6 16 70 92\n 41 41 26 56 83 40 80 70 33\n 41 48 72 33 47 32 37 16 94 29\n 53 71 44 65 25 43 91 52 97 51 14\n 70 11 33 28 77 73 17 78 39 68 17 57\n 91 71 52 38 17 14 91 43 58 50 27 29 48\n 63 66 4 68 89 53 67 30 73 16 69 87 40 31\n 4 62 98 27 23 9 70 98 73 93 38 53 60 4 23\n"})}),"\n",(0,a.jsxs)(e.p,{children:["Slide down in this case is equal to ",(0,a.jsx)(e.code,{children:"1074"}),"."]}),"\n",(0,a.jsx)(e.h2,{id:"solving-the-problem",children:"Solving the problem"}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["I will describe the following ways you can approach this problem and implement\nthem in ",(0,a.jsx)(e.em,{children:"Java"}),(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-1",id:"user-content-fnref-1","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"1"})}),"."]})}),"\n",(0,a.jsxs)(e.p,{children:["For all of the following solutions I will be using basic ",(0,a.jsx)(e.code,{children:"main"})," function that\nwill output ",(0,a.jsx)(e.code,{children:"true"}),"/",(0,a.jsx)(e.code,{children:"false"})," based on the expected output of our algorithm. Any\nother differences will lie only in the solutions of the problem. You can see the\n",(0,a.jsx)(e.code,{children:"main"})," here:"]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:'public static void main(String[] args) {\n System.out.print("Test #1: ");\n System.out.println(longestSlideDown(new int[][] {\n { 3 },\n { 7, 4 },\n { 2, 4, 6 },\n { 8, 5, 9, 3 }\n }) == 23 ? "passed" : "failed");\n\n System.out.print("Test #2: ");\n System.out.println(longestSlideDown(new int[][] {\n { 75 },\n { 95, 64 },\n { 17, 47, 82 },\n { 18, 35, 87, 10 },\n { 20, 4, 82, 47, 65 },\n { 19, 1, 23, 75, 3, 34 },\n { 88, 2, 77, 73, 7, 63, 67 },\n { 99, 65, 4, 28, 6, 16, 70, 92 },\n { 41, 41, 26, 56, 83, 40, 80, 70, 33 },\n { 41, 48, 72, 33, 47, 32, 37, 16, 94, 29 },\n { 53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14 },\n { 70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57 },\n { 91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48 },\n { 63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31 },\n { 4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23 },\n }) == 1074 ? "passed" : "failed");\n}\n'})}),"\n",(0,a.jsx)(e.h2,{id:"na\xefve-solution",children:"Na\xefve solution"}),"\n",(0,a.jsx)(e.p,{children:"Our na\xefve solution consists of trying out all the possible slides and finding\nthe one with maximum sum."}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: We have gotten out of bounds, there's no reasonable value to\n // return, so we just return the \u2039MIN_VALUE\u203a to ensure that it cannot\n // be maximum.\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: Bottom of the pyramid, we just return the value, there's\n // nowhere to slide anymore.\n return pyramid[row][col];\n }\n\n // Otherwise we account for the current position and return maximum of the\n // available \u201cslides\u201d.\n return pyramid[row][col] + Math.max(\n longestSlideDown(pyramid, row + 1, col),\n longestSlideDown(pyramid, row + 1, col + 1));\n}\n\npublic static int longestSlideDown(int[][] pyramid) {\n // We start the slide in the top cell of the pyramid.\n return longestSlideDown(pyramid, 0, 0);\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"As you can see, we have 2 overloads:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"int longestSlideDown(int[][] pyramid);\nint longestSlideDown(int[][] pyramid, int row, int col);\n"})}),"\n",(0,a.jsxs)(e.p,{children:["First one is used as a ",(0,a.jsx)(e.em,{children:"public interface"})," to the solution, you just pass in the\npyramid itself. Second one is the recursive \u201calgorithm\u201d that finds the slide\ndown."]}),"\n",(0,a.jsxs)(e.p,{children:["It is a relatively simple solution\u2026 There's nothing to do at the bottom of the\npyramid, so we just return the value in the ",(0,a.jsx)(e.em,{children:"cell"}),". Otherwise we add it and try\nto slide down the available cells below the current row."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"If you get the source code and run it yourself, it runs rather fine\u2026 I hope you\nare wondering about the time complexity of the proposed solution and, since it\nreally is a na\xefve solution, the time complexity is pretty bad. Let's find the\nworst case scenario."}),"\n",(0,a.jsx)(e.p,{children:"Let's start with the first overload:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid) {\n return longestSlideDown(pyramid, 0, 0);\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["There's not much to do here, so we can safely say that the time complexity of\nthis function is bounded by ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]}),", where ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"T"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"})]})})]})," is our second overload. This\ndoesn't tell us anything, so let's move on to the second overload where we are\ngoing to define the ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})," function."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: We have gotten out of bounds, there's no reasonable value to\n // return, so we just return the \u2039MIN_VALUE\u203a to ensure that it cannot\n // be maximum.\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: Bottom of the pyramid, we just return the value, there's\n // nowhere to slide anymore.\n return pyramid[row][col];\n }\n\n // Otherwise we account for the current position and return maximum of the\n // available \u201cslides\u201d.\n return pyramid[row][col] + Math.max(\n longestSlideDown(pyramid, row + 1, col),\n longestSlideDown(pyramid, row + 1, col + 1));\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["Fun fact is that the whole \u201calgorithm\u201d consists of just 2 ",(0,a.jsx)(e.code,{children:"return"})," statements\nand nothing else. Let's dissect them!"]}),"\n",(0,a.jsxs)(e.p,{children:["First ",(0,a.jsx)(e.code,{children:"return"})," statement is the base case, so it has a constant time complexity."]}),"\n",(0,a.jsxs)(e.p,{children:["Second one a bit tricky. We add two numbers together, which we'll consider as\nconstant, but for the right part of the expression we take maximum from the left\nand right paths. OK\u2026 So what happens? We evaluate the ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," while\nchoosing the under and right both. They are separate computations though, so we\nare branching from each call of ",(0,a.jsx)(e.code,{children:"longestSlideDown"}),", unless it's a base case."]}),"\n",(0,a.jsx)(e.p,{children:"What does that mean for us then? We basically get"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"{"}),(0,a.jsxs)(e.mtable,{rowspacing:"0.36em",columnalign:"left left",columnspacing:"1em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsx)(e.mn,{children:"1"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mtext,{children:",\xa0if\xa0"}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"1"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"1"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsx)(e.mtext,{children:",\xa0otherwise"})})})]})]})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(y) =\n\\begin{cases}\n1 & \\text{, if } y = rows \\\\\n1 + 2 \\cdot T(y + 1) & \\text{, otherwise}\n\\end{cases}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mclose",children:")"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:(0,a.jsx)(e.span,{className:"delimsizing size4",children:"{"})}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.69em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.69em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord",children:"1"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.25em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord",children:"1"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"1"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.19em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"arraycolsep",style:{width:"1em"}}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.69em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.69em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord text",children:(0,a.jsx)(e.span,{className:"mord",children:",\xa0if\xa0"})}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.25em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord text",children:(0,a.jsx)(e.span,{className:"mord",children:",\xa0otherwise"})})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.19em"},children:(0,a.jsx)(e.span,{})})})]})})]})}),(0,a.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"That looks rather easy to compute, isn't it? If you sum it up, you'll get:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mo,{children:"\u2208"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsxs)(e.msup,{children:[(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"})]})]}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(rows) \\in \\mathcal{O}(2^{rows})"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"\u2208"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsx)(e.span,{className:"vlist-t",children:(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.7144em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.113em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mathnormal mtight",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal mtight",children:"s"})]})})]})})})})})]}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"If you wonder why, I'll try to describe it intuitively:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["In each call to ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," we do some work in constant time,\nregardless of being in the base case. Those are the ",(0,a.jsx)(e.code,{children:"1"}),"s in both cases."]}),"\n",(0,a.jsxs)(e.li,{children:["If we are not in the base case, we move one row down ",(0,a.jsx)(e.strong,{children:"twice"}),". That's how we\nobtained ",(0,a.jsx)(e.code,{children:"2 *"})," and ",(0,a.jsx)(e.code,{children:"y + 1"})," in the ",(0,a.jsx)(e.em,{children:"otherwise"})," case."]}),"\n",(0,a.jsxs)(e.li,{children:["We move row-by-row, so we move down ",(0,a.jsx)(e.code,{children:"y"}),"-times and each call splits to two\nsubtrees."]}),"\n",(0,a.jsxs)(e.li,{children:["Overall, if we were to represent the calls as a tree, we would get a full\nbinary tree of height ",(0,a.jsx)(e.code,{children:"y"}),", in each node we do some work in constant time,\ntherefore we can just sum the ones."]}),"\n"]}),"\n",(0,a.jsx)(e.admonition,{type:"warning",children:(0,a.jsx)(e.p,{children:"It would've been more complicated to get an exact result. In the equation above\nwe are assuming that the width of the pyramid is bound by the height."})}),"\n",(0,a.jsxs)(e.p,{children:["Hopefully we can agree that this is not the best we can do. ","\ud83d\ude09"]}),"\n",(0,a.jsx)(e.h2,{id:"greedy-solution",children:"Greedy solution"}),"\n",(0,a.jsxs)(e.p,{children:["We will try to optimize it a bit. Let's start with a relatively simple ",(0,a.jsx)(e.em,{children:"greedy"}),"\napproach."]}),"\n",(0,a.jsx)(e.admonition,{title:"Greedy algorithms",type:"info",children:(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Greedy algorithms"})," can be described as algorithms that decide the action on the\noptimal option at the moment."]})}),"\n",(0,a.jsx)(e.p,{children:"We can try to adjust the na\xefve solution. The most problematic part are the\nrecursive calls. Let's apply the greedy approach there:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row == pyramid.length - 1) {\n // BASE: We're at the bottom\n return pyramid[row][col];\n }\n\n if (col + 1 >= pyramid[row + 1].length\n || pyramid[row + 1][col] > pyramid[row + 1][col + 1]) {\n // If we cannot go right or it's not feasible, we continue to the left.\n return pyramid[row][col] + longestSlideDown(pyramid, row + 1, col);\n }\n\n // Otherwise we just move to the right.\n return pyramid[row][col] + longestSlideDown(pyramid, row + 1, col + 1);\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["OK, if we cannot go right ",(0,a.jsx)(e.strong,{children:"or"})," the right path adds smaller value to the sum,\nwe simply go left."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-1",children:"Time complexity"}),"\n",(0,a.jsxs)(e.p,{children:["We have switched from ",(0,a.jsx)(e.em,{children:"adding the maximum"})," to ",(0,a.jsx)(e.em,{children:"following the \u201cbigger\u201d path"}),", so\nwe improved the time complexity tremendously. We just go down the pyramid all\nthe way to the bottom. Therefore we are getting:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsx)(e.p,{children:"We have managed to convert our exponential solution into a linear one."}),"\n",(0,a.jsx)(e.h3,{id:"running-the-tests",children:"Running the tests"}),"\n",(0,a.jsx)(e.p,{children:"However, if we run the tests, we notice that the second test failed:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:"Test #1: passed\nTest #2: failed\n"})}),"\n",(0,a.jsxs)(e.p,{children:["What's going on? Well, we have improved the time complexity, but greedy\nalgorithms are not the ideal solution to ",(0,a.jsx)(e.strong,{children:"all"})," problems. In this case there\nmay be a solution that is bigger than the one found using the greedy algorithm."]}),"\n",(0,a.jsx)(e.p,{children:"Imagine the following pyramid:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 1\n 2 3\n 5 6 7\n 8 9 10 11\n99 13 14 15 16\n"})}),"\n",(0,a.jsx)(e.p,{children:"We start at the top:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"1"}),", we can choose from ",(0,a.jsx)(e.code,{children:"2"})," and ",(0,a.jsx)(e.code,{children:"3"}),", ",(0,a.jsx)(e.code,{children:"3"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"3"}),", we can choose from ",(0,a.jsx)(e.code,{children:"6"})," and ",(0,a.jsx)(e.code,{children:"7"}),", ",(0,a.jsx)(e.code,{children:"7"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"7"}),", we can choose from ",(0,a.jsx)(e.code,{children:"10"})," and ",(0,a.jsx)(e.code,{children:"11"}),", ",(0,a.jsx)(e.code,{children:"11"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"11"}),", we can choose from ",(0,a.jsx)(e.code,{children:"15"})," and ",(0,a.jsx)(e.code,{children:"16"}),", ",(0,a.jsx)(e.code,{children:"16"})," looks better, so\nwe choose it."]}),"\n"]}),"\n",(0,a.jsxs)(e.p,{children:["Our final sum is: ",(0,a.jsx)(e.code,{children:"1 + 3 + 7 + 11 + 16 = 38"}),", but in the bottom left cell we\nhave a ",(0,a.jsx)(e.code,{children:"99"})," that is bigger than our whole sum."]}),"\n",(0,a.jsx)(e.admonition,{type:"tip",children:(0,a.jsx)(e.p,{children:"Dijkstra's algorithm is a greedy algorithm too, try to think why it is correct."})}),"\n",(0,a.jsx)(e.h2,{id:"top-down-dp",children:"Top-down DP"}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Top-down dynamic programming"})," is probably the most common approach, since (at\nleast looks like) is the easiest to implement. The whole point is avoiding the\nunnecessary computations that we have already done."]}),"\n",(0,a.jsxs)(e.p,{children:["In our case, we can use our na\xefve solution and put a ",(0,a.jsx)(e.em,{children:"cache"})," on top of it that\nwill make sure, we don't do unnecessary calculations."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"// This \u201cstructure\u201d is required, since I have decided to use \u2039TreeMap\u203a which\n// requires the ordering on the keys. It represents one position in the pyramid.\nrecord Position(int row, int col) implements Comparable {\n public int compareTo(Position r) {\n if (row != r.row) {\n return Integer.valueOf(row).compareTo(r.row);\n }\n\n if (col != r.col) {\n return Integer.valueOf(col).compareTo(r.col);\n }\n\n return 0;\n }\n}\n\npublic static int longestSlideDown(\n int[][] pyramid,\n TreeMap cache,\n Position position) {\n int row = position.row;\n int col = position.col;\n\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: out of bounds\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: bottom of the pyramid\n return pyramid[position.row][position.col];\n }\n\n if (!cache.containsKey(position)) {\n // We haven't computed the position yet, so we run the same \u201cformula\u201d as\n // in the na\xefve version \xbband\xab we put calculated slide into the cache.\n // Next time we want the slide down from given position, it will be just\n // retrieved from the cache.\n int slideDown = Math.max(\n longestSlideDown(pyramid, cache, new Position(row + 1, col)),\n longestSlideDown(pyramid, cache, new Position(row + 1, col + 1)));\n cache.put(position, pyramid[row][col] + slideDown);\n }\n\n return cache.get(position);\n}\n\npublic static int longestSlideDown(int[][] pyramid) {\n // At the beginning we need to create a cache and share it across the calls.\n TreeMap cache = new TreeMap<>();\n return longestSlideDown(pyramid, cache, new Position(0, 0));\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["You have probably noticed that ",(0,a.jsx)(e.code,{children:"record Position"})," have appeared. Since we are\ncaching the already computed values, we need a \u201creasonable\u201d key. In this case we\nshare the cache only for one ",(0,a.jsx)(e.em,{children:"run"})," (i.e. pyramid) of the ",(0,a.jsx)(e.code,{children:"longestSlideDown"}),", so\nwe can cache just with the indices within the pyramid, i.e. the ",(0,a.jsx)(e.code,{children:"Position"}),"."]}),"\n",(0,a.jsx)(e.admonition,{title:"Record",type:"tip",children:(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Record"})," is relatively new addition to the Java language. It is basically an\nimmutable structure with implicitly defined ",(0,a.jsx)(e.code,{children:".equals()"}),", ",(0,a.jsx)(e.code,{children:".hashCode()"}),",\n",(0,a.jsx)(e.code,{children:".toString()"})," and getters for the attributes."]})}),"\n",(0,a.jsxs)(e.p,{children:["Because of the choice of ",(0,a.jsx)(e.code,{children:"TreeMap"}),", we had to additionally define the ordering\non it."]}),"\n",(0,a.jsxs)(e.p,{children:["In the ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," you can notice that the computation which used to be\nat the end of the na\xefve version above, is now wrapped in an ",(0,a.jsx)(e.code,{children:"if"})," statement that\nchecks for the presence of the position in the cache and computes the slide down\njust when it's needed."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-2",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"If you think that evaluating time complexity for this approach is a bit more\ntricky, you are right. Keeping the cache in mind, it is not the easiest thing\nto do. However there are some observations that might help us figure this out:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsx)(e.li,{children:"Slide down from each position is calculated only once."}),"\n",(0,a.jsx)(e.li,{children:"Once calculated, we use the result from the cache."}),"\n"]}),"\n",(0,a.jsxs)(e.p,{children:["Knowing this, we still cannot, at least easily, describe the time complexity of\nfinding the best slide down from a specific position, ",(0,a.jsx)(e.strong,{children:"but"})," we can bound it\nfrom above for the ",(0,a.jsx)(e.strong,{children:"whole"})," run from the top. Now the question is how we can do\nthat!"]}),"\n",(0,a.jsxs)(e.p,{children:["Overall we are doing the same things for almost",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-2",id:"user-content-fnref-2","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"2"})})," all of the positions within\nthe pyramid:"]}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["\n",(0,a.jsx)(e.p,{children:"We calculate and store it (using the partial results stored in cache). This\nis done only once."}),"\n",(0,a.jsxs)(e.p,{children:["For each calculation we take 2 values from the cache and insert one value.\nBecause we have chosen ",(0,a.jsx)(e.code,{children:"TreeMap"}),", these 3 operations have logarithmic time\ncomplexity and therefore this step is equivalent to ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"3"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"3 \\cdot \\log_2{n}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"3"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),"."]}),"\n",(0,a.jsx)(e.p,{children:"However for the sake of simplicity, we are going to account only for the\ninsertion, the reason is rather simple, if we include the 2 retrievals here,\nit will be interleaved with the next step, therefore it is easier to keep the\nretrievals in the following point."}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsx)(e.p,{children:"You might have noticed it's still not that easy, cause we're not having full\ncache right from the beginning, but the sum of those logarithms cannot be\nexpressed in a nice way, so taking the upper bound, i.e. expecting the cache\nto be full at all times, is the best option for nice and readable complexity\nof the whole approach."})}),"\n",(0,a.jsxs)(e.p,{children:["Our final upper bound of this work is therefore ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\log_2{n}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})})]}),"."]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{children:["\n",(0,a.jsxs)(e.p,{children:["We retrieve it from the cache. Same as in first point, but only twice, so we\nget ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"2 \\cdot \\log_2{n}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),"."]}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["It's done twice because of the ",(0,a.jsx)(e.code,{children:".containsKey()"})," in the ",(0,a.jsx)(e.code,{children:"if"})," condition."]})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(e.p,{children:"Okay, we have evaluated work done for each of the cells in the pyramid and now\nwe need to put it together."}),"\n",(0,a.jsx)(e.p,{children:"Let's split the time complexity of our solution into two operands:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(r + s)"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"r"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"r"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})]})})]})," will represent the ",(0,a.jsx)(e.em,{children:"actual"})," calculation of the cells and ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"s"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"s"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})})]})," will represent\nthe additional retrievals on top of the calculation."]}),"\n",(0,a.jsxs)(e.p,{children:["We calculate the values only ",(0,a.jsx)(e.strong,{children:"once"}),", therefore we can safely agree on:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"r"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\nr &= n \\cdot \\log{n} \\\\\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1.5em",verticalAlign:"-0.5em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"1em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.16em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.5em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"1em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.16em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.5em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,a.jsxs)(e.p,{children:["What about the ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"s"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"s"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})})]})," though? Key observation here is the fact that we have 2\nlookups on the tree in each of them ",(0,a.jsx)(e.strong,{children:"and"})," we do it twice, cause each cell has\nat most 2 parents:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"("}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{fence:"true",children:")"})]})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"4"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\ns &= n \\cdot 2 \\cdot \\left( 2 \\cdot \\log{n} \\right) \\\\\ns &= 4 \\cdot n \\cdot \\log{n}\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:"("}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose delimcenter",style:{top:"0em"},children:")"})]})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"4"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsxs)(e.p,{children:["You might've noticed that lookups actually take more time than the construction\nof the results. This is not entirely true, since we have included the\n",(0,a.jsx)(e.code,{children:".containsKey()"})," and ",(0,a.jsx)(e.code,{children:".get()"})," from the ",(0,a.jsx)(e.code,{children:"return"})," statement in the second part."]}),(0,a.jsx)(e.p,{children:"If we were to represent this more precisely, we could've gone with:"}),(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"r"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"3"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\nr &= 3 \\cdot n \\cdot \\log{n} \\\\\ns &= 2 \\cdot n \\cdot \\log{n}\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"3"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),(0,a.jsx)(e.p,{children:"On the other hand we are summing both numbers together, therefore in the end it\ndoesn't really matter."}),(0,a.jsxs)(e.p,{children:["(",(0,a.jsx)(e.em,{children:"Feel free to compare the sums of both \u201csplits\u201d."}),")"]})]}),"\n",(0,a.jsxs)(e.p,{children:["And so our final time complexity for the whole ",(0,a.jsx)(e.em,{children:"top-down dynamic programming"}),"\napproach is:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"4"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mn,{children:"5"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(r + s) \\\\\n\\mathcal{O}(n \\cdot \\log{n} + 4 \\cdot n \\cdot \\log{n}) \\\\\n\\mathcal{O}(5 \\cdot n \\cdot \\log{n}) \\\\\n\\mathcal{O}(n \\cdot \\log{n})"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"4"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4445em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord",children:"5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4445em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsxs)(e.p,{children:["As you can see, this is worse than our ",(0,a.jsx)(e.em,{children:"greedy"})," solution that was incorrect, but\nit's better than the ",(0,a.jsx)(e.em,{children:"na\xefve"})," one."]}),"\n",(0,a.jsx)(e.h3,{id:"memory-complexity",children:"Memory complexity"}),"\n",(0,a.jsxs)(e.p,{children:["With this approach we need to talk about the memory complexity too, because we\nhave introduced cache. If you think that the memory complexity is linear to the\ninput, you are right. We start at the top and try to find each and every slide\ndown. At the end we get the final result for ",(0,a.jsx)(e.code,{children:"new Position(0, 0)"}),", so we need to\ncompute everything below."]}),"\n",(0,a.jsx)(e.p,{children:"That's how we obtain:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"n"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"n"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})]})})]})," represents the total amount of cells in the pyramid, i.e."]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.munderover,{children:[(0,a.jsx)(e.mo,{children:"\u2211"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"0"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"p"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"y"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"r"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"a"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"m"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"i"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"d"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"."}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"l"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"e"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"n"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"g"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"t"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"h"})]}),(0,a.jsx)(e.mo,{children:"\u2212"}),(0,a.jsx)(e.mn,{children:"1"})]})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"p"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"y"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"r"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"a"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"m"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"i"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"d"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"["}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{fence:"true",children:"]"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"."}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"l"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"e"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"n"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"g"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"t"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"h"})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\sum_{y=0}^{\\mathtt{pyramid.length} - 1} \\mathtt{pyramid}\\left[y\\right]\\mathtt{.length}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3.2709em",verticalAlign:"-1.4032em"}}),(0,a.jsx)(e.span,{className:"mop op-limits",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.8677em"},children:[(0,a.jsxs)(e.span,{style:{top:"-1.8829em",marginLeft:"0em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,a.jsx)(e.span,{className:"mord mtight",children:"0"})]})})]}),(0,a.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{children:(0,a.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,a.jsxs)(e.span,{style:{top:"-4.3666em",marginLeft:"0em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mtight",children:(0,a.jsx)(e.span,{className:"mord mathtt mtight",children:"pyramid.length"})}),(0,a.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,a.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.4032em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathtt",children:"pyramid"})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:"["}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mclose delimcenter",style:{top:"0em"},children:"]"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathtt",children:".length"})})]})})]})}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["If you're wondering whether it's correct because of the second ",(0,a.jsx)(e.code,{children:"if"})," in our\nfunction, your guess is right. However we are expressing the complexity in the\nBachmann-Landau notation, so we care about the ",(0,a.jsx)(e.strong,{children:"upper bound"}),", not the exact\nnumber."]})}),"\n",(0,a.jsxs)(e.admonition,{title:"Can this be optimized?",type:"tip",children:[(0,a.jsx)(e.p,{children:"Yes, it can! Try to think about a way, how can you minimize the memory\ncomplexity of this approach. I'll give you a hint:"}),(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})})]}),"\n",(0,a.jsx)(e.h2,{id:"bottom-up-dp",children:"Bottom-up DP"}),"\n",(0,a.jsxs)(e.p,{children:["If you try to think in depth about the top-down DP solution, you might notice\nthat the ",(0,a.jsx)(e.em,{children:"core"})," of it stands on caching the calculations that have been already\ndone on the lower \u201clevels\u201d of the pyramid. Our bottom-up implementation will be\nusing this fact!"]}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsxs)(e.p,{children:["As I have said in the ",(0,a.jsx)(e.em,{children:"top-down DP"})," section, it is the easiest way to implement\nDP (unless the cached function has complicated parameters, in that case it might\nget messy)."]}),(0,a.jsx)(e.p,{children:"Bottom-up dynamic programming can be more effective, but may be more complicated\nto implement right from the beginning."})]}),"\n",(0,a.jsx)(e.p,{children:"Let's see how we can implement it:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid) {\n // In the beginning we declare new array. At this point it is easier to just\n // work with the one dimension, i.e. just allocating the space for the rows.\n int[][] slideDowns = new int[pyramid.length][];\n\n // Bottom row gets just copied, there's nothing else to do\u2026 It's the base\n // case.\n slideDowns[pyramid.length - 1] = Arrays.copyOf(pyramid[pyramid.length - 1],\n pyramid[pyramid.length - 1].length);\n\n // Then we need to propagate the found slide downs for each of the levels\n // above.\n for (int y = pyramid.length - 2; y >= 0; --y) {\n // We start by copying the values lying in the row we're processing.\n // They get included in the final sum and we need to allocate the space\n // for the precalculated slide downs anyways.\n int[] row = Arrays.copyOf(pyramid[y], pyramid[y].length);\n\n // At this we just need to \u201cfetch\u201d the partial results from \u201cneighbours\u201d\n for (int x = 0; x < row.length; ++x) {\n // We look under our position, since we expect the rows to get\n // shorter, we can safely assume such position exists.\n int under = slideDowns[y + 1][x];\n\n // Then we have a look to the right, such position doesn't have to\n // exist, e.g. on the right edge, so we validate the index, and if\n // it doesn't exist, we just assign minimum of the \u2039int\u203a which makes\n // sure that it doesn't get picked in the \u2039Math.max()\u203a call.\n int toRight = x + 1 < slideDowns[y + 1].length\n ? slideDowns[y + 1][x + 1]\n : Integer.MIN_VALUE;\n\n // Finally we add the best choice at this point.\n row[x] += Math.max(under, toRight);\n }\n\n // And save the row we've just calculated partial results for to the\n // \u201ctable\u201d.\n slideDowns[y] = row;\n }\n\n // At the end we can find our seeked slide down at the top cell.\n return slideDowns[0][0];\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"I've tried to explain the code as much as possible within the comments, since it\nmight be more beneficial to see right next to the \u201coffending\u201d lines."}),"\n",(0,a.jsxs)(e.p,{children:["As you can see, in this approach we go from the other side",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-3",id:"user-content-fnref-3","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"3"})}),", the bottom of\nthe pyramid and propagate the partial results up."]}),"\n",(0,a.jsxs)(e.admonition,{type:"info",children:[(0,a.jsxs)(e.mdxAdmonitionTitle,{children:["How is this different from the ",(0,a.jsx)(e.em,{children:"greedy"})," solution???"]}),(0,a.jsxs)(e.p,{children:["If you try to compare them, you might find a very noticable difference. The\ngreedy approach is going from the top to the bottom without ",(0,a.jsx)(e.strong,{children:"any"})," knowledge of\nwhat's going on below. On the other hand, bottom-up DP is going from the bottom\n(",(0,a.jsx)(e.em,{children:"DUH\u2026"}),") and ",(0,a.jsx)(e.strong,{children:"propagates"})," the partial results to the top. The propagation is\nwhat makes sure that at the top I don't choose the best ",(0,a.jsx)(e.strong,{children:"local"})," choice, but\nthe best ",(0,a.jsx)(e.strong,{children:"overall"})," result I can achieve."]})]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-3",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"Time complexity of this solution is rather simple. We allocate an array for the\nrows and then for each row, we copy it and adjust the partial results. Doing\nthis we get:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows + 2n)"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"Of course, this is an upper bound, since we iterate through the bottom row only\nonce."}),"\n",(0,a.jsx)(e.h3,{id:"memory-complexity-1",children:"Memory complexity"}),"\n",(0,a.jsxs)(e.p,{children:["We're allocating an array for the pyramid ",(0,a.jsx)(e.strong,{children:"again"})," for our partial results, so\nwe get:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsx)(e.p,{children:"If we were writing this in C++ or Rust, we could've avoided that, but not\nreally."}),(0,a.jsxs)(e.p,{children:["C++ would allow us to ",(0,a.jsx)(e.strong,{children:"copy"})," the pyramid rightaway into the parameter, so we\nwould be able to directly change it. However it's still a copy, even though we\ndon't need to allocate anything ourselves. It's just implicitly done for us."]}),(0,a.jsxs)(e.p,{children:["Rust is more funny in this case. If the pyramids weren't used after the call of\n",(0,a.jsx)(e.code,{children:"longest_slide_down"}),", it would simply ",(0,a.jsx)(e.strong,{children:"move"})," them into the functions. If they\nwere used afterwards, the compiler would force you to either borrow it, or\n",(0,a.jsx)(e.em,{children:"clone-and-move"})," for the function."]}),(0,a.jsx)(e.hr,{}),(0,a.jsxs)(e.p,{children:["Since we're doing it in Java, we get a reference to the ",(0,a.jsx)(e.em,{children:"original"})," array and we\ncan't do whatever we want with it."]})]}),"\n",(0,a.jsx)(e.h2,{id:"summary",children:"Summary"}),"\n",(0,a.jsxs)(e.p,{children:["And we've finally reached the end. We have seen 4 different \u201csolutions\u201d",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-4",id:"user-content-fnref-4","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"4"})})," of\nthe same problem using different approaches. Different approaches follow the\norder in which you might come up with them, each approach influences its\nsuccessor and represents the way we can enhance the existing implementation."]}),"\n",(0,a.jsx)(e.hr,{}),"\n",(0,a.jsx)(e.admonition,{title:"source",type:"info",children:(0,a.jsxs)(e.p,{children:["You can find source code referenced in the text\n",(0,a.jsx)(e.a,{href:"pathname:///files/algorithms/recursion/pyramid-slide-down.tar.gz",children:"here"}),"."]})}),"\n",(0,a.jsxs)(e.section,{"data-footnotes":!0,className:"footnotes",children:[(0,a.jsx)(e.h2,{className:"sr-only",id:"footnote-label",children:"Footnotes"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{id:"user-content-fn-1",children:["\n",(0,a.jsxs)(e.p,{children:["cause why not, right!? ",(0,a.jsx)(e.a,{href:"#user-content-fnref-1","data-footnote-backref":"","aria-label":"Back to reference 1",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-2",children:["\n",(0,a.jsxs)(e.p,{children:["except the bottom row ",(0,a.jsx)(e.a,{href:"#user-content-fnref-2","data-footnote-backref":"","aria-label":"Back to reference 2",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-3",children:["\n",(0,a.jsxs)(e.p,{children:["definitely not an RHCP reference ","\ud83d\ude09 ",(0,a.jsx)(e.a,{href:"#user-content-fnref-3","data-footnote-backref":"","aria-label":"Back to reference 3",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-4",children:["\n",(0,a.jsxs)(e.p,{children:["one was not correct, thus the quotes ",(0,a.jsx)(e.a,{href:"#user-content-fnref-4","data-footnote-backref":"","aria-label":"Back to reference 4",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n"]}),"\n"]})]})}function o(s={}){const{wrapper:e}={...(0,i.a)(),...s.components};return e?(0,a.jsx)(e,{...s,children:(0,a.jsx)(h,{...s})}):h(s)}},11151:(s,e,n)=>{n.d(e,{Z:()=>r,a:()=>t});var a=n(67294);const i={},l=a.createContext(i);function t(s){const e=a.useContext(l);return a.useMemo((function(){return"function"==typeof s?s(e):{...e,...s}}),[e,s])}function r(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(i):s.components||i:t(s.components),a.createElement(l.Provider,{value:e},s.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[2619],{14457:(s,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>t,default:()=>o,frontMatter:()=>l,metadata:()=>r,toc:()=>m});var a=n(85893),i=n(11151);const l={id:"pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",tags:["java","recursion","exponential","greedy","dynamic-programming","top-down-dp","bottom-up-dp"],last_updated:{date:new Date("2023-08-17T00:00:00.000Z")}},t=void 0,r={id:"recursion/pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",source:"@site/algorithms/04-recursion/2023-08-17-pyramid-slide-down.md",sourceDirName:"04-recursion",slug:"/recursion/pyramid-slide-down",permalink:"/algorithms/recursion/pyramid-slide-down",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/algorithms/04-recursion/2023-08-17-pyramid-slide-down.md",tags:[{label:"java",permalink:"/algorithms/tags/java"},{label:"recursion",permalink:"/algorithms/tags/recursion"},{label:"exponential",permalink:"/algorithms/tags/exponential"},{label:"greedy",permalink:"/algorithms/tags/greedy"},{label:"dynamic-programming",permalink:"/algorithms/tags/dynamic-programming"},{label:"top-down-dp",permalink:"/algorithms/tags/top-down-dp"},{label:"bottom-up-dp",permalink:"/algorithms/tags/bottom-up-dp"}],version:"current",lastUpdatedAt:1701199517,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{id:"pyramid-slide-down",title:"Introduction to dynamic programming",description:"Solving a problem in different ways.\n",tags:["java","recursion","exponential","greedy","dynamic-programming","top-down-dp","bottom-up-dp"],last_updated:{date:"2023-08-17T00:00:00.000Z"}},sidebar:"autogeneratedBar",previous:{title:"Recursion and backtracking with Robot Karel",permalink:"/algorithms/recursion/karel-1"},next:{title:"Red-Black Trees",permalink:"/algorithms/category/red-black-trees"}},c={},m=[{value:"Problem",id:"problem",level:2},{value:"Solving the problem",id:"solving-the-problem",level:2},{value:"Na\xefve solution",id:"na\xefve-solution",level:2},{value:"Time complexity",id:"time-complexity",level:3},{value:"Greedy solution",id:"greedy-solution",level:2},{value:"Time complexity",id:"time-complexity-1",level:3},{value:"Running the tests",id:"running-the-tests",level:3},{value:"Top-down DP",id:"top-down-dp",level:2},{value:"Time complexity",id:"time-complexity-2",level:3},{value:"Memory complexity",id:"memory-complexity",level:3},{value:"Bottom-up DP",id:"bottom-up-dp",level:2},{value:"Time complexity",id:"time-complexity-3",level:3},{value:"Memory complexity",id:"memory-complexity-1",level:3},{value:"Summary",id:"summary",level:2}];function h(s){const e={a:"a",admonition:"admonition",annotation:"annotation",code:"code",em:"em",h2:"h2",h3:"h3",hr:"hr",li:"li",math:"math",mdxAdmonitionTitle:"mdxAdmonitionTitle",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",mspace:"mspace",mstyle:"mstyle",msub:"msub",msup:"msup",mtable:"mtable",mtd:"mtd",mtext:"mtext",mtr:"mtr",munderover:"munderover",ol:"ol",p:"p",pre:"pre",section:"section",semantics:"semantics",span:"span",strong:"strong",sup:"sup",...(0,i.a)(),...s.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(e.p,{children:"In this post we will try to solve one problem in different ways."}),"\n",(0,a.jsx)(e.h2,{id:"problem",children:"Problem"}),"\n",(0,a.jsxs)(e.p,{children:["The problem we are going to solve is one of ",(0,a.jsx)(e.em,{children:"CodeWars"})," katas and is called\n",(0,a.jsx)(e.a,{href:"https://www.codewars.com/kata/551f23362ff852e2ab000037",children:"Pyramid Slide Down"}),"."]}),"\n",(0,a.jsxs)(e.p,{children:["We are given a 2D array of integers and we are to find the ",(0,a.jsx)(e.em,{children:"slide down"}),".\n",(0,a.jsx)(e.em,{children:"Slide down"})," is a maximum sum of consecutive numbers from the top to the bottom."]}),"\n",(0,a.jsx)(e.p,{children:"Let's have a look at few examples. Consider the following pyramid:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 3\n 7 4\n 2 4 6\n8 5 9 3\n"})}),"\n",(0,a.jsx)(e.p,{children:"This pyramid has following slide down:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" *3\n *7 4\n 2 *4 6\n8 5 *9 3\n"})}),"\n",(0,a.jsxs)(e.p,{children:["And its value is ",(0,a.jsx)(e.code,{children:"23"}),"."]}),"\n",(0,a.jsxs)(e.p,{children:["We can also have a look at a ",(0,a.jsx)(e.em,{children:"bigger"})," example:"]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 75\n 95 64\n 17 47 82\n 18 35 87 10\n 20 4 82 47 65\n 19 1 23 3 34\n 88 2 77 73 7 63 67\n 99 65 4 28 6 16 70 92\n 41 41 26 56 83 40 80 70 33\n 41 48 72 33 47 32 37 16 94 29\n 53 71 44 65 25 43 91 52 97 51 14\n 70 11 33 28 77 73 17 78 39 68 17 57\n 91 71 52 38 17 14 91 43 58 50 27 29 48\n 63 66 4 68 89 53 67 30 73 16 69 87 40 31\n 4 62 98 27 23 9 70 98 73 93 38 53 60 4 23\n"})}),"\n",(0,a.jsxs)(e.p,{children:["Slide down in this case is equal to ",(0,a.jsx)(e.code,{children:"1074"}),"."]}),"\n",(0,a.jsx)(e.h2,{id:"solving-the-problem",children:"Solving the problem"}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["I will describe the following ways you can approach this problem and implement\nthem in ",(0,a.jsx)(e.em,{children:"Java"}),(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-1",id:"user-content-fnref-1","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"1"})}),"."]})}),"\n",(0,a.jsxs)(e.p,{children:["For all of the following solutions I will be using basic ",(0,a.jsx)(e.code,{children:"main"})," function that\nwill output ",(0,a.jsx)(e.code,{children:"true"}),"/",(0,a.jsx)(e.code,{children:"false"})," based on the expected output of our algorithm. Any\nother differences will lie only in the solutions of the problem. You can see the\n",(0,a.jsx)(e.code,{children:"main"})," here:"]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:'public static void main(String[] args) {\n System.out.print("Test #1: ");\n System.out.println(longestSlideDown(new int[][] {\n { 3 },\n { 7, 4 },\n { 2, 4, 6 },\n { 8, 5, 9, 3 }\n }) == 23 ? "passed" : "failed");\n\n System.out.print("Test #2: ");\n System.out.println(longestSlideDown(new int[][] {\n { 75 },\n { 95, 64 },\n { 17, 47, 82 },\n { 18, 35, 87, 10 },\n { 20, 4, 82, 47, 65 },\n { 19, 1, 23, 75, 3, 34 },\n { 88, 2, 77, 73, 7, 63, 67 },\n { 99, 65, 4, 28, 6, 16, 70, 92 },\n { 41, 41, 26, 56, 83, 40, 80, 70, 33 },\n { 41, 48, 72, 33, 47, 32, 37, 16, 94, 29 },\n { 53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14 },\n { 70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57 },\n { 91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48 },\n { 63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31 },\n { 4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23 },\n }) == 1074 ? "passed" : "failed");\n}\n'})}),"\n",(0,a.jsx)(e.h2,{id:"na\xefve-solution",children:"Na\xefve solution"}),"\n",(0,a.jsx)(e.p,{children:"Our na\xefve solution consists of trying out all the possible slides and finding\nthe one with maximum sum."}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: We have gotten out of bounds, there's no reasonable value to\n // return, so we just return the \u2039MIN_VALUE\u203a to ensure that it cannot\n // be maximum.\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: Bottom of the pyramid, we just return the value, there's\n // nowhere to slide anymore.\n return pyramid[row][col];\n }\n\n // Otherwise we account for the current position and return maximum of the\n // available \u201cslides\u201d.\n return pyramid[row][col] + Math.max(\n longestSlideDown(pyramid, row + 1, col),\n longestSlideDown(pyramid, row + 1, col + 1));\n}\n\npublic static int longestSlideDown(int[][] pyramid) {\n // We start the slide in the top cell of the pyramid.\n return longestSlideDown(pyramid, 0, 0);\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"As you can see, we have 2 overloads:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"int longestSlideDown(int[][] pyramid);\nint longestSlideDown(int[][] pyramid, int row, int col);\n"})}),"\n",(0,a.jsxs)(e.p,{children:["First one is used as a ",(0,a.jsx)(e.em,{children:"public interface"})," to the solution, you just pass in the\npyramid itself. Second one is the recursive \u201calgorithm\u201d that finds the slide\ndown."]}),"\n",(0,a.jsxs)(e.p,{children:["It is a relatively simple solution\u2026 There's nothing to do at the bottom of the\npyramid, so we just return the value in the ",(0,a.jsx)(e.em,{children:"cell"}),". Otherwise we add it and try\nto slide down the available cells below the current row."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"If you get the source code and run it yourself, it runs rather fine\u2026 I hope you\nare wondering about the time complexity of the proposed solution and, since it\nreally is a na\xefve solution, the time complexity is pretty bad. Let's find the\nworst case scenario."}),"\n",(0,a.jsx)(e.p,{children:"Let's start with the first overload:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid) {\n return longestSlideDown(pyramid, 0, 0);\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["There's not much to do here, so we can safely say that the time complexity of\nthis function is bounded by ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]}),", where ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"T"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"})]})})]})," is our second overload. This\ndoesn't tell us anything, so let's move on to the second overload where we are\ngoing to define the ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})," function."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: We have gotten out of bounds, there's no reasonable value to\n // return, so we just return the \u2039MIN_VALUE\u203a to ensure that it cannot\n // be maximum.\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: Bottom of the pyramid, we just return the value, there's\n // nowhere to slide anymore.\n return pyramid[row][col];\n }\n\n // Otherwise we account for the current position and return maximum of the\n // available \u201cslides\u201d.\n return pyramid[row][col] + Math.max(\n longestSlideDown(pyramid, row + 1, col),\n longestSlideDown(pyramid, row + 1, col + 1));\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["Fun fact is that the whole \u201calgorithm\u201d consists of just 2 ",(0,a.jsx)(e.code,{children:"return"})," statements\nand nothing else. Let's dissect them!"]}),"\n",(0,a.jsxs)(e.p,{children:["First ",(0,a.jsx)(e.code,{children:"return"})," statement is the base case, so it has a constant time complexity."]}),"\n",(0,a.jsxs)(e.p,{children:["Second one a bit tricky. We add two numbers together, which we'll consider as\nconstant, but for the right part of the expression we take maximum from the left\nand right paths. OK\u2026 So what happens? We evaluate the ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," while\nchoosing the under and right both. They are separate computations though, so we\nare branching from each call of ",(0,a.jsx)(e.code,{children:"longestSlideDown"}),", unless it's a base case."]}),"\n",(0,a.jsx)(e.p,{children:"What does that mean for us then? We basically get"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"{"}),(0,a.jsxs)(e.mtable,{rowspacing:"0.36em",columnalign:"left left",columnspacing:"1em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsx)(e.mn,{children:"1"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mtext,{children:",\xa0if\xa0"}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"1"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"1"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,a.jsx)(e.mtext,{children:",\xa0otherwise"})})})]})]})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(y) =\n\\begin{cases}\n1 & \\text{, if } y = rows \\\\\n1 + 2 \\cdot T(y + 1) & \\text{, otherwise}\n\\end{cases}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mclose",children:")"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:(0,a.jsx)(e.span,{className:"delimsizing size4",children:"{"})}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.69em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.69em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord",children:"1"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.25em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord",children:"1"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"1"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.19em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"arraycolsep",style:{width:"1em"}}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.69em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.69em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord text",children:(0,a.jsx)(e.span,{className:"mord",children:",\xa0if\xa0"})}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.25em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.008em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord text",children:(0,a.jsx)(e.span,{className:"mord",children:",\xa0otherwise"})})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.19em"},children:(0,a.jsx)(e.span,{})})})]})})]})}),(0,a.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"That looks rather easy to compute, isn't it? If you sum it up, you'll get:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"T"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mo,{children:"\u2208"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsxs)(e.msup,{children:[(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"})]})]}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"T(rows) \\in \\mathcal{O}(2^{rows})"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"T"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"\u2208"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsx)(e.span,{className:"vlist-t",children:(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.7144em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.113em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mathnormal mtight",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal mtight",children:"s"})]})})]})})})})})]}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"If you wonder why, I'll try to describe it intuitively:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["In each call to ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," we do some work in constant time,\nregardless of being in the base case. Those are the ",(0,a.jsx)(e.code,{children:"1"}),"s in both cases."]}),"\n",(0,a.jsxs)(e.li,{children:["If we are not in the base case, we move one row down ",(0,a.jsx)(e.strong,{children:"twice"}),". That's how we\nobtained ",(0,a.jsx)(e.code,{children:"2 *"})," and ",(0,a.jsx)(e.code,{children:"y + 1"})," in the ",(0,a.jsx)(e.em,{children:"otherwise"})," case."]}),"\n",(0,a.jsxs)(e.li,{children:["We move row-by-row, so we move down ",(0,a.jsx)(e.code,{children:"y"}),"-times and each call splits to two\nsubtrees."]}),"\n",(0,a.jsxs)(e.li,{children:["Overall, if we were to represent the calls as a tree, we would get a full\nbinary tree of height ",(0,a.jsx)(e.code,{children:"y"}),", in each node we do some work in constant time,\ntherefore we can just sum the ones."]}),"\n"]}),"\n",(0,a.jsx)(e.admonition,{type:"warning",children:(0,a.jsx)(e.p,{children:"It would've been more complicated to get an exact result. In the equation above\nwe are assuming that the width of the pyramid is bound by the height."})}),"\n",(0,a.jsxs)(e.p,{children:["Hopefully we can agree that this is not the best we can do. ","\ud83d\ude09"]}),"\n",(0,a.jsx)(e.h2,{id:"greedy-solution",children:"Greedy solution"}),"\n",(0,a.jsxs)(e.p,{children:["We will try to optimize it a bit. Let's start with a relatively simple ",(0,a.jsx)(e.em,{children:"greedy"}),"\napproach."]}),"\n",(0,a.jsx)(e.admonition,{title:"Greedy algorithms",type:"info",children:(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Greedy algorithms"})," can be described as algorithms that decide the action on the\noptimal option at the moment."]})}),"\n",(0,a.jsx)(e.p,{children:"We can try to adjust the na\xefve solution. The most problematic part are the\nrecursive calls. Let's apply the greedy approach there:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid, int row, int col) {\n if (row == pyramid.length - 1) {\n // BASE: We're at the bottom\n return pyramid[row][col];\n }\n\n if (col + 1 >= pyramid[row + 1].length\n || pyramid[row + 1][col] > pyramid[row + 1][col + 1]) {\n // If we cannot go right or it's not feasible, we continue to the left.\n return pyramid[row][col] + longestSlideDown(pyramid, row + 1, col);\n }\n\n // Otherwise we just move to the right.\n return pyramid[row][col] + longestSlideDown(pyramid, row + 1, col + 1);\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["OK, if we cannot go right ",(0,a.jsx)(e.strong,{children:"or"})," the right path adds smaller value to the sum,\nwe simply go left."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-1",children:"Time complexity"}),"\n",(0,a.jsxs)(e.p,{children:["We have switched from ",(0,a.jsx)(e.em,{children:"adding the maximum"})," to ",(0,a.jsx)(e.em,{children:"following the \u201cbigger\u201d path"}),", so\nwe improved the time complexity tremendously. We just go down the pyramid all\nthe way to the bottom. Therefore we are getting:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsx)(e.p,{children:"We have managed to convert our exponential solution into a linear one."}),"\n",(0,a.jsx)(e.h3,{id:"running-the-tests",children:"Running the tests"}),"\n",(0,a.jsx)(e.p,{children:"However, if we run the tests, we notice that the second test failed:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:"Test #1: passed\nTest #2: failed\n"})}),"\n",(0,a.jsxs)(e.p,{children:["What's going on? Well, we have improved the time complexity, but greedy\nalgorithms are not the ideal solution to ",(0,a.jsx)(e.strong,{children:"all"})," problems. In this case there\nmay be a solution that is bigger than the one found using the greedy algorithm."]}),"\n",(0,a.jsx)(e.p,{children:"Imagine the following pyramid:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{children:" 1\n 2 3\n 5 6 7\n 8 9 10 11\n99 13 14 15 16\n"})}),"\n",(0,a.jsx)(e.p,{children:"We start at the top:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"1"}),", we can choose from ",(0,a.jsx)(e.code,{children:"2"})," and ",(0,a.jsx)(e.code,{children:"3"}),", ",(0,a.jsx)(e.code,{children:"3"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"3"}),", we can choose from ",(0,a.jsx)(e.code,{children:"6"})," and ",(0,a.jsx)(e.code,{children:"7"}),", ",(0,a.jsx)(e.code,{children:"7"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"7"}),", we can choose from ",(0,a.jsx)(e.code,{children:"10"})," and ",(0,a.jsx)(e.code,{children:"11"}),", ",(0,a.jsx)(e.code,{children:"11"})," looks better, so we\nchoose it."]}),"\n",(0,a.jsxs)(e.li,{children:["Current cell: ",(0,a.jsx)(e.code,{children:"11"}),", we can choose from ",(0,a.jsx)(e.code,{children:"15"})," and ",(0,a.jsx)(e.code,{children:"16"}),", ",(0,a.jsx)(e.code,{children:"16"})," looks better, so\nwe choose it."]}),"\n"]}),"\n",(0,a.jsxs)(e.p,{children:["Our final sum is: ",(0,a.jsx)(e.code,{children:"1 + 3 + 7 + 11 + 16 = 38"}),", but in the bottom left cell we\nhave a ",(0,a.jsx)(e.code,{children:"99"})," that is bigger than our whole sum."]}),"\n",(0,a.jsx)(e.admonition,{type:"tip",children:(0,a.jsx)(e.p,{children:"Dijkstra's algorithm is a greedy algorithm too, try to think why it is correct."})}),"\n",(0,a.jsx)(e.h2,{id:"top-down-dp",children:"Top-down DP"}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Top-down dynamic programming"})," is probably the most common approach, since (at\nleast looks like) is the easiest to implement. The whole point is avoiding the\nunnecessary computations that we have already done."]}),"\n",(0,a.jsxs)(e.p,{children:["In our case, we can use our na\xefve solution and put a ",(0,a.jsx)(e.em,{children:"cache"})," on top of it that\nwill make sure, we don't do unnecessary calculations."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"// This \u201cstructure\u201d is required, since I have decided to use \u2039TreeMap\u203a which\n// requires the ordering on the keys. It represents one position in the pyramid.\nrecord Position(int row, int col) implements Comparable {\n public int compareTo(Position r) {\n if (row != r.row) {\n return Integer.valueOf(row).compareTo(r.row);\n }\n\n if (col != r.col) {\n return Integer.valueOf(col).compareTo(r.col);\n }\n\n return 0;\n }\n}\n\npublic static int longestSlideDown(\n int[][] pyramid,\n TreeMap cache,\n Position position) {\n int row = position.row;\n int col = position.col;\n\n if (row >= pyramid.length || col < 0 || col >= pyramid[row].length) {\n // BASE: out of bounds\n return Integer.MIN_VALUE;\n }\n\n if (row == pyramid.length - 1) {\n // BASE: bottom of the pyramid\n return pyramid[position.row][position.col];\n }\n\n if (!cache.containsKey(position)) {\n // We haven't computed the position yet, so we run the same \u201cformula\u201d as\n // in the na\xefve version \xbband\xab we put calculated slide into the cache.\n // Next time we want the slide down from given position, it will be just\n // retrieved from the cache.\n int slideDown = Math.max(\n longestSlideDown(pyramid, cache, new Position(row + 1, col)),\n longestSlideDown(pyramid, cache, new Position(row + 1, col + 1)));\n cache.put(position, pyramid[row][col] + slideDown);\n }\n\n return cache.get(position);\n}\n\npublic static int longestSlideDown(int[][] pyramid) {\n // At the beginning we need to create a cache and share it across the calls.\n TreeMap cache = new TreeMap<>();\n return longestSlideDown(pyramid, cache, new Position(0, 0));\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["You have probably noticed that ",(0,a.jsx)(e.code,{children:"record Position"})," have appeared. Since we are\ncaching the already computed values, we need a \u201creasonable\u201d key. In this case we\nshare the cache only for one ",(0,a.jsx)(e.em,{children:"run"})," (i.e. pyramid) of the ",(0,a.jsx)(e.code,{children:"longestSlideDown"}),", so\nwe can cache just with the indices within the pyramid, i.e. the ",(0,a.jsx)(e.code,{children:"Position"}),"."]}),"\n",(0,a.jsx)(e.admonition,{title:"Record",type:"tip",children:(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.em,{children:"Record"})," is relatively new addition to the Java language. It is basically an\nimmutable structure with implicitly defined ",(0,a.jsx)(e.code,{children:".equals()"}),", ",(0,a.jsx)(e.code,{children:".hashCode()"}),",\n",(0,a.jsx)(e.code,{children:".toString()"})," and getters for the attributes."]})}),"\n",(0,a.jsxs)(e.p,{children:["Because of the choice of ",(0,a.jsx)(e.code,{children:"TreeMap"}),", we had to additionally define the ordering\non it."]}),"\n",(0,a.jsxs)(e.p,{children:["In the ",(0,a.jsx)(e.code,{children:"longestSlideDown"})," you can notice that the computation which used to be\nat the end of the na\xefve version above, is now wrapped in an ",(0,a.jsx)(e.code,{children:"if"})," statement that\nchecks for the presence of the position in the cache and computes the slide down\njust when it's needed."]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-2",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"If you think that evaluating time complexity for this approach is a bit more\ntricky, you are right. Keeping the cache in mind, it is not the easiest thing\nto do. However there are some observations that might help us figure this out:"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsx)(e.li,{children:"Slide down from each position is calculated only once."}),"\n",(0,a.jsx)(e.li,{children:"Once calculated, we use the result from the cache."}),"\n"]}),"\n",(0,a.jsxs)(e.p,{children:["Knowing this, we still cannot, at least easily, describe the time complexity of\nfinding the best slide down from a specific position, ",(0,a.jsx)(e.strong,{children:"but"})," we can bound it\nfrom above for the ",(0,a.jsx)(e.strong,{children:"whole"})," run from the top. Now the question is how we can do\nthat!"]}),"\n",(0,a.jsxs)(e.p,{children:["Overall we are doing the same things for almost",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-2",id:"user-content-fnref-2","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"2"})})," all of the positions within\nthe pyramid:"]}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{children:["\n",(0,a.jsx)(e.p,{children:"We calculate and store it (using the partial results stored in cache). This\nis done only once."}),"\n",(0,a.jsxs)(e.p,{children:["For each calculation we take 2 values from the cache and insert one value.\nBecause we have chosen ",(0,a.jsx)(e.code,{children:"TreeMap"}),", these 3 operations have logarithmic time\ncomplexity and therefore this step is equivalent to ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"3"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"3 \\cdot \\log_2{n}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"3"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),"."]}),"\n",(0,a.jsx)(e.p,{children:"However for the sake of simplicity, we are going to account only for the\ninsertion, the reason is rather simple, if we include the 2 retrievals here,\nit will be interleaved with the next step, therefore it is easier to keep the\nretrievals in the following point."}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsx)(e.p,{children:"You might have noticed it's still not that easy, cause we're not having full\ncache right from the beginning, but the sum of those logarithms cannot be\nexpressed in a nice way, so taking the upper bound, i.e. expecting the cache\nto be full at all times, is the best option for nice and readable complexity\nof the whole approach."})}),"\n",(0,a.jsxs)(e.p,{children:["Our final upper bound of this work is therefore ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\log_2{n}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})})]}),"."]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{children:["\n",(0,a.jsxs)(e.p,{children:["We retrieve it from the cache. Same as in first point, but only twice, so we\nget ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.msub,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"})]}),(0,a.jsx)(e.mn,{children:"2"})]}),(0,a.jsx)(e.mi,{children:"n"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"2 \\cdot \\log_2{n}"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.9386em",verticalAlign:"-0.2441em"}}),(0,a.jsxs)(e.span,{className:"mop",children:[(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"msupsub",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.207em"},children:(0,a.jsxs)(e.span,{style:{top:"-2.4559em",marginRight:"0.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.2441em"},children:(0,a.jsx)(e.span,{})})})]})})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),"."]}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["It's done twice because of the ",(0,a.jsx)(e.code,{children:".containsKey()"})," in the ",(0,a.jsx)(e.code,{children:"if"})," condition."]})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(e.p,{children:"Okay, we have evaluated work done for each of the cells in the pyramid and now\nwe need to put it together."}),"\n",(0,a.jsx)(e.p,{children:"Let's split the time complexity of our solution into two operands:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(r + s)"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"r"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"r"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})]})})]})," will represent the ",(0,a.jsx)(e.em,{children:"actual"})," calculation of the cells and ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"s"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"s"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})})]})," will represent\nthe additional retrievals on top of the calculation."]}),"\n",(0,a.jsxs)(e.p,{children:["We calculate the values only ",(0,a.jsx)(e.strong,{children:"once"}),", therefore we can safely agree on:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"r"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\nr &= n \\cdot \\log{n} \\\\\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1.5em",verticalAlign:"-0.5em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"1em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.16em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.5em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsx)(e.span,{className:"vlist",style:{height:"1em"},children:(0,a.jsxs)(e.span,{style:{top:"-3.16em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"0.5em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,a.jsxs)(e.p,{children:["What about the ",(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"s"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"s"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})})]})," though? Key observation here is the fact that we have 2\nlookups on the tree in each of them ",(0,a.jsx)(e.strong,{children:"and"})," we do it twice, cause each cell has\nat most 2 parents:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"("}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{fence:"true",children:")"})]})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"4"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\ns &= n \\cdot 2 \\cdot \\left( 2 \\cdot \\log{n} \\right) \\\\\ns &= 4 \\cdot n \\cdot \\log{n}\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:"("}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose delimcenter",style:{top:"0em"},children:")"})]})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"4"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsxs)(e.p,{children:["You might've noticed that lookups actually take more time than the construction\nof the results. This is not entirely true, since we have included the\n",(0,a.jsx)(e.code,{children:".containsKey()"})," and ",(0,a.jsx)(e.code,{children:".get()"})," from the ",(0,a.jsx)(e.code,{children:"return"})," statement in the second part."]}),(0,a.jsx)(e.p,{children:"If we were to represent this more precisely, we could've gone with:"}),(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:[(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"r"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"3"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]}),(0,a.jsxs)(e.mtr,{children:[(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsx)(e.mi,{children:"s"})})}),(0,a.jsx)(e.mtd,{children:(0,a.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mrow,{}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"})]})})})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\nr &= 3 \\cdot n \\cdot \\log{n} \\\\\ns &= 2 \\cdot n \\cdot \\log{n}\n\\end{align*}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3em",verticalAlign:"-1.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsxs)(e.span,{className:"mtable",children:[(0,a.jsx)(e.span,{className:"col-align-r",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"col-align-l",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.75em"},children:[(0,a.jsxs)(e.span,{style:{top:"-3.91em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"3"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]}),(0,a.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsxs)(e.span,{className:"mord",children:[(0,a.jsx)(e.span,{className:"mord"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mrel",children:"="}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})})]})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.25em"},children:(0,a.jsx)(e.span,{})})})]})})]})})]})})]})}),(0,a.jsx)(e.p,{children:"On the other hand we are summing both numbers together, therefore in the end it\ndoesn't really matter."}),(0,a.jsxs)(e.p,{children:["(",(0,a.jsx)(e.em,{children:"Feel free to compare the sums of both \u201csplits\u201d."}),")"]})]}),"\n",(0,a.jsxs)(e.p,{children:["And so our final time complexity for the whole ",(0,a.jsx)(e.em,{children:"top-down dynamic programming"}),"\napproach is:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"4"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mn,{children:"5"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"}),(0,a.jsx)(e.mspace,{linebreak:"newline"}),(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{children:"\u22c5"}),(0,a.jsx)(e.mi,{children:"log"}),(0,a.jsx)(e.mo,{children:"\u2061"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(r + s) \\\\\n\\mathcal{O}(n \\cdot \\log{n} + 4 \\cdot n \\cdot \\log{n}) \\\\\n\\mathcal{O}(5 \\cdot n \\cdot \\log{n}) \\\\\n\\mathcal{O}(n \\cdot \\log{n})"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(e.span,{className:"mord",children:"4"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4445em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord",children:"5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4445em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]}),(0,a.jsx)(e.span,{className:"mspace newline"}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(e.span,{className:"mop",children:["lo",(0,a.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsxs)(e.p,{children:["As you can see, this is worse than our ",(0,a.jsx)(e.em,{children:"greedy"})," solution that was incorrect, but\nit's better than the ",(0,a.jsx)(e.em,{children:"na\xefve"})," one."]}),"\n",(0,a.jsx)(e.h3,{id:"memory-complexity",children:"Memory complexity"}),"\n",(0,a.jsxs)(e.p,{children:["With this approach we need to talk about the memory complexity too, because we\nhave introduced cache. If you think that the memory complexity is linear to the\ninput, you are right. We start at the top and try to find each and every slide\ndown. At the end we get the final result for ",(0,a.jsx)(e.code,{children:"new Position(0, 0)"}),", so we need to\ncompute everything below."]}),"\n",(0,a.jsx)(e.p,{children:"That's how we obtain:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsx)(e.mrow,{children:(0,a.jsx)(e.mi,{children:"n"})}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"n"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"})]})})]})," represents the total amount of cells in the pyramid, i.e."]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.munderover,{children:[(0,a.jsx)(e.mo,{children:"\u2211"}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{children:"="}),(0,a.jsx)(e.mn,{children:"0"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"p"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"y"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"r"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"a"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"m"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"i"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"d"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"."}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"l"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"e"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"n"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"g"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"t"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"h"})]}),(0,a.jsx)(e.mo,{children:"\u2212"}),(0,a.jsx)(e.mn,{children:"1"})]})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"p"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"y"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"r"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"a"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"m"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"i"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"d"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mo,{fence:"true",children:"["}),(0,a.jsx)(e.mi,{children:"y"}),(0,a.jsx)(e.mo,{fence:"true",children:"]"})]}),(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"."}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"l"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"e"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"n"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"g"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"t"}),(0,a.jsx)(e.mi,{mathvariant:"monospace",children:"h"})]})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\sum_{y=0}^{\\mathtt{pyramid.length} - 1} \\mathtt{pyramid}\\left[y\\right]\\mathtt{.length}"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"3.2709em",verticalAlign:"-1.4032em"}}),(0,a.jsx)(e.span,{className:"mop op-limits",children:(0,a.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(e.span,{className:"vlist-r",children:[(0,a.jsxs)(e.span,{className:"vlist",style:{height:"1.8677em"},children:[(0,a.jsxs)(e.span,{style:{top:"-1.8829em",marginLeft:"0em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,a.jsx)(e.span,{className:"mord mtight",children:"0"})]})})]}),(0,a.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{children:(0,a.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,a.jsxs)(e.span,{style:{top:"-4.3666em",marginLeft:"0em"},children:[(0,a.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,a.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(e.span,{className:"mord mtight",children:[(0,a.jsx)(e.span,{className:"mord mtight",children:(0,a.jsx)(e.span,{className:"mord mathtt mtight",children:"pyramid.length"})}),(0,a.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,a.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]})]}),(0,a.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,a.jsx)(e.span,{className:"vlist-r",children:(0,a.jsx)(e.span,{className:"vlist",style:{height:"1.4032em"},children:(0,a.jsx)(e.span,{})})})]})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathtt",children:"pyramid"})}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsxs)(e.span,{className:"minner",children:[(0,a.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:"["}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"y"}),(0,a.jsx)(e.span,{className:"mclose delimcenter",style:{top:"0em"},children:"]"})]}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,a.jsx)(e.span,{className:"mord",children:(0,a.jsx)(e.span,{className:"mord mathtt",children:".length"})})]})})]})}),"\n",(0,a.jsx)(e.admonition,{type:"caution",children:(0,a.jsxs)(e.p,{children:["If you're wondering whether it's correct because of the second ",(0,a.jsx)(e.code,{children:"if"})," in our\nfunction, your guess is right. However we are expressing the complexity in the\nBachmann-Landau notation, so we care about the ",(0,a.jsx)(e.strong,{children:"upper bound"}),", not the exact\nnumber."]})}),"\n",(0,a.jsxs)(e.admonition,{title:"Can this be optimized?",type:"tip",children:[(0,a.jsx)(e.p,{children:"Yes, it can! Try to think about a way, how can you minimize the memory\ncomplexity of this approach. I'll give you a hint:"}),(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})})]}),"\n",(0,a.jsx)(e.h2,{id:"bottom-up-dp",children:"Bottom-up DP"}),"\n",(0,a.jsxs)(e.p,{children:["If you try to think in depth about the top-down DP solution, you might notice\nthat the ",(0,a.jsx)(e.em,{children:"core"})," of it stands on caching the calculations that have been already\ndone on the lower \u201clevels\u201d of the pyramid. Our bottom-up implementation will be\nusing this fact!"]}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsxs)(e.p,{children:["As I have said in the ",(0,a.jsx)(e.em,{children:"top-down DP"})," section, it is the easiest way to implement\nDP (unless the cached function has complicated parameters, in that case it might\nget messy)."]}),(0,a.jsx)(e.p,{children:"Bottom-up dynamic programming can be more effective, but may be more complicated\nto implement right from the beginning."})]}),"\n",(0,a.jsx)(e.p,{children:"Let's see how we can implement it:"}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-java",children:"public static int longestSlideDown(int[][] pyramid) {\n // In the beginning we declare new array. At this point it is easier to just\n // work with the one dimension, i.e. just allocating the space for the rows.\n int[][] slideDowns = new int[pyramid.length][];\n\n // Bottom row gets just copied, there's nothing else to do\u2026 It's the base\n // case.\n slideDowns[pyramid.length - 1] = Arrays.copyOf(pyramid[pyramid.length - 1],\n pyramid[pyramid.length - 1].length);\n\n // Then we need to propagate the found slide downs for each of the levels\n // above.\n for (int y = pyramid.length - 2; y >= 0; --y) {\n // We start by copying the values lying in the row we're processing.\n // They get included in the final sum and we need to allocate the space\n // for the precalculated slide downs anyways.\n int[] row = Arrays.copyOf(pyramid[y], pyramid[y].length);\n\n // At this we just need to \u201cfetch\u201d the partial results from \u201cneighbours\u201d\n for (int x = 0; x < row.length; ++x) {\n // We look under our position, since we expect the rows to get\n // shorter, we can safely assume such position exists.\n int under = slideDowns[y + 1][x];\n\n // Then we have a look to the right, such position doesn't have to\n // exist, e.g. on the right edge, so we validate the index, and if\n // it doesn't exist, we just assign minimum of the \u2039int\u203a which makes\n // sure that it doesn't get picked in the \u2039Math.max()\u203a call.\n int toRight = x + 1 < slideDowns[y + 1].length\n ? slideDowns[y + 1][x + 1]\n : Integer.MIN_VALUE;\n\n // Finally we add the best choice at this point.\n row[x] += Math.max(under, toRight);\n }\n\n // And save the row we've just calculated partial results for to the\n // \u201ctable\u201d.\n slideDowns[y] = row;\n }\n\n // At the end we can find our seeked slide down at the top cell.\n return slideDowns[0][0];\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"I've tried to explain the code as much as possible within the comments, since it\nmight be more beneficial to see right next to the \u201coffending\u201d lines."}),"\n",(0,a.jsxs)(e.p,{children:["As you can see, in this approach we go from the other side",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-3",id:"user-content-fnref-3","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"3"})}),", the bottom of\nthe pyramid and propagate the partial results up."]}),"\n",(0,a.jsxs)(e.admonition,{type:"info",children:[(0,a.jsxs)(e.mdxAdmonitionTitle,{children:["How is this different from the ",(0,a.jsx)(e.em,{children:"greedy"})," solution???"]}),(0,a.jsxs)(e.p,{children:["If you try to compare them, you might find a very noticable difference. The\ngreedy approach is going from the top to the bottom without ",(0,a.jsx)(e.strong,{children:"any"})," knowledge of\nwhat's going on below. On the other hand, bottom-up DP is going from the bottom\n(",(0,a.jsx)(e.em,{children:"DUH\u2026"}),") and ",(0,a.jsx)(e.strong,{children:"propagates"})," the partial results to the top. The propagation is\nwhat makes sure that at the top I don't choose the best ",(0,a.jsx)(e.strong,{children:"local"})," choice, but\nthe best ",(0,a.jsx)(e.strong,{children:"overall"})," result I can achieve."]})]}),"\n",(0,a.jsx)(e.h3,{id:"time-complexity-3",children:"Time complexity"}),"\n",(0,a.jsx)(e.p,{children:"Time complexity of this solution is rather simple. We allocate an array for the\nrows and then for each row, we copy it and adjust the partial results. Doing\nthis we get:"}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"r"}),(0,a.jsx)(e.mi,{children:"o"}),(0,a.jsx)(e.mi,{children:"w"}),(0,a.jsx)(e.mi,{children:"s"}),(0,a.jsx)(e.mo,{children:"+"}),(0,a.jsx)(e.mn,{children:"2"}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(rows + 2n)"})]})})}),(0,a.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"ro"}),(0,a.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(e.span,{className:"mbin",children:"+"}),(0,a.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord",children:"2"}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})]})]})}),"\n",(0,a.jsx)(e.p,{children:"Of course, this is an upper bound, since we iterate through the bottom row only\nonce."}),"\n",(0,a.jsx)(e.h3,{id:"memory-complexity-1",children:"Memory complexity"}),"\n",(0,a.jsxs)(e.p,{children:["We're allocating an array for the pyramid ",(0,a.jsx)(e.strong,{children:"again"})," for our partial results, so\nwe get:"]}),"\n",(0,a.jsx)(e.span,{className:"katex-display",children:(0,a.jsxs)(e.span,{className:"katex",children:[(0,a.jsx)(e.span,{className:"katex-mathml",children:(0,a.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,a.jsxs)(e.semantics,{children:[(0,a.jsxs)(e.mrow,{children:[(0,a.jsx)(e.mi,{mathvariant:"script",children:"O"}),(0,a.jsx)(e.mo,{stretchy:"false",children:"("}),(0,a.jsx)(e.mi,{children:"n"}),(0,a.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{O}(n)"})]})})}),(0,a.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(e.span,{className:"base",children:[(0,a.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.02778em"},children:"O"}),(0,a.jsx)(e.span,{className:"mopen",children:"("}),(0,a.jsx)(e.span,{className:"mord mathnormal",children:"n"}),(0,a.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),"\n",(0,a.jsxs)(e.admonition,{type:"tip",children:[(0,a.jsx)(e.p,{children:"If we were writing this in C++ or Rust, we could've avoided that, but not\nreally."}),(0,a.jsxs)(e.p,{children:["C++ would allow us to ",(0,a.jsx)(e.strong,{children:"copy"})," the pyramid rightaway into the parameter, so we\nwould be able to directly change it. However it's still a copy, even though we\ndon't need to allocate anything ourselves. It's just implicitly done for us."]}),(0,a.jsxs)(e.p,{children:["Rust is more funny in this case. If the pyramids weren't used after the call of\n",(0,a.jsx)(e.code,{children:"longest_slide_down"}),", it would simply ",(0,a.jsx)(e.strong,{children:"move"})," them into the functions. If they\nwere used afterwards, the compiler would force you to either borrow it, or\n",(0,a.jsx)(e.em,{children:"clone-and-move"})," for the function."]}),(0,a.jsx)(e.hr,{}),(0,a.jsxs)(e.p,{children:["Since we're doing it in Java, we get a reference to the ",(0,a.jsx)(e.em,{children:"original"})," array and we\ncan't do whatever we want with it."]})]}),"\n",(0,a.jsx)(e.h2,{id:"summary",children:"Summary"}),"\n",(0,a.jsxs)(e.p,{children:["And we've finally reached the end. We have seen 4 different \u201csolutions\u201d",(0,a.jsx)(e.sup,{children:(0,a.jsx)(e.a,{href:"#user-content-fn-4",id:"user-content-fnref-4","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"4"})})," of\nthe same problem using different approaches. Different approaches follow the\norder in which you might come up with them, each approach influences its\nsuccessor and represents the way we can enhance the existing implementation."]}),"\n",(0,a.jsx)(e.hr,{}),"\n",(0,a.jsx)(e.admonition,{title:"source",type:"info",children:(0,a.jsxs)(e.p,{children:["You can find source code referenced in the text\n",(0,a.jsx)(e.a,{href:"pathname:///files/algorithms/recursion/pyramid-slide-down.tar.gz",children:"here"}),"."]})}),"\n",(0,a.jsxs)(e.section,{"data-footnotes":!0,className:"footnotes",children:[(0,a.jsx)(e.h2,{className:"sr-only",id:"footnote-label",children:"Footnotes"}),"\n",(0,a.jsxs)(e.ol,{children:["\n",(0,a.jsxs)(e.li,{id:"user-content-fn-1",children:["\n",(0,a.jsxs)(e.p,{children:["cause why not, right!? ",(0,a.jsx)(e.a,{href:"#user-content-fnref-1","data-footnote-backref":"","aria-label":"Back to reference 1",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-2",children:["\n",(0,a.jsxs)(e.p,{children:["except the bottom row ",(0,a.jsx)(e.a,{href:"#user-content-fnref-2","data-footnote-backref":"","aria-label":"Back to reference 2",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-3",children:["\n",(0,a.jsxs)(e.p,{children:["definitely not an RHCP reference ","\ud83d\ude09 ",(0,a.jsx)(e.a,{href:"#user-content-fnref-3","data-footnote-backref":"","aria-label":"Back to reference 3",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n",(0,a.jsxs)(e.li,{id:"user-content-fn-4",children:["\n",(0,a.jsxs)(e.p,{children:["one was not correct, thus the quotes ",(0,a.jsx)(e.a,{href:"#user-content-fnref-4","data-footnote-backref":"","aria-label":"Back to reference 4",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n"]}),"\n"]})]})}function o(s={}){const{wrapper:e}={...(0,i.a)(),...s.components};return e?(0,a.jsx)(e,{...s,children:(0,a.jsx)(h,{...s})}):h(s)}},11151:(s,e,n)=>{n.d(e,{Z:()=>r,a:()=>t});var a=n(67294);const i={},l=a.createContext(i);function t(s){const e=a.useContext(l);return a.useMemo((function(){return"function"==typeof s?s(e):{...e,...s}}),[e,s])}function r(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(i):s.components||i:t(s.components),a.createElement(l.Provider,{value:e},s.children)}}}]); \ No newline at end of file diff --git a/assets/js/7052c0bc.beae1b38.js b/assets/js/7052c0bc.7402024f.js similarity index 95% rename from assets/js/7052c0bc.beae1b38.js rename to assets/js/7052c0bc.7402024f.js index 7d7cab7..0e18860 100644 --- a/assets/js/7052c0bc.beae1b38.js +++ b/assets/js/7052c0bc.7402024f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[9731],{42286:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>a,contentTitle:()=>c,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var o=n(85893),r=n(11151);const i={id:"cpp-intro",title:"Introduction",slug:"/"},c=void 0,s={id:"cpp-intro",title:"Introduction",description:"",source:"@site/cpp/00-intro.md",sourceDirName:".",slug:"/",permalink:"/cpp/",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/cpp/00-intro.md",tags:[],version:"current",lastUpdatedAt:1701196739,formattedLastUpdatedAt:"Nov 28, 2023",sidebarPosition:0,frontMatter:{id:"cpp-intro",title:"Introduction",slug:"/"},sidebar:"autogeneratedBar",next:{title:"Exceptions and RAII",permalink:"/cpp/category/exceptions-and-raii"}},a={},p=[];function u(t){return(0,o.jsx)(o.Fragment,{})}function d(t={}){const{wrapper:e}={...(0,r.a)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(u,{...t})}):u()}},11151:(t,e,n)=>{n.d(e,{Z:()=>s,a:()=>c});var o=n(67294);const r={},i=o.createContext(r);function c(t){const e=o.useContext(i);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:c(t.components),o.createElement(i.Provider,{value:e},t.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[9731],{42286:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>a,contentTitle:()=>c,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var o=n(85893),r=n(11151);const i={id:"cpp-intro",title:"Introduction",slug:"/"},c=void 0,s={id:"cpp-intro",title:"Introduction",description:"",source:"@site/cpp/00-intro.md",sourceDirName:".",slug:"/",permalink:"/cpp/",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/cpp/00-intro.md",tags:[],version:"current",lastUpdatedAt:1701199517,formattedLastUpdatedAt:"Nov 28, 2023",sidebarPosition:0,frontMatter:{id:"cpp-intro",title:"Introduction",slug:"/"},sidebar:"autogeneratedBar",next:{title:"Exceptions and RAII",permalink:"/cpp/category/exceptions-and-raii"}},a={},p=[];function u(t){return(0,o.jsx)(o.Fragment,{})}function d(t={}){const{wrapper:e}={...(0,r.a)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(u,{...t})}):u()}},11151:(t,e,n)=>{n.d(e,{Z:()=>s,a:()=>c});var o=n(67294);const r={},i=o.createContext(r);function c(t){const e=o.useContext(i);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:c(t.components),o.createElement(i.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/794ef108.ed8ed4b7.js b/assets/js/794ef108.166aea3d.js similarity index 95% rename from assets/js/794ef108.ed8ed4b7.js rename to assets/js/794ef108.166aea3d.js index 613e4d6..de581e2 100644 --- a/assets/js/794ef108.ed8ed4b7.js +++ b/assets/js/794ef108.166aea3d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[3803],{86427:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>a,contentTitle:()=>s,default:()=>l,frontMatter:()=>i,metadata:()=>c,toc:()=>u});var o=n(85893),r=n(11151);const i={id:"c-intro",title:"Introduction",slug:"/"},s=void 0,c={id:"c-intro",title:"Introduction",description:"",source:"@site/c/00-intro.md",sourceDirName:".",slug:"/",permalink:"/c/",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/00-intro.md",tags:[],version:"current",lastUpdatedAt:1701196739,formattedLastUpdatedAt:"Nov 28, 2023",sidebarPosition:0,frontMatter:{id:"c-intro",title:"Introduction",slug:"/"},sidebar:"autogeneratedBar",next:{title:"Bonuses",permalink:"/c/category/bonuses"}},a={},u=[];function d(t){return(0,o.jsx)(o.Fragment,{})}function l(t={}){const{wrapper:e}={...(0,r.a)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(d,{...t})}):d()}},11151:(t,e,n)=>{n.d(e,{Z:()=>c,a:()=>s});var o=n(67294);const r={},i=o.createContext(r);function s(t){const e=o.useContext(i);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function c(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:s(t.components),o.createElement(i.Provider,{value:e},t.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[3803],{86427:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>a,contentTitle:()=>s,default:()=>l,frontMatter:()=>i,metadata:()=>c,toc:()=>u});var o=n(85893),r=n(11151);const i={id:"c-intro",title:"Introduction",slug:"/"},s=void 0,c={id:"c-intro",title:"Introduction",description:"",source:"@site/c/00-intro.md",sourceDirName:".",slug:"/",permalink:"/c/",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/00-intro.md",tags:[],version:"current",lastUpdatedAt:1701199517,formattedLastUpdatedAt:"Nov 28, 2023",sidebarPosition:0,frontMatter:{id:"c-intro",title:"Introduction",slug:"/"},sidebar:"autogeneratedBar",next:{title:"Bonuses",permalink:"/c/category/bonuses"}},a={},u=[];function d(t){return(0,o.jsx)(o.Fragment,{})}function l(t={}){const{wrapper:e}={...(0,r.a)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(d,{...t})}):d()}},11151:(t,e,n)=>{n.d(e,{Z:()=>c,a:()=>s});var o=n(67294);const r={},i=o.createContext(r);function s(t){const e=o.useContext(i);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function c(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:s(t.components),o.createElement(i.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/84d1e0d8.2391d00c.js b/assets/js/84d1e0d8.7240ea58.js similarity index 97% rename from assets/js/84d1e0d8.2391d00c.js rename to assets/js/84d1e0d8.7240ea58.js index 952c41f..d064654 100644 --- a/assets/js/84d1e0d8.2391d00c.js +++ b/assets/js/84d1e0d8.7240ea58.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[1885],{49713:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var o=n(85893),s=n(11151);const r={id:"algorithms-intro",title:"Introduction",slug:"/"},i=void 0,a={id:"algorithms-intro",title:"Introduction",description:"In this part you can find \u201crandom\u201d additional materials I have written over the",source:"@site/algorithms/00-intro.md",sourceDirName:".",slug:"/",permalink:"/algorithms/",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/algorithms/00-intro.md",tags:[],version:"current",lastUpdatedAt:1701196739,formattedLastUpdatedAt:"Nov 28, 2023",sidebarPosition:0,frontMatter:{id:"algorithms-intro",title:"Introduction",slug:"/"},sidebar:"autogeneratedBar",next:{title:"Algorithms and Correctness",permalink:"/algorithms/category/algorithms-and-correctness"}},c={},d=[];function l(t){const e={a:"a",em:"em",p:"p",...(0,s.a)(),...t.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(e.p,{children:["In this part you can find \u201crandom\u201d additional materials I have written over the\ncourse of teaching ",(0,o.jsx)(e.em,{children:"Algorithms and data structures I"}),"."]}),"\n",(0,o.jsx)(e.p,{children:"It is a various mix of stuff that may have been produced as a follow-up on some\nquestion asked at the seminar or spontanously."}),"\n",(0,o.jsxs)(e.p,{children:["If you have some ideas for posts, please do not hesitate to submit them as issues\nin the linked ",(0,o.jsx)(e.a,{href:"https://gitlab.fi.muni.cz/xfocko/kb/issues",children:"GitLab"}),"."]})]})}function u(t={}){const{wrapper:e}={...(0,s.a)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(l,{...t})}):l(t)}},11151:(t,e,n)=>{n.d(e,{Z:()=>a,a:()=>i});var o=n(67294);const s={},r=o.createContext(s);function i(t){const e=o.useContext(r);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(s):t.components||s:i(t.components),o.createElement(r.Provider,{value:e},t.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[1885],{49713:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var o=n(85893),s=n(11151);const r={id:"algorithms-intro",title:"Introduction",slug:"/"},i=void 0,a={id:"algorithms-intro",title:"Introduction",description:"In this part you can find \u201crandom\u201d additional materials I have written over the",source:"@site/algorithms/00-intro.md",sourceDirName:".",slug:"/",permalink:"/algorithms/",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/algorithms/00-intro.md",tags:[],version:"current",lastUpdatedAt:1701199517,formattedLastUpdatedAt:"Nov 28, 2023",sidebarPosition:0,frontMatter:{id:"algorithms-intro",title:"Introduction",slug:"/"},sidebar:"autogeneratedBar",next:{title:"Algorithms and Correctness",permalink:"/algorithms/category/algorithms-and-correctness"}},c={},d=[];function l(t){const e={a:"a",em:"em",p:"p",...(0,s.a)(),...t.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(e.p,{children:["In this part you can find \u201crandom\u201d additional materials I have written over the\ncourse of teaching ",(0,o.jsx)(e.em,{children:"Algorithms and data structures I"}),"."]}),"\n",(0,o.jsx)(e.p,{children:"It is a various mix of stuff that may have been produced as a follow-up on some\nquestion asked at the seminar or spontanously."}),"\n",(0,o.jsxs)(e.p,{children:["If you have some ideas for posts, please do not hesitate to submit them as issues\nin the linked ",(0,o.jsx)(e.a,{href:"https://gitlab.fi.muni.cz/xfocko/kb/issues",children:"GitLab"}),"."]})]})}function u(t={}){const{wrapper:e}={...(0,s.a)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(l,{...t})}):l(t)}},11151:(t,e,n)=>{n.d(e,{Z:()=>a,a:()=>i});var o=n(67294);const s={},r=o.createContext(s);function i(t){const e=o.useContext(r);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(s):t.components||s:i(t.components),o.createElement(r.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/aa24fd5d.143c547f.js b/assets/js/aa24fd5d.143c547f.js new file mode 100644 index 0000000..a0f600b --- /dev/null +++ b/assets/js/aa24fd5d.143c547f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[7257],{90251:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>h,default:()=>d,frontMatter:()=>r,metadata:()=>l,toc:()=>o});var s=n(85893),i=n(11151);const r={id:"python",slug:"/hash-tables/breaking/python",title:"Breaking Python",description:"Actually getting the worst-case time complexity in Python.\n",tags:["cpp","python","hash-tables"],last_update:{date:new Date("2023-11-28T00:00:00.000Z")}},h="Breaking the Hash Table in Python",l={id:"hash-tables/2023-11-28-breaking/python",title:"Breaking Python",description:"Actually getting the worst-case time complexity in Python.\n",source:"@site/algorithms/12-hash-tables/2023-11-28-breaking/01-python.md",sourceDirName:"12-hash-tables/2023-11-28-breaking",slug:"/hash-tables/breaking/python",permalink:"/algorithms/hash-tables/breaking/python",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/algorithms/12-hash-tables/2023-11-28-breaking/01-python.md",tags:[{label:"cpp",permalink:"/algorithms/tags/cpp"},{label:"python",permalink:"/algorithms/tags/python"},{label:"hash-tables",permalink:"/algorithms/tags/hash-tables"}],version:"current",lastUpdatedAt:1701129600,formattedLastUpdatedAt:"Nov 28, 2023",sidebarPosition:1,frontMatter:{id:"python",slug:"/hash-tables/breaking/python",title:"Breaking Python",description:"Actually getting the worst-case time complexity in Python.\n",tags:["cpp","python","hash-tables"],last_update:{date:"2023-11-28T00:00:00.000Z"}},sidebar:"autogeneratedBar",previous:{title:"Breaking Hash Table",permalink:"/algorithms/hash-tables/breaking"},next:{title:"Possible Mitigations",permalink:"/algorithms/hash-tables/breaking/mitigations"}},a={},o=[{value:"Preparing the attack",id:"preparing-the-attack",level:2},{value:"Sequences",id:"sequences",level:3},{value:"Results",id:"results",level:2},{value:"Comparing with the tree",id:"comparing-with-the-tree",level:2},{value:"References",id:"references",level:2}];function c(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",section:"section",strong:"strong",sup:"sup",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"breaking-the-hash-table-in-python",children:"Breaking the Hash Table in Python"}),"\n",(0,s.jsxs)(t.p,{children:["Our language of choice for bringing the worst out of the hash table is ",(0,s.jsx)(t.em,{children:"Python"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["Let's start by talking about the hash function and why we've chosen Python for\nthis. Hash function for integers in Python is simply ",(0,s.jsx)(t.em,{children:"identity"}),", as you might've\nguessed, there's no avalanche effect. Another thing that helps us is the fact\nthat integers in Python are technically ",(0,s.jsx)(t.code,{children:"BigInt"}),"s",(0,s.jsx)(t.sup,{children:(0,s.jsx)(t.a,{href:"#user-content-fn-1",id:"user-content-fnref-1","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"1"})}),". This allows us to put bit\nmore pressure on the hashing function."]}),"\n",(0,s.jsxs)(t.p,{children:["From the perspective of the implementation, it is a hash table that uses probing\nto resolve conflicts. This also means that it's a contiguous space in memory.\nIndexing works like in the provided example above. When the hash table reaches\na ",(0,s.jsx)(t.em,{children:"breaking point"})," (defined somewhere in the C code), it reallocates the table\nand rehashes everything."]}),"\n",(0,s.jsx)(t.admonition,{type:"tip",children:(0,s.jsx)(t.p,{children:"Resizing and rehashing can reduce the conflicts. That is coming from the fact\nthat the position in the table is determined by the hash and the size of the\ntable itself."})}),"\n",(0,s.jsx)(t.h2,{id:"preparing-the-attack",children:"Preparing the attack"}),"\n",(0,s.jsx)(t.p,{children:"Knowing the things above, it is not that hard to construct a method how to cause\nas many conflicts as possible. Let's go over it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"We know that integers are hashed to themselves."}),"\n",(0,s.jsx)(t.li,{children:"We also know that from that hash we use only lower bits that are used as\nindices."}),"\n",(0,s.jsx)(t.li,{children:"We also know that there's a rehashing on resize that could possibly fix the\nconflicts."}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"We will test with different sequences:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"ordered one, numbers through 1 to N"}),"\n",(0,s.jsx)(t.li,{children:"ordered one in a reversed order, numbers through N back to 1"}),"\n",(0,s.jsx)(t.li,{children:"numbers that are shifted to the left, so they create conflicts until resize"}),"\n",(0,s.jsx)(t.li,{children:"numbers that are shifted to the left, but resizing helps only in the end"}),"\n",(0,s.jsx)(t.li,{children:"numbers that are shifted to the left, but they won't be taken in account even\nafter final resize"}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"For each of these sequences, we will insert 10\u2077 elements and look each of them\nup for 10 times in a row."}),"\n",(0,s.jsxs)(t.p,{children:["As a base of our benchmark, we will use a ",(0,s.jsx)(t.code,{children:"Strategy"})," class and then for each\nstrategy we will just implement the sequence of numbers that it uses:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:'class Strategy:\n def __init__(self, data_structure=set):\n self._table = data_structure()\n\n @cached_property\n def elements(self):\n raise NotImplementedError("Implement for each strategy")\n\n @property\n def name(self):\n raise NotImplementedError("Implement for each strategy")\n\n def run(self):\n print(f"\\nBenchmarking:\\t\\t{self.name}")\n\n # Extract the elements here, so that the evaluation of them does not\n # slow down the relevant part of benchmark\n elements = self.elements\n\n # Insertion phase\n start = monotonic_ns()\n for x in elements:\n self._table.add(x)\n after_insertion = monotonic_ns()\n\n print(f"Insertion phase:\\t{(after_insertion - start) / 1000000:.2f}ms")\n\n # Lookup phase\n start = monotonic_ns()\n for _ in range(LOOPS):\n for x in elements:\n assert x in self._table\n after_lookups = monotonic_ns()\n\n print(f"Lookup phase:\\t\\t{(after_lookups - start) / 1000000:.2f}ms")\n'})}),"\n",(0,s.jsx)(t.h3,{id:"sequences",children:"Sequences"}),"\n",(0,s.jsx)(t.p,{children:"Let's have a look at how we generate the numbers to be inserted:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["ordered sequence (ascending)","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"x for x in range(N_ELEMENTS)\n"})}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["ordered sequence (descending)","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"x for x in reversed(range(N_ELEMENTS))\n"})}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["progressive sequence that \u201cheals\u201d on resize","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"(x << max(5, x.bit_length())) for x in range(N_ELEMENTS)\n"})}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["progressive sequence that \u201cheals\u201d in the end","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"(x << max(5, x.bit_length())) for x in reversed(range(N_ELEMENTS))\n"})}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["conflicts everywhere","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"x << 32 for x in range(N_ELEMENTS)\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"results",children:"Results"}),"\n",(0,s.jsx)(t.p,{children:"Let's have a look at the obtained results after running the code:"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"center"},children:"Technique"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Insertion phase"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Lookup phase"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"ordered sequence (ascending)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"558.60ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"3304.26ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"ordered sequence (descending)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"554.08ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"3365.84ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"progressive sequence that \u201cheals\u201d on resize"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"3781.30ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"28565.71ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"progressive sequence that \u201cheals\u201d in the end"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"3280.38ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"26494.61ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"conflicts everywhere"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"4027.54ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"29132.92ms"})})]})]})]}),"\n",(0,s.jsx)(t.p,{children:"You can see a noticable \u201cjump\u201d in the time after switching to the \u201cprogressive\u201d\nsequence. The last sequence that has conflicts all the time has the worst time,\neven though it's rather comparable with the first progressive sequence with\nregards to the insertion phase."}),"\n",(0,s.jsxs)(t.p,{children:["If we were to compare the ",(0,s.jsx)(t.em,{children:"always conflicting"})," one with the first one, we can\nsee that insertion took over 7\xd7 longer and lookups almost 9\xd7 longer."]}),"\n",(0,s.jsxs)(t.p,{children:["You can have a look at the code ",(0,s.jsx)(t.a,{href:"path:///files/algorithms/hash-tables/breaking/benchmark.py",children:"here"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"comparing-with-the-tree",children:"Comparing with the tree"}),"\n",(0,s.jsxs)(t.admonition,{type:"danger",children:[(0,s.jsxs)(t.p,{children:["Source code can be found ",(0,s.jsx)(t.a,{href:"path:///files/algorithms/hash-tables/breaking/benchmark.cpp",children:"here"}),"."]}),(0,s.jsx)(t.p,{children:(0,s.jsx)(t.em,{children:"Viewer discretion advised."})})]}),"\n",(0,s.jsx)(t.p,{children:"Python doesn't have a tree structure for sets/maps implemented, therefore for\na comparison we will run a similar benchmark in C++. By running the same\nsequences on both hash table and tree (RB-tree) we will obtain the following\nresults:"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"center"},children:"Technique"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Insertion (hash)"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Lookup (hash)"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Insertion (tree)"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Lookup (tree)"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"ordered (ascending)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"316ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"298ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"2098ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"5914ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"ordered (descending)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"259ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"315ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"1958ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"14747ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"progressive a)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"1152ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"6021ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"2581ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"16074ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"progressive b)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"1041ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"6096ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"2770ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"15986ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"conflicts"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"964ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"1633ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"2559ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"13285ms"})})]})]})]}),"\n",(0,s.jsx)(t.admonition,{type:"note",children:(0,s.jsx)(t.p,{children:"We can't forget that implementation details be involved. Hash function is still\nthe identity, to my knowledge."})}),"\n",(0,s.jsx)(t.p,{children:"One interesting thing to notice is the fact that the progressive sequences took\nthe most time in lookups (which is not same as in the Python)."}),"\n",(0,s.jsx)(t.p,{children:"Now, if we have a look at the tree implementation, we can notice two very\ndistinctive things:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["Tree implementations are not affected by the input, therefore (except for the\nfirst sequence) we can see ",(0,s.jsx)(t.strong,{children:"very consistent"})," times."]}),"\n",(0,s.jsx)(t.li,{children:"Compared to the hash table the times are much higher and not very ideal."}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"The reason for the 2nd point may not be very obvious. From the technical\nperspective it makes some sense. Let's dive into it!"}),"\n",(0,s.jsxs)(t.p,{children:["If we take a hash table, it is an array in a memory, therefore it is contiguous\npiece of memory. (For more information I'd suggest looking into the 1st blog\npost below in references section by ",(0,s.jsx)(t.em,{children:"Bjarne Stroustrup"}),")"]}),"\n",(0,s.jsxs)(t.p,{children:["On the other hand, if we take a look at the tree, each node holds some\nattributes and pointers to the left and right descendants of itself. Even if we\nmaintain a reasonable height of the tree (keep the tree balanced), we still need\nto follow the pointers which point to the nodes ",(0,s.jsx)(t.em,{children:"somewhere"})," on the heap. When\ntraversing the tree, we get a consistent time complexity, but at the expense of\njumping between the nodes on the heap which takes some time."]}),"\n",(0,s.jsxs)(t.admonition,{type:"danger",children:[(0,s.jsx)(t.p,{children:"This is not supposed to leverage the hash table and try to persuade people not\nto use the tree representations. There are benefits coming from the respective\ndata structures, even if the time is not the best."}),(0,s.jsx)(t.p,{children:"Overall if we compare the worst-case time complexities of the tree and hash\ntable, tree representation comes off better."})]}),"\n",(0,s.jsx)(t.admonition,{title:"Challenge",type:"tip",children:(0,s.jsx)(t.p,{children:"Try to benchmark with the similar approach in the Rust. Since Rust uses\ndifferent hash function, it would be the best to just override the hash, this\nway you can also avoid the hard part of this attack (making up the numbers that\nwill collide)."})}),"\n",(0,s.jsx)(t.hr,{}),"\n",(0,s.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["Bjarne Stroustrup.\n",(0,s.jsx)(t.a,{href:"https://www.stroustrup.com/bs_faq.html#list",children:"Are lists evil?"})]}),"\n"]}),"\n",(0,s.jsxs)(t.section,{"data-footnotes":!0,className:"footnotes",children:[(0,s.jsx)(t.h2,{className:"sr-only",id:"footnote-label",children:"Footnotes"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{id:"user-content-fn-1",children:["\n",(0,s.jsxs)(t.p,{children:["Arbitrary-sized integers, they can get as big as your memory allows. ",(0,s.jsx)(t.a,{href:"#user-content-fnref-1","data-footnote-backref":"","aria-label":"Back to reference 1",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n"]}),"\n"]})]})}function d(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,t,n)=>{n.d(t,{Z:()=>l,a:()=>h});var s=n(67294);const i={},r=s.createContext(i);function h(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:h(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/aa24fd5d.a1be9355.js b/assets/js/aa24fd5d.a1be9355.js deleted file mode 100644 index 2cc7a2e..0000000 --- a/assets/js/aa24fd5d.a1be9355.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[7257],{90251:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>h,default:()=>d,frontMatter:()=>r,metadata:()=>l,toc:()=>o});var s=n(85893),i=n(11151);const r={id:"python",slug:"/hash-tables/breaking/python",title:"Breaking Python",description:"Actually getting the worst-case time complexity in Python.\n",tags:["cpp","python","hash-tables"],last_update:{date:new Date("2023-11-28T00:00:00.000Z")}},h=void 0,l={id:"hash-tables/2023-11-28-breaking/python",title:"Breaking Python",description:"Actually getting the worst-case time complexity in Python.\n",source:"@site/algorithms/12-hash-tables/2023-11-28-breaking/01-python.md",sourceDirName:"12-hash-tables/2023-11-28-breaking",slug:"/hash-tables/breaking/python",permalink:"/algorithms/hash-tables/breaking/python",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/algorithms/12-hash-tables/2023-11-28-breaking/01-python.md",tags:[{label:"cpp",permalink:"/algorithms/tags/cpp"},{label:"python",permalink:"/algorithms/tags/python"},{label:"hash-tables",permalink:"/algorithms/tags/hash-tables"}],version:"current",lastUpdatedAt:1701129600,formattedLastUpdatedAt:"Nov 28, 2023",sidebarPosition:1,frontMatter:{id:"python",slug:"/hash-tables/breaking/python",title:"Breaking Python",description:"Actually getting the worst-case time complexity in Python.\n",tags:["cpp","python","hash-tables"],last_update:{date:"2023-11-28T00:00:00.000Z"}},sidebar:"autogeneratedBar",previous:{title:"Breaking Hash Table",permalink:"/algorithms/hash-tables/breaking"},next:{title:"Possible Mitigations",permalink:"/algorithms/hash-tables/breaking/mitigations"}},a={},o=[{value:"Breaking the Hash Table in Python",id:"breaking-the-hash-table-in-python",level:2},{value:"Preparing the attack",id:"preparing-the-attack",level:2},{value:"Sequences",id:"sequences",level:3},{value:"Results",id:"results",level:2},{value:"Comparing with the tree",id:"comparing-with-the-tree",level:2},{value:"References",id:"references",level:2}];function c(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",h3:"h3",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",section:"section",strong:"strong",sup:"sup",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"breaking-the-hash-table-in-python",children:"Breaking the Hash Table in Python"}),"\n",(0,s.jsxs)(t.p,{children:["Our language of choice for bringing the worst out of the hash table is ",(0,s.jsx)(t.em,{children:"Python"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["Let's start by talking about the hash function and why we've chosen Python for\nthis. Hash function for integers in Python is simply ",(0,s.jsx)(t.em,{children:"identity"}),", as you might've\nguessed, there's no avalanche effect. Another thing that helps us is the fact\nthat integers in Python are technically ",(0,s.jsx)(t.code,{children:"BigInt"}),"s",(0,s.jsx)(t.sup,{children:(0,s.jsx)(t.a,{href:"#user-content-fn-1",id:"user-content-fnref-1","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"1"})}),". This allows us to put bit\nmore pressure on the hashing function."]}),"\n",(0,s.jsxs)(t.p,{children:["From the perspective of the implementation, it is a hash table that uses probing\nto resolve conflicts. This also means that it's a contiguous space in memory.\nIndexing works like in the provided example above. When the hash table reaches\na ",(0,s.jsx)(t.em,{children:"breaking point"})," (defined somewhere in the C code), it reallocates the table\nand rehashes everything."]}),"\n",(0,s.jsx)(t.admonition,{type:"tip",children:(0,s.jsx)(t.p,{children:"Resizing and rehashing can reduce the conflicts. That is coming from the fact\nthat the position in the table is determined by the hash and the size of the\ntable itself."})}),"\n",(0,s.jsx)(t.h2,{id:"preparing-the-attack",children:"Preparing the attack"}),"\n",(0,s.jsx)(t.p,{children:"Knowing the things above, it is not that hard to construct a method how to cause\nas many conflicts as possible. Let's go over it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"We know that integers are hashed to themselves."}),"\n",(0,s.jsx)(t.li,{children:"We also know that from that hash we use only lower bits that are used as\nindices."}),"\n",(0,s.jsx)(t.li,{children:"We also know that there's a rehashing on resize that could possibly fix the\nconflicts."}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"We will test with different sequences:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"ordered one, numbers through 1 to N"}),"\n",(0,s.jsx)(t.li,{children:"ordered one in a reversed order, numbers through N back to 1"}),"\n",(0,s.jsx)(t.li,{children:"numbers that are shifted to the left, so they create conflicts until resize"}),"\n",(0,s.jsx)(t.li,{children:"numbers that are shifted to the left, but resizing helps only in the end"}),"\n",(0,s.jsx)(t.li,{children:"numbers that are shifted to the left, but they won't be taken in account even\nafter final resize"}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"For each of these sequences, we will insert 10\u2077 elements and look each of them\nup for 10 times in a row."}),"\n",(0,s.jsxs)(t.p,{children:["As a base of our benchmark, we will use a ",(0,s.jsx)(t.code,{children:"Strategy"})," class and then for each\nstrategy we will just implement the sequence of numbers that it uses:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:'class Strategy:\n def __init__(self, data_structure=set):\n self._table = data_structure()\n\n @cached_property\n def elements(self):\n raise NotImplementedError("Implement for each strategy")\n\n @property\n def name(self):\n raise NotImplementedError("Implement for each strategy")\n\n def run(self):\n print(f"\\nBenchmarking:\\t\\t{self.name}")\n\n # Extract the elements here, so that the evaluation of them does not\n # slow down the relevant part of benchmark\n elements = self.elements\n\n # Insertion phase\n start = monotonic_ns()\n for x in elements:\n self._table.add(x)\n after_insertion = monotonic_ns()\n\n print(f"Insertion phase:\\t{(after_insertion - start) / 1000000:.2f}ms")\n\n # Lookup phase\n start = monotonic_ns()\n for _ in range(LOOPS):\n for x in elements:\n assert x in self._table\n after_lookups = monotonic_ns()\n\n print(f"Lookup phase:\\t\\t{(after_lookups - start) / 1000000:.2f}ms")\n'})}),"\n",(0,s.jsx)(t.h3,{id:"sequences",children:"Sequences"}),"\n",(0,s.jsx)(t.p,{children:"Let's have a look at how we generate the numbers to be inserted:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["ordered sequence (ascending)","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"x for x in range(N_ELEMENTS)\n"})}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["ordered sequence (descending)","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"x for x in reversed(range(N_ELEMENTS))\n"})}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["progressive sequence that \u201cheals\u201d on resize","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"(x << max(5, x.bit_length())) for x in range(N_ELEMENTS)\n"})}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["progressive sequence that \u201cheals\u201d in the end","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"(x << max(5, x.bit_length())) for x in reversed(range(N_ELEMENTS))\n"})}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["conflicts everywhere","\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-py",children:"x << 32 for x in range(N_ELEMENTS)\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"results",children:"Results"}),"\n",(0,s.jsx)(t.p,{children:"Let's have a look at the obtained results after running the code:"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"center"},children:"Technique"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Insertion phase"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Lookup phase"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"ordered sequence (ascending)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"558.60ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"3304.26ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"ordered sequence (descending)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"554.08ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"3365.84ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"progressive sequence that \u201cheals\u201d on resize"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"3781.30ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"28565.71ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"progressive sequence that \u201cheals\u201d in the end"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"3280.38ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"26494.61ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"conflicts everywhere"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"4027.54ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"29132.92ms"})})]})]})]}),"\n",(0,s.jsx)(t.p,{children:"You can see a noticable \u201cjump\u201d in the time after switching to the \u201cprogressive\u201d\nsequence. The last sequence that has conflicts all the time has the worst time,\neven though it's rather comparable with the first progressive sequence with\nregards to the insertion phase."}),"\n",(0,s.jsxs)(t.p,{children:["If we were to compare the ",(0,s.jsx)(t.em,{children:"always conflicting"})," one with the first one, we can\nsee that insertion took over 7\xd7 longer and lookups almost 9\xd7 longer."]}),"\n",(0,s.jsxs)(t.p,{children:["You can have a look at the code ",(0,s.jsx)(t.a,{href:"path:///files/algorithms/hash-tables/breaking/benchmark.py",children:"here"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"comparing-with-the-tree",children:"Comparing with the tree"}),"\n",(0,s.jsxs)(t.admonition,{type:"danger",children:[(0,s.jsxs)(t.p,{children:["Source code can be found ",(0,s.jsx)(t.a,{href:"path:///files/algorithms/hash-tables/breaking/benchmark.cpp",children:"here"}),"."]}),(0,s.jsx)(t.p,{children:(0,s.jsx)(t.em,{children:"Viewer discretion advised."})})]}),"\n",(0,s.jsx)(t.p,{children:"Python doesn't have a tree structure for sets/maps implemented, therefore for\na comparison we will run a similar benchmark in C++. By running the same\nsequences on both hash table and tree (RB-tree) we will obtain the following\nresults:"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"center"},children:"Technique"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Insertion (hash)"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Lookup (hash)"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Insertion (tree)"}),(0,s.jsx)(t.th,{style:{textAlign:"right"},children:"Lookup (tree)"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"ordered (ascending)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"316ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"298ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"2098ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"5914ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"ordered (descending)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"259ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"315ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"1958ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"14747ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"progressive a)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"1152ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"6021ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"2581ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"16074ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"progressive b)"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"1041ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"6096ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"2770ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"15986ms"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"center"},children:"conflicts"}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"964ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"1633ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"2559ms"})}),(0,s.jsx)(t.td,{style:{textAlign:"right"},children:(0,s.jsx)(t.code,{children:"13285ms"})})]})]})]}),"\n",(0,s.jsx)(t.admonition,{type:"note",children:(0,s.jsx)(t.p,{children:"We can't forget that implementation details be involved. Hash function is still\nthe identity, to my knowledge."})}),"\n",(0,s.jsx)(t.p,{children:"One interesting thing to notice is the fact that the progressive sequences took\nthe most time in lookups (which is not same as in the Python)."}),"\n",(0,s.jsx)(t.p,{children:"Now, if we have a look at the tree implementation, we can notice two very\ndistinctive things:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["Tree implementations are not affected by the input, therefore (except for the\nfirst sequence) we can see ",(0,s.jsx)(t.strong,{children:"very consistent"})," times."]}),"\n",(0,s.jsx)(t.li,{children:"Compared to the hash table the times are much higher and not very ideal."}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"The reason for the 2nd point may not be very obvious. From the technical\nperspective it makes some sense. Let's dive into it!"}),"\n",(0,s.jsxs)(t.p,{children:["If we take a hash table, it is an array in a memory, therefore it is contiguous\npiece of memory. (For more information I'd suggest looking into the 1st blog\npost below in references section by ",(0,s.jsx)(t.em,{children:"Bjarne Stroustrup"}),")"]}),"\n",(0,s.jsxs)(t.p,{children:["On the other hand, if we take a look at the tree, each node holds some\nattributes and pointers to the left and right descendants of itself. Even if we\nmaintain a reasonable height of the tree (keep the tree balanced), we still need\nto follow the pointers which point to the nodes ",(0,s.jsx)(t.em,{children:"somewhere"})," on the heap. When\ntraversing the tree, we get a consistent time complexity, but at the expense of\njumping between the nodes on the heap which takes some time."]}),"\n",(0,s.jsxs)(t.admonition,{type:"danger",children:[(0,s.jsx)(t.p,{children:"This is not supposed to leverage the hash table and try to persuade people not\nto use the tree representations. There are benefits coming from the respective\ndata structures, even if the time is not the best."}),(0,s.jsx)(t.p,{children:"Overall if we compare the worst-case time complexities of the tree and hash\ntable, tree representation comes off better."})]}),"\n",(0,s.jsx)(t.admonition,{title:"Challenge",type:"tip",children:(0,s.jsx)(t.p,{children:"Try to benchmark with the similar approach in the Rust. Since Rust uses\ndifferent hash function, it would be the best to just override the hash, this\nway you can also avoid the hard part of this attack (making up the numbers that\nwill collide)."})}),"\n",(0,s.jsx)(t.hr,{}),"\n",(0,s.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["Bjarne Stroustrup.\n",(0,s.jsx)(t.a,{href:"https://www.stroustrup.com/bs_faq.html#list",children:"Are lists evil?"})]}),"\n"]}),"\n",(0,s.jsxs)(t.section,{"data-footnotes":!0,className:"footnotes",children:[(0,s.jsx)(t.h2,{className:"sr-only",id:"footnote-label",children:"Footnotes"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{id:"user-content-fn-1",children:["\n",(0,s.jsxs)(t.p,{children:["Arbitrary-sized integers, they can get as big as your memory allows. ",(0,s.jsx)(t.a,{href:"#user-content-fnref-1","data-footnote-backref":"","aria-label":"Back to reference 1",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n"]}),"\n"]})]})}function d(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},11151:(e,t,n)=>{n.d(t,{Z:()=>l,a:()=>h});var s=n(67294);const i={},r=s.createContext(i);function h(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:h(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b1288602.9d3ae1e4.js b/assets/js/b1288602.2548704d.js similarity index 99% rename from assets/js/b1288602.9d3ae1e4.js rename to assets/js/b1288602.2548704d.js index 7111fc5..f51aaf9 100644 --- a/assets/js/b1288602.9d3ae1e4.js +++ b/assets/js/b1288602.2548704d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[59],{51456:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var r=t(85893),s=t(11151);const o={title:"Submitting merge requests"},i="Submitting merge requests for review",a={id:"mr",title:"Submitting merge requests",description:"This tutorial aims to show you how to follow basic git workflow and submit changes",source:"@site/c/mr.md",sourceDirName:".",slug:"/mr",permalink:"/c/mr",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/mr.md",tags:[],version:"current",lastUpdatedAt:1701196739,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{title:"Submitting merge requests"},sidebar:"autogeneratedBar",previous:{title:"Practice exam C",permalink:"/c/pexam/cams"}},c={},h=[{value:"Tutorial",id:"tutorial",level:2},{value:"Step #1 - Starting from the clean repository",id:"step-1---starting-from-the-clean-repository",level:3},{value:"Step #2 - Create new branch",id:"step-2---create-new-branch",level:3},{value:"Step #3 - Do the assignment",id:"step-3---do-the-assignment",level:3},{value:"Step #4 - Commit and upload the changes to GitLab",id:"step-4---commit-and-upload-the-changes-to-gitlab",level:3},{value:"Step #5 - Creating a merge request manually",id:"step-5---creating-a-merge-request-manually",level:3},{value:"Step #6 - Set assignees",id:"step-6---set-assignees",level:3},{value:"Step #7 - Return to default branch",id:"step-7---return-to-default-branch",level:3}];function l(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"submitting-merge-requests-for-review",children:"Submitting merge requests for review"}),"\n",(0,r.jsxs)(n.p,{children:["This tutorial aims to show you how to follow basic git workflow and submit changes\nthrough ",(0,r.jsx)(n.em,{children:"Merge Requests"})," for review."]}),"\n",(0,r.jsxs)(n.p,{children:["The rudimentary idea behind aims for changes to be present on a separate branch\nthat is supposedly ",(0,r.jsx)(n.em,{children:"merged"})," into the default branch. Till then changes can be reviewed\non ",(0,r.jsx)(n.em,{children:"Merge Request"})," and additional changes may be made based on the reviews. Once\nthe changes satisfy requirements, the merge request is merged."]}),"\n",(0,r.jsx)(n.h2,{id:"tutorial",children:"Tutorial"}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:["Use this tutorial only for bonus assignments ",(0,r.jsx)(n.strong,{children:"made by your tutors"})," or in case\nyou need to make up for the absence."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"step-1---starting-from-the-clean-repository",children:"Step #1 - Starting from the clean repository"}),"\n",(0,r.jsxs)(n.p,{children:["In your repository (either locally or on aisa) type ",(0,r.jsx)(n.code,{children:"git status"})," and check if your\nrepository is clean and you are present on the main branch (",(0,r.jsx)(n.code,{children:"master"}),", ",(0,r.jsx)(n.code,{children:"main"})," or\n",(0,r.jsx)(n.code,{children:"trunk"}),"). If you do not know what your default branch is, it is probably ",(0,r.jsx)(n.code,{children:"master"}),"\nand you should not be on any other branch."]}),"\n",(0,r.jsx)(n.p,{children:"Output of the command should look like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ git status\nOn branch master # Or main or trunk.\nYour branch is up to date with 'origin/master'.\n\nnothing to commit, working tree clean\n"})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:["In case you are on different branch or there are uncommitted changes,\n",(0,r.jsx)(n.strong,{children:"do not continue!!!"})," Clean your repository (commit the changes or discard\nthem), before you continue."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"step-2---create-new-branch",children:"Step #2 - Create new branch"}),"\n",(0,r.jsx)(n.p,{children:"In your repository write command:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ git checkout -b BRANCH\nSwitched to a new branch 'BRANCH'\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Instead of ",(0,r.jsx)(n.code,{children:"BRANCH"})," use some reasonable name for the branch. For example if you\nare working on the seminar from 3rd week, name the branch ",(0,r.jsx)(n.code,{children:"seminar-03"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"step-3---do-the-assignment",children:"Step #3 - Do the assignment"}),"\n",(0,r.jsx)(n.p,{children:"Download the skeleton for the seminar assignment, extract and program. For example\nif you are working on 3rd seminar, you can do so by:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ wget https://www.fi.muni.cz/pb071/seminars/seminar-03/pb071-seminar-03.zip\naisa$ unzip pb071-seminar-03.zip\n# Now you should have directory 'seminar-03'.\naisa$ rm pb071-seminar-03.zip\naisa$ cd seminar-03\n# You can work on the assignment.\n"})}),"\n",(0,r.jsx)(n.h3,{id:"step-4---commit-and-upload-the-changes-to-gitlab",children:"Step #4 - Commit and upload the changes to GitLab"}),"\n",(0,r.jsxs)(n.p,{children:["The same way you ",(0,r.jsx)(n.em,{children:"add"})," and ",(0,r.jsx)(n.em,{children:"commit"})," files for the homework assignments, you do for\nthe seminar."]}),"\n",(0,r.jsxs)(n.p,{children:["Now you can upload the changes to GitLab. ",(0,r.jsx)(n.code,{children:"git push"})," is not enough, since repository\non GitLab does not know your new branch. You can solve this by adding arguments:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ git push origin BRANCH\n...\nremote: To create a merge request for BRANCH, visit:\nremote: https://gitlab.fi.muni.cz/login/pb071/merge_requests/new?merge_request%5Bsource_branch%5D=BRANCH\n...\n"})}),"\n",(0,r.jsx)(n.p,{children:"In the output you should have a link for creating a merge request. If you see this\nlink, open it and skip next step."}),"\n",(0,r.jsx)(n.h3,{id:"step-5---creating-a-merge-request-manually",children:"Step #5 - Creating a merge request manually"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"Open your repository on GitLab."}),"\n",(0,r.jsxs)(n.li,{children:["On the left panel click on ",(0,r.jsx)(n.em,{children:"Merge Requests"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["Click on ",(0,r.jsx)(n.em,{children:"New Merge Request"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["In ",(0,r.jsx)(n.em,{children:"Source branch"})," select ",(0,r.jsx)(n.code,{children:"login/pb071"})," and ",(0,r.jsx)(n.code,{children:"BRANCH"}),", which you created."]}),"\n",(0,r.jsxs)(n.li,{children:["In ",(0,r.jsx)(n.em,{children:"Target branch"})," select ",(0,r.jsx)(n.code,{children:"login/pb071"})," and your default branch you have seen\nin the output of the first command. (most likely ",(0,r.jsx)(n.code,{children:"master"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:["Click on ",(0,r.jsx)(n.em,{children:"Compare branches and continue"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"step-6---set-assignees",children:"Step #6 - Set assignees"}),"\n",(0,r.jsxs)(n.p,{children:["On the page that is opened, please check at the top that you are creating merge\nrequest ",(0,r.jsx)(n.strong,{children:"from"})," your new branch ",(0,r.jsx)(n.strong,{children:"to"})," your default branch (one of ",(0,r.jsx)(n.code,{children:"master"}),", ",(0,r.jsx)(n.code,{children:"main"}),"\nor ",(0,r.jsx)(n.code,{children:"trunk"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["Then in the field ",(0,r.jsx)(n.em,{children:"Assignees"})," set your tutors based on the seminar group. You can\nuse login for a quick look up."]}),"\n",(0,r.jsxs)(n.p,{children:["In the end click on ",(0,r.jsx)(n.em,{children:"Submit merge request"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"step-7---return-to-default-branch",children:"Step #7 - Return to default branch"}),"\n",(0,r.jsx)(n.p,{children:"Homework assignments can be submitted only from branches specified in the rules\nfor the course. Because of that, before you do anything else, you should switch\nback to your default branch."}),"\n",(0,r.jsxs)(n.p,{children:["First of all, same as in step #1, check that your repository is clean with ",(0,r.jsx)(n.code,{children:"git status"}),".\nFor the sake of safety, do not continue without clean repository. Then with command\n",(0,r.jsx)(n.code,{children:"git checkout BRANCH"})," switch to your default branch ",(0,r.jsx)(n.code,{children:"BRANCH"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["If you do not know which branch is your default, try ",(0,r.jsx)(n.code,{children:"git branch"})," that outputs all branches in your repository. Default branch is typically ",(0,r.jsx)(n.code,{children:"master"}),", but can\nbe ",(0,r.jsx)(n.code,{children:"main"})," or ",(0,r.jsx)(n.code,{children:"trunk"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ git status\n# Check if repository is clean\n\n# If you know, what is your default branch, you can skip next command.\naisa$ git branch\n# Find the default branch in the list; should be one of the `master`, `main` or\n# `trunk` and you should not have more than one of those.\n# In case the list clears the terminal and you cannot see shell prompt, you can\n# press `q` to quit the pager.\n\naisa$ git checkout master\n"})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.p,{children:["Adapted from: ",(0,r.jsx)(n.a,{href:"https://www.fi.muni.cz/~xlacko1/pb071/mr.html",children:"https://www.fi.muni.cz/~xlacko1/pb071/mr.html"})]})]})}function d(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},11151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>i});var r=t(67294);const s={},o=r.createContext(s);function i(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[59],{51456:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var r=t(85893),s=t(11151);const o={title:"Submitting merge requests"},i="Submitting merge requests for review",a={id:"mr",title:"Submitting merge requests",description:"This tutorial aims to show you how to follow basic git workflow and submit changes",source:"@site/c/mr.md",sourceDirName:".",slug:"/mr",permalink:"/c/mr",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/mr.md",tags:[],version:"current",lastUpdatedAt:1701199517,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{title:"Submitting merge requests"},sidebar:"autogeneratedBar",previous:{title:"Practice exam C",permalink:"/c/pexam/cams"}},c={},h=[{value:"Tutorial",id:"tutorial",level:2},{value:"Step #1 - Starting from the clean repository",id:"step-1---starting-from-the-clean-repository",level:3},{value:"Step #2 - Create new branch",id:"step-2---create-new-branch",level:3},{value:"Step #3 - Do the assignment",id:"step-3---do-the-assignment",level:3},{value:"Step #4 - Commit and upload the changes to GitLab",id:"step-4---commit-and-upload-the-changes-to-gitlab",level:3},{value:"Step #5 - Creating a merge request manually",id:"step-5---creating-a-merge-request-manually",level:3},{value:"Step #6 - Set assignees",id:"step-6---set-assignees",level:3},{value:"Step #7 - Return to default branch",id:"step-7---return-to-default-branch",level:3}];function l(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"submitting-merge-requests-for-review",children:"Submitting merge requests for review"}),"\n",(0,r.jsxs)(n.p,{children:["This tutorial aims to show you how to follow basic git workflow and submit changes\nthrough ",(0,r.jsx)(n.em,{children:"Merge Requests"})," for review."]}),"\n",(0,r.jsxs)(n.p,{children:["The rudimentary idea behind aims for changes to be present on a separate branch\nthat is supposedly ",(0,r.jsx)(n.em,{children:"merged"})," into the default branch. Till then changes can be reviewed\non ",(0,r.jsx)(n.em,{children:"Merge Request"})," and additional changes may be made based on the reviews. Once\nthe changes satisfy requirements, the merge request is merged."]}),"\n",(0,r.jsx)(n.h2,{id:"tutorial",children:"Tutorial"}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:["Use this tutorial only for bonus assignments ",(0,r.jsx)(n.strong,{children:"made by your tutors"})," or in case\nyou need to make up for the absence."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"step-1---starting-from-the-clean-repository",children:"Step #1 - Starting from the clean repository"}),"\n",(0,r.jsxs)(n.p,{children:["In your repository (either locally or on aisa) type ",(0,r.jsx)(n.code,{children:"git status"})," and check if your\nrepository is clean and you are present on the main branch (",(0,r.jsx)(n.code,{children:"master"}),", ",(0,r.jsx)(n.code,{children:"main"})," or\n",(0,r.jsx)(n.code,{children:"trunk"}),"). If you do not know what your default branch is, it is probably ",(0,r.jsx)(n.code,{children:"master"}),"\nand you should not be on any other branch."]}),"\n",(0,r.jsx)(n.p,{children:"Output of the command should look like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ git status\nOn branch master # Or main or trunk.\nYour branch is up to date with 'origin/master'.\n\nnothing to commit, working tree clean\n"})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:["In case you are on different branch or there are uncommitted changes,\n",(0,r.jsx)(n.strong,{children:"do not continue!!!"})," Clean your repository (commit the changes or discard\nthem), before you continue."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"step-2---create-new-branch",children:"Step #2 - Create new branch"}),"\n",(0,r.jsx)(n.p,{children:"In your repository write command:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ git checkout -b BRANCH\nSwitched to a new branch 'BRANCH'\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Instead of ",(0,r.jsx)(n.code,{children:"BRANCH"})," use some reasonable name for the branch. For example if you\nare working on the seminar from 3rd week, name the branch ",(0,r.jsx)(n.code,{children:"seminar-03"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"step-3---do-the-assignment",children:"Step #3 - Do the assignment"}),"\n",(0,r.jsx)(n.p,{children:"Download the skeleton for the seminar assignment, extract and program. For example\nif you are working on 3rd seminar, you can do so by:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ wget https://www.fi.muni.cz/pb071/seminars/seminar-03/pb071-seminar-03.zip\naisa$ unzip pb071-seminar-03.zip\n# Now you should have directory 'seminar-03'.\naisa$ rm pb071-seminar-03.zip\naisa$ cd seminar-03\n# You can work on the assignment.\n"})}),"\n",(0,r.jsx)(n.h3,{id:"step-4---commit-and-upload-the-changes-to-gitlab",children:"Step #4 - Commit and upload the changes to GitLab"}),"\n",(0,r.jsxs)(n.p,{children:["The same way you ",(0,r.jsx)(n.em,{children:"add"})," and ",(0,r.jsx)(n.em,{children:"commit"})," files for the homework assignments, you do for\nthe seminar."]}),"\n",(0,r.jsxs)(n.p,{children:["Now you can upload the changes to GitLab. ",(0,r.jsx)(n.code,{children:"git push"})," is not enough, since repository\non GitLab does not know your new branch. You can solve this by adding arguments:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ git push origin BRANCH\n...\nremote: To create a merge request for BRANCH, visit:\nremote: https://gitlab.fi.muni.cz/login/pb071/merge_requests/new?merge_request%5Bsource_branch%5D=BRANCH\n...\n"})}),"\n",(0,r.jsx)(n.p,{children:"In the output you should have a link for creating a merge request. If you see this\nlink, open it and skip next step."}),"\n",(0,r.jsx)(n.h3,{id:"step-5---creating-a-merge-request-manually",children:"Step #5 - Creating a merge request manually"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"Open your repository on GitLab."}),"\n",(0,r.jsxs)(n.li,{children:["On the left panel click on ",(0,r.jsx)(n.em,{children:"Merge Requests"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["Click on ",(0,r.jsx)(n.em,{children:"New Merge Request"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["In ",(0,r.jsx)(n.em,{children:"Source branch"})," select ",(0,r.jsx)(n.code,{children:"login/pb071"})," and ",(0,r.jsx)(n.code,{children:"BRANCH"}),", which you created."]}),"\n",(0,r.jsxs)(n.li,{children:["In ",(0,r.jsx)(n.em,{children:"Target branch"})," select ",(0,r.jsx)(n.code,{children:"login/pb071"})," and your default branch you have seen\nin the output of the first command. (most likely ",(0,r.jsx)(n.code,{children:"master"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:["Click on ",(0,r.jsx)(n.em,{children:"Compare branches and continue"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"step-6---set-assignees",children:"Step #6 - Set assignees"}),"\n",(0,r.jsxs)(n.p,{children:["On the page that is opened, please check at the top that you are creating merge\nrequest ",(0,r.jsx)(n.strong,{children:"from"})," your new branch ",(0,r.jsx)(n.strong,{children:"to"})," your default branch (one of ",(0,r.jsx)(n.code,{children:"master"}),", ",(0,r.jsx)(n.code,{children:"main"}),"\nor ",(0,r.jsx)(n.code,{children:"trunk"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["Then in the field ",(0,r.jsx)(n.em,{children:"Assignees"})," set your tutors based on the seminar group. You can\nuse login for a quick look up."]}),"\n",(0,r.jsxs)(n.p,{children:["In the end click on ",(0,r.jsx)(n.em,{children:"Submit merge request"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"step-7---return-to-default-branch",children:"Step #7 - Return to default branch"}),"\n",(0,r.jsx)(n.p,{children:"Homework assignments can be submitted only from branches specified in the rules\nfor the course. Because of that, before you do anything else, you should switch\nback to your default branch."}),"\n",(0,r.jsxs)(n.p,{children:["First of all, same as in step #1, check that your repository is clean with ",(0,r.jsx)(n.code,{children:"git status"}),".\nFor the sake of safety, do not continue without clean repository. Then with command\n",(0,r.jsx)(n.code,{children:"git checkout BRANCH"})," switch to your default branch ",(0,r.jsx)(n.code,{children:"BRANCH"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["If you do not know which branch is your default, try ",(0,r.jsx)(n.code,{children:"git branch"})," that outputs all branches in your repository. Default branch is typically ",(0,r.jsx)(n.code,{children:"master"}),", but can\nbe ",(0,r.jsx)(n.code,{children:"main"})," or ",(0,r.jsx)(n.code,{children:"trunk"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"aisa$ git status\n# Check if repository is clean\n\n# If you know, what is your default branch, you can skip next command.\naisa$ git branch\n# Find the default branch in the list; should be one of the `master`, `main` or\n# `trunk` and you should not have more than one of those.\n# In case the list clears the terminal and you cannot see shell prompt, you can\n# press `q` to quit the pager.\n\naisa$ git checkout master\n"})}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(n.p,{children:["Adapted from: ",(0,r.jsx)(n.a,{href:"https://www.fi.muni.cz/~xlacko1/pb071/mr.html",children:"https://www.fi.muni.cz/~xlacko1/pb071/mr.html"})]})]})}function d(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},11151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>i});var r=t(67294);const s={},o=r.createContext(s);function i(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d05e838c.1b2f4a74.js b/assets/js/d05e838c.ac17e06f.js similarity index 99% rename from assets/js/d05e838c.1b2f4a74.js rename to assets/js/d05e838c.ac17e06f.js index 3d32e27..178267b 100644 --- a/assets/js/d05e838c.1b2f4a74.js +++ b/assets/js/d05e838c.ac17e06f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[6544],{63004:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>a,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var s=r(85893),t=r(11151);const i={id:"seminar-05-06",title:"5th and 6th seminar",description:"200IQ encryption.\n"},c=void 0,o={id:"bonuses/seminar-05-06",title:"5th and 6th seminar",description:"200IQ encryption.\n",source:"@site/c/bonuses/05-06.md",sourceDirName:"bonuses",slug:"/bonuses/seminar-05-06",permalink:"/c/bonuses/seminar-05-06",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/bonuses/05-06.md",tags:[],version:"current",lastUpdatedAt:1701196739,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{id:"seminar-05-06",title:"5th and 6th seminar",description:"200IQ encryption.\n"},sidebar:"autogeneratedBar",previous:{title:"4th seminar",permalink:"/c/bonuses/seminar-04"},next:{title:"8th seminar",permalink:"/c/bonuses/seminar-08"}},d={},l=[{value:"Introduction",id:"introduction",level:2},{value:"Task no. 1: Reverse (0.5 K\u20a1)",id:"task-no-1-reverse-05-k",level:3},{value:"Task no. 2: Vigen\xe8re (0.5 K\u20a1)",id:"task-no-2-vigen\xe8re-05-k",level:3},{value:"Bonus part (0.5 K\u20a1)",id:"bonus-part-05-k",level:4},{value:"Task no. 3: Bit madness (0.5 K\u20a1)",id:"task-no-3-bit-madness-05-k",level:3},{value:"Task no. 4: All combined to BMP (0.5 K\u20a1)",id:"task-no-4-all-combined-to-bmp-05-k",level:3},{value:"Submitting",id:"submitting",level:2}];function h(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"For this bonus you can get at maximum 2.5 K\u20a1."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.a,{href:"pathname:///files/c/bonuses/05-06.tar.gz",children:"Source"})}),"\n",(0,s.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)(n.p,{children:"In this bonus you will implement few functions that will be used together for\nimplementing a very special cipher."}),"\n",(0,s.jsx)(n.h3,{id:"task-no-1-reverse-05-k",children:"Task no. 1: Reverse (0.5 K\u20a1)"}),"\n",(0,s.jsxs)(n.p,{children:["Write a function ",(0,s.jsx)(n.code,{children:"char* reverse(const char* text)"})," that returns copy of the input\nstring in reversed order (also uppercase)."]}),"\n",(0,s.jsxs)(n.p,{children:["In case you are given ",(0,s.jsx)(n.code,{children:"NULL"}),", return ",(0,s.jsx)(n.code,{children:"NULL"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Example (more in tests):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-c",children:'char* reversed = reverse("Hello world!");\n\nprintf("%s\\n", reversed);\n// "!DLROW OLLEH"\n\nif (reversed != NULL) {\n free(reversed);\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"task-no-2-vigen\xe8re-05-k",children:"Task no. 2: Vigen\xe8re (0.5 K\u20a1)"}),"\n",(0,s.jsx)(n.p,{children:"Vigen\xe8re cipher is similar to the Caesar cipher, but you also have a key that is\nused for encrypting (or decrypting)."}),"\n",(0,s.jsx)(n.p,{children:"Your task is to write two functions:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"char* vigenere_encrypt(const char* key, const char* text)"})," for encrypting"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"char* vigenere_decrypt(const char* key, const char* text)"})," for decrypting"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"In both of those you should return uppercase characters."}),"\n",(0,s.jsx)(n.p,{children:"Meaning of the parameters you are given:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"key"})," - String that represents key that is used for *crypting. It consists of\none word and can have only characters of the alphabet. Does not matter if they\nare uppercase or lowercase."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"text"})," - String that is to be *crypted."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Function returns address of the encrypted (or decrypted) string. Or ",(0,s.jsx)(n.code,{children:"NULL"})," in case\nerror occurs."]}),"\n",(0,s.jsx)(n.p,{children:"Example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-c",children:'char *encrypted = vigenere_encrypt("CoMPuTeR", "Hello world!");\n\nprintf("%s\\n", encrypted);\n// "JSXAI PSINR!"\n\nif (encrypted != NULL) {\n free(encrypted)\n}\n'})}),"\n",(0,s.jsx)(n.h4,{id:"bonus-part-05-k",children:"Bonus part (0.5 K\u20a1)"}),"\n",(0,s.jsx)(n.p,{children:"If you can utilize helper function that would do both encrypting and decrypting,\nyou can gain 0.5 K\u20a1."}),"\n",(0,s.jsxs)(n.p,{children:["Usage of ",(0,s.jsx)(n.code,{children:"true"}),"/",(0,s.jsx)(n.code,{children:"false"})," to decide path in code is prohibited. It leads to merging\nof both functions into one. Point of this part is to discover a way to do this\ngenerically in such way that there are no separate paths for one or the other. One\nfunction with no branching for both of them, parametrization is your friend :)"]}),"\n",(0,s.jsx)(n.h3,{id:"task-no-3-bit-madness-05-k",children:"Task no. 3: Bit madness (0.5 K\u20a1)"}),"\n",(0,s.jsx)(n.p,{children:"This is a state of the art crypto. Please do not share :)"}),"\n",(0,s.jsx)(n.p,{children:"For encrypting:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Split the character that is to be encrypted in halves (4 and 4 bits each)."}),"\n",(0,s.jsx)(n.li,{children:"Bits in 1st half are to be split into pairs. Swap bits in those pairs."}),"\n",(0,s.jsxs)(n.li,{children:["Then use the 4 bits that you created in the 2nd step for ",(0,s.jsx)(n.code,{children:"XOR"})," with the other\n4 bits."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["This simple and ingenious principle will be illustrated on the following example.\nString we want to encrypt is ",(0,s.jsx)(n.code,{children:"Hello world!"}),". We need to encrypt each letter separately,\nso we will demonstrate on letter ",(0,s.jsx)(n.code,{children:"H"}),":"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Letter ",(0,s.jsx)(n.code,{children:"H"})," is represented in ASCII as ",(0,s.jsx)(n.code,{children:"72"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"72"})," represented in binary is: ",(0,s.jsx)(n.code,{children:"01001000"}),". So first 4 bits are: ",(0,s.jsx)(n.code,{children:"0100"})," and last\n4 bits are ",(0,s.jsx)(n.code,{children:"1000"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["First half of bits (",(0,s.jsx)(n.code,{children:"0100"}),") consists of 2 pairs (",(0,s.jsx)(n.code,{children:"01"})," and ",(0,s.jsx)(n.code,{children:"00"}),") which we swap\n(",(0,s.jsx)(n.code,{children:"01 ~> 10"})," and ",(0,s.jsx)(n.code,{children:"00 ~> 00"}),"). That way we get ",(0,s.jsx)(n.code,{children:"1000"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"That half is used for xor with the other 4 bits:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:" 1000 // second half\nXOR 1000 // first half after 2nd step\n--------\n 0000\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Now we combine both halves (first one is ",(0,s.jsx)(n.code,{children:"1000"}),", which we got from the 2nd step\nand second one is ",(0,s.jsx)(n.code,{children:"0000"}),", which we got from the 3rd step) and get ",(0,s.jsx)(n.code,{children:"10000000"}),",\nwhich is encrypted character ",(0,s.jsx)(n.code,{children:"H"})," using this method."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"In case of decryption, reverse those steps."}),"\n",(0,s.jsx)(n.p,{children:"Your task is to implement functions:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"unsigned char* bit_encrypt(const char* text)"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"char* bit_decrypt(const unsigned char* text)"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-c",children:'unsigned char* encrypted = bit_encrypt("Hello world!");\n\nfor (int i = 0; i < 12;i++) {\n printf("%x ", encrypted[i]);\n //80 9c 95 95 96 11 bc 96 b9 95 9d 10\n}\n\nif (encrypted != NULL) {\n free(encrypted);\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"task-no-4-all-combined-to-bmp-05-k",children:"Task no. 4: All combined to BMP (0.5 K\u20a1)"}),"\n",(0,s.jsx)(n.p,{children:"Authors of the BMP cipher are non-disclosed :)"}),"\n",(0,s.jsx)(n.p,{children:"Create pair of functions:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"unsigned char* bmp_encrypt(const char* key, const char* text)"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"char* bmp_decrypt(const char* key, const unsigned char* text)"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"BMP cipher consists of following steps for encrypting:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Reverse the input string"}),"\n",(0,s.jsx)(n.li,{children:"Use Vigenere on the string you got from step #1"}),"\n",(0,s.jsx)(n.li,{children:"Use bit madness on the string you got from step #2"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"For decrypting, reverse the steps."}),"\n",(0,s.jsx)(n.h2,{id:"submitting",children:"Submitting"}),"\n",(0,s.jsx)(n.p,{children:"In case you have any questions, feel free to reach out to me."}),"\n",(0,s.jsx)(n.hr,{})]})}function a(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},11151:(e,n,r)=>{r.d(n,{Z:()=>o,a:()=>c});var s=r(67294);const t={},i=s.createContext(t);function c(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:c(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfi=self.webpackChunkfi||[]).push([[6544],{63004:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>a,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var s=r(85893),t=r(11151);const i={id:"seminar-05-06",title:"5th and 6th seminar",description:"200IQ encryption.\n"},c=void 0,o={id:"bonuses/seminar-05-06",title:"5th and 6th seminar",description:"200IQ encryption.\n",source:"@site/c/bonuses/05-06.md",sourceDirName:"bonuses",slug:"/bonuses/seminar-05-06",permalink:"/c/bonuses/seminar-05-06",draft:!1,unlisted:!1,editUrl:"https://github.com/mfocko/blog/tree/main/c/bonuses/05-06.md",tags:[],version:"current",lastUpdatedAt:1701199517,formattedLastUpdatedAt:"Nov 28, 2023",frontMatter:{id:"seminar-05-06",title:"5th and 6th seminar",description:"200IQ encryption.\n"},sidebar:"autogeneratedBar",previous:{title:"4th seminar",permalink:"/c/bonuses/seminar-04"},next:{title:"8th seminar",permalink:"/c/bonuses/seminar-08"}},d={},l=[{value:"Introduction",id:"introduction",level:2},{value:"Task no. 1: Reverse (0.5 K\u20a1)",id:"task-no-1-reverse-05-k",level:3},{value:"Task no. 2: Vigen\xe8re (0.5 K\u20a1)",id:"task-no-2-vigen\xe8re-05-k",level:3},{value:"Bonus part (0.5 K\u20a1)",id:"bonus-part-05-k",level:4},{value:"Task no. 3: Bit madness (0.5 K\u20a1)",id:"task-no-3-bit-madness-05-k",level:3},{value:"Task no. 4: All combined to BMP (0.5 K\u20a1)",id:"task-no-4-all-combined-to-bmp-05-k",level:3},{value:"Submitting",id:"submitting",level:2}];function h(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"For this bonus you can get at maximum 2.5 K\u20a1."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.a,{href:"pathname:///files/c/bonuses/05-06.tar.gz",children:"Source"})}),"\n",(0,s.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)(n.p,{children:"In this bonus you will implement few functions that will be used together for\nimplementing a very special cipher."}),"\n",(0,s.jsx)(n.h3,{id:"task-no-1-reverse-05-k",children:"Task no. 1: Reverse (0.5 K\u20a1)"}),"\n",(0,s.jsxs)(n.p,{children:["Write a function ",(0,s.jsx)(n.code,{children:"char* reverse(const char* text)"})," that returns copy of the input\nstring in reversed order (also uppercase)."]}),"\n",(0,s.jsxs)(n.p,{children:["In case you are given ",(0,s.jsx)(n.code,{children:"NULL"}),", return ",(0,s.jsx)(n.code,{children:"NULL"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Example (more in tests):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-c",children:'char* reversed = reverse("Hello world!");\n\nprintf("%s\\n", reversed);\n// "!DLROW OLLEH"\n\nif (reversed != NULL) {\n free(reversed);\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"task-no-2-vigen\xe8re-05-k",children:"Task no. 2: Vigen\xe8re (0.5 K\u20a1)"}),"\n",(0,s.jsx)(n.p,{children:"Vigen\xe8re cipher is similar to the Caesar cipher, but you also have a key that is\nused for encrypting (or decrypting)."}),"\n",(0,s.jsx)(n.p,{children:"Your task is to write two functions:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"char* vigenere_encrypt(const char* key, const char* text)"})," for encrypting"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"char* vigenere_decrypt(const char* key, const char* text)"})," for decrypting"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"In both of those you should return uppercase characters."}),"\n",(0,s.jsx)(n.p,{children:"Meaning of the parameters you are given:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"key"})," - String that represents key that is used for *crypting. It consists of\none word and can have only characters of the alphabet. Does not matter if they\nare uppercase or lowercase."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"text"})," - String that is to be *crypted."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Function returns address of the encrypted (or decrypted) string. Or ",(0,s.jsx)(n.code,{children:"NULL"})," in case\nerror occurs."]}),"\n",(0,s.jsx)(n.p,{children:"Example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-c",children:'char *encrypted = vigenere_encrypt("CoMPuTeR", "Hello world!");\n\nprintf("%s\\n", encrypted);\n// "JSXAI PSINR!"\n\nif (encrypted != NULL) {\n free(encrypted)\n}\n'})}),"\n",(0,s.jsx)(n.h4,{id:"bonus-part-05-k",children:"Bonus part (0.5 K\u20a1)"}),"\n",(0,s.jsx)(n.p,{children:"If you can utilize helper function that would do both encrypting and decrypting,\nyou can gain 0.5 K\u20a1."}),"\n",(0,s.jsxs)(n.p,{children:["Usage of ",(0,s.jsx)(n.code,{children:"true"}),"/",(0,s.jsx)(n.code,{children:"false"})," to decide path in code is prohibited. It leads to merging\nof both functions into one. Point of this part is to discover a way to do this\ngenerically in such way that there are no separate paths for one or the other. One\nfunction with no branching for both of them, parametrization is your friend :)"]}),"\n",(0,s.jsx)(n.h3,{id:"task-no-3-bit-madness-05-k",children:"Task no. 3: Bit madness (0.5 K\u20a1)"}),"\n",(0,s.jsx)(n.p,{children:"This is a state of the art crypto. Please do not share :)"}),"\n",(0,s.jsx)(n.p,{children:"For encrypting:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Split the character that is to be encrypted in halves (4 and 4 bits each)."}),"\n",(0,s.jsx)(n.li,{children:"Bits in 1st half are to be split into pairs. Swap bits in those pairs."}),"\n",(0,s.jsxs)(n.li,{children:["Then use the 4 bits that you created in the 2nd step for ",(0,s.jsx)(n.code,{children:"XOR"})," with the other\n4 bits."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["This simple and ingenious principle will be illustrated on the following example.\nString we want to encrypt is ",(0,s.jsx)(n.code,{children:"Hello world!"}),". We need to encrypt each letter separately,\nso we will demonstrate on letter ",(0,s.jsx)(n.code,{children:"H"}),":"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Letter ",(0,s.jsx)(n.code,{children:"H"})," is represented in ASCII as ",(0,s.jsx)(n.code,{children:"72"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"72"})," represented in binary is: ",(0,s.jsx)(n.code,{children:"01001000"}),". So first 4 bits are: ",(0,s.jsx)(n.code,{children:"0100"})," and last\n4 bits are ",(0,s.jsx)(n.code,{children:"1000"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["First half of bits (",(0,s.jsx)(n.code,{children:"0100"}),") consists of 2 pairs (",(0,s.jsx)(n.code,{children:"01"})," and ",(0,s.jsx)(n.code,{children:"00"}),") which we swap\n(",(0,s.jsx)(n.code,{children:"01 ~> 10"})," and ",(0,s.jsx)(n.code,{children:"00 ~> 00"}),"). That way we get ",(0,s.jsx)(n.code,{children:"1000"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"That half is used for xor with the other 4 bits:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:" 1000 // second half\nXOR 1000 // first half after 2nd step\n--------\n 0000\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Now we combine both halves (first one is ",(0,s.jsx)(n.code,{children:"1000"}),", which we got from the 2nd step\nand second one is ",(0,s.jsx)(n.code,{children:"0000"}),", which we got from the 3rd step) and get ",(0,s.jsx)(n.code,{children:"10000000"}),",\nwhich is encrypted character ",(0,s.jsx)(n.code,{children:"H"})," using this method."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"In case of decryption, reverse those steps."}),"\n",(0,s.jsx)(n.p,{children:"Your task is to implement functions:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"unsigned char* bit_encrypt(const char* text)"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"char* bit_decrypt(const unsigned char* text)"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-c",children:'unsigned char* encrypted = bit_encrypt("Hello world!");\n\nfor (int i = 0; i < 12;i++) {\n printf("%x ", encrypted[i]);\n //80 9c 95 95 96 11 bc 96 b9 95 9d 10\n}\n\nif (encrypted != NULL) {\n free(encrypted);\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"task-no-4-all-combined-to-bmp-05-k",children:"Task no. 4: All combined to BMP (0.5 K\u20a1)"}),"\n",(0,s.jsx)(n.p,{children:"Authors of the BMP cipher are non-disclosed :)"}),"\n",(0,s.jsx)(n.p,{children:"Create pair of functions:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"unsigned char* bmp_encrypt(const char* key, const char* text)"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"char* bmp_decrypt(const char* key, const unsigned char* text)"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"BMP cipher consists of following steps for encrypting:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Reverse the input string"}),"\n",(0,s.jsx)(n.li,{children:"Use Vigenere on the string you got from step #1"}),"\n",(0,s.jsx)(n.li,{children:"Use bit madness on the string you got from step #2"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"For decrypting, reverse the steps."}),"\n",(0,s.jsx)(n.h2,{id:"submitting",children:"Submitting"}),"\n",(0,s.jsx)(n.p,{children:"In case you have any questions, feel free to reach out to me."}),"\n",(0,s.jsx)(n.hr,{})]})}function a(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},11151:(e,n,r)=>{r.d(n,{Z:()=>o,a:()=>c});var s=r(67294);const t={},i=s.createContext(t);function c(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:c(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.f17742ff.js b/assets/js/runtime~main.306284ce.js similarity index 94% rename from assets/js/runtime~main.f17742ff.js rename to assets/js/runtime~main.306284ce.js index 38dafea..3061bda 100644 --- a/assets/js/runtime~main.f17742ff.js +++ b/assets/js/runtime~main.306284ce.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,c,f,b={},d={};function t(e){var a=d[e];if(void 0!==a)return a.exports;var c=d[e]={exports:{}};return b[e].call(c.exports,c,c.exports,t),c.exports}t.m=b,e=[],t.O=(a,c,f,b)=>{if(!c){var d=1/0;for(i=0;i=b)&&Object.keys(t.O).every((e=>t.O[e](c[o])))?c.splice(o--,1):(r=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[c,f,b]},t.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return t.d(a,{a:a}),a},c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,t.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var b=Object.create(null);t.r(b);var d={};a=a||[null,c({}),c([]),c(c)];for(var r=2&f&&e;"object"==typeof r&&!~a.indexOf(r);r=c(r))Object.getOwnPropertyNames(r).forEach((a=>d[a]=()=>e[a]));return d.default=()=>e,t.d(b,d),b},t.d=(e,a)=>{for(var c in a)t.o(a,c)&&!t.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((a,c)=>(t.f[c](e,a),a)),[])),t.u=e=>"assets/js/"+({59:"b1288602",146:"dff2ebad",354:"bc0c9d90",494:"1a606400",569:"ddc7679f",655:"9a3dc578",728:"686a7a89",822:"8c0e532b",866:"4200b1a9",1011:"377f3aa1",1050:"a7098721",1145:"947341b7",1171:"d7f7fb17",1235:"86cd1460",1353:"d1aceb2e",1378:"0220f5fc",1464:"97a42631",1475:"e1d2ae23",1492:"d4b1e057",1494:"16cbc838",1648:"48b268a6",1851:"0fcbc6ca",1885:"84d1e0d8",1960:"e31003e9",2125:"06c4a8fc",2177:"3da4b779",2210:"9df0e937",2264:"962da50c",2433:"b5a32f14",2445:"decbf9d1",2482:"dd841e73",2619:"5fe5d476",2741:"d675395f",2997:"d8f4410e",3039:"765ea78b",3086:"cfa2b263",3089:"a6aa9e1f",3184:"7e6d325b",3220:"34ab65f4",3276:"6e3cbca1",3388:"29694455",3519:"4621632b",3561:"95b96bb9",3608:"9e4087bc",3618:"a6a48ea2",3707:"24fecc0a",3731:"087808f1",3734:"0123bc76",3751:"3720c009",3803:"794ef108",3887:"933b95b3",4013:"01a85c17",4064:"f48be158",4195:"c4f5d8e4",4256:"75cccf44",4269:"0bfe45d5",4327:"4e546705",4343:"df0885f0",4368:"a94703ab",4382:"a4c10cf4",4394:"51624505",4562:"976c4f3b",4637:"19d7c045",4638:"2fcf0558",5169:"d79dd549",5287:"6bc697d0",5376:"1535ede8",5430:"52f2a5bf",5521:"9287eafd",5634:"595c7293",5658:"af8b72a7",5775:"8e6bb954",5824:"a80747a0",5975:"4edd2021",6097:"b0291f37",6103:"ccc49370",6179:"d57b4369",6292:"d255bd7f",6306:"4f96b16e",6327:"fb4361d3",6342:"2b89902a",6435:"28d80ff8",6519:"bc2d22bc",6544:"d05e838c",6573:"c580b66a",6864:"bb984793",6890:"22a175ec",7084:"45c9e308",7257:"aa24fd5d",7438:"b8cbf382",7568:"0608d96f",7755:"ab2721d4",7918:"17896441",7920:"1a4e3797",7926:"3011a4c0",8058:"520f8175",8091:"bb882650",8326:"15966941",8387:"eba2374c",8472:"ff82dde7",8480:"8b1802c5",8518:"a7bd4aaa",8520:"62d847b3",8529:"1acf65cc",8610:"6875c492",8643:"ff472cd9",8757:"e89da83e",8786:"a082abd3",8807:"dead8108",8908:"d309b5b1",9066:"8d31a880",9173:"5ca803d2",9179:"b9f7f5c4",9197:"b25fbc58",9228:"66d5ef6c",9300:"146d9b84",9385:"95f41f0b",9414:"354a7b72",9661:"5e95c892",9679:"b45dccf0",9731:"7052c0bc",9771:"534d4833",9817:"14eb3368",9898:"0178f9ad",9924:"df203c0f"}[e]||e)+"."+{59:"9d3ae1e4",109:"192a1082",130:"aaabb811",132:"6eeb92f1",146:"2596a554",240:"962c2c3a",354:"22532279",494:"9499d809",569:"4b5bdacd",655:"07cb1f6c",728:"ebbeda14",822:"8df94607",866:"faadd2c9",1011:"4ebbc06f",1050:"33f429e4",1145:"06e92a4d",1171:"3796c0b9",1235:"f549d2c3",1325:"fc0073e5",1353:"3f8e795e",1378:"6bd42e59",1426:"5a43a299",1464:"f6ad4dc0",1475:"2bc6580d",1492:"c26d5bb6",1494:"eafc393a",1504:"972c6306",1644:"e1df3952",1648:"56c72f30",1763:"dd6ac9f1",1772:"7702e9c0",1851:"24ec8bc7",1885:"2391d00c",1960:"e9396e0a",2125:"18eb9afc",2177:"1354e52a",2183:"695e6dce",2210:"2c53d1aa",2264:"ea10811e",2433:"68cedca8",2445:"369aa5a6",2482:"9e9c9dbf",2619:"f7c213ae",2661:"adb036a5",2693:"86767de9",2696:"9c4ce6ae",2700:"eb54ab23",2741:"1f389aac",2997:"e8838bb3",3039:"29a37caf",3076:"0d102429",3086:"efd5103c",3089:"75141289",3184:"0dc3275f",3220:"5fa3179c",3276:"a0392349",3343:"c68ed9e0",3388:"5fa079ce",3519:"bd86e6e4",3561:"f1e9070e",3608:"b07604ed",3618:"7749d78c",3619:"169a66d1",3707:"0d18355b",3731:"0a5fb140",3734:"d7742152",3751:"f4cf5d33",3803:"ed8ed4b7",3887:"05a0e2a2",4013:"57ba4b21",4064:"5e2dd98c",4195:"5d3c1d6d",4238:"732f7e6d",4256:"b0cfb80e",4269:"143f3da4",4327:"40303d4d",4343:"2970a5ee",4368:"5939a7a6",4382:"e91bee7a",4394:"60fbe3b9",4562:"8c7c9f5c",4637:"fd298b3d",4638:"14a64e69",4706:"bf286a6c",5169:"0ed0fe01",5269:"a9818fb6",5287:"410760a1",5326:"480380dd",5376:"550c1ca8",5430:"839d7f40",5521:"7613dea7",5634:"4258c254",5658:"37a3aa6c",5775:"967c2127",5790:"a9566ed9",5824:"b21945df",5943:"ebdacf10",5975:"ba1a6e92",6097:"5b91d377",6103:"92d892f3",6179:"6f772ce2",6255:"4bb462ce",6292:"da5efa5d",6306:"072f92b8",6327:"7b58c634",6342:"cec021fa",6435:"b8c94f5a",6519:"36b6ca38",6544:"1b2f4a74",6573:"53c3dc84",6648:"7d3c04e0",6864:"0560af7f",6890:"ebe0aeb7",6945:"1665fd21",6985:"b22ddd47",7084:"57b8321c",7257:"a1be9355",7438:"b92ec171",7568:"a18c3650",7755:"6fad72ba",7918:"0840295c",7920:"4e3726f1",7926:"bfa0084e",7936:"da5208cb",8016:"f7e4e334",8058:"85515c7b",8091:"6eee4002",8326:"58ddb6d9",8387:"71f2685d",8472:"e3161817",8480:"408315a3",8518:"69e4c2b5",8520:"ea246a7d",8529:"33171995",8610:"d5bd7daa",8643:"a09aa523",8757:"1856d5b6",8786:"6458a62f",8807:"9d966504",8894:"bbb1746a",8908:"924b0302",8955:"88257d8a",9066:"d72d8191",9138:"6232b886",9173:"986e22d4",9179:"8dd00486",9197:"90e65bfc",9228:"fc107ca5",9300:"bdf83d64",9385:"b012cd5f",9414:"257f6430",9661:"ea0b11d7",9679:"7ab0cc2a",9731:"beae1b38",9771:"162e2ecd",9817:"8ed8ad48",9893:"04fdeb2a",9898:"568886e5",9924:"12cfbe9e"}[e]+".js",t.miniCssF=e=>{},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),t.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),f={},t.l=(e,a,c,b)=>{if(f[e])f[e].push(a);else{var d,r;if(void 0!==c)for(var o=document.getElementsByTagName("script"),n=0;n{d.onerror=d.onload=null,clearTimeout(l);var b=f[e];if(delete f[e],d.parentNode&&d.parentNode.removeChild(d),b&&b.forEach((e=>e(c))),a)return a(c)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=u.bind(null,d.onerror),d.onload=u.bind(null,d.onload),r&&document.head.appendChild(d)}},t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.p="/",t.gca=function(e){return e={15966941:"8326",17896441:"7918",29694455:"3388",51624505:"4394",b1288602:"59",dff2ebad:"146",bc0c9d90:"354","1a606400":"494",ddc7679f:"569","9a3dc578":"655","686a7a89":"728","8c0e532b":"822","4200b1a9":"866","377f3aa1":"1011",a7098721:"1050","947341b7":"1145",d7f7fb17:"1171","86cd1460":"1235",d1aceb2e:"1353","0220f5fc":"1378","97a42631":"1464",e1d2ae23:"1475",d4b1e057:"1492","16cbc838":"1494","48b268a6":"1648","0fcbc6ca":"1851","84d1e0d8":"1885",e31003e9:"1960","06c4a8fc":"2125","3da4b779":"2177","9df0e937":"2210","962da50c":"2264",b5a32f14:"2433",decbf9d1:"2445",dd841e73:"2482","5fe5d476":"2619",d675395f:"2741",d8f4410e:"2997","765ea78b":"3039",cfa2b263:"3086",a6aa9e1f:"3089","7e6d325b":"3184","34ab65f4":"3220","6e3cbca1":"3276","4621632b":"3519","95b96bb9":"3561","9e4087bc":"3608",a6a48ea2:"3618","24fecc0a":"3707","087808f1":"3731","0123bc76":"3734","3720c009":"3751","794ef108":"3803","933b95b3":"3887","01a85c17":"4013",f48be158:"4064",c4f5d8e4:"4195","75cccf44":"4256","0bfe45d5":"4269","4e546705":"4327",df0885f0:"4343",a94703ab:"4368",a4c10cf4:"4382","976c4f3b":"4562","19d7c045":"4637","2fcf0558":"4638",d79dd549:"5169","6bc697d0":"5287","1535ede8":"5376","52f2a5bf":"5430","9287eafd":"5521","595c7293":"5634",af8b72a7:"5658","8e6bb954":"5775",a80747a0:"5824","4edd2021":"5975",b0291f37:"6097",ccc49370:"6103",d57b4369:"6179",d255bd7f:"6292","4f96b16e":"6306",fb4361d3:"6327","2b89902a":"6342","28d80ff8":"6435",bc2d22bc:"6519",d05e838c:"6544",c580b66a:"6573",bb984793:"6864","22a175ec":"6890","45c9e308":"7084",aa24fd5d:"7257",b8cbf382:"7438","0608d96f":"7568",ab2721d4:"7755","1a4e3797":"7920","3011a4c0":"7926","520f8175":"8058",bb882650:"8091",eba2374c:"8387",ff82dde7:"8472","8b1802c5":"8480",a7bd4aaa:"8518","62d847b3":"8520","1acf65cc":"8529","6875c492":"8610",ff472cd9:"8643",e89da83e:"8757",a082abd3:"8786",dead8108:"8807",d309b5b1:"8908","8d31a880":"9066","5ca803d2":"9173",b9f7f5c4:"9179",b25fbc58:"9197","66d5ef6c":"9228","146d9b84":"9300","95f41f0b":"9385","354a7b72":"9414","5e95c892":"9661",b45dccf0:"9679","7052c0bc":"9731","534d4833":"9771","14eb3368":"9817","0178f9ad":"9898",df203c0f:"9924"}[e]||e,t.p+t.u(e)},(()=>{var e={1303:0,532:0};t.f.j=(a,c)=>{var f=t.o(e,a)?e[a]:void 0;if(0!==f)if(f)c.push(f[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var b=new Promise(((c,b)=>f=e[a]=[c,b]));c.push(f[2]=b);var d=t.p+t.u(a),r=new Error;t.l(d,(c=>{if(t.o(e,a)&&(0!==(f=e[a])&&(e[a]=void 0),f)){var b=c&&("load"===c.type?"missing":c.type),d=c&&c.target&&c.target.src;r.message="Loading chunk "+a+" failed.\n("+b+": "+d+")",r.name="ChunkLoadError",r.type=b,r.request=d,f[1](r)}}),"chunk-"+a,a)}},t.O.j=a=>0===e[a];var a=(a,c)=>{var f,b,d=c[0],r=c[1],o=c[2],n=0;if(d.some((a=>0!==e[a]))){for(f in r)t.o(r,f)&&(t.m[f]=r[f]);if(o)var i=o(t)}for(a&&a(c);n{"use strict";var e,a,c,f,b={},d={};function t(e){var a=d[e];if(void 0!==a)return a.exports;var c=d[e]={exports:{}};return b[e].call(c.exports,c,c.exports,t),c.exports}t.m=b,e=[],t.O=(a,c,f,b)=>{if(!c){var d=1/0;for(i=0;i=b)&&Object.keys(t.O).every((e=>t.O[e](c[o])))?c.splice(o--,1):(r=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[c,f,b]},t.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return t.d(a,{a:a}),a},c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,t.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var b=Object.create(null);t.r(b);var d={};a=a||[null,c({}),c([]),c(c)];for(var r=2&f&&e;"object"==typeof r&&!~a.indexOf(r);r=c(r))Object.getOwnPropertyNames(r).forEach((a=>d[a]=()=>e[a]));return d.default=()=>e,t.d(b,d),b},t.d=(e,a)=>{for(var c in a)t.o(a,c)&&!t.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((a,c)=>(t.f[c](e,a),a)),[])),t.u=e=>"assets/js/"+({59:"b1288602",146:"dff2ebad",354:"bc0c9d90",494:"1a606400",569:"ddc7679f",655:"9a3dc578",728:"686a7a89",822:"8c0e532b",866:"4200b1a9",1011:"377f3aa1",1050:"a7098721",1145:"947341b7",1171:"d7f7fb17",1235:"86cd1460",1353:"d1aceb2e",1378:"0220f5fc",1464:"97a42631",1475:"e1d2ae23",1492:"d4b1e057",1494:"16cbc838",1648:"48b268a6",1851:"0fcbc6ca",1885:"84d1e0d8",1960:"e31003e9",2125:"06c4a8fc",2177:"3da4b779",2210:"9df0e937",2264:"962da50c",2433:"b5a32f14",2445:"decbf9d1",2482:"dd841e73",2619:"5fe5d476",2741:"d675395f",2997:"d8f4410e",3039:"765ea78b",3086:"cfa2b263",3089:"a6aa9e1f",3184:"7e6d325b",3220:"34ab65f4",3276:"6e3cbca1",3388:"29694455",3519:"4621632b",3561:"95b96bb9",3608:"9e4087bc",3618:"a6a48ea2",3707:"24fecc0a",3731:"087808f1",3734:"0123bc76",3751:"3720c009",3803:"794ef108",3887:"933b95b3",4013:"01a85c17",4064:"f48be158",4195:"c4f5d8e4",4256:"75cccf44",4269:"0bfe45d5",4327:"4e546705",4343:"df0885f0",4368:"a94703ab",4382:"a4c10cf4",4394:"51624505",4562:"976c4f3b",4637:"19d7c045",4638:"2fcf0558",5169:"d79dd549",5287:"6bc697d0",5376:"1535ede8",5430:"52f2a5bf",5521:"9287eafd",5634:"595c7293",5658:"af8b72a7",5775:"8e6bb954",5824:"a80747a0",5975:"4edd2021",6097:"b0291f37",6103:"ccc49370",6179:"d57b4369",6292:"d255bd7f",6306:"4f96b16e",6327:"fb4361d3",6342:"2b89902a",6435:"28d80ff8",6519:"bc2d22bc",6544:"d05e838c",6573:"c580b66a",6864:"bb984793",6890:"22a175ec",7084:"45c9e308",7257:"aa24fd5d",7438:"b8cbf382",7568:"0608d96f",7755:"ab2721d4",7918:"17896441",7920:"1a4e3797",7926:"3011a4c0",8058:"520f8175",8091:"bb882650",8326:"15966941",8387:"eba2374c",8472:"ff82dde7",8480:"8b1802c5",8518:"a7bd4aaa",8520:"62d847b3",8529:"1acf65cc",8610:"6875c492",8643:"ff472cd9",8757:"e89da83e",8786:"a082abd3",8807:"dead8108",8908:"d309b5b1",9066:"8d31a880",9173:"5ca803d2",9179:"b9f7f5c4",9197:"b25fbc58",9228:"66d5ef6c",9300:"146d9b84",9385:"95f41f0b",9414:"354a7b72",9661:"5e95c892",9679:"b45dccf0",9731:"7052c0bc",9771:"534d4833",9817:"14eb3368",9898:"0178f9ad",9924:"df203c0f"}[e]||e)+"."+{59:"2548704d",109:"192a1082",130:"aaabb811",132:"6eeb92f1",146:"2596a554",240:"962c2c3a",354:"22532279",494:"9499d809",569:"4b5bdacd",655:"07cb1f6c",728:"ebbeda14",822:"8df94607",866:"faadd2c9",1011:"4ebbc06f",1050:"33f429e4",1145:"06e92a4d",1171:"3796c0b9",1235:"f549d2c3",1325:"fc0073e5",1353:"3f8e795e",1378:"6bd42e59",1426:"5a43a299",1464:"f6ad4dc0",1475:"2bc6580d",1492:"c26d5bb6",1494:"eafc393a",1504:"972c6306",1644:"e1df3952",1648:"56c72f30",1763:"dd6ac9f1",1772:"7702e9c0",1851:"24ec8bc7",1885:"7240ea58",1960:"e9396e0a",2125:"18eb9afc",2177:"1354e52a",2183:"695e6dce",2210:"2c53d1aa",2264:"ea10811e",2433:"68cedca8",2445:"369aa5a6",2482:"9e9c9dbf",2619:"73f34dd7",2661:"adb036a5",2693:"86767de9",2696:"9c4ce6ae",2700:"eb54ab23",2741:"1f389aac",2997:"e8838bb3",3039:"29a37caf",3076:"0d102429",3086:"efd5103c",3089:"75141289",3184:"0dc3275f",3220:"5fa3179c",3276:"a0392349",3343:"c68ed9e0",3388:"5fa079ce",3519:"bd86e6e4",3561:"f1e9070e",3608:"b07604ed",3618:"7749d78c",3619:"169a66d1",3707:"0d18355b",3731:"0a5fb140",3734:"d7742152",3751:"f4cf5d33",3803:"166aea3d",3887:"05a0e2a2",4013:"57ba4b21",4064:"5e2dd98c",4195:"5d3c1d6d",4238:"732f7e6d",4256:"b0cfb80e",4269:"143f3da4",4327:"40303d4d",4343:"2970a5ee",4368:"5939a7a6",4382:"e91bee7a",4394:"60fbe3b9",4562:"8c7c9f5c",4637:"fd298b3d",4638:"14a64e69",4706:"bf286a6c",5169:"0ed0fe01",5269:"a9818fb6",5287:"410760a1",5326:"480380dd",5376:"2f775329",5430:"839d7f40",5521:"7613dea7",5634:"8e9a4314",5658:"37a3aa6c",5775:"967c2127",5790:"a9566ed9",5824:"b21945df",5943:"ebdacf10",5975:"ba1a6e92",6097:"5b91d377",6103:"92d892f3",6179:"6f772ce2",6255:"4bb462ce",6292:"da5efa5d",6306:"072f92b8",6327:"7b58c634",6342:"cec021fa",6435:"b8c94f5a",6519:"36b6ca38",6544:"ac17e06f",6573:"53c3dc84",6648:"7d3c04e0",6864:"0560af7f",6890:"ebe0aeb7",6945:"1665fd21",6985:"b22ddd47",7084:"57b8321c",7257:"143c547f",7438:"b92ec171",7568:"a18c3650",7755:"6fad72ba",7918:"0840295c",7920:"4e3726f1",7926:"bfa0084e",7936:"da5208cb",8016:"f7e4e334",8058:"85515c7b",8091:"6eee4002",8326:"58ddb6d9",8387:"71f2685d",8472:"e3161817",8480:"408315a3",8518:"69e4c2b5",8520:"ea246a7d",8529:"33171995",8610:"d5bd7daa",8643:"a09aa523",8757:"1856d5b6",8786:"6458a62f",8807:"9d966504",8894:"bbb1746a",8908:"924b0302",8955:"88257d8a",9066:"d72d8191",9138:"6232b886",9173:"986e22d4",9179:"8dd00486",9197:"90e65bfc",9228:"fc107ca5",9300:"bdf83d64",9385:"b012cd5f",9414:"257f6430",9661:"ea0b11d7",9679:"7ab0cc2a",9731:"7402024f",9771:"162e2ecd",9817:"8ed8ad48",9893:"04fdeb2a",9898:"568886e5",9924:"12cfbe9e"}[e]+".js",t.miniCssF=e=>{},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),t.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),f={},t.l=(e,a,c,b)=>{if(f[e])f[e].push(a);else{var d,r;if(void 0!==c)for(var o=document.getElementsByTagName("script"),n=0;n{d.onerror=d.onload=null,clearTimeout(l);var b=f[e];if(delete f[e],d.parentNode&&d.parentNode.removeChild(d),b&&b.forEach((e=>e(c))),a)return a(c)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=u.bind(null,d.onerror),d.onload=u.bind(null,d.onload),r&&document.head.appendChild(d)}},t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.p="/",t.gca=function(e){return e={15966941:"8326",17896441:"7918",29694455:"3388",51624505:"4394",b1288602:"59",dff2ebad:"146",bc0c9d90:"354","1a606400":"494",ddc7679f:"569","9a3dc578":"655","686a7a89":"728","8c0e532b":"822","4200b1a9":"866","377f3aa1":"1011",a7098721:"1050","947341b7":"1145",d7f7fb17:"1171","86cd1460":"1235",d1aceb2e:"1353","0220f5fc":"1378","97a42631":"1464",e1d2ae23:"1475",d4b1e057:"1492","16cbc838":"1494","48b268a6":"1648","0fcbc6ca":"1851","84d1e0d8":"1885",e31003e9:"1960","06c4a8fc":"2125","3da4b779":"2177","9df0e937":"2210","962da50c":"2264",b5a32f14:"2433",decbf9d1:"2445",dd841e73:"2482","5fe5d476":"2619",d675395f:"2741",d8f4410e:"2997","765ea78b":"3039",cfa2b263:"3086",a6aa9e1f:"3089","7e6d325b":"3184","34ab65f4":"3220","6e3cbca1":"3276","4621632b":"3519","95b96bb9":"3561","9e4087bc":"3608",a6a48ea2:"3618","24fecc0a":"3707","087808f1":"3731","0123bc76":"3734","3720c009":"3751","794ef108":"3803","933b95b3":"3887","01a85c17":"4013",f48be158:"4064",c4f5d8e4:"4195","75cccf44":"4256","0bfe45d5":"4269","4e546705":"4327",df0885f0:"4343",a94703ab:"4368",a4c10cf4:"4382","976c4f3b":"4562","19d7c045":"4637","2fcf0558":"4638",d79dd549:"5169","6bc697d0":"5287","1535ede8":"5376","52f2a5bf":"5430","9287eafd":"5521","595c7293":"5634",af8b72a7:"5658","8e6bb954":"5775",a80747a0:"5824","4edd2021":"5975",b0291f37:"6097",ccc49370:"6103",d57b4369:"6179",d255bd7f:"6292","4f96b16e":"6306",fb4361d3:"6327","2b89902a":"6342","28d80ff8":"6435",bc2d22bc:"6519",d05e838c:"6544",c580b66a:"6573",bb984793:"6864","22a175ec":"6890","45c9e308":"7084",aa24fd5d:"7257",b8cbf382:"7438","0608d96f":"7568",ab2721d4:"7755","1a4e3797":"7920","3011a4c0":"7926","520f8175":"8058",bb882650:"8091",eba2374c:"8387",ff82dde7:"8472","8b1802c5":"8480",a7bd4aaa:"8518","62d847b3":"8520","1acf65cc":"8529","6875c492":"8610",ff472cd9:"8643",e89da83e:"8757",a082abd3:"8786",dead8108:"8807",d309b5b1:"8908","8d31a880":"9066","5ca803d2":"9173",b9f7f5c4:"9179",b25fbc58:"9197","66d5ef6c":"9228","146d9b84":"9300","95f41f0b":"9385","354a7b72":"9414","5e95c892":"9661",b45dccf0:"9679","7052c0bc":"9731","534d4833":"9771","14eb3368":"9817","0178f9ad":"9898",df203c0f:"9924"}[e]||e,t.p+t.u(e)},(()=>{var e={1303:0,532:0};t.f.j=(a,c)=>{var f=t.o(e,a)?e[a]:void 0;if(0!==f)if(f)c.push(f[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var b=new Promise(((c,b)=>f=e[a]=[c,b]));c.push(f[2]=b);var d=t.p+t.u(a),r=new Error;t.l(d,(c=>{if(t.o(e,a)&&(0!==(f=e[a])&&(e[a]=void 0),f)){var b=c&&("load"===c.type?"missing":c.type),d=c&&c.target&&c.target.src;r.message="Loading chunk "+a+" failed.\n("+b+": "+d+")",r.name="ChunkLoadError",r.type=b,r.request=d,f[1](r)}}),"chunk-"+a,a)}},t.O.j=a=>0===e[a];var a=(a,c)=>{var f,b,d=c[0],r=c[1],o=c[2],n=0;if(d.some((a=>0!==e[a]))){for(f in r)t.o(r,f)&&(t.m[f]=r[f]);if(o)var i=o(t)}for(a&&a(c);n - + diff --git a/blog/aoc-2022/1st-week/index.html b/blog/aoc-2022/1st-week/index.html index e9ff838..b856d4f 100644 --- a/blog/aoc-2022/1st-week/index.html +++ b/blog/aoc-2022/1st-week/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/aoc-2022/2nd-week/index.html b/blog/aoc-2022/2nd-week/index.html index d50932d..62dc912 100644 --- a/blog/aoc-2022/2nd-week/index.html +++ b/blog/aoc-2022/2nd-week/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/aoc-2022/3rd-week/index.html b/blog/aoc-2022/3rd-week/index.html index e3a5785..4919e61 100644 --- a/blog/aoc-2022/3rd-week/index.html +++ b/blog/aoc-2022/3rd-week/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/aoc-2022/4th-week/index.html b/blog/aoc-2022/4th-week/index.html index 964becf..3b6c858 100644 --- a/blog/aoc-2022/4th-week/index.html +++ b/blog/aoc-2022/4th-week/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/aoc-2022/intro/index.html b/blog/aoc-2022/intro/index.html index a76ea62..b659f62 100644 --- a/blog/aoc-2022/intro/index.html +++ b/blog/aoc-2022/intro/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/archive/index.html b/blog/archive/index.html index 5457610..783fc26 100644 --- a/blog/archive/index.html +++ b/blog/archive/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/index.html b/blog/index.html index aa93677..a26972b 100644 --- a/blog/index.html +++ b/blog/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/leetcode/sort-diagonally/index.html b/blog/leetcode/sort-diagonally/index.html index 53a4b1a..86668ec 100644 --- a/blog/leetcode/sort-diagonally/index.html +++ b/blog/leetcode/sort-diagonally/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/admin/index.html b/blog/tags/admin/index.html index a9e6bba..8debf90 100644 --- a/blog/tags/admin/index.html +++ b/blog/tags/admin/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/advent-of-code-2022/index.html b/blog/tags/advent-of-code-2022/index.html index dd7413a..163e4c3 100644 --- a/blog/tags/advent-of-code-2022/index.html +++ b/blog/tags/advent-of-code-2022/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/advent-of-code/index.html b/blog/tags/advent-of-code/index.html index 09f4e5f..20f32d8 100644 --- a/blog/tags/advent-of-code/index.html +++ b/blog/tags/advent-of-code/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/copr/index.html b/blog/tags/copr/index.html index 7988eb8..e6c67a8 100644 --- a/blog/tags/copr/index.html +++ b/blog/tags/copr/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/cpp/index.html b/blog/tags/cpp/index.html index 59843dc..f7eab32 100644 --- a/blog/tags/cpp/index.html +++ b/blog/tags/cpp/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/index.html b/blog/tags/index.html index 0f1592a..03790a8 100644 --- a/blog/tags/index.html +++ b/blog/tags/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/iterators/index.html b/blog/tags/iterators/index.html index 52f159b..25e36a8 100644 --- a/blog/tags/iterators/index.html +++ b/blog/tags/iterators/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/leetcode/index.html b/blog/tags/leetcode/index.html index e4cf916..ff6d45d 100644 --- a/blog/tags/leetcode/index.html +++ b/blog/tags/leetcode/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/red-hat/index.html b/blog/tags/red-hat/index.html index cbda3b3..31ceb2c 100644 --- a/blog/tags/red-hat/index.html +++ b/blog/tags/red-hat/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/rust/index.html b/blog/tags/rust/index.html index 8fbcc6d..6146950 100644 --- a/blog/tags/rust/index.html +++ b/blog/tags/rust/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/vps/index.html b/blog/tags/vps/index.html index 11c5e66..2c87bbd 100644 --- a/blog/tags/vps/index.html +++ b/blog/tags/vps/index.html @@ -14,7 +14,7 @@ - + diff --git a/blog/tags/🏭/index.html b/blog/tags/🏭/index.html index 779201d..7c74791 100644 --- a/blog/tags/🏭/index.html +++ b/blog/tags/🏭/index.html @@ -14,7 +14,7 @@ - + diff --git a/c/bonuses/seminar-03/index.html b/c/bonuses/seminar-03/index.html index a50ae6d..0c4a525 100644 --- a/c/bonuses/seminar-03/index.html +++ b/c/bonuses/seminar-03/index.html @@ -16,7 +16,7 @@ - + diff --git a/c/bonuses/seminar-04/index.html b/c/bonuses/seminar-04/index.html index 20f0e1f..2108972 100644 --- a/c/bonuses/seminar-04/index.html +++ b/c/bonuses/seminar-04/index.html @@ -16,7 +16,7 @@ - + diff --git a/c/bonuses/seminar-05-06/index.html b/c/bonuses/seminar-05-06/index.html index 2dea6b4..ce84a22 100644 --- a/c/bonuses/seminar-05-06/index.html +++ b/c/bonuses/seminar-05-06/index.html @@ -16,7 +16,7 @@ - + @@ -114,6 +114,6 @@ which is encrypted character H using this method.

For decrypting, reverse the steps.

Submitting

In case you have any questions, feel free to reach out to me.

-
+
\ No newline at end of file diff --git a/c/bonuses/seminar-08/index.html b/c/bonuses/seminar-08/index.html index b834067..626d78c 100644 --- a/c/bonuses/seminar-08/index.html +++ b/c/bonuses/seminar-08/index.html @@ -16,7 +16,7 @@ - + @@ -94,6 +94,6 @@ Implementation and format of the pretty-print is totally up to you. :)

Submitting

In case you have any questions, feel free to reach out to me.

-
+
\ No newline at end of file diff --git a/c/bonuses/seminar-10/index.html b/c/bonuses/seminar-10/index.html index cc3601d..cf8d9fb 100644 --- a/c/bonuses/seminar-10/index.html +++ b/c/bonuses/seminar-10/index.html @@ -16,7 +16,7 @@ - + @@ -136,6 +136,6 @@ it is a not requirement at all and you can still get all points for the bonus ;)

Submitting

In case you have any questions, feel free to reach out to me.

-
+
\ No newline at end of file diff --git a/c/category/bonuses/index.html b/c/category/bonuses/index.html index ade465e..5fdb844 100644 --- a/c/category/bonuses/index.html +++ b/c/category/bonuses/index.html @@ -16,7 +16,7 @@ - + diff --git a/c/category/practice-exams/index.html b/c/category/practice-exams/index.html index ecf5a35..7defdca 100644 --- a/c/category/practice-exams/index.html +++ b/c/category/practice-exams/index.html @@ -16,7 +16,7 @@ - + diff --git a/c/index.html b/c/index.html index d06490d..7f06891 100644 --- a/c/index.html +++ b/c/index.html @@ -14,10 +14,10 @@ - + - + \ No newline at end of file diff --git a/c/mr/index.html b/c/mr/index.html index b1c8c5b..721c2e6 100644 --- a/c/mr/index.html +++ b/c/mr/index.html @@ -14,7 +14,7 @@ - + @@ -87,6 +87,6 @@ For the sake of safety, do not continue without clean repository. Then with comm be main or trunk.

aisa$ git status
# Check if repository is clean

# If you know, what is your default branch, you can skip next command.
aisa$ git branch
# Find the default branch in the list; should be one of the `master`, `main` or
# `trunk` and you should not have more than one of those.
# In case the list clears the terminal and you cannot see shell prompt, you can
# press `q` to quit the pager.

aisa$ git checkout master

-

Adapted from: https://www.fi.muni.cz/~xlacko1/pb071/mr.html

+

Adapted from: https://www.fi.muni.cz/~xlacko1/pb071/mr.html

\ No newline at end of file diff --git a/c/pexam/cams/index.html b/c/pexam/cams/index.html index 26932df..e257274 100644 --- a/c/pexam/cams/index.html +++ b/c/pexam/cams/index.html @@ -16,7 +16,7 @@ - + diff --git a/c/pexam/garbage_collect/index.html b/c/pexam/garbage_collect/index.html index be2d63c..8d6c973 100644 --- a/c/pexam/garbage_collect/index.html +++ b/c/pexam/garbage_collect/index.html @@ -16,7 +16,7 @@ - + diff --git a/contributions/index.html b/contributions/index.html index d63617b..135ed98 100644 --- a/contributions/index.html +++ b/contributions/index.html @@ -14,7 +14,7 @@ - + diff --git a/cpp/category/exceptions-and-raii/index.html b/cpp/category/exceptions-and-raii/index.html index 338a13a..ec16317 100644 --- a/cpp/category/exceptions-and-raii/index.html +++ b/cpp/category/exceptions-and-raii/index.html @@ -16,7 +16,7 @@ - + diff --git a/cpp/environment/index.html b/cpp/environment/index.html index b7595ed..8d70482 100644 --- a/cpp/environment/index.html +++ b/cpp/environment/index.html @@ -16,7 +16,7 @@ - + diff --git a/cpp/exceptions-and-raii/placeholders/index.html b/cpp/exceptions-and-raii/placeholders/index.html index 1ad373b..99be4da 100644 --- a/cpp/exceptions-and-raii/placeholders/index.html +++ b/cpp/exceptions-and-raii/placeholders/index.html @@ -16,7 +16,7 @@ - + diff --git a/cpp/index.html b/cpp/index.html index f8fdebf..af16c78 100644 --- a/cpp/index.html +++ b/cpp/index.html @@ -14,10 +14,10 @@ - + - + \ No newline at end of file diff --git a/files/algorithms/graphs/iterative-and-iterators.tar.bz2 b/files/algorithms/graphs/iterative-and-iterators.tar.bz2 index 3d33ce9894b9cbf6557a6ea5fd6c2bf1f5ca9dc8..a0b1bd035d7f8dec20be39621bebd88f359be641 100644 GIT binary patch delta 1919 zcmV-_2Y~pK4~-8FLRx4!F+o`-Q(1lVy_1m+C4Viui!DF{T67(-C@2~lLP)8iW}po{ zOrEBXP#PHlpbt|(13&-)pkkVglT8TPjT$rn00000003kFaAX=Z0h3HaO$I@TVFN&D z#KdR-07`n2Xj9TP8a=8F1JnQj3{3z4G-;zlKnDgvqd*xn#5B-k7={ou28>KbfB*zZ z2!A3p(qNe;(-hH=6Hf?ajWjegXk^nyngRTT|KDTvL^bK^@j%GFXjL&rv=9@oF3RiE zvi+5w1nm;ZqzuI4*Gp@j0>GM&eTv0oNTO0u0}=`c_&MX_At56o!BIhhU?h#xO+EHi zX(3}G$r3OuDJ;ZMfn_L+jKM4f!7?-wDSry8a!r~Q3aEyAOBGlPEDAIwlwq6U3l|Mh zJJ5WD{);{b9{P5R=sPS_Et7O~)2-qr;I_A##XV%I%6PROAg>$aBlCDQH{f8zov! zPXU>W><&85ATW^d6?@#a63I#mVvOKLMAo_yBEbR;F|}UJit;s;QnViQ)~LcYC8=Ds zX@%`@y9=mVbMeoVQBzuF7*z#?L4RTJGpGT|I77k6#7&q|4I5^6ZoG>L*w~V6+YANh zR+d?5>4=9OEdnM`s^aK1w7F5J$gt-?h{VsBm^_Y{F@BM)zQJyS+2vQ3@kR!J5s_)+ zo$n*=8tF<*n4GC1G*nSNgrN}A6zXaKoM%d{ginf02f`9H-e*0Zf!YI;rhms<8-mg1 zY*EZn$Q*UcxVA%aw|`j-MQC4>Q(j;W)1)nI@M68l%LU$yvJCNCG7PwImT%vXIfEK;6k#waVlc=60I(# zG@x}JzjqIO@Vnr5MB+QTpH0)Q53p+_vud?_dniIj-G{tIzaMVfoLTKXT$^wo^4mr6 z_`{QUN-D25VvR0Qi88)udO{%ZMKZ5{&TTMqWchR-T?XQLePt#ioPRK4+_~uFXkxbn zHk+(j_QW_z))o2~;#^>-nfYwkjq3~z=w5>|0dTD(mDYT_R)A;I3*y;62K2|-*Hu+j zGU1w5hp5;PgK)%1IEPwnINO&@5*R4P&K4Y4KTcW5LHc}S`5Y!|S>wk!rcGm7UYHl(QBalXru$&}Xz@CZW*C`>Cs1@%gdI*`JRXX$RY5=~0~<_->lVrl3AhvPPa)57GywZ|EsW8R5eIm{*r0A!0r&?h z2Gj9Gx-cvp7zma_&=v#f6P!7R9Z2pd0t|XuH5ammzz|^{wSN(dxFf)zYco?oH_%4 zK}eMt5JHpqfnodrx_1F+!VJ(N9|vFu8@qHo`^T`*a2x-&@!(HFTKE$nOviwF6Dk>i zPq!7H&M9U;i@)Q&;@T303iL|}RFfUk%^XG~Q;JFJ(vM(T9pPc%<1pkQtFTG}kPV)pE&<4z1BZ}2;avgK z&Czg#D6mRwW5!%q7uf{vZrpvA=JLr0e$D{EaDVxc+7=BdgP@&VM4sY!tWMGT0=6&X zEI;;xwcVRe3;(Am9rPm1t7K z+HVRAA#U%z#^6ka=@^N`Y)o+@-L$tO0OlZ&XGw$%!#9y6G@zn=K!2W5`OV7E|E17P z;b`ol&Q(pbVVd9Rv}HJY!ibGBoN0*DMzN%rh9I!y4`8=yj=($aVTJwFNIv>r F$$%OHSZn|Q delta 1901 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 delta 1640 zcmV-u2ABDy52Fu|OMfpjCbm|q)$U6Bv%uz*S=^q|XO=s7W{W$I`TN(*nv8t2?@yTb z*WPxh0GbB}_*rc=s^Y%dYKc!oz1rNX9yIFJgL<`9tL#Bz6Pih7%W*eC;B$)+vd03~ zr7T-+;Pr3v+8-&}XAoc7=j42Fb5wk5_nGH=LvFr1>6!4T*nfFacv2t)#U_;T*=yzn zlMX(DhwlSE33zWdp`DXE+TM@dhY~%DT~mI_tTDay*iFZ!ykS<_`|0O$6zK3Sa2)H( zp&jbtM|*$qK$x+gw&O`bJi{r#-H-O>=K2Su)_zl7BxWn!r778wG(*DHiQzA(L`6{;RzGL}5fgEY~I^=dl86`dPoVXr$VapDM5EEuk zEl$a6?2W=g4Jb|vbZs%V#b)hZnbT;zL zXkM=a9OJPLIp^4<(jo;=(Na@z<=B06kdd5uDdrmlAKAVsT0nK^o2YHB(ubP<3|u3v zXy`F&^+&{*LPk%aO42*SqoRyjN>-8r zGFO((13I(oI75-PN zY5sQ~*p~lwcgX*6fpU9H*RipP8TO%CF*?|S8wyRQwrl&Nt@Lcc54$_&huv&`h`yD4 z=V8&tG8tNqPrnm;>?+w~nOu3E13G+)?**I%E5@QbCKexs0fpf9Z`uX~^Y;@s7|V?k zG?zLn^a~w-BQ&e#zl=i8+>B*#clyV_jZ=MDI$S}f5D+r(@ zq@@f>Dpagxqz3E-{4xxtAM_z%e5fL5rL=+48zo6aPyMp&5F?;jsU!7ylQhd-crIGb zAD1>QoELkf@SxyZsw^ZF(le3nF_T07yJ_m9yIh!mp)>=GSXGrlH{&_6)UcRa?9pb~ zk@Tp@lBEu1sw|sJrJb+Vd!?$1*2~96WW!u|$up^JD3L{GQBSm5vb03)SvnpJk=6Jn z0xt@8gymi+mU|i5|Ex?z zi7mu`wl(<{u^_;kyhogSP=N;Llw*f!$WJ4Z7Hd<{cG;ff=J7rqLb2K>#p2kQ#>`)VuBPN=Or4&bYx3e;i1wdLn8sefy)q> zX?k=lj&hKU;z%Rnm(kRdw-h zljr8->jX(KE=9O^KOr1(VM3Z$t0xu8Updq~8Bh33BvZDcxi0n(6nXXkjCruVkGEz3 z>*{}_-b&a1R;{7y|9#-!zyFCB_*A+7h6BMcX<{2s_(msdyw4fv?~r3gp&p;yS>uU+ zLq*fdaaD926)W#=Y@bIeR^$;yzgQ;4&v@Z@nc;=uWr~+uyxigC3toa^a;sB(!55vo z;pmAOtQ==#9HUKh4$$N)_OiGuzeP=Lz>7Yj>dE;|i>W>-A>j{y6QSEpg!mev(DNGz z-K`Ot$!O*au}y|!GT!+@(@k7(yNNS@?>5mCCStzOmreW>EL@-}*4byq;nEaD?=5f| zLnimfPsC!^D=8aa532R6SU!WH-(wc!wQo7m!T9Ourv zTK)ZBtx>BS?2+ny826Lc{|E5>uQLAC%9{A^$~YbWAASC(h<_9Q*2I5T#_9O~==VQG m{9Dylb4~nrW!z65f0Ka+7L$+%1PzV<5B>v{R-1|dPyhhY_ebLZ diff --git a/files/algorithms/recursion/karel-1.tar.bz2 b/files/algorithms/recursion/karel-1.tar.bz2 index f35cb5ba4f9a8181b38ea6f9ef41cdce4e20b103..63dc5b6a567257b3a23deaa177adf53f1b558768 100644 GIT binary patch literal 5877 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 Pkr^Hc(|*Q@02l!P$iV)8 delta 5550 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 diff --git a/files/algorithms/recursion/pyramid-slide-down.tar.bz2 b/files/algorithms/recursion/pyramid-slide-down.tar.bz2 index f5408d0d8628532dc82d15767b54c1c7f9c9b7ef..235efe6a516144e1d9f1a00d91b341bcb31e404b 100644 GIT binary patch delta 1433 zcmV;K1!nq+42uj7LRx4!F+o`-Q(4fVJ0Fn_hJOkG003wj00E%T007Vc0a8K;AZlre zf~T4j394;PKUChR&8VKE5b{H5w9+*`U{neX8 zS$`rnl@b$}q(qEJl0M(V)E`Lu$Nf!IpDhg%*0I)7TYk9$e4^DRDZ6sc)kEifspF%0JR<0-w0 zZjzGKyLFeDQmV@tYI!kjn9nZ!_sG*)v3}dD<w9~G!oq~+^R3c6Sou+hver^ZPHRI9nO#wRK9TA48|>24=C2K z=EBAcnwps!3m7QaT){@Bro&;OV}Da3jS4e07dhLe{^% zd2!u+&9I|=yJyHd13m4J(z3@X;^`^QOS#IO)a)}ng^r_Btm`r|8$|aXACK4Zz{sMF zH*y?v{~U#!MJ0+eGAQ#LWr{2?hFMr`bmva^}-g!)Ze@h6)-{GHV$2yKF|&TM#)_h0mip2{sM@$p##WMtGi0QNB~5Lpm>r#p8B1VF|CV1@eu zz=bq33`vRnWodt@UuU}`mV6&jm_ES$V_Bx%_RDYl&wKx8hY!58oPTtR3WviKy-2^& zST6PY&)IH^`{FLWHC3PqukantFeD{llE$qc&+Hz`^J`&SJw857n6E)t8E;tsafrO9ewbRDUL+luzl+54`sdzo#>jN)w|-!tipD;5WIV@>GgD4hbUh4cqFf zKL&2$+4(GS6`mwleVYC2vlp>c%P3%L2a*k344kJS92E;6mB*tvE*i(oN*hMWIE7A0 zRa@Nw#JRR#2_pvi$L*ndN~5WIqy4GNk>Eqr~$baZ{_wE8A7LK3;Wre~gT6 zX&S{S{@>s8Vs4cxvh&(StMm?2V%MUvRbwCMl00)e&Mw3Iy_0j8wJKI;nC%Zpak&*v zSxZMfRf?^+7k~Zpk;r+qw+Bdi+I4ap1M@S~I$UW^Cc_YJiAa*&RL*}J#otDKR@%x^ nNYZl#ggXfj$}C&J?H!}GRz=GT2w0K-;_gVN3KAL=Cjw*O{;;;r delta 1432 zcmV;J1!ww;42ld6LRx4!F+o`-Q&}cDKKzjmhJQ4m00000000004FCWYBp^Zpo|u?Q zd7&_xrqt8*O{mSNo}&=*Lus_qH9q6(JVlSqs;Zz?L`mJ3Z+~G$i>GpiW0;bO7A%N- ziQyDg6sb+m#+0J3c@{2MTE$YWQq;AIhiQVAyA#K2C0w>KRaRcaSfWZOkLCNTHioi9 zZhtByCoxEg7?C7>zlW$kf%lL4nyEfI8YQi7#+2hZtCCA`pWxGZvCWT}FZi8-O?KUX&y}jXKVM23x*6JTNJ~UzMwUm+7n$W{0S5#k5pn81=3pBL(`#5;reSehS zx2JY5UAr#J)NIpC^j1XZ%Uo-3o1PQX&UrcYa^QoCVcvC@IZGYKabvt(qrAw$-dMq* zk(owjriF}(DA4j68kQC;WMpP!Y+S*apvII(4&RBr^Gu$J`JCxWsXy`p*jh7K~uh&9y7*R>oq$L!y_TMPjT@0eSZuLiYU{6 zA;&-Q$XUcvSfeu{k1@trqQeMfmo3JI^2FXyT(NTF>ncYvvAEFOWMoleh=0i7!F|>V zv0OMsiZ>QD7A$W!mp2>D;*AP57%plsT(KXmM+!8eZ^+QWg9gQh@`hy$6g8q`p>s0D zjjTn@N+_dov7wO2qgo?lOA^#9Xlynp!BkZWqlltfgxg~yLxGu*sKK$RnVGzz<_(3* z8sL)U2LgqK69x@UO-#*A4S&Xl<6}a`#$d6jV#dZsh78IiW@cD^-w5;hZRhjaFHt-y z&-Pl?etQ?kh8y>q&o8?Fq*V4%X;+Ve$vosqvSb68M4(AzN#!$U(Ex}c04Nf#U@#v` z3&PSRL-@+l|4P2kc1JAwpGcTK!2M%crtTKYcl^(L|7V9k-davNMSlfD>cuZoFZ0$5 zy?(RyTc-Z_i?2;pYx=U8+TrWZLaI~ko>SzWpWZ)k=sEOe%_MjjJqKaTSYl#F#WtEx zhsZw}6Lfp4$&mDyJu014JSlpz@l>^=(Z6wEsR;Kz7&Y0)zx?yIoppg$YFHp zk}ijff$}zbB>0Mi)PFLG{W+ocp5fW_W^zeFbm-W;9He*-4rsiUB97CYBwiuEg;hu3 z&E7kIC5|Gq#ESA+uim>cdlgKwh6b>B;MLA#Wu7&uNpZ41&>S!+OD_BDpI1p=SX;nek7b_N&6jV%<~>`Q?JJ>+f}?iK6QA1jErt+ z8pSC7-{13MZNp(LIr+)b4s#MW2E+Alj-?5vn4ri^NK}%f zpyHBkDN-=?L6F?!dyDe7hfsRjb@Cer=4YsNIMSR=j6uF7B1?7CIs9)IeEId;b16w9 mNz57$?Ib@av2O#ocMj=U7c49xVn_drxgwk>NE00&egOb#VZNmR diff --git a/files/algorithms/recursion/pyramid-slide-down.tar.gz b/files/algorithms/recursion/pyramid-slide-down.tar.gz index eb03455652cf48f16c2ae8cd5985a48f3dcbe719..ecb34f5f3ebd4f38c80a522db226683907918b83 100644 GIT binary patch delta 1309 zcmV+&1>*XT3yuqrf`4*NM?cVwzT=n&pzp)^F07K&ivbSeRS>YaU2Yam|Jm06jly3> zVVnXV>fS2#7rnP}?5&g2!^3FxdErlCy6}<&vN-|whk#IhSh^GsevrZ<4CX9J&-pa^ z31?9UPhL(gClJXA)>WDuSyz$?CoqD5-HHw+-&?R?o?fFEhJTVNZWJnFa012zjmY48 z(=b|pyy_^KCRr`FnPH2tYIh5fT!k_46k&~CYbxd`o*$1uKZTQ%buslkeTc)`)_~U& z4L0ot_oWc-KzO=?H{7U_K854syQ*j99ah1N#i&)N=NgVN)5|+7caugM{^8HBQ`EWR zg6OKIs~p$VtAF^R$*nl-RDBKagOtr#+&g>!;jcg6{`TqTdbn5vOaqQbaOS1gy`^{8 z5&3Fa65X=SL%FQQ;P{k6a~t`BY|PSC92CX%34Wxkk}EHho6w)Z(({APc^dn{94CPn z&y(UHov)LWEqmcA?L{b(c8)G^QNee{Yd9)|T@_mdoqyW;%hnTLX!Tie4;DPs7r{Na z8raP}CiZC1Z|)pu;Ak+^xYY&lri*{^68>}15=vnw}fF}4Gj&8reUOL6+bOO4bUkX zbJ3W~rGL>T9{O%edPDA0gkYj#AHCq$#h`{QN!b_%|C%W0;CF!5ZImDAQqO9cK|&8* zxF(m8*;>5qN}od>!mwG_;fZj4TSja0i1FMI&pBvgh&CK-8!a{AaT$j6%hSw?!w1mi zgT$*akiVU_N*OW+?$1)PhAm^@u{eCLqaV}dd4KR+o9&3v=*vZeDgzXC!~mgLU4@0+ z{h^#UytJ0lQc@J-*$%W4IAiWKQ z*?*`qRmH9{5{!D2OSCs>q+;AMb_!xT9u<|g64NhVYNEmij2q93#$)3|;aauwDk-a) zsL(cY`Fyjy(cQvDpSopJ0ku2F{~UdrLn6OKeu?}N`6crE|3U-*`{4OEY>)KsIs8wz zE#iMKffD}{Bmb4@-?&EqkcV-`@&@#*S$`&R`3=x!?zQEXV1*-o9rn3}tK~N!YnQc0 zlEeD-@Co#f_#g4VYJ$Z7i2o7)BmS48f&X2E5xDs!5k{Y5A814k_Bl3@4{u|#op%ydy^@Q3xEGk z%8k_IlI$YvWP%Xao}Mcr_i6-j4;xL-xGT)?##^k|$1ASZ?QMKW^{o$svpb8zS%uK< zaK@!e&dN9Y8k{LZdXZ%o#2!K5%CT42d8t#4ay}qh7XKKg-t?N4rSs8+O}EnX4&L?8l#{b!z?%?hJ|Ksi}Hm=R{j4+B(tJiMCF(bs`W51OkCTAP@)y0)apv5C{YUffhg@5C{YU Tfj}S-2#?0U9=^zn08jt`tInTj delta 1310 zcmV+(1>yRR3y%wsf`2kxQ$Ns+zGL?fK;MV+U05Zl7Xuu`s~});yWA|C{4& z!Z-y!)V)>eFM4m|*jp#3hlkPX^TMCPbm1ilWOD-U4*{Y2uyiRN{2+xz7|dCcp7Uw+ z6V9Rzp1hn~P9TyKtgAFRvaTc(PGAH9yA>TuzPDh(JiSIS41Xn4+$dDU-~@~b8j->G zreU=Hc-2udO|n{UGs6~P)$SG|xe8<8DZ(1P)>O<>JUtgD8`Vfb=tpTqm z8f@AP?n@!uf$($(Z@5tJws z1<_SaS2?b!SAX$ClUs4vsrnk;2PvDgxOevc!(V^C{q57w^>DEUmi=u+@Gan4O_;*V{!OgM?a>^^MByEHro-S(U*$`RR$>Phyg;gx(W-s z`$IWzcxf%8rKBjvvmYq0mRM?H@CMS-(2~Il4|1lNrSXw#(a>GHbu|jH!-vEFnvxJ+ z5K*1~{}MAcTknni@8tiMjhw&2|4qXt{{Ipvv3xo5&*u1=kV3*F8`E%6V*OXp5u~?) zFn=3WrmEOgMuJgqa*6gPjZ}x!JR=dQ6@-{4ky2|btf-t!>b~jHw<9( ztPO=6Pw{?DzFte4j3@0fc3G1jNwoU{Bfj}S-2m}IwKp+qZ1OkCTAQun_1OkCT UAP@)y0^!m47q(sn=>Sjw0Ak0D+yDRo diff --git a/files/algorithms/time-complexity/extend.tar.bz2 b/files/algorithms/time-complexity/extend.tar.bz2 index 6162dd801665c49e73ce27048da2cee5f3cfedb1..575755e1933788ebb9fec2f94cfbff5967bee701 100644 GIT binary patch delta 3987 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 delta 3955 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