Wednesday, March 26, 2014

Hack 77 - I didn't lie

I solved problem 77 in a language called Hack (hacklang.org), which, in the trend of languages that attempt to be "language X but with change Y", is an attempt at making a better version of PHP where it is harder to shoot yourself in the foot. It has type annotations, so it might succeed at that, though I didn't have enough time to see if those annotations actually lead to good static type checking. Anyway, Problem 77 is the type of problem that, if I didn't have to switch languages all the time, would have taken very little effort, but it still didn't take that much effort because it was pretty easy to create my solution to this problem from the last. Still dynamic programming, still similar probably of counting the ways to write a number as a sum. Because I had a pretty crazily high upper bound on my search (1000), this runs in .4s on my machine, searching only up to 100 gives a 4x speedup. Even though I haven't used PHP much, didn't have too many problems with Hack: main problems were a) it took something like 5 hours to install, b) Forget semicolons as I was moving from Python and Forth, and c) Of course I dropped some $'s, I personally think that if I were to make a "better PHP", the $'s would have been one of the first things I would have cut, it seems pretty clear from all the non-Perl, non-PHP languages out there that people generally don't want/need special characters to denote variables. (Also, no, that is not a typo, hack files begin with <?hh but have no closing >).
<?hh

function isPrime(int $x): int {
    if ($x < 2) {
        return false;
    } else if ($x % 2 == 0) {
        return $x == 2;
    }

    for ($i = 3; $i*$i <= $x; $i+=2) {
        if ($x % $i == 0) {
            return false;
        }
    }
    return true;
}

$count = Vector<Vector<int>>{ } ;
$BOUND = 1000;

for ($i = 0; $i < $BOUND; $i++) {
    $count[] = Vector<int>{};
    for ($j = 0; $j < $BOUND; $j++) {
        $count[$i][] = 0;
    }
}

for ($i = 0; $i < $BOUND; $i++) {
    for ($j = 0; $j < $BOUND; $j++) {
        if ($i == 2 or ($j == 2 and $i % 2 == 0)) {
            $count[$i][$j] = 1;
        } else if ($i < 2 or $j < 2) {
            $count[$i][$j] = 0;
        } else if ($j >= $i) {
            $count[$i][$j] = $count[$i][$i-1];
            if (isPrime($i)) {
                $count[$i][$j] += 1;
            }
        } else if (isPrime($j)) {
            $count[$i][$j] = $count[$i - $j][$j] + $count[$i][$j - 1];
            if ($count[$i][$j] > 5000) {
                echo $i . "\n";
                $i = $BOUND;
                $j = $BOUND;
            }
        } else {
            $count[$i][$j] = $count[$i][$j - 1];
        }
    }
}


No comments:

Post a Comment