Tuesday, June 13, 2017

Interesting opinions About Job Interviews

I one day stumbled upon this site (Things I Learned From Failing Technical Interviews), a section called "Do not be Yourself" intrigued me.

Contrary to the popular suggestions from many career advisers to be yourself during job interview, the person suggests the interviewee not to be him/herself, but to be a robot.  I totally agree with his opinion.  If you've done multiple job interviews for software engineer job position, you might have experienced some unease when the interviewer expects you to be perfect in coding in front of him/her. No syntax errors, have to memorize the APIs, etc.  The blogger continues to say that hiring a candidate is just like another upgrade of server or adding another PC in the server cluster, which is to offload work from the team to the new hired.

It is almost a guarantee that you will be asked something you don't know and even an hour of thinking about it and problem solving around it you still won't know.  Sometimes you get asked something you've known it long time ago, but can no longer able to recall, grasp it and/or explain it to them clearly.  You feel like you're an idiot with glamorous titles and said experiences (and preconceive that the interviewer must say in his mind, "why the heck this guy is applying for this position", or "Oh boy, another fake"?)

Another job-seeking-related blog: I will get That Job at Google

Wednesday, June 7, 2017

Swamping two variables without temporary variable

Based on the Boolean Algebra, where XOR operator is commutative and associative:

A = A ⊕ B
B = B ⊕ A = B ⊕ (A ⊕ B) = B ⊕ (B ⊕ A) = (B ⊕ B) ⊕ A
  = 0 ⊕ A = A
A = A ⊕ B = (A ⊕ B) ⊕ A = B ⊕ (A ⊕ A) = B

So the steps are:

A = A^B;
B = B^A;
A = A^B;

Another way is by doing arithmetics:

A = A - B;
B = A + B;
A = B - A;

Or
A = A + B;
B = A - B;

A = A - B;

If we look at carefully, the XOR operator is actually a half-adder operation (with carry bit).

A ⊕ B = A' * B + A * B', where if A=1 the result would be equal to B', else equal to B.

Tuesday, May 23, 2017

Bits Reversal - Advanced

Suppose we have 16-bit number where we want to reverse some bits between bits i'th and j'th.  To illustrate that, say we have a 16-bit value stored in v:

|<-------- L = sizeof(short)*CHAR_BIT --------->|
 15                       7                1   0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|  |  |  | x| x| x| x| x| x| x|  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 
          ^                  ^
          |                  |
         i=12               j=6
|<------>|
 L - i - 1
  

So, we want to reverse bits between bits 6th to 12th.

Assume i is always greater than j (i > j):
Number of bits to reverse: n = (i - j) + 1

Mask to use: (2^n - 1) << j

Or, in the case above:

n = (12 - 6) + 1 = 7
mask = (2^7 - 1) << 6 = 127 << 6  = 0x1FC0 (0001111111000000 in binary)

Then we mask the bits stored in v and shift it back to 0 (to do reverse operation):

r = (v & mask)  >> j;

r =
 15                       7                1   0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 0| 0| 0| 0| 0| 0| 0| 0| 0| x| x| x| x| x| x| x|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


We use bit reversal operation as posted previously on r:

r = bit_reversal(r);

After this call, the bits are reversed, but filled in from MSB.  We need to put them to the position originally started.

 15                       7                1   0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| x| x| x| x| x| x| x|  |  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                    |-------> shr 3

<========= sizeof(unsigned int)* CHAR_BIT ======>


m = sizeof(short) * CHAR_BIT - n - j
m = 2*8 - 7 -6 = 16 - 13 = 3

Final result is:

(v & !mask) | ((r >> m) & mask);

Bit Reversal - Explained

The page Bit Twiddling Hacks shows how to reverse bits in an integer (e.g, reverse LSB with MSB bits or reading bits from the opposite direction), but seems it doesn't explain anything why that works.

Here I try to explain it step by step.  Let start with a 8-bit char first.  Assume each letter in ABCDEFGH represents each bits in the char (e.g, A is for MSB etc.).

x = ABCDEFGH

ABCDEFGH
10101010 (or 0xAA)
-------- &
A0C0E0G0  ---- >> 1 : 0A0C0E0G

ABCDEFGH
01010101 (or 0x55)
-------- &
0B0D0F0H  ---- << 1 : B0D0F0H0

0A0C0E0G
B0D0F0H0
-------- |
BADCFEHG  ---> stored as a new x, then we do next operation

BADCFEHG
11001100  (or 0xCC)
--------- &
BA00FE00  ---- >> 2: 00BA00FE

BADCFEHG
00110011  (or 0x33)
--------- &
00DC00HG  ---- << 2: DC00HG00

00BA00FE
DC00HG00
-------- |
DCBAHGFE


Last, we operate the similar thing on the high and low nibbes:

DCBAHGFE
11110000 (or 0xF0)
-------- &
DCBA0000   ==> >> 4 = 0000DCBA

DCBAHGFE
00001111 (or 0x0F)
-------- &
0000HGFE   ==> << 4 = HGFE0000

0000DCBA
HGFE0000
--------|
HGFEDCBA

Finally, we now get HGFEDCBA which is the reversed bits of ABCDEFGH!  To summarize, to reverse bits in an octet, we do operations:

x = (x & 0xAA >> 1) | (x & 0x55 << 1);
x = (x & 0xCC >> 2) | (x & 0x33 << 2);
x = (x & 0xF0 >> 4) | (x & 0x0F >> 4);

For operation on 32-bit data, we do the similar one, except we do with 32-bit mask (instead of 10101010 binary or 0xAA, we mask with 0xAAAAAAAA) plus extra two pair of masks (0xF0F0F0F0 and 0x0F0F0F0F, 0xFF00FF00 and 0x00FF00FF) with shift left/right 4, 8 and 16 bit.

So, bit-reversal computation or algorithm for 32-bit integer:

unsigned int reverse_bits(unsigned int x)
{
    x = ((x & 0xA0A0A0A0) >> 1) | ((x & 0x05050505) << 1);
    x = ((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2);
    x = ((x & 0x0F0F0F0F) >> 4) | ((x & 0xF0F0F0F0) << 4);
    x = ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8);
    return (x >> 16) | (x << 16);
}




Monday, April 17, 2017

Infrastructure of Data Science and Analytics

Data Science apparently is now becoming a trend.  It basically a collection of methods and paradigms in querying, analysing, processing and visualizing big data.  Oil companies, business intelligence and marketing, social media, Artificial Intelligence, etc. want that.

Definition
Big Data: Extremely large data sets that may be analyzed computationally to revel patterns, trends, and associations, especially relating to human behavior an interactions.

  • Cluster: a collection of computers working together in parallel (distributed processing) and in the same local network and using the similar hardware
  • Grid: Similar to grid, but computers are geographically spread out and use more heterogeneous hardware.  
  • Hadoop: a Java-based programming framework that supports the processing and storage of extremely large data sets by using MapReduce framework.  It's open source under Apache license.
  • MapReduce, a core component of the Apache's Hadoop Software Framework.  Originated from Google Research paper with the same name.
  • Hiv
  • Pig: a high-level platform for creating programs that run on Apache Hadoop.  It consists of high-level language called Pig Latin abstracting underlying Java on Hadoop.
  • SQL
  • Full-stack
  • MIKE2.0
  • Groovy
  • Tez

Monday, March 20, 2017

OpenWRT Modules: JUCI

JUCI = JavaScript for UCI (Unified Configuration Interface): the Web UI interface to the UCI (or, simply "The GUI front end" of OpenWRT).  Mainly developed by Martin K.  Schröder <mkschreder.uk@gmail.com>
Foundation: The jQuery and angularJS famework.

About
URL
JUCI GIT Repohttps://github.com/mkschreder/juci
JUCI Documentation in HTML formhttp://mkschreder.github.io/juci
overview of how juci workshttp://mkschreder.github.io/juci/manual/how-juci-works.html
AngularJS
AngularJS version 1 Documentationhttps://docs.angularjs.org/guide

Client Browser

Must be HTML5-enabled browser with Javascript enabled.

Principles

OpenWrt's central configuration is split into several files located in the /etc/config/ directory. Each file relates roughly to the part of the system it configures. 

Flow

  1. Modify config file (a file in /etc/config)
  2. restart service that uses that config file (/etc/init.d/<service script>)

Directory Structure

TOPDIR=$HOME/work/raptor/openwrt
As defined in $TOPDIR/feeds/juci/juci/Makefile, the tarballed juci package is downloaded into $TOPDIR/dl/juci-<ver#>.tar.gz
and untarred into $TOPDIR/build_dir/target-arm_cortex-a9_uClibs-<ver>

MAKE
====
Steps done in pakage/feeds//Makefile:
TARGETNAME=target-arm_cortex-a9_uClibc-0.9.33.2_eabi
PKG_BUILD_DIR=$TOPDIR/build_dir/$TARGETNAME/
mkdir -p ${PKG_BUILD_DIR}
cp $TOPDIR/package/feeds//src/* ${PKG_BUILD_DIR}/
make -C $TOPDIR/staging_dir/${TARGETNAME}/usr/src/juci/ MODULE=${PKG_BUILD_DIR}

Files

To see the latest pull of JUCI into our branch, check PKG_VERSION in $TOPDIR/feeds/juci/juci/Makefile
In $TOPDIR/target/linux/bcm5301x/base-files/etc/uci-defaults/config:
  • content-filter
  • juci
  • srg-diagnostics
  • system
  • user-interfaces

In $TOPDIR//packages/juci-full-/files/etc/config/:
  • capo

In $TOPDIR//packages/juci--family-shield/files/etc/config/family-shield/:
  • family-shield

In $TOPDIR/package/base-files/files/etc/config/:
  • iptv
  • network
  • ntra
  • webdav
  • wifi-insight

In $TOPDIR/network/services/ipset-dns/files/:
  • ipset-dns.config (installed as ipset-dns in target's /etc/config)


To do clean build of the whole JUCI + Juci modules:

Building Juci
make package/feeds/juci/juci/{clean,prepare,compile} package/index V=s

JUCI html files are compiled into the *.js files by command:

HTML to JS
./scripts/juci-build-tpl-cache


(The Makefile above converts html files into *.js and put in tarball file named: node_modules.tar.gz

JUCI in feed

This subdirectory is used when we want to create a JUCI patch.  We git pull the juci module into $TOPDIR/feeds/juci/juci. 

See Creating patches to JUCI core modules

The following script might be useful to do the steps as described above

JUCI Checkout
#!/bin/bash
if [ $# -lt 1 ]
then
    echo ""
    echo "$0 <juci version/tag>"
    echo ""
    echo "Current version for SOS: v2.16.09"
    exit
fi
tag=$1
cd ~/work/raptor/openwrt
./scripts/feeds update juci
pushd feeds/juci
git submodule init
git submodule update
cd juci/src
git checkout ${tag}
popd
make package/juci/clean V=s && make V=s


Once we've done the script above, we can start editing files needed.  Once we're done, just create a patch (assuming we're already in directory $TOPDIR/feeds/juci/juci/src):

Creating patch
git diff -p --stat > ../patches/01x-my-patch-name.patch


JUCI Components

  • JUCI core (juci.js)
  • Plugins (for example: js/50-juci-ddns.js, etc.)
  • Theme *.js

The plugins are located (to be exact: extracted to) $BUILD_DIR/$TARGETNAME/juci-<juci-ver#>/plugins/
For example, for menu "WIFI", the plugin is in $HOME/work/raptor/openwrt/build_dir/target-arm_cortex-a9_uClibc-0.9.33.2_eabi/juci-fcfb1fcd85735c69ffad89a9d3d9b6c26d3df810/plugins/juci-openwrt-wireless

JUCI on Target Device

The JUCI config file is /etc/config/juci, which contains menus and submenus
To tell juci to reload, type juci-update

Creating JUCI Patch

Creating patches to JUCI core modules

LINKS

Juci Coding Standard
JUCI Build Environment Setup
Testing juci core patches
JUCI Debugging Tips
Creating patches to JUCI core modules
JUCI Coding Standard