https://youngforest.github.io/enYoungForest's blog2024-01-12T03:58:52.000Zhttps://youngforest.github.io/en/2024/01/12/Actions-After-Address-Change-in-Ireland/Actions After Address Change in Ireland<p>As an new immigrant in Ireland, it is very common that you move every year. It is painful to move. It makes the situation worse because many things in Ireland are related to your address. This post summary the actions you need to take after you move to a new address. It would prevent you from missing any important mail, which could be posted to your previous address if you forget to change your information somewhere.</p>
<ol>
<li>Bank accounts.</li>
<li>Broker accounts.</li>
<li>Pension accounts.</li>
<li>Medical insurance.</li>
<li>Revenue.</li>
<li>Car registration.</li>
<li>Your employer’s portal.</li>
</ol>
<p>For some accounts which are related to your job, like pension, Company stocks, you need to contact your HR to change your address.</p>
2024-01-12T03:58:52.000Zhttps://youngforest.github.io/en/2023/09/20/Ireland-France-visa-monitor/Ireland France visa monitor<p>It is a painful process to book an France visa appointment. A tool was implemented to notify you when a new slot is released. As a 9 years of expereinced software engineer, I finally beat the scalpers and got my France visa appointment by the script. A software engineer never bows to scalpers.</p>
<p>Currently, only Dublin Ireland appointments are supported. Please read the instructions docs to learn how to use it: <a href="https://docs.google.com/document/d/1uHJCxINt9Sb0f1HHybCFhxkmpzxRURilsxqD6OQLpQ4/edit?usp=sharing">Google Docs</a></p>
2023-09-20T06:13:01.000Zhttps://youngforest.github.io/en/2023/04/01/IB-Bonds-Tutorial/IB Bonds Tutorial<p><a href="https://www.interactivebrokers.com/en/?f=/en/general/education/hdi_bonds.php">How Do I Trade Bonds?</a></p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/x4kv7d0j82A" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<h2 id="IB-Bonds-Tutorial"><a href="#IB-Bonds-Tutorial" class="headerlink" title="IB Bonds Tutorial"></a>IB Bonds Tutorial</h2><h3 id="What-are-Bonds"><a href="#What-are-Bonds" class="headerlink" title="What are Bonds?"></a>What are Bonds?</h3><p>Bonds are a type of interest-bearing security usually issued by a government or corporation that obligates the issuer to pay the holder interest (usually at set intervals) and to repay the entire amount of the loan at maturity. Bonds can be grouped in the following categories:</p>
<ul>
<li>Government Bonds are bonds issued by a national government. Bonds issued by the U.S. Government are called Treasuries. They belong to three categories with different maturities: Treasury bills, Treasury notes and Treasury bonds. Treasuries are considered the safest bond investments since the U.S. government backs them and it is highly unlikely that a situation of default will occur. Treasuries with long maturities have more potential for inflation and credit risk.</li>
<li>Municipal Bonds are popular in the United States. They represent debt obligations of a U.S. state or local governments. Municipal bonds are considered riskier investments than Treasuries, but they are exempt from taxing by the federal government and local governments often exempt their own citizens from taxes on its bonds. Municipal bonds often have a lower coupon rate because of the tax break.</li>
<li>Corporate Bonds are issued by private corporations. Corporate bonds come in various maturities. They are considered the riskiest of the bonds because there is much more of a credit risk with corporate bonds, but this usually means that the bond holder will be paid a higher interest rate. Corporations with low credit ratings issue bonds that are speculative products called junk bonds. Par value, or face amount, is usually $1,000, but bond prices are quoted as a percentage. For example, a quote of 90 is a bond selling for $900.</li>
</ul>
<h3 id="Bonds-Characteristics-and-Rating"><a href="#Bonds-Characteristics-and-Rating" class="headerlink" title="Bonds Characteristics and Rating"></a>Bonds Characteristics and Rating</h3><p>Par Value. The par value of a bond (also called principal or face amount) is the amount that the issuer agrees to pay the investor when the bond matures. An investor who buys a bond with par value of $1,000 can expect to receive $1,000 when the bond reaches maturity. The par value of a bond can greatly differ from its market price, which is the price an investor pays to purchase the bond. A bond sold for more than its par value is selling “at a premium”, while a bond that is selling for less than its par value is selling “at discount”.</p>
<p>Bond Prices. The price of a bond usually is stated as a percentage of its par value. For example a bond with face value of $1,000 and a price of 90 is selling at a discount equal to 90% of its par value (90% * $1,000 = $900).</p>
<p>Maturity. The maturity of a bond is the day on which the issuer must pay the principal (face amount) of the bond to the investor. Maturities generally can vary from 10 years to as long as 100 years. Bonds with higher maturities pay higher interest rates all other factors being equal.</p>
<p>Coupon Rate. Until it matures the issuer agrees to pay the investor a stated amount of interest called the coupon rate or nominal yield. The amount of the coupon rate is the stated interest rate multiplied by the bond’s par value.</p>
<p>Current Yield. It measures the interest that the investor receives from the bond compared to its current market price. It is computed by dividing the annual interest by the current market price. One issue with the current yield is that it does not represent the future price appreciation on a discount bond or the price depreciation on a premium bond when held to maturity.</p>
<p>Yield to Maturity. It measures the investor’s total overall return. It is the most commonly quoted type of yield for bonds. It includes the annual interest that an investor receives and also the difference between the price paid by the investor for the bond and the amount received at maturity.</p>
<p>Bonds Rating. Standard & Poor’s and Moody’s Investors Service assign credit ratings to governments and corporations which help determine the amount of interest paid. The ratings represent greater default risk as you read down the chart below:</p>
<table>
<thead>
<tr>
<th align="center">Quality</th>
<th align="center">Moody’s</th>
<th align="center">Standard & Poor’s</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Best Quality</td>
<td align="center">Aaa</td>
<td align="center">AAA</td>
</tr>
<tr>
<td align="center">High Quality</td>
<td align="center">Aa</td>
<td align="center">AA</td>
</tr>
<tr>
<td align="center">Upper-medium Grade</td>
<td align="center">A</td>
<td align="center">A</td>
</tr>
<tr>
<td align="center">Medium Grade</td>
<td align="center">Baa</td>
<td align="center">BBB</td>
</tr>
<tr>
<td align="center">Junk bonds/Speculative/High yield</td>
<td align="center">Ba, B, Caa, Ca</td>
<td align="center">BB, B, CCC, CC</td>
</tr>
<tr>
<td align="center">Default</td>
<td align="center"></td>
<td align="center">D</td>
</tr>
</tbody></table>
<h3 id="Risks"><a href="#Risks" class="headerlink" title="Risks"></a>Risks</h3><p>Trading bonds may not be suitable for all investors. Although bonds are generally considered conservative investments, there are numerous risks involved in bond trading.</p>
<p>Credit risk. When the investor purchases a corporate bond, the investor is lending money to a company. There is always the risk that the issuer will go bankrupt. If this happens, the investor will not receive his investment back. Credit risk is taken into account in the pricing of bonds.</p>
<p>Prepayment risk. Prepayment risk involves the scenario where an issuer “calls” a bond. If this happens, his investment will be paid back early. Certain bonds are callable and others are not. This information is detailed in the prospectus. If a bond is callable, the prospectus will detail a “yield-to-call” figure. Corporations may call their bonds when interest rates fall below current bond rates.</p>
<p>Conversely, a “put” provision allows a bondholder to redeem a bond at par value before it matures. Investors may do this when interest rates are rising and they can get higher rates elsewhere. The issuer will assign specific dates to take advantage of a put provision. Prepayment risk is taken into account in the pricing of bonds.</p>
<p>Inflation risk. Inflation risk is the risk that the rate of the yield to call or maturity of the bond will not provide a positive return over the rate of inflation for the period of the investment. In other words, if the rate of inflation for the period of an investment is 3 percent and the yield to maturity of a bond is 2 percent, the investor will receive more money in interest and principal than the investor invested, but the value of that money returned is actually less than what was originally invested in the bond. As the inflation rate rises, so do interest rates. Although the yield on the bond increases, the price of the actual bond decreases.</p>
<p>Interest rate risk. Changes in interest rates during the term of any bond may affect the market value of the bond prior to call or the maturity date. There is generally an inverse relationship in between market interest rates and bond prices. This can be explained as follows. The coupon rate of a bond remains fixed over the life of the bond. As interest rates in the market increase, a buyer of the bond will want to see a yield to maturity that reflects the now higher market rates. Since coupon rates are fixed, the price paid must be less than the par value of the bond to a degree that compensates for the difference between the bond’s coupon rate and the higher market rate. The opposite happens in case of decreasing market interest rates. As interest rates decrease, the prices of existing bonds increase.</p>
<h2 id="Questions"><a href="#Questions" class="headerlink" title="Questions"></a>Questions</h2><h3 id="Which-answer-is-correct-for-question-“Which-of-the-following-is-correct-regarding-Bonds-”"><a href="#Which-answer-is-correct-for-question-“Which-of-the-following-is-correct-regarding-Bonds-”" class="headerlink" title="Which answer is correct for question “Which of the following is correct regarding Bonds?”"></a>Which answer is correct for question “Which of the following is correct regarding Bonds?”</h3><ol>
<li>Bonds are a type of interest-bearing security that obligates the issuer to pay the holder the entire amount of the loan at maturity.</li>
<li>Bonds are a type of security that signifies proportionate ownership in the issuing corporation. This entitles the holder to that proportion of the corporation’s assets and earnings.</li>
<li>Bonds are a portfolio of securities managed by an investment company in accordance with specified investment objectives.</li>
<li>Bonds are financial derivatives that give buyers the right, but not the obligation, to buy or sell an underlying asset at an agreed-upon price and date.</li>
</ol>
<h3 id="Which-of-the-following-is-not-correct-regarding-Bonds"><a href="#Which-of-the-following-is-not-correct-regarding-Bonds" class="headerlink" title="Which of the following is not correct regarding Bonds?"></a>Which of the following is not correct regarding Bonds?</h3><ol>
<li>Treasuries are considered the safest bond investments.</li>
<li>Municipal bonds are considered riskier investments than Treasuries.</li>
<li>Corporate bonds are considered the riskiest of the bonds because of the higher credit risk.</li>
<li>Corporate bonds are debt instruments issued by the City of London Corporation.</li>
</ol>
<p>Answer 1 is correct. As an interest bearing security, a bond obliges the issuer to pay the holder the entire amount of the loan at maturity.<br>Answer 4 is not correct regarding bonds. Corporate bonds are debt instruments issued by corporations, not by the City of London Corporation.</p>
<h3 id="Which-of-the-following-is-not-correct-regarding-Bonds-1"><a href="#Which-of-the-following-is-not-correct-regarding-Bonds-1" class="headerlink" title="Which of the following is not correct regarding Bonds?"></a>Which of the following is not correct regarding Bonds?</h3><ol>
<li>The face amount is the price an investor pays to purchase the bond.</li>
<li>The par value of a bond is the amount that the issuer agrees to pay the investor when the bond matures.</li>
<li>A bond sold for more than its par value is selling “at a premium”.</li>
<li>A bond that is selling for less than its par value is selling “at discount”.</li>
</ol>
<p>Answer 1 is not correct regarding bonds. The face amount of a bond is the amount the issuer agrees to pay the investor when the bond matures, not the price the investor pays to purchase the bond.</p>
<h3 id="Which-of-the-following-is-not-correct-regarding-Bonds-2"><a href="#Which-of-the-following-is-not-correct-regarding-Bonds-2" class="headerlink" title="Which of the following is not correct regarding Bonds?"></a>Which of the following is not correct regarding Bonds?</h3><ol>
<li>The price of a bond usually is stated a percentage of its par value.</li>
<li>A bond with face value of $1,000 and a price of 88 is selling for 88% of its par value (88% * $1,000 = $880).</li>
<li>A bond with face value of $1,000 and a price of 88 is selling at a premium equal to 12% of its par value (12% * $1,000 = $120).</li>
<li>The par value of a bond can differ from its market price.</li>
</ol>
<p>Answer 3 is not correct regarding bonds. A bond with face value of $1,000 and a price of 88 is selling at a discount equal to 12% of its par value, not at a premium.</p>
<h3 id="Which-of-the-following-is-not-correct-regarding-Bonds-3"><a href="#Which-of-the-following-is-not-correct-regarding-Bonds-3" class="headerlink" title="Which of the following is not correct regarding Bonds?"></a>Which of the following is not correct regarding Bonds?</h3><ol>
<li>The maturity of a bond is the day on which the issuer must pay the principal (face amount) of the bond to the investor.</li>
<li>Maturities generally can vary from 10 years to as long as 100 years.</li>
<li>Bonds with higher maturities generally pay higher interest rates all other factors being equal.</li>
<li>Bonds with higher maturities generally pay lower interest rates all other factors being the same.</li>
</ol>
<p>Answer 4 is not correct regarding bonds. Bonds with higher maturities generally pay higher interest rates all other factors being equal.</p>
<h3 id="Which-of-the-following-is-not-correct-regarding-Bonds-Yields"><a href="#Which-of-the-following-is-not-correct-regarding-Bonds-Yields" class="headerlink" title="Which of the following is not correct regarding Bonds Yields?"></a>Which of the following is not correct regarding Bonds Yields?</h3><ol>
<li>The nominal yield is the stated interest rate paid to the investor multiplied by the bond’s par value.</li>
<li>The current yield is computed by dividing the annual interest by the current market price.</li>
<li>The yield to maturity takes into account both the interest that an investor receives and the difference between the price paid by the investor for the bond and the amount received at maturity.</li>
<li>The yield to maturity does not take into account the interest that an investor receives, but only the difference between the price paid by the investor for the bond and the amount received at maturity.</li>
</ol>
<p>Answer 4 is not correct regarding bond yields. The yield to maturity takes into account both the interest that an investor receives and the difference between the price paid by the investor for the bond and the amount received at maturity.</p>
<h3 id="Which-of-the-following-is-not-correct-regarding-Bonds-Rating"><a href="#Which-of-the-following-is-not-correct-regarding-Bonds-Rating" class="headerlink" title="Which of the following is not correct regarding Bonds Rating?"></a>Which of the following is not correct regarding Bonds Rating?</h3><ol>
<li>The bond credit rating represents a bond issuer’s financial strength, or its ability to pay a bond’s principal and interest, in a timely fashion.</li>
<li>A junk bond is a bond with rating “BB” or lower according to Standard & Poor’s.</li>
<li>Morgan Stanley is one of three major independent credit rating agencies.</li>
<li>Junk bonds usually offer a higher yield to compensate for the lower credit rating.</li>
</ol>
<p>Answer 3 is not correct regarding bonds rating. Morgan Stanley is not one of the three major independent credit rating agencies, which are Standard & Poor’s, Moody’s and Fitch Ratings.</p>
<h3 id="Which-of-the-following-is-not-correct-regarding-Callable-Bonds"><a href="#Which-of-the-following-is-not-correct-regarding-Callable-Bonds" class="headerlink" title="Which of the following is not correct regarding Callable Bonds?"></a>Which of the following is not correct regarding Callable Bonds?</h3><ol>
<li>Prepayment risk involves the scenario where an issuer calls a bond prior to maturity.</li>
<li>Issuers usually call their bonds when interest rates fall below current bond rates.</li>
<li>Investors usually call their bonds when interest rates rises above current bond rates.</li>
<li>Prepayment risk is taken into account in the pricing of bonds.</li>
</ol>
<p>The answer 3 statement “Investors usually call their bonds when interest rates rises above current bond rates” is not correct for Callable Bonds. Instead, Callable Bonds give issuers the right to call or force the holder to sell the bond back prior to maturity, usually when interest rates fall below the current bond rates. Prepayment risk involves the possibility of a bond being paid back prior to maturity. Prepayment risk is usually taken into account when pricing bonds. Thus, statements 1 and 4 are correct while statement 2 is correct for callable bonds.</p>
<h3 id="Which-of-the-following-is-not-correct-regarding-Interest-Rate-Risk"><a href="#Which-of-the-following-is-not-correct-regarding-Interest-Rate-Risk" class="headerlink" title="Which of the following is not correct regarding Interest Rate Risk?"></a>Which of the following is not correct regarding Interest Rate Risk?</h3><ol>
<li>Changes in interest rates during the term of a bond may affect the market value of the bond prior to call or the maturity date.</li>
<li>Interest rate risk takes into account the eventuality that the issuer is not able to pay the coupon interest rate as defined in the prospectus.</li>
<li>There is generally an inverse relationship in between market interest rates and current bond prices.</li>
<li>As interest rates in the market increase, the market value (price) of existing bonds will tend to decrease.</li>
</ol>
<p>The statement “Interest rate risk takes into account the eventuality that the issuer is not able to pay the coupon interest rate as defined in the prospectus” is not correct for Interest Rate Risk. The possibility of the issuer not being able to pay the coupon rate is considered under Default Risk instead of Interest Rate Risk. Interest Rate Risk refers to the possibility that changes in interest rates during the term of a bond may affect the market value of the bond prior to call or the maturity date. Generally, there is an inverse relationship between market interest rates and current bond prices, meaning that as interest rates increase, the market value (price) of existing bonds will tend to decrease. Thus, statements 1, 3, and 4 are correct while statement 2 is incorrect. </p>
<h3 id="Which-of-the-following-is-correct-regarding-Inflation-Risk"><a href="#Which-of-the-following-is-correct-regarding-Inflation-Risk" class="headerlink" title="Which of the following is correct regarding Inflation Risk?"></a>Which of the following is correct regarding Inflation Risk?</h3><ol>
<li>Inflation risk is the risk that the rate of the yield to call or maturity of the bond will not provide a positive return over the rate of inflation for the period of the investment.</li>
<li>Inflation risk is the risk that the bond issuer is able to pay back to the investor only part of the face value of the bond at maturity.</li>
<li>Inflation risk is the risk that the bond issuer is not able to pay to the investor the bond coupons in a timely fashion.</li>
<li>As the inflation rate rises, the market price of existing bonds tends to increase.</li>
</ol>
<p>The correct answer is 1: Inflation risk is the risk that the rate of the yield to call or maturity of the bond will not provide a positive return over the rate of inflation for the period of the investment.</p>
<p>Option 2 describes credit risk, which is the risk that the bond issuer may default on payments.</p>
<p>Option 3 describes liquidity risk, which is the risk that the investor may not be able to sell the bond easily in the market or receive the coupon payments in a timely manner.</p>
<p>Option 4 is incorrect. As the inflation rate rises, the market price of existing bonds tends to decrease, because investors demand a higher yield to compensate for the loss of purchasing power caused by inflation.</p>
2023-04-01T03:36:09.000Zhttps://youngforest.github.io/en/2022/12/17/Windows-Dev-Improvement/Windows Development Environment improvement tips From a Microsoft Employee<h2 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h2><p>As a former Mac user, transitioning to Windows 11 was initially challenging for me. I found myself missing the ease of use and convenience of MacOS, and I struggled to adapt to the different development environment. However, with some effort and exploration, I discovered some tools and techniques that have helped me improve my experience as a developer in Windows. I know someone has to use Windows as his dev machine, like Microsoft employees. In this article, I want to share my experience and offer some tips and resources to help you enhance your Windows development environment, specifically with regards to shell improvements.</p>
<h2 id="Clink"><a href="#Clink" class="headerlink" title="Clink"></a>Clink</h2><p>Clink is a powerful tool that enhances the functionality of the Windows command prompt. It provides several features that can help you be more productive and efficient when working with the command line.</p>
<h3 id="How-to-install-and-set-up-Clink"><a href="#How-to-install-and-set-up-Clink" class="headerlink" title="How to install and set up Clink"></a>How to install and set up Clink</h3><h3 id="How-to-install-and-set-up-Clink-1"><a href="#How-to-install-and-set-up-Clink-1" class="headerlink" title="How to install and set up Clink"></a>How to install and set up Clink</h3><ol>
<li>Download the Clink installer from the <a href="https://mridgers.github.io/clink/">official website</a>.</li>
<li>Run the installer and follow the on-screen instructions to install Clink on your system.</li>
<li>Once the installation is complete, open the Windows command prompt.</li>
<li>Type <code>clink install</code> and press Enter to enable Clink in the command prompt. This will add Clink to your PATH environment variable and configure some default settings.</li>
<li>Restart your command prompt to apply the changes.</li>
</ol>
<p>You can customize Clink further by editing the configuration file <code>clink_inputrc.ini</code>, which is located in your user profile directory (e.g., <code>C:\Users\username</code>). The file contains various options that you can adjust to customize the behavior of Clink. For example, you can change the color scheme, add new keyboard shortcuts, and define aliases for commonly used commands.</p>
<p>Here’s an example of how to modify the color scheme in <code>clink_inputrc.ini</code>:</p>
<ol>
<li>Open <code>clink_inputrc.ini</code> in a text editor.</li>
<li>Locate the <code>[colors]</code> section.</li>
<li>Change the values of the color codes to your desired values. For example, to change the foreground color of directory listings to yellow, you can set <code>ls+di=33;1</code>.</li>
</ol>
<p>You can find more information about customizing Clink in <a href="https://mridgers.github.io/clink/">the official documentation</a>.</p>
<h3 id="Examples-of-using-Clink"><a href="#Examples-of-using-Clink" class="headerlink" title="Examples of using Clink"></a>Examples of using Clink</h3><p>Clink provides many useful features that can improve your command line experience on Windows. Here are some examples:</p>
<h4 id="1-Tab-completion"><a href="#1-Tab-completion" class="headerlink" title="1. Tab completion"></a>1. Tab completion</h4><p>Clink offers tab completion for commands, options, and file paths. To use tab completion, simply type the first few letters of a command or file path, then press the <code>Tab</code> key to complete it. If there are multiple options or file paths that match your input, you can press <code>Tab</code> repeatedly to cycle through them.</p>
<h4 id="2-Aliases"><a href="#2-Aliases" class="headerlink" title="2. Aliases"></a>2. Aliases</h4><p>You can define aliases for commonly used commands using Clink’s <code>alias</code> command. For example, if you frequently use <code>dir /w</code>, you can create an alias called <code>ls</code> that maps to this command. To create the alias, type the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">alias ls=dir /w</span><br></pre></td></tr></table></figure>
<p>Now, whenever you type <code>ls</code> in the command prompt, it will be replaced with <code>dir /w</code>.</p>
<h4 id="3-History-navigation"><a href="#3-History-navigation" class="headerlink" title="3. History navigation"></a>3. History navigation</h4><p>Clink allows you to navigate your command history using the up and down arrow keys. This is particularly useful if you need to repeat a command that you typed earlier.</p>
<h4 id="4-Customization"><a href="#4-Customization" class="headerlink" title="4. Customization"></a>4. Customization</h4><p>As mentioned earlier, you can customize Clink further by editing the configuration file <code>clink_inputrc.ini</code>. Here are some examples of customization options:</p>
<ul>
<li>Change the color scheme of the command prompt.</li>
<li>Define keyboard shortcuts for frequently used commands.</li>
<li>Set default options for certain commands.</li>
</ul>
<p>You can find more information about these and other customization options in the official Clink documentation.</p>
<h4 id="4-Navigating-directories"><a href="#4-Navigating-directories" class="headerlink" title="4. Navigating directories"></a>4. Navigating directories</h4><p>Clink provides several shortcuts for navigating directories. Here are some examples:</p>
<ul>
<li><code>cd..</code>: This takes you up one directory level.</li>
<li><code>cd\</code>: This takes you to the root directory.</li>
<li><code>cd.</code>: This changes the current directory to the current directory (in other words, it does nothing).</li>
<li><code>cd~</code>: This takes you to your home directory.</li>
</ul>
<h4 id="5-Copying-and-moving-files"><a href="#5-Copying-and-moving-files" class="headerlink" title="5. Copying and moving files"></a>5. Copying and moving files</h4><p>Clink provides aliases for commonly used file management commands. Here are some examples:</p>
<ul>
<li><code>cp</code>: This is an alias for the <code>copy</code> command. For example, to copy a file called <code>example.txt</code> from the current directory to a directory called <code>backup</code>, you can use the following command: <code>cp example.txt backup</code>.</li>
<li><code>mv</code>: This is an alias for the <code>move</code> command. For example, to move a file called <code>example.txt</code> from the current directory to a directory called <code>archive</code>, you can use the following command: <code>mv example.txt archive</code>.</li>
</ul>
<h4 id="6-Managing-processes"><a href="#6-Managing-processes" class="headerlink" title="6. Managing processes"></a>6. Managing processes</h4><p>Clink provides several commands for managing processes. Here are some examples:</p>
<ul>
<li><code>tasklist</code>: This displays a list of all running processes, along with their process ID (PID) and other information.</li>
<li><code>taskkill</code>: This terminates a process based on its PID or image name. For example, to terminate a process with the image name <code>notepad.exe</code>, you can use the following command: <code>taskkill /im notepad.exe</code>.</li>
</ul>
<p>By taking advantage of Clink’s features and aliases, you can navigate directories, copy and move files, and manage processes more easily and quickly. </p>
<p>Overall, Clink is a powerful tool that can greatly enhance your command line experience on Windows. By using its features and customizing it to your needs, you can work more efficiently and productively.</p>
<h3 id="Powershell"><a href="#Powershell" class="headerlink" title="Powershell"></a>Powershell</h3><p>Powershell is a more advanced command-line interface for Windows that provides a wide range of features and capabilities. It can help you perform complex tasks more efficiently and effectively.</p>
<h3 id="How-to-install-and-set-up-Powershell"><a href="#How-to-install-and-set-up-Powershell" class="headerlink" title="How to install and set up Powershell"></a>How to install and set up Powershell</h3><p>PowerShell is a powerful command-line interface for Windows that provides a more powerful and flexible environment than the traditional Command Prompt. Here’s how to install and set up PowerShell:</p>
<ol>
<li><p>Check your Windows version: PowerShell is included with Windows 7 SP1 and later versions. If you have an earlier version of Windows, you’ll need to install PowerShell Core.</p>
</li>
<li><p>Install PowerShell: If you don’t already have PowerShell installed, you can download it from the Microsoft website. Go to the <a href="https://github.com/PowerShell/PowerShell/releases">PowerShell downloads page</a> and download the version that matches your operating system.</p>
</li>
<li><p>Open PowerShell: Once you have PowerShell installed, you can open it by typing “powershell” into the Start menu or by pressing Windows key + X and selecting “Windows PowerShell” from the menu.</p>
</li>
<li><p>Customize your PowerShell profile: You can customize your PowerShell profile to add aliases, functions, and other customizations. To do this, open PowerShell and type <code>notepad $PROFILE</code> to open your profile file in Notepad. You can then add your customizations to this file and save it.</p>
</li>
<li><p>Install modules: PowerShell has a large library of modules that can be installed to add additional functionality. To install a module, use the <code>Install-Module</code> command. For example, to install the Azure PowerShell module, you can use the following command: <code>Install-Module -Name Az -AllowClobber</code>.</p>
</li>
</ol>
<p>By installing and customizing PowerShell, you can have a more powerful and flexible command-line environment on Windows.</p>
<h3 id="Examples-of-using-Powershell"><a href="#Examples-of-using-Powershell" class="headerlink" title="Examples of using Powershell"></a>Examples of using Powershell</h3><h3 id="Examples-of-how-Powershell-can-help-with-system-management-tasks"><a href="#Examples-of-how-Powershell-can-help-with-system-management-tasks" class="headerlink" title="Examples of how Powershell can help with system management tasks"></a>Examples of how Powershell can help with system management tasks</h3><p>PowerShell is a powerful tool for managing Windows systems. Here are a few examples of how PowerShell can help with system management tasks:</p>
<h4 id="Managing-Windows-services"><a href="#Managing-Windows-services" class="headerlink" title="Managing Windows services"></a>Managing Windows services</h4><p>Powershell can be used to manage Windows services. For example, to start the Print Spooler service, you can use the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Start-Service -Name Spooler</span><br></pre></td></tr></table></figure>
<p>To stop the service, you can use the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Stop-Service -Name Spooler</span><br></pre></td></tr></table></figure>
<h4 id="Configuring-network-settings"><a href="#Configuring-network-settings" class="headerlink" title="Configuring network settings"></a>Configuring network settings</h4><p>Powershell can also be used to configure network settings. For example, to set the IP address of a network adapter, you can use the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 192.168.1.100 -PrefixLength 24 -DefaultGateway 192.168.1.1</span><br></pre></td></tr></table></figure>
<p>This command sets the IP address of the “Ethernet” adapter to 192.168.1.100 with a subnet mask of 255.255.255.0 and a default gateway of 192.168.1.1.</p>
<h4 id="Performing-system-maintenance-tasks"><a href="#Performing-system-maintenance-tasks" class="headerlink" title="Performing system maintenance tasks"></a>Performing system maintenance tasks</h4><p>Powershell can also be used to perform various system maintenance tasks. For example, to check your system for disk errors, you can use the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Get-Volume | Get-Partition | Get-Disk | Repair-Volume -SpotFix</span><br></pre></td></tr></table></figure>
<p>This command checks all volumes, partitions, and disks for errors and attempts to fix them.</p>
<p>These are just a few examples of how PowerShell can be used to manage and maintain Windows systems. With PowerShell, the possibilities are endless!</p>
<h2 id="Winget"><a href="#Winget" class="headerlink" title="Winget"></a>Winget</h2><p><a href="https://learn.microsoft.com/en-us/windows/package-manager/winget/">Winget</a> is a package manager for Windows that allows you to easily install, manage, and update applications from the command line. It is similar to package managers like Homebrew on MacOS or apt on Ubuntu, and provides a simple and convenient way to manage software on your Windows system. With Winget, you can quickly install and update applications without having to search for and download installation files manually, making it a valuable tool for developers and power users on Windows.</p>
<h3 id="Examples-of-using-Winget"><a href="#Examples-of-using-Winget" class="headerlink" title="Examples of using Winget"></a>Examples of using Winget</h3><p>Winget makes it easy to install applications from the command line. Here are a few examples:</p>
<h4 id="Install-an-application"><a href="#Install-an-application" class="headerlink" title="Install an application"></a>Install an application</h4><p>To install an application, simply enter the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget install <application></span><br></pre></td></tr></table></figure>
<p>For example, to install Visual Studio Code, you would enter:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget install Microsoft.VisualStudioCode</span><br></pre></td></tr></table></figure>
<h4 id="List-installed-applications"><a href="#List-installed-applications" class="headerlink" title="List installed applications"></a>List installed applications</h4><p>To list the applications that are currently installed on your system, you can use the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget list</span><br></pre></td></tr></table></figure>
<h4 id="Search-for-an-application"><a href="#Search-for-an-application" class="headerlink" title="Search for an application"></a>Search for an application</h4><p>To search for an application, you can use the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget search <application></span><br></pre></td></tr></table></figure>
<p>For example, to search for Firefox, you would enter:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget search Firefox</span><br></pre></td></tr></table></figure>
<h4 id="Uninstall-an-application"><a href="#Uninstall-an-application" class="headerlink" title="Uninstall an application"></a>Uninstall an application</h4><p>To uninstall an application that was installed using Winget, you can use the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget uninstall <application></span><br></pre></td></tr></table></figure>
<p>For example, to uninstall Visual Studio Code, you would enter:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget uninstall Microsoft.VisualStudioCode</span><br></pre></td></tr></table></figure>
<p>These are just a few examples of how you can use Winget to install and manage applications on your Windows system. With Winget, you can easily install and update applications from the command line, making it a valuable tool for developers and power users alike.</p>
<h3 id="OhMyPosh"><a href="#OhMyPosh" class="headerlink" title="OhMyPosh"></a>OhMyPosh</h3><p>OhMyPosh is a tool that lets you customize your Powershell prompt. It allows you to create custom themes that can make your command-line interface more visually appealing and easier to use.</p>
<p><a href="https://ohmyposh.dev/docs/installation/windows">Install instructions</a></p>
<h2 id="Autojump"><a href="#Autojump" class="headerlink" title="Autojump"></a>Autojump</h2><p><a href="https://github.com/wting/autojump">Autojump</a> is a tool that helps you navigate your file system more efficiently. It remembers the directories you visit and lets you quickly jump back to them using a short command.</p>
<h3 id="Installing-Autojump"><a href="#Installing-Autojump" class="headerlink" title="Installing Autojump"></a>Installing Autojump</h3><p>Open a PowerShell terminal as an administrator.</p>
<p>Install Autojump by running the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget install autojump</span><br></pre></td></tr></table></figure>
<p>You can find your PowerShell profile by running the following command:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$PROFILE</span><br></pre></td></tr></table></figure>
<p>Restart your PowerShell terminal to apply the changes.</p>
<h3 id="Using-Autojump"><a href="#Using-Autojump" class="headerlink" title="Using Autojump"></a>Using Autojump</h3><p>Autojump is a command-line tool that allows you to navigate your file system more efficiently and quickly by remembering the directories you’ve visited and providing shortcuts to them.</p>
<h4 id="Jump-to-a-directory"><a href="#Jump-to-a-directory" class="headerlink" title="Jump to a directory"></a>Jump to a directory</h4><p>To jump to a directory that you’ve visited before, simply type j followed by a unique part of the directory name. For example:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">j documents</span><br></pre></td></tr></table></figure>
<p>This will jump to the directory that contains the word “documents” in its name.</p>
<h4 id="List-directories"><a href="#List-directories" class="headerlink" title="List directories"></a>List directories</h4><p>To see a list of the directories that Autojump remembers, type:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">j --stat</span><br></pre></td></tr></table></figure>
<p>This will display a list of the directories along with the number of times you’ve visited each one.</p>
<p>With Autojump, you can navigate your file system more efficiently and quickly, making your development experience on Windows more enjoyable and efficient.</p>
<h2 id="Z-lua-a-faster-equivalent-of-autojump"><a href="#Z-lua-a-faster-equivalent-of-autojump" class="headerlink" title="Z.lua, a faster equivalent of autojump"></a>Z.lua, a faster equivalent of autojump</h2><p><a href="https://github.com/skywind3000/z.lua">z.lua</a> is a faster equivalent of autojump. It is written in pure Lua and has no external dependencies. It is also faster than autojump. I use it more on Windows and PowerShell.</p>
<h2 id="Conclusion"><a href="#Conclusion" class="headerlink" title="Conclusion"></a>Conclusion</h2><p>In conclusion, Windows can be a great platform for development if you have the right tools and know how to use them. In this article, we have covered several tools that can help improve your Windows development experience, including Clink, PowerShell, OhMyPosh, Winget, and Autojump.</p>
<p>Clink and PowerShell provide a powerful shell experience that is comparable to what you get on other platforms. OhMyPosh allows you to customize your PowerShell prompt and make it more visually appealing. Winget is a package manager that makes it easy to install and manage software on Windows. Autojump provides a quick and efficient way to navigate your file system.</p>
<p>By using these tools and tips, you can enhance your development experience on Windows and work more efficiently. With the right setup, Windows can be just as powerful and enjoyable as other platforms for development.</p>
<h2 id="References"><a href="#References" class="headerlink" title="References"></a>References</h2><ul>
<li><a href="https://mridgers.github.io/clink/">https://mridgers.github.io/clink/</a></li>
<li><a href="https://github.com/wting/autojump">https://github.com/wting/autojump</a></li>
<li><a href="https://ohmyposh.dev/docs/installation/prompt">https://ohmyposh.dev/docs/installation/prompt</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/package-manager/winget/">https://learn.microsoft.com/en-us/windows/package-manager/winget/</a></li>
</ul>
2022-12-17T14:28:25.000Zhttps://youngforest.github.io/en/2022/03/19/Hennge-challenge-3/Hennge challenge 3<p>Last Sunday, I submitted my application for the Hennge Back-end(Tokyo, Japan) SDE position. After that, my mail box received a Challenge 3 email from Hennge. The challenge is very interesting. When I had enough free time on this Saturday, I finished this challenge finally. I spent about 3 hours on this. The process is here.</p>
<h2 id="Challenge-details"><a href="#Challenge-details" class="headerlink" title="Challenge details"></a>Challenge details</h2><p>The Challenge link is 403 after I submitted my solution. So, I share the process from my memory.<br>Fortunately, the archive is here: <a href="https://drive.google.com/file/d/1wWorFu889-DdEwuh9IAK2Eaei9rH1mGI/view?usp=sharing">Google Drive</a>.</p>
<p>First, implement a sum of squares of numbers program with Python/Go. You need to implement the input and output process by yourself.<br>Second, create a private github gist with the code.<br>Last, post the gist link to the Hennge server.</p>
<p>The code is very simple. I used Python to implement it.<br>Don’t ignore the instructions in the challenge.<br><strong>Specific rules for Python solution: Do not use any for loop, while loop, or any list / set / dictionary comprehension.</strong></p>
<p><a href="https://pyneng.readthedocs.io/en/latest/book/08_python_basic_examples/x_comprehensions.html">What is list/set/dictionary comprehension?</a><br>It is <code>[x for x in a_list]</code> in Python.</p>
<p>We can use <code>map</code> and <code>reduce</code> in Python to replace the iteration. It is functional programming.<br>If you are familiar with some functional programming languages, like Lisp, you could know that there is no loop syntax existing and the recursive function is the same as the iteration.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">```python</span><br><span class="line"></span><br><span class="line">```python</span><br><span class="line"><span class="keyword">from</span> functools <span class="keyword">import</span> reduce</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_non_negative_square_sum_from_input</span>():</span><br><span class="line"> X = <span class="built_in">int</span>(<span class="built_in">input</span>())</span><br><span class="line"> <span class="keyword">return</span> reduce(<span class="keyword">lambda</span> x, y: x + (y * y <span class="keyword">if</span> y > <span class="number">0</span> <span class="keyword">else</span> <span class="number">0</span>), <span class="built_in">map</span>(<span class="built_in">int</span>, <span class="built_in">input</span>().split()), <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line"> N = <span class="built_in">int</span>(<span class="built_in">input</span>())</span><br><span class="line"> ans = reduce(<span class="keyword">lambda</span> x, y: <span class="built_in">print</span>(get_non_negative_square_sum_from_input()), <span class="built_in">range</span>(N), [])</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure>
<p>After struggle with Github two-factor authentication and manual account recovery review, I finally sign in to Github and created <a href="https://gist.github.com/YoungForest/329c22200e7fad36e6ef984e3afe0325">my gist</a>, which is secret as required.</p>
<p>I think the hardest part is the authentication POST.</p>
<p>First, I needed to covert the shared secret to TOTP (Time-Based One-Time Password) with RFC 6238.<br>I tried to find a online tool to do that. But unfortunately, the current online tools have a limited options. For example, you can not choose the hash function as <code>HMAC-SHA-512</code> instead of default <code>HMAC-SHA-1</code>.<br>Therefore, as a result, I wrote a <a href="https://totp.youngforest.me/">TOTP Generator Online</a> by myself. Hope it could help you.<br>Fortunately, I found a sample Java implementation in <a href="https://datatracker.ietf.org/doc/html/rfc6238">the RFC 6238 document</a>. By the way, because the input in the code is a HEX string. I covert my shared secret <code>sen.yang96@outlook.comHENNGECHALLENGE003</code> to HEX string with <a href="https://www.convertstring.com/EncodeDecode/HexEncode">a online tool</a>. The challenge required a 10-digits code. The default in the code is 8-digits. I met this response using 8-digits.</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"message"</span><span class="punctuation">:</span> <span class="string">"Access denied: Invalid token, malformed token"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure>
<p>After I changed it to 10-digits, the error updated to:</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"message"</span><span class="punctuation">:</span> <span class="string">"Access denied: Invalid token, wrong code"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure>
<p>I debugged a lot and found that it is the issue of timestamp. Because TOTP is time-based.<br>When I change the timestamp to <code>Instant.now() + 30s</code>, the password passed:</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span><span class="attr">"message"</span><span class="punctuation">:</span><span class="string">"Congratulations! You have achieved mission 3"</span><span class="punctuation">}</span></span><br></pre></td></tr></table></figure>
<p>The final code after my changes is:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">Copyright (c) 2011 IETF Trust and the persons identified as</span></span><br><span class="line"><span class="comment">authors of the code. All rights reserved.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">Redistribution and use in source and binary forms, with or without</span></span><br><span class="line"><span class="comment">modification, is permitted pursuant to, and subject to the license</span></span><br><span class="line"><span class="comment">terms contained in, the Simplified BSD License set forth in Section</span></span><br><span class="line"><span class="comment">4.c of the IETF Trust's Legal Provisions Relating to IETF Documents</span></span><br><span class="line"><span class="comment">(http://trustee.ietf.org/license-info).</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.UndeclaredThrowableException;</span><br><span class="line"><span class="keyword">import</span> java.security.GeneralSecurityException;</span><br><span class="line"><span class="keyword">import</span> java.text.DateFormat;</span><br><span class="line"><span class="keyword">import</span> java.text.SimpleDateFormat;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="keyword">import</span> javax.crypto.Mac;</span><br><span class="line"><span class="keyword">import</span> javax.crypto.spec.SecretKeySpec;</span><br><span class="line"><span class="keyword">import</span> java.math.BigInteger;</span><br><span class="line"><span class="keyword">import</span> java.util.TimeZone;</span><br><span class="line"><span class="keyword">import</span> java.time.Instant;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This is an example implementation of the OATH</span></span><br><span class="line"><span class="comment"> * TOTP algorithm.</span></span><br><span class="line"><span class="comment"> * Visit www.openauthentication.org for more information.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Johan Rydell, PortWise, Inc.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TOTP</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="title function_">TOTP</span><span class="params">()</span> {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This method uses the JCE to provide the crypto algorithm.</span></span><br><span class="line"><span class="comment"> * HMAC computes a Hashed Message Authentication Code with the</span></span><br><span class="line"><span class="comment"> * crypto hash algorithm as a parameter.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> crypto: the crypto algorithm (HmacSHA1, HmacSHA256,</span></span><br><span class="line"><span class="comment"> * HmacSHA512)</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> keyBytes: the bytes to use for the HMAC key</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> text: the message or text to be authenticated</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">byte</span>[] hmac_sha(String crypto, <span class="type">byte</span>[] keyBytes,</span><br><span class="line"> <span class="type">byte</span>[] text) {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Mac hmac;</span><br><span class="line"> hmac = Mac.getInstance(crypto);</span><br><span class="line"> <span class="type">SecretKeySpec</span> <span class="variable">macKey</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SecretKeySpec</span>(keyBytes, <span class="string">"RAW"</span>);</span><br><span class="line"> hmac.init(macKey);</span><br><span class="line"> <span class="keyword">return</span> hmac.doFinal(text);</span><br><span class="line"> } <span class="keyword">catch</span> (GeneralSecurityException gse) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UndeclaredThrowableException</span>(gse);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This method converts a HEX string to Byte[]</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> hex: the HEX string</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span>: a byte array</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">byte</span>[] hexStr2Bytes(String hex) {</span><br><span class="line"> <span class="comment">// Adding one byte to get the right conversion</span></span><br><span class="line"> <span class="comment">// Values starting with "0" can be converted</span></span><br><span class="line"> <span class="type">byte</span>[] bArray = <span class="keyword">new</span> <span class="title class_">BigInteger</span>(<span class="string">"10"</span> + hex, <span class="number">16</span>).toByteArray();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Copy all the REAL bytes, not the "first"</span></span><br><span class="line"> <span class="type">byte</span>[] ret = <span class="keyword">new</span> <span class="title class_">byte</span>[bArray.length - <span class="number">1</span>];</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < ret.length; i++)</span><br><span class="line"> ret[i] = bArray[i + <span class="number">1</span>];</span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span>[] DIGITS_POWER</span><br><span class="line"> <span class="comment">// 0 1 2 3 4 5 6 7 8 9 10</span></span><br><span class="line"> = { <span class="number">1</span>, <span class="number">10</span>, <span class="number">100</span>, <span class="number">1000</span>, <span class="number">10000</span>, <span class="number">100000</span>, <span class="number">1000000</span>, <span class="number">10000000</span>, <span class="number">100000000</span>, <span class="number">1000000000</span>, <span class="number">1000000000</span> };</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This method generates a TOTP value for the given</span></span><br><span class="line"><span class="comment"> * set of parameters.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> key: the shared secret, HEX encoded</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> time: a value that reflects a time</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> returnDigits: number of digits to return</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span>: a numeric String in base 10 that includes</span></span><br><span class="line"><span class="comment"> * {<span class="doctag">@link</span> truncationDigits} digits</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">generateTOTP</span><span class="params">(String key,</span></span><br><span class="line"><span class="params"> String time,</span></span><br><span class="line"><span class="params"> String returnDigits)</span> {</span><br><span class="line"> <span class="keyword">return</span> generateTOTP(key, time, returnDigits, <span class="string">"HmacSHA1"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This method generates a TOTP value for the given</span></span><br><span class="line"><span class="comment"> * set of parameters.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> key: the shared secret, HEX encoded</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> time: a value that reflects a time</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> returnDigits: number of digits to return</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span>: a numeric String in base 10 that includes</span></span><br><span class="line"><span class="comment"> * {<span class="doctag">@link</span> truncationDigits} digits</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">generateTOTP256</span><span class="params">(String key,</span></span><br><span class="line"><span class="params"> String time,</span></span><br><span class="line"><span class="params"> String returnDigits)</span> {</span><br><span class="line"> <span class="keyword">return</span> generateTOTP(key, time, returnDigits, <span class="string">"HmacSHA256"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This method generates a TOTP value for the given</span></span><br><span class="line"><span class="comment"> * set of parameters.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> key: the shared secret, HEX encoded</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> time: a value that reflects a time</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> returnDigits: number of digits to return</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span>: a numeric String in base 10 that includes</span></span><br><span class="line"><span class="comment"> * {<span class="doctag">@link</span> truncationDigits} digits</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">generateTOTP512</span><span class="params">(String key,</span></span><br><span class="line"><span class="params"> String time,</span></span><br><span class="line"><span class="params"> String returnDigits)</span> {</span><br><span class="line"> <span class="keyword">return</span> generateTOTP(key, time, returnDigits, <span class="string">"HmacSHA512"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This method generates a TOTP value for the given</span></span><br><span class="line"><span class="comment"> * set of parameters.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> key: the shared secret, HEX encoded</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> time: a value that reflects a time</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> returnDigits: number of digits to return</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> crypto: the crypto function to use</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span>: a numeric String in base 10 that includes</span></span><br><span class="line"><span class="comment"> * {<span class="doctag">@link</span> truncationDigits} digits</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">generateTOTP</span><span class="params">(String key,</span></span><br><span class="line"><span class="params"> String time,</span></span><br><span class="line"><span class="params"> String returnDigits,</span></span><br><span class="line"><span class="params"> String crypto)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">codeDigits</span> <span class="operator">=</span> Integer.decode(returnDigits).intValue();</span><br><span class="line"> <span class="type">String</span> <span class="variable">result</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Using the counter</span></span><br><span class="line"> <span class="comment">// First 8 bytes are for the movingFactor</span></span><br><span class="line"> <span class="comment">// Compliant with base RFC 4226 (HOTP)</span></span><br><span class="line"> <span class="keyword">while</span> (time.length() < <span class="number">16</span>)</span><br><span class="line"> time = <span class="string">"0"</span> + time;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Get the HEX in a Byte[]</span></span><br><span class="line"> <span class="type">byte</span>[] msg = hexStr2Bytes(time);</span><br><span class="line"> <span class="type">byte</span>[] k = hexStr2Bytes(key);</span><br><span class="line"> <span class="type">byte</span>[] hash = hmac_sha(crypto, k, msg);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// put selected bytes into result int</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">offset</span> <span class="operator">=</span> hash[hash.length - <span class="number">1</span>] & <span class="number">0xf</span>;</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> <span class="variable">binary</span> <span class="operator">=</span> ((hash[offset] & <span class="number">0x7f</span>) << <span class="number">24</span>) |</span><br><span class="line"> ((hash[offset + <span class="number">1</span>] & <span class="number">0xff</span>) << <span class="number">16</span>) |</span><br><span class="line"> ((hash[offset + <span class="number">2</span>] & <span class="number">0xff</span>) << <span class="number">8</span>) |</span><br><span class="line"> (hash[offset + <span class="number">3</span>] & <span class="number">0xff</span>);</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> <span class="variable">otp</span> <span class="operator">=</span> binary % DIGITS_POWER[codeDigits];</span><br><span class="line"></span><br><span class="line"> result = Integer.toString(otp);</span><br><span class="line"> <span class="keyword">while</span> (result.length() < codeDigits) {</span><br><span class="line"> result = <span class="string">"0"</span> + result;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="comment">// Seed for HMAC-SHA1 - 20 bytes</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">seed</span> <span class="operator">=</span> <span class="string">"3132333435363738393031323334353637383930"</span>;</span><br><span class="line"> <span class="comment">// Seed for HMAC-SHA256 - 32 bytes</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">seed32</span> <span class="operator">=</span> <span class="string">"3132333435363738393031323334353637383930"</span> +</span><br><span class="line"> <span class="string">"313233343536373839303132"</span>;</span><br><span class="line"> <span class="comment">// Seed for HMAC-SHA512 - 64 bytes</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">seed64</span> <span class="operator">=</span> <span class="string">"73656E2E79616E673936406F75746C6F6F6B2E636F6D48454E4E47454348414C4C454E4745303033"</span>;</span><br><span class="line"> <span class="comment">// "3132333435363738393031323334353637383930" +</span></span><br><span class="line"> <span class="comment">// "3132333435363738393031323334353637383930" +</span></span><br><span class="line"> <span class="comment">// "3132333435363738393031323334353637383930" +</span></span><br><span class="line"> <span class="comment">// "31323334";</span></span><br><span class="line"> <span class="type">long</span> <span class="variable">T0</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="type">long</span> <span class="variable">X</span> <span class="operator">=</span> <span class="number">30</span>;</span><br><span class="line"> <span class="type">long</span> testTime[] = { Instant.now().toEpochMilli() / <span class="number">1000L</span> + <span class="number">30</span> }; <span class="comment">// { 30L, 59L, 1111111109L, 1111111111L,</span></span><br><span class="line"> <span class="comment">// 1234567890L, 2000000000L, 20000000000L };</span></span><br><span class="line"></span><br><span class="line"> <span class="type">String</span> <span class="variable">steps</span> <span class="operator">=</span> <span class="string">"0"</span>;</span><br><span class="line"> <span class="type">DateFormat</span> <span class="variable">df</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SimpleDateFormat</span>(<span class="string">"yyyy-MM-dd HH:mm:ss"</span>);</span><br><span class="line"> df.setTimeZone(TimeZone.getTimeZone(<span class="string">"UTC"</span>));</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> System.out.println(</span><br><span class="line"> <span class="string">"+---------------+-----------------------+"</span> +</span><br><span class="line"> <span class="string">"------------------+--------+--------+"</span>);</span><br><span class="line"> System.out.println(</span><br><span class="line"> <span class="string">"| Time(sec) | Time (UTC format) "</span> +</span><br><span class="line"> <span class="string">"| Value of T(Hex) | TOTP | Mode |"</span>);</span><br><span class="line"> System.out.println(</span><br><span class="line"> <span class="string">"+---------------+-----------------------+"</span> +</span><br><span class="line"> <span class="string">"------------------+--------+--------+"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i < testTime.length; i++) {</span><br><span class="line"> <span class="type">long</span> <span class="variable">T</span> <span class="operator">=</span> (testTime[i] - T0) / X;</span><br><span class="line"> steps = Long.toHexString(T).toUpperCase();</span><br><span class="line"> <span class="keyword">while</span> (steps.length() < <span class="number">16</span>)</span><br><span class="line"> steps = <span class="string">"0"</span> + steps;</span><br><span class="line"> <span class="type">String</span> <span class="variable">fmtTime</span> <span class="operator">=</span> String.format(<span class="string">"%1$-11s"</span>, testTime[i]);</span><br><span class="line"> <span class="type">String</span> <span class="variable">utcTime</span> <span class="operator">=</span> df.format(<span class="keyword">new</span> <span class="title class_">Date</span>(testTime[i] * <span class="number">1000</span>));</span><br><span class="line"> System.out.print(<span class="string">"| "</span> + fmtTime + <span class="string">" | "</span> + utcTime +</span><br><span class="line"> <span class="string">" | "</span> + steps + <span class="string">" |"</span>);</span><br><span class="line"> System.out.println(generateTOTP(seed, steps, <span class="string">"8"</span>,</span><br><span class="line"> <span class="string">"HmacSHA1"</span>) + <span class="string">"| SHA1 |"</span>);</span><br><span class="line"> System.out.print(<span class="string">"| "</span> + fmtTime + <span class="string">" | "</span> + utcTime +</span><br><span class="line"> <span class="string">" | "</span> + steps + <span class="string">" |"</span>);</span><br><span class="line"> System.out.println(generateTOTP(seed32, steps, <span class="string">"8"</span>,</span><br><span class="line"> <span class="string">"HmacSHA256"</span>) + <span class="string">"| SHA256 |"</span>);</span><br><span class="line"> System.out.print(<span class="string">"| "</span> + fmtTime + <span class="string">" | "</span> + utcTime +</span><br><span class="line"> <span class="string">" | "</span> + steps + <span class="string">" |"</span>);</span><br><span class="line"> System.out.println(generateTOTP(seed64, steps, <span class="string">"10"</span>,</span><br><span class="line"> <span class="string">"HmacSHA512"</span>) + <span class="string">"| SHA512 |"</span>);</span><br><span class="line"></span><br><span class="line"> System.out.println(</span><br><span class="line"> <span class="string">"+---------------+-----------------------+"</span> +</span><br><span class="line"> <span class="string">"------------------+--------+--------+"</span>);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (<span class="keyword">final</span> Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Second, I should send my post with <a href="https://datatracker.ietf.org/doc/html/rfc2617#section-2">HTTP Basic Authentication (RFC 2617)</a>.<br>The use-id is my email and password is the TOTP code. With the help of <a href="https://stackoverflow.com/questions/20803339/basic-authorization-command-for-curl">this StackOverflow question: basic authorization command for curl</a>, there is 2 options to do this.</p>
<ol>
<li>Manually get Base64 encoded string and send it.</li>
</ol>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">I tested on a Mac OS.</span></span><br><span class="line">echo -ne "sen.yang96@outlook.com:<TOTP 10 digits code>" | base64</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">output is something like this: c2VuLnlhbmc5NkBvdXRsb29rLmNvbTo4MzUzMDkyMA==</span></span><br><span class="line">curl -d '{ "github_url": "https://gist.github.com/YoungForest/329c22200e7fad36e6ef984e3afe0325", "contact_email": "sen.yang96@outlook.com", "solution_language": "python"}' -H 'Content-Type: application/json' -H 'Authorization: Basic <Base64 string>' https://api.challenge.hennge.com/challenges/003</span><br></pre></td></tr></table></figure>
<ol start="2">
<li>CURL could help you do the Base64 encoding.<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -d '{ "github_url": "https://gist.github.com/YoungForest/329c22200e7fad36e6ef984e3afe0325", "contact_email": "sen.yang96@outlook.com", "solution_language": "python"}' -H 'Content-Type: application/json' -u sen.yang96@outlook.com:<TOTP 10 digits code> https://api.challenge.hennge.com/challenges/003</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h2 id="Follow-up"><a href="#Follow-up" class="headerlink" title="Follow up"></a>Follow up</h2><p>After the congratulations response, I received a link by email to submit my Resume and CV.<br>It was my first time to do the challenge in a job application. I had done some homeworks/assignments and OA tests before. This challenge is so different and interesting. Through it, I learned a lot about TOTP and HTTP authentication.</p>
<p>Unfortunately, the final result is not good. I didn’t get any interview. I knew a few people who applied <strong>Hennge</strong> too because of this article. No one gets interviews and further progress after this challenge. If you complete the challenge and don’t get good response, it’s not your fault. Hennge seems just don’t hire candidates through the challenge.</p>
<blockquote>
<p>Thank you for your interest in Back-End Engineer position at HENNGE and for taking the time to complete the test.</p>
<p>While we were impressed with your background and experience, the selection process was highly competitive and unfortunately we have decided to move forward with another candidate that better fits our requirements at the moment.</p>
<p>Please understand that HENNGE does not provide specific details on the results of the application process.</p>
<p>We wish you the best of luck in your future endeavors.</p>
<p>Best regards,<br>HENNGE Recruiting Team</p>
</blockquote>
2022-03-19T05:17:20.000Zhttps://youngforest.github.io/en/2021/12/18/Migrate-from-Travis-CI-to-Github-Action/Migrate from Travis CI to Github Action<p>Two months ago, I configured Travis CI to automatically deploy my blog in<br><a href="https://youngforest.github.io/en/2021/10/09/Travis-CI-Hexo-Automatically-Deploy/">Travis CI Hexo Automatically Deploy</a>.<br>However, I found it do not work this month. Unfortunately, Travis do not support free build for public repos now. I have to migrate to Github Action in order to auto CD.</p>
<p>I followed <a href="https://sanonz.github.io/2020/deploy-a-hexo-blog-from-github-actions/">this post</a> to do that. Some changes should be applied in <code>deploy.yml</code> file, especially <strong>theme</strong>.<br>For example, <a href="https://github.com/YoungForest/Hexo/blob/master/.github/workflows/deploy.yml">my Chinese blog <code>deploy.yml</code></a> and <a href="https://github.com/YoungForest/en/blob/master/.github/workflows/deploy.yml">my English blog <code>deploy.yml</code></a>.</p>
<p>Close auto build in <a href="https://app.travis-ci.com/">Travis CI Dashboard</a>: Your repos -> Setting -> General -> uncheck <strong>Build pushed branches</strong> and <strong>Build pushed pull requests</strong>.</p>
2021-12-18T02:47:17.000Zhttps://youngforest.github.io/en/2021/10/24/LeetCode-weekly-contest-264/LeetCode weekly contest 264<table>
<thead>
<tr>
<th>Rank</th>
<th>Name</th>
<th>Score</th>
<th>Finish Time</th>
<th>Q1 (3)</th>
<th>Q2 (4)</th>
<th>Q3 (5)</th>
<th>Q4 (6)</th>
</tr>
</thead>
<tbody><tr>
<td>323 / 12700</td>
<td>YoungForest</td>
<td>18</td>
<td>1:00:46</td>
<td>0:11:32 🐞1</td>
<td>0:27:23</td>
<td>0:42:54 🐞1</td>
<td>0:50:46</td>
</tr>
</tbody></table>
<p>After 6 weeks of cruel daily check in, I am finally free from solve the daily problem everyday in cruel group. The condition of free is that the contest rank is within top 500 in the world and solving all 4 problems in weekly contest. Congratulations on me.</p>
<h2 id="2047-Number-of-Valid-Words-in-a-Sentence"><a href="#2047-Number-of-Valid-Words-in-a-Sentence" class="headerlink" title="2047. Number of Valid Words in a Sentence"></a>2047. Number of Valid Words in a Sentence</h2><p>Sign on problem.<br>It is more difficult than usual. The corner case needs to be careful of. For example, ‘-‘ is not a valid word.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">countValidWords</span>(<span class="params">self, sentence: <span class="built_in">str</span></span>) -> <span class="built_in">int</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">isPunctuation</span>(<span class="params">c</span>):</span><br><span class="line"> <span class="keyword">return</span> c == <span class="string">'!'</span> <span class="keyword">or</span> c == <span class="string">'.'</span> <span class="keyword">or</span> c == <span class="string">','</span></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">isLower</span>(<span class="params">c</span>):</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">ord</span>(c) >= <span class="built_in">ord</span>(<span class="string">'a'</span>) <span class="keyword">and</span> <span class="built_in">ord</span>(c) <= <span class="built_in">ord</span>(<span class="string">'z'</span>)</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">check</span>(<span class="params">word</span>):</span><br><span class="line"> <span class="comment"># It only contains lowercase letters, hyphens, and/or punctuation (no digits).</span></span><br><span class="line"> <span class="comment"># There is at most one hyphen '-'. If present, it should be surrounded by lowercase characters ("a-b" is valid, but "-ab" and "ab-" are not valid).</span></span><br><span class="line"> <span class="comment"># There is at most one punctuation mark. If present, it should be at the end of the token.</span></span><br><span class="line"> hyphenCount = <span class="number">0</span></span><br><span class="line"> punctuationCount = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> c <span class="keyword">in</span> word:</span><br><span class="line"> <span class="keyword">if</span> c == <span class="string">'-'</span>:</span><br><span class="line"> hyphenCount += <span class="number">1</span></span><br><span class="line"> <span class="keyword">if</span> c.isdigit():</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"> <span class="keyword">if</span> isPunctuation(c):</span><br><span class="line"> punctuationCount += <span class="number">1</span></span><br><span class="line"> <span class="keyword">if</span> hyphenCount > <span class="number">1</span> <span class="keyword">or</span> punctuationCount > <span class="number">1</span>: <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"> <span class="keyword">if</span> punctuationCount == <span class="number">1</span> <span class="keyword">and</span> <span class="keyword">not</span> isPunctuation(word[-<span class="number">1</span>]): <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"> <span class="keyword">if</span> hyphenCount == <span class="number">1</span>:</span><br><span class="line"> l = word.split(<span class="string">'-'</span>)</span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">len</span>(l) != <span class="number">2</span>: <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> (<span class="built_in">len</span>(l[<span class="number">0</span>]) >= <span class="number">1</span> <span class="keyword">and</span> isLower(l[<span class="number">0</span>][-<span class="number">1</span>])) <span class="keyword">or</span> <span class="keyword">not</span> (<span class="built_in">len</span>(l[<span class="number">1</span>]) >= <span class="number">1</span> <span class="keyword">and</span> isLower(l[<span class="number">1</span>][<span class="number">0</span>])): <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line"> ans = <span class="number">0</span></span><br><span class="line"> words = sentence.split()</span><br><span class="line"> <span class="keyword">for</span> word <span class="keyword">in</span> words:</span><br><span class="line"> <span class="comment"># print (word)</span></span><br><span class="line"> <span class="keyword">if</span> check(word):</span><br><span class="line"> <span class="comment"># print('Yes')</span></span><br><span class="line"> ans += <span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> ans</span><br></pre></td></tr></table></figure>
<p>Time complexity: O(N),<br>Space complexity: O(N).</p>
<p>A easier solution is <code>re</code>, aka regular expression.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">countValidWords</span>(<span class="params">self, sentence: <span class="built_in">str</span></span>) -> <span class="built_in">int</span>:</span><br><span class="line"> pattern = re.<span class="built_in">compile</span>(<span class="string">'(^[a-z]+(-[a-z]+)?)?[,.!]?$'</span>)</span><br><span class="line"> word_count = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> word <span class="keyword">in</span> sentence.split():</span><br><span class="line"> <span class="keyword">if</span> pattern.<span class="keyword">match</span>(word):</span><br><span class="line"> word_count = word_count + <span class="number">1</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> word_count</span><br></pre></td></tr></table></figure>
<p>Time complexity: O(N),<br>Space complexity: O(N).</p>
<h2 id="2048-Next-Greater-Numerically-Balanced-Number"><a href="#2048-Next-Greater-Numerically-Balanced-Number" class="headerlink" title="2048. Next Greater Numerically Balanced Number"></a>2048. Next Greater Numerically Balanced Number</h2><p>Many people’s solutions are “Accepted” using brute force. Iterate every number greater than n, and check if it is numerically balanced.<br>I proposed a better solution in contest. Because of <code>0 <= n <= 10^6</code>, I manually enumerate all numerically balanced numbers and find the next greater one. The possible balance numbers is countable. One trick here is using <code>permutations</code> to iterate all permutations of a string.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">nextBeautifulNumber</span>(<span class="params">self, n: <span class="built_in">int</span></span>) -> <span class="built_in">int</span>:</span><br><span class="line"> <span class="comment"># 1digit: 1</span></span><br><span class="line"> <span class="comment"># 2digit: 22</span></span><br><span class="line"> <span class="comment"># 3digit: 333 or 1+2</span></span><br><span class="line"> <span class="comment"># 4digit: 1+3 or 4</span></span><br><span class="line"> <span class="comment"># 5digit: 5 or 1+4 or 2+3</span></span><br><span class="line"> <span class="comment"># 6digit: 6 or 1+5 or 2+4 or 1+2+3</span></span><br><span class="line"> <span class="comment"># 7digit: 7 or 1+6 or 1+2+4 1224444</span></span><br><span class="line"> <span class="keyword">if</span> n == <span class="number">10</span>**<span class="number">6</span>: <span class="keyword">return</span> <span class="number">1224444</span></span><br><span class="line"> ans = <span class="number">1224444</span></span><br><span class="line"> s = <span class="built_in">str</span>(n)</span><br><span class="line"> <span class="comment"># 6! 720</span></span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">check</span>(<span class="params">l</span>):</span><br><span class="line"> ans = <span class="built_in">float</span>(<span class="string">'inf'</span>)</span><br><span class="line"> origin = <span class="string">''</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> l:</span><br><span class="line"> origin += <span class="built_in">str</span>(i) * i</span><br><span class="line"> perms = [<span class="string">''</span>.join(p) <span class="keyword">for</span> p <span class="keyword">in</span> permutations(origin)]</span><br><span class="line"> <span class="keyword">for</span> s <span class="keyword">in</span> perms:</span><br><span class="line"> i = <span class="built_in">int</span>(s)</span><br><span class="line"> <span class="keyword">if</span> i > n:</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, i)</span><br><span class="line"> <span class="keyword">return</span> ans</span><br><span class="line"> </span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">6</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">1</span>, <span class="number">5</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">2</span>, <span class="number">4</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">5</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">1</span>, <span class="number">4</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">2</span>, <span class="number">3</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">4</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">1</span>, <span class="number">3</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">3</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">1</span>, <span class="number">2</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">2</span>]))</span><br><span class="line"> ans = <span class="built_in">min</span>(ans, check([<span class="number">1</span>]))</span><br><span class="line"> <span class="keyword">return</span> ans</span><br></pre></td></tr></table></figure>
<p>Time complexity: O(13 * 6!),<br>Space complexity: O(6!).</p>
<h2 id="2049-Count-Nodes-With-the-Highest-Score"><a href="#2049-Count-Nodes-With-the-Highest-Score" class="headerlink" title="2049. Count Nodes With the Highest Score"></a>2049. Count Nodes With the Highest Score</h2><ol>
<li>We could use <code>DFS</code> to calculate every subtrees’ size. </li>
<li>Calculate the score of each node. 3 possible states when deleting a node: two children, one child, no child. A corner case is the root node. It do not have the parent.</li>
<li>Find the highest score and its frequency.</li>
</ol>
<p>A corner case is that the products could overflow <code>int</code>. It is <code>10^5 * 10^5</code> maximally. <code>long long</code> could avoid this runtime error easily.</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T></span><br><span class="line">ostream& <span class="keyword">operator</span> <<(ostream& out, <span class="type">const</span> vector<T>& a) {</span><br><span class="line"> out << <span class="string">"["</span>; <span class="type">bool</span> first = <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span>& v : a) { out << (first ? <span class="string">""</span> : <span class="string">", "</span>); out << v; first = <span class="number">0</span>;} out << <span class="string">"]"</span>;</span><br><span class="line"> <span class="keyword">return</span> out;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">using</span> ll = <span class="type">long</span> <span class="type">long</span>;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">countHighestScoreNodes</span><span class="params">(vector<<span class="type">int</span>>& parents)</span> </span>{</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> n = parents.<span class="built_in">size</span>();</span><br><span class="line"> vector<vector<<span class="type">int</span>>> <span class="built_in">children</span>(n);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i < n; ++i) {</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> parent = parents[i];</span><br><span class="line"> children[parent].<span class="built_in">push_back</span>(i);</span><br><span class="line"> }</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> root = <span class="number">0</span>;</span><br><span class="line"> vector<vector<ll>> <span class="built_in">subtreeSize</span>(n);</span><br><span class="line"> function<ll(<span class="type">const</span> <span class="type">int</span>)> dfs = [&](<span class="type">const</span> <span class="type">int</span> root) -> ll {</span><br><span class="line"> ll ans = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> child : children[root]) {</span><br><span class="line"> <span class="type">const</span> ll childSize = <span class="built_in">dfs</span>(child);</span><br><span class="line"> subtreeSize[root].<span class="built_in">push_back</span>(childSize);</span><br><span class="line"> ans += childSize;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> };</span><br><span class="line"> <span class="type">const</span> ll totalSize = <span class="built_in">dfs</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="function">vector<ll> <span class="title">scores</span><span class="params">(n)</span></span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < n; ++i) {</span><br><span class="line"> <span class="keyword">if</span> (children[i].<span class="built_in">size</span>() == <span class="number">0</span>) {</span><br><span class="line"> scores[i] = totalSize - <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (children[i].<span class="built_in">size</span>() == <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span> (totalSize - <span class="number">1</span> == subtreeSize[i][<span class="number">0</span>]) {</span><br><span class="line"> scores[i] = subtreeSize[i][<span class="number">0</span>];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> scores[i] = subtreeSize[i][<span class="number">0</span>] * (totalSize - <span class="number">1</span> - subtreeSize[i][<span class="number">0</span>]);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (totalSize - <span class="number">1</span> - subtreeSize[i][<span class="number">0</span>] - subtreeSize[i][<span class="number">1</span>] == <span class="number">0</span>) {</span><br><span class="line"> scores[i] = subtreeSize[i][<span class="number">0</span>] * subtreeSize[i][<span class="number">1</span>];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> scores[i] = subtreeSize[i][<span class="number">0</span>] * subtreeSize[i][<span class="number">1</span>] * (totalSize - <span class="number">1</span> - subtreeSize[i][<span class="number">0</span>] - subtreeSize[i][<span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// cout << scores << endl;</span></span><br><span class="line"> <span class="type">const</span> ll highestScore = *<span class="built_in">max_element</span>(scores.<span class="built_in">begin</span>(), scores.<span class="built_in">end</span>());</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">count</span>(scores.<span class="built_in">begin</span>(), scores.<span class="built_in">end</span>(), highestScore);</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>Time complexity: O(n),<br>Space complexity: O(n).</p>
<h2 id="2050-Parallel-Courses-III"><a href="#2050-Parallel-Courses-III" class="headerlink" title="2050. Parallel Courses III"></a>2050. Parallel Courses III</h2><p>Typical topo sort.<br>With <code>priority_queue</code>, we could iterate every course end events from time increasing.</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">minimumTime</span><span class="params">(<span class="type">int</span> n, vector<vector<<span class="type">int</span>>>& relations, vector<<span class="type">int</span>>& time)</span> </span>{</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">indegree</span><span class="params">(n, <span class="number">0</span>)</span></span>;</span><br><span class="line"> vector<vector<<span class="type">int</span>>> <span class="built_in">out</span>(n);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">const</span> <span class="keyword">auto</span>& r : relations) {</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> p = r[<span class="number">0</span>] - <span class="number">1</span>;</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> n = r[<span class="number">1</span>] - <span class="number">1</span>;</span><br><span class="line"> indegree[n]++;</span><br><span class="line"> out[p].<span class="built_in">push_back</span>(n);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">using</span> pii = pair<<span class="type">int</span>, <span class="type">int</span>>; <span class="comment">// end time, course number</span></span><br><span class="line"> priority_queue<pii, vector<pii>, greater<>> events;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < n; ++i) {</span><br><span class="line"> <span class="keyword">if</span> (indegree[i] == <span class="number">0</span>) {</span><br><span class="line"> events.<span class="built_in">push</span>({time[i], i});</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (!events.<span class="built_in">empty</span>()) {</span><br><span class="line"> <span class="keyword">auto</span> [currentTime, courseNumber] = events.<span class="built_in">top</span>();</span><br><span class="line"> ans = currentTime;</span><br><span class="line"> events.<span class="built_in">pop</span>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> to : out[courseNumber]) {</span><br><span class="line"> indegree[to]--;</span><br><span class="line"> <span class="keyword">if</span> (indegree[to] == <span class="number">0</span>) {</span><br><span class="line"> events.<span class="built_in">push</span>({currentTime + time[to], to});</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>Time complexity: O(N * logN),<br>Space complexity: O(N).</p>
2021-10-24T09:20:15.000Zhttps://youngforest.github.io/en/2021/10/09/Travis-CI-Hexo-Automatically-Deploy/Travis CI + Hexo Automatically Deploy<p><a href="https://hexo.io/docs/">Hexo</a> is a powerful blog engine. It is a good choice for a personal blog. I have used it for 5 years. Recently, I setup <a href="https://youngforest.github.io/en">my English site</a> besides <a href="https://youngforest.github.io/">the original Chinese site</a>. With 2 sites, it is more work to write, git and deploy.<br>Fortunately, there is a better solution for this problem. We could use <a href="https://travis-ci.com/">Travis CI</a> to automatically deploy the blog. The remain work is writing posts and git commit and push them. The CI would help us to deploy sites automatically.</p>
<span id="more"></span>
<h2 id="How-to-configure-that"><a href="#How-to-configure-that" class="headerlink" title="How to configure that?"></a>How to configure that?</h2><p><a href="https://education.travis-ci.com/">Sign up for Travis CI using Github account</a>.</p>
<p>With <a href="https://education.github.com/pack/offers">Github education package</a>, you could have the benefit to private builds for free while you’re a student. But it is only an optional choice, you can still use Travis CI without it.</p>
<p><a href="https://app.travis-ci.com/account/repositories">Give Travis CI the permission to access your Github repositories</a>.</p>
<p>In <a href="https://github.com/settings/tokens">Personal access tokens</a>, generate a token for Travis CI with <code>repo</code> scopes. Copy the token.</p>
<p>In <a href="https://app.travis-ci.com/account/repositories">Travis CI repositories page</a>, select your <strong>Hexo</strong> repo and click on <strong>Settings</strong>. In <strong>Environment Variables</strong> section, <strong>Add</strong> a new variable with <strong>NAME</strong> is <code>GH_TOKEN</code>, <strong>VALUE</strong> is the token you copied in the last step.</p>
<p>Create a file named <code>.travis.yml</code> in your Hexo repo. Refer to following content and change the value as your situation. I added some comments for help.</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">os: linux</span><br><span class="line">language: node_js </span><br><span class="line">node_js:</span><br><span class="line"> - 12 # using nodejs LTS v12</span><br><span class="line">branches:</span><br><span class="line"> only:</span><br><span class="line"> - master # only monitor master branch</span><br><span class="line">cache:</span><br><span class="line"> directories:</span><br><span class="line"> - node_modules # cache node_modules to speed up build process</span><br><span class="line">before_script: ## According to your theme and custom configuration, update the script</span><br><span class="line"> - npm install -g hexo-cli # install Hexo in CI environment</span><br><span class="line"> - cd themes </span><br><span class="line"> - git clone https://github.com/next-theme/hexo-theme-next.git next # We do not commit the themes/next folder. Therefore, pull it every time.</span><br><span class="line"> - cd next</span><br><span class="line"> - npm install # install next dependencies</span><br><span class="line"> - cd ../.. # return the root folder</span><br><span class="line"> - npm install # install the dependencies</span><br><span class="line">script: </span><br><span class="line"> - hexo generate # generate static files</span><br><span class="line">deploy: # reference: https://docs.travis-ci.com/user/deployment/pages/</span><br><span class="line"> provider: pages</span><br><span class="line"> skip_cleanup: true # not clean after build</span><br><span class="line"> token: $GH_TOKEN # the variable you set in last step</span><br><span class="line"> keep_history: true</span><br><span class="line"> # fqdn: blog.ne0ng.page # custom domain,delete this field if using username.github.io</span><br><span class="line"> repo: YoungForest/youngforest.github.io # the repo you want to deploy. If this field is not set manually, the default value is current repo. Sometimes, the site repo is the same with the source files but in different branches.</span><br><span class="line"> on:</span><br><span class="line"> branch: master # sources files is in master branch</span><br><span class="line"> local_dir: public </span><br><span class="line"> target_branch: master # the branch of generated files. If using `username.github.io` repo, it has to be master. Otherwise, change it to your github pages branch.</span><br></pre></td></tr></table></figure>
<p>Once you push the <code>.travis.yml</code> file to your repo, you can see the build status in <a href="https://app.travis-ci.com/">Travis CI</a>. Once it complete, check your site repo and access your blog to see the update.</p>
2021-10-09T03:03:49.000Zhttps://youngforest.github.io/en/2021/09/22/LeetCode-biweekly-contest-61/LeetCode biweekly contest 61<p><a href="https://leetcode.com/contest/biweekly-contest-61">LeetCode biweekly contest 61</a></p>
2021-09-22T12:31:32.000Zhttps://youngforest.github.io/en/2021/09/22/LeetCode-weekly-contest-259/LeetCode weekly contest 259<p><a href="https://leetcode.com/contest/weekly-contest-259/">LeetCode weekly contest 259</a></p>
<p>This weekend is Chinese mid-autumn festival, which is a tradition day to got together with family. I am a country boy. My family live in another province, Shanxi. It is about 1,000 km far from Beijing, where I studied and work. Because of that, I cannot visit my parents. Fortunately, my girlfriend grow in Beijing. Her parents invite us to their home for lunch and dinner. They prepared much seafood because their daughter loves it. This is my excuse for not attending this contest.<br>I solved those problems after contest and share my intuitions and solutions now.</p>
<p>So no score board here.</p>
<h2 id="2011-Final-Value-of-Variable-After-Performing-Operations"><a href="#2011-Final-Value-of-Variable-After-Performing-Operations" class="headerlink" title="2011. Final Value of Variable After Performing Operations"></a>2011. Final Value of Variable After Performing Operations</h2><p>Sign-in question. A trick, which could reduce 4 operations to 2, is that the middle character (operations[i][1]) decides increment or decrement. With this, we could simplify our code.</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">finalValueAfterOperations</span><span class="params">(vector<string>& operations)</span> </span>{</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">const</span> <span class="keyword">auto</span>& s : operations) {</span><br><span class="line"> <span class="keyword">if</span> (s[<span class="number">1</span>] == <span class="string">'-'</span>) {</span><br><span class="line"> --ans;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> ++ans;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>Time complexity: O(N), where <code>N = operations.size()</code><br>Space complexity: O(1).</p>
<h2 id="2012-Sum-of-Beauty-in-the-Array"><a href="#2012-Sum-of-Beauty-in-the-Array" class="headerlink" title="2012. Sum of Beauty in the Array"></a>2012. Sum of Beauty in the Array</h2><p>For score is 2, compare <code>nums[i]</code> with the largest number before <code>i</code> and the smallest number after <code>i</code>. We maintain a variable to record and update <code>the largest number</code> and a pre-calculate array to record <code>the smallest number</code>.</p>
<p>For score is 1, just compare <code>nums[i]</code> with <code>nums[i-1]</code> and <code>nums[i+1]</code>.</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">sumOfBeauties</span><span class="params">(vector<<span class="type">int</span>>& nums)</span> </span>{</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> n = nums.<span class="built_in">size</span>();</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">smallestNumber</span><span class="params">(n + <span class="number">1</span>)</span></span>;</span><br><span class="line"> smallestNumber[n] = numeric_limits<<span class="type">int</span>>::<span class="built_in">max</span>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = n<span class="number">-1</span>; i >= <span class="number">0</span>; --i) {</span><br><span class="line"> smallestNumber[i] = <span class="built_in">min</span>(nums[i], smallestNumber[i+<span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> largestNumber = nums[<span class="number">0</span>];</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i < n - <span class="number">1</span>; ++i) {</span><br><span class="line"> <span class="type">int</span> score = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (largestNumber < nums[i] && nums[i] < smallestNumber[i+<span class="number">1</span>]) {</span><br><span class="line"> score = <span class="number">2</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (nums[i<span class="number">-1</span>] < nums[i] && nums[i] < nums[i+<span class="number">1</span>]) {</span><br><span class="line"> score = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> largestNumber = <span class="built_in">max</span>(largestNumber, nums[i]);</span><br><span class="line"> ans += score;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>Time complexity: O(n),<br>Space complexity: O(n).</p>
<h2 id="2013-Detect-Squares"><a href="#2013-Detect-Squares" class="headerlink" title="2013. Detect Squares"></a>2013. Detect Squares</h2><p>Attention: <strong>Square</strong> instead of <strong>rectangle</strong>.<br>I wasted a lot of time because of this misunderstanding. Luckily, it is not on real contest.</p>
<p>Use <code>unordered_map<int, map<int, int>></code> to store all points.<br>When count squares, we iterate every row and find the width, then with width find the other two points.</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">DetectSquares</span> {</span><br><span class="line"> <span class="type">static</span> <span class="keyword">constexpr</span> <span class="type">int</span> MX = <span class="number">1001</span>;</span><br><span class="line"> unordered_map<<span class="type">int</span>, map<<span class="type">int</span>, <span class="type">int</span>>> points;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">DetectSquares</span>() {</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(vector<<span class="type">int</span>> point)</span> </span>{</span><br><span class="line"> ++points[point[<span class="number">0</span>]][point[<span class="number">1</span>]];</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">count</span><span class="params">(vector<<span class="type">int</span>> point)</span> </span>{</span><br><span class="line"> <span class="comment">// iterate in Y axis, iterate in X axis</span></span><br><span class="line"> <span class="comment">// time complexity: n</span></span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> x = point[<span class="number">0</span>];</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> y = point[<span class="number">1</span>];</span><br><span class="line"> <span class="type">const</span> <span class="keyword">auto</span>& row = points[x];</span><br><span class="line"> <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">const</span> <span class="keyword">auto</span>& p : points) {</span><br><span class="line"> <span class="keyword">if</span> (p.first == x) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="type">const</span> <span class="keyword">auto</span>& row2 = p.second;</span><br><span class="line"> <span class="keyword">auto</span> it = row2.<span class="built_in">find</span>(y);</span><br><span class="line"> <span class="keyword">if</span> (it != row2.<span class="built_in">end</span>()) {</span><br><span class="line"> <span class="comment">// find D</span></span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> width = <span class="built_in">abs</span>(p.first - x);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i : {+width, -width}) {</span><br><span class="line"> <span class="keyword">auto</span> itB = row.<span class="built_in">find</span>(y + i);</span><br><span class="line"> <span class="keyword">auto</span> itC = row2.<span class="built_in">find</span>(y + i);</span><br><span class="line"> <span class="keyword">if</span> (itB != row.<span class="built_in">end</span>() && itC != row2.<span class="built_in">end</span>()) {</span><br><span class="line"> ans += it->second * itB->second * itC -> second;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Your DetectSquares object will be instantiated and called as such:</span></span><br><span class="line"><span class="comment"> * DetectSquares* obj = new DetectSquares();</span></span><br><span class="line"><span class="comment"> * obj->add(point);</span></span><br><span class="line"><span class="comment"> * int param_2 = obj->count(point);</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>
<p>Time complexity:</p>
<ul>
<li>DetectSquares: O(1),</li>
<li>add: O(log n),</li>
<li>count: O(n log n).<br>Space complexity: O(n).<br>Where n = points number.</li>
</ul>
<h2 id="2014-Longest-Subsequence-Repeated-k-Times"><a href="#2014-Longest-Subsequence-Repeated-k-Times" class="headerlink" title="2014. Longest Subsequence Repeated k Times"></a>2014. Longest Subsequence Repeated k Times</h2>2021-09-22T12:31:19.000Zhttps://youngforest.github.io/en/2021/09/15/LeetCode-weekly-contest-258/LeetCode weekly contest 258<table>
<thead>
<tr>
<th>Rank</th>
<th>Name</th>
<th>Score</th>
<th>Finish Time</th>
<th>Q1 (3)</th>
<th>Q2 (4)</th>
<th>Q3 (5)</th>
<th>Q4 (6)</th>
</tr>
</thead>
<tbody><tr>
<td>540 / 12179</td>
<td>YoungForest</td>
<td>12</td>
<td>0:19:13</td>
<td>0:02:46</td>
<td>0:12:18</td>
<td>0:19:13</td>
<td>null</td>
</tr>
</tbody></table>
<p>From this week, I will write my summary posts for the LeetCode weekly and biweekly contests in English. Before this, I have written more than 100 LeetCode contests summary posts in Chinese. For future international interviews and jobs opportunities, I believe writing English LeetCode summary is a good way to improve my expression and algorithm.</p>
2021-09-15T06:48:07.000Zhttps://youngforest.github.io/en/2020/05/27/best-implement-to-use-pair-as-key-to-std-unordered-map-in-C/Best implement to use pair as key to std::unordered_map in C++<p>Reference: <a href="https://www.mica.edu.vn/perso/Vu-Hai/EE3490/Ref/The%20C++Standard%20Library%20-%202nd%20Edition.pdf">C++ Standard Library: A tutorial and reference, Second version</a> Chapter 7.9.2: Creating and Controlling unordered Container</p>
<p>All solutions I found in Google use <code>XOR</code> to generate hashcode of <code>pair</code>, which is totally bad. see <a href="https://stackoverflow.com/questions/5889238/why-is-xor-the-default-way-to-combine-hashes">why-is-xor-the-default-way-to-combine-hashes</a>. However, the book has given us the best solution, using <code>hash_combine</code>, which is taken from <code>Boost</code>. The solution is much better than XOR when I tested it in Online Judge(<a href="https://atcoder.jp/contests/abc168/tasks/abc168_e">Atcoder</a>). I organized the code as a template as follow. You can copy and paste it as much as you can. And it is convenient to change it to fit any custom struct/class.</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><functional></span></span></span><br><span class="line"><span class="comment">// from boost (functional/hash):</span></span><br><span class="line"><span class="comment">// see http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html template</span></span><br><span class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">hash_combine</span><span class="params">(std::<span class="type">size_t</span> &seed, <span class="type">const</span> T &val)</span> </span>{</span><br><span class="line"> seed ^= std::<span class="built_in">hash</span><T>()(val) + <span class="number">0x9e3779b9</span> + (seed << <span class="number">6</span>) + (seed >> <span class="number">2</span>);</span><br><span class="line">}</span><br><span class="line"><span class="comment">// auxiliary generic functions to create a hash value using a seed</span></span><br><span class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T> <span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">hash_val</span><span class="params">(std::<span class="type">size_t</span> &seed, <span class="type">const</span> T &val)</span> </span>{</span><br><span class="line"> <span class="built_in">hash_combine</span>(seed, val);</span><br><span class="line">}</span><br><span class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T, <span class="keyword">typename</span>... Types></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">void</span> <span class="title">hash_val</span><span class="params">(std::<span class="type">size_t</span> &seed, <span class="type">const</span> T &val, <span class="type">const</span> Types &... args)</span> </span>{</span><br><span class="line"> <span class="built_in">hash_combine</span>(seed, val);</span><br><span class="line"> <span class="built_in">hash_val</span>(seed, args...);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> <<span class="keyword">typename</span>... Types></span><br><span class="line"><span class="function"><span class="keyword">inline</span> std::<span class="type">size_t</span> <span class="title">hash_val</span><span class="params">(<span class="type">const</span> Types &... args)</span> </span>{</span><br><span class="line"> std::<span class="type">size_t</span> seed = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">hash_val</span>(seed, args...);</span><br><span class="line"> <span class="keyword">return</span> seed;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">pair_hash</span> {</span><br><span class="line"> <span class="keyword">template</span> <<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span>></span><br><span class="line"> <span class="function">std::<span class="type">size_t</span> <span class="title">operator</span><span class="params">()</span><span class="params">(<span class="type">const</span> std::pair<T1, T2> &p)</span> <span class="type">const</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">hash_val</span>(p.first, p.second);</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><bits/stdc++.h></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">using</span> ll = <span class="type">long</span> <span class="type">long</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> unordered_map<pair<ll, ll>, ll, pair_hash> slopeCount;</span><br><span class="line"> unordered_set<pair<ll, ll>, pair_hash> seen;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>There is a hash implementation for <code>Tuple</code>. I updated the answer in<a href="https://stackoverflow.com/a/62035742/6393787">StackOverflow</a>。Please go there if you need hash tuple.</p>
2020-05-27T04:29:34.000Z