Poker Hands

Just your basic poker hands. https://www.codeeval.com/open_challenges/86/

Started with the top hands then went to the lower ones. I use the positions before the decimal point to indicate the magnitude of the hand (royal flush being the greatest, singles being lowest). The positions after the decimal point are used to indicated additional subvalues that are required. IE two pairs can go down to the 2nd pair comparison or even to the single, thus need additional values. However, royal flush uses none of these additional slots because there can only be 1 royal flush, disregarding suit order.

Code:

var mapping = {
    '2': 2,
    '3': 3,
    '4': 4,
    '5': 5,
    '6': 6,
    '7': 7,
    '8': 8,
    '9': 9,
    'T': 10,
    'J': 11,
    'Q': 12,
    'K': 13,
    'A': 14
};

function Compare(line) {
    var cards = line.split(" ");
    var left = CheckHand(cards.slice(0,5));
    var right = CheckHand(cards.slice(5));
    if (left==right)
        return "none";
    else if (left > right)
        return "left";
    else
        return "right";
}

function CheckHand(cards) {
    cards.sort(function(x,y) {
        return mapping[x.charAt(0)] > mapping[y.charAt(0)];
    });
    var straight = IsStraight(cards);
    var flush = IsFlush(cards);
    var cardCounts = CardCount(cards);
    
    // just return straight flush
    if (straight && flush) {
        if (typeof cardCounts["12"]!=="undefined") {
            // it is a royal flush
            return 10;
        }
        return 9;
    }
    
    var pair1=0, pair2=0, triple=0;
    var singles = [];
    for (var i in cardCounts) {
        if (cardCounts[i]==4) {
            if (i<10)
                return "8.0"+i;     // four of a kind
            return "8."+i;
        } else if (cardCounts[i]==3) {
            if (i<10)
                triple="0"+i;
            else
                triple = i;
        } else if (cardCounts[i]==2&&pair1==0) {
            if (i<10)
                pair1="0"+i;     // one pair
            else
                pair1=i;
        } else if (cardCounts[i]==2) {
            if (i<10)
                pair2="0"+i;
            else
                pair2=i;
        } else { // singles
            if (i<10) {
                singles.push("0"+i);
            } else {
                singles.push(i);
            }
        }
    }
    
    // if hand is a fullhouse
    if (pair1>0&&triple>0) {
        if (triple<10)
            return "7.0"+triple+pair1;     // fullhouse (the triple first because that is the "high" since it is unique (you can't have 2 hands with three cards in the same round)
        return "7."+triple+pair1;
    } else if (flush) {
        return "6.0"+singles.reverse().join("");     // flush
    } else if (straight) {
        // check if it was ace with a 2 (low)
        if (singles[0]=="02")
            return "5.05";     // straight
        return "5."+singles.pop();     // straight
    } else if (triple!=0) {
        return "4."+triple+singles.pop()+singles.pop();
    } else if (pair2!=0) {
        return "3."+pair2+pair1+singles[0];    // two pair, + singles hand
    } else if (pair1!=0) {
        return "2."+pair1+singles.reverse().join("");          // one pair, + singles
    }
    return "1."+singles.reverse().join("");
}

function CardCount(cards) {
    var counts = {};
    for (var i=0, max = cards.length; max>i; i++) {
        if (typeof counts[ mapping[cards[i].charAt(0)] ]=="undefined")
            counts[ mapping[cards[i].charAt(0)] ]=0;
        counts[ mapping[cards[i].charAt(0)] ]++;
    }
    return counts;
}

// assumes the hand is sorted already in ascending order
// ace is assumed to be sorted with value of 1
function IsStraight(cards) {
    var start = mapping[cards[0].charAt(0)];
    var max=cards.length;
    var end = mapping[cards[max-1].charAt(0)];
    if (end==14&&start==2)
    {
        for (var i=1; ii; i++) {
        if (cards[i].charAt(1)!=suit)
            return false;
    }
    return true;
}

Taxes and the Weekend

Saturday

I watched 5 Centimeters Per Second. Very touching. I then played LoL for few hours. I finished the day by watching The Promised Lands with Matt Damon as the main protagonist.

Sunday

I went to SF and attended the Cherry Blossom Festival. It was not that festive in my opinion. I expected a little more cultural events. But then again, I guess I had a higher expectation since it was in San Francisco. I forget that the volunteer work that I did was at festivals just like the one I attended. But I got takoyaki and they were pretty scrumptious.

lol and pushups

So my friend wanted to “get into shape” so he is doing pushups. 3 for every kill he gets in a LoL game, 1 for every assist. I decided to join him.

I just got 20 kills and 11 assists in one game. That is 71 pushups. I have only done 53 of them and I am tired. It doesn’t help that I already did 60 today.

Shortest Path

So I am NOT SURE if this works. I did not run it yet. I just quickly coded it up and then am posting it here. I am feeling a bit off right now so I may or may not get back to this. This is a rough attempt at Dijkstra’s, which took around 15 or so minutes to do.

This has issues with creating the graph. You need to create it in a way so that the values of the nodes reflect the location of where it is in the nodeList array (or just add a reference to it). Otherwise it should be fine.

        function Graph() {
            this.nodeList = [];
            this.Insert = function(value) {
                this.nodeList.push(new Node(value));
            };
            this.MinPath = function() {
                var pathLength = [];
                var pathTaken = [];
                var inf = 1000000; // largest number ever
                for (var i=0, max=nodeList.length; i<max; i++) {        
                    pathLength[i]=inf;
                    pathTaken[i]=0;
                }

                var currentDistance = 0;
                for (var i=0, max=nodeList.length; i<max; i++) {
                    for (var j=0, maxJ=this.nodeList[i].edges.length; j<maxJ; j++) {                         currentNode = this.nodeList[i].edges[j].to;                         currentDistance = pathLengths[i]+this.nodeList[i].edges[j].weight;                         if (pathLength[currentNode] > currentDistance) {
                            pathLength[this.nodeList[i].edges[j].value] = currentDistance;
                            pathTaken[currentNode] = i;
                        }
                    }
                }
            };
        }
        function Node(value) {
            this.value = value;
            this.edges = [];
            this.Connect = function(weight, to) {
                var edge = new Edge(weight, to, this);
                this.edges.push(edge).sort(this.edgeCompare);
                // sort the edges here so we do not need to worry about it while doing min path.
            };
            this.edgeCompare = function(a,b) {
                if (a.weight < b.weight)                     return -1;                 if (a.weight > b.weight)
                    return 1;
                return 0;
            }
        }
        function Edge(weight, to, from) {
            this.weight = weight;
            this.to = to;
            this.from = from;
        }

Permutation

Let’s get permutations.

The unique function I added to the Array prototype is to make the array unique. I did not bother with creating permutations that were unique, so I just created all permutations and then used a bucket approach to eliminate duplicates. I wanted practice with more recursive problems.

Array.prototype.Unique = function() {
            var arrTemp = {};
            var arr = [];
            for (var i=0, max = this.length; i<max; i++) {
                arrTemp[this[i]] = 1;
            }
            for (var i in arrTemp) {
                arr.push(i);
            }
            return arr;
        };
        var line = "1233";

        console.log(Permutate(line.split("")).Unique());

        // assume it is sorted.
        function Permutate(letters,current) {
            if (letters.length==0)
                return [];
            if (letters.length==1)
                return letters;

            var result = [];
            for (var i=0, max = letters.length; i<max; i++) {
                var partial = Permutate(letters.slice(0,i).concat(letters.slice(i+1)),letters[i]);
                for (var j=0, maxJ = partial.length; j<maxJ; j++) {
                    if (current!=partial[j])
                        result.push(letters[i] + partial[j]);
                }
            }
            return result;
        }

Telephone Words

Challenge: https://www.codeeval.com/open_challenges/59/

Methodology:

Create a mapping for number -> letter. This is a 1 to many, so you will have to handle the many. This means doing a loop.

For ease of mind, I simplified the problem into subproblems, leading to a recursive solution. I looked at the problem by looking at what to do when given only 1 number, and then 2, and so on. With 1, you return the direct mapping result. With 2, you return the direct mapping of 1 concatenated with all the mappings of the 2nd digit. This means you have to do iterate through the original mapping and add that on to the 2nd digit. And then you continue to append the two to receive your final result.

Solution:

var line = "4155230";

mapping = [];
mapping[0] = ["0"];
mapping[1] = ["1"];
mapping[2] = ["a", "b", "c"];
mapping[3] = ["d", "e", "f"];
mapping[4] = ["g", "h", "i"];
mapping[5] = ["j", "k", "l"];
mapping[6] = ["m", "n", "o"];
mapping[7] = ["p", "q", "r", "s"];
mapping[8] = ["t", "u", "v"];
mapping[9] = ["w", "x", "y", "z"];

console.log(List(line.split("")));

function List(input) {
    var result = [];
    if (input.length==1)
    {
        return mapping[input[0]];
    }
    var res = List(input.slice(1));
    var map = mapping[input[0]];
    for (var i=0, max=map.length; i<max; i++) {
        for (var j=0, maxJ = res.length; j<maxJ; j++) {
            result.push(map[i]+res[j]);
        }
    }
    return result;
}

Longest Common Subsequence

function GetSubsequence(wordA, wordB) {
    var maxA = wordA.length;
    var maxB = wordB.length;
    
    var result = [];
    for (var i=0; i < maxA+1; i++) {
        result[i] = [];
        for (var j=0; j < maxB+1; j++) {
            result[i][j]=-1;
        }
    }
    // LCS(0,0);
    LCS();
    console.log(GenerateSubsequence());

    function GenerateSubsequence() {
        var s = "";
        var i=0, j=0;
        while (i < maxA && j < maxB) {
            if (wordA[i]==wordB[j]) {
                s = s + wordA[i];
                i++; j++;
            } else if (result[i+1][j] >= result[i][j+1]) i++;
            else j++;
        }
        return s;
    }
    
    // iterative, bottom-up
    function LCS() {
        for (var i=maxA; i >=0; i--) {
            for (var j=maxB; j >=0; j--) {
                if (i>=maxA || j>=maxB) {
                    result[i][j]=0;
                } else if (wordA[i]==wordB[j]) {
                    result[i][j] = 1 + result[i+1][j+1];
                } else {
                    result[i][j] = Max(result[i+1][j], result[i][j+1]);
                }
            }
        }
    }
    
    /*
    // recursive
    function LCS(i, j) {
        if (result[i][j] < 0) {
            if (i>=maxA || j>=maxB) {
                result[i][j]=0;
            } else if (wordA[i]==wordB[j]) {
                result[i][j] = 1 + LCS(i+1,j+1);
            } else {
                result[i][j] = Max(LCS(i+1, j), LCS(i, j+1));
            }
        }
        return result[i][j];
    }*/

    function Max(a, b) {
        if (a>b) return a;
        return b;
    }
}

In Time

Watched the movie In Time. The plot reminds me a bit like Bonnie and Clyde except set in a futuristic setting. The acting was sub-par. The lines were believable in the sense that I could see the average person saying them. But there weren’t any powerful lines.

The character development was pretty nil. You have a static antihero who is trying to save the world. You get a hint that it is in his blood, but that part is not gone into depth. You have the static cop, who it is later revealed grew up in the slums. It reminded me of Javert from Les Miserables. I think that side note of him having grown up in the slums and becoming a time keeper did not need to be announced, or else it should have been made light of earlier in the film. Having it revealed at the end did not add to the plot much, but having it earlier would have made the audience wonder more about the setting. They would not have seen such a one-sided view of the world. In this way, the whole movie would have been more relate-able and would have added a depth to the time keeper.

The movie was all right. Although not a blockbuster hit. The setting was interesting, but it is such a reminder of reality and how limited in time we are. While watching this film, I could not help but think about what other people thought while watching it. All I could think of was that this was a perfect metaphor for life. Everything you do costs you money, which is just a translation of our time. So in essence, we are selling our time. And we are very limited with it. I think having 25 years of life is better than average, in my opinion. 25 years where you do not need to work? Saying you start going to work right after school, that is 18 years of freedom. And saying how retirement programs are looking very bleak in the near future due to the idea that the younger generation will support the old is just expecting too much. That is 7 years additional that people get to bum around. All right, if you go to college and graduate in a reasonable number of years, you get out around 21 or 22. And let’s face it, undergraduate is pretty much a joke. So those years will count to you bumming around. So that’s up to 22. Then you start work. That means you only get 22 years of “freedom”. That is 3 less than the 25. I guess the straight up number of 26 years seems a bit small, but that is better than the average person.

I do not mean those people that can pay for things and retire at 65 or so, or after working 20-40 years. I am talking about the average joe, the person that has to work until they can’t work and then they require the support of others. Although I have a twisted view of that since I do not personally come from that. I work in a different industry and thus am paid a higher wage, whether or not it is reasonable is a different story entirely which I will not go into at the moment.

Any how, enough of the rant about how 25 years is pretty good. The movie was 5/10. It did not have much to it. No highlights that I can think of. It was not comical either. It tried to be a straight-up action film, but then attempted to add not-so-wise words of wisdom. If this was straight up action, with more explosions and gunfire, I might rate this higher. But the attempt of having a story made it worse, since it seemed half-way executed. The plot needed to be developed more, whether that meant 10 or so additional minutes of footage or replacement of a scene.

Longest Common Substring (LCS)

I misread a problem that was asking to solve for non-contiguous longest common substring so then I ended up with this longest common substring instead.

This solution uses a 2d array that is equal in dimensions of the 2 string lengths+1. [word.length+1][word2.length+1]

function LCS(a, b) {
	var arr = [];
	var substr;
	var substringMax = 0;
	var max_a = a.length+1;
	var max_b = b.length+1;

	for (var i=0; i < max_a; i++)
	{
		arr[i] = [];
		for (var j=0; j< max_b; j++) {
			arr[i][j] = 0;
		}
	}
	max_a--;
	max_b--;
	for (var i=0; i < max_a; i++) {
		for (var j=0; j<max_b; j++) {
 			if (a[i]==b[i]) {
 				arr[i+1][j+1]++;
 				if (arr[i+1][j+1] > substringMax) {
					substringMax = arr[i+1][j+1];
					substr = "";
					for (var x=0;x < substringMax; x++)
					{
						substr+=a[i+x];
					}
				}
			}
		}
	}
	return substr;
}