IFCP 2009 - O final
Autor: Rafael Gustavo | Publicado: 2009-11-10T13:09:00-02:00

Desculpe desapontá-los, mas abandonei o projeto de terminar o problema do ICFP2009 antes do final do ano. Na verdade, fiquei um pouco aborrecido pois queria ter implementado um visualizador das órbitas, e não estou com tempo de aprender OpenGL.Coloco aqui a última versão do código de transferência entre órbitas. O algoritmo é bastante simples: uma outra mônada RWS que envolve o IO, apenas para escrever a saída na tela. Ainda não critico o final da execução e nem escrevo o arquivo de saída no formato do problema, mas dá para se divertir vendo a distância entre o satélite e a órbita destino diminuindo!! Aproveitem!module Main whereimport System.IO import System.Environmentimport Control.Monad.RWSimport qualified Data.ByteString.Lazy as BLimport OBFFileimport Vectorimport OBFProgramimport OBFDataimport OVM--                Read       Write               State         --                Program    Time,Input         Time,VMInput,Memorytype SimVM a=RWST (OVM())   [(Integer,OBFData)] (Integer,OBFData,OBFData) IO amain::IO ()main=do         (fn:scene:args)&lt;-getArgs        withBinaryFile fn ReadMode (readAndRun (read scene))  readAndRun::Double-&gt;Handle-&gt;IO ()readAndRun s h=    do        (p,d)&lt;-readOBFFile h        let i=singleton 0x3e80 s        dum&lt;-case s of                s | s&gt;=1000 &amp;&amp; s&lt;2000 -&gt;print "Hohmann"                s | s&gt;=2000 &amp;&amp; s&lt;3000 -&gt;print "Meet and Greet"                s | s&gt;=3000 &amp;&amp; s&lt;4000 -&gt;print "Eccentric Meet and Greet"                s | s&gt;=4000 &amp;&amp; s&lt;5000 -&gt;print "Operation Clear Skies"                s | s&gt;=5000 &amp;&amp; s&lt;6000 -&gt;print "Operation Dance with Stars"        ret&lt;-execSim hohmannSim p i d        print retexecSim::SimVM()-&gt;OVM()-&gt;OBFData-&gt;OBFData-&gt;IO [(Integer,OBFData)]execSim s p i d=liftM snd $ execRWST s p (0,i,d)hohmannSim::SimVM ()hohmannSim=     do               i&lt;-gets (input)        (co ,v, tgt )&lt;-getPositionSpeedTarget        let (dv1,dv2,tof_d)=calcHohmann co tgt        let tof=floor tof_d ::Int                liftIO $ print $ "targetOrbit="++show(tgt)        liftIO $ print $ show(tgt&gt;co)        liftIO $ print $ "currentSpeed="++show(v)        liftIO $ print $ "dV1="++show(dv1)        liftIO $ print $ "dV2="++show(dv2)        liftIO $ print $ "tof_d="++show(tof_d)        liftIO $ print $ "tof="++show(tof)        let (dx1,dy1)=colinearVector dv1 v         liftIO $ print $ "deltaVector="++show(dx1,dy1)        let i'=i `union` (fromList [(2,dx1),(3,dy1)])        applyInput i'        (_,_)&lt;-stepOVM        applyInput i        replicateM_ (tof-4) stepOVM        (co ,v, tgt )&lt;-getPositionSpeedTarget        let (dx2,dy2)=colinearVector dv2 v        let i'=i `union` (fromList [(2,dx2),(3,dy2)])        applyInput i'        (_,_)&lt;-stepOVM        applyInput i        replicateM_ (1000) stepOVM        return ()    where        input (t,i,d)=i        time  (t,i,d)=t        memory(t,i,d)=d    getPositionSpeedTarget::SimVM (Double, Vector Double,Double)getPositionSpeedTarget=do        (t ,o )&lt;-stepOVM        (t ,o')&lt;-stepOVM        return (currOrbit o', currSpeed o o', o'!-!4)stepOVM::SimVM (Integer,OBFData)stepOVM=do    p&lt;-ask    (t,i,d)&lt;-get    let (d',o)=execOVM p d i    put ((t+1),i,d')    let co=currOrbit o    let tgto=o!-!4    liftIO $ print $ "-------------- At time "++show (t+1)++" --------------"    liftIO $ print $ "Score: "++show(o!-!0)    liftIO $ print $ "Fuel: "++show(o!-!1)    liftIO $ print $ "Position: "++show(myPosition o)    liftIO $ print $ "Current Orbit: "++show(co)    liftIO $ print $ "Target Orbit: "++show(tgto)    liftIO $ print $ "Distance to go: "++show(tgto-co)    return ((t+1),o)applyInput::OBFData-&gt;SimVM()applyInput=modify.changeInput    where         changeInput i (t,_,d)=(t,i,d)    myPosition::OBFData-&gt;Vector DoublemyPosition = liftM2 (,) (!-!2) (!-!3)    currOrbit::OBFData-&gt;DoublecurrOrbit=magnitude.myPositioncurrSpeed::OBFData-&gt;OBFData-&gt;Vector DoublecurrSpeed a b=diff (myPosition a) (myPosition b){- Helpful constants -}earthMu= constG * earthM constG = 6.67428e-11 ::DoubleearthM = 6.00000e24  ::DoubleearthR = 6.357e6     ::Double{- returns the delta-vs and time of flight of a hohmann transfer   between two circular orbits. -}calcHohmann::Double-&gt;Double-&gt;(Double,Double,Double)calcHohmann r1 r2=(dv1,dv2,tof)    where        dv1=(f r1)*((g r2)-1)        dv2=(f r2)*(1-(g r1))        tof=pi*sqrt((a^3)/earthMu)        a=(r1+r2)/2        f x=sqrt (earthMu/x)        g x=sqrt (x/a)PS: Vector é um type synonim para (Int,Int)!