Created
September 26, 2014 00:29
-
-
Save cooper6581/04a9916be8ddccdd915f to your computer and use it in GitHub Desktop.
Daily #181
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"bufio" | |
"os" | |
"regexp" | |
"strconv" | |
"time" | |
) | |
func find_speeders(lines []string) { | |
speed_limit, mph := parse_speed_limit(lines[0]) | |
cameras := parse_cameras(lines[1:]) | |
cars := parse_cars(lines[1:], len(cameras)) | |
for car := range(cars) { | |
for camera := 0; camera < len(cameras) - 1; camera++ { | |
delta := cars[car][camera+1] - cars[car][camera] | |
speed := (3600.0 / delta) * (cameras[camera+1] - cameras[camera]) | |
units := "mph" | |
if !mph { | |
units = "kph" | |
speed /= 1000 | |
} else { | |
speed *= 0.000621371 | |
} | |
if speed > speed_limit { | |
fmt.Printf("Vehicle %s broke the speed limit by %.02f %s.\n", | |
car, speed - speed_limit, units) | |
} | |
} | |
} | |
} | |
func parse_speed_limit(line string) (float64, bool) { | |
speed_re := regexp.MustCompile("Speed limit is (.*) (.*)\\.") | |
res := speed_re.FindStringSubmatch(line) | |
speed, err := strconv.ParseFloat(res[1], 64) | |
if err != nil { | |
panic(err) | |
} | |
mph := true | |
if res[2] != "mph" { | |
mph = false | |
} | |
return speed, mph | |
} | |
func parse_cameras(lines []string) []float64 { | |
//Note: This will break if cameras distances aren't listed in order | |
cameras := make([]float64, 0, 8) | |
camera_re := regexp.MustCompile("Speed.*is (\\d+).*.") | |
for _, line := range(lines) { | |
if res, _ := regexp.MatchString("Start of log for camera.*", line); res == true { | |
break | |
} | |
distance, err := strconv.ParseFloat(camera_re.FindStringSubmatch(line)[1], 64) | |
if err != nil { | |
panic(err) | |
} | |
cameras = append(cameras, distance) | |
} | |
return cameras | |
} | |
func parse_cars(lines []string, cameras int) map[string][]float64 { | |
cars := make(map[string][]float64) | |
for _, line := range(lines) { | |
// skip lines that we can't parse | |
if res, _ := regexp.MatchString("Vehicle .*", line); res == false { | |
continue | |
} | |
plate, camera, log := parse_log_line(line) | |
_, ok := cars[plate] | |
if !ok { | |
cars[plate] = new_car(camera, log, cameras) | |
} else { | |
cars[plate][camera] = log | |
} | |
} | |
return cars | |
} | |
func new_car(camera int64, log float64, number_of_cameras int) []float64 { | |
logs := make([]float64, number_of_cameras) | |
logs[camera] = log | |
return logs | |
} | |
func parse_log_line(line string) (string, int64, float64) { | |
car_re := regexp.MustCompile("Vehicle (.*) passed camera (.*) at (.*).") | |
res := car_re.FindStringSubmatch(line) | |
camera, perr := strconv.ParseInt(res[2], 10, 64) | |
if perr != nil { | |
panic(perr) | |
} | |
// convert string into Time so we can return epoch | |
t, terr := time.Parse("15:04:05", res[3]) | |
if terr != nil { | |
panic(terr) | |
} | |
return res[1], camera - 1, float64(t.Unix()) | |
} | |
func read_lines(file_name string) []string { | |
lines := make([]string, 0, 1024) | |
fh, err := os.Open(file_name) | |
if err != nil { | |
panic(err) | |
} | |
scanner := bufio.NewScanner(fh) | |
for scanner.Scan() { | |
lines = append(lines, scanner.Text()) | |
} | |
return lines | |
} | |
func main() { | |
if len(os.Args) != 2 { | |
fmt.Println("Usage:", os.Args[0], "<filename>") | |
os.Exit(1) | |
} | |
lines := read_lines(os.Args[1]) | |
find_speeders(lines) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment