Skip to content

Instantly share code, notes, and snippets.

@cooper6581
Created September 26, 2014 00:29
Show Gist options
  • Save cooper6581/04a9916be8ddccdd915f to your computer and use it in GitHub Desktop.
Save cooper6581/04a9916be8ddccdd915f to your computer and use it in GitHub Desktop.
Daily #181
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