<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Alexander V on Medium]]></title>
        <description><![CDATA[Stories by Alexander V on Medium]]></description>
        <link>https://medium.com/@alexanderv?source=rss-f2289f999e5d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*fpkqu84lsgNPdn31q4t-Bg.jpeg</url>
            <title>Stories by Alexander V on Medium</title>
            <link>https://medium.com/@alexanderv?source=rss-f2289f999e5d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 17 May 2026 02:59:26 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@alexanderv/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[ Fast.ai Course Lesson 2: Deploying Cat vs Dog Classifier to Hugging Face Spaces in the Summer…]]></title>
            <link>https://medium.com/@alexanderv/fast-ai-course-lesson-2-deploying-cat-vs-dog-classifier-to-hugging-face-spaces-in-the-summer-1b3d4013909f?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/1b3d4013909f</guid>
            <category><![CDATA[fastai]]></category>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Fri, 25 Jul 2025 17:22:09 GMT</pubDate>
            <atom:updated>2025-07-25T18:02:34.355Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OORRemtu1MExtBSZ1y810w.png" /></figure><h3>🐾 Fast.ai Course Lesson 2: Deploying Cat vs Dog Classifier to Hugging Face Spaces in the Summer of 2025</h3><p>If you’re working through the <a href="https://course.fast.ai/">Fast.ai course</a> in the <strong>summer of 2025</strong> — this is for you.</p><p>In this post, I’ll walk you through how I deployed my trained <strong>Cats vs Dogs</strong> image classifier to <strong>Hugging Face Spaces</strong> using <strong>Gradio</strong>. This is <strong>Lesson 2</strong> of the course.</p><p>It took some version wrangling, YAML tweaking, and a few broken builds to get there — but the final result is finally <a href="https://huggingface.co/spaces/alexbrabus/dogs_cats"><strong>live</strong></a><strong>.</strong></p><p>👉 For the <strong>core learning steps</strong>, follow <a href="https://course.fast.ai/Lessons/lesson2.html">Lesson 2 here</a></p><p>Below is what’s changed in the 3 years and what will not work if you just follow the video / notebook from 2023.</p><h3>✅ What worked for me in 2025:</h3><h4>🧠 I trained the model in Colab</h4><p>Downloaded the .pkl file and uploaded it to my Hugging Face repo manually. Git wouldn’t let me push over 10MB.</p><h4>🧪 My app.py (Gradio interface)</h4><pre>from fastai.vision.all import *<br>import gradio as gr<br>import cloudpickle<br><br>learn = load_learner(&#39;model.pkl&#39;)<br>categories = (&#39;Cat&#39;, &#39;Dog&#39;)<br><br>def classify_image(img):<br>    pred, idx, probs = learn.predict(img)<br>    return {categories[i]: float(probs[i]) for i in range(len(categories))}<br><br>image = gr.Image(type=&quot;pil&quot;, label=&quot;Upload an image of a cat or dog&quot;)<br>label = gr.Label(num_top_classes=2, label=&quot;Prediction&quot;)<br><br>app = gr.Interface(fn=classify_image, inputs=image, outputs=label, title=&quot;Cat vs Dog Classifier&quot;)<br>app.launch(inline=False)</pre><h4>🧾 My requirements.txt</h4><pre>fastai==2.8.2<br>gradio==4.24.0<br>fasttransform<br>cloudpickle</pre><h4>⚙️ My README.md config block</h4><pre>---<br>title: Dogs Cats<br>emoji: 🐾<br>colorFrom: pink<br>colorTo: blue<br>sdk: gradio<br>python_version: 3.11<br>sdk_version: 5.38.2<br>app_file: app.py<br>pinned: false<br>license: apache-2.0<br>short_description: a dog or a cat?<br>---</pre><p>This configuration block defines your runtime environment. <strong>python_version: 3.11</strong> is important — older versions from 2023 may not match what your dependencies expect in 2025.</p><p>If you’re stuck or hitting weird bugs, feel free to fork my repo or reach out.</p><p>🐶😸 Good luck!</p><p>Reach out on X: <a href="https://x.com/alexvasyuk">@alexvasyuk</a><br>ChatGPT wrote this post.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1b3d4013909f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Product Design PM Interview Question — Improve Amazon’s Home and Lighting category page]]></title>
            <link>https://medium.com/@alexanderv/product-design-pm-interview-question-improve-amazons-home-and-lighting-category-page-ce438d587ca3?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/ce438d587ca3</guid>
            <category><![CDATA[product-management]]></category>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Tue, 25 Oct 2022 14:50:23 GMT</pubDate>
            <atom:updated>2022-10-25T14:50:23.047Z</atom:updated>
            <content:encoded><![CDATA[<h3>Product Design PM Interview Question — Improve Amazon’s Home and Lighting category page</h3><p>Prompt: Assume you are on the Home and Lighting team for the USA market, how would you go about improving our category page?</p><p><strong>Step 1 — Context</strong></p><p>CANDIDATE: I want to make sure I’m on the same page with you. You are talking about the main page for the category “Home and Lighting” for US users on Amazon’s Desktop, Mobile Web, and iOS &amp; Android clients. The people who visit this page are ordinary Amazon users from different walks of life looking to find the best deal on the internet for the items they are looking for. They use the category page to begin their search for items they want to buy.</p><p><strong>Step 2 — Personas</strong></p><p>CANDIDATE: Great, let’s start by breaking up the user base into multiple personas. I can imagine the following groups to frequent the category page:</p><ul><li><em>Homeowners:</em> age 30–45; first time homeowners; low-mid budget range; busy professional; time sensitive; multitasking. Purpose — want to find best-value quality items at the cheapest price point; want a one stop-shop for all their home &amp; lighting needs as they are busy professionals with no time to shop around. Picking out lights and other items probably feels like a chore technology should solve for them.</li><li><em>Contractors:</em> age 25–40; price insensitive; busy on multiple projects — too many details to keep in mind. Have incentive to either a) purchase the most convenient option, even if it’s more expensive — they aren’t paying. b) purchase from a merchant they receive commission from — personal financial gain.</li><li><em>Interior designers:</em> age 30–50; work within client budgets, busy on multiple projects — too many details to keep in mind. Have incentive to work with merchants who pay they commission per customer.</li></ul><p>From the three, I’d recommend focusing on the first time home owners as they probably make up the majority of the users visiting the category page.</p><p><strong>Step 3 — User needs</strong></p><p>CANDIDATE: I briefly mentioned some key needs of first-time home owners, let me outline a few in more detail:</p><ul><li>As the first time home owner I want a one stop shop for all my home &amp; lightning needs so I can quickly buy validated things for my house. I don’t have time to research and validate many options myself. I want to rely on social proof and research of others to get recommendations on what I should buy.</li><li>As the first time home owner I want to get the best price, yet not spend excessive time searching for it. The majority of my budget has been spent on the downpayment, but I don’t want to sacrifice quality of my lighting, etc.</li><li>As the first time home owner I want to make sure I install what I purchase a) correctly b) without devoting too much time to figuring out how to do it, because I’m short on time and don’t have the budget to make a mistake and have to purchase the item again.</li></ul><p><strong>Step 4 — Prioritize user needs</strong></p><p>CANDIDATE: To prioritize what to tackle first I choose and estimate the key parameters that affect the decision. For this problem I chose revenue impact and effort as the two key parameters. In the future we could also factor in impact on customer satisfaction.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7IoXKOGMkpTRJ5FXLII9cw.png" /></figure><p>The winner among the three needs for first-time homeowners is the need to afford quality items. Let’s see what we can do about it.</p><p><strong>Step 5 — Brainstorm solutions</strong></p><p>CANDIDATE: There are multiple ways to make something more affordable, one of the most straightforward ones is to sell it at a discount. But often times it is neither feasible nor economically rational. Lets brainstorm alternative ways to make items more affordable.</p><p>Idea 1: Advertise the option to pay in installments on the “Home and Lighting” category page. Since the category page is where the majority of the users land, advertising this new financial instrument should increase sales among users who can’t afford the item at a lump sum.</p><p>Idea 2: Advertise “group” buying on the “Home and Lighting” category page, whereby when enough people commit to purchasing by a certain deadline, the item is sold at a reduced price to each person. Users can offer such deals to sellers on Amazon as a reversal to when the seller needs to figure out the threshold for the minimal number of people and the discounted price.</p><p>Idea 3: Often the decision to purchase is the result of many potential purchases competing for the same budget. Highlight on the “Home and Lighting” category page the scarcity of the recommended items or groups of items. For example if there’s a world shortage of microchips, highlight the scarcity of home appliances that use them.</p><p><strong>Step 6 — Evaluate trade-offs</strong></p><p>CANDIDATE: To evaluate tradeoffs between potential solutions I usually define a few relevant criteria within the context of the problem. Here I think it’s important to consider: honesty, revenue potential, and ease of implementation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PArVbBFal5NQ_dLifxueaQ.png" /></figure><p>Since we are dealing with financial instruments it is paramount to consider how honest the users will perceive them to be in the context of other platforms they user and market norms in general.</p><p>Installments need to be communicated as tools devoid of hidden fees and other “gotcha” fine print moments. The customer needs to know exactly how installments are scheduled and paid out, and what the consequences are for failure to pay.</p><p>Group buying is relatively straightforward, it’s just a simple abstraction over the checkout process which is delayed in time. It is important to communicate clearly that the purchase will not happen if the minimal number of customers isn’t met. Failure to do so will generate disgruntled customers and negatively affect brand perception.</p><p>Scarcity highlights can be perceived to be the most dishonest as it is easily faked. Additionally people can leave the platform agitated having negative thoughts, because they either couldn’t afford the increase in price or they could, but overpaid for what was once cheaper.</p><p><strong>Step 7 — Make a recommendation</strong></p><p>CANDIDATE: To summarize I recommend that we improve the “Home &amp; Lighting” category page by introducing the ability to pay with installments, which should solve a critical problem of affording more quality items for our core audience — first time home owners — and be useful to other user segments who can benefit from splitting up the price into more manageable chunks.</p><p>Although there are substantial risks in a) execution (e.g debt collection is not our expertise) b) brand perception if this financial instrument is deemed dishonest, the business will benefit, because we will have introduced a new revenue stream which if successful can be easily scaled to other categories.</p><p><strong>Reviewing the answer</strong></p><p>Few things people suggested to pay attention to:</p><ul><li>In the “Context” step, clarify what the goal for the improvement is. Is it to drive revenue or improve customer experience? Ideally attach a metric to the goal and center the conversation around it. By doing so you are starting with a goal that can be measured (success metric) and when you end your discussion, you can circle back and point out that your proposed solution drives this success metric the best.</li><li>Think a bit deeper when defining personas and imagine how their CJM differs from the average one. Things like buying in bulk and getting alternative offers when you go over budget seem very logical and intuitive.</li><li>I thought I could shortcut on prioritizing which customer segment to focus on, by assuming and stating that they are the majority. But this stands out as shallow. Think of a few criteria and use them to prioritize which customer segment to choose from. Examples: which customer segment aligns best with company’s strategic vision; which customer segment generates the most revenue; which customer segment is growing very rapidly across the market. Perhaps I’m missing some key ones here, would love to hear from you!</li><li>Validating your solutions is an important sub-step of evaluating tradeoffs. Best done by demonstrating a good grasp on some real world numbers + conversions and being able to apply them to the specific case you are working on.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ce438d587ca3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Tries — javascript simple implementation]]></title>
            <link>https://medium.com/@alexanderv/tries-javascript-simple-implementation-e2a4e54e4330?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/e2a4e54e4330</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[computer-science]]></category>
            <category><![CDATA[data-structures]]></category>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Fri, 17 Jul 2015 23:33:22 GMT</pubDate>
            <atom:updated>2019-04-30T15:20:22.685Z</atom:updated>
            <content:encoded><![CDATA[<h4>What is a trie?</h4><p>A <strong>trie</strong> is a tree. It’s an n-ary tree, designed for efficient re<strong>trie</strong>val. How efficient is efficient? A trie allows us to search for a string in O(m), where m is the number of characters in that string. Do other data structures perform better? Perhaps, here is an argument in favor of Hashtables:</p><p><a href="http://loup-vaillant.fr/projects/string-interning/benchmark">Trie vs Hash Table Deathmatch!</a></p><p>Anyhow — tries. In a trie one can retrieve anything one can prefix and the most common example is to retrieve <strong>strings</strong>. One can treat individual <strong>characters</strong> as <strong>prefixes</strong> to a <strong>string</strong>. If we are to imagine a tree like structure with nodes having characters for keys, we will see that a path from the root to a leaf constitutes a string. We will also see that if two string were to share first character, their paths will share that one node and branch off into different directions afterwards. If one was so inclined, she could have a value at every leaf, which is admissible, however most of the nodes will just have a key, as they serve as prefixes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/293/1*krinmyx8b9O6ZWSSW8gkLw.png" /></figure><p>Note the root is an empty string denotes as “.” and \0 or <strong>null </strong>signals that the node completes a string.</p><h4>Operations</h4><p>What can a trie do and what can one for on a trie? Three simple operations are as follows:</p><ol><li>add</li><li>search</li><li>remove</li></ol><h4>Data structure representation</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0a401f65a7d5ef9220e6899078d1459c/href">https://medium.com/media/0a401f65a7d5ef9220e6899078d1459c/href</a></iframe><h4>Implementation</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3f6dcaf8e0c9a088bbaccb34ab80798e/href">https://medium.com/media/3f6dcaf8e0c9a088bbaccb34ab80798e/href</a></iframe><p>The <strong>add </strong>method has two while loops. The first looks for an appropriate place to insert an element and the second iterates through the remaining characters of the string, filling out the trie.</p><p>The <strong>search </strong>method returns the depth of the given key or <strong>-1</strong> if it does not find any.</p><p>If the string in question is present in the trie, the <strong>remove </strong>method recurses down to the node that represents the last character of the string and removes nodes associated with the characters in the string only if they have no sub nodes dependent on them.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e2a4e54e4330" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Network Panel — chrome developer tools]]></title>
            <link>https://medium.com/@alexanderv/network-panel-chrome-developer-tools-a1c1d5c4e88?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/a1c1d5c4e88</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[notes]]></category>
            <category><![CDATA[chrome]]></category>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Wed, 06 May 2015 16:50:24 GMT</pubDate>
            <atom:updated>2015-05-06T16:50:24.710Z</atom:updated>
            <content:encoded><![CDATA[<p>NOTE: always disable cache when recording network traffic</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/660/1*dECuZykfPwXvqSJyeAEp6Q.png" /></figure><p><strong>Filters:</strong></p><p>Only interested in traffic associated with font resources? — use a filter — font filter.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xEycjuAiHDkFf7KJ0z2a7g.png" /></figure><p>The ‘Filter’ search box, top-left corner, allows for advanced filters. Ex: type in “Domain”.</p><p>Don’t neglect the statistics:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ohBjFz988BB_h08umg5ciw.png" /><figcaption>How many requests occurred, how much network traffic was transferred, the time it took, when DOMContentLoaded even was fired, when Load event was fired</figcaption></figure><p>Wondering what the difference between <strong>DOMContentLoaded</strong> and <strong>Load</strong> events is? Me too.</p><p>From the <a href="https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded">Mozilla Developer Center</a>:</p><blockquote>The <strong>DOMContentLoaded </strong>event is fired when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading (the <strong>load </strong>event can be used to detect a fully-loaded page).</blockquote><p>Okay, so I choose an actual item resource — I get a few panes: headers, response, preview, cookies, timing. These are self explanatory.</p><p>Back in the default view I see default columns: method, status, type… right click on any one — I get more options: cookies, domain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*caQ_amSd8P_V5RvW3R75TQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/253/1*nwE3HoOPnvI71gkDureccQ.png" /></figure><p>Right click on a resource itself — get copy options.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/251/1*InDLbMDD3PXUyiNsJKgYag.png" /></figure><p>By the way — initiator column. It tells me how a resource came to be. Style — link tag. JS — probably a script tag. It can also give a stack of calls that initiated the resource.</p><p>Reference: TutsPlus “Chrome developer tools”</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a1c1d5c4e88" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Chrome Developer Tools — The Console Panel]]></title>
            <link>https://medium.com/@alexanderv/chrome-developer-tools-the-console-panel-3a28146d820b?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/3a28146d820b</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[chrome]]></category>
            <category><![CDATA[notes]]></category>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Tue, 05 May 2015 18:51:32 GMT</pubDate>
            <atom:updated>2015-05-05T19:48:25.370Z</atom:updated>
            <content:encoded><![CDATA[<h3>Chrome Developer Tools — The Console Panel</h3><p>Why — accelerate debugging</p><p>The console panel gives the ability to inject javascript into the context of the current page.</p><p><strong>Console API:</strong></p><p><strong>console.error</strong> — gives us a stack of the function calls that lead up to the error</p><p><strong>console.group(n) &amp; console.groupEnd (n)</strong>— group logging messages</p><p><strong>%c</strong> — inside the log message allows us to apply limited css properties to the message</p><p><strong>console.time(name) &amp; console.timeEnd(name)</strong> — everything executed in-between these two calls is timed, then the time is logged as “name: time”</p><p><strong>Command API:</strong></p><p><strong>$0 </strong>— returns currently selected element</p><p><strong>$_</strong> — returns the value of the last evaluated piece of code</p><p>Handy trick: to get <strong>autocomplete</strong> on a jquery selection — make the selection, then use <strong>$_</strong> to get the last value — press “.” and autocomplete is available. This works because the code has already been evaluated.</p><p><strong>getEventListeners(x) </strong>— returns a list of event listeners registered on the DOM node ‘x’ we passed in. For instance x could be <strong>document.body. </strong>Right click<strong>— </strong>‘show function definition’ will take you to the defining function. Good for debugging outside in.</p><p><strong>keys/values(o) </strong>— returns keys/value of the object o</p><p><strong>monitorEvents(object, eventName) </strong>— ex: monitorEvents(window, ‘scroll’) logs scroll events to the console. Good for debugging outside in.</p><p><strong>Object API:</strong></p><p><strong>Object.observe: </strong>to pause in the debugger every time a property is set on an object we care about we can do this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/678fce57077fc4b707acd4c65115d3c1/href">https://medium.com/media/678fce57077fc4b707acd4c65115d3c1/href</a></iframe><p><strong>Object.defineProperty</strong> — find out every time a property on the object in question is being accessed.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b8cf1ac5d72f1d398b61a209afd67ca7/href">https://medium.com/media/b8cf1ac5d72f1d398b61a209afd67ca7/href</a></iframe><p>Reference: Tutsplus course “Chrome developer tools”</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3a28146d820b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Linked List of Integers — Remove a node]]></title>
            <link>https://medium.com/@alexanderv/linked-list-of-integers-remove-a-node-d1490e7a3d93?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/d1490e7a3d93</guid>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Sat, 18 Oct 2014 03:22:23 GMT</pubDate>
            <atom:updated>2014-10-18T03:22:23.139Z</atom:updated>
            <content:encoded><![CDATA[<h3>Linked List of Integers — Remove a node</h3><p><em>*The formulation of the question comes from 28 questions by Arden Dertat<br></em>Given a linked list of integers and an integer, delete every node of the linked list containing the value.</p><p>Input: linked list of integers and an integer value<br>Output: same linked list without the nodes containing the integer value<br>Constraints: in linear time</p><h4>Step 1: Questions</h4><p>Q: Is the linked list doubly or singly linked?<br>A: Doubly</p><h4>Step 2: Design an algorithm</h4><p>The mechanics of the algorithm are simple. Keep track of the parent of the current node. If the current node is to be removed, set parent’s next to current’s next and current next’s parent to the parent. However there are a couple corner cases that need to be addressed.</p><ol><li>The head node is to be removed. — The function return value ought to be the head node.</li><li>There are duplicate elements, in which case you only advance the current node</li></ol><h4>Step 3: Pseudocode</h4><p>The <strong>Node </strong>class will have pointers to the next and parent nodes and an integer variable to hold the data;</p><pre>private Node parent;<br>private Node next;<br>private Node data;</pre><p>Since the member variables are private the class defines public getters and setters:</p><pre>public Node getParent() {..}<br>public Node getNext() {..}<br>public void setParent() {..}<br>public void setNext() {..}<br>public Integer getData() {..}</pre><p>We should not be able to create an empty node, so the constructor will take an int as its argument and assign it to the data variable.</p><pre>public Node(int d) {data = d}</pre><p>The <strong>DoublyLinkedList </strong>class has pointers to its head and its tail.</p><pre>private Node head;<br>private Node tail;</pre><p>Again the member variable are private, so we define getters/setters as we did previously. The append method takes an integer argument, create a new node and appends it to tail. Here we need to remember that if the head is null, the tail should also be null and if the append is called both head and tail are set to the same node.</p><pre>append(int d) {<br> if head is null, set head and tail to a new node(d)<br> else set tail&#39;s next to a new node(d), set the new node&#39;s parent to tail and advance the tail<br>}</pre><p>We do not define a constructor for this class, so one with no arguments is defined for us by default.</p><p>The remove method will return the head of the linked list just in case the head is the node to be removed. Other than that the mechanism of deletion is specified in step 2. Here is the pseudocode:</p><pre>Node remove(int d) {<br>id head == null: return null<br>while head isn&#39;t null and head&#39;s data matches d: advance head and set new head&#39;s parent to null<br>while there are still nodes to be traversed:<br> if current node&#39;s data matches d: set parent&#39;s next to<br> current&#39;s next and current&#39;s next&#39;s parent to parent, advance<br> current only<br> else advance both parent and current<br>return head</pre><h4>Step 4: Code</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8b78fca008ea0f78893566c101a06595/href">https://medium.com/media/8b78fca008ea0f78893566c101a06595/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d1490e7a3d93" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Parsing mathematical expressions into a binary tree — Part 2]]></title>
            <link>https://medium.com/@alexanderv/parsing-mathematical-expressions-into-a-binary-tree-part-2-570e61dc8632?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/570e61dc8632</guid>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Thu, 09 Oct 2014 00:00:24 GMT</pubDate>
            <atom:updated>2014-10-09T00:00:24.648Z</atom:updated>
            <content:encoded><![CDATA[<p>The second part of the problem involved adding parentheses functionality, which turned out easier than expected.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1f8610eb01fa3c6383a3b5fd111ebcb1/href">https://medium.com/media/1f8610eb01fa3c6383a3b5fd111ebcb1/href</a></iframe><p>The entire code is below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0c803a9d0fc92e2833007e344c4cf27f/href">https://medium.com/media/0c803a9d0fc92e2833007e344c4cf27f/href</a></iframe><p>To test this code run something like:</p><pre>evaluate(infixToBinaryTree(“3+4*2/(1-(3+4*2/1–5))”))</pre><p>This should return 1.4</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=570e61dc8632" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Parsing mathematical expressions into a binary tree — Part 1]]></title>
            <link>https://medium.com/@alexanderv/parse-and-evaluate-mathematical-expressions-dd6451e51a96?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/dd6451e51a96</guid>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Tue, 07 Oct 2014 01:12:13 GMT</pubDate>
            <atom:updated>2014-10-09T04:27:32.943Z</atom:updated>
            <content:encoded><![CDATA[<h3>Parsing mathematical expressions into a binary tree — Part 1</h3><p><em>This is a rewrite of my original article as I realized the problem was more complicated than I initially thought.</em></p><p>Parse and evaluate “(1+2)*3” expression.</p><p>This is a two step process. First I decided to tackle the problem without worrying about parentheses. Turns out that there is an algorithm named “<a href="http://en.wikipedia.org/wiki/Shunting-yard_algorithm">Shunting-yard algorithm</a>” that parses mathematical expressions specified in infix notation (normal human readable notation, in which the two expressions above are specified). Follow the Wikipedia link above to read about the algorithm.</p><p>However this procedure will return the output queue in the <a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation">Reverse Polish Notation</a>(RPN), so the output will look like this: “1 2 3 * +” What I want is to build a binary tree in the form:</p><pre> + <br>1 * <br> 2 3 </pre><p>To convert my output into binary tree form, it is informative to read about how RPN is <a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation">parsed</a>. Based on that knowledge I came up with my own version of the algorithm that creates a binary tree which if traversed post-order will produce the correct result of a mathematical expression. Note that I replaced the output queue with an output stack.</p><p>First I defined some auxiliary classes and methods. Stack class is really just a wrapper for an array, with an additional peek method. Operator is a parent to fours of its subclasses: Plus, Minus, Multiply, Divide, which each define how they are applied two two arguments arg1 and arg2. createOperator is a factory method for the Operator class.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b1a53824a1a61a9724f92ca7bd6399e1/href">https://medium.com/media/b1a53824a1a61a9724f92ca7bd6399e1/href</a></iframe><p>The main part of the application is the infixToBinary function. In its core it is a for loop that parses the string (one bug I quickly discovered was that numbers can have more than one digit):</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/093c9904a366acee01b0397abd1d914d/href">https://medium.com/media/093c9904a366acee01b0397abd1d914d/href</a></iframe><p>and the logic of the algorithm:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f230882bb687bf4d52566df66a9ebdba/href">https://medium.com/media/f230882bb687bf4d52566df66a9ebdba/href</a></iframe><p>If a token is a number it is pushed onto the outputStack, where it waits to be converted into a node of the resulting binary tree by either one of two functions: createSubtree() or updateTree(). Essentially my modification consists of placing subtrees onto the output stack for the updateTree() to pick up when in the final while loop it assembles the entire binary tree. Note that for this version of the algorithm intermediate subtrees are computed if the next operator on the stack is <strong>less than or equal</strong> to the current one, not just less than. A quick example :“3 — 5 +2&quot;. The correct answer to this is 0, but if you only choose to create intermediate subtrees for operators less than the current one, then you will end up with -4, because the algorithm will create a tree looking like this:</p><pre> -<br>3 +<br> 5 2 </pre><p>I learned it the hard way.</p><p>The createSubtree function creates intermediate subtrees that are then placed on the output stack:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9b288b35dbbf3381ba0be9a40e647fb0/href">https://medium.com/media/9b288b35dbbf3381ba0be9a40e647fb0/href</a></iframe><p>The updateTree walks through the stack creating the final tree:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cf85e70b0933e99fcc7d67543fd77dfd/href">https://medium.com/media/cf85e70b0933e99fcc7d67543fd77dfd/href</a></iframe><p>To test the tree use this evaluation function</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/22e2ed44d6a0ebada15c1b6a788a4034/href">https://medium.com/media/22e2ed44d6a0ebada15c1b6a788a4034/href</a></iframe><p><a href="https://medium.com/@alexanderv/parsing-mathematical-expressions-into-a-binary-tree-part-2-570e61dc8632">Read Part 2</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dd6451e51a96" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Merge two object]]></title>
            <link>https://medium.com/@alexanderv/merge-two-object-cc6c08ea3af6?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/cc6c08ea3af6</guid>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Sat, 04 Oct 2014 21:09:30 GMT</pubDate>
            <atom:updated>2014-10-09T04:27:51.594Z</atom:updated>
            <content:encoded><![CDATA[<h3>Merge two objects</h3><p>Objective:</p><pre>Write a function that will recursively merge two objects with the following conditions:<br>1.) If a[field] is an array, and b[field] is defined and is not an array, add b[field] to the array<br>2.) If a[field] is an array an b[field] exists but is undefined or null, set a[field] to an empty array<br>3.) If a[filed] is an array and b[field] is an array, set a[field] to b[field]<br>4.) If a[field] exists and b[field] exists but is undefined, delete a[field]<br>5.) If b[field] is a non-complex type (number, string, boolean, et cetera), copy to a[field]</pre><p>This is my attempt:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a89aac39fc983d0f98136ed049aa27aa/href">https://medium.com/media/a89aac39fc983d0f98136ed049aa27aa/href</a></iframe><p>A couple valuable things I came across while doing this problem:<br>1. == vs === The difference lies in type conversion to compare to values. === does not do type conversion, whereas == does.</p><p>2. The correct way to check if a variable is undefined is</p><pre>typeof nameOfVariable === &quot;undefined&quot;</pre><p>This ensures that even if ‘nameOfVariable’ is not defined, the condition still returns true.</p><p>3. I needed to write deepCompare(a, result) to check my answer:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/773afa3962b0b3a20be1f0c5c11ed346/href">https://medium.com/media/773afa3962b0b3a20be1f0c5c11ed346/href</a></iframe><p>The reason I have the second for loop is because ‘b’ can have fields that ‘a’ doesn’t and vice versa.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cc6c08ea3af6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Finding the missing element]]></title>
            <link>https://medium.com/@alexanderv/finding-the-missing-element-a6599c20084a?source=rss-f2289f999e5d------2</link>
            <guid isPermaLink="false">https://medium.com/p/a6599c20084a</guid>
            <dc:creator><![CDATA[Alexander V]]></dc:creator>
            <pubDate>Fri, 03 Oct 2014 05:43:10 GMT</pubDate>
            <atom:updated>2014-10-03T05:43:10.914Z</atom:updated>
            <content:encoded><![CDATA[<p>**This questions comes from “28 interview questions” by Arden Dertat.</p><p>Given an array of positive integers and a second array, which was formed by shuffling the elements of the first array and deleting one, find the missing element.</p><ol><li>Sum all elements in 1st array and in 2nd array. The difference of two sums will be your missing number. As Arden points out, with large number this approach wont work because of overflow.</li><li>Sort both arrays and scan both at the same time. Once you hit two elements that differ, the one in the first array is the missing element-&gt; O(nlogn) and requires no duplicate elements</li><li>Create a counter hashmap. Scan the second array counting how many times each element appears, then scan the first one, subtracting from appropriate values in the hash. When you hit a zero -&gt; missing element. Although this is O(N) in time, it is also O(N) in space.</li><li>XOR all elements in first and second array, you will be left with the missing element. XORing the number with itself gives 0, plus what is very important is the order of the xor operation does not make a difference, meaning n1 ^ n2 ^ n3 ^n2 ^n3 = n1. This approach is O(n) time and O(1) space.</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a6599c20084a" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>