// Learn more about F# at http://fsharp.net open System open System.Drawing open System.IO open System.Collections.Generic open System.Diagnostics open System.Windows.Forms let path = @"c:\bin1.obf" let scenarioID = 1001 [] type m [] type kg [] type radians let Distance (x:float, y:float) = (sqrt(x*x+y*y)) let ToPolar(x:float,y:float) = let angle = atan2 (y/1.0) (x/1.0) (Distance(x,y), angle*1.0) let ToRect(r:float,angle:float) = r * cos(angle/1.0), r * sin(angle/1.0) let GM = 6.67428e-11 * 6.0e24(**) let HohmannDeltaV1(r1:float,r2:float) = sqrt(GM/r1) * (sqrt(2.0 * r2/(r1 + r2)) - 1.0) * 1.0 let HohmannDeltaV2(r1:float,r2:float) = sqrt(GM/r2) * (1.0 - sqrt(2.0 * r1/(r1 + r2))) * 1.0 let HohmannTransfer (inputs:float [],outputs:float []) = seq { let S () = outputs.[2] * 1.0, outputs.[3] * 1.0 let V (x,y) = inputs.[2] <- -x/1.0; inputs.[3] <- -y/1.0 yield false let targetOrbitRadius = outputs.[4] * 1.0 let sx1, sy1 = S () yield false let sx2, sy2 = S () yield false let initialOrbitRadius = Distance(sx2, sy2) let vx = sx2 - sx1 let vy = sy2 - sy1 let v, theta = ToPolar(vx,vy) let deltav1 = HohmannDeltaV1(initialOrbitRadius, targetOrbitRadius) V (ToRect(deltav1,theta)) yield false V (0.0,0.0) let lastsx = ref (outputs.[2]*1.0) let lastsy = ref (outputs.[3]*1.0) while Distance(S ()) >= Distance(!lastsx,!lastsy) do let sx, sy = S () lastsx := sx lastsy := sy yield false done let sx, sy = S () let vx = sx - !lastsx let vy = sy - !lastsy let v, theta = ToPolar(vx,vy) let deltav2 = HohmannDeltaV2(initialOrbitRadius, targetOrbitRadius) V (ToRect(deltav2, theta)) yield false V (0.0, 0.0) for i = 1 to 10000 do yield outputs.[0] <> 0.0 done yield true } type addr = int type comp = | LTZ | LEZ | EQZ | GEZ | GTZ override this.ToString() = match this with | LTZ -> "<" | LEZ -> "<=" | EQZ -> "=" | GEZ -> ">=" | GTZ -> ">" static member Parse value = match value with | 0u -> LTZ | 1u -> LEZ | 2u -> EQZ | 3u -> GEZ | 4u -> GTZ | _ -> failwith "comp" member this.Op value = match this with | LTZ -> value < 0.0 | LEZ -> value <= 0.0 | EQZ -> value = 0.0 | GEZ -> value >= 0.0 | GTZ -> value > 0.0 type Instruction = | Add of addr * addr | Sub of addr * addr | Mult of addr * addr | Div of addr * addr | Output of addr * addr | Phi of addr * addr | Noop | Cmpz of comp * addr | Sqrt of addr | Copy of addr | Input of addr override this.ToString() = match this with | Add(r1,r2) -> sprintf "Add(%d,%d)" r1 r2 | Sub(r1,r2) -> sprintf "Sub(%d,%d)" r1 r2 | Mult(r1,r2) -> sprintf "Mult(%d,%d)" r1 r2 | Div(r1,r2) -> sprintf "Div(%d,%d)" r1 r2 | Output(r1,r2) -> sprintf "Output(%d,%d)" r1 r2 | Phi(r1,r2) -> sprintf "Phi(%d,%d)" r1 r2 | Noop -> "Noop" | Cmpz(comp,r1) -> sprintf "Cmpz(%O,%d)" comp r1 | Sqrt(r1) -> sprintf "Sqrt(%d)" r1 | Copy(r1) -> sprintf "Copy(%d)" r1 | Input(r1) -> sprintf "Input(%d)" r1 static member Execute (status, instructions:Instruction seq,mem:double [],input:double [], output:double []) = let out = mem instructions |> Seq.iteri (fun rd instruction -> match instruction with | Add(r1,r2) -> out.[rd] <- mem.[r1] + mem.[r2] | Sub(r1,r2) -> out.[rd] <- mem.[r1] - mem.[r2] | Mult(r1,r2) -> out.[rd] <- mem.[r1] * mem.[r2] | Div(r1,r2) -> out.[rd] <- if mem.[r2] = 0.0 then 0.0 else mem.[r1] / mem.[r2] | Output(r1,r2) -> output.[r1] <- mem.[r2] | Phi(r1,r2) -> out.[rd] <- if !status then mem.[r1] else mem.[r2] | Noop -> out.[rd] <- mem.[rd] | Cmpz(op,r1) -> status := op.Op(mem.[r1]) | Sqrt(r1) -> out.[rd] <- sqrt(mem.[r1]) | Copy(r1) -> out.[rd] <- mem.[r1] | Input(r1) -> out.[rd] <- input.[r1] ) static member Parse (value:UInt32) = let ParseSType () = let op = value >>> 24 let imm = (value >>> 21) &&& 0x7u let r = value &&& 0x3fffu |> int match op with | 0u -> Noop | 1u -> Cmpz(comp.Parse(imm), r) | 2u -> Sqrt(r) | 3u -> Copy(r) | 4u -> Input(r) | _ -> failwith "SType failed" let ParseDType () = let op = value >>> 28 let r1 = (value >>> 14) &&& 0x3fffu |> int let r2 = value &&& 0x3fffu |> int match op with | 1u -> Add(r1,r2) | 2u -> Sub(r1,r2) | 3u -> Mult(r1,r2) | 4u -> Div(r1,r2) | 5u -> Output(r1,r2) | 6u -> Phi(r1,r2) | _ -> failwith "DType failed" if value &&& 0xf0000000u = 0u then ParseSType () else ParseDType () let CreateSubmission (inputs:float [] seq) = use stream = File.Create (sprintf @"c:\%d.osf" scenarioID) let writer = new BinaryWriter(stream) // Write header writer.Write(0xCAFEBABE) let teamID = 15 writer.Write(teamID) writer.Write(scenarioID) // Write port set up writer.Write(0) // time step writer.Write(1) // count writer.Write(0x3e80) // port addr writer.Write(float scenarioID) // value // Write deltas from inputs let first = Seq.hd inputs let last = ref (Array.create first.Length 0.0) inputs |> Seq.iteri (fun timeStep values -> let deltas = List() values |> Seq.iteri (fun addr value -> if not (value = (!last).[addr]) then deltas.Add(addr,value) ) last := values if deltas.Count > 0 then writer.Write(timeStep) Debug.WriteLine(timeStep) writer.Write(deltas.Count) Debug.WriteLine(deltas.Count) deltas |> Seq.iter (fun (addr,value) -> writer.Write(addr) writer.Write(value) Debug.WriteLine(sprintf "%d %f" addr value) ) ) // Write Terminator let finalTimeStep = Seq.length inputs Debug.WriteLine(finalTimeStep) writer.Write(finalTimeStep+2) writer.Write(0) [] do use stream = File.OpenRead(path) let reader = new BinaryReader(stream) let mutable even = true let instructions = List() let data = List() while stream.Position < stream.Length do match even with | true -> data.Add(reader.ReadDouble()) instructions.Add(reader.ReadUInt32()) | false -> instructions.Add(reader.ReadUInt32()) data.Add(reader.ReadDouble()) even <- if even then false else true done //instructions |> Seq.map (fun o -> o.ToString("X")) |> Seq.iter Debug.WriteLine //data |> Seq.iter Debug.WriteLine let s = instructions |> Seq.map Instruction.Parse //s |> Seq.iter (fun i -> Debug.WriteLine(i)) let mem = data.ToArray() let input = Array.create 16384 0.0 input.[2] <- 0.0 input.[3] <- 0.0 input.[0x3e80] <- float scenarioID let output = Array.create 16384 0.0 let status = ref false let points = List() let targetOrbitRadius = ref 0.0 let inputs = List() let i = ref 0 HohmannTransfer (input, output) |> Seq.find (fun score -> Instruction.Execute(status, s, mem, input, output) points.Add(output.[2], output.[3]) targetOrbitRadius := output.[4] incr i //let values = output |> Seq.take 5 |> Seq.map (sprintf "%O") |> Seq.to_array //Debug.WriteLine(String.Join(", ", values)) //let x,y = output.[2], output.[3] //let l = sqrt(x*x + y*y) //Debug.WriteLine(l) inputs.Add(Seq.take 5 input |> Seq.to_array) score ) |> ignore Debug.WriteLine(sprintf "Score: %f" output.[0]) CreateSubmission inputs let width, height = 400.0, 400.0 let CreatePicture () = let maxx, maxy, minx, miny = points |> Seq.fold (fun (axx,axy,inx,iny) (x,y) -> (max axx x, max axy y, min inx x, min iny y) ) (0.0,0.0,0.0,0.0) let maxyy = max maxy (abs miny) let maxxx = max maxx (abs minx) let maxxy = max maxyy maxxx let maxxy = max maxxy !targetOrbitRadius let bm = new Bitmap(int width, int height) let gr = Graphics.FromImage (bm) gr.Clear(Color.Black) let Plot (gr:Graphics) (pen:Pen) r (x,y) = let xx = width/2.0 - (width/2.0 * x/maxxy) let yy = height/2.0 - (height/2.0 * y/maxxy) let rx = (width/2.0 * r/ maxxy) let ry = (height/2.0 * r / maxxy) gr.DrawEllipse(pen, int (xx-rx), int (yy-ry), int (rx*2.0), int (ry*2.0)) Plot gr (new Pen(Color.Yellow)) !targetOrbitRadius (0.0,0.0) Plot gr (new Pen(Color.Blue)) (6.37*1000000.0) (0.0,0.0) let r = maxxy / width let pen = new Pen(Color.White) points |> Seq.iter (Plot gr pen r) Seq.hd points |> Plot gr (new Pen(Color.Red)) r new PictureBox(Dock=DockStyle.Fill, Image=bm) let form = new Form(Width=(int width)+16, Height=(int height)+40) form.Controls.Add(CreatePicture ()) Application.Run(form)