LeetCode 2. Add Two Numbers

Here is my solution to Add Two Numbers problem in PHP:

/**
 * Definition for a singly-linked list.
 * class ListNode {
 *     public $val = 0;
 *     public $next = null;
 *     function __construct($val = 0, $next = null) {
 *         $this->val = $val;
 *         $this->next = $next;
 *     }
 * }
 */
class Solution {

    /**
     * @param ListNode $l1
     * @param ListNode $l2
     * @return ListNode
     */
    function addTwoNumbers($l1, $l2) {
        $ans = new ListNode(0, null);
        $p = $l1;
        $q = $l2;
        $current = $ans;
        $carry=0;

        while ($p != null || $q != null) {
            $x = isset($p) ? $p->val : 0;
            $y = isset($q) ? $q->val : 0;
            $sum = $carry + $x + $y;
            $carry = (int) ($sum/10);
            $current->next = new ListNode($sum%10);
            $current = $current->next;
            if ($p != null) $p = $p->next;
            if ($q != null) $q = $q->next;
        }
        if ($carry > 0) {
            $current->next = new ListNode($carry);
        }

        return $ans->next;
    }
}

Docker in 5 minutes

I have been using Docker and Kubernetes for several years now but never really took any time to really read about it. There were a lot of gaps in my understanding of how Docker works and what really is possible with it. Just recently my employer started to offer Udemy’s subscription, so I took Hands on Docker course. Here are some of the important things I learned in this course.

Where do you run Docker containers

You run these in Windows or MacOS but most likely you will use Linux in production. And unlike Windows and MacOS, you can run Docker on Linux VPS.

Important Docker commands

# get running docker containers
docker ps

# get all docker containers including those that have exited
docker ps -a

# stop container by its id or name
docker stop first_few_chars_of_id

# list docker images stored on the host
docker images

# remove image
docker rmi image_name

# download a new image
docker pull image_name
docker pul image_name:specific_tag

# append a command
docker run image_name command to run with parameters
docker run ubuntu sleep 5

# execute command in a conatiner
docker exec container_id cat /etc/hosts

# interactive session inside container
docker exec -it conatiner_id /bin/bash

# run container in background/daemon mode
docker run -d webapp

# tail logs
docker logs -f conatiner_id

# attach to conatiner running in detach/daemon mode
docker attach container_id

# map ports, for example, to map port 80 on host to port 8080 in container
dokcer run -p 80:8080 webapp

LeetCode 7. Reverse Integer

My initial solution for Reverse Integer problem:

/**
 * @param {number} x
 * @return {number}
 */
var reverse = function(x) {

    let ans = '';
    if (x<0) {
        ans = '-';
        x*=-1;
    }

    str = x.toString();

    for (let i=str.length-1; i>=0; i--) {
        ans += str[i];
    }

    ans = parseInt(ans);
    if (ans>2**31-1 || ans<(-2)**31) {
        return 0;
    }
    return ans;
};

Results

Runtime: 104 ms, faster than 34.78% of JavaScript online submissions for Reverse Integer.

Memory Usage: 40.5 MB, less than 33.80% of JavaScript online submissions for Reverse Integer.

Optimized Version:

After looking at solution and transpiling it to JavaScript:

/**
 * @param {number} x
 * @return {number}
 */
var reverse = function(x) {

    const max = 2**31-1;
    const min = (-2)**31;
    let ans = 0;

    while (x != 0) {
        const pop = x%10;
        x = Math.trunc(x/10);
        if (ans > max/10) return 0;
        if (ans < min/10) return 0;

        ans = ans * 10 + pop;
    }

    return ans;
};

Optimized Results

Runtime: 92 ms, faster than 87.08% of JavaScript online submissions for Reverse Integer.

Memory Usage: 40.4 MB, less than 33.80% of JavaScript online submissions for Reverse Integer.


LeetCode 3. Longest Substring Without Repeating Characters

Here is my solution in PHP to this problem.

class Solution {

    /**
     * @param String $s
     * @return Integer
     */
    function lengthOfLongestSubstring($s) {
        $n = strlen($s);
        $ans = 0;
        $i = 0;
        $j = 0;

        $arr = [];

        while ($i < $n && $j < $n) {
            if (!in_array($s[$j], $arr)) {
                $arr[] = $s[$j++];
                $ans = max($ans, $j-$i);
            } else {
                array_splice($arr, 0, 1);
                $i++;
            }
        }


        return $ans;
    }
}

And here is solution JavaScript based on this Udemy lesson:

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    if (s.length <= 1) return s.length;

    const seenChars = {};
    let i=0, longest=0;

    for (let j=0; j<s.length; j++) {
        const currentChar = s[j];
        const currentCharIndex = seenChars[currentChar];

        if (currentCharIndex>=i) {
            i = currentCharIndex+1;
        }

        longest = Math.max(longest, j-i+1);
        seenChars[currentChar] = j;
    }

    return longest;
};

Json_error_ctrl_char

I was using mcrypt to encrypt json_encoded data.

On other side, mycrypt was able to decrpyt data but json_decode was not working. It would throw JSON\_ERROR\_CTRL_CHAR error.

However, without mcrypt, json_decode worked flawlessly.

After some trial and error, I found that applying trim function after decrypting data would let me use json_decode without any issues.


Find Large Directories on AIX

I usually run it from under a partition which is running out of space. It can take a while.

du -g | sort -n -r


Error Xcode Select Error Tool Xcodebuild Requires Xcode Active Developer Directory Command Line Tools Instance

Playing with Cordova, I was getting this error when building iOS version:

Error: xcode-select: error: tool 'xcodebuild' requires Xcode,
but active developer directory is a command line tools instance

Even full install of Xcode didn’t fix this error.

The solution was to run following command to use full Xcode instead of command line tools version that I had installed earlier:

sudo xcode-select --switch /Applications/Xcode-beta.app/Contents/Developer


Setup Outgoing Email on Lightsail Ubuntu VPS

I followed instructions here: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-18-04

Everything seemed okay but email were not getting delivered. Logs showed me that smtp connections were timing out:

tail -f /var/log/mail.log
May  3 12:28:10 postfix/smtp[3160]: connect to gmail-smtp-in.l.google.com[172.217.197.27]:25: Connection timed out
May  3 12:28:10  postfix/smtp[3160]: connect to alt1.gmail-smtp-in.l.google.com[2800:3f0:4003:c00::1a]:25: Network is unreachable
May  3 12:28:40 postfix/smtp[3160]: 4984C41A1E: to=<xxxx@gmail.com>, relay=none, delay=3246, delays=3186/0.01/60/0, dsn=4.4.1, status=deferred (connect to alt2.gmail-smtp-in.l.google.com[2a00:1450:400b:c00::1a]:25: Network is unreachable)

However, I could ping any of above ip addresses just fine.

Next step was to see if ip address of my VPS was blacklisted in RBLs, I used https://mxtoolbox.com/blacklists.aspx. None of my ip addresses were in any black list.

Port 25 was open in firewall, both on server and in Lightsail’s networking UI.

After spending another hour or so troubleshooting, I found this thread: https://forums.aws.amazon.com/thread.jspa?threadID=316397. It seems AWS/Lightsail have recently started to throttle outgoing emails, but by throttling they meant completely blocking it. You need to open a support ticket to remove these limits here: https://console.aws.amazon.com/support/contacts?#/rdns-limits

So I submitted my request, hopefully, this will resolve the issue.

UPDATE: It worked, now my VPS can send outgoing emails.


hsts Neterr_cert_common_name_invalid

Without full understanding, I had enabled HSTS on amerkhalid.com with option includeSubDomains. I had a subdomain that was used as “Custom Domain” to SmugMug site. After enabling HSTS, these subdomains started to throw NET::ERR_CERT_COMMON_NAME_INVALID.

The fix is of course simple, don’t use includeSubDomains. But that opens up your top level domain to man in middle attacks.

For now, I decided to follow the best practices and leave includeSubDomains enabled. And decided to not use custom domain for my SmugMug site.

Lastly, you can clear HSTS settings in Chrome by:

  1. Enter in Address Bar chrome://net-internals/#hsts
  2. Under Delete domain type your domain
  3. Hit Delete button.

TypeError: require.extensions.hasOwnProperty is not a function

While playing with https://github.com/alexa/interactive-adventure-game-tool, I ran into following error:

> interactive-adventure-game-tool@1.0.0 start /Users/amer/alexa/interactive-adventure-game-tool
> node node_modules/gulp/bin/gulp.js

/Users/amer/alexa/interactive-adventure-game-tool/node_modules/require-dir/index.js:97
            if (!require.extensions.hasOwnProperty(ext)) {
                                    ^

TypeError: require.extensions.hasOwnProperty is not a function
    at requireDir (/Users/amer/alexa/interactive-adventure-game-tool/node_modules/require-dir/index.js:97:37)
    at Object.<anonymous> (/Users/amer/alexa/interactive-adventure-game-tool/gulpfile.js:1:85)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Module.require (module.js:604:17)
    at require (internal/module.js:11:18)
    at Liftoff.handleArguments (/Users/amer/alexa/interactive-adventure-game-tool/node_modules/gulp/bin/gulp.js:116:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! interactive-adventure-game-tool@1.0.0 start: `node node_modules/gulp/bin/gulp.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the interactive-adventure-game-tool@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/amer/.npm/_logs/2018-01-02T05_12_24_832Z-debug.log

The solution was to update require-dir to version 0.3.2 in package.json and run npm install again.


LeetCode 1664: Ways to Make a Fair Array

I tried to do this all by myself but got stuck, ended up transpiling this solution in PHP.

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer
     */
    function waysToMakeFair($nums) {
        $len = count($nums);
        $ans = 0;

        $leftOdd = 0;
        $rightOdd = 0;
        $leftEven = 0;
        $rightEven = 0;

        for ($i=0; $i<$len; $i++) {
            if ($i%2 === 0)
                $rightEven += $nums[$i];
            else
                $rightOdd += $nums[$i];
        }

        for ($i=0; $i<$len; $i++) {
            if ($i%2 === 0)
                $rightEven -= $nums[$i];
            else
                $rightOdd -= $nums[$i];

            if ($leftEven + $rightOdd === $rightEven + $leftOdd) $ans++;

            if ($i%2 === 0)
                $leftEven += $nums[$i];
            else
                $leftOdd += $nums[$i];
        }

        return $ans;
    }
}

LeetCode 20: Valid Parentheses

Here is my solution to this problem in PHP:

/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    const stack = [];
    const brackets = {
        '(': ')',
        '{': '}',
        '[': ']'
    };

    for (i=0; i<s.length; i++) {
        if (s.length === 0) return true;

        const c = s[i];
        if (brackets[c]) {
            stack.push(c);
        } else {
            const lastBracket = stack.pop();
            if (brackets[lastBracket] !== c) return false;
        }
    }

    if (stack.length > 0) return false;

    return true;
};

LeetCode 844. Backspace String Compare

Here is my solution Backspace String Compare problem.

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var backspaceCompare = function(s, t) {
    s = processString(s);
    t = processString(t);
    //console.log({s, t})
    return s===t;
};

let processString = function(s) {
    const a = [];
    let skip = 0;
    for (let i = s.length-1; i >= 0; i--) {
        if (s[i] === '#') {
            skip++;
        } else if (skip > 0) {
            skip--;
        } else {
            a.push(s[i]);
        }
        //console.log({a, skip, i})
    }
    let re = '';
    //console.log({ a: a.length})
    while (a.length > 0) {
        re += a.pop();
        //console.log({i, re, a: a.length})
    }
    return re;
}

Results:

Runtime: 80 ms, faster than 73.76% of JavaScript online submissions for Backspace String Compare.

Memory Usage: 39.3 MB, less than 33.63% of JavaScript online submissions for Backspace String Compare.


Leetcode 690: Employee Importance Solution

Here is another LeetCode solution for Employee Importance Problem.

/**
* Definition for Employee.
* class Employee {
*     public $id = null;
*     public $importance = null;
*     public $subordinates = array();
*     function __construct($id, $importance, $subordinates) {
*         $this->id = $id;
*         $this->importance = $importance;
*         $this->subordinates = $subordinates;
*     }
* }
*/

class Solution {
/**
 * @param Employee[] $employees
 * @param Integer $id
 * @return Integer
 */

function getImportance($employees, $id) {
  if (empty($employees)) return 0;
  $emap = [];
  foreach ($employees as $e) {
    $emap[$e->id] = $e;
  }

  return $this->recurse($emap, $id);
 }

function recurse($emap, $id) {
  $e = $emap[$id];
  $ans = $e->importance;
  foreach ($e->subordinates as $sub) {
    $ans += $this->recurse($emap, $sub);
  }
  return $ans;
 }
}

LeetCode 1249. Minimum Remove to Make Valid Parentheses

Here is my solution to this problem:

/**
 * @param {string} s
 * @return {string}
 */
var minRemoveToMakeValid = function(s) {
    const stack = [];
    const charArray = s.split("");
    const rightBracketsToRemove = [];

    for (let i=0;i<charArray.length;i++) {
        if (charArray[i] === '(') {
            stack.push(i);
        } else if (charArray[i] === ')' && stack.length > 0) {
            stack.pop();
        } else if (charArray[i] === ')') {
            charArray[i] = '';
        }
    }

    while (stack.length > 0) {
        const i = stack.pop();
        charArray[i] = '';
    }

    return charArray.join('');
};

Leetcode 13: Roman to Integers

Here is my solution to this problem in PHP:

class Solution {

    private $v = ['M' => 1000, 'D' => 500, 'C' => 100, 'L' => 50, 'X' => 10, 'V' => 5, 'I' => 1];
    /**
     * @param String $s
     * @return Integer
     */
    function romanToInt($s) {
        $n = 0;
        $last = '';
        for ($i=0;$i<strlen($s); $i++) {
            $n += $this->v[$s[$i]];
            if (($s[$i] == 'V' || $s[$i] == 'X') && $last == 'I') {
                $n = $n - 2;
            } elseif (($s[$i] == 'L' || $s[$i] == 'C') && $last == 'X') {
                $n -= 20;
            } elseif (($s[$i] == 'D' || $s[$i] == 'M') && $last == 'C') {
                $n -= 200;
            }
            $last = $s[$i];
        }

        return $n;
    }
}