import Jam
import Data.List
import Data.Maybe
main = jam $ do
w <- gets
let
dict = case nub w of [d] -> ['?', d]
(d0:d1:ds) -> d1:d0:ds
pure . show
$ foldl (\n d -> n * length dict + fromJust (d `elemIndex` dict)) 0 w
All Your Base
We already solved this recommended beginner problem, but we’ll write it again using our Jam monad:
Center of Mass
A little algebra shows the distance of the center of mass from the origin,
is a quadratic equation in t, with a positive leading coefficient.
Differentiating with respect to t, or just by completing the square,
the minimum occurs when:
xs*vxs + ys*vys + zs*vzs == (vxs^2 + vys^2 + vzs^2) t
where xs ys zs vxs vys vzs are the sum of each of the six numbers, that is
the three position coordinates and the three velocity coordinates, across all
fireflies.
We are only interested in t >= 0 so if the minimum is attained for a negative
t value, we clip it to t = 0. The leading cofficient is positive, hence the
parabola opens upward, which implies the distance is smallest when t = 0 for
this case. Thus:
import Jam
import Control.Monad
import Data.List
import Text.Printf
main = jam $ do
[n] <- getints
(ps, vs) <- splitAt 3 . foldl1' (zipWith (+)) <$> replicateM n getdbls
let
t0 = max 0 $ -(sum $ zipWith (*) ps vs) / (sum $ (^2) <$> vs)
d0 = sqrt $ sum $ map ((^2) . (/ fromIntegral n)) $
zipWith (+) ps $ map (*t0) vs
pure $ printf "%.7f %.7f" d0 t0
We have gratuitiously applied list functions like sum and zipWith to avoid
explicitly mentioning the three coordinates.
Bribe the Prisoners
Suppose we release some prisoner first. Once done, the prisoners on one side can no longer communicate with those on the other.
Thus, the minimum total cost is the number of filled cells in a row on either side, plus the sum of the two solutions to smaller instances of the same problem, namely, the sum of the minimum costs to release the remaining prisoners on each side of the released prisoner considered independently.
We turn this observation into a dynamic programming solution. We use
sentinel values 0 and p + 1 to remove special cases with the edges of
the priosn. Then, we consder releasing each prisoner in turn, relying on
a memoized recursion to solve the subproblems, and return the cheapest
solution, or 0 if there is nothing to do.
import Jam
import Data.Array
import Data.Maybe
import Data.MemoTrie
import Safe
main = jam $ do
[p, _] <- getints
qs <- getints
let
a = listArray (0, length qs + 1) $ (0:qs) ++ [p+1]
f(i, j) = fromMaybe 0 $ foldl1May' min
[a!j - a!i - 2 + g(i, k) + g(k, j) | k <- [i+1..j-1]]
g = memo f
pure $ show $ g $ bounds a