Mars Lander - Puzzle discussion

Hi everybody,
Level 1, Java - I’m trying to figure out how the actual Y is computed. The vertical speed in each round is the speed from previous round minus gravity (3.711) plus power (that’s correct, read numbers match). With this I would expect that Y is the Y from the previous round plus speed. But that’s somehow wrong.

For example, with no power, the speed after the first round is -3.711 (rounded to -4, matches the read value). And I expect Y to be 2496.289 (2500 + (-3.711)) and rounded to 2496. But the read value is 2498. What am I missing?

I have tried to divide the speed by 2, subtract 1/(round number) and few other adjustments, but my computations never match the Y given by the line reading.

3 Likes

The 3.711 is acceleration. At the start of the turn you are at 0, at the end you are at -3.711. During the turn you slowly change from one speed to the other. Your speed for the turn will be velocity + (acceleration/2), which gives 2500 + (0 + (-3.711/2)) = 2498.1445. Unfortunately the server only sends you the integer part so if you need an accurate position / velocity you need to track it yourself and ignore the server.

5 Likes

Awesome series. But why so few tests? I substituted my primitive inefficient algorithm from the 2nd to the 3rd episode, and received a 250XP freebie for passing the “half” of tests without any complicated mathematics :confused:

1 Like

I uses a physics approach as well, and I used EXCEL as a visualization tool for my algorithm which served me extremely well for quick tests :wink:

Critical for this algorithm is to know by when (how many seconds left) the lander will reach Ylanding based on current Yspeed and by when it will reach Xlanding based on current Xspeed. As both velocities vY and vX are limited, I also needed to calculate how many seconds to brake in X-direction to stay within landing limits of -20…20m/s and what this braking would do to the velocity in Y-direction.
To make it easier for me, I only allowed the most efficient rotate angles (45°, 0°, -45°) and built in an optimizer to find the best possible spot to land on within allowed X landing range.

The algorithm has just two outputs: modeFlagX and modeFlagY. modeFlagY is only set in case current vY is nearing maximum allowable Y-velocity based on time needed to reach destined X position and maximum Yspeed for landing (-40).
modeFlagX is just requesting the lander to accelerate, brake, or no change of direction needed based on target X. It will only allow to brake/accelerate if modeFlagY is NOT requesting to thrust upwards.

The algo for Level 2 DOES NOT NEED a pathfinding function yet, I will develop this for level3 later on.

I’ll post some snapshots once the forum lets me :wink:

3 Likes

@RoboStac’s post solved this for me. In my opinion, this behavior should have been better documented.

My new, working, state update looks like this:

thr = radians(thetan)
co = cos(thr)
si = -sin(thr)
vxn = clamp(vx+powern*si, -500, 500)
vyn = clamp(vy+powern*co+g, -500, 500)
xn = x+vx+0.5*powern*si
yn = y+vy+0.5*(powern*co+g)
fueln = fuel-powern
1 Like

Hi, I’m trying to solve episode 2 in JavaScript. But I’m kind of lost. I know The landing spot has two Y points equals. But, Do I have to find it before I start printing values, or I have to look for a spot as the shuttle goes throw.
How can I get this value. I don’t know how can I compare Y in Xinitial and Y in Xfinal (X + wide).

1 Like

Hi why won´t this work??

    // game loop
    while (true)
    {
        inputs = Console.ReadLine().Split(' ');
        int X = int.Parse(inputs[0]);
        int Y = int.Parse(inputs[1]);
        int hSpeed = int.Parse(inputs[2]); // the horizontal speed (in m/s), can be negative.
        int vSpeed = int.Parse(inputs[3]); // the vertical speed (in m/s), can be negative.
        int fuel = int.Parse(inputs[4]); // the quantity of remaining fuel in liters.
        int rotate = int.Parse(inputs[5]); // the rotation angle in degrees (-90 to 90).
        int power = int.Parse(inputs[6]); // the thrust power (0 to 4).
         
        // Write an action using Console.WriteLine()
        // To debug: Console.Error.WriteLine("Debug messages...");
        
        if (vSpeed < -38)
        {
            power = 3;
        }    
        else 
        {
            power = 0;
        }    
        


        // 2 integers: rotate power. rotate is the desired rotation angle (should be 0 for level 1), power is the desired thrust power (0 to 4).
        Console.WriteLine("0 power");
    }
}

}

1 Like

Define what “work” should do.

In your code, you modify the variable power but don’t use it afterwards.

1 Like

Hi, has anyone tried to solve this problem in Scala? I don’t know how codingames generates the code - and how it is vetted - but I’m under the impression the default Scala code is erroneous and I haven’t managed to make it run for me. Without adding any conditions there are three errors for me. The first one seemed to be a simple spelling mistake. The two other ones however I haven’t managed to solve. If anyone could give a helping hand, it’d be greatly appreciated.

2 Likes

you are right … there is a problem with the stub …

differents cases for the same variable

val surfaceN
until surfacen

problem with variable “X” and “Y” … works with “x” and “y” …
looks like scala does not like variables name beginning by uppercase (but i am not a scala expert)

2 Likes

There are errors in the script for Scala. This is the correction to get it to compile

import math._
import scala.util._
import scala.io.StdIn._

/**
 * Auto-generated code below aims at helping you parse
 * the standard input according to the problem statement.
 **/
object Player extends App {
    val surfaceN = readLine.toInt // the number of points used to draw the surface of Mars.
    for(i <- 0 until surfaceN) {
        // landX: X coordinate of a surface point. (0 to 6999)
        // landY: Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars.
        val Array(landX, landY) = (readLine split " ").map (_.toInt)
    }

    // game loop
    while(true) {
        // hSpeed: the horizontal speed (in m/s), can be negative.
        // vSpeed: the vertical speed (in m/s), can be negative.
        // fuel: the quantity of remaining fuel in liters.
        // rotate: the rotation angle in degrees (-90 to 90).
        // power: the thrust power (0 to 4).
        val Array(landX, landY, hSpeed, vSpeed, fuel, rotate, power) = (readLine split " ").map (_.toInt)
        
        // Write an action using println
        // To debug: Console.err.println("Debug messages...")
        

        // 2 integers: rotate power. rotate is the desired rotation angle (should be 0 for level 1), power is the desired thrust power (0 to 4).
        //println("0 3")

    }
}
2 Likes

Thank you for your help. Since I believe the landing coordinates are supposed to be different from the actual coordinates I chose the solution above, changing X and Y to x and y.

I’m pretty sure I tried changing the variable names to ‘a’ and ‘b’, but I thought it didn’t help.
Edit : just tried it again, and I must just have been confused, changing it to whatever lower case character works.

1 Like

Thanks for this 0.5 trick !

I have spent hours banging my head over my desk because the physics I had learn at high school were not working here. I agree with you : the specification does not explain it clearly. Unless it was a trap…

But I still do not catch everything… For instance, why didn’t you write

vxn = clamp(vx+0.5*powern*si, -500, 500)
vyn = clamp(vy+0.5*(powern*co+g), -500, 500)
xn = x+vxn
yn = y+vyn
1 Like

The velocity must be updated with the full power, not the half power. The 0.5 trick is to add the “direct” influence of the power on the position. Compare with the formula for constant acceleration:

s = s0 + v0*t + 0.5*a*t^2

Consider the case where t is 1:

s = s0 + v0 + 0.5*a

and apply this multiple times for different a:

s(n+1) = s(n) + v(n) + 0.5*a(n+1)

(-ish)

The speed update formula, on the other hand, is v = v0 + a*t, which simplifies to v = v0 + a for the t=1 case, or v(n+1) = v(n) + 0.5*a(n+1) for the iterative case.

1 Like

Maybe somebody will help, who is trying to use genetic algorythm, but could not pass test because of time limit. Try to rotate not by every degree, but by 2 (4,8) degrees, this decreases the number of populations to find the solution.

2 Likes

Same here when using Rust.

Running the solution locally with the cargo build --release flag runs 24 times faster.

[No full solution please.]

1 Like

I can’t arrive to slow the lander. Why ?
The $power stay at 3 !

while (TRUE)
{
fscanf(STDIN, “%d %d %d %d %d %d %d”, $X, $Y, $hSpeed, $vSpeed, $fuel, $rotate, $power);

if ($power < 4) {
    $power = $power + 1;
}

echo("0 3\n");

}

1 Like

you echo the constant 3 and not $power.

2 Likes

Ok, thanks for your answer.

1 Like

Hello, I am testing scala and by making mars lander ep01, there is a defect with the initial configuration, for the attribution of the variables x and y are written in capital letters which poses problem with the system, it would be necessary to put them in small letters.
good day to all.

2 Likes