4
\$\begingroup\$

This problem:

The Shallow Alto city council has organized a special committee to review the traffic situation in the city. Despite the fact that there is nothing whatsoever to do in the city, citizens still write complaints about the amount of time it takes them to get from one unexciting location to the next. The committee has been asked to figure out how long it takes someone to travel down the streets of Shallow Alto given the current traffic light programming. To do this, they want you to write an algorithm which, given the speed a car travels down a road and the timing of the traffic lights, returns the amount of time it takes the car to travel down the street. The traffic lights will be in an int[], with each element representing the amount of time in seconds between signal changes. Initially, all traffic lights have just turned green, and are at the beginning of their cycle. The order of the traffic lights in the int[] will be the order in which a car encounters them. The speed you will be given is in meters per second. Assume that the car starts 150 meters before the first traffic light, that there are 150 meters between each traffic light, and that the car stops 150 meters after the last traffic light. Disregard all acceleration and deceleration; a car is either at its given speed or entirely stopped, and it takes no time to go from one state to the other. If a car reaches a traffic light just as it turns red, it immediately stops and waits for it to turn green again (at which point it starts moving immediately). If the light just turned green, there is no wait and the car drives on through. Return the time, in seconds, that it takes the car to travel the entire distance. Round down any fractional parts, (for example 55.5 becomes 55 and 44.9 becomes 44), but do not do this until returning.

But in F# instead of C#:

namespace TrafficFlow

module Traffic = 

    let isGreen currentTime switchItme =
        let state = int currentTime / int switchItme
        state % 2 = 0

    let waitTime (currentTime : float) switchTime =  
        match (isGreen currentTime switchTime) with
            | false -> if (currentTime % switchTime) < 0.01 then switchTime else currentTime % switchTime
            | _ -> 0.0


    let time distanceBetween speed  (lights : seq<int>) =
        let timeBetween = float distanceBetween / float speed
        (lights |> Seq.fold (fun acc x -> float acc + timeBetween + waitTime acc (float x) ) timeBetween)

open Traffic 
open System   

module Program =

    [<EntryPoint>]
    let main argv = 

        let distance = 150        

        printf "0) time: %d\n" (int (time distance 30  [10; 10; 10]))
        printf "1) time: %d\n" (int (time distance 20  [10; 10; 10]))
        printf "2) time: %d\n" (int (time distance 20  [10; 20; 30]))
        printf "3) time: %d\n" (int (time distance 5  [10; 11; 12; 13; 14; 15]))
        printf "4) time: %d\n" (int (time distance 5  [60; 60; 60; 60; 60; 60; 60; 60; 60; 60]))
        printf "5) time: %d\n" (int (time distance 25  [55;29;26;12;19;39;18;20;23;28;56;20;59;48;33;40;30;60;19]))

        Console.ReadLine() |> ignore

        0 // return an integer exit code
\$\endgroup\$
2
\$\begingroup\$

This looks very clean and simple, which is always* a good thing when programming. First, you don't save state, nor do you have long functions--each function does what says in a couple lines. One nitpick is your naming:

let isGreen currentTime switchItme

switchItme should probably be switchTime.

You indented the conditions of your match statement too far. That should be indented as:

match (isGreen currentTime switchTime) with
| false -> if (currentTime % switchTime) < 0.01 then switchTime else currentTime % switchTime
| _ -> 0.0

In F#, you typically don't use if statements, except for choosing a path based on the value of a boolean literal, and I only do that when I can use it like a C# ternary. I would write the match in your second function as:

match (isGreen currentTime switchTime) with
| true -> 0.0
| false ->
    match (currentTime % switchTime) with
    | c when c < 0.01 -> switchTime
    | _ -> currentTime % switchTime

F# has a printfn function that is the same as printf, except it prints a newline at the end. You should use this instead of manually specifying you want a newline with printf "...\n"

* Well, sometimes complicated, fast code is better in performance-critical environments.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.