5/100 - Sleep is for the weak

I am currently weak.

#Coding question of the day is,

Since we touch on permutation in 4/100 day, we shall do combination today.

Given a string ‘ab’,
Example of permutation: [‘ab’,’ba’] Order is important.
Example of combination: [‘ab’] Order does not matter.

Q: Find all combinations of a string.

1
2
3
4
5
def combi(string):
return string

string = 'abc'
print combi(string) # print 'abc'

haha, I’m kidding. (Please laugh, even though I am so sleepy, I tried to crack a joke)

Question on combination would be something like…

Q: Given a set of coins (1,2,3) and a value (5). Find out the number of combinations with the set of coins that sum up to the given value.

Try it at https://leetcode.com/problems/coin-change-2/description/

1
2
3
4
5
6
7
8
9
10
11
12
13
Given coins (1,2,3) and value (5),

List of combinations:
11111
1112
113
122
23

Answer:
5

For this question, we just want the number of combinations instead of the list of combination. We will do the latter next time.

Soluton 1: Naive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def combination(coins, value):
# base cases
# there is a combination
if value == 0:
return 1

# there is no combination or index out of range

if value < 0 or len(coins) == 0:
return 0

return combination(coins[1:], value) + combination(coins, value - coins[0])


coins, value = [1, 2, 3], 10
print combination(coins, value)

Result:

1
5

Time Complexity: exponential?, depends on size of coins and the value. Must I prove it? T.T

Soluton 2: Better with memoization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def combination(coins, value, memo):
# base cases
# there is a combination
if value == 0:
return 1

# there is no combination or index out of range
if value < 0 or len(coins) == 0:
return 0

sortedSetOfCoinsWithValue = (''.join(map(str, sorted(coins))),
value - coins[0])

if sortedSetOfCoinsWithValue not in memo:
memo[sortedSetOfCoinsWithValue] = combination(coins, value - coins[0],
memo)
return combination(coins[1:], value,
memo) + memo[sortedSetOfCoinsWithValue]


def combinationUtil(coins, value):
# handle invalid cases
if len(coins) == 0 or value == 0:
return -1

memo = {}
numberOfCombinations = combination(coins, value, memo)

# as a requirement, return -1 if there is no combination
if numberOfCombinations == 0:
return -1

return numberOfCombinations


coins, value = [1, 2, 3], 5
print combinationUtil(coins, value)

Result:

1
5

Time Complexity: Exponential, we will look into it again.
Space Complexity: O(1) unless we calculate recursive stack used.

Not as efficient if I have many coins or the value is big.

coins, value = [i for i in range(100)], 1000
coins, value = [1], 1000
RuntimeError: maximum recursion depth exceeded while getting the str of an object

But good enough today’s CODE FOR TODAY.


4/100 - TGIF

#Before I start,

I am seeing a pattern forming. I cheated a day so today I am doing twice of everything. I am hungry already.

#Today I learned,

Creating a healthy habit is not easy. I gave in to sleep on day 4 because I was sleepy. Damn you, the need to sleep more than ordinary people. And that consistency is an addiction.

#Impossible ideas are,

  1. This place is tooo wordy. I don’t enjoy reading as much as I enjoy typing nonsense here. Translating all these into a video would be useful.
  2. Detect throw distance from phone. Throwing phone all day long. Would be good for game like Pokemon. A pretend throw game.
  3. Connect multiple screens to form a big screen using just browser.
  4. Create a mini hackathon since I can’t commit to normal hackathon. An hour kind of hacking that gives you mini rewards.
  5. Phone to detect futuristic hand gesture in the air. You know what I am saying.
  6. AI in browser. Dangerous but I like.

#Coding question of the day is,

Q: Find the permutation of a string containing distinct characters

Using string = ‘abc’, the answer is [‘abc’,’acb’,’bac’,’bca’,’cab’,cba’]

Breaking it down, write now the solution and find a pattern out of it.

1
2
3
4
5
6
7
8
abc
acb

bac
bca

cab
cba

I added a global count to the solution to demonstrate the usefulness of memoization compared to just recursion.

Solution 1: (Naive)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
count = 0
def permutate(string):
# count is just to compare between this solutiona and the next one
global count
count = count + 1

# base cases
if len(string) == 1 or len(string) == 0:
return string

currentPermutationSet = []
for i in range(len(string)):
# string is immutable so we create a new string without the current index character
remainingString = string.replace(string[i], '')
permutatationSet = permutate(remainingString)

# concat current index character with the set of permutation from remaining characters and add to currentPermutationSet
for j in range(len(permutatationSet)):
currentPermutationSet.append(string[i] + permutatationSet[j])

return currentPermutationSet

string = 'abcdef'
print permutate(string)
print count

Result:

1
2
['abcdef', 'abcdfe', 'abcedf', 'abcefd', 'abcfde', 'abcfed', 'abdcef', 'abdcfe', 'abdecf', 'abdefc', 'abdfce', 'abdfec', 'abecdf', 'abecfd', 'abedcf', 'abedfc', 'abefcd', 'abefdc', 'abfcde', 'abfced', 'abfdce', 'abfdec', 'abfecd', 'abfedc', 'acbdef', 'acbdfe', 'acbedf', 'acbefd', 'acbfde', 'acbfed', 'acdbef', 'acdbfe', 'acdebf', 'acdefb', 'acdfbe', 'acdfeb', 'acebdf', 'acebfd', 'acedbf', 'acedfb', 'acefbd', 'acefdb', 'acfbde', 'acfbed', 'acfdbe', 'acfdeb', 'acfebd', 'acfedb', 'adbcef', 'adbcfe', 'adbecf', 'adbefc', 'adbfce', 'adbfec', 'adcbef', 'adcbfe', 'adcebf', 'adcefb', 'adcfbe', 'adcfeb', 'adebcf', 'adebfc', 'adecbf', 'adecfb', 'adefbc', 'adefcb', 'adfbce', 'adfbec', 'adfcbe', 'adfceb', 'adfebc', 'adfecb', 'aebcdf', 'aebcfd', 'aebdcf', 'aebdfc', 'aebfcd', 'aebfdc', 'aecbdf', 'aecbfd', 'aecdbf', 'aecdfb', 'aecfbd', 'aecfdb', 'aedbcf', 'aedbfc', 'aedcbf', 'aedcfb', 'aedfbc', 'aedfcb', 'aefbcd', 'aefbdc', 'aefcbd', 'aefcdb', 'aefdbc', 'aefdcb', 'afbcde', 'afbced', 'afbdce', 'afbdec', 'afbecd', 'afbedc', 'afcbde', 'afcbed', 'afcdbe', 'afcdeb', 'afcebd', 'afcedb', 'afdbce', 'afdbec', 'afdcbe', 'afdceb', 'afdebc', 'afdecb', 'afebcd', 'afebdc', 'afecbd', 'afecdb', 'afedbc', 'afedcb', 'bacdef', 'bacdfe', 'bacedf', 'bacefd', 'bacfde', 'bacfed', 'badcef', 'badcfe', 'badecf', 'badefc', 'badfce', 'badfec', 'baecdf', 'baecfd', 'baedcf', 'baedfc', 'baefcd', 'baefdc', 'bafcde', 'bafced', 'bafdce', 'bafdec', 'bafecd', 'bafedc', 'bcadef', 'bcadfe', 'bcaedf', 'bcaefd', 'bcafde', 'bcafed', 'bcdaef', 'bcdafe', 'bcdeaf', 'bcdefa', 'bcdfae', 'bcdfea', 'bceadf', 'bceafd', 'bcedaf', 'bcedfa', 'bcefad', 'bcefda', 'bcfade', 'bcfaed', 'bcfdae', 'bcfdea', 'bcfead', 'bcfeda', 'bdacef', 'bdacfe', 'bdaecf', 'bdaefc', 'bdafce', 'bdafec', 'bdcaef', 'bdcafe', 'bdceaf', 'bdcefa', 'bdcfae', 'bdcfea', 'bdeacf', 'bdeafc', 'bdecaf', 'bdecfa', 'bdefac', 'bdefca', 'bdface', 'bdfaec', 'bdfcae', 'bdfcea', 'bdfeac', 'bdfeca', 'beacdf', 'beacfd', 'beadcf', 'beadfc', 'beafcd', 'beafdc', 'becadf', 'becafd', 'becdaf', 'becdfa', 'becfad', 'becfda', 'bedacf', 'bedafc', 'bedcaf', 'bedcfa', 'bedfac', 'bedfca', 'befacd', 'befadc', 'befcad', 'befcda', 'befdac', 'befdca', 'bfacde', 'bfaced', 'bfadce', 'bfadec', 'bfaecd', 'bfaedc', 'bfcade', 'bfcaed', 'bfcdae', 'bfcdea', 'bfcead', 'bfceda', 'bfdace', 'bfdaec', 'bfdcae', 'bfdcea', 'bfdeac', 'bfdeca', 'bfeacd', 'bfeadc', 'bfecad', 'bfecda', 'bfedac', 'bfedca', 'cabdef', 'cabdfe', 'cabedf', 'cabefd', 'cabfde', 'cabfed', 'cadbef', 'cadbfe', 'cadebf', 'cadefb', 'cadfbe', 'cadfeb', 'caebdf', 'caebfd', 'caedbf', 'caedfb', 'caefbd', 'caefdb', 'cafbde', 'cafbed', 'cafdbe', 'cafdeb', 'cafebd', 'cafedb', 'cbadef', 'cbadfe', 'cbaedf', 'cbaefd', 'cbafde', 'cbafed', 'cbdaef', 'cbdafe', 'cbdeaf', 'cbdefa', 'cbdfae', 'cbdfea', 'cbeadf', 'cbeafd', 'cbedaf', 'cbedfa', 'cbefad', 'cbefda', 'cbfade', 'cbfaed', 'cbfdae', 'cbfdea', 'cbfead', 'cbfeda', 'cdabef', 'cdabfe', 'cdaebf', 'cdaefb', 'cdafbe', 'cdafeb', 'cdbaef', 'cdbafe', 'cdbeaf', 'cdbefa', 'cdbfae', 'cdbfea', 'cdeabf', 'cdeafb', 'cdebaf', 'cdebfa', 'cdefab', 'cdefba', 'cdfabe', 'cdfaeb', 'cdfbae', 'cdfbea', 'cdfeab', 'cdfeba', 'ceabdf', 'ceabfd', 'ceadbf', 'ceadfb', 'ceafbd', 'ceafdb', 'cebadf', 'cebafd', 'cebdaf', 'cebdfa', 'cebfad', 'cebfda', 'cedabf', 'cedafb', 'cedbaf', 'cedbfa', 'cedfab', 'cedfba', 'cefabd', 'cefadb', 'cefbad', 'cefbda', 'cefdab', 'cefdba', 'cfabde', 'cfabed', 'cfadbe', 'cfadeb', 'cfaebd', 'cfaedb', 'cfbade', 'cfbaed', 'cfbdae', 'cfbdea', 'cfbead', 'cfbeda', 'cfdabe', 'cfdaeb', 'cfdbae', 'cfdbea', 'cfdeab', 'cfdeba', 'cfeabd', 'cfeadb', 'cfebad', 'cfebda', 'cfedab', 'cfedba', 'dabcef', 'dabcfe', 'dabecf', 'dabefc', 'dabfce', 'dabfec', 'dacbef', 'dacbfe', 'dacebf', 'dacefb', 'dacfbe', 'dacfeb', 'daebcf', 'daebfc', 'daecbf', 'daecfb', 'daefbc', 'daefcb', 'dafbce', 'dafbec', 'dafcbe', 'dafceb', 'dafebc', 'dafecb', 'dbacef', 'dbacfe', 'dbaecf', 'dbaefc', 'dbafce', 'dbafec', 'dbcaef', 'dbcafe', 'dbceaf', 'dbcefa', 'dbcfae', 'dbcfea', 'dbeacf', 'dbeafc', 'dbecaf', 'dbecfa', 'dbefac', 'dbefca', 'dbface', 'dbfaec', 'dbfcae', 'dbfcea', 'dbfeac', 'dbfeca', 'dcabef', 'dcabfe', 'dcaebf', 'dcaefb', 'dcafbe', 'dcafeb', 'dcbaef', 'dcbafe', 'dcbeaf', 'dcbefa', 'dcbfae', 'dcbfea', 'dceabf', 'dceafb', 'dcebaf', 'dcebfa', 'dcefab', 'dcefba', 'dcfabe', 'dcfaeb', 'dcfbae', 'dcfbea', 'dcfeab', 'dcfeba', 'deabcf', 'deabfc', 'deacbf', 'deacfb', 'deafbc', 'deafcb', 'debacf', 'debafc', 'debcaf', 'debcfa', 'debfac', 'debfca', 'decabf', 'decafb', 'decbaf', 'decbfa', 'decfab', 'decfba', 'defabc', 'defacb', 'defbac', 'defbca', 'defcab', 'defcba', 'dfabce', 'dfabec', 'dfacbe', 'dfaceb', 'dfaebc', 'dfaecb', 'dfbace', 'dfbaec', 'dfbcae', 'dfbcea', 'dfbeac', 'dfbeca', 'dfcabe', 'dfcaeb', 'dfcbae', 'dfcbea', 'dfceab', 'dfceba', 'dfeabc', 'dfeacb', 'dfebac', 'dfebca', 'dfecab', 'dfecba', 'eabcdf', 'eabcfd', 'eabdcf', 'eabdfc', 'eabfcd', 'eabfdc', 'eacbdf', 'eacbfd', 'eacdbf', 'eacdfb', 'eacfbd', 'eacfdb', 'eadbcf', 'eadbfc', 'eadcbf', 'eadcfb', 'eadfbc', 'eadfcb', 'eafbcd', 'eafbdc', 'eafcbd', 'eafcdb', 'eafdbc', 'eafdcb', 'ebacdf', 'ebacfd', 'ebadcf', 'ebadfc', 'ebafcd', 'ebafdc', 'ebcadf', 'ebcafd', 'ebcdaf', 'ebcdfa', 'ebcfad', 'ebcfda', 'ebdacf', 'ebdafc', 'ebdcaf', 'ebdcfa', 'ebdfac', 'ebdfca', 'ebfacd', 'ebfadc', 'ebfcad', 'ebfcda', 'ebfdac', 'ebfdca', 'ecabdf', 'ecabfd', 'ecadbf', 'ecadfb', 'ecafbd', 'ecafdb', 'ecbadf', 'ecbafd', 'ecbdaf', 'ecbdfa', 'ecbfad', 'ecbfda', 'ecdabf', 'ecdafb', 'ecdbaf', 'ecdbfa', 'ecdfab', 'ecdfba', 'ecfabd', 'ecfadb', 'ecfbad', 'ecfbda', 'ecfdab', 'ecfdba', 'edabcf', 'edabfc', 'edacbf', 'edacfb', 'edafbc', 'edafcb', 'edbacf', 'edbafc', 'edbcaf', 'edbcfa', 'edbfac', 'edbfca', 'edcabf', 'edcafb', 'edcbaf', 'edcbfa', 'edcfab', 'edcfba', 'edfabc', 'edfacb', 'edfbac', 'edfbca', 'edfcab', 'edfcba', 'efabcd', 'efabdc', 'efacbd', 'efacdb', 'efadbc', 'efadcb', 'efbacd', 'efbadc', 'efbcad', 'efbcda', 'efbdac', 'efbdca', 'efcabd', 'efcadb', 'efcbad', 'efcbda', 'efcdab', 'efcdba', 'efdabc', 'efdacb', 'efdbac', 'efdbca', 'efdcab', 'efdcba', 'fabcde', 'fabced', 'fabdce', 'fabdec', 'fabecd', 'fabedc', 'facbde', 'facbed', 'facdbe', 'facdeb', 'facebd', 'facedb', 'fadbce', 'fadbec', 'fadcbe', 'fadceb', 'fadebc', 'fadecb', 'faebcd', 'faebdc', 'faecbd', 'faecdb', 'faedbc', 'faedcb', 'fbacde', 'fbaced', 'fbadce', 'fbadec', 'fbaecd', 'fbaedc', 'fbcade', 'fbcaed', 'fbcdae', 'fbcdea', 'fbcead', 'fbceda', 'fbdace', 'fbdaec', 'fbdcae', 'fbdcea', 'fbdeac', 'fbdeca', 'fbeacd', 'fbeadc', 'fbecad', 'fbecda', 'fbedac', 'fbedca', 'fcabde', 'fcabed', 'fcadbe', 'fcadeb', 'fcaebd', 'fcaedb', 'fcbade', 'fcbaed', 'fcbdae', 'fcbdea', 'fcbead', 'fcbeda', 'fcdabe', 'fcdaeb', 'fcdbae', 'fcdbea', 'fcdeab', 'fcdeba', 'fceabd', 'fceadb', 'fcebad', 'fcebda', 'fcedab', 'fcedba', 'fdabce', 'fdabec', 'fdacbe', 'fdaceb', 'fdaebc', 'fdaecb', 'fdbace', 'fdbaec', 'fdbcae', 'fdbcea', 'fdbeac', 'fdbeca', 'fdcabe', 'fdcaeb', 'fdcbae', 'fdcbea', 'fdceab', 'fdceba', 'fdeabc', 'fdeacb', 'fdebac', 'fdebca', 'fdecab', 'fdecba', 'feabcd', 'feabdc', 'feacbd', 'feacdb', 'feadbc', 'feadcb', 'febacd', 'febadc', 'febcad', 'febcda', 'febdac', 'febdca', 'fecabd', 'fecadb', 'fecbad', 'fecbda', 'fecdab', 'fecdba', 'fedabc', 'fedacb', 'fedbac', 'fedbca', 'fedcab', 'fedcba']
1237

We can do it better by storing computed permutations of strings into an object.

Example, given string = ‘abcd’
a bcd -> bcd -> b cd -> cd // compute permutation of cd
b acd -> acd -> a cd -> cd // compute permutation of cd again!
c abd
d abc

Solution 2: (Better)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
count = 0

def permutateUtil(set): # base cases
global count
count = count + 1

string = set[0]
memo = set[1]

if len(string) == 1 or len(string) == 0:
return (string, memo)

currentPermutationSet = []
for i in range(len(string)):
remainingString = string.replace(string[i], '')
sortedString = ''.join(sorted(remainingString))
if sortedString not in memo:
memo[sortedString] = permutateUtil((remainingString,
memo))[0] #bc,cb
for j in range(len(memo[sortedString])):
currentPermutationSet.append(string[i] + memo[sortedString][j])

return (currentPermutationSet, memo)


def permutate(string):
memo = {}
set = (string, memo)
solution = permutateUtil(set)
return solution[0]


string = 'abcdef'
print permutate(string)
print count

Result:

1
2
['abcdef', 'abcdfe', 'abcedf', 'abcefd', 'abcfde', 'abcfed', 'abdcef', 'abdcfe', 'abdecf', 'abdefc', 'abdfce', 'abdfec', 'abecdf', 'abecfd', 'abedcf', 'abedfc', 'abefcd', 'abefdc', 'abfcde', 'abfced', 'abfdce', 'abfdec', 'abfecd', 'abfedc', 'acbdef', 'acbdfe', 'acbedf', 'acbefd', 'acbfde', 'acbfed', 'acdbef', 'acdbfe', 'acdebf', 'acdefb', 'acdfbe', 'acdfeb', 'acebdf', 'acebfd', 'acedbf', 'acedfb', 'acefbd', 'acefdb', 'acfbde', 'acfbed', 'acfdbe', 'acfdeb', 'acfebd', 'acfedb', 'adbcef', 'adbcfe', 'adbecf', 'adbefc', 'adbfce', 'adbfec', 'adcbef', 'adcbfe', 'adcebf', 'adcefb', 'adcfbe', 'adcfeb', 'adebcf', 'adebfc', 'adecbf', 'adecfb', 'adefbc', 'adefcb', 'adfbce', 'adfbec', 'adfcbe', 'adfceb', 'adfebc', 'adfecb', 'aebcdf', 'aebcfd', 'aebdcf', 'aebdfc', 'aebfcd', 'aebfdc', 'aecbdf', 'aecbfd', 'aecdbf', 'aecdfb', 'aecfbd', 'aecfdb', 'aedbcf', 'aedbfc', 'aedcbf', 'aedcfb', 'aedfbc', 'aedfcb', 'aefbcd', 'aefbdc', 'aefcbd', 'aefcdb', 'aefdbc', 'aefdcb', 'afbcde', 'afbced', 'afbdce', 'afbdec', 'afbecd', 'afbedc', 'afcbde', 'afcbed', 'afcdbe', 'afcdeb', 'afcebd', 'afcedb', 'afdbce', 'afdbec', 'afdcbe', 'afdceb', 'afdebc', 'afdecb', 'afebcd', 'afebdc', 'afecbd', 'afecdb', 'afedbc', 'afedcb', 'bacdef', 'bacdfe', 'bacedf', 'bacefd', 'bacfde', 'bacfed', 'badcef', 'badcfe', 'badecf', 'badefc', 'badfce', 'badfec', 'baecdf', 'baecfd', 'baedcf', 'baedfc', 'baefcd', 'baefdc', 'bafcde', 'bafced', 'bafdce', 'bafdec', 'bafecd', 'bafedc', 'bcadef', 'bcadfe', 'bcaedf', 'bcaefd', 'bcafde', 'bcafed', 'bcdaef', 'bcdafe', 'bcdeaf', 'bcdefa', 'bcdfae', 'bcdfea', 'bceadf', 'bceafd', 'bcedaf', 'bcedfa', 'bcefad', 'bcefda', 'bcfade', 'bcfaed', 'bcfdae', 'bcfdea', 'bcfead', 'bcfeda', 'bdacef', 'bdacfe', 'bdaecf', 'bdaefc', 'bdafce', 'bdafec', 'bdcaef', 'bdcafe', 'bdceaf', 'bdcefa', 'bdcfae', 'bdcfea', 'bdeacf', 'bdeafc', 'bdecaf', 'bdecfa', 'bdefac', 'bdefca', 'bdface', 'bdfaec', 'bdfcae', 'bdfcea', 'bdfeac', 'bdfeca', 'beacdf', 'beacfd', 'beadcf', 'beadfc', 'beafcd', 'beafdc', 'becadf', 'becafd', 'becdaf', 'becdfa', 'becfad', 'becfda', 'bedacf', 'bedafc', 'bedcaf', 'bedcfa', 'bedfac', 'bedfca', 'befacd', 'befadc', 'befcad', 'befcda', 'befdac', 'befdca', 'bfacde', 'bfaced', 'bfadce', 'bfadec', 'bfaecd', 'bfaedc', 'bfcade', 'bfcaed', 'bfcdae', 'bfcdea', 'bfcead', 'bfceda', 'bfdace', 'bfdaec', 'bfdcae', 'bfdcea', 'bfdeac', 'bfdeca', 'bfeacd', 'bfeadc', 'bfecad', 'bfecda', 'bfedac', 'bfedca', 'cabdef', 'cabdfe', 'cabedf', 'cabefd', 'cabfde', 'cabfed', 'cadbef', 'cadbfe', 'cadebf', 'cadefb', 'cadfbe', 'cadfeb', 'caebdf', 'caebfd', 'caedbf', 'caedfb', 'caefbd', 'caefdb', 'cafbde', 'cafbed', 'cafdbe', 'cafdeb', 'cafebd', 'cafedb', 'cbadef', 'cbadfe', 'cbaedf', 'cbaefd', 'cbafde', 'cbafed', 'cbdaef', 'cbdafe', 'cbdeaf', 'cbdefa', 'cbdfae', 'cbdfea', 'cbeadf', 'cbeafd', 'cbedaf', 'cbedfa', 'cbefad', 'cbefda', 'cbfade', 'cbfaed', 'cbfdae', 'cbfdea', 'cbfead', 'cbfeda', 'cdabef', 'cdabfe', 'cdaebf', 'cdaefb', 'cdafbe', 'cdafeb', 'cdbaef', 'cdbafe', 'cdbeaf', 'cdbefa', 'cdbfae', 'cdbfea', 'cdeabf', 'cdeafb', 'cdebaf', 'cdebfa', 'cdefab', 'cdefba', 'cdfabe', 'cdfaeb', 'cdfbae', 'cdfbea', 'cdfeab', 'cdfeba', 'ceabdf', 'ceabfd', 'ceadbf', 'ceadfb', 'ceafbd', 'ceafdb', 'cebadf', 'cebafd', 'cebdaf', 'cebdfa', 'cebfad', 'cebfda', 'cedabf', 'cedafb', 'cedbaf', 'cedbfa', 'cedfab', 'cedfba', 'cefabd', 'cefadb', 'cefbad', 'cefbda', 'cefdab', 'cefdba', 'cfabde', 'cfabed', 'cfadbe', 'cfadeb', 'cfaebd', 'cfaedb', 'cfbade', 'cfbaed', 'cfbdae', 'cfbdea', 'cfbead', 'cfbeda', 'cfdabe', 'cfdaeb', 'cfdbae', 'cfdbea', 'cfdeab', 'cfdeba', 'cfeabd', 'cfeadb', 'cfebad', 'cfebda', 'cfedab', 'cfedba', 'dabcef', 'dabcfe', 'dabecf', 'dabefc', 'dabfce', 'dabfec', 'dacbef', 'dacbfe', 'dacebf', 'dacefb', 'dacfbe', 'dacfeb', 'daebcf', 'daebfc', 'daecbf', 'daecfb', 'daefbc', 'daefcb', 'dafbce', 'dafbec', 'dafcbe', 'dafceb', 'dafebc', 'dafecb', 'dbacef', 'dbacfe', 'dbaecf', 'dbaefc', 'dbafce', 'dbafec', 'dbcaef', 'dbcafe', 'dbceaf', 'dbcefa', 'dbcfae', 'dbcfea', 'dbeacf', 'dbeafc', 'dbecaf', 'dbecfa', 'dbefac', 'dbefca', 'dbface', 'dbfaec', 'dbfcae', 'dbfcea', 'dbfeac', 'dbfeca', 'dcabef', 'dcabfe', 'dcaebf', 'dcaefb', 'dcafbe', 'dcafeb', 'dcbaef', 'dcbafe', 'dcbeaf', 'dcbefa', 'dcbfae', 'dcbfea', 'dceabf', 'dceafb', 'dcebaf', 'dcebfa', 'dcefab', 'dcefba', 'dcfabe', 'dcfaeb', 'dcfbae', 'dcfbea', 'dcfeab', 'dcfeba', 'deabcf', 'deabfc', 'deacbf', 'deacfb', 'deafbc', 'deafcb', 'debacf', 'debafc', 'debcaf', 'debcfa', 'debfac', 'debfca', 'decabf', 'decafb', 'decbaf', 'decbfa', 'decfab', 'decfba', 'defabc', 'defacb', 'defbac', 'defbca', 'defcab', 'defcba', 'dfabce', 'dfabec', 'dfacbe', 'dfaceb', 'dfaebc', 'dfaecb', 'dfbace', 'dfbaec', 'dfbcae', 'dfbcea', 'dfbeac', 'dfbeca', 'dfcabe', 'dfcaeb', 'dfcbae', 'dfcbea', 'dfceab', 'dfceba', 'dfeabc', 'dfeacb', 'dfebac', 'dfebca', 'dfecab', 'dfecba', 'eabcdf', 'eabcfd', 'eabdcf', 'eabdfc', 'eabfcd', 'eabfdc', 'eacbdf', 'eacbfd', 'eacdbf', 'eacdfb', 'eacfbd', 'eacfdb', 'eadbcf', 'eadbfc', 'eadcbf', 'eadcfb', 'eadfbc', 'eadfcb', 'eafbcd', 'eafbdc', 'eafcbd', 'eafcdb', 'eafdbc', 'eafdcb', 'ebacdf', 'ebacfd', 'ebadcf', 'ebadfc', 'ebafcd', 'ebafdc', 'ebcadf', 'ebcafd', 'ebcdaf', 'ebcdfa', 'ebcfad', 'ebcfda', 'ebdacf', 'ebdafc', 'ebdcaf', 'ebdcfa', 'ebdfac', 'ebdfca', 'ebfacd', 'ebfadc', 'ebfcad', 'ebfcda', 'ebfdac', 'ebfdca', 'ecabdf', 'ecabfd', 'ecadbf', 'ecadfb', 'ecafbd', 'ecafdb', 'ecbadf', 'ecbafd', 'ecbdaf', 'ecbdfa', 'ecbfad', 'ecbfda', 'ecdabf', 'ecdafb', 'ecdbaf', 'ecdbfa', 'ecdfab', 'ecdfba', 'ecfabd', 'ecfadb', 'ecfbad', 'ecfbda', 'ecfdab', 'ecfdba', 'edabcf', 'edabfc', 'edacbf', 'edacfb', 'edafbc', 'edafcb', 'edbacf', 'edbafc', 'edbcaf', 'edbcfa', 'edbfac', 'edbfca', 'edcabf', 'edcafb', 'edcbaf', 'edcbfa', 'edcfab', 'edcfba', 'edfabc', 'edfacb', 'edfbac', 'edfbca', 'edfcab', 'edfcba', 'efabcd', 'efabdc', 'efacbd', 'efacdb', 'efadbc', 'efadcb', 'efbacd', 'efbadc', 'efbcad', 'efbcda', 'efbdac', 'efbdca', 'efcabd', 'efcadb', 'efcbad', 'efcbda', 'efcdab', 'efcdba', 'efdabc', 'efdacb', 'efdbac', 'efdbca', 'efdcab', 'efdcba', 'fabcde', 'fabced', 'fabdce', 'fabdec', 'fabecd', 'fabedc', 'facbde', 'facbed', 'facdbe', 'facdeb', 'facebd', 'facedb', 'fadbce', 'fadbec', 'fadcbe', 'fadceb', 'fadebc', 'fadecb', 'faebcd', 'faebdc', 'faecbd', 'faecdb', 'faedbc', 'faedcb', 'fbacde', 'fbaced', 'fbadce', 'fbadec', 'fbaecd', 'fbaedc', 'fbcade', 'fbcaed', 'fbcdae', 'fbcdea', 'fbcead', 'fbceda', 'fbdace', 'fbdaec', 'fbdcae', 'fbdcea', 'fbdeac', 'fbdeca', 'fbeacd', 'fbeadc', 'fbecad', 'fbecda', 'fbedac', 'fbedca', 'fcabde', 'fcabed', 'fcadbe', 'fcadeb', 'fcaebd', 'fcaedb', 'fcbade', 'fcbaed', 'fcbdae', 'fcbdea', 'fcbead', 'fcbeda', 'fcdabe', 'fcdaeb', 'fcdbae', 'fcdbea', 'fcdeab', 'fcdeba', 'fceabd', 'fceadb', 'fcebad', 'fcebda', 'fcedab', 'fcedba', 'fdabce', 'fdabec', 'fdacbe', 'fdaceb', 'fdaebc', 'fdaecb', 'fdbace', 'fdbaec', 'fdbcae', 'fdbcea', 'fdbeac', 'fdbeca', 'fdcabe', 'fdcaeb', 'fdcbae', 'fdcbea', 'fdceab', 'fdceba', 'fdeabc', 'fdeacb', 'fdebac', 'fdebca', 'fdecab', 'fdecba', 'feabcd', 'feabdc', 'feacbd', 'feacdb', 'feadbc', 'feadcb', 'febacd', 'febadc', 'febcad', 'febcda', 'febdac', 'febdca', 'fecabd', 'fecadb', 'fecbad', 'fecbda', 'fecdab', 'fecdba', 'fedabc', 'fedacb', 'fedbac', 'fedbca', 'fedcab', 'fedcba']
63

Time complexity: O(n!) same for both. The second one is just more efficient since we don’t need to recalculate permutations of substring.
Space complexity: O(n!) woohoo!

#Build a cool thing which is,

  • Gonna add 2 levels on blackbox. Got a feedback that the countdown time is not accurate for different timezone. Since I am doing everything frontend only for now. Let’s see how we can fix that. (Postpone this because I am so sleeeepy)

  • Fix styles and add a 2d demo on yoah. (Excited but I need to sleep now)

#Open source

I found out about http://js13kgames.com/ through Twitter. “The competition will start at 13:00 CEST, 13th August and will end at 13:00 CEST, 13th September 2018”. I GONNA JOIN THIS!

Also, I heard you get stickers by contributing to Gatsby. Let’s find an easy issue to fix.

#Retrospective on my fake day4,

This 100daysofcode challenge challenges my sleep. Time becomes so valuable. My rest is threathened. My mental health is shaking. I am 1mm outside of my comfort zone. I am proud and ashamed at the same time.

P/S: I just came up with the question and solutions, could contain mistakes since I have not tested it fully with edge cases. Use with care.


-> 3/100 day

TICBO, pronounced as “tickbo”, In my country’s language (Singlish, ftw) means “have you ticked your task already?”. We are very lazy but creative people.

#Today I learned,

1) That thoughts become actions. And that lodash is pretty good.

lodash is a really efficient JavaScript library that optimizes your code. Before es6 map, shorthand etc, I think lodash is the king. I use the word ‘think’ because I never use it until recently. I used the functions throttle and debounce over video events that I never knew call more than 1 time per second. 🤦

Q: How to use it?

  1. Install only the library you need from lodash. ^^
  2. Import the library if you are using babel, otherwise use “const get = require(‘lodash.get’);”.
  3. Use it.

DEMO on lodash get, documentation at https://lodash.com/docs/4.17.10#get

Without lodash,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const object = {
key: [
{
value: {
inceptionValue: 1
}
},
{
value: {
inceptionValue: 2
}
},
{
thisIsNotTheValueWeWant: "sometime thing's fucked up"
}
]
};

const firstInceptionValue =
object &&
object.length > 0 &&
object[0].key &&
object[0].key.value &&
object[0].key.value.inceptionValue // all conditions are true
? object[0].key.value.inceptionValue // use this value
: 0;

const thirdInceptionValue =
object &&
object.length > 0 &&
object[2].key &&
object[2].key.value && // will stop here with undefined error
object[2].key.value.inceptionValue
? object[2].key.value.inceptionValue
: 0; // and use this value

console.log(firstInceptionValue); // 1
console.log(thirdInceptionValue); // 0

With lodash,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import get from "lodash.get";

const object = {
key: [
{
value: {
inceptionValue: 1
}
},
{
value: {
inceptionValue: 2
}
},
{
value: null
}
]
};

// ░░░░░░░░░▄░░░░░░░░░ ▄
// ░░░░░░░░▌▒█░░░░░░░░░░░▄▀▒▌
// ░░░░░░░░▌▒▒█░░░░░░░░▄▀▒▒▒▐
// ░░░░░░░▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐
// ░░░░░▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐
// ░░░▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌
// ░░▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒▌
// ░░▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐
// ░▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄▌
// ░▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒▌
// ▌▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒▐
// ▐▒▒▐▀▐▀▒░▄▄▒▄▒▒▒▒▒▒░▒░▒░▒▒▒▒▌
// ▐▒▒▒▀▀▄▄▒▒▒▄▒▒▒▒▒▒▒▒░▒░▒░▒▒▐
// ░▌▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒░▒░▒░▒░▒▒▒▌
// ░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▒▄▒▒▐
// ░░▀▄▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▄▒▒▒▒▌
// ░░░░▀▄▒▒▒▒▒▒▒▒▒▒▄▄▄▀▒▒▒▒▄▀
// ░░░░░░▀▄▄▄▄▄▄▀▀▀▒▒▒▒▒▄▄—
// much shorter, so wow, much cool,
// get(object, deep nested key name, default value if it doesn't exist);
const firstInceptionValue = get(object, "key[0].value.inceptionValue", 0);
const thirdInceptionValue = get(object, "key[2].value.inceptionValue", 0);

console.log(firstInceptionValue); // 1
console.log(thirdInceptionValue); // 0

2) Use Prettier

Life sucks. People are getting superficial day by day. Prettier is a makeup artist you never knew you needed. If you are using VSCode, you are in luck. There’s a plugin that will auto indent your code prettily after you save the file. If you don’t like plugin, you can also integrate using command line tool.

Prettier is a code formatter, not a human makeup artist.
Check it out at https://github.com/prettier/prettier

If only I can do a “save” in the morning on myself, I don’t need to spend time getting ready to look okay. Sidetrack a little, why prettier and not handsomer.

#Impossible ideas are,

FYI, these are just some crazy ideas I force myself to squeeze out daily. Some I wish I build them, some I wish I am able to build them, some I wish technology allows me to build them. Some I wish may happen out of magic, like teaching Robert Downey Junior to code or Casey neistat (seems more possible) or getting invited to Pixar and getting all the pixar toys. #hopetheuniverseislistening

  1. Find out the distance between you and someone. (Creepy I know, maybe a loved one? hmmmm…)
  2. Use mobile phone as a remote control by just opening a browser. I am looking at VR/AR. 😎
  3. Display hologram from mobile phone. Whutttt
  4. Code easily on phone. Tried typing a JavaScript snippet on twitter, spend so much time indenting and finding brackets. hmmmmm…

#Coding question of the day is,

Q: Find all permutations of a string.

Permutation means order does not matter.

1
2
3
4
5
6
7
8
Given the string `abc`
Answer:
abc
acb
bca
bac
cab
cba

WOAH. Not a simple question. I am running over time today, need to sleep now. Will update tomorrow. opps.

#Build a cool thing which is,

TLDR; DEMO on the blackbox game I am building. Super raw.

I built a new level (level2) at blackbox. (Do a happy dance) Click the box below to play despite the spoiler above. Feel the itch to code? You can contribute a level at https://github.com/linxea/blackbox. It’ll be fun, I promise.


<– Click to play

#Optional today again.

(I should be ashamed)

But a shout-out to dev.to, they have open sourced their codebase. Woah. https://github.com/thepracticaldev/dev.to It’s trending now too in the holy world of github.

Wanna give another shout-out to pressure, a JavaScript library for force touch. https://github.com/stuyam/pressure. I love love love it. Gonna use it soon in one of my #buildacoolthing thingy.

Not sure why I am doing shout-out to emptiness. Perhaps a shout-out to my future self who happens to come to the site to click on the advertisement to earn that 1 cent.

#sadbuttrue

I should just host my daily show. Late night with linxea where I share random things I find online with bad grammar. :< #codernotwriter


-> 2/100 day

Today while travelling to work, I came up with an acroynm for the stuff I want to do every day.

#TICBO

Today I learned.
Impossible ideas are.
Coding question of the day is.
Build a cool thing which is.
Open source contribution or optional.

#Today I learned,

Use srcset and sizes in <img> to request for relevant sizes depending on your browser size. Open in small screen, browser will fetch same-image-320w.jpg. If you resize it to a bigger screen, browser will automatically fetch the bigger image and replace it. :O

DEMO - I used two different images to demonstrate the change.

1
2
3
4
5
<img srcset="same-image-320w.jpg 320w,
same-image-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
800px"
src="same-image-800w.jpg" alt="image">

#Impossible ideas are,

  1. Grow a plant in web browser.
  2. Code and deploy just from mobile phone.
  3. Make website alive, a website that is alive and reacts according to your actions.
  4. Shake to get inspiration quotes.
  5. A loading bar that is also a game.
  6. Bring me to Pixar.

#Coding question of the day is,

Q: Given a number and an array of sorted distinct array of integers, find the index of the number.

First ask question like how’s the weather, how are you. Nah, I’m kidding.

The simplest solution I can give is to iterate through the array and return index of the number if the value of the index == number. What happen if we cannot find the number?

That’s the question to ask.

Null case. What should we return if the array of integers does not contain the given number? Probably suggest None (for python) or null but not -1 since integers could contain negative value. Well, you got to ask if there are any negative values at all.

1
2
3
4
5
def findIndex(arr, number):
for i in range(len(arr)):
if arr[i] == number:
return i
return None
1
2
Time complexity: O(n) yuck
Space complexity: O(1) since we never store anything

We can do it better.

Notice the “sorted” and “distinct”, these are helping words. We can divide and conquer the array since it’s sorted and distinct.

Yes, binary search.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def findIndexUtil(arr, number, start, end):
if start < end:
# Find the middle index
mid = (end - start) / 2 + start

# Yes! we found it!
if arr[mid] == number:
return mid
# If curent value is still smaller than number, move to the right half
elif arr[mid] < number:
return findIndexUtil(arr, number, mid+1, end):
# If curent value is bigger than number, move to the left half
else:
return findIndexUtil(arr, number, start, mid-1):

# Nope, we can't find it. Handle such case by returning None/null/error
return None

def findIndex(arr, number):
start, end = 0, len(arr) - 1

# Util is a shortform for utility, like a helper function to do work
# Normally we name it the functionWeAreUsingUtil
return findIndexUtil(arr, number, start, end)
1
2
Time complexity: O(log n) ^^
Space complexity: O(1) since we never store anything

#Build a cool thing which is,

a really simple blackbox game. Check it out https://linxea.github.io/blackbox/



#Optional today

because I am sleepy today but I will find some open source libraries to play with soon.


100DaysOfCode

Day 1 [ ~3 hours spent! ]

Today we will do a coding question, think of a few impossible ideas, tell you what I learned at work and build something cool.

1. Coding Question [Dynamic Programming]

Q: Given a 2d array of size x by y, find the number of ways you can travel from top left(0,0) to bottom right(x,y). You can only move right or down.

-> Before you read the answer below, try your solution at https://leetcode.com/problems/unique-paths/description/

1
2
3
4
5
6
7
8
9
10
Example:

00 -> 01 -> 02
| | |
10 -> 11 -> 12
| | |
20 -> 21 -> 22

Given x,y = 3,3
Number of ways = 6

First, identify what are row and column.

1
2
3
4
5
6
col0  col1  col2
00 -> 01 -> 02 row 0
| | |
10 -> 11 -> 12 row 1
| | |
20 -> 21 -> xy row 2

There are x rows.
At each row, there is y number of columns.

Q: What kind of parameters do we have?

A: We got rowIndex, columnIndex.

Q: What are the rules?

A: Rules says that we can only move down or right. So we need to increment rowIndex and columnIndex.
A: If current position is out of range, we got to handle that by returning 0.
A: Our base case will be when we reach index (x,y). Return 1 to identify 1 way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def findUniquePathsUtil(rowLength, columnLength, rowIndex, columnIndex):
# terminating case
if rowIndex > rowLength or columnIndex > columnLength:
return 0

# base case
if rowIndex == rowLength and columnIndex == columnLength:
return 1

# recursively move to the right and down until it reaches the base case
return findUniquePathsUtil(rowLength, columnLength, rowIndex + 1,
columnIndex) + findUniquePathsUtil(
rowLength, columnLength, rowIndex, columnIndex + 1)

def findUniquePaths(self, m, n):
return findUniquePathsUtil(m-1, n-1, 0, 0)

m,n = 3,3
print findUniquePaths(m,n)

Time Complexity: exponential
Space Complexity: exponential if we count recurisve stack, otherwise it’s O(1)

Q: Can we do better?

A: Yes we can, with memoization. Use a 2d array to store number of ways calculated at each position.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def findUniquePathsUtil(rowLength, columnLength, rowIndex, columnIndex, memo):
# terminating case
if rowIndex > rowLength or columnIndex > columnLength:
return 0

# base case
if rowIndex == rowLength and columnIndex == columnLength:
return 1

# if number of ways is already calculated at position, return from memo
if memo[rowIndex][columnIndex] > -1:
return memo[rowIndex][columnIndex]

# recursively move to the right and down until it reaches the base case
memo[rowIndex][columnIndex] = findUniquePathsUtil(rowLength, columnLength, rowIndex + 1, columnIndex, memo) + findUniquePathsUtil(
rowLength, columnLength, rowIndex, columnIndex + 1, memo)

return memo[rowIndex][columnIndex]

def findUniquePaths(self, m, n):
memo = [[-1 for _ in range(n)] for _ in range(m)]
return findUniquePathsUtil(m-1, n-1, 0, 0, memo)

m,n = 3,3
print findUniquePaths(m,n)

Time Complexity: O(mn)
Space Complexity: O(mn) because of memo array

2. Few crazy ideas

  1. Build a holographic app
  2. Scribble svg that can transform to things I like
  3. Explaining coding question helps me to understand what I don’t know, probably an app to faciliate this kinda thing would be useful
  4. Build a motion sensor thingy on website
  5. Build a popup book effect on website because I miss popup book so much.
  6. Build my own Jarvis

3. What I learned at work

1 We can use shorthand in .babelrc / webpack, both of the examples below work.

1
2
3
4
5
"plugins": ["babel-plugin-myPlugin"]

or

"plugins": ["myPlugin"]

2 Get cold sweat while removing libraries from package.json and updating package-lock.json and yarn.lock files.

  • yarn remove library then npm uninstall library --save
    or
  • manually remove library from package.json then run npm install, yarn install

3 VPC. Virtual private cloud.

Shared server between client and server app means client can access server api using domain extension vpc. E.g. Client can do api call with http://serverapi.vpc instead of https://serverapi.com. Save trips since the call does not go out to the internet.

FYI, I am so grateful that I can learn so much at work. I learn something new everyday.

4. Build something cool [time is running out, got to sleep]

Today topic is motion sensor.

So I googled and found https://developers.google.com/web/updates/2017/09/sensors-for-the-web which led me to
https://github.com/intel/generic-sensor-demos. Got disappointed because 90% of the demos do not work on my iphone browsers. But I found https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Using_device_orientation_with_3D_transforms and it works.

Demo at https://linxea.github.io/yoah/

TLDR; I draw a square that rotates when you rotate your phone. Tested on Chrome and Safari browsers on iphone.

(LOOK AT THAT, GETTING WORK DONE YO. #2.4 on crazy idea coming life at ya)


pretty forEach vs ugly for loop

My colleague said for loop is ugly. So judgemental.

index.html

1
2
3
4
5
<div id="elements">
<p class"child"></p>
<p class"child"></p>
<p class"child"></p>
</div>

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ugly for loop
const elements = document.getElementById('elements');
for (let i = 0; i < elements.length; i++) {
elements.children[i].innerHTML = i;
}

// prettier option is to use forEach but it doesnt work for HTMLCollection because HTMLCollection is not an array! WHUT.
elements.forEach(function (child, index) { // Uncaught TypeError: elements.forEach is not a function
child.innerHTML = index;
});

// the answer is to use JS ARRAY OBJECT! Array.prototype.forEach or [].forEach for HTMLCollection elements
[].forEach.call(elements, function(child, index) {
child.innerHTML = index;
});

Time to move on from for loop. You have served me well, especially in school days. Anyway, I wouldn’t know HTMLCollection is not an array if I hadn’t use forEach. Cool.


How to send XMLHttpRequest POST with JSON Object

WTF IS CORS

What the fuck is Cross Origin Resource Sharing [CORS]?
When a.com makes a request to b.com, that’s CORS.

Most browsers implement Same Origin Policy [SOP], for security reason of cors. So scam.com cannot do a POST request to bank.com when you open both links in the same browser. But you can still do it if you have the right headers and request handling.

IRRITATING ERRORS:

1
Failed to load http://localhost:3000/profile: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access.
1
Failed to load http://localhost:3000/profile: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin 'http://localhost:8000' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
1
Failed to load http://localhost:3000/profile: Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

So if you get CORS errors like 504 Gateway timeout or No ‘Access-Control-Allow-Origin’ header,
That’s because:

  1. You are using method other than GET, HEAD, POST or
  2. You have custom header in your request like ‘X-Custom-Header’ or
  3. Your ‘Content-Type’ is not ‘application/x-www-urlencoded’ or ‘mutipart/form-data’ or ‘text/plain’

CORS FLOW

I will be using XMLHttpRequest, an API to send request from client to server. XMLHttpRequest can be used with different protocols and is able to send different data types despite its confusing name.

Client sends a POST request from browser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<body>
<button onclick="sendPOSTWithJSON()">POST WITH JSON OBJECT USING CORS!</button>
<script>
function sendPOSTWithJSON(){
const xhttp = new XMLHttpRequest(); // can use for any type of data, not just xml
xhttp.open('POST', 'http://localhost:3000/profile', true); // set true for async
xhttp.setRequestHeader('Content-Type', 'application/json'); // browser will send preflight request for cors with json, DELETE method or custom headers
xhttp.withCredentials = true; // to use cookie; server also needs to set access-control-allow-credentials to true
xhttp.send(JSON.stringify({
payload: 'data',
}));
xhttp.onreadystatechange = function() {
if (xhttp.readyState === 4) {
if (xhttp.status === 204) {
alert('YAY');
} else if (xhttp.status >= 400) {
alert('ERROR');
}
}
}
}
</script>
</body>
</html>

Server handles both OPTIONS and POST methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const express = require('express');
const app = express();
const bodyParser = require('body-parser');

app.use(bodyParser.json());

app.options('/profile', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8000');
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.sendStatus(204);
});
app.post('/profile', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8000');
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

if (req.body && req.body.payload) {
// do something
res.sendStatus(204);
} else {
// error
res.sendStatus(400);
}
});

app.listen(3000, () => console.log('Listen on Port 3000'));

Check Requests from Chrome DevTools from Network tab

Useful explanation which triggered my AHA moment:

https://security.stackexchange.com/questions/8264/why-is-the-same-origin-policy-so-important
https://www.html5rocks.com/static/images/cors_server_flowchart.png
https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
http://johnzhang.io/options-request-in-express
http://arunranga.com/examples/access-control/preflightXSInvocation.txt


React onClick Errors

[ DEMO EXAMPLE ON AMAZING CODESANDBOX.IO ]

Noob errors made by me:

1. function handleClick is called on first render, I didn’t even click on anything

1
2
3
4
5
6
7
8
9
10
11
12
13
class Component extends React.component {
render() {
<Card id={props.id} handleClick={this.handleClick.bind(this)} />
}
}

const Card = props => (
<Button handleClick={props.handleClick(props.id)} /> // apparently this calls the function `props.handleClick` even without onClick being triggered
);

const Button = props => (
<button onClick={props.handleClick}> // another mistake here
);

Solution:

If you use function with bracket () props.handleClick(props.id), it will trigger the function. Solve the error by passing parameter props.cardId in the button component and using the bracket () in the component that is supposed to trigger the function.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Component extends React.component {
render() {
<Card id={props.id} handleClick={this.handleClick.bind(this)} />
}
}

const Card = props => (
<Button cardId={props.id} handleClick={props.handleClick} /> // don't pass anything in the function `props.handleClick` if you don't want to call it at this level (Card Component)
);

const Button = props => (
<button onClick={props.handleClick(props.cardId)}> // another mistake here
);

2. onClick is not detected, silly me

1
2
3
4
5
6
7
8
9
10
11
12
13
class Component extends React.component {
render() {
<Card id={props.id} handleClick={this.handleClick.bind(this)} />
}
}

const Card = props => (
<Button cardId={props.id} handleClick={props.handleClick} />
);

const Button = props => (
<button onClick={props.handleClick(props.cardId)}> // error here!
);

Solution:

Same as the previous bug, using bracket() will activate the function at first render even without you clicking on anything. To trigger the right behaviour, you need to add callback parameter evt which triggers the function only when it detects click.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Component extends React.component {
render() {
<Card id={props.id} handleClick={this.handleClick.bind(this)} />
}
}

const Card = props => (
<Button cardId={props.id} handleClick={props.handleClick} />
);

const Button = props => (
<button onClick={evt => props.handleClick(props.cardId, evt)}>
);

quicksort-versus-mergesort

QuickSort wins MergeSort at sorting Array

  • QS is an in place sort [means swap elements within 1 array only]
  • MS requires O(N) extra storage [need to assign new arrays to store value]
  • Tail recursive, tail call optimizations [NO IDEA WHAT IT MEANS]
  • Everyone is saying QS is practical

MergSort wins QuickSort at sorting Linked List

reference: http://www.geeksforgeeks.org/quick-sort/


apply-of-undefined

Error:

If you get the error below out of a sudden, it’s probably because one of your million dependencies screwed up.

1
TypeError: Cannot read property 'apply' of undefined

Solution:

Use tilde ~ for your dependency in package.json. ~ allows patches only, while ^ allows minor changes and patches.
For production, I highly recommend you to ~ your important dependencies. I learnt it the hard way. ~.~ tmd

1
2
3
4
5
6
7
Package.json
{
"name": "toomuch",
"dependencies": {
"hexo": "~3.2.0",
}
}