├── .gitignore ├── CNAME ├── LICENSE ├── README.md ├── _config.yml ├── _includes └── cookie-consent.html ├── _layouts └── default.html ├── about.md ├── ads.txt ├── ai └── meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory │ ├── README.md │ └── media │ ├── ChatGPT-powered-chat-robot.png │ ├── ai-manuel.jpg │ ├── ai-manuel.psd │ └── supportbot_event_sequence.svg ├── algorithms ├── .gitignore ├── README.md ├── distributed-computing │ └── distributed-sorting │ │ ├── README.md │ │ ├── distributed-sorting.js │ │ └── media │ │ ├── chromium_design_document_template.png │ │ ├── distributed_sort_problem_definition.png │ │ ├── intro.mp4 │ │ ├── leader_controller_group.png │ │ ├── node_failure.mp4 │ │ ├── problem_visualization.mp4 │ │ ├── thumb.png │ │ └── tournament_tree.mp4 ├── dynamic-programming │ ├── common-sequences │ │ └── longest-common-subsequence.js │ ├── kadanes-algorithm │ │ ├── README.md │ │ ├── max-min-sum-subarray.js │ │ └── media │ │ │ └── kadanes-algorithm.mp4 │ ├── sliding-window │ │ ├── README.md │ │ ├── desired-subarray-sum.js │ │ ├── max-sequence-by-flipping.js │ │ ├── max-subarray-sum.js │ │ ├── media │ │ │ └── sliding_window_technique.mp4 │ │ └── shortest-substring-of-letters.js │ └── staircase-problems │ │ ├── README.md │ │ ├── media │ │ ├── alternative_big_o_notation_mug.jpg │ │ ├── memoized_recursive_fibonacci_animation.mp4 │ │ ├── recursion_tree.png │ │ ├── recursive_fibonacci_animation.mp4 │ │ ├── staircase_problem.png │ │ └── thumb.png │ │ ├── staircase-problems.js │ │ └── staircase-problems.py ├── merge │ ├── k-way-merge.js │ └── two-way-merge.py ├── package-lock.json ├── package.json ├── primitives │ ├── alternative-big-o-notation │ │ ├── README.md │ │ └── media │ │ │ ├── alternative_big_o_notation_poster.jpg │ │ │ ├── alternative_big_o_notation_sticker.jpg │ │ │ └── thumb.png │ ├── big-o-time-space-complexity-types-explained │ │ ├── README.md │ │ └── media │ │ │ ├── alternative_big_o_notation_poster.jpg │ │ │ ├── binary_search.mp4 │ │ │ └── quanticdev_sticker.jpg │ ├── recursion-visualization │ │ ├── README.md │ │ └── media │ │ │ ├── fibonacci_5.mp4 │ │ │ ├── modified_fibonacci_5.mp4 │ │ │ ├── power_of_2.mp4 │ │ │ ├── recursion_tree.png │ │ │ └── thumb.png │ └── subarray-vs-substring-vs-subsequence-vs-subset │ │ └── README.md ├── sort │ └── insertion-sort.js └── trees │ ├── generic-tree │ └── generic-tree.js │ ├── heap │ └── binary-heap.js │ ├── lockable-tree │ ├── README.md │ └── lockable-tree.js │ └── tournament-tree │ └── tournament-tree.js ├── articles ├── _template │ ├── README.md │ └── media │ │ └── THUMB_TODO.png ├── automating-my-youtube-uploads-using-nodejs │ ├── README.md │ └── media │ │ ├── software_development_life_cycle.png │ │ └── thumb.jpg ├── cleaning-macbook-after-16800-hours-of-use │ ├── README.md │ └── media │ │ ├── macbook_battery_service_recommended.jpg │ │ └── macbook_pro_open_back.jpg ├── engineering-principles │ └── README.md ├── essential-software-for-working-from-home │ ├── README.md │ └── media │ │ ├── quanticdev_github_repo.png │ │ ├── slack_apps.png │ │ ├── slack_bot.png │ │ ├── slack_desktop_and_mobile.png │ │ ├── trello_board.png │ │ ├── word_online.png │ │ ├── zoom_meeting.jpg │ │ └── zoombombing.png ├── fastest-php-best-practices │ └── README.md ├── h265-encoding-on-arm-cpus │ ├── README.md │ └── media │ │ └── x265-arm_vs_x86.png ├── how-i-mass-refactored-our-production-codebase-without-fear │ ├── README.md │ └── media │ │ ├── appium_architecture_diagram.png │ │ ├── device_farm-automated_testing_on_mobile_phone.mp4 │ │ ├── device_farm.jpg │ │ ├── device_farm.mp4 │ │ ├── device_farm_usb_hub.jpg │ │ ├── firebase_test_lab.png │ │ ├── method_chaining.mp4 │ │ ├── opensft.png │ │ └── thumb.jpg ├── how-to-fund-your-project │ └── README.md ├── how-to-manage-money │ ├── README.md │ └── media │ │ ├── dow_jones_industrial_average_100_years.png │ │ ├── euro_vs_usd.png │ │ ├── msci_world_10y_performance.png │ │ ├── my_portfolio.jpg │ │ └── yearly_mortgage_rates.png ├── how-to-present-like-apple │ ├── README.md │ └── media │ │ └── apple_special_event_quanticdev.jpg ├── how-to-use-github │ ├── README.md │ └── media │ │ ├── bitbucket_about.png │ │ ├── git_about.jpg │ │ ├── github_raspberry_pi_schematics.png │ │ ├── github_top_bar.png │ │ ├── gitlab_features.png │ │ └── my_macbook_setup.jpg ├── is-windows-good-for-developers │ ├── README.md │ └── media │ │ ├── thumb.png │ │ ├── winget-dependency-management.png │ │ └── winget-package-versions.png ├── linux-laptop-at-perfect-price │ ├── README.md │ └── media │ │ ├── lenovo_thinkpad_e595.png │ │ └── lenovo_thinkpad_e595_ports.jpg ├── manjaro-linux-productivity-machine │ └── README.md ├── max-value-pc-build-guide │ ├── README.md │ └── media │ │ ├── bios_settings.png │ │ ├── computer_build_black_mesa_gameplay.mp4 │ │ ├── computer_cable_management.jpg │ │ ├── computer_chassis_back_io.jpg │ │ ├── computer_components_on_desk.jpg │ │ ├── computer_under_desk.jpg │ │ ├── coomputer_build_cleanup.jpg │ │ ├── cpu_fan_installation.jpg │ │ ├── cpu_installation.jpg │ │ ├── graphics_card_installation.jpg │ │ ├── motherboard_installation.jpg │ │ ├── motherboard_power_cables_installation.jpg │ │ ├── passmark_cpu.png │ │ ├── passmark_gpu.png │ │ ├── power_supply_cables.jpg │ │ ├── power_supply_installation.jpg │ │ ├── quantic_developers_club_poster.jpg │ │ ├── ram_installation.jpg │ │ ├── ssd_installation.jpg │ │ └── thumb.jpg ├── method-chaining │ ├── README.md │ └── media │ │ └── thumb.png ├── most-valuable-thing-to-learn-in-one-hour │ ├── README.md │ └── media │ │ ├── first_aid_kit.jpg │ │ ├── google_notes.png │ │ ├── levels_fyi.png │ │ ├── raspberry_pi_kit.jpg │ │ └── raspberry_pi_screen.jpg ├── my-project-got-800-stars-in-two-days-on-github │ ├── README.md │ └── media │ │ ├── koan_github.png │ │ ├── koan_github_README.png │ │ ├── koan_github_issues.png │ │ ├── koan_hackernews_2014.png │ │ ├── koan_heroku_demo.png │ │ ├── koan_heroku_demo_login.png │ │ ├── koan_logo.png │ │ ├── koan_on_newsletters.png │ │ └── thumb.png ├── obs-studio │ ├── README.md │ └── media │ │ ├── crowner_screenshot.png │ │ ├── github_10000USD_bounty.png │ │ └── obs_studio_screenshot.jpg ├── raspberry-pi-guide-for-developers │ ├── README.md │ └── media │ │ ├── docker_performance_cpu.png │ │ ├── docker_performance_latency.png │ │ ├── overlayfs.png │ │ ├── raspberry_connected.jpg │ │ └── raspberry_hardware_features.jpg ├── serverless │ ├── README.md │ └── media │ │ └── serverless-architecture.png ├── software-design-patterns │ └── README.md ├── software-engineer-compensation-guide │ ├── README.md │ └── media │ │ ├── senior-eng-companies.png │ │ └── senior-eng-l6.png ├── software-engineering-in-2020 │ ├── README.md │ └── media │ │ ├── github_organization_count.png │ │ ├── github_user_count.png │ │ ├── growth_of_natural_language_processing_nlp.png │ │ ├── jupyter_notebooks_per_year.png │ │ ├── largest_tech_companies_by_revenue.png │ │ ├── open_source_by_continent.png │ │ ├── open_source_contributions_per_year.png │ │ ├── software_engineer_demand_by_role.png │ │ ├── software_engineer_salaries_by_role.png │ │ ├── top_open_source_contributor_companies.png │ │ ├── top_open_source_projects.png │ │ ├── top_package_managers.png │ │ └── top_programming_languages.png └── website-with-github-pages │ ├── README.md │ └── media │ ├── github_pages_react.jpg │ ├── quanticdev_com-github_source.jpg │ ├── quanticdev_com-google_analytics.jpg │ └── quanticdev_com-mobile.jpg ├── assets ├── css │ └── style.scss └── media │ ├── quanticdev_poster.jpg │ └── quanticdev_sticker.jpg ├── favicon.ico ├── favicon.png ├── gpt.py ├── notes.md ├── privacy.md ├── shop.md ├── tools ├── code-animation │ ├── code.js │ ├── code.py │ └── main.py └── recursion-visualization │ ├── asset-manifest.json │ ├── icon │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── mstile-150x150.png │ ├── safari-pinned-tab.svg │ └── site.webmanifest │ ├── index.html │ ├── prism-dark.css │ ├── prism-light.css │ └── static │ ├── js │ ├── 2.676818fa.chunk.js │ ├── 2.676818fa.chunk.js.LICENSE.txt │ ├── 2.676818fa.chunk.js.map │ ├── main.673ef02c.chunk.js │ ├── main.673ef02c.chunk.js.map │ ├── runtime-main.0131dfd2.js │ └── runtime-main.0131dfd2.js.map │ └── media │ ├── first.e33117eb.svg │ ├── last.14dc4eba.svg │ ├── logo.b572fca9.svg │ ├── next.fbb21171.svg │ └── previous.aad86071.svg └── web ├── react-js-frequenty-asked-questions-faq ├── README.md └── media │ ├── mui_component_library.jpg │ ├── react_diagrams_1.jpg │ ├── react_logo.png │ ├── react_native.png │ ├── sample_react_source_code.jpeg │ └── virtual-dom.png └── what-is-react-and-why-should-i-use-it ├── README.md └── media ├── mui_component_library.jpg ├── react_diagrams_2.jpg ├── react_logo.png ├── react_native.png ├── sample_react_source_code.jpeg └── virtual-dom.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Editors 2 | .idea/ 3 | .vscode/ 4 | tools/code-animation/media/ 5 | 6 | # Other 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | quanticdev.com -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Teoman Soygul 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuanticDev 2 | QuanticDev's engineering and software development resources. All the articles and videos are based on my experiences as a software engineer with a decade of experience and education in electronics and semiconductor physics. In my career, I have developed several popular open-source projects, apps, games, services, and more. 3 | 4 |

5 | 6 | ### Social 7 | * YouTube: [youtube.com/quanticdev](https://www.youtube.com/quanticdev) 8 | * Twitter: [twitter.com/quanticdev](https://twitter.com/quanticdev) 9 | * Instagram: [instagram.com/quantic_dev](https://www.instagram.com/quantic_dev) 10 | 11 | ### Contributing 12 | If you want to contribute to any article, you are welcome to make a pull request or create a new issue on GitHub. You can comment under YouTube videos, or read existing comments. 13 | 14 | ## Tools 15 | * [Recursion Visualizer](/tools/recursion-visualization) 16 | 17 | ## Courses 18 | * _Upcoming.._ 19 | 20 | ## Software Engineering 21 | * [A Senior Developer's Linux Setup](https://www.youtube.com/watch?v=fa2Z1wdjFYg) [Video Only] 22 | * [AI Socks Matching App in 10 Minutes](https://www.youtube.com/watch?v=nE_VbgEPogs) [Video Only] 23 | * [How I Mass Refactored Our Production Codebase Without Fear - Engineering Stories](/articles/how-i-mass-refactored-our-production-codebase-without-fear) 24 | * [Method Chaining is Awesome](/articles/method-chaining) 25 | * [Automating My YouTube Uploads Using Node.js](/articles/automating-my-youtube-uploads-using-nodejs) 26 | * [My Project Got 800 Stars in Two Days on GitHub - KOAN (Open-Source)](/articles/my-project-got-800-stars-in-two-days-on-github) 27 | * [Is Windows Good for Developers Again?](/articles/is-windows-good-for-developers) 28 | * [Responding to Harvard's Survey Request About My Open-Source Contributions](https://www.youtube.com/watch?v=rtmHrhOeAfI) [Video Only] 29 | * [Fastest PHP Best Practices Guide](/articles/fastest-php-best-practices) 30 | * [State of Software Engineering in 2020](/articles/software-engineering-in-2020) 31 | * [How to Correctly Use GitHub for Software Development - My Full Workflow With Tutorial](/articles/how-to-use-github) 32 | * [Raspberry Pi: A Developer's Companion - A Complete Guide with Docker](/articles/raspberry-pi-guide-for-developers) 33 | * [What Is Serverless (Function-as-a-Service), and Is It Worth?](/articles/serverless) 34 | * [Cleanest Linux Productivity and Development Environment using Manjaro Linux](/articles/manjaro-linux-productivity-machine) 35 | * [Software Quality Assurance - How Do Software Companies Test Their Products?](https://www.youtube.com/watch?v=ztb8HNc2kCU) [Video Only] 36 | * [Software Design Patterns, Principles, and Best Practices](/articles/software-design-patterns) 37 | 38 | ## Engineering Essentials 39 | * [Software Engineer Compensation Guide - From Junior ($100K) to Senior ($500K++) Engineer Compensations](/articles/software-engineer-compensation-guide) 40 | * [Fundamental Engineering Principles - What are the expectations form developers and engineers?](/articles/engineering-principles) 41 | 42 | ## Algorithms 43 | * [Distributed Sorting - Google Interview Question - Algorithm and System Design - Full 2 Hour Interview Walkthrough](/algorithms/distributed-computing/distributed-sorting) 44 | * [Merge Algorithms - 2-Way and K-Way Merge](https://www.youtube.com/watch?v=Xo54nlPHSpg) [Video Only] 45 | * [Recursion Visualization](/algorithms/primitives/recursion-visualization) 46 | * [Staircase Problems](/algorithms/dynamic-programming/staircase-problems) 47 | * [Alternative Big O Notation](/algorithms/primitives/alternative-big-o-notation) 48 | * [Big O Time/Space Complexity Types Explained - Logarithmic, Polynomial, Exponential, and More](/algorithms/primitives/big-o-time-space-complexity-types-explained) 49 | * [Kadane's Algorithm and Its Proof - Max/Min Sum Subarray Problem](/algorithms/dynamic-programming/kadanes-algorithm) 50 | * [Lockable Tree - Google Interview Question](/algorithms/trees/lockable-tree) 51 | * [Subarray vs Substring vs Subsequence vs Subset](/algorithms/primitives/subarray-vs-substring-vs-subsequence-vs-subset) 52 | * [Sliding Window Technique](/algorithms/dynamic-programming/sliding-window) 53 | 54 | ## AI 55 | * [Meet Our New Tech-Support Guy: Fine-Tuned ChatGPT-4 with External Long-Term Memory](/ai/meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory) 56 | 57 | ## Web Development 58 | * [What is React and why should I use it?](/web/what-is-react-and-why-should-i-use-it) 59 | * [React.js - Frequently asked Questions (FAQs)](/web/react-js-frequenty-asked-questions-faq) 60 | 61 | ## Guides 62 | * [Maximum Value PC Build by a Software Engineer - Complete Desktop Computer Build Guide](/articles/max-value-pc-build-guide) 63 | * [How to Get a Great Linux Laptop at a Perfect Price - Lenovo ThinkPad Without a Pre-installed OS](/articles/linux-laptop-at-perfect-price) 64 | * [How to Find Funding for Your Project](/articles/how-to-fund-your-project) 65 | * [Essential Software for Working From Home](/articles/essential-software-for-working-from-home) 66 | * [OBS Studio: Open-Source Software for Video Recording and Live Streaming](/articles/obs-studio) 67 | * [How to Manage Money as a Techie - How I Invest as a Software Engineer](/articles/how-to-manage-money) 68 | * [How to Set up a Free Website with GitHub Pages & How I Created quanticdev.com](/articles/website-with-github-pages) 69 | * [What Is the Most Valuable Thing You Can Learn in One Hour?](/articles/most-valuable-thing-to-learn-in-one-hour) 70 | 71 | ## Hardware & Software 72 | * [Cleaning My MacBook After 16800 Hours of Use!](/articles/cleaning-macbook-after-16800-hours-of-use) 73 | * [How Fast is H.265/HEVC Software Encoding on ARM CPUs (iPhone/Android) With FFmpeg?](/articles/h265-encoding-on-arm-cpus) 74 | 75 | ## Product Management 76 | * [How to Present Like Apple? - Recreating an Apple Keynote](/articles/how-to-present-like-apple) 77 | 78 | ## Case Studies 79 | * [Stripe's $35B valuation in 8 years - How a tech startup reaches billion-dollar valuation?](https://www.youtube.com/watch?v=nlFAbBvu7hA) [Video Only] 80 | 81 | ## Other 82 | * [Our Startup Office Tour - But He Gets Wider After Every Corner](https://www.youtube.com/watch?v=Et5I2w59Pkw) [Video Only] 83 | * [Physicist Reviews Black Mesa Research Facility](https://www.youtube.com/watch?v=GLGRkMQdm78) [Video Only] 84 | 85 | ## Your Host 86 | Teoman "QuanticDev" Soygul ([soygul.com](https://soygul.com){:target="_blank"}{:rel="noopener"}) · info(at)quanticdev.com 87 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker 2 | show_downloads: false 3 | -------------------------------------------------------------------------------- /_includes/cookie-consent.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | 60 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | {% if page.url == "/" %}{{ site.description }}{% else %}{{ page.title | default: site.title }}{% endif %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 | 28 |

{{ site.title | default: site.github.repository_name }}

29 |
30 |

{{ site.description | default: site.github.project_tagline }}

31 | 32 |
33 | {% if site.show_downloads %} 34 | Download as .zip 35 | Download as .tar.gz 36 | {% endif %} 37 | Home 38 | 39 | View on GitHub 40 |
41 |
42 |
43 | 44 |
45 |
46 | {{ content }} 47 |
48 |
49 | 50 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /about.md: -------------------------------------------------------------------------------- 1 | # About QuanticDev 2 | Teoman "QuanticDev" Soygul's engineering and software development resources. The articles and videos are mostly on software and engineering, while occasionally diving into tech topics, tech news, analysis, and more. All the articles and videos are based on my experiences as a software engineer with a decade of experience and education in electronics and semiconductor physics. In my career, I have developed several popular open-source projects, apps, games, services, and more. 3 | 4 | ## Contact 5 | You can reach me at [info@quanticdev.com](mailto:info@quanticdev.com) 6 | You can also use the social media links below. 7 | 8 | ### Social 9 | * YouTube: [youtube.com/quanticdev](https://www.youtube.com/quanticdev){:target="_blank"}{:rel="noopener"} 10 | * Twitter: [twitter.com/quanticdev](https://twitter.com/quanticdev){:target="_blank"}{:rel="noopener"} 11 | * Instagram: [instagram.com/quantic_dev](https://www.instagram.com/quantic_dev){:target="_blank"}{:rel="noopener"} 12 | * GitHub: [github.com/soygul/QuanticDev](https://github.com/soygul/QuanticDev){:target="_blank"}{:rel="noopener"} 13 | 14 | ### Personal 15 | * My personal website: [soygul.com](https://soygul.com){:target="_blank"}{:rel="noopener"} 16 | 17 | ### Contributing 18 | If you want to contribute to any article, you are welcome to make a pull request or create a new issue on GitHub. You can comment under YouTube videos of the articles, or read existing comments there. 19 | 20 | ### Intro Video 21 |

22 | -------------------------------------------------------------------------------- /ads.txt: -------------------------------------------------------------------------------- 1 | google.com, pub-2026571203025921, DIRECT, f08c47fec0942fa0 -------------------------------------------------------------------------------- /ai/meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory/media/ChatGPT-powered-chat-robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/ai/meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory/media/ChatGPT-powered-chat-robot.png -------------------------------------------------------------------------------- /ai/meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory/media/ai-manuel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/ai/meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory/media/ai-manuel.jpg -------------------------------------------------------------------------------- /ai/meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory/media/ai-manuel.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/ai/meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory/media/ai-manuel.psd -------------------------------------------------------------------------------- /ai/meet-our-new-tech-support-guy_fine-tuned-chatgpt-4-with-external-long-term-memory/media/supportbot_event_sequence.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Customer (asks question) 4 | 5 | 6 | 7 | 8 | 9 | Query Vector Database (Long-Term Memory) 10 | 11 | 12 | 13 | 14 | 15 | Semantically Related Context Data 16 | 17 | 18 | 19 | 20 | 21 | Fine-Tuned ChatGPT-4 Model (Domain-Specific) 22 | 23 | 24 | 25 | 26 | 27 | Chatbot Response 28 | 29 | -------------------------------------------------------------------------------- /algorithms/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # next.js build output 79 | .next 80 | 81 | # nuxt.js build output 82 | .nuxt 83 | 84 | # gatsby files 85 | .cache/ 86 | public 87 | 88 | # vuepress build output 89 | .vuepress/dist 90 | 91 | # Serverless directories 92 | .serverless/ 93 | 94 | # FuseBox cache 95 | .fusebox/ 96 | 97 | # DynamoDB Local files 98 | .dynamodb/ 99 | -------------------------------------------------------------------------------- /algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Algorithm Questions 2 | **For a list of all algorithm interview question articles, see [QuanticDev Home](/../../#algorithms)** 3 | 4 | Accompanying code for `Algorithm Questions` video series. 5 | 6 | Algorithms are categorized by their types (search, sort, dynamic, etc.) in directories. 7 | 8 | You can run the examples using `node file-name.js` or `python3 file-name.py`. 9 | -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/distributed-sorting.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const BinaryHeap = require('../../trees/heap/binary-heap') 3 | const TournamentTree = require('../../trees/tournament-tree/tournament-tree') 4 | 5 | /** 6 | * Distributed sorting algorithm implementation for my "Distributed Sorting" video: https://www.youtube.com/watch?v=vgKjatRVtys 7 | * The video explains the algorithm using animations so I highly recommend checking it out before reading the code. 8 | * 9 | * Sorts given data using desired number of computers (compute nodes). 10 | * 11 | * Data is divided into equally sized chunks and sent over to the compute nodes to be 12 | * sorted using heapsort. Once all data is sorted, the coordinator node pulls 13 | * the first element from each compute node and builds a loser tournament tree to do an n-way merge. 14 | * After that, the root node of the tournament tree (smallest element) is returned 15 | * and another element is pulled from the node that provided the returned element 16 | * and the root of the tournament tree is recalculated. This process continues until all the data in 17 | * all the nodes is consumed. 18 | * 19 | * Since a full implementation would require networking, 20 | * below code is simplified to make everything happen on the same computer. 21 | * 22 | * @param data - An array of integers to sort. 23 | * @param nodeCount - Number of computers to distribute this calculation over. 24 | * @returns {[]} - Sorted data. 25 | */ 26 | function distributedSort (data, nodeCount) { 27 | // split the data to chunks to be send to each node 28 | const nodes = [] 29 | const dataChunkLength = Math.ceil(data.length / nodeCount) 30 | 31 | for (let i = 0; i < nodeCount; i++) { 32 | nodes.push(createNode(data.slice(i * dataChunkLength, (i + 1) * dataChunkLength))) 33 | } 34 | 35 | // signal each node to start sorting their data 36 | nodes.forEach(n => n.sort()) 37 | 38 | // create a tournament tree and start doing k-way merge 39 | // by pulling one value at a time from each node 40 | const tree = new TournamentTree(nodes.map(n => n.getValue())) 41 | const mergedArr = [] 42 | 43 | for (let i = 1; i <= data.length; i++) { 44 | mergedArr.push(tree.popRoot()) 45 | 46 | const val = nodes[tree.missingLeafIndex].getValue() 47 | if (val) { 48 | tree.insertLeaf(val) 49 | } else { 50 | // when we exhaust all the data in a node, just plug in a sentinel value 51 | tree.insertLeaf(Infinity) 52 | } 53 | } 54 | 55 | return mergedArr 56 | } 57 | 58 | // creates and returns a compute node for sorting a chunk of data 59 | function createNode (dataChunk) { 60 | return { 61 | dataChunk: dataChunk, 62 | minHeap: new BinaryHeap([], false), 63 | sort: function () { 64 | this.dataChunk.forEach(val => this.minHeap.insert(val)) 65 | }, 66 | getValue: function () { 67 | return this.minHeap.popRoot() 68 | } 69 | } 70 | } 71 | 72 | /** 73 | * Tests 74 | */ 75 | 76 | // test case #1 77 | const exampleInput1 = [4, 10, 1, 14, 7, 9, 3, 5] 78 | const solution1 = [1, 3, 4, 5, 7, 9, 10, 14] 79 | 80 | const calculatedSolution1 = distributedSort(exampleInput1, 2) 81 | 82 | console.log(`Example Input Array #1: ${exampleInput1}, and the exact solution: ${solution1}, and calculated solution: ${calculatedSolution1}`) 83 | assert.deepStrictEqual(calculatedSolution1, solution1) 84 | -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/media/chromium_design_document_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/distributed-computing/distributed-sorting/media/chromium_design_document_template.png -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/media/distributed_sort_problem_definition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/distributed-computing/distributed-sorting/media/distributed_sort_problem_definition.png -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/media/intro.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/distributed-computing/distributed-sorting/media/intro.mp4 -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/media/leader_controller_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/distributed-computing/distributed-sorting/media/leader_controller_group.png -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/media/node_failure.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/distributed-computing/distributed-sorting/media/node_failure.mp4 -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/media/problem_visualization.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/distributed-computing/distributed-sorting/media/problem_visualization.mp4 -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/media/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/distributed-computing/distributed-sorting/media/thumb.png -------------------------------------------------------------------------------- /algorithms/distributed-computing/distributed-sorting/media/tournament_tree.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/distributed-computing/distributed-sorting/media/tournament_tree.mp4 -------------------------------------------------------------------------------- /algorithms/dynamic-programming/common-sequences/longest-common-subsequence.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Given two arrays, find their longest common subsequence. 5 | * 6 | * @param inputArr1 - First array. 7 | * @param inputArr2 - Second array. 8 | * @returns {[]} - Longest common subsequence of the two inputs. 9 | */ 10 | function longestCommonSubsequence_BottomUp (inputArr1, inputArr2) { 11 | const lcs = [] 12 | 13 | inputArr1.forEach((char1, index1) => { 14 | inputArr2.forEach((char2, index2) => { 15 | // rules: 16 | // if char1 !== char2: take largest of the right diagonal value 17 | // if char1 === char2: take left diagonal value + 1 18 | if (char1 === char2) lcs.push([]) 19 | }) 20 | }) 21 | 22 | return lcs 23 | } 24 | 25 | // same algorithms but implemented with Dynamic Programming (memoized recursion) 26 | // this is a way worse solution both in space and time complexity but easier to write 27 | function longestCommonSubsequence_Recursion (inputArr1, inputArr2) { 28 | const lcs = [] 29 | 30 | 31 | 32 | return lcs 33 | } 34 | 35 | /** 36 | * Tests 37 | */ 38 | 39 | // test case #1 40 | const inputArr1 = 'abccdef' 41 | const inputArr2 = 'abed' 42 | const solution1 = 'abd' 43 | 44 | const calculatedSolution1 = longestCommonSubsequence_BottomUp(inputArr1.split(''), inputArr2.split('')) 45 | 46 | console.log(`Example Input #1: ${inputArr1}, Input #2: ${inputArr2}, Solution: ${calculatedSolution1}`) 47 | assert.deepStrictEqual(calculatedSolution1, solution1) 48 | 49 | // todo: test for lcs of '' and 'abcc..' 50 | -------------------------------------------------------------------------------- /algorithms/dynamic-programming/kadanes-algorithm/README.md: -------------------------------------------------------------------------------- 1 | # Kadane's Algorithm and Its Proof - Max/Min Sum Subarray Problem 2 | In this article, you will get the optimum solution to the maximum/minimum sum subarray problem: The Kadane's Algorithm. The problem at hand is simple. Given an array of integers, say `[-1, 1, 3, -2]`, find the subarrays with the maximum and minimum possible sums (for the given example: `max=[1, 3]`, `min=[-2]`). Kadane's Algorithm solves this problem with a nice `O(n)` time and `O(1)` space complexity. A variation of this problem is when you are trying to find the maximum/minimum sum subarray with at least `k` elements. Again, a slightly modified version of Kadane's Algo can be used in solving it. Finally, we will prove the correctness of Kadane's Algorithms. 3 | 4 | In the article, you will find the solutions to the following questions, as well as their time and space complexities: 5 | * Medium Difficulty: Kadane's Algorithm: Given an array of integers, find the subarray with the maximum/minimum possible sum. 6 | * Medium Difficulty: Sliding Window on Kadane's Algorithm: Given an array of integers, find the subarray with the maximum/minimum possible sum with at least k elements. 7 | * Hard: Prove Kadane's Algorithm: Prove the correctness of Kadane's Algorithm. 8 | 9 | ## Resources 10 | You can find the video narration of this article on YouTube: [https://www.youtube.com/watch?v=4csAswCkXZM](https://www.youtube.com/watch?v=4csAswCkXZM){:target="_blank"}{:rel="noopener"} 11 | 12 | 13 | 14 | Video has additional tips and illustrations. If you want to read the comments or leave a comment, do so under YouTube video. If you want to contribute to the article, make a pull request on GitHub. 15 | 16 | * Solution code to examples are available on: [https://github.com/soygul/QuanticDev/tree/master/algorithms/dynamic-programming/kadanes-algorithm](https://github.com/soygul/QuanticDev/tree/master/algorithms/dynamic-programming/kadanes-algorithm){:target="_blank"}{:rel="noopener"} 17 | 18 | * My Sliding Window Technique article: [Sliding Window Technique + 4 Questions](/algorithms/dynamic-programming/sliding-window){:target="_blank"}{:rel="noopener"} 19 | 20 | ## Overview 21 | When all integers in a given array are positive, you can use the much simpler Sliding Windows Technique. For arrays with negative numbers, you can modify it to be all positive numbers and then apply the sliding window technique, but that requires extra processing; hence it is not the optimum solution. I have a separate article discussing the sliding window technique in depth along with various sample questions, and you can find the link to it above. 22 | 23 | Kadane's Algorithm uses optimal substructures to solve the max/min subarray sum problem. Each max/min subarray ending at each index is calculated using the max/min subarray ending at the previous index. You can say that this is an accumulation function with some additional rules. As a result of this, it is one of my favorite examples of Dynamic Programming. In the article, I will explain how Kadane's Algorithm is an optimal substructure problem using a basic animation. 24 | 25 | ## Question #1: Medium Difficulty: Given an array of integers, find the subarray with the maximum/minimum possible sum 26 | Example Input: `[1, 2, -4, 3, 4, -2]` 27 | 28 | Requirements Analysis: 29 | * Analyze the requirements even in simple questions, they might not be so simple! 30 | * Input size could be anything so we should limit memory usage. 31 | * We should be able to handle negative numbers. 32 | 33 | Problem Analysis: 34 | * Input size is unlimited, so memory can blow up if we are not careful of what we keep in memory. 35 | * Do not pre-calculate and store all possible variations beforehand (brute force approach). 36 | * Do not use recursion. Call stack will overflow. 37 | * Think of corner cases like empty array, all negative numbers, all zeroes, etc. 38 | 39 | Approach #1: Brute Force 40 | * Calculate all possible subarray sums and store them in a separate array. 41 | * Iterate over the sums array and return the maximum or minimum sum. 42 | * Time complexity: `~O(n^2)` (quadratic time complexity) 43 | * Space complexity: `~O(n^2)` (quadratic space complexity) 44 | 45 | Approach #2: Kadane's Algorithm 46 | * Start summing the elements starting with the first element. Record the max sum as 0. 47 | * If current sum is greater than the max sum, assign it to the max sum. 48 | * If current sum is less than 0, restart summing from the next element. 49 | * Time complexity: `O(n)` (linear time complexity) 50 | * Space complexity: `O(1)` (constant space complexity) 51 | * Inverse the "less than / greater than" checks to find the minimum subarray sum. 52 | * You can find the code for this solution at: [https://github.com/soygul/QuanticDev/blob/master/algorithms/dynamic-programming/kadanes-algorithm/max-min-sum-subarray.js](https://github.com/soygul/QuanticDev/blob/master/algorithms/dynamic-programming/kadanes-algorithm/max-min-sum-subarray.js){:target="_blank"}{:rel="noopener"} 53 | * You can also watch me solving this problem in the video in the resources section. 54 | 55 | ## How Does It Work? 56 | 57 | 58 | Rules: 59 | * Maximum subarray sum at every index = maximum subarray sum at previous index + element value at index 60 | * If max sum at an index is < 0, set sum at that index to 0. 61 | * `MaxSum(index) = Max(MaxSum(index - 1) + arr[index], 0)` 62 | 63 | ## Tips! 64 | * You can use a modified version of Sliding Windows Technique instead of Kadane's Algorithm. It is simpler but not as efficient. If you are interested, I have the link to my Sliding Window Technique article in the resources section above. 65 | * Kadane's Algorithm is just a specialized accumulation algorithm. You will frequently see it and similar accumulation algorithms in programming interviews. 66 | 67 | ## Question #2: Medium Difficulty: Given an array of integers, find the subarray with the maximum/minimum possible sum with at least k elements 68 | Example Input `(k=3)`: `[1, 2, -4, 3, 4, -2]` 69 | 70 | Max Sum at Each Index: `[1, 3, 0, 3, 7, 5]` 71 | 72 | Solution: Sliding Window on Kadane's Algorithm 73 | * Apply Kadane's Algorithm to the array and store maximum sum up to every index in another array. 74 | * Use a sliding sum window of k elements on given array. Check if max sum at previous index makes the sliding window sum bigger. 75 | * Time Complexity: `O(n)` 76 | * Space Complexity: `O(n)` (can be made `O(1)`) 77 | 78 | ## Proof of Correctness of Kadane's Algorithm 79 | * Define: `MaxSum(i) = Max(Sum(0->i), Sum(1->i), Sum(2->i), ..., Sum(i->i))` where `Sum(x->i)` is the sum of all elements from index x to i. So we list all possible subarrays and take the one with the maximum sum here. We established this in the brute-force solution. 80 | * Note: `Sum(x->i+1) = Sum(x->i) + El(i+1)` where `El(i+1)` is the element value at index `i+1`. 81 | * As a Result: `MaxSum(i+1) = Max(Sum(0->i) + El(i), Sum(1->i) + El(i+1), ..., Sum(i->i) + El(i+1), El(i+1))= Max(Max(Sum(0->i) + El(i+1), Sum(1->i) + El(i+1), ..., Sum(i->i) + El(i+1)), El(i+1))` 82 | * Note: `max(a+y, b+y, c+y)=max(a, b, c) + y` 83 | * As a Result: `MaxSum(i+1) = Max(Max(Sum(0->i), Sum(1->i), Sum(2->i), ..., Sum(i->i)) + El(i+1), El(i+1))= Max(MaxSum(i) + El(i+1), El(i+1))` 84 | * Note: We used `MaxSum(i+1) = Max(MaxSum(i) + El(i+1), 0)` in our problems before, which is also valid. 85 | * You can also use `induction` or `contradiction` to prove Kadane's Algorithm. 86 | 87 | ## More Tips! 88 | * In interviews, you can always get questions combining multiple algorithms and techniques. 89 | * You can be asked to prove the correctness of an algorithm in a more senior interview. 90 | * You can check out rest of my algorithms articles on the home page. 91 | 92 | ## Video Solutions 93 | If you want video solutions for the above questions, visit the YouTube link in the resources section. The video has a lot more in-depth info on solution techniques along with helpful visuals. 94 | -------------------------------------------------------------------------------- /algorithms/dynamic-programming/kadanes-algorithm/max-min-sum-subarray.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Given an array of integers, find the subarray with the maximum/minimum possible sum. 5 | * There might be multiple subarrays with the same sum, but we only keep track of one. 6 | * Solution is implemented using Kadane's Algorithm. 7 | * 8 | * If you want to see the video description of this algorithm, you can find it here: https://www.youtube.com/watch?v=4csAswCkXZM 9 | * It has animated description and several interview questions and their solutions in it. 10 | * 11 | * @param inputArr - An array of integers. 12 | * @param isMaxSum - If true, find the subarray with the maximum possible sum. If false, find the minimum instead. 13 | * @returns [] - The subarray with the maximum/minimum possible sum. 14 | */ 15 | function getMaxMinSubarray (inputArr, isMaxSum = true) { 16 | // validate the input 17 | assert(Array.isArray(inputArr) && inputArr.every(n => Number.isInteger(n)), 'Input should be an array of integers.') 18 | 19 | // now calculate the maximum (or minimum) sum up to each index using kadane's algo 20 | let currentSum = 0; let currentSumStart = 0; let currentSumEnd = 0 21 | let maxSum = 0; let maxSumStart = 0; let maxSumEnd = 0 22 | const maxMinFn = isMaxSum ? Math.max : Math.min 23 | 24 | inputArr.forEach((n, i) => { 25 | if (currentSum === 0) currentSumStart = i 26 | currentSumEnd = i 27 | currentSum = maxMinFn(0, currentSum + n) 28 | 29 | maxSum = maxMinFn(maxSum, currentSum) 30 | if (maxSum === currentSum) { 31 | maxSumStart = currentSumStart 32 | maxSumEnd = currentSumEnd 33 | } 34 | }) 35 | 36 | return maxSum === 0 ? [] : inputArr.slice(maxSumStart, maxSumEnd + 1) 37 | } 38 | 39 | /** 40 | * Tests 41 | */ 42 | 43 | // test case #1: mixed integers 44 | const exampleInput1 = [-5, 2, -1, 3, -2] 45 | const maxSolution1 = [2, -1, 3] 46 | const minSolution1 = [-5] 47 | 48 | const calculatedMaxSolution1 = getMaxMinSubarray(exampleInput1, true) 49 | const calculatedMinSolution1 = getMaxMinSubarray(exampleInput1, false) 50 | 51 | console.log(`Example Input #1: ${JSON.stringify(exampleInput1)}, Max Sum Subarray: ${JSON.stringify(calculatedMaxSolution1)}, Min Sum Subarray: ${JSON.stringify(calculatedMinSolution1)}`) 52 | assert.deepStrictEqual(calculatedMaxSolution1, maxSolution1) 53 | assert.deepStrictEqual(calculatedMinSolution1, minSolution1) 54 | 55 | // test case #2: empty array 56 | const exampleInput2 = [] 57 | const maxSolution2 = [] 58 | const minSolution2 = [] 59 | 60 | const calculatedMaxSolution2 = getMaxMinSubarray(exampleInput2, true) 61 | const calculatedMinSolution2 = getMaxMinSubarray(exampleInput2, false) 62 | 63 | console.log(`Example Input #2: ${JSON.stringify(exampleInput2)}, Max Sum Subarray: ${JSON.stringify(calculatedMaxSolution2)}, Min Sum Subarray: ${JSON.stringify(calculatedMinSolution2)}`) 64 | assert.deepStrictEqual(calculatedMaxSolution2, maxSolution2) 65 | assert.deepStrictEqual(calculatedMinSolution2, minSolution2) 66 | 67 | // test case #3: all 0's 68 | const exampleInput3 = [0, 0, 0] 69 | const maxSolution3 = [] 70 | const minSolution3 = [] 71 | 72 | const calculatedMaxSolution3 = getMaxMinSubarray(exampleInput3, true) 73 | const calculatedMinSolution3 = getMaxMinSubarray(exampleInput3, false) 74 | 75 | console.log(`Example Input #3: ${JSON.stringify(exampleInput3)}, Max Sum Subarray: ${JSON.stringify(calculatedMaxSolution3)}, Min Sum Subarray: ${JSON.stringify(calculatedMinSolution3)}`) 76 | assert.deepStrictEqual(calculatedMaxSolution3, maxSolution3) 77 | assert.deepStrictEqual(calculatedMinSolution3, minSolution3) 78 | 79 | // test case #4: all negative 80 | const exampleInput4 = [-1, -2, -3, -4, -5] 81 | const maxSolution4 = [] 82 | const minSolution4 = [-1, -2, -3, -4, -5] 83 | 84 | const calculatedMaxSolution4 = getMaxMinSubarray(exampleInput4, true) 85 | const calculatedMinSolution4 = getMaxMinSubarray(exampleInput4, false) 86 | 87 | console.log(`Example Input #4: ${JSON.stringify(exampleInput4)}, Max Sum Subarray: ${JSON.stringify(calculatedMaxSolution4)}, Min Sum Subarray: ${JSON.stringify(calculatedMinSolution4)}`) 88 | assert.deepStrictEqual(calculatedMaxSolution4, maxSolution4) 89 | assert.deepStrictEqual(calculatedMinSolution4, minSolution4) 90 | 91 | // test case #5: all positive 92 | const exampleInput5 = [1, 2, 3, 4, 5] 93 | const maxSolution5 = [1, 2, 3, 4, 5] 94 | const minSolution5 = [] 95 | 96 | const calculatedMaxSolution5 = getMaxMinSubarray(exampleInput5, true) 97 | const calculatedMinSolution5 = getMaxMinSubarray(exampleInput5, false) 98 | 99 | console.log(`Example Input #5: ${JSON.stringify(exampleInput5)}, Max Sum Subarray: ${JSON.stringify(calculatedMaxSolution5)}, Min Sum Subarray: ${JSON.stringify(calculatedMinSolution5)}`) 100 | assert.deepStrictEqual(calculatedMaxSolution5, maxSolution5) 101 | assert.deepStrictEqual(calculatedMinSolution5, minSolution5) 102 | -------------------------------------------------------------------------------- /algorithms/dynamic-programming/kadanes-algorithm/media/kadanes-algorithm.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/dynamic-programming/kadanes-algorithm/media/kadanes-algorithm.mp4 -------------------------------------------------------------------------------- /algorithms/dynamic-programming/sliding-window/desired-subarray-sum.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Given a array of positive integers, find the subarrays of integers that add up to a given number. 5 | * 6 | * If you want to see the video description of this algorithm, you can find it here: https://www.youtube.com/watch?v=jM2dhDPYMQM 7 | * It has animated description and several interview questions and their solutions in it. 8 | * 9 | * @param inputArr - An array of positive integers. 10 | * @param desiredSum - The desired sum as an integer. 11 | * @returns {[]} - An array of subarrays that add up to the desired sum. 12 | */ 13 | function getSubarrays (inputArr, desiredSum) { 14 | // validate input 15 | assert(desiredSum > 0, 'Desired sum must be greater than 0.') 16 | 17 | // current window sum and window sum start index 18 | let sum = 0; let sumStartIndex = 0 19 | const solutions = [] 20 | 21 | inputArr.forEach((item, index) => { 22 | sum += item 23 | 24 | while (sum > desiredSum) { 25 | sum -= inputArr[sumStartIndex] 26 | sumStartIndex++ 27 | } 28 | 29 | if (sum === desiredSum) solutions.push(inputArr.filter((_, i) => i >= sumStartIndex && i <= index)) 30 | }) 31 | 32 | return solutions 33 | } 34 | 35 | /** 36 | * Tests 37 | */ 38 | 39 | // test case #1 40 | const exampleInput1 = [1, 7, 9, 4, 3, 2, 2] 41 | const desiredSum1 = 7 42 | const solution1 = [[7], [4, 3], [3, 2, 2]] 43 | 44 | const calculatedSolution1 = getSubarrays(exampleInput1, desiredSum1) 45 | 46 | console.log(`Example Input #1: ${JSON.stringify(exampleInput1)}, Desired Sum: ${desiredSum1}, Solution: ${JSON.stringify(calculatedSolution1)}`) 47 | assert.deepStrictEqual(calculatedSolution1, solution1) 48 | 49 | // test case #2 50 | const exampleInput2 = [23, 1, 6, 9, 15, 8] 51 | const desiredSum2 = 24 52 | const solution2 = [[23, 1], [9, 15]] 53 | 54 | const calculatedSolution2 = getSubarrays(exampleInput2, desiredSum2) 55 | 56 | console.log(`Example Input #2: ${JSON.stringify(exampleInput2)}, Desired Sum: ${desiredSum2}, Solution: ${JSON.stringify(calculatedSolution2)}`) 57 | assert.deepStrictEqual(calculatedSolution2, solution2) 58 | 59 | // test case #3 60 | // sliding window technique cannot handle negative numbers in this case so solution will not be full 61 | const exampleInput3 = [-1, -4, 0, 5, 3, 2, 1] 62 | const desiredSum3 = 5 63 | const solution3 = [[-1, -4, 0, 5, 3, 2], [5], [3, 2]] 64 | 65 | const calculatedSolution3 = getSubarrays(exampleInput3, desiredSum3) 66 | 67 | console.log(`Example Input #3: ${JSON.stringify(exampleInput3)}, Desired Sum: ${desiredSum3}, Solution (some missing): ${JSON.stringify(calculatedSolution3)}`) 68 | assert.notDeepStrictEqual(calculatedSolution3, solution3) 69 | -------------------------------------------------------------------------------- /algorithms/dynamic-programming/sliding-window/max-sequence-by-flipping.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Given an array of 0's and 1's, 5 | * find the maximum sequence of continuous 1's that can be formed by flipping at-most k 0's to 1's. 6 | * 7 | * If you want to see the video description of this algorithm, you can find it here: https://www.youtube.com/watch?v=jM2dhDPYMQM 8 | * It has animated description and several interview questions and their solutions in it. 9 | * 10 | * @param inputArr - An array of 0's and 1's. 11 | * @param maxFlips - Maximum no of 0's that can be flipped to 1's. 12 | * @returns {number} - Length of the maximum possible sequence of continuous 1's. 13 | */ 14 | function getMaxSequence (inputArr, maxFlips) { 15 | // validate input 16 | assert(maxFlips >= 0, 'Max flips cannot be negative.') 17 | 18 | let subArrStart = 0; let subArrEnd = 0 19 | let flippedZeroes = 0 20 | let longestSubArr = { start: 0, end: 0, len: 0 } 21 | 22 | inputArr.forEach((item, index) => { 23 | // always start by increasing window size 24 | subArrEnd = index 25 | 26 | if (item === 0) flippedZeroes++ 27 | 28 | const subArrLen = 1 + subArrEnd - subArrStart 29 | if (flippedZeroes <= maxFlips && subArrLen > longestSubArr.len) longestSubArr = { start: subArrStart, end: subArrEnd, len: subArrLen } 30 | 31 | // decrease window size until we are less than or equal to the max flip limit 32 | while (flippedZeroes > maxFlips) { 33 | if (inputArr[subArrStart] === 0) flippedZeroes-- 34 | 35 | subArrStart++ 36 | } 37 | }) 38 | 39 | return inputArr.slice(longestSubArr.start, longestSubArr.end + 1) 40 | } 41 | 42 | /** 43 | * Tests 44 | */ 45 | 46 | // test case #1 47 | const exampleInput1 = [1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0] 48 | const maxFlips1 = 2 49 | const solution1 = [0, 1, 1, 0, 1, 1] 50 | 51 | const calculatedSolution1 = getMaxSequence(exampleInput1, maxFlips1) 52 | 53 | console.log(`Example Input #1: ${JSON.stringify(exampleInput1)}, Maximum Flips: ${maxFlips1}, Solution: ${JSON.stringify(calculatedSolution1)} (Length: ${calculatedSolution1.length})`) 54 | assert.deepStrictEqual(calculatedSolution1, solution1) 55 | 56 | // test case #2 57 | const exampleInput2 = [0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0] 58 | const maxFlips2 = 3 59 | const solution2 = [1, 0, 0, 0, 1, 1, 1, 1] 60 | 61 | const calculatedSolution2 = getMaxSequence(exampleInput2, maxFlips2) 62 | 63 | console.log(`Example Input #2: ${JSON.stringify(exampleInput2)}, Maximum Flips: ${maxFlips2}, Solution: ${JSON.stringify(calculatedSolution2)} (Length: ${calculatedSolution1.length})`) 64 | assert.deepStrictEqual(calculatedSolution2, solution2) 65 | -------------------------------------------------------------------------------- /algorithms/dynamic-programming/sliding-window/max-subarray-sum.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Given an array of integers, find maximum sum subarray of the required size. 5 | * 6 | * If you want to see the video description of this algorithm, you can find it here: https://www.youtube.com/watch?v=jM2dhDPYMQM 7 | * It has animated description and several interview questions and their solutions in it. 8 | * 9 | * @param inputArr - An array of integers. 10 | * @param subarraySize - Desired subarray size as a positive integer. 11 | * @returns [] - A subarray of size {subarraySize} that has the maximum possible sum. 12 | */ 13 | function getMaxSubarray (inputArr, subarraySize) { 14 | // validate input 15 | assert(subarraySize > 0, 'Subarray size must be positive.') 16 | 17 | let currentSum = 0 18 | let maxSum = 0; let maxSumStartIndex = 0 19 | 20 | // iterate entire array from left to right 21 | inputArr.forEach((number, index) => { 22 | // increase the window size by one from the right 23 | currentSum += number 24 | 25 | if (index < subarraySize) { 26 | // continue to accumulate until we reach the desired subarray size (= max window size) 27 | maxSum = currentSum 28 | } else { 29 | // we are over the max window size so remove one element from the left 30 | currentSum -= inputArr[index - subarraySize] 31 | 32 | if (currentSum > maxSum) { 33 | // we have a new maximum sum window so record its starting index 34 | maxSum = currentSum 35 | maxSumStartIndex = index - subarraySize + 1 36 | } 37 | } 38 | }) 39 | 40 | return inputArr.slice(maxSumStartIndex, maxSumStartIndex + subarraySize) 41 | } 42 | 43 | /** 44 | * Tests 45 | */ 46 | 47 | // test case #1 48 | const exampleInput1 = [-1, 2, 3, 0, -3, 9] 49 | const subarraySize1 = 2 50 | const solution1 = [-3, 9] 51 | 52 | const calculatedSolution1 = getMaxSubarray(exampleInput1, subarraySize1) 53 | 54 | console.log(`Example Input #1: ${JSON.stringify(exampleInput1)}, Subarray Size: ${subarraySize1}, Solution: ${JSON.stringify(calculatedSolution1)}`) 55 | assert.deepStrictEqual(calculatedSolution1, solution1) 56 | 57 | // test case #2 58 | const exampleInput2 = [6, 0, -1, 2, 1, -3, 4] 59 | const subarraySize2 = 3 60 | const solution2 = [6, 0, -1] 61 | 62 | const calculatedSolution2 = getMaxSubarray(exampleInput2, subarraySize2) 63 | 64 | console.log(`Example Input #2: ${JSON.stringify(exampleInput2)}, Subarray Size: ${subarraySize2}, Solution: ${JSON.stringify(calculatedSolution2)}`) 65 | assert.deepStrictEqual(calculatedSolution2, solution2) 66 | 67 | // test case #3 68 | const exampleInput3 = [6, -3, -5, 1, 2, 0, 4] 69 | const subarraySize3 = 4 70 | const solution3 = [1, 2, 0, 4] 71 | 72 | const calculatedSolution3 = getMaxSubarray(exampleInput3, subarraySize3) 73 | 74 | console.log(`Example Input #3: ${JSON.stringify(exampleInput3)}, Subarray Size: ${subarraySize3}, Solution: ${JSON.stringify(calculatedSolution3)}`) 75 | assert.deepStrictEqual(calculatedSolution3, solution3) 76 | -------------------------------------------------------------------------------- /algorithms/dynamic-programming/sliding-window/media/sliding_window_technique.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/dynamic-programming/sliding-window/media/sliding_window_technique.mp4 -------------------------------------------------------------------------------- /algorithms/dynamic-programming/sliding-window/shortest-substring-of-letters.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Given a string and n characters, find the shortest substring that contains all the given characters. 5 | * 6 | * If you want to see the video description of this algorithm, you can find it here: https://www.youtube.com/watch?v=jM2dhDPYMQM 7 | * It has animated description and several interview questions and their solutions in it. 8 | * 9 | * @param inputString - Any string. 10 | * @param characters - A string of characters that the substring should contain. 11 | * @returns {string} - The shortest substring containing all the desired characters. 12 | */ 13 | function getShortestSubstring (inputString, characters) { 14 | // current sliding window starting index 15 | let windowStartIndex = 0 16 | 17 | // start/end indexes of smallest window that has all the needed chars 18 | let smallestWindowStartIndex = 0; let smallestWindowEndIndex = 0 19 | 20 | // calculate how many times of which characters we need to find, resulting object will be like: {a: 2, b: 4, x: 1} 21 | const neededCharCounts = characters.split('').reduce((freq, char) => { freq[char] ? freq[char]++ : freq[char] = 1; return freq }, {}) 22 | 23 | // how many of the needed chars we didn't find yet in the current window 24 | let missingCharCount = characters.length 25 | 26 | // traverse the entire string and look for missing needed chars 27 | for (let windowEndIndex = 0; windowEndIndex < inputString.length; windowEndIndex++) { 28 | const char = inputString[windowEndIndex] 29 | 30 | // if we found one of the missing needed chars, decrease its needed count by one 31 | if (char in neededCharCounts) { 32 | if (neededCharCounts[char] > 0) missingCharCount-- 33 | 34 | // needed count might fall to negative since the current window might contain the needed char too many times 35 | neededCharCounts[char]-- 36 | } 37 | 38 | // if we managed to find all the needed chars in the current sliding window 39 | // repeatedly shrink the window from left as long we still have all the needed chars in the window 40 | if (!missingCharCount) { 41 | let leftChar = inputString[windowStartIndex] 42 | while (windowStartIndex < windowEndIndex && (!(leftChar in neededCharCounts) || neededCharCounts[leftChar] < 0)) { 43 | if (leftChar in neededCharCounts) neededCharCounts[leftChar]++ 44 | windowStartIndex++ 45 | leftChar = inputString[windowStartIndex] 46 | } 47 | 48 | // take note of the smallest window (that has all the needed chars) that we found up to this moment 49 | if (!smallestWindowEndIndex || (windowEndIndex - windowStartIndex) < (smallestWindowEndIndex - smallestWindowStartIndex)) { 50 | smallestWindowStartIndex = windowStartIndex 51 | smallestWindowEndIndex = windowEndIndex 52 | } 53 | } 54 | } 55 | 56 | return inputString.slice(smallestWindowStartIndex, smallestWindowEndIndex + 1) 57 | } 58 | 59 | /** 60 | * Tests 61 | */ 62 | 63 | // test case #1 64 | const exampleInput1 = 'a93kdabc991cba35fg' 65 | const desiredCharacters1 = 'abcabc' 66 | const solution1 = 'abc991cba' 67 | 68 | const calculatedSolution1 = getShortestSubstring(exampleInput1, desiredCharacters1) 69 | 70 | console.log(`Example Input #1: ${exampleInput1}, Desired Characters: ${desiredCharacters1}, Solution: ${calculatedSolution1}`) 71 | assert.deepStrictEqual(calculatedSolution1, solution1) 72 | 73 | // test case #2 74 | const exampleInput2 = 'asb2.9d/d!304#b$%^%!ksd,2294iubasdmc' 75 | const desiredCharacters2 = 'b$#2' 76 | const solution2 = '#b$%^%!ksd,2' 77 | 78 | const calculatedSolution2 = getShortestSubstring(exampleInput2, desiredCharacters2) 79 | 80 | console.log(`Example Input #2: ${exampleInput2}, Desired Characters: ${desiredCharacters2}, Solution: ${calculatedSolution2}`) 81 | assert.deepStrictEqual(calculatedSolution2, solution2) 82 | 83 | // test case #3 84 | const exampleInput3 = 'xad9dk0293nc' 85 | const desiredCharacters3 = 'xd3' 86 | const solution3 = 'xad9dk0293' 87 | 88 | const calculatedSolution3 = getShortestSubstring(exampleInput3, desiredCharacters3) 89 | 90 | console.log(`Example Input #3: ${exampleInput3}, Desired Characters: ${desiredCharacters3}, Solution: ${calculatedSolution3}`) 91 | assert.deepStrictEqual(calculatedSolution3, solution3) 92 | 93 | // test case #4 94 | const exampleInput4 = 'gho8cbb' 95 | const desiredCharacters4 = 'bob' 96 | const solution4 = 'o8cbb' 97 | 98 | const calculatedSolution4 = getShortestSubstring(exampleInput4, desiredCharacters4) 99 | 100 | console.log(`Example Input #4: ${exampleInput4}, Desired Characters: ${desiredCharacters4}, Solution: ${calculatedSolution4}`) 101 | assert.deepStrictEqual(calculatedSolution4, solution4) 102 | -------------------------------------------------------------------------------- /algorithms/dynamic-programming/staircase-problems/media/alternative_big_o_notation_mug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/dynamic-programming/staircase-problems/media/alternative_big_o_notation_mug.jpg -------------------------------------------------------------------------------- /algorithms/dynamic-programming/staircase-problems/media/memoized_recursive_fibonacci_animation.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/dynamic-programming/staircase-problems/media/memoized_recursive_fibonacci_animation.mp4 -------------------------------------------------------------------------------- /algorithms/dynamic-programming/staircase-problems/media/recursion_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/dynamic-programming/staircase-problems/media/recursion_tree.png -------------------------------------------------------------------------------- /algorithms/dynamic-programming/staircase-problems/media/recursive_fibonacci_animation.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/dynamic-programming/staircase-problems/media/recursive_fibonacci_animation.mp4 -------------------------------------------------------------------------------- /algorithms/dynamic-programming/staircase-problems/media/staircase_problem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/dynamic-programming/staircase-problems/media/staircase_problem.png -------------------------------------------------------------------------------- /algorithms/dynamic-programming/staircase-problems/media/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/dynamic-programming/staircase-problems/media/thumb.png -------------------------------------------------------------------------------- /algorithms/dynamic-programming/staircase-problems/staircase-problems.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is the solution to the staircase problem using Fibonacci-like sequences. 3 | If you want to see the other solutions as well some other staircase problem variants, see the JavaScript file. 4 | 5 | If you want to see the video description of this algorithm, you can find it here: https://www.youtube.com/watch?v=qSE2iKRU4UA 6 | It has animated description and several interview questions and their solutions in it. 7 | """ 8 | 9 | 10 | def climb_stairs(stair_count, max_steps): 11 | """ 12 | Given n number of stairs, you can climb at most m stairs at a time. 13 | For instance, for m=3, you can climb 1, 2, or 3 stairs at a time. 14 | Count the number of different ways that you can reach to the top. 15 | 16 | Solution below uses the optimal approach of calculating the solution using a Fibonacci-like sequence. 17 | 18 | Time Complexity: O(m*n) 19 | Space Complexity: O(m) 20 | 21 | :param stair_count: No of stairs to climb (n). 22 | :param max_steps: Max no of stairs you can climb at a time (m). 23 | :return: Number of different ways to reach the top. 24 | """ 25 | if stair_count <= 1: 26 | return stair_count 27 | if max_steps <= 1: 28 | return 1 29 | 30 | stairs = [1] 31 | for _ in range(stair_count): 32 | stairs.append(sum(stairs)) 33 | if len(stairs) > max_steps: 34 | stairs.pop(0) 35 | return stairs[-1] 36 | 37 | 38 | # tests 39 | assert climb_stairs(0, 2) == 0 40 | assert climb_stairs(1, 2) == 1 41 | assert climb_stairs(2, 2) == 2 42 | assert climb_stairs(7, 2) == 21 43 | assert climb_stairs(40, 1) == 1 44 | assert climb_stairs(16, 7) == 31489 45 | assert climb_stairs(30, 30) == 536870912 46 | 47 | print('done: all tests pass') 48 | -------------------------------------------------------------------------------- /algorithms/merge/k-way-merge.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const TournamentTree = require('../trees/tournament-tree/tournament-tree') 3 | 4 | /** 5 | * Given k sorted arrays, merge them into a single sorted array. 6 | * 7 | * In this solution, we will use tournament trees to generate a single sorted array as efficiently as possible. 8 | * 9 | * This is a rather large topic and I highly recommend you check out my animated video on this topic to get a better 10 | * understanding of this problem and it's variants (like distributed sort) and their solutions. 11 | * You can find the video here: https://www.youtube.com/watch?v=Xo54nlPHSpg 12 | * 13 | * Time Complexity: Θ(n logk) - Notice the big Theta notation. k is the number of given input arrays. 14 | * Auxiliary Space: ~2k (to store the tournament tree) + n to store the output 15 | * 16 | * @param inputArrays - An array of arrays to be merged. 17 | * @returns - The merged array (sorted). 18 | */ 19 | function kWayMerge (inputArrays) { 20 | // validate the input 21 | assert(Array.isArray(inputArrays) && inputArrays.every(arr => Array.isArray(arr)), 'Input should be an array of arrays.') 22 | 23 | const totalElements = inputArrays.map(a => a.length).reduce((total, current) => total + current) 24 | const tree = new TournamentTree(inputArrays.map(a => a.shift())) 25 | const mergedArr = [] 26 | 27 | // put the top element from each array into a tournament tree and get the smallest element from the tree root 28 | for (let i = 1; i <= totalElements; i++) { 29 | mergedArr.push(tree.popRoot()) 30 | 31 | if (inputArrays[tree.missingLeafIndex]) { 32 | tree.insertLeaf(inputArrays[tree.missingLeafIndex].shift()) 33 | } else { 34 | // when we exhaust all the data in an array, just plug in a sentinel value 35 | tree.insertLeaf(Infinity) 36 | } 37 | } 38 | 39 | return mergedArr 40 | } 41 | 42 | /** 43 | * Tests 44 | */ 45 | 46 | // test case #1 47 | const exampleInput1 = [[4, 9], [1, 7], [3, 6]] 48 | const solution1 = [1, 3, 4, 6, 7, 9] 49 | 50 | const calculatedSolution1 = kWayMerge(exampleInput1) 51 | 52 | console.log(`Example Input #1: Expected Solution: ${JSON.stringify(solution1)}, Calculated Solution: ${JSON.stringify(calculatedSolution1)}`) 53 | assert.deepStrictEqual(calculatedSolution1, solution1) 54 | -------------------------------------------------------------------------------- /algorithms/merge/two-way-merge.py: -------------------------------------------------------------------------------- 1 | def two_way_merge(array1, array2): 2 | """ 3 | Given two sorted arrays, merge them into a single sorted array. 4 | 5 | This is a very simple operation but is a precursor to k-way merge. 6 | We compare each element at the beginning of each array and remove smaller one and add it to the merged array. 7 | If one of the arrays run out of elements, we just copy rest of the other array into the merged array and return. 8 | 9 | Time Complexity: O(n) - Since we only need to do one comparison operation per element. 10 | Auxiliary Space: O(n) - We will store the final sorted data in an array of size O(n), 11 | which is the combined length of the given arrays. 12 | 13 | If you want to see the fully animated video explanation, it is here: https://www.youtube.com/watch?v=Xo54nlPHSpg 14 | 15 | :param array1: A sorted array of values. 16 | :param array2: Another sorted array of values. 17 | :return: A single sorted array. 18 | """ 19 | 20 | longer_arr_len = len(array1) + len(array2) 21 | merged_arr = [] 22 | 23 | for i in range(longer_arr_len): 24 | if len(array1) == 0: 25 | merged_arr += array2 26 | break 27 | if len(array2) == 0: 28 | merged_arr += array1 29 | break 30 | 31 | if array1[0] < array2[0]: 32 | merged_arr.append(array1.pop(0)) 33 | else: 34 | merged_arr.append(array2.pop(0)) 35 | 36 | return merged_arr 37 | 38 | 39 | # tests 40 | assert two_way_merge([], []) == [] 41 | assert two_way_merge([1], []) == [1] 42 | assert two_way_merge([], [5]) == [5] 43 | assert two_way_merge([7, 9, 13], [1, 11]) == [1, 7, 9, 11, 13] 44 | assert two_way_merge([1, 3, 8], [0]) == [0, 1, 3, 8] 45 | assert two_way_merge([-9, -4, 3], [-5, 5]) == [-9, -5, -4, 3, 5] 46 | assert two_way_merge([], []) == [] 47 | 48 | print('done: all tests pass') 49 | -------------------------------------------------------------------------------- /algorithms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "algorithms", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "standard --fix" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "standard": "^14" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /algorithms/primitives/alternative-big-o-notation/README.md: -------------------------------------------------------------------------------- 1 | # Alternative Big O Notation 2 | I always found things easy to remember when they rhyme, especially with humor. So, here is my take on big O notation, which can help you remember the rankings of big O types: 3 | 4 | ``` 5 | O(1) = O(yeah) 6 | O(logn) = O(nice) 7 | O(n) = O(k) 8 | O(n^2) = O(my) 9 | O(2^n) = O(no) 10 | O(n!) = O(mg) 11 | O(n^n) = O(sh*t!) 12 | ``` 13 | 14 | If you want to see my actual article explaining Big O time/space complexity types, here it is: 15 | * [Big O Time/Space Complexity Types Explained - Logarithmic, Polynomial, Exponential, and More](/algorithms/primitives/big-o-time-space-complexity-types-explained){:target="_blank"}{:rel="noopener"} 16 | 17 | If you want to have the alternative Big O notation as a sticker, so you can stick it to unusual places, you can get it from [quanticdev.com/shop](/shop){:target="_blank"}{:rel="noopener"}. 18 | 19 | [![Alternative Big O Notation Poster](media/alternative_big_o_notation_sticker.jpg)](https://www.redbubble.com/i/sticker/Alternative-Big-O-Notation-by-quanticdev/54268092.EJUG5){:target="_blank"}{:rel="noopener"} 20 | 21 | If you really want to confuse fellow software engineers, you can also get it as a small poster, bigger poster, framed print, hoodie, phone case, mug, blanket, or even a shower curtain! 22 | 23 | [![Alternative Big O Notation Poster](media/alternative_big_o_notation_poster.jpg)](https://www.redbubble.com/shop/ap/54268092){:target="_blank"}{:rel="noopener"} 24 | 25 | **Side Note**: Asymptotically, O(n^n) is equal to O(2^n), so the last line in the alternative big O notation list is just for the humor's sake. 26 | 27 | ## Video? 28 | Did I forget to say that there is also a video version of this article (!) 29 | 30 | 31 | -------------------------------------------------------------------------------- /algorithms/primitives/alternative-big-o-notation/media/alternative_big_o_notation_poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/alternative-big-o-notation/media/alternative_big_o_notation_poster.jpg -------------------------------------------------------------------------------- /algorithms/primitives/alternative-big-o-notation/media/alternative_big_o_notation_sticker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/alternative-big-o-notation/media/alternative_big_o_notation_sticker.jpg -------------------------------------------------------------------------------- /algorithms/primitives/alternative-big-o-notation/media/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/alternative-big-o-notation/media/thumb.png -------------------------------------------------------------------------------- /algorithms/primitives/big-o-time-space-complexity-types-explained/media/alternative_big_o_notation_poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/big-o-time-space-complexity-types-explained/media/alternative_big_o_notation_poster.jpg -------------------------------------------------------------------------------- /algorithms/primitives/big-o-time-space-complexity-types-explained/media/binary_search.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/big-o-time-space-complexity-types-explained/media/binary_search.mp4 -------------------------------------------------------------------------------- /algorithms/primitives/big-o-time-space-complexity-types-explained/media/quanticdev_sticker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/big-o-time-space-complexity-types-explained/media/quanticdev_sticker.jpg -------------------------------------------------------------------------------- /algorithms/primitives/recursion-visualization/README.md: -------------------------------------------------------------------------------- 1 | # Recursion Visualization 2 | Recursion is a concept that is best understood through visualization. In this article, you will see visualizations for different kinds of recursions. For simplicity, I chose to animate recursive functions using trees. Properties of the recursion tree visualizations are: 3 | * Each node represents a single recursive function call. 4 | * The height of the recursion tree is the depth of our function call stack (n). 5 | * The rate of change of the tree's width represents the time complexity of our function (m): 6 | 7 | ![Recursion Tree](media/recursion_tree.png) 8 | 9 | If you want to see the visualizations, dive right in. 10 | 11 | Table of contents: 12 | * [Resources](#resources) 13 | * [Recursive Power Function Visualization](#power-function) 14 | * [Recursive Fibonacci Calculation Visualization](#calculating-5th-fibonacci-number-using-recursion) 15 | * [Recursive Fibonacci-like Sequence Calculation Visualization](#modified-fibonacci-sequence) 16 | * [Conclusion](#conclusion) 17 | 18 | ## Resources 19 | You can find the video version of this article on YouTube: [https://www.youtube.com/watch?v=mFb1Fj4sVcU](https://www.youtube.com/watch?v=mFb1Fj4sVcU){:target="_blank"}{:rel="noopener"} 20 | 21 | 22 | 23 | The video has all the illustrations along with the narrative. If you want to read the comments or leave a comment, do so under the YouTube video. If you want to contribute to the article, make a pull request on GitHub. 24 | 25 | The [Recursion Visualization Tool](/tools/recursion-visualization){:target="_blank"}{:rel="noopener"} I used in this video. Made by Bruno Papa. 26 | 27 | My ["Staircase Problem + 3 Variants"](/algorithms/dynamic-programming/staircase-problems){:target="_blank"}{:rel="noopener"} article, which is a great real-world application of recursive solutions, as well as memoization and plain iteration. 28 | 29 | ## Power Function 30 | What you see is the visualization of a "2 to the power of n" (2^n) function which is implemented using recursion: 31 | 32 | 33 | 34 | The code is simple: 35 | 36 | ```python 37 | def pow(x, n): 38 | if n == 1: 39 | return x 40 | return x * pow(x, n-1) 41 | ``` 42 | 43 | At each level, we multiply the result of the deeper recursive call with 2, hence calculating 2 raised to the power of n. A much better way of implementing this would be to use fast-power, but for demonstration sake, we will stick with recursion. As you saw in the animation, our call stack goes all the way down and then back up, bringing back the result from the deepest level. So, our call stack never bounces up and down. Let's switch to a Fibonacci example to investigate a recursion where the call stack depth increases and decreases along with where we are at the calculation. 44 | 45 | ## Calculating 5th Fibonacci Number Using Recursion 46 | In this example, you are seeing the visualization of the calculation of 5th Fibonacci number using recursion: 47 | 48 | 49 | 50 | The formula for calculating Fibonacci numbers is straightforward. Every Fibonacci number is the sum of the previous two Fibonacci numbers. The code for the recursive calculation of Fibonacci numbers is also quite simple: 51 | 52 | ```python 53 | def fib(n): 54 | if n <= 1: 55 | return n 56 | else: 57 | return fib(n-1) + fib(n-2) 58 | ``` 59 | 60 | Since all we do is to sum the previous two Fibonacci numbers at each step, the width of our recursion tree branches are restricted to two children. And the height of the recursion tree reaches a maximum of 5, which is our call stack depth. Modern programming runtimes allow call stack depths of hundreds of thousands so we could go a lot deeper, but it would take a lot of time due to the exponential complexity of our calculation: 61 | 62 | ``` 63 | Time Complexity: O(2^n) 64 | Space Complexity: O(1) 65 | Call Stack: O(n) 66 | ``` 67 | 68 | Now, why is the time complexity exponential. As you can see, at every level of the recursion tree, it gets wider by a factor of two. This means that every consecutive Fibonacci number will take double the amount of time to calculate. At least we don't create new variables per calculation, so our space complexity is constant. And as you just saw, our call stack only grows linearly. 69 | 70 | ## Modified Fibonacci Sequence 71 | What if the Fibonacci numbers were the sum of the previous three Fibonacci numbers instead of two? How would our recursion tree look like? Let's find out: 72 | 73 | 74 | 75 | As you can see, the only difference this time is the width of the recursion tree. Our height still maxes out at five, but the width of our recursion tree grows by a factor of three this time. This will again result in exponential time complexity, one that grows cubically. 76 | 77 | ## Conclusion 78 | If you want to see an excellent example of recursion in programming interviews, check out my "Staircase Problems + 3 Variants" article. Solutions of staircase problems, and other unique paths problems, are Fibonacci-like sequences. In that article, I explain how to solve them using recursion, memoized recursion, and simple iteration. You can find the link to it in the resources section above. And if you want to see my other algorithms articles, check out the home page. Finally, the source for the visualization tool that I used is also in the resources section. 79 | -------------------------------------------------------------------------------- /algorithms/primitives/recursion-visualization/media/fibonacci_5.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/recursion-visualization/media/fibonacci_5.mp4 -------------------------------------------------------------------------------- /algorithms/primitives/recursion-visualization/media/modified_fibonacci_5.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/recursion-visualization/media/modified_fibonacci_5.mp4 -------------------------------------------------------------------------------- /algorithms/primitives/recursion-visualization/media/power_of_2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/recursion-visualization/media/power_of_2.mp4 -------------------------------------------------------------------------------- /algorithms/primitives/recursion-visualization/media/recursion_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/recursion-visualization/media/recursion_tree.png -------------------------------------------------------------------------------- /algorithms/primitives/recursion-visualization/media/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/algorithms/primitives/recursion-visualization/media/thumb.png -------------------------------------------------------------------------------- /algorithms/primitives/subarray-vs-substring-vs-subsequence-vs-subset/README.md: -------------------------------------------------------------------------------- 1 | # Know the Difference: Subarray vs Substring vs Subsequence vs Subset 2 | Today we are going to make a comparison of subarray vs substring vs subsequence vs subset. These are all similar concepts but have important differences. For instance, if you have a requirement to write an algorithm to find the subsets of a certain data and you come up with something that only finds the subsequences, you will only be half done. Or in an interview situation, you need to be extra careful about your choice of wording. If a question asks you to return a subsequence and you return a subset, you might fail the interview. Let me start by describing each concept with examples. Finally, I will give you a comparison table. 3 | 4 | ## Resources 5 | You can find the video narration of this article on YouTube with illustrations: [https://www.youtube.com/watch?v=uzhN-QhzR2g](https://www.youtube.com/watch?v=uzhN-QhzR2g){:target="_blank"}{:rel="noopener"} 6 | 7 | 8 | 9 | Video has additional tips and illustrations. If you want to read the comments or leave a comment, do so under YouTube video. If you want to contribute to the article, make a pull request on GitHub. 10 | 11 | ## Subarray 12 | A subarray is a contiguous sequence of elements within an array. For instance, the subarrays of the array `{1, 2, 1}` would be `{1}`, `{2}`, `{1, 2}`, `{2, 1}`, `{1, 2, 1}`, `{}`. Things to note: 13 | * You can use braces (aka curly brackets) `{}` or square brackets `[]` to denote arrays. 14 | * A subarray should be a contiguous subsequence of the parent array. As a result, `{1, 1}` is not a valid subarray of the array `{1, 2, 1}`, since `{2}` in the middle is skipped, so it is not a contiguous subsequence anymore. 15 | * The full array itself is a subarray of itself. 16 | * An empty array is a subarray of any array. 17 | * You cannot have duplicate subarray members. The element `{1}` appears twice in the array `{1, 2, 1}` but you can only count `{1}` once as the subarray of `{1, 2, 1}`. 18 | * Order of elements in the subarray should be the same as in the array. As a result, `{2, 1, 1}` is not a subarray of `{1, 2, 1}`. 19 | 20 | ## Substring 21 | A substring is exactly the same thing as a subarray but in the context of strings. For instance, the substrings of the string `"ara"` would be `"a"`, `"r"`, `"ar"`, `"ra"`, `"ara"`, `""`. Things to note: 22 | * A substring is just a subarray that is made up of only characters. 23 | * You can use single `'` or double quotes `"` to denote substrings. 24 | * All the rules mentioned for subarrays also apply to substrings. 25 | 26 | ## Subsequence 27 | Both in mathematics and computer science, a subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements. This means a subsequence is a generalized subarray, where the rule of contiguity does not apply. For instance, the subsequences of the sequence `` would be ``, ``, ``, ``, ``, ``, `<>`. 28 | * In math, it is customary to use angle brackets (`<>`) to denote subsequences. In programming, you can use whatever your programming language uses for arrays and lists. 29 | * Unlike subarrays, subsequences do not need to be contiguous so `` is a perfectly valid subsequence of `` whereas it is not a valid subarray. 30 | * Subsequences still need to preserve element order just like subarrays, so `` and `` are not valid subsequences. 31 | * Apart from the contiguity difference mentioned above, the rest of the rules that apply to subarrays also apply to subsequences. 32 | 33 | Tip: Subsequences is a great interview question topic. I have an algorithm article coming up on Longest Common Subsequence questions. If you want to read it when it is out, don't forget to follow me on social media. 34 | 35 | ## Subset 36 | A set is subset of another set if all its elements are contained by that set. This means, neither contiguity nor ordering of elements matter. For instance, the subsets of the set `{1, 2, 3}` would be `{1}`, `{2}`, `{3}`, `{1, 2}`, `{1, 3}`, `{2, 3}`, `{1, 2, 3}`, `{}`. 37 | * Subsets do not need to be contiguous. `{1, 3}` is a perfectly valid subset. 38 | * Subsets do not need to preserve element order. As a result, both `{1, 2}` and `{2, 1}` represent the same subset. While listing the subsets of the set, you can either write `{1, 2}` or `{2, 1}`, and it does not matter. But you cannot list both at the same time since they are exactly the same thing. 39 | * Note on Sets: Unlike arrays, strings, and sequences, sets do not allow duplicate elements. As a result, `{1, 2, 1}` would not be a valid set. 40 | 41 | ## Comparison Table 42 | 43 | | | Subarray | Substring | Subsequence | Subset | 44 | |---|---|---|---|---| 45 | | Contiguous | Yes | Yes | No | No | 46 | | Elements Ordered | Yes | Yes | Yes | No | 47 | 48 | As you can see in the table, subarrays and substrings need to be made up of contiguous sequence of elements of their parents, while subsequences and subsets do not have to be. In addition, all of subarrays, substrings and subsequences should preserve element order, meaning their elements should appear in the same order that they appear in their parents, while subsets can have their elements appear in any order. 49 | 50 | While memorizing all the details about these data structures is hard, learning them is not. And the best way to learn them is to use them in real life. Not everyone does algorithm-heavy programming, so my recommendation for most developers is to solve algorithm questions from time to time. They are not only good exercise to keep your computer science fundamentals sharp, but they will also help you to be familiar with new and improved problem-solving techniques. Computer science is a very active branch of science and existing algorithms are being improved every day, and new solutions for existing questions are being found. Solving an algorithm question once in a while is not only fun, but it is tremendously helpful in interview situations. 51 | 52 | If you want to keep your algorithm game up and be ready for interviews at any time, follow me on social media, and in return, I will give you the best and most popular interview questions and the best possible solutions to them. And that is it for this quick article, I will see you in the next algorithm question article. I am planning for a hard one that I plan to ask in the next hiring event, so watch out! 53 | -------------------------------------------------------------------------------- /algorithms/sort/insertion-sort.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * In-pace insertion sort implementation. 5 | * See my animated video if you want a visualization. 6 | * 7 | * This will perform really well on already mostly sorted data, or small arrays. 8 | * It will perform terribly on large arrays however. 9 | * Hence it is very useful as a second-stage algorithm of a divide-and-conquer sorting strategy. 10 | * 11 | * Time complexity: O(n^2) 12 | * Auxiliary space: O(1) 13 | * 14 | * @param data - Input data array. 15 | * @returns {[]} - Sorted data. 16 | */ 17 | function insertionSort (data) { 18 | // validate the input 19 | assert(Array.isArray(data), 'Input should be an array.') 20 | 21 | // use a simple nested iteration 22 | for (let i = 1, current = data[i]; i < data.length; i++, current = data[i]) { 23 | // shift elements up until we find the correct spot for the current element 24 | for (let j = i - 1; j >= 0; j--) { 25 | if (data[j] <= current) { 26 | data[j + 1] = current 27 | break 28 | } else { 29 | data[j + 1] = data[j] 30 | if (j === 0) data[0] = current 31 | } 32 | } 33 | } 34 | 35 | return data 36 | } 37 | 38 | /** 39 | * Tests 40 | */ 41 | 42 | // test case #1 43 | const exampleInput1 = [2, 3, 4, 1, 5] 44 | const solution1 = [1, 2, 3, 4, 5] 45 | 46 | const calculatedSolution1 = insertionSort(exampleInput1) 47 | 48 | console.log(`Example Input #1: Expected Solution: ${JSON.stringify(solution1)}, Calculated Solution: ${JSON.stringify(calculatedSolution1)}`) 49 | assert.deepStrictEqual(calculatedSolution1, solution1) 50 | 51 | // test case #2 52 | const exampleInput2 = [5, 0, -2, 1, 0, 5, 1] 53 | const solution2 = [-2, 0, 0, 1, 1, 5, 5] 54 | 55 | const calculatedSolution2 = insertionSort(exampleInput2) 56 | 57 | console.log(`Example Input #2: Expected Solution: ${JSON.stringify(solution2)}, Calculated Solution: ${JSON.stringify(calculatedSolution2)}`) 58 | assert.deepStrictEqual(calculatedSolution2, solution2) 59 | 60 | // test case #3 61 | const exampleInput3 = [0, 0, 0, 0, 0] 62 | const solution3 = exampleInput3 63 | 64 | const calculatedSolution3 = insertionSort(exampleInput3) 65 | 66 | console.log(`Example Input #3: Expected Solution: ${JSON.stringify(solution3)}, Calculated Solution: ${JSON.stringify(calculatedSolution3)}`) 67 | assert.deepStrictEqual(calculatedSolution3, solution3) 68 | -------------------------------------------------------------------------------- /algorithms/trees/generic-tree/generic-tree.js: -------------------------------------------------------------------------------- 1 | // todo: implement more methods found in: https://github.com/joowani/binarytree/blob/master/binarytree/__init__.py 2 | 3 | class Tree { 4 | /** 5 | * General tree implementation. 6 | * @param root - Optional root node. 7 | */ 8 | constructor (root = new Node()) { 9 | this.root = root 10 | } 11 | 12 | /** 13 | * Traverse the tree from left to right, top to bottom, like reading a book. 14 | * Tree is traversed without recursion. 15 | * Time complexity: 16 | * Space complexity: 17 | * @param callback - Callback function to receive the next node. Traversal continues as long as callback returns true. 18 | */ 19 | traverseBreadthFirst = (callback) => { 20 | // todo: use Symbol.iterator instead for a much simple syntax 21 | while (callback()) { 22 | } 23 | } 24 | 25 | /** 26 | * Traverse the tree from top to bottom, left to right. 27 | * Tree is traversed without recursion. 28 | * Time complexity: 29 | * Space complexity: 30 | * @param callback - Callback function to receive the next node. Traversal continues as long as callback returns true. 31 | */ 32 | traverseDepthFirst = (callback) => { 33 | while (callback()) { 34 | } 35 | } 36 | } 37 | 38 | class Node { 39 | /** 40 | * Node constructor. 41 | * @param children - Optional child nodes. 42 | * @param parent - Optional parent node. 43 | */ 44 | constructor (children, parent) { 45 | children && children.forEach(c => c.parent = this) 46 | this.children = children 47 | this.parent = parent 48 | } 49 | } -------------------------------------------------------------------------------- /algorithms/trees/heap/binary-heap.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Binary heap implementation used in my "Distributed Sorting" video: https://www.youtube.com/watch?v=vgKjatRVtys 5 | */ 6 | class BinaryHeap { 7 | // we use the flat array representation of a heap as it is visualized here: https://en.wikipedia.org/wiki/Heap_(data_structure)#Implementation 8 | nodes = [] 9 | 10 | // we assume a max-heap if this is true, min-heap otherwise 11 | isMaxHeap = true 12 | 13 | constructor (dataArr, isMaxHeap) { 14 | this.nodes = dataArr 15 | if (isMaxHeap !== undefined) this.isMaxHeap = isMaxHeap 16 | 17 | this.heapify() 18 | } 19 | 20 | heapify () { 21 | // heapify the nodes array using siftDown method by Floyd: https://en.wikipedia.org/wiki/Heapsort#Algorithm 22 | } 23 | 24 | insert (value) { 25 | // insert the new value into the first empty spot (which is the end of the array) and start pushing it up 26 | // until the tree satisfies the heap property again 27 | this.nodes.push(value) 28 | let tmp 29 | for (let currentNodeIndex = this.nodes.length - 1, parentNodeIndex = this.getParentIndex(currentNodeIndex); parentNodeIndex > -1; currentNodeIndex = parentNodeIndex) { 30 | if ((this.isMaxHeap && this.nodes[currentNodeIndex] > this.nodes[parentNodeIndex]) || (!this.isMaxHeap && this.nodes[currentNodeIndex] < this.nodes[parentNodeIndex])) { 31 | tmp = this.nodes[currentNodeIndex] 32 | this.nodes[currentNodeIndex] = this.nodes[parentNodeIndex] 33 | this.nodes[parentNodeIndex] = tmp 34 | } else { 35 | break 36 | } 37 | } 38 | } 39 | 40 | popRoot () { 41 | const root = this.nodes[0] 42 | 43 | // assign the bottom right-most child as the new root and push that value down to its correct location 44 | this.nodes[0] = this.nodes.length === 1 ? undefined : this.nodes.pop() 45 | this.pushDown(0) 46 | 47 | return root 48 | } 49 | 50 | getParentIndex (i) { 51 | return Math.floor((i - 1) / 2) 52 | } 53 | 54 | getLeftChildIndex (i) { 55 | return 2 * i + 1 56 | } 57 | 58 | pushDown (i) { 59 | let currentNodeIndex = i, currentNodeValue, leftChildIndex, leftChildValue, rightChildIndex, rightChildValue, swapToIndex 60 | 61 | while (true) { 62 | currentNodeValue = this.nodes[currentNodeIndex] 63 | leftChildIndex = this.getLeftChildIndex(currentNodeIndex) 64 | leftChildValue = this.nodes[leftChildIndex] 65 | rightChildIndex = leftChildIndex + 1 66 | rightChildValue = this.nodes[rightChildIndex] 67 | 68 | if (leftChildValue === undefined) break 69 | 70 | // swap the parent with the larger (for max heap) or smaller (for min heap) of the children if necessary 71 | if (this.isMaxHeap) { 72 | swapToIndex = (leftChildValue >= rightChildValue || rightChildValue === undefined) ? leftChildIndex : rightChildIndex 73 | if (currentNodeValue >= this.nodes[swapToIndex]) break 74 | } else { 75 | swapToIndex = (leftChildValue <= rightChildValue || rightChildValue === undefined) ? leftChildIndex : rightChildIndex 76 | if (currentNodeValue <= this.nodes[swapToIndex]) break 77 | } 78 | 79 | this.nodes[currentNodeIndex] = this.nodes[swapToIndex] 80 | this.nodes[swapToIndex] = currentNodeValue 81 | } 82 | } 83 | } 84 | 85 | module.exports = BinaryHeap 86 | 87 | /** 88 | * Tests 89 | */ 90 | 91 | // test case #1 92 | const exampleInput1 = [4, 3, 1, 5] 93 | const solution1 = [1, 4, 3, 5] 94 | 95 | const heap1 = new BinaryHeap([], false) 96 | exampleInput1.forEach(e => heap1.insert(e)) 97 | const calculatedSolution1 = heap1.nodes 98 | 99 | console.log(`Example Input Array #1: ${exampleInput1}, and the exact solution: ${solution1}, and calculated solution: ${calculatedSolution1}`) 100 | assert.deepStrictEqual(calculatedSolution1, solution1) 101 | 102 | // test case #1 103 | const exampleInput2 = [4, 3, 1, 5, 2] 104 | 105 | const heap2 = new BinaryHeap([], false) 106 | exampleInput2.forEach(e => heap2.insert(e)) 107 | 108 | assert.deepStrictEqual(heap2.popRoot(), 1) 109 | assert.deepStrictEqual(heap2.popRoot(), 2) 110 | assert.deepStrictEqual(heap2.popRoot(), 3) 111 | assert.deepStrictEqual(heap2.popRoot(), 4) 112 | assert.deepStrictEqual(heap2.popRoot(), 5) 113 | assert.deepStrictEqual(heap2.popRoot(), undefined) 114 | -------------------------------------------------------------------------------- /algorithms/trees/lockable-tree/lockable-tree.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Lockable tree node that can be locked only if none of the ancestors or descendants are locked. 5 | * Locking/unlocking operations run in O(h) time (h = height of the tree). 6 | * This is a very minimal implementation and could be improved with getters/setters, parameter validation, and thread safety. 7 | * 8 | * If you want to see the video description of this algorithm, you can find it here: https://www.youtube.com/watch?v=1mTGZHcs7zw 9 | * It has animated description and several interview questions and their solutions in it. 10 | */ 11 | class LockableNode { 12 | /** 13 | * Node constructor. 14 | * @param children - Optional child nodes. 15 | * @param parent - Optional parent node. 16 | */ 17 | constructor (children, parent) { 18 | children && children.forEach(c => c.parent = this) 19 | this.children = children 20 | this.parent = parent 21 | this.locked = false 22 | this.lockedDescendantCount = 0 23 | } 24 | 25 | /** 26 | * Locks the node if none of the ancestors or descendants are locked. 27 | * @returns {boolean} - True if the node is successfully locked, or has already been locked. False otherwise. 28 | */ 29 | lock = () => { 30 | if (this.locked) return true 31 | if (this.lockedDescendantCount > 0) return false 32 | 33 | // check ancestors 34 | // since every descendant informs their ancestors about their locking status, we don't need to check our descendants separately 35 | for (let ancestor = this.parent; ancestor !== undefined; ancestor = ancestor.parent) { 36 | if (ancestor.locked) return false 37 | } 38 | 39 | // inform all ancestors that their locked descendant count increased by one 40 | for (let ancestor = this.parent; ancestor !== undefined; ancestor = ancestor.parent) { 41 | ancestor.lockedDescendantCount++ 42 | } 43 | 44 | this.locked = true 45 | return true 46 | } 47 | 48 | /** 49 | * Unlocks the node if it was locked. 50 | */ 51 | unlock = () => { 52 | if (!this.locked) return 53 | 54 | // inform all ancestors that one of their locked descendant count decreased by one 55 | for (let ancestor = this.parent; ancestor !== undefined; ancestor = ancestor.parent) { 56 | ancestor.lockedDescendantCount-- 57 | } 58 | 59 | this.locked = false 60 | } 61 | } 62 | 63 | /** 64 | * Tests 65 | */ 66 | 67 | /** 68 | * Initial testing tree with a single locked node. 69 | * 70 | * [no-locked] 71 | * |--------[no-locked] 72 | * | |--------[!!!!LOCKED!!!!!] 73 | * | |--------[no-locked] 74 | * | |--------[no-locked] 75 | * | |--------[no-locked] 76 | * | |--------[no-locked] 77 | * |--------[no-locked] 78 | * | |--------[no-locked] 79 | * | |--------[no-locked] 80 | * |--------[no-locked] 81 | * |--------[no-locked] 82 | * 83 | * @type {LockableNode} 84 | */ 85 | const rootNode = new LockableNode([ 86 | new LockableNode([ 87 | new LockableNode([ 88 | new LockableNode([]), 89 | new LockableNode([]), 90 | new LockableNode([]) 91 | ]), 92 | new LockableNode([]) 93 | ]), 94 | new LockableNode([ 95 | new LockableNode([]), 96 | new LockableNode([]) 97 | ]), 98 | new LockableNode([ 99 | new LockableNode([]) 100 | ]) 101 | ]) 102 | 103 | // lock the node [Root:1:1] to complete the sample tree above and do some validations 104 | // note: array indices start from 0 where out tree index notation starts from 1 like [Root:1:1] 105 | assert.deepStrictEqual(rootNode.children[0].children[0].lock(), true, 'Tree node [Root:1:1] should be lockable.') 106 | assert.deepStrictEqual(rootNode.children[0].children[0].locked, true, 'Tree node [Root:1:1] should be locked.') 107 | assert.deepStrictEqual(rootNode.children[0].children[0].lock(), true, 'Tree node [Root:1:1] should already be locked.') 108 | assert.deepStrictEqual(rootNode.children[0].children[0].lockedDescendantCount, 0, 'Tree node [Root:1:1] should not have locked descendants.') 109 | assert.deepStrictEqual(rootNode.children[0].lockedDescendantCount, 1, 'Tree node [Root:1] should have 1 locked descendant.') 110 | assert.deepStrictEqual(rootNode.lockedDescendantCount, 1, 'Tree node [Root] should have 1 locked descendant.') 111 | assert.deepStrictEqual(rootNode.children[0].children[0].children[0].lock(), false, 'Tree node [Root:1:1:1] should not be lockable.') 112 | assert.deepStrictEqual(rootNode.children[0].children[0].children[2].lock(), false, 'Tree node [Root:1:1:3] should not be lockable.') 113 | assert.deepStrictEqual(rootNode.children[0].lock(), false, 'Tree node [Root:1] should not be lockable.') 114 | assert.deepStrictEqual(rootNode.lock(), false, 'Tree node [Root] should not be lockable.') 115 | 116 | // lock [Root:1:2] and more validations 117 | // this is the sibling of [Root:1:1] so it should be lockable 118 | assert.deepStrictEqual(rootNode.children[0].children[1].lock(), true, 'Tree node [Root:1:2] should be lockable.') 119 | assert.deepStrictEqual(rootNode.children[0].children[1].locked, true, 'Tree node [Root:1:2] should be locked.') 120 | assert.deepStrictEqual(rootNode.children[0].lockedDescendantCount, 2, 'Tree node [Root:1] should have 2 locked descendants.') 121 | assert.deepStrictEqual(rootNode.lockedDescendantCount, 2, 'Tree node [Root] should have 2 locked descendants.') 122 | 123 | // unlock the node [Root:1:1] and do some validations 124 | rootNode.children[0].children[0].unlock() 125 | assert.deepStrictEqual(rootNode.children[0].children[0].locked, false, 'Tree node [Root:1:1] should be unlocked.') 126 | assert.deepStrictEqual(rootNode.children[0].children[0].lockedDescendantCount, 0, 'Tree node [Root:1:1] should not have locked descendants.') 127 | assert.deepStrictEqual(rootNode.children[0].lockedDescendantCount, 1, 'Tree node [Root:1] should have 1 locked descendant.') 128 | assert.deepStrictEqual(rootNode.lockedDescendantCount, 1, 'Tree node [Root] should have 1 locked descendant.') 129 | 130 | console.log('All lockable tree tests pass.') 131 | -------------------------------------------------------------------------------- /algorithms/trees/tournament-tree/tournament-tree.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | /** 4 | * Tournament Tree implementation used in my K-Way Merge algorithm video: https://www.youtube.com/watch?v=Xo54nlPHSpg 5 | * 6 | * This implementation is specifically called a "loser tournament tree" since smallest element becomes the root (similar to a min-heap). 7 | * Hence a "winner tournament tree" is similar to a max-heap. 8 | * 9 | * Both K-Way Merge and Tournament Trees have interesting uses in computer science, especially in distributed computing. 10 | * Check out the video if you want to see some examples. 11 | * The video is fully animated to make it easy for you to understand these complex topics, and the relevant programming interview questions. 12 | */ 13 | class TournamentTree { 14 | // each element at each level is represented like [value, selfIndexAtBelowLevel] 15 | // and we keep each level in its own subarray so the tree will look like: 16 | // 17 | // nodes = [ 18 | // [[1, 0]], 19 | // [[1, 0], [2, 2]], 20 | // [[1, null], [5, null], [2, null], [Infinity, null]] 21 | // ] 22 | // 23 | // above is the sample tournament tree to be kept in the "nodes" field for a given input data of: [1, 5, 2] 24 | // 25 | nodes = [] 26 | 27 | // once we remove the root element, all the branches plus the associated leaf will be removed, so we keep track of it 28 | missingLeafIndex = null 29 | 30 | constructor (dataArr) { 31 | // store entire tree as array of arrays in a bottom-up manner 32 | // index 0 = leaves, index 1 = bottom branches, index 1++ = higher branches all the way to the root 33 | this.nodes = [dataArr.map(e => [e, null])] 34 | 35 | // construct the rest of the tournament tree 36 | for (let level = 0; this.nodes[level].length > 1; level++) { 37 | // create next level 38 | this.nodes.push([]) 39 | 40 | // assign this level's tournament victors to next level 41 | for (let i = 0; i < this.nodes[level].length; i = i + 2) { 42 | const left = this.nodes[level][i][0] 43 | const right = this.nodes[level][i + 1] ? this.nodes[level][i + 1][0] : Infinity 44 | 45 | // store the node value along with its index in the lower level so we can track it backward when removing the root 46 | this.nodes[level + 1].push(left < right ? [left, i] : [right, i + 1]) 47 | } 48 | } 49 | } 50 | 51 | popRoot () { 52 | // working our way back, remove all the branches that the root element came from 53 | const rootNodeValue = this.nodes[this.nodes.length - 1][0][0] 54 | 55 | // loop until we reach a node without a descendant (a leaf node) 56 | for (let level = this.nodes.length - 1, i = 0, currentNode = this.nodes[level][i]; true; level--, i = currentNode[1], currentNode = this.nodes[level][i]) { 57 | this.nodes[level][i] = [null, null] 58 | 59 | if (level === 0) { 60 | this.missingLeafIndex = i 61 | break 62 | } 63 | } 64 | 65 | return rootNodeValue 66 | } 67 | 68 | insertLeaf (value) { 69 | // insert the leaf into the blank spot 70 | this.nodes[0][this.missingLeafIndex] = [value, null] 71 | 72 | // rebuild the missing branches 73 | let index1 = this.missingLeafIndex 74 | for (let level = 0; level < this.nodes.length - 1; level++) { 75 | let index2 = index1 - 1 76 | let nextLevelIndex = index2 / 2 77 | if (index1 % 2 === 0) { 78 | index2 = index1 + 1 79 | nextLevelIndex = index1 / 2 80 | } 81 | 82 | const e1 = this.nodes[level][index1][0] 83 | const e2 = this.nodes[level][index2] ? this.nodes[level][index2][0] : Infinity 84 | this.nodes[level + 1][nextLevelIndex] = e1 < e2 ? [e1, index1] : [e2, index2] 85 | index1 = nextLevelIndex 86 | } 87 | 88 | this.missingLeafIndex = null 89 | } 90 | 91 | sort () { 92 | // return the full sorted array by repeatedly popping the root node 93 | // and pushing Infinity as sentinel value for the missing leaves 94 | const sorted = [] 95 | for (let i = 0; i < this.nodes[0].length; i++) { 96 | sorted.push(this.popRoot()) 97 | this.insertLeaf(Infinity) 98 | } 99 | 100 | return sorted 101 | } 102 | } 103 | 104 | module.exports = TournamentTree 105 | 106 | /** 107 | * Tests 108 | */ 109 | 110 | // test case #1 111 | const exampleInput1 = [5, 1, 9, 3] 112 | const tree1 = new TournamentTree(exampleInput1) 113 | 114 | assert.deepStrictEqual(tree1.popRoot(), 1) 115 | tree1.insertLeaf(2) 116 | assert.deepStrictEqual(tree1.popRoot(), 2) 117 | tree1.insertLeaf(Infinity) // need this to make the calculation for the next root to happen 118 | assert.deepStrictEqual(tree1.popRoot(), 3) 119 | tree1.insertLeaf(1) 120 | assert.deepStrictEqual(tree1.popRoot(), 1) 121 | tree1.insertLeaf(10) 122 | assert.deepStrictEqual(tree1.popRoot(), 5) 123 | console.log(`Example Input Array #1: ${exampleInput1}, and the tree: ${JSON.stringify(tree1)}, passed.`) 124 | 125 | // test case #2 126 | const exampleInput2 = [4, 3, 1, 2, 5] 127 | const solution2 = [1, 2, 3, 4, 5] 128 | const calculatedSolution2 = new TournamentTree(exampleInput2).sort() 129 | 130 | console.log(`Example Input Array #2: ${exampleInput2}, and the exact solution: ${solution2}, and calculated solution: ${calculatedSolution2}`) 131 | assert.deepStrictEqual(calculatedSolution2, solution2) 132 | 133 | // test case #3 134 | const exampleInput3 = [2, 2, 2, 2, 2] 135 | const solution3 = [2, 2, 2, 2, 2] 136 | const calculatedSolution3 = new TournamentTree(exampleInput3).sort() 137 | 138 | console.log(`Example Input Array #3: ${JSON.stringify(exampleInput3)}, and the exact solution: ${JSON.stringify(solution3)}, and calculated solution: ${JSON.stringify(calculatedSolution3)}`) 139 | assert.deepStrictEqual(calculatedSolution3, solution3) 140 | 141 | // test case #4 142 | const exampleInput4 = [47] 143 | const solution4 = [47] 144 | const calculatedSolution4 = new TournamentTree(exampleInput4).sort() 145 | 146 | console.log(`Example Input Array #4: ${JSON.stringify(exampleInput4)}, and the exact solution: ${JSON.stringify(solution4)}, and calculated solution: ${JSON.stringify(calculatedSolution4)}`) 147 | assert.deepStrictEqual(calculatedSolution4, solution4) 148 | 149 | // test case #5 150 | const exampleInput5 = [-5, 0, -9, 1, -1, 10] 151 | const solution5 = [-9, -5, -1, 0, 1, 10] 152 | const calculatedSolution5 = new TournamentTree(exampleInput5).sort() 153 | 154 | console.log(`Example Input Array #5: ${JSON.stringify(exampleInput5)}, and the exact solution: ${JSON.stringify(solution5)}, and calculated solution: ${JSON.stringify(calculatedSolution5)}`) 155 | assert.deepStrictEqual(calculatedSolution5, solution5) 156 | -------------------------------------------------------------------------------- /articles/_template/README.md: -------------------------------------------------------------------------------- 1 | ## Template 2 | Xxxxxxxxxx 3 | 4 | 5 | 6 | ![XXXXXXXXXXXXXXXXXX](media/XXXXXXXXXXXXXXXXXX) 7 | 8 | 9 | # TITLE 10 | Intro 11 | 12 | Table of contents: 13 | * [Resources](#resources) 14 | * [Overview](#overview) 15 | * [xxxxx](#xxxxx) 16 | * [xxxxx](#xxxxx) 17 | * [xxxxx](#xxxxx) 18 | * [xxxxx](#xxxxx) 19 | * [xxxxx](#xxxxx) 20 | * [xxxxx](#xxxxx) 21 | * [Conclusion](#conclusion) 22 | 23 | ## Resources 24 | You can find the video version of this article on YouTube: [https://www.youtube.com/watch?v=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX](https://www.youtube.com/watch?v=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX){:target="_blank"}{:rel="noopener"} 25 | 26 | 27 | 28 | The video has additional tips and illustrations. If you want to read the comments or leave a comment, do so under the YouTube video. If you want to contribute to the article, make a pull request on GitHub. 29 | 30 | Resources mentioned in this article: 31 | * [XXXXXXXXXXXXXX](XXXXXXXXXXXXXX){:target="_blank"}{:rel="noopener"} 32 | * [XXXXXXXXXXXXXXXXX](XXXXXXXXXXXXXXXXX){:target="_blank"}{:rel="noopener"} 33 | 34 | Relevant articles referred to in this article: 35 | * [XXXXXXXXXXXXXX](/articles/xxxxxxx){:target="_blank"}{:rel="noopener"} 36 | * [XXXXXXXXXXXXXX](/algorithms/xxxxxxx){:target="_blank"}{:rel="noopener"} 37 | 38 | ## Overview 39 | Overview 40 | 41 | ## Conclusion 42 | Conclusion 43 | -------------------------------------------------------------------------------- /articles/_template/media/THUMB_TODO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/_template/media/THUMB_TODO.png -------------------------------------------------------------------------------- /articles/automating-my-youtube-uploads-using-nodejs/media/software_development_life_cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/automating-my-youtube-uploads-using-nodejs/media/software_development_life_cycle.png -------------------------------------------------------------------------------- /articles/automating-my-youtube-uploads-using-nodejs/media/thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/automating-my-youtube-uploads-using-nodejs/media/thumb.jpg -------------------------------------------------------------------------------- /articles/cleaning-macbook-after-16800-hours-of-use/README.md: -------------------------------------------------------------------------------- 1 | # Cleaning My MacBook After 16800 Hours of Use! 2 | I estimated that I had used my mac for approximately 10 hours a day, 5 days a week, 48 weeks a year, for 7 years straight, for a total for whopping 16800 hours. I have written the first versions of most of the software components of my startup using this computer. And all this time, this machine worked without a hiccup. It was never repaired, and I never opened the back cover. However, its battery is getting swollen, so it is a good time to upgrade to a newer machine. Before recycling the machine, I decided to open it for once and vacuum the fans to see if it makes a difference. Oh boy, did it make a difference! You can find the fan test in the video if you want to check it out. 3 | 4 | ## Resources 5 | You can find the video narration of this article on YouTube: [https://www.youtube.com/watch?v=W0qAMLShAkk](https://www.youtube.com/watch?v=W0qAMLShAkk){:target="_blank"}{:rel="noopener"} 6 | 7 | 8 | 9 | If you want to read the comments or leave a comment, do so under the YouTube video. If you want to contribute to the article, make a pull request on GitHub. 10 | 11 | Hacker News discussions on this article: [https://news.ycombinator.com/item?id=23583611](https://news.ycombinator.com/item?id=23583611){:target="_blank"}{:rel="noopener"} 12 | 13 | ## The Cleanup 14 | I want to remind anyone who would like to try this to turn off their computers first. I don't care about this machine anymore, so I just left it in sleep mode. I also recommend setting the vacuum to minimum possible setting and be very gentle while sweeping. It would be very easy to suck in any loose components or wires. In addition, dust particles traveling inside the vacuum hose will build up some static. This can create some static discharge onto the electronic components. In my experience, this can only happen if you are cleaning something amazingly dusty, like an old desktop computer. If you have an air compressor/blower available, or at least a can of compressed air, it is a better option. For the record, I used a 1.2 mm P5 Pentalobe Screwdriver to open the back panel. You can find it pretty much in any hardware store. 15 | 16 | ![MacBook Pro Open Back](media/macbook_battery_service_recommended.jpg) 17 | 18 | Once I open the back panel, you can see that batteries are badly swollen. Even in that shape, they are stable, but I would not recommend trying to poke a hole in them. You would be likely to short circuit the inner panels, and it could start venting poisonous lithium gasses. 19 | 20 | ![MacBook Pro Open Back](media/macbook_pro_open_back.jpg) 21 | 22 | As you can see, both the fan blades and the heat pipe grills are clogged with 7 years' worth of dust! No wonder why the machine was overheating all the time. 23 | 24 | After a throughout vacuuming, I let the CPU to run at max load for about 5 minutes. After 5 minutes, I could hear the higher-pitched airflow sound. Before cleaning, there was no airflow noise and only a low-pitched noise from the fans themselves. When I put my hand behind the monitor, I can feel the hot air flowing again. This didn't happen in years! Anyway, this is the final moments of this machine. I will leave it up for recycling. Or maybe someone will be willing to fix it and use it. We'll see. 25 | -------------------------------------------------------------------------------- /articles/cleaning-macbook-after-16800-hours-of-use/media/macbook_battery_service_recommended.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/cleaning-macbook-after-16800-hours-of-use/media/macbook_battery_service_recommended.jpg -------------------------------------------------------------------------------- /articles/cleaning-macbook-after-16800-hours-of-use/media/macbook_pro_open_back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/cleaning-macbook-after-16800-hours-of-use/media/macbook_pro_open_back.jpg -------------------------------------------------------------------------------- /articles/engineering-principles/README.md: -------------------------------------------------------------------------------- 1 | # Fundamental Engineering Principles - What are the expectations form developers and engineers? 2 | Elevate your engineering career via aligning with these fundamental engineering principles. This article will provide you with guidance on common expectations from an engineer. Exercise the given tips in your day-to-day work life, and the confidence will be steaming from your ears! Points mentioned in the article apply to all disciplines of engineering at all ranks; junior developer, senior electronics engineer, VP of engineering, all the same. 3 | 4 | ## Resources 5 | You can find the video narration of this article on YouTube: [https://www.youtube.com/watch?v=GKlfcNzTqrg](https://www.youtube.com/watch?v=GKlfcNzTqrg){:target="_blank"}{:rel="noopener"} 6 | 7 | 8 | 9 | Video has additional tips for each principle discussed. If you want to read the comments or leave a comment, do so under the YouTube video. If you want to contribute to the article, make a pull request on GitHub. 10 | * Importance of written communication: "Jeff Bezos Turned Narrative into Amazon's Competitive Advantage", Hacker News discussion thread: [https://news.ycombinator.com/item?id=19115686](https://news.ycombinator.com/item?id=19115686){:target="_blank"}{:rel="noopener"} 11 | 12 | ## Article 13 | What are the expectations form developers and engineers? Below are the fundamental engineering principles, explained one-by-one in bullet points. 14 | 15 | 1 - Communication 16 | * Everyone in the field will universally agree on communication to be the essence of engineering. Everyone will all say the same thing as if they did a secret pact. 17 | * Engineering is a team game and good communication is the most basic requirement. This is a broad topic so let us divide and conquer it. Oral and written communication. 18 | * Oral communication 19 | * Speak slowly, especially if you are using tech terms heavily. 20 | * If you need to go talk to someone about a technical matter, go prepared; take notes on what to talk, list the conversation topics. 21 | * If you need to show them something, prepare it beforehand. Do not waste peoples' time. They will like you better. 22 | * Written communication 23 | * When it comes to writing, practice makes perfect. Make a habit of writing. 24 | * Write good emails, and be clear and concise in team chat apps. 25 | * Write good commit messages. 26 | * Write documentation files (readmes, design docs, etc.) wherever possible. 27 | * Practice writing brief memos for meetings. 28 | * If you choose to present your ideas using slides, hand out a written memo version of it to the audience. As you get senior, so you start to favor written form over PowerPoint. You will eventually join the gang anyway! 29 | * And finally, be responsive 30 | * Be responsive in team chat apps and mails. They will be your primary means of communication in many work environments. The more responsive you are, the more connected you become and people will like working with you, rather than waiting for you to respond to a chat ping for an hour. 31 | * However, you need to handle distractions. If you need to concentrate, use snooze or no-distraction mode features of your communication tools. 32 | 33 | 2 - Collaboration 34 | * This is where communication and preparation will help you a lot. 35 | * Hold meetings 36 | * Morning standups or briefs. 37 | * Lunch discussions. 38 | * Round table decision making. 39 | * Do favors so you can expect them 40 | * Be convincing 41 | * You work with more than just your fellow engineers. You will have to convince your managers, designers, and all non-tech fellows. Good communication will be triumph here. 42 | * Listen 43 | * To your customers. Customer is king said Dr. Samuelson Nobel Prize winner in economics. You might be getting customer feedback through a filter like a product manager, that is still one of the most valuable feedback you can ever get. 44 | * To your managers. 45 | * To your colleagues. 46 | * Disagree 47 | * Do not shy away from disagreement. No one (including you) knows the best at all times. 48 | 49 | 3 - Analytical thinking 50 | * Your lifelong education has the primary objective of making you think analytically. 51 | * Always think before you act. Before every task think about 52 | * Why are you doing this? 53 | * Can you not do this? Most of the time, you will find out that you do not need to do what you have in mind, because you might be able to reuse existing work instead of reinventing. 54 | * If you must do it, can you KISS? Use your creativity to KISS. 55 | * Never let emotions get in the way of decision making. Keep your relations with people around you professional at least during work hours to help with that. 56 | * Work the problem. Do not make things worse by guessing. (Wise words from Apollo 13 flight director Gene Kranz). 57 | * Consult your colleges and hold a brief discussion with your colleges if your analytical brain fails you. They are there for a reason! 58 | 59 | 4 - Organization 60 | * Manage your time. Use a time tracking software to track your hours with other people for collaboration and meetings. 61 | * Manage your project schedule. Use a project task tracker like Trello to prioritize tasks from most important to least, based on time available. 62 | * Manage equipment. This is your desk if you are an office dweller. 63 | 64 | 5 - Engineering excellence 65 | * Less is more. Concentrate on delivering the best possible result rather than delivering a ton. 66 | * Revise your work. Good books are not written, they are rewritten. - Michael Crichton. 67 | 68 | 6 - Money 69 | * Do not shy from spending money on what makes you productive. Computers, tablets, drawing equipment, cameras... Money spent on your work equipment is money well spent. 70 | 71 | 7 - Commitment 72 | * When decisions are made, commit to them. Deliver results (or failure). 73 | * Indecisiveness is worse than anything so keep walking until success or failure. Both will provide invaluable data for future decision making. 74 | 75 | 8 - Leadership 76 | * You always hear this, but leadership does not mean giving people orders. It means being able to make independent decisions and act on them. You have colleges but you will not do pair work all day long. 77 | * Take responsibility for tasks. Do not expect someone to show up and handle it for you. 78 | * Make decisions and execute on them. 79 | * If you get a chance to be in recruitment meetings, take it! 80 | 81 | 9 - Confidence 82 | * Trust in yourself. Trust in your work. Accept the fact that you will make mistakes and break things. But you build great things in the process also. If nothing, you will learn a lot. 83 | * Your job as a quantic engineer is always to remain calm and collected. If you radiate confidence, people follow you. They feel more secure around you. 84 | 85 | 10 - Finally, always remember the engineering motto. "The stage is beneath our talent, but we shall elevate it". Fine words from the wise man Jhin. We make the world a better place. 86 | 87 | You will experience most of these during your career. These will also come up repeatedly in job interviews for anything from engineering to management. Do not try to memorize them, use them. It is the best way to learn. 88 | -------------------------------------------------------------------------------- /articles/essential-software-for-working-from-home/media/quanticdev_github_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/essential-software-for-working-from-home/media/quanticdev_github_repo.png -------------------------------------------------------------------------------- /articles/essential-software-for-working-from-home/media/slack_apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/essential-software-for-working-from-home/media/slack_apps.png -------------------------------------------------------------------------------- /articles/essential-software-for-working-from-home/media/slack_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/essential-software-for-working-from-home/media/slack_bot.png -------------------------------------------------------------------------------- /articles/essential-software-for-working-from-home/media/slack_desktop_and_mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/essential-software-for-working-from-home/media/slack_desktop_and_mobile.png -------------------------------------------------------------------------------- /articles/essential-software-for-working-from-home/media/trello_board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/essential-software-for-working-from-home/media/trello_board.png -------------------------------------------------------------------------------- /articles/essential-software-for-working-from-home/media/word_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/essential-software-for-working-from-home/media/word_online.png -------------------------------------------------------------------------------- /articles/essential-software-for-working-from-home/media/zoom_meeting.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/essential-software-for-working-from-home/media/zoom_meeting.jpg -------------------------------------------------------------------------------- /articles/essential-software-for-working-from-home/media/zoombombing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/essential-software-for-working-from-home/media/zoombombing.png -------------------------------------------------------------------------------- /articles/fastest-php-best-practices/README.md: -------------------------------------------------------------------------------- 1 | # PHP Best Practices: 2 | 1 - Use something else. 3 | 4 | ## Resources 5 | If you really want, you can find the video narration of this article on YouTube: [https://www.youtube.com/watch?v=IK3RxZ2XsgA](https://www.youtube.com/watch?v=IK3RxZ2XsgA){:target="_blank"}{:rel="noopener"} 6 | 7 | 8 | -------------------------------------------------------------------------------- /articles/h265-encoding-on-arm-cpus/README.md: -------------------------------------------------------------------------------- 1 | # How Fast is H.265/HEVC Software Encoding on ARM CPUs (iPhone/Android) With FFmpeg? 2 | I recently had a crazy idea of using my idle mobile devices as a video render cluster. I have used the following FFmpeg command to compress a 4K H.264 footage to H.265 footage with a CRF (Constant Rate Factor) of 22, both on my Android phone and on my Mac: 3 | 4 | * ffmpeg -i vid.mp4 -c:v libx265 -crf 22 -c:a copy vid-265-crf22.mp4 5 | 6 | The command uses pure software encoding and is multi-threaded by default. Both on my phone and my computer, all the CPU cores were utilized above 95% during encoding. I have used Homebrew on my Mac to install the FFmpeg package, whereas on my Android, I have used Termux. 7 | 8 | The speed difference between desktop and mobile encoding was astounding! In the article, you will discover why there is such a difference along with what the future holds for H.265 software encoding on mobile devices. 9 | 10 | ## Resources 11 | You can find the video narration of this article on YouTube: [https://www.youtube.com/watch?v=UZCKD-zcrfU](https://www.youtube.com/watch?v=UZCKD-zcrfU){:target="_blank"}{:rel="noopener"} 12 | 13 | 14 | 15 | Video has additional tips and illustrations. If you want to read the comments or leave a comment, do so under the YouTube video. If you want to contribute to the article, make a pull request on GitHub. 16 | 17 | Relevant resources referred to in this article: 18 | * [Discussion on Doom9 Forum about x265 encoding speed on ARM processors](https://forum.doom9.org/showthread.php?p=1817880#post1817880){:target="_blank"}{:rel="noopener"} 19 | * [x265 Source Code](https://github.com/videolan/x265){:target="_blank"}{:rel="noopener"} 20 | * [Nvidia NVENC hardware encoder quality test for H.264](https://www.youtube.com/watch?v=-fi9o2NyPaY){:target="_blank"}{:rel="noopener"} 21 | 22 | ## The Numbers 23 | ![H.265 with x265 on ARM vs x86 (Mobile vs Desktop)](media/x265-arm_vs_x86.png) 24 | 25 | As I mentioned, I did the FFmpeg H.265 software encoding comparison between ARM and x86. The speed difference between my quad-core Intel i7 4850HQ 15" MacBook Pro and my 8-core Exynos 7885 Samsung phone was an astounding 1000%! 26 | * 4-core Intel i7 4850HQ: ~3.3 fps @ 45 Watts 27 | * 8-core Exynos 7885: ~0.31 fps @ 5 Watts 28 | 29 | That is a 10-fold difference overall or 20-fold difference per core. The Intel CPU in my 15" MacBook Pro is rated for 45W TDP (Thermal Design Power), whereas my phone's ARM CPU is rated for a measly 5W. There is a 9-fold difference in the thermal envelope of these CPUs, so that must explain the massive difference in performance, right? Not really. If we check out the Geekbench score for these two CPUs, the difference is only 3.5-fold: 30 | * 4-core Intel i7 4850HQ: 3463 (Multi-Core) 31 | * 8-core Exynos 7885: 1010 (Multi-Core) 32 | 33 | This is very much in line with my expectations. I would expect ARM CPUs to be substantially more power-efficient than desktop processors. So, seeing an ARM processor be about 2.5-times more power-efficient per Geekbench score is perfectly normal to me. 34 | * 4-core Intel i7 4850HQ: 77 Geekbench Score / Watt 35 | * 8-core Exynos 7885: 202 Geekbench Score / Watt 36 | 37 | So why is the H.265 encoding with FFmpeg 10-times slower on an ARM processor? According to my research, the x265 library used by FFmpeg is not well optimized for ARM yet. Quoting directly from the official x265 project's response on a discussion on this topic in Doom9 Forums: 38 | 39 | > "We have some limited ARM Neon optimization (x265\source\common\arm), but this is not anywhere near as complete as our x86 SIMD optimization. We have had discussions with various people at various times about doing a full optimization effort, but as of today this has not bubbled up to the top of the priority list for our customers or our strategic hardware partners. Of course, x265 is open source, and contributions are always welcomed." 40 | 41 | I went ahead and checked the x265 project's source code on GitHub and seen that ARM code is very rarely updated whereas the x86 code is much more frequently maintained. It is safe to assume that H.265 software encoding performance on ARM devices like phones and tablets will not improve anytime soon. It might be possible to use the hardware encoders found on these devices to accelerate H.265 encoding massively. However, hardware encoders generally perform worse than software encoders in terms of quality, and they do not offer a rich selection of parameters that you can use with the software encoder. For instance, I do not know of any H.265 encoder that supports Constant Rate Factor yet, which is my go-to encoding mode. 42 | 43 | ## Conclusion 44 | If you want to use your spare Android or iPhone for H.265 video encoding, forget about it! It is painstakingly slow. I am back to leaving my laptop on during nights for rendering. However, I have recently read that the latest generation of Nvidia cards delivers excellent H.264 quality with their NVENC hardware encoder. If you want to check out the quality analysis video, the link is in the resources section above. If I decide to build a desktop render machine with Nvidia hardware, I will test it on H.265 and let you guys know. 45 | -------------------------------------------------------------------------------- /articles/h265-encoding-on-arm-cpus/media/x265-arm_vs_x86.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/h265-encoding-on-arm-cpus/media/x265-arm_vs_x86.png -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/appium_architecture_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/appium_architecture_diagram.png -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/device_farm-automated_testing_on_mobile_phone.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/device_farm-automated_testing_on_mobile_phone.mp4 -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/device_farm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/device_farm.jpg -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/device_farm.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/device_farm.mp4 -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/device_farm_usb_hub.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/device_farm_usb_hub.jpg -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/firebase_test_lab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/firebase_test_lab.png -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/method_chaining.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/method_chaining.mp4 -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/opensft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/opensft.png -------------------------------------------------------------------------------- /articles/how-i-mass-refactored-our-production-codebase-without-fear/media/thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-i-mass-refactored-our-production-codebase-without-fear/media/thumb.jpg -------------------------------------------------------------------------------- /articles/how-to-manage-money/media/dow_jones_industrial_average_100_years.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-manage-money/media/dow_jones_industrial_average_100_years.png -------------------------------------------------------------------------------- /articles/how-to-manage-money/media/euro_vs_usd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-manage-money/media/euro_vs_usd.png -------------------------------------------------------------------------------- /articles/how-to-manage-money/media/msci_world_10y_performance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-manage-money/media/msci_world_10y_performance.png -------------------------------------------------------------------------------- /articles/how-to-manage-money/media/my_portfolio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-manage-money/media/my_portfolio.jpg -------------------------------------------------------------------------------- /articles/how-to-manage-money/media/yearly_mortgage_rates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-manage-money/media/yearly_mortgage_rates.png -------------------------------------------------------------------------------- /articles/how-to-present-like-apple/media/apple_special_event_quanticdev.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-present-like-apple/media/apple_special_event_quanticdev.jpg -------------------------------------------------------------------------------- /articles/how-to-use-github/media/bitbucket_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-use-github/media/bitbucket_about.png -------------------------------------------------------------------------------- /articles/how-to-use-github/media/git_about.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-use-github/media/git_about.jpg -------------------------------------------------------------------------------- /articles/how-to-use-github/media/github_raspberry_pi_schematics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-use-github/media/github_raspberry_pi_schematics.png -------------------------------------------------------------------------------- /articles/how-to-use-github/media/github_top_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-use-github/media/github_top_bar.png -------------------------------------------------------------------------------- /articles/how-to-use-github/media/gitlab_features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-use-github/media/gitlab_features.png -------------------------------------------------------------------------------- /articles/how-to-use-github/media/my_macbook_setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/how-to-use-github/media/my_macbook_setup.jpg -------------------------------------------------------------------------------- /articles/is-windows-good-for-developers/media/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/is-windows-good-for-developers/media/thumb.png -------------------------------------------------------------------------------- /articles/is-windows-good-for-developers/media/winget-dependency-management.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/is-windows-good-for-developers/media/winget-dependency-management.png -------------------------------------------------------------------------------- /articles/is-windows-good-for-developers/media/winget-package-versions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/is-windows-good-for-developers/media/winget-package-versions.png -------------------------------------------------------------------------------- /articles/linux-laptop-at-perfect-price/README.md: -------------------------------------------------------------------------------- 1 | # How to Get a Great Linux Laptop at a Perfect Price - Lenovo ThinkPad Without a Pre-installed OS 2 | Today I am going to give you a quick guide on how to get a great Linux laptop at a perfect price. In my experience, Lenovo ThinkPad laptops are one of the least problematic laptop series with Linux, so I will focus on them. ThinkPads with AMD Ryzen CPUs sell for roughly $200 less than their Intel competitors while offering better performance. In addition, you can get a ThinkPad T or E series laptop without the pre-installed Windows, which will save you another $100. I used to recommend the T series above anything, but these days they offer very little over the E series. 3 | 4 | ## Note for Future ThinkPad Releases 5 | Even though I use ThinkPad E595 as an example in this article, new ThinkPads with newer AMD Ryzen CPUs will be out nearly every year. For future laptop releases, you can apply the same technique that I will be demonstrating here and get the same sweet deals. As of writing this note (Sep-2020), ThinkPad E15/E14 and T15/T14 are partially available, so you can try your luck with them. This guide might also work with non E/T series laptops. If you want to check the Linux compatibility of future models, I have the link to the compatibility table in the next section. 6 | 7 | ## Resources 8 | You can find the video narration of this article on YouTube: [https://www.youtube.com/watch?v=9Wx1fM_oWH8](https://www.youtube.com/watch?v=9Wx1fM_oWH8){:target="_blank"}{:rel="noopener"} 9 | 10 | 11 | 12 | Video has live instructions for this guide. If you want to read the comments or leave a comment, do so under the YouTube video. If you want to contribute to the article, make a pull request on GitHub. 13 | 14 | Lenovo affiliate link which you can use in your purchase to help out the QuanticDev website: 15 | * [https://lenovo.7eer.net/A97BN](https://lenovo.7eer.net/A97BN){:target="_blank"}{:rel="noopener"} 16 | 17 | If you want to check the Linux compatibility of future Lenovo laptops, below is the compatibility table: 18 | * [https://wiki.archlinux.org/index.php/Laptop/Lenovo#E_series](https://wiki.archlinux.org/index.php/Laptop/Lenovo#E_series){:target="_blank"}{:rel="noopener"} 19 | * [https://www.thinkwiki.org/wiki/E14_hardware_tweaks](https://www.thinkwiki.org/wiki/E14_hardware_tweaks){:target="_blank"}{:rel="noopener"} 20 | 21 | Reddit discussion on this article: 22 | * [https://www.reddit.com/r/linux/comments/il8jym/how_to_get_a_great_linux_laptop_at_a_perfect/](https://www.reddit.com/r/linux/comments/il8jym/how_to_get_a_great_linux_laptop_at_a_perfect/){:target="_blank"}{:rel="noopener"} 23 | 24 | My [Cleanest Linux Productivity and Development Environment using Manjaro Linux](/articles/manjaro-linux-productivity-machine){:target="_blank"}{:rel="noopener"} article which can help you set up your shiny new laptop. 25 | 26 | ## Lenovo ThinkPad E595 (E Series) 27 | For this guide we will buy a Lenovo ThinkPad E595, so let's start by checking it out. The ThinkPad E595 has acceptable bezels on its great IPS display and a passable 720p webcam on the top bezel. The 45Wh battery should last you for 6-7 hours of coding. (Note that E15 is the successor to E595, and it will become available in August 2020, so you might try that instead.) 28 | 29 | ![Lenovo ThinkPad E595](media/lenovo_thinkpad_e595.png) 30 | 31 | It is charged through the USB-C port with a USB-C charger, has HDMI, Ethernet socket, and a MicroSD slot. It does not have a dedicated graphics card, which means more power efficiency and fewer problems with Linux. Ryzen's integrated Vega graphics is quite adequate anyway. Even the video editing software started utilizing the integrated Vega graphics card to accelerate editing and rendering. 32 | 33 | ![Lenovo ThinkPad E595 Ports](media/lenovo_thinkpad_e595_ports.jpg) 34 | 35 | Now let's jump in and buy one of these guys. 36 | 37 | ## Purchase Guide 38 | Start by going to the Lenovo website at lenovo.com, or using my affiliate link in the resources section above, in case you want to help quanticdev.com. Once the website loads, scroll all the way down and select your country from the dropdown on the bottom right. After that, click on "Laptops" from the top navigation menu. On the new page, look for E595. If you want an identical 14" laptop, you can go with the E495, but for productivity, I recommend E595 for its bigger screen. Once you click on E595's thumbnail, you will see that it also has Intel counterpart, but we want the AMD one, so make sure that AMD is selected. Click on **"Show All"** to see all the pre-configured models. From the models list, click on the **cheapest one on the left with the Ryzen 3 CPU**. This step is important because only the cheapest one offers the option to purchase without the pre-installed Windows. Do not worry though, we will beef up its configuration after the selection. So, the cheapest base model currently is **$453** (US Dollars without VAT). Click on **"Customize & Buy"**, and you will be taken to the component configuration page. 39 | 40 | **Note**: If you want to see me doing all these for you live, check out the YouTube video in the resources section above. 41 | 42 | The first thing to do on the configuration page is to select the **Ryzen 5** option. It has double the cores of Ryzen 3 and a better integrated GPU. You can also go with **Ryzen 7** if you have the budget or the need for speed. However, this is a laptop in the end, so you are guaranteed to be thermally throttled at some point, so you will start to get diminishing returns as you go higher on the core count. Below the CPU selection, you will see the Operation System selection box. Windows 10 Home is selected by default, but we do not want it. Select **"No Operating System"**, and you will instantly **save $100**. After that, scroll down and select your memory. You can go with **16 GB or 32 GB** depending on the tools you will use. Remember, Linux is very memory efficient, but apps you will use might not be. 43 | 44 | Now scroll down a bit and deselect the 1 TB 5400 RPM spinning disk from the storage options. I recommend avoiding spinning disks, but if you have some large files that you want to store on a slower disk, you can leave it selected. Or you can add a larger capacity disk to that slot later when you need it. Just make sure that the dimensions of the 3rd party disk that you are planning to use are correct for your laptop. Scroll down again, and you will see the second hard-drive option. The default selected one is a 128 GB M.2 SSD. Change that to the **512 GB or 1 TB** one so you will have ample fast storage for all your apps. Finally, you can change your keyboard layout to a different language. And that is it. Rest of the configuration is greyed-out by default. Add your new laptop to your cart, and you will see that it adds up to $507 (without VAT). It is probably the best machine you can get at this price and quality for a Linux compatible machine. Since the price is so low, Lenovo will not let you put in any discount coupons. But if you are a student, you can go to the **Laptops > Student Discount** section from the top menu. If you have a .edu email address, you can get a 20% discount from that price. Isn't being a student a great thing now (no, it is not!). 45 | 46 | ### Tip 47 | I have a dedicated article on how to setup a clean **Linux productivity and development environment using Manjaro Linux**. It is a 10-minute guide that takes you from installing Linux for the first time on your new laptop to developing a React app with your shiny new Linux tools. If you want to read it, the link is in the resources section above. 48 | 49 | ## Conclusion 50 | Don't forget, whenever a next generation of ThinkPads with newer AMD Ryzen processors come out, you can always apply the same technique. If you want to check the Linux compatibility of future models, I have the link to the compatibility table in the resources section above. In addition, I will leave an affiliate link to the Lenovo ThinkPad website in the resources section. If you want to support quanticdev, you can use it in your purchase, and the website will get a small percentage of the sale. Finally, if you know someone who needs a great Linux laptop for an amazing price, share this guide with them. 51 | -------------------------------------------------------------------------------- /articles/linux-laptop-at-perfect-price/media/lenovo_thinkpad_e595.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/linux-laptop-at-perfect-price/media/lenovo_thinkpad_e595.png -------------------------------------------------------------------------------- /articles/linux-laptop-at-perfect-price/media/lenovo_thinkpad_e595_ports.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/linux-laptop-at-perfect-price/media/lenovo_thinkpad_e595_ports.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/bios_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/bios_settings.png -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/computer_build_black_mesa_gameplay.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/computer_build_black_mesa_gameplay.mp4 -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/computer_cable_management.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/computer_cable_management.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/computer_chassis_back_io.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/computer_chassis_back_io.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/computer_components_on_desk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/computer_components_on_desk.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/computer_under_desk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/computer_under_desk.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/coomputer_build_cleanup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/coomputer_build_cleanup.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/cpu_fan_installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/cpu_fan_installation.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/cpu_installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/cpu_installation.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/graphics_card_installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/graphics_card_installation.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/motherboard_installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/motherboard_installation.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/motherboard_power_cables_installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/motherboard_power_cables_installation.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/passmark_cpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/passmark_cpu.png -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/passmark_gpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/passmark_gpu.png -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/power_supply_cables.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/power_supply_cables.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/power_supply_installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/power_supply_installation.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/quantic_developers_club_poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/quantic_developers_club_poster.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/ram_installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/ram_installation.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/ssd_installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/ssd_installation.jpg -------------------------------------------------------------------------------- /articles/max-value-pc-build-guide/media/thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/max-value-pc-build-guide/media/thumb.jpg -------------------------------------------------------------------------------- /articles/method-chaining/README.md: -------------------------------------------------------------------------------- 1 | # Method Chaining is Awesome 2 | Have you ever worked with classes that are thousands of lines long? Those classes end up encapsulating tens of related functionality, and you end up repeating that class' name many times, like in the following example: 3 | 4 | ```python 5 | db.connect('postgresql://localhost/testdb') 6 | db.initialize() 7 | 8 | user = db.create_new_user('John Doe', 'john.doe@quanticdev.com') 9 | user.give_permission('create_blog_post') 10 | 11 | post = user.new_blog_post('Test Blog Post Title', 'Lorem ipsum dolor sit amet...') 12 | post.upload_thumbnail('./test_thumbnail.jpg') 13 | post.publish() 14 | ``` 15 | 16 | But not today. In this article, we will clean up some mess using method chaining: 17 | 18 | ```python 19 | db.connect('postgresql://localhost/testdb') \ 20 | .initialize() \ 21 | .create_new_user('John Doe', 'john.doe@quanticdev.com') \ 22 | .give_permission('create_blog_post') \ 23 | .new_blog_post('Test Blog Post Title', 'Lorem ipsum dolor sit amet...') \ 24 | .upload_thumbnail('./test_thumbnail.jpg') \ 25 | .publish() 26 | ``` 27 | 28 | Table of contents: 29 | * [Resources](#resources) 30 | * [Inspiration for This Article](#inspiration-for-this-article) 31 | * [Method Chaining](#method-chaining) 32 | * [Benefits and Drawbacks](#benefits-and-drawbacks) 33 | * [Conclusion](#conclusion) 34 | 35 | ## Resources 36 | You can find the video version of this article on YouTube: [https://www.youtube.com/watch?v=OdOl_O8hyBM](https://www.youtube.com/watch?v=OdOl_O8hyBM){:target="_blank"}{:rel="noopener"} 37 | 38 | 39 | 40 | The video has animated transitions for all the code if that help you understand better. If you want to read the comments or leave a comment, do so under the YouTube video. If you want to contribute to the article, make a pull request on GitHub. 41 | 42 | If you want to read more on the subject, here are some good Wiki articles to check out: 43 | * [https://en.wikipedia.org/wiki/Method_chaining](https://en.wikipedia.org/wiki/Method_chaining){:target="_blank"}{:rel="noopener"} 44 | * [https://en.wikipedia.org/wiki/Fluent_interface](https://en.wikipedia.org/wiki/Fluent_interface){:target="_blank"}{:rel="noopener"} 45 | 46 | ## Inspiration for This Article 47 | The inspiration for this article comes from my recent mass cleanup of our test framework at the office. Like many other complex system developers, we have our custom test framework to do all sorts of automated end-to-end testing, simulating real user interactions with our apps on real devices. I can't show the code, but it has been neglected for several years now. While modernizing it, I also decided to refactor it to use chainable methods, just as you would expect from modern test frameworks. The resulting code was exceptionally clean and developer-friendly, and it was well worth the time investment. Before diving into specifics, let me summarize what method chaining is for you. 48 | 49 | ## Method Chaining 50 | Method chaining is an idiom in object-oriented languages where an object's methods return a reference to the object itself. This way, method calls can be chained together, without requiring variables to store the intermediate method call results. 51 | 52 | Imagine a database object. To be able to use it for the first time on an empty database, you first need to connect to your database then initialize it. In code, it would be like this: 53 | 54 | ```python 55 | db.connect('postgresql://localhost/testdb') 56 | db.initialize() 57 | ``` 58 | 59 | This is not too bad. You only have to reference the database object twice. But imagine if you could chain these calls: 60 | 61 | ```python 62 | db.connect('postgresql://localhost/testdb').initialize() 63 | ``` 64 | 65 | Much nicer isn't it. And it will become much better in situations where it saves you 5-6 object references. If you like, you can put each method call on a new line so it will be easier to use debug-points. Here is an example using Python syntax: 66 | 67 | ```python 68 | db.connect('postgresql://localhost/testdb') \ 69 | .initialize() \ 70 | .close() 71 | ``` 72 | 73 | I find method chaining to be an excellent utility for classes with lots of small and relevant functionality. Objects encapsulating database queries, test code, and UI code are great examples of this. Now let's go ahead and investigate the implementation of our database class from the previous example: 74 | 75 | ```python 76 | class DB: 77 | def connect(self, url): 78 | pass 79 | 80 | def initialize(self): 81 | pass 82 | 83 | def close(self): 84 | pass 85 | ``` 86 | 87 | In its current shape, you cannot chain the methods in this class. It is an easy fix, though. All we have to do is to finish each method with a "return self" statement so each method will return a reference to the object itself: 88 | 89 | ```python 90 | class DB: 91 | def connect(self, url): 92 | # todo 93 | return self 94 | 95 | def initialize(self): 96 | # todo 97 | return self 98 | 99 | def close(self): 100 | # todo 101 | return self 102 | ``` 103 | 104 | Now we can safely chain the methods in our database class. As you might have realized, any function that needs to return something other than the object itself won't be chainable. 105 | 106 | Method chaining can also be used to build a fluent interface or implement the builder pattern, which allows you to craft large objects or even SQL queries through a chain of methods. If you want to read more on the subject, I have links to several Wiki articles for them in the resources section above. Now let's analyze the benefits and drawbacks of method chains. 107 | 108 | ## Benefits and Drawbacks 109 | The benefit of method chaining is obvious; cleaner and concise code. You don't have to keep repeating calls to same objects for consecutive operations on the same object, which is especially useful in repetitive code like test code. You also don't need to create temporary variables to store results from previous method calls. However, this will make it difficult to put debug points on the right method in the chain. To get around this limitation, you can separate each method call with a new line, or add a chainable `breakpoint()` method, or just put debug point on the whole statement and do step-in/step-out. Some programming language debuggers already support adding debug points on methods in the chain directly. 110 | 111 | One interesting side effect of method chaining is that it will make logging harder. You normally put logging code in between method calls like this: 112 | 113 | ```python 114 | db.connect('postgresql://localhost/testdb') 115 | log.info('Initializing the database.') 116 | db.initialize() 117 | ``` 118 | 119 | Once you switch to method chaining, you might add a simple chainable log method to your class to work around the problem: 120 | 121 | ```python 122 | db.connect('postgresql://localhost/testdb') \ 123 | .log_info('Initializing the database.') \ 124 | .initialize() 125 | ``` 126 | 127 | ## Conclusion 128 | In conclusion, method chaining is not a silver bullet, but for where it fits, it brings conciseness and clarity, which I always like. In my experience, tests and data filtering and manipulation code are prime candidates for method chaining. Next time you are going to implement a framework or a utility class, you can provide chainable methods to make life easier for the prospective users of that code. 129 | 130 | ```javascript 131 | readers 132 | .filter(p => p.followed_me_on_twitter === true) 133 | .sort(p => p.time) 134 | .pat_on_the_back() 135 | ``` 136 | 137 | If you have checked out the video in the resources section, I have used various code animations for it this time. I will produce a separate article on how I make my code animations. If you don't want to miss it, follow me on my socials. 138 | -------------------------------------------------------------------------------- /articles/method-chaining/media/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/method-chaining/media/thumb.png -------------------------------------------------------------------------------- /articles/most-valuable-thing-to-learn-in-one-hour/media/first_aid_kit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/most-valuable-thing-to-learn-in-one-hour/media/first_aid_kit.jpg -------------------------------------------------------------------------------- /articles/most-valuable-thing-to-learn-in-one-hour/media/google_notes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/most-valuable-thing-to-learn-in-one-hour/media/google_notes.png -------------------------------------------------------------------------------- /articles/most-valuable-thing-to-learn-in-one-hour/media/levels_fyi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/most-valuable-thing-to-learn-in-one-hour/media/levels_fyi.png -------------------------------------------------------------------------------- /articles/most-valuable-thing-to-learn-in-one-hour/media/raspberry_pi_kit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/most-valuable-thing-to-learn-in-one-hour/media/raspberry_pi_kit.jpg -------------------------------------------------------------------------------- /articles/most-valuable-thing-to-learn-in-one-hour/media/raspberry_pi_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/most-valuable-thing-to-learn-in-one-hour/media/raspberry_pi_screen.jpg -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/koan_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/koan_github.png -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/koan_github_README.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/koan_github_README.png -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/koan_github_issues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/koan_github_issues.png -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/koan_hackernews_2014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/koan_hackernews_2014.png -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/koan_heroku_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/koan_heroku_demo.png -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/koan_heroku_demo_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/koan_heroku_demo_login.png -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/koan_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/koan_logo.png -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/koan_on_newsletters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/koan_on_newsletters.png -------------------------------------------------------------------------------- /articles/my-project-got-800-stars-in-two-days-on-github/media/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/my-project-got-800-stars-in-two-days-on-github/media/thumb.png -------------------------------------------------------------------------------- /articles/obs-studio/README.md: -------------------------------------------------------------------------------- 1 | # OBS Studio: Open-Source Software for Video Recording and Live Streaming - Guide 2 | Today I am going to show you how to use OBS Studio to live-stream or record yourself, your screen, or both together. OBS Studio is an open-source software for video recording and live streaming. It has been gaining traction over the years with the rise of live streaming on social media. Gaming focused streaming platforms like YouTube Live and Twitch added fuel to the fire. You can use OBS to stream to pretty much any platform while recording your stream locally. You can even use it as a virtual cam for video conference, for instance, Zoom calls. You can also apply a bunch of filters to your video and audio like noise reduction. I personally use it to record my screen for product demos or to create pre-recorded presentations. When I am preparing to make a webcast, I record my final practice session. If anything happens during the live session, I can at least playback the recorded version. 3 | 4 | Table of contents: 5 | * Overview 6 | * OBS Streaming & Recording Demo 7 | * Picture-in-Picture Mode 8 | * Conclusion 9 | 10 | ## Resources 11 | You can find the video narration of this article on YouTube: [https://www.youtube.com/watch?v=GO9JSW-RqUE](https://www.youtube.com/watch?v=GO9JSW-RqUE){:target="_blank"}{:rel="noopener"} 12 | 13 | 14 | 15 | Video has live demonstrations. If you want to read the comments or leave a comment, do so under the YouTube video. If you want to contribute to the article, make a pull request on GitHub. 16 | 17 | * OBS Studio Home: [https://obsproject.com](https://obsproject.com){:target="_blank"}{:rel="noopener"} 18 | * Source code: [https://github.com/obsproject/obs-studio](https://github.com/obsproject/obs-studio){:target="_blank"}{:rel="noopener"} 19 | * Recent Hacker News discussion on topic: [https://news.ycombinator.com/item?id=22748247](https://news.ycombinator.com/item?id=22748247){:target="_blank"}{:rel="noopener"} 20 | 21 | "Crowner": My Android game with "Choose Your Own Adventure" style of text-based gameplay which is used to demonstrate streaming in this guide: 22 | * [https://play.google.com/store/apps/details?id=com.soygul.crowner](https://play.google.com/store/apps/details?id=com.soygul.crowner){:target="_blank"}{:rel="noopener"} 23 | 24 | ## Overview 25 | I am the QuanticDev, and today I am going to show you how to use OBS Studio to live-stream or record yourself, your screen, or both together. OBS Studio is an open-source software for video recording and live streaming. 26 | 27 | ![OBS Studio Screenshot](media/obs_studio_screenshot.jpg) 28 | 29 | It has been gaining traction over the years with the rise of live streaming on social media. Gaming focused streaming platforms like YouTube Live and Twitch added fuel to the fire. You can use OBS to stream to pretty much any platform while recording your stream locally. You can even use it as a virtual cam for video conference, for instance, Zoom calls. You can also apply a bunch of filters to your video and audio like noise reduction. I personally use it to record my screen for product demos or to create pre-recorded presentations. When I am preparing to make a webcast, I record my final practice session. If anything happens during the live session, I can at least playback the recorded version. Now let's jump in and record a simple product demo while streaming it live at the same time! The product in question is my very own "Choose Your Own Adventure" game called Crowner. 30 | 31 | ![Crowner Screenshot](media/crowner_screenshot.png) 32 | 33 | I will stream the gameplay on Twitch.tv while saving it locally to an mp4 file. 34 | 35 | ## OBS Streaming & Recording Demo 36 | 37 | **Note: Live demonstration of the instructions below are on YouTube and the video link is in the resources section on top.** 38 | 39 | We will start by opening an Android emulator and OBS Studio window side by side. As you can see, first thing that appears in the OBS window is your desktop. We will continue by adding a new scene using the "+" button on the "Scenes" column which is on the bottom left of the OBS window. Now for this scene, we need a visual source. We will use the "+" button at the bottom of the "Sources" column and select "Window Capture" since we want to capture the Android emulator window and not the entire screen. It takes us to the window selection popup so we can select the Android Emulator window from the dropdown. After hitting OK, we see the Android emulator screen. We can resize and center it as we wish. 40 | 41 | Before starting the gameplay stream, we need to do some configuration. Let's click the "Settings" button on the right side of the OBS window. From there, we go to the "Stream" tab and fill in the streaming service we want to use and the required credentials for it. For this example, we will go with Twitch.tv. If you want to change the video quality, you can do so from the "Output" tab. Now let's close the tab and click "Start Streaming" and "Start Recording" buttons. Now we are both recording our stream locally to a file and broadcasting it online. 42 | 43 | Let's start the game and check Twitch if we are online yet. And yes, we are broadcasting the Android emulator screen. Everything is set, so now let's go ahead and do some gaming. In Crowner, you are a king, and you need to govern your kingdom. It is text-based and is very simple to play yet has quite a challenging storyline. Your decisions affect the prosperity of your kingdom as well as your popularity as a king. You are bound to strike a balance in your decision-making, or your demise will be tragic. If you want to check it out, the link to the Android version is in the resources section above. 44 | 45 | Once our streaming session is done, we can stop streaming and recording and check out the footage. As you can see, our footage looks good and quite clean with no compression artifacts. I used my quad-core MacBook to play, record, and stream at the same time. The CPU usage was about 50% during all of this, as I set OBS to use hardware encoding. 46 | 47 | ## Picture-in-Picture Mode 48 | One final thing I want to show you is the picture-in-picture mode. If you want to stream a window or your screen plus yourself, you can add another source to the same scene. Go to your Android Emulator scene and hit the "+" button under the Sources column and select "Video Capture Device". That is your webcam by default. After resizing and relocating yourself, enjoy your picture-in-picture stream. You can add more sources to the scene like static images, video files, etc. and create quite advanced scenes. 49 | 50 | ## Conclusion 51 | You can repeat the same steps and record your PowerPoint window to create a pre-recorded presentation. Or you can record your entire screen to create guides just as I did, and stream it live on YouTube at the same time! I highly recommend setting aside 10 minutes to setup OBS on your computer, as it will fill all your future recording/webcasting needs. It is open-source and free. And if you are a developer, it has bounties like this one that can benefit everyone, and earn you $10,000 while at it! 52 | 53 | ![OBS Studio GitHub 10000USD Bounty](media/github_10000USD_bounty.png) 54 | 55 | OBS Studio is open-source at its fines. Use it, share it, donate to it. And while at it, you can give me a sub so I can inform you about my other finest selections from the open-source world. If you know someone that is starting streaming, or a colleague that wants to record presentations, share this article with them to give them a helping hand. -------------------------------------------------------------------------------- /articles/obs-studio/media/crowner_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/obs-studio/media/crowner_screenshot.png -------------------------------------------------------------------------------- /articles/obs-studio/media/github_10000USD_bounty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/obs-studio/media/github_10000USD_bounty.png -------------------------------------------------------------------------------- /articles/obs-studio/media/obs_studio_screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/obs-studio/media/obs_studio_screenshot.jpg -------------------------------------------------------------------------------- /articles/raspberry-pi-guide-for-developers/media/docker_performance_cpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/raspberry-pi-guide-for-developers/media/docker_performance_cpu.png -------------------------------------------------------------------------------- /articles/raspberry-pi-guide-for-developers/media/docker_performance_latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/raspberry-pi-guide-for-developers/media/docker_performance_latency.png -------------------------------------------------------------------------------- /articles/raspberry-pi-guide-for-developers/media/overlayfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/raspberry-pi-guide-for-developers/media/overlayfs.png -------------------------------------------------------------------------------- /articles/raspberry-pi-guide-for-developers/media/raspberry_connected.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/raspberry-pi-guide-for-developers/media/raspberry_connected.jpg -------------------------------------------------------------------------------- /articles/raspberry-pi-guide-for-developers/media/raspberry_hardware_features.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/raspberry-pi-guide-for-developers/media/raspberry_hardware_features.jpg -------------------------------------------------------------------------------- /articles/serverless/media/serverless-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/serverless/media/serverless-architecture.png -------------------------------------------------------------------------------- /articles/software-engineer-compensation-guide/media/senior-eng-companies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineer-compensation-guide/media/senior-eng-companies.png -------------------------------------------------------------------------------- /articles/software-engineer-compensation-guide/media/senior-eng-l6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineer-compensation-guide/media/senior-eng-l6.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/github_organization_count.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/github_organization_count.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/github_user_count.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/github_user_count.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/growth_of_natural_language_processing_nlp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/growth_of_natural_language_processing_nlp.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/jupyter_notebooks_per_year.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/jupyter_notebooks_per_year.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/largest_tech_companies_by_revenue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/largest_tech_companies_by_revenue.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/open_source_by_continent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/open_source_by_continent.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/open_source_contributions_per_year.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/open_source_contributions_per_year.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/software_engineer_demand_by_role.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/software_engineer_demand_by_role.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/software_engineer_salaries_by_role.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/software_engineer_salaries_by_role.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/top_open_source_contributor_companies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/top_open_source_contributor_companies.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/top_open_source_projects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/top_open_source_projects.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/top_package_managers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/top_package_managers.png -------------------------------------------------------------------------------- /articles/software-engineering-in-2020/media/top_programming_languages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/software-engineering-in-2020/media/top_programming_languages.png -------------------------------------------------------------------------------- /articles/website-with-github-pages/media/github_pages_react.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/website-with-github-pages/media/github_pages_react.jpg -------------------------------------------------------------------------------- /articles/website-with-github-pages/media/quanticdev_com-github_source.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/website-with-github-pages/media/quanticdev_com-github_source.jpg -------------------------------------------------------------------------------- /articles/website-with-github-pages/media/quanticdev_com-google_analytics.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/website-with-github-pages/media/quanticdev_com-google_analytics.jpg -------------------------------------------------------------------------------- /articles/website-with-github-pages/media/quanticdev_com-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/articles/website-with-github-pages/media/quanticdev_com-mobile.jpg -------------------------------------------------------------------------------- /assets/css/style.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | @import "{{ site.theme }}"; 5 | 6 | header h3 { 7 | font-size: 30px; 8 | line-height: 1.5; 9 | margin: 0 0 0 -40px; 10 | font-weight: bold; 11 | font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; 12 | color: $conifer;//$header; 13 | text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1), 14 | 0 0 5px rgba(181, 232, 83, 0.1), 15 | 0 0 10px rgba(181, 232, 83, 0.1); 16 | letter-spacing: -1px; 17 | -webkit-font-smoothing: antialiased; 18 | } 19 | 20 | header h3:before { 21 | content: "./ "; 22 | font-size: 24px; 23 | } 24 | 25 | header h4 { 26 | font-size: 18px; 27 | font-weight: 300; 28 | color: #666; 29 | } 30 | 31 | .home { 32 | h2 { 33 | margin-top: 2.5rem; 34 | } 35 | 36 | ul li { 37 | margin-top: 0.5rem; 38 | 39 | a { 40 | text-decoration: none; 41 | } 42 | } 43 | } 44 | 45 | iframe[src*=youtube] { 46 | display: block; 47 | margin: 0 auto; 48 | max-width: 100%; 49 | padding-bottom: 10px; 50 | } 51 | 52 | video { 53 | max-width: 100%; 54 | height: auto; 55 | } 56 | 57 | body { 58 | overflow-wrap: break-word; 59 | } 60 | 61 | #main_content { 62 | -webkit-font-smoothing: revert; 63 | } 64 | -------------------------------------------------------------------------------- /assets/media/quanticdev_poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/assets/media/quanticdev_poster.jpg -------------------------------------------------------------------------------- /assets/media/quanticdev_sticker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/assets/media/quanticdev_sticker.jpg -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/favicon.ico -------------------------------------------------------------------------------- /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/favicon.png -------------------------------------------------------------------------------- /gpt.py: -------------------------------------------------------------------------------- 1 | import openai 2 | 3 | openai.api_key = "" 4 | 5 | # gpt-4-32k 6 | openai.ChatCompletion.create( 7 | model="gpt-3.5-turbo", 8 | messages=[ 9 | {"role": "system", "content": "You are a helpful assistant."}, 10 | {"role": "user", "content": "Who won the world series in 2020?"}, 11 | {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}, 12 | {"role": "user", "content": "Where was it played?"} 13 | ] 14 | ) 15 | -------------------------------------------------------------------------------- /notes.md: -------------------------------------------------------------------------------- 1 | # Tools & Tech Used in quanticdev.com 2 | * https://pages.github.com 3 | * https://jekyllrb.com 4 | * https://github.com/pages-themes/hacker 5 | * https://shopify.github.io/liquid/basics/operators 6 | -------------------------------------------------------------------------------- /shop.md: -------------------------------------------------------------------------------- 1 | # QuanticDev Shop 2 | Shop for material related to the articles and videos as well as QuanticDev's original artwork at: [quanticdev.redbubble.com](https://quanticdev.redbubble.com){:target="_blank"}{:rel="noopener"} 3 | 4 | 5 | 6 | 7 | # Samples 8 | [![QuanticDev Poster](assets/media/quanticdev_poster.jpg)](https://quanticdev.redbubble.com){:target="_blank"}{:rel="noopener"} 9 | 10 | [![QuanticDev Sticker](assets/media/quanticdev_sticker.jpg)](https://quanticdev.redbubble.com){:target="_blank"}{:rel="noopener"} 11 | -------------------------------------------------------------------------------- /tools/code-animation/code.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/code-animation/code.js -------------------------------------------------------------------------------- /tools/code-animation/code.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/code-animation/code.py -------------------------------------------------------------------------------- /tools/code-animation/main.py: -------------------------------------------------------------------------------- 1 | from manim import * 2 | 3 | 4 | """ 5 | $ manim code.py/js -p 6 | 7 | -p: preview: open vide file after rendering 8 | """ 9 | 10 | 11 | def highlight_line(code: Code, line_from, line_to): 12 | if not line_to: 13 | line_to = line_from 14 | lines = range(line_from, line_to) 15 | 16 | return [ApplyMethod(code.code[line_no].set_opacity, 1 if line_no in lines else .3) for line_no in range(len(code.code))] 17 | 18 | 19 | def create_code(code_src: str, ext: str = 'py', scale_factor: float = .7, insert_line_no=False): 20 | file = f'code.{ext}' 21 | with open(file, 'w') as f: 22 | f.write(code_src.replace(""" 23 | """, """ 24 | """)) # hack: not to get newlines trimmed by LaTex renderer, we replace '\n' with '\n ' 25 | 26 | code = Code(file, scale_factor=scale_factor, insert_line_no=insert_line_no) 27 | 28 | with open(file, 'w') as f: 29 | f.write('') 30 | 31 | return code 32 | 33 | 34 | # https://docs.manim.community/en/stable/reference.html 35 | class AnimatedCode(Scene): 36 | config['pixel_height'] = 2160 37 | config['pixel_width'] = 3840 38 | 39 | def animation_template(self): 40 | title = Tex('Title') 41 | title.to_corner(UP + LEFT) 42 | self.play(title) 43 | 44 | self.clear() 45 | code = create_code("""xxxxxx""") 46 | self.play(ShowCreation(code, run_time=10, rate_func=linear)) 47 | self.wait(5) 48 | 49 | self.play(*highlight_line(code, 2, 6)) 50 | self.wait(5) 51 | 52 | self.clear() 53 | code2 = create_code("""xxxxxx""") 54 | self.play(Transform(code, code2, run_time=2, rate_func=linear)) 55 | self.wait(5) 56 | 57 | def construct(self): 58 | code = create_code("""db.connect('postgresql://localhost/testdb') 59 | db.initialize() 60 | 61 | user = db.create_new_user('John Doe', 'john.doe@quanticdev.com') 62 | user.give_permission('create_blog_post') 63 | 64 | post = user.new_blog_post('Test Blog Post Title', 'Lorem ipsum dolor sit amet...') 65 | post.upload_thumbnail('./test_thumbnail.jpg') 66 | post.publish()""") 67 | self.play(ShowCreation(code, run_time=10, rate_func=linear)) 68 | self.wait(5) 69 | 70 | self.clear() 71 | 72 | code2 = create_code("""db.connect('postgresql://localhost/testdb') \\ 73 | .initialize() \\ 74 | .create_new_user('John Doe', 'john.doe@quanticdev.com') \\ 75 | .give_permission('create_blog_post') \\ 76 | .new_blog_post('Test Blog Post Title', 'Lorem ipsum dolor sit amet...') \\ 77 | .upload_thumbnail('./test_thumbnail.jpg') \\ 78 | .publish()""") 79 | self.play(Transform(code, code2, run_time=2, rate_func=linear)) 80 | self.wait(5) 81 | 82 | self.clear() 83 | 84 | code = create_code("""db.connect('postgresql://localhost/testdb') 85 | db.initialize()""") 86 | self.play(ShowCreation(code, run_time=5)) 87 | self.wait(5) 88 | 89 | self.clear() 90 | 91 | code2 = create_code("""db.connect('postgresql://localhost/testdb').initialize()""") 92 | self.play(Transform(code, code2, run_time=2, rate_func=linear)) 93 | self.wait(5) 94 | 95 | self.clear() 96 | 97 | code3 = create_code("""db.connect('postgresql://localhost/testdb') \\ 98 | .initialize() \\ 99 | .close()""") 100 | self.play(Transform(code2, code3, run_time=2, rate_func=linear)) 101 | self.wait(5) 102 | 103 | self.clear() 104 | 105 | code = create_code("""class DB: 106 | def connect(self, url): 107 | pass 108 | 109 | def initialize(self): 110 | pass 111 | 112 | def close(self): 113 | pass""") 114 | self.play(ShowCreation(code, run_time=10, rate_func=linear)) 115 | self.wait(5) 116 | 117 | self.clear() 118 | 119 | code2 = create_code("""class DB: 120 | def connect(self, url): 121 | # todo 122 | return self 123 | 124 | def initialize(self): 125 | # todo 126 | return self 127 | 128 | def close(self): 129 | # todo 130 | return self""") 131 | self.play(Transform(code, code2, run_time=2, rate_func=linear)) 132 | self.wait(5) 133 | 134 | self.clear() 135 | 136 | code = create_code("""db.connect('postgresql://localhost/testdb') 137 | log.info('Initializing the database.') 138 | db.initialize()""") 139 | self.play(ShowCreation(code, run_time=10, rate_func=linear)) 140 | self.wait(5) 141 | 142 | self.clear() 143 | 144 | code2 = create_code("""db.connect('postgresql://localhost/testdb') \\ 145 | .log_info('Initializing the database.') \\ 146 | .initialize()""") 147 | self.play(Transform(code, code2, run_time=2, rate_func=linear)) 148 | self.wait(5) 149 | 150 | self.clear() 151 | 152 | code = create_code("""subscribers 153 | .filter(p => p.liked_the_video === true) 154 | .sort(p => p.name) 155 | .pat_on_the_back()""", ext='js') 156 | self.play(ShowCreation(code, run_time=10, rate_func=linear)) 157 | self.wait(5) 158 | -------------------------------------------------------------------------------- /tools/recursion-visualization/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.js": "./static/js/main.673ef02c.chunk.js", 4 | "main.js.map": "./static/js/main.673ef02c.chunk.js.map", 5 | "runtime-main.js": "./static/js/runtime-main.0131dfd2.js", 6 | "runtime-main.js.map": "./static/js/runtime-main.0131dfd2.js.map", 7 | "static/js/2.676818fa.chunk.js": "./static/js/2.676818fa.chunk.js", 8 | "static/js/2.676818fa.chunk.js.map": "./static/js/2.676818fa.chunk.js.map", 9 | "index.html": "./index.html", 10 | "service-worker.js": "./service-worker.js", 11 | "static/js/2.676818fa.chunk.js.LICENSE.txt": "./static/js/2.676818fa.chunk.js.LICENSE.txt", 12 | "static/media/first.e33117eb.svg": "./static/media/first.e33117eb.svg", 13 | "static/media/last.14dc4eba.svg": "./static/media/last.14dc4eba.svg", 14 | "static/media/logo.b572fca9.svg": "./static/media/logo.b572fca9.svg", 15 | "static/media/next.fbb21171.svg": "./static/media/next.fbb21171.svg", 16 | "static/media/previous.aad86071.svg": "./static/media/previous.aad86071.svg" 17 | }, 18 | "entrypoints": [ 19 | "static/js/runtime-main.0131dfd2.js", 20 | "static/js/2.676818fa.chunk.js", 21 | "static/js/main.673ef02c.chunk.js" 22 | ] 23 | } -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/recursion-visualization/icon/android-chrome-192x192.png -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/recursion-visualization/icon/android-chrome-512x512.png -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/recursion-visualization/icon/apple-touch-icon.png -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/recursion-visualization/icon/favicon-16x16.png -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/recursion-visualization/icon/favicon-32x32.png -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/recursion-visualization/icon/favicon.ico -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soygul/QuanticDev/d0a360b7628108dfd0396b2357f99fa8fbd2fa52/tools/recursion-visualization/icon/mstile-150x150.png -------------------------------------------------------------------------------- /tools/recursion-visualization/icon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /tools/recursion-visualization/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Recursion Tree Visualizer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | -------------------------------------------------------------------------------- /tools/recursion-visualization/prism-dark.css: -------------------------------------------------------------------------------- 1 | /** 2 | * prism.js Dark theme for JavaScript, CSS and HTML 3 | * Based on the slides of the talk “/Reg(exp){2}lained/” 4 | * @author Lea Verou 5 | */ 6 | 7 | code[class*="language-"], 8 | pre[class*="language-"] { 9 | color: white; 10 | background: none; 11 | text-shadow: 0 -.1em .2em black; 12 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 13 | font-size: 1em; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | @media print { 32 | code[class*="language-"], 33 | pre[class*="language-"] { 34 | text-shadow: none; 35 | } 36 | } 37 | 38 | pre[class*="language-"], 39 | :not(pre) > code[class*="language-"] { 40 | background: hsl(30, 20%, 25%); 41 | } 42 | 43 | /* Code blocks */ 44 | pre[class*="language-"] { 45 | padding: 1em; 46 | margin: .5em 0; 47 | overflow: auto; 48 | border: .3em solid hsl(30, 20%, 40%); 49 | border-radius: .5em; 50 | box-shadow: 1px 1px .5em black inset; 51 | } 52 | 53 | /* Inline code */ 54 | :not(pre) > code[class*="language-"] { 55 | padding: .15em .2em .05em; 56 | border-radius: .3em; 57 | border: .13em solid hsl(30, 20%, 40%); 58 | box-shadow: 1px 1px .3em -.1em black inset; 59 | white-space: normal; 60 | } 61 | 62 | .token.comment, 63 | .token.prolog, 64 | .token.doctype, 65 | .token.cdata { 66 | color: hsl(30, 20%, 50%); 67 | } 68 | 69 | .token.punctuation { 70 | opacity: .7; 71 | } 72 | 73 | .token.namespace { 74 | opacity: .7; 75 | } 76 | 77 | .token.property, 78 | .token.tag, 79 | .token.boolean, 80 | .token.number, 81 | .token.constant, 82 | .token.symbol { 83 | color: hsl(350, 40%, 70%); 84 | } 85 | 86 | .token.selector, 87 | .token.attr-name, 88 | .token.string, 89 | .token.char, 90 | .token.builtin, 91 | .token.inserted { 92 | color: hsl(75, 70%, 60%); 93 | } 94 | 95 | .token.operator, 96 | .token.entity, 97 | .token.url, 98 | .language-css .token.string, 99 | .style .token.string, 100 | .token.variable { 101 | color: hsl(40, 90%, 60%); 102 | } 103 | 104 | .token.atrule, 105 | .token.attr-value, 106 | .token.keyword { 107 | color: hsl(350, 40%, 70%); 108 | /* font-weight: bold; */ 109 | } 110 | 111 | .token.regex, 112 | .token.important { 113 | color: #e90; 114 | } 115 | 116 | .token.important, 117 | .token.bold { 118 | font-weight: bold; 119 | } 120 | .token.italic { 121 | font-style: italic; 122 | } 123 | 124 | .token.entity { 125 | cursor: help; 126 | } 127 | 128 | .token.deleted { 129 | color: red; 130 | } 131 | -------------------------------------------------------------------------------- /tools/recursion-visualization/prism-light.css: -------------------------------------------------------------------------------- 1 | /** 2 | * prism.js default theme for JavaScript, CSS and HTML 3 | * Based on dabblet (http://dabblet.com) 4 | * @author Lea Verou 5 | */ 6 | 7 | code[class*='language-'], 8 | pre[class*='language-'] { 9 | color: black; 10 | background: none; 11 | text-shadow: 0 1px white; 12 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 13 | font-size: 1em; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | pre[class*='language-']::-moz-selection, 32 | pre[class*='language-'] ::-moz-selection, 33 | code[class*='language-']::-moz-selection, 34 | code[class*='language-'] ::-moz-selection { 35 | text-shadow: none; 36 | background: #b3d4fc; 37 | } 38 | 39 | pre[class*='language-']::selection, 40 | pre[class*='language-'] ::selection, 41 | code[class*='language-']::selection, 42 | code[class*='language-'] ::selection { 43 | text-shadow: none; 44 | background: #b3d4fc; 45 | } 46 | 47 | @media print { 48 | code[class*='language-'], 49 | pre[class*='language-'] { 50 | text-shadow: none; 51 | } 52 | } 53 | 54 | /* Code blocks */ 55 | pre[class*='language-'] { 56 | padding: 1em; 57 | margin: 0.5em 0; 58 | overflow: auto; 59 | } 60 | 61 | :not(pre) > code[class*='language-'], 62 | pre[class*='language-'] { 63 | background: #f5f2f0; 64 | } 65 | 66 | /* Inline code */ 67 | :not(pre) > code[class*='language-'] { 68 | padding: 0.1em; 69 | border-radius: 0.3em; 70 | white-space: normal; 71 | } 72 | 73 | .token.comment, 74 | .token.prolog, 75 | .token.doctype, 76 | .token.cdata { 77 | color: slategray; 78 | } 79 | 80 | .token.punctuation { 81 | color: #999; 82 | } 83 | 84 | .token.namespace { 85 | opacity: 0.7; 86 | } 87 | 88 | .token.property, 89 | .token.tag, 90 | .token.boolean, 91 | .token.number, 92 | .token.constant, 93 | .token.symbol, 94 | .token.deleted { 95 | color: #905; 96 | } 97 | 98 | .token.selector, 99 | .token.attr-name, 100 | .token.string, 101 | .token.char, 102 | .token.builtin, 103 | .token.inserted { 104 | color: #690; 105 | } 106 | 107 | .token.operator, 108 | .token.entity, 109 | .token.url, 110 | .language-css .token.string, 111 | .style .token.string { 112 | color: #9a6e3a; 113 | } 114 | 115 | .token.atrule, 116 | .token.attr-value, 117 | .token.keyword { 118 | color: #07a; 119 | /* font-weight: bold; */ 120 | } 121 | 122 | .token.function, 123 | .token.class-name { 124 | color: #dd4a68; 125 | } 126 | 127 | .token.regex, 128 | .token.important, 129 | .token.variable { 130 | color: #e90; 131 | } 132 | 133 | .token.important, 134 | .token.bold { 135 | font-weight: bold; 136 | } 137 | .token.italic { 138 | font-style: italic; 139 | } 140 | 141 | .token.entity { 142 | cursor: help; 143 | } 144 | -------------------------------------------------------------------------------- /tools/recursion-visualization/static/js/2.676818fa.chunk.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /** 8 | * Prism: Lightweight, robust, elegant syntax highlighting 9 | * 10 | * @license MIT 11 | * @author Lea Verou 12 | * @namespace 13 | * @public 14 | */ 15 | 16 | /** @license React v0.19.1 17 | * scheduler.production.min.js 18 | * 19 | * Copyright (c) Facebook, Inc. and its affiliates. 20 | * 21 | * This source code is licensed under the MIT license found in the 22 | * LICENSE file in the root directory of this source tree. 23 | */ 24 | 25 | /** @license React v16.13.1 26 | * react-dom.production.min.js 27 | * 28 | * Copyright (c) Facebook, Inc. and its affiliates. 29 | * 30 | * This source code is licensed under the MIT license found in the 31 | * LICENSE file in the root directory of this source tree. 32 | */ 33 | 34 | /** @license React v16.13.1 35 | * react-is.production.min.js 36 | * 37 | * Copyright (c) Facebook, Inc. and its affiliates. 38 | * 39 | * This source code is licensed under the MIT license found in the 40 | * LICENSE file in the root directory of this source tree. 41 | */ 42 | 43 | /** @license React v16.13.1 44 | * react.production.min.js 45 | * 46 | * Copyright (c) Facebook, Inc. and its affiliates. 47 | * 48 | * This source code is licensed under the MIT license found in the 49 | * LICENSE file in the root directory of this source tree. 50 | */ 51 | -------------------------------------------------------------------------------- /tools/recursion-visualization/static/js/runtime-main.0131dfd2.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,i,l=r[0],a=r[1],f=r[2],p=0,s=[];p