Category Archives: Code

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;
}

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;
    }
}

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;
}

Counting Primes

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

Methodology: Create a prime number list. Mechanism used: sieve. The only penalty of using a sieve is that you need to know what the upper bound. After creating the list, just look for up to the point of the lowest prime number that is greater to a. Check if that number is greater than b, if it is, then return 0. Otherwise increase a counter and count the number of prime numbers between the starting prime and a prime that is greater than the second number b.

var primes = PrimeListSieved(500000);

console.log(CountingPrimes(2,10));
function CountingPrimes(a, b) {
  var i;
  var count=0;
  for (i=0; a < primes[i]; i++);   if (primes[i]>b)
    return 0;
  count++;
  while (b > primes[i++]) {
    count++;
  }
  if (b==primes[i])
      count++;
  return count;
}

function PrimeListSieved(max) {
  var primesA=[];
  for (var i=0; i<max; i++) {
      primesA.push(null);
  }

  for (var i=2; i<max; i++) {
    if (primesA[i]==null) {
      for (var j=i+i; j < max; j+=i) {
        primesA[j] = "ASD";
      }
    }
  }

  var primes = [];
  for (var i=2; i<max; i++) {
      if (primesA[i]==null)
        primes.push(i);
  }
  return primes;
}

Longest Line

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

The first thing I look at was the input size. Since the input size is small, and the number of look-ups will probably not be saturated (first number!=max), this made sense NOT to sort the lengths.

If the sample size or was an unspecified number, sorting would be required. If the number was greater than 14, a non-quadratic sorting method would need to be written. If the sample size was less than that, an insertion sort or bubble sort could be used. But no sorting was required for this problem since the information was temporal.

The problem was pretty straight forward. Get the character count of each line and then find the longest ones. Loop through all the lines to grab the maximum. Output that and then remove it from the list, and repeat until the number of lines desired is reached.

function LongestLine(input) {
    var count = input[0];
    input.shift();
    var arr = input;
    var greatest = 0;
    var line = 0;

    var strLen = [];
    for (var i=0, max=arr.length; i<max; i++)     {         strLen.push(arr[i].length);     }          // do not sort (making an assumption that the number of look-ups are small     // which makes sense, because the maximum is the line numbers     // and for javascript, they said 7.     while (count-- > 0) {
        line = 0;
        greatest = 0;
        for (var i=0, max=strLen.length;i<max;i++) {             if (strLen[i] > greatest) {
                greatest = strLen[i];
                line = i;
            }
        }
        console.log(arr[line]);
        arr.splice(line,1);
        strLen.splice(line,1);
    }
}

Minimum Coins

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

Methodology: Have a running count of the number of coins, have a list sorted in descending order of the denominations, and have a count of the current value left over. Loop through the denominations and take away from the current value as many whole number of that denomination (just divide). Then find the remainder (modulus). Repeat until all denominations are done or until no more coin value.

function Coins(num) {
  var denomination = [5,3,1];
  var current = num;
  var number_of_coins = 0;
  for (var i=0, max=denomination.length; i < max && current > 0; i++) {
    number_of_coins += parseInt(current/denomination[i]);
    current=current%denomination[i];
  }
}