Modifications of original code.
Functions were modified to generate the required outcome.
Jupyter used to test ideas. Project saved for viewing if required.
All bar the fourth passed the test
Notes test 4 which failed. Unable to get speed rounded to one decimal place. Comments online suggest this a common problem to do with floating point numbers. However, problem did not occur on my Mac.
Additional comments added to script.
"""Test equipment positions.""" from __future__ import annotations from collections import Counter, defaultdict import datetime as dt import math import numpy as np import pandas as pd from typing import Any from datetime import datetime # datetime required for calculation of time differences. def data_dict() -> defaultdict[str, Any]: """Return all equipment positions.""" d = defaultdict(list) d['T123'].append({'position': {'x': 42, 'y': 24, 'z': 0.42}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)}) d['T456'].append({'position': {'x': 21.0, 'y': 34, 'z': 0.289}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)}) d['T789'].append({'position': {'x': 17, 'y': 39, 'z': 0.789}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)}) d['T456'].append({'position': {'x': 91.0, 'y': 114, 'z': 0.489}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)}) d['T123'].append({'position': {'x': 43, 'y': 25, 'z': 0.43}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=1)}) d['T789'].append({'position': {'x': 19., 'y': 79, 'z': 0.991}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=6)}) d['T123'].append({'position': {'x': 46, 'y': 29, 'z': 0.44}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)}) d['T456'].append({'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)}) d['T123'].append({'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)}) d['T789'].append({'position': {'x': 23., 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)}) return d def latest_snapshot() -> defaultdict[str, Any]: """Return a snapshot of latest equipment.""" # put latest information into a defaultdict[list] list to match list type other def() such as data_dict #return { # 'T123': {'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)}, # 'T456': {'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)}, # 'T789': {'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)}, #} d = defaultdict(list) d['T123'].append({'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)}) d['T456'].append({'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)}) d['T789'].append({'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)}) return d def counts() -> dict[str, int]: """Return counts per equipment.""" return { 'T123': 4, 'T456': 3, 'T789': 3 } def speeds() -> defaultdict[str, Any]: """Return speeds of equipment.""" d = defaultdict(list) d['T123'].append({'speed': 4.242654947082074, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)}) d['T123'].append({'speed': 5.00000999999, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)}) d['T123'].append({'speed': 1.4142489172702237, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=1)}) d['T123'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)}) d['T456'].append({'speed': 102.0687849638664, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)}) d['T456'].append({'speed': 35.43388209045123, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)}) d['T456'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)}) d['T789'].append({'speed': 4.473538196997986, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)}) d['T789'].append({'speed': 6.6750796998987205, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=6)}) d['T789'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)}) return d def find_furthest_west(d: defaultdict) -> str: """ Find the name of the truck that is furthest west. That is, the truck with the smallest easting position component. """ # get most west truck min_lat = 180 truck = '' # truck number for key in d.keys(): a1 = d[key] posit = (a1.__getitem__(0))['position'] # get position lat_temp = posit['x'] if lat_temp < min_lat: # save truck number with lowest x (hence west) value. min_lat = lat_temp truck = key return truck def get_latest_snapshot(d: defaultdict) -> dict[str, Any]: """ Return a snapshot of the latest positional updates for the equipment. """ # get latest entry for each truck. e = defaultdict(list) for key in d.keys(): # Key is truck number truck = d[key] #print(len(truck)) count = 0 #print(range(len(truck))) for entry_n1 in range(len(truck)): # loop through all entries for a truck to get latest entry time_temp_n1 = (truck.__getitem__(entry_n1))['timestamp'] # get time information from list if count == 0: time_temp_n2 = time_temp_n1 entry_n2 = entry_n1 count = 1 else: if time_temp_n1 > time_temp_n2: time_temp_n2 = time_temp_n1 entry_n2 = entry_n1 # put latest entry in e list. e[key].append({'position':(truck.__getitem__(entry_n2))['position'],'timestamp':time_temp_n2}) return e def get_counts(d: defaultdict) -> dict[str, int]: """Return a dict of trucks and the times they have provided updates.""" e = {} for key in d.keys(): # key is the truck number. truck = d[key] no_entries = len(truck) # get number of entries per truck. e[key] = no_entries return(e) def calculate_speeds(d: defaultdict) -> defaultdict[str, Any]: """Return a dict of equipment and the speeds they are travelling at.""" # Select a truck, order entries by time, calculate difference in time and space, calculate the speed. # No units is given so no conversion in speed is done. Speed in distance / second. e = defaultdict(list) for key in d.keys(): truck = d[key] truck_ordered = truck.sort(key=lambda x:x['timestamp']) # order truck time # get position and time difference. Calculuate speed. no_entries = len(truck) count = 0 len_n1 = len(truck) for entry_n1 in range(len_n1): time_temp_n1 = (truck.__getitem__(entry_n1))['timestamp'] # get time position_temp_n1 = (truck.__getitem__(entry_n1))['position'] # get position if count == 0: e[key].append({'speed':None,'timestamp':time_temp_n1}) # first time entry, set speed to None. count = 1 else: time_temp_n2 = (truck.__getitem__(entry_n1 + 1))['timestamp'] position_temp_n2 = (truck.__getitem__(entry_n1 + 1))['position'] # get spatial difference x_diff = abs(position_temp_n2['x'] - position_temp_n1['x']) y_diff = abs(position_temp_n2['y'] - position_temp_n1['y']) distance = math.sqrt((x_diff * x_diff) + (y_diff * y_diff)) # get temporal difference time_diff = abs((time_temp_n1 - time_temp_n2).total_seconds()) # calculate speed speed = round((distance / time_diff),1) # round to 1 decimal place e[key].append({'speed':speed,'timestamp':time_temp_n1}) count = count + 1 # Break loop if count == len_n1 - 1: break return e
- """Test equipment positions."""
- from __future__ import annotations
- from collections import Counter, defaultdict
- import datetime as dt
- import math
- import numpy as np
- import pandas as pd
- from typing import Any
- from datetime import datetime # datetime required for calculation of time differences.
- def data_dict() -> defaultdict[str, Any]:
- """Return all equipment positions."""
- d = defaultdict(list)
- d['T123'].append({'position': {'x': 42, 'y': 24, 'z': 0.42}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
- d['T456'].append({'position': {'x': 21.0, 'y': 34, 'z': 0.289}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
- d['T789'].append({'position': {'x': 17, 'y': 39, 'z': 0.789}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
- d['T456'].append({'position': {'x': 91.0, 'y': 114, 'z': 0.489}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
- d['T123'].append({'position': {'x': 43, 'y': 25, 'z': 0.43}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=1)})
- d['T789'].append({'position': {'x': 19., 'y': 79, 'z': 0.991}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=6)})
- d['T123'].append({'position': {'x': 46, 'y': 29, 'z': 0.44}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)})
- d['T456'].append({'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
- d['T123'].append({'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
- d['T789'].append({'position': {'x': 23., 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
- return d
def latest_snapshot() -> dict[str, Any]:- def latest_snapshot() -> defaultdict[str, Any]:
- """Return a snapshot of latest equipment."""
return {'T123': {'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)},'T456': {'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)},'T789': {'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)},}- # put latest information into a defaultdict[list] list to match list type other def() such as data_dict
- #return {
- # 'T123': {'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)},
- # 'T456': {'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)},
- # 'T789': {'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)},
- #}
- d = defaultdict(list)
- d['T123'].append({'position': {'x': 49.0, 'y': 32, 'z': 0.451}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
- d['T456'].append({'position': {'x': 24.0, 'y': 37, 'z': 0.297}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
- d['T789'].append({'position': {'x': 23.0, 'y': 81, 'z': 1.103}, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
- return d
- def counts() -> dict[str, int]:
- """Return counts per equipment."""
- return {
- 'T123': 4,
- 'T456': 3,
- 'T789': 3
- }
- def speeds() -> defaultdict[str, Any]:
- """Return speeds of equipment."""
- d = defaultdict(list)
- d['T123'].append({'speed': 4.242654947082074, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
- d['T123'].append({'speed': 5.00000999999, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)})
- d['T123'].append({'speed': 1.4142489172702237, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=1)})
- d['T123'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
- d['T456'].append({'speed': 102.0687849638664, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
- d['T456'].append({'speed': 35.43388209045123, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
- d['T456'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
- d['T789'].append({'speed': 4.473538196997986, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
- d['T789'].append({'speed': 6.6750796998987205, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=6)})
- d['T789'].append({'speed': None, 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=0)})
- return d
- def find_furthest_west(d: defaultdict) -> str:
- """
- Find the name of the truck that is furthest west. That is,
- the truck with the smallest easting position component.
- """
return ''- # get most west truck
- min_lat = 180
- truck = '' # truck number
- for key in d.keys():
- a1 = d[key]
- posit = (a1.__getitem__(0))['position'] # get position
- lat_temp = posit['x']
- if lat_temp < min_lat: # save truck number with lowest x (hence west) value.
- min_lat = lat_temp
- truck = key
- return truck
- def get_latest_snapshot(d: defaultdict) -> dict[str, Any]:
- """
- Return a snapshot of the latest positional updates for the
- equipment.
- """
return {}- # get latest entry for each truck.
- e = defaultdict(list)
- for key in d.keys(): # Key is truck number
- truck = d[key]
- #print(len(truck))
- count = 0
- #print(range(len(truck)))
- for entry_n1 in range(len(truck)): # loop through all entries for a truck to get latest entry
- time_temp_n1 = (truck.__getitem__(entry_n1))['timestamp'] # get time information from list
- if count == 0:
- time_temp_n2 = time_temp_n1
- entry_n2 = entry_n1
- count = 1
- else:
- if time_temp_n1 > time_temp_n2:
- time_temp_n2 = time_temp_n1
- entry_n2 = entry_n1
- # put latest entry in e list.
- e[key].append({'position':(truck.__getitem__(entry_n2))['position'],'timestamp':time_temp_n2})
- return e
- def get_counts(d: defaultdict) -> dict[str, int]:
- """Return a dict of trucks and the times they have provided updates."""
return {}- e = {}
- for key in d.keys(): # key is the truck number.
- truck = d[key]
- no_entries = len(truck) # get number of entries per truck.
- e[key] = no_entries
- return(e)
- def calculate_speeds(d: defaultdict) -> defaultdict[str, Any]:
- """Return a dict of equipment and the speeds they are travelling at."""
return defaultdict(list)- # Select a truck, order entries by time, calculate difference in time and space, calculate the speed.
- # No units is given so no conversion in speed is done. Speed in distance / second.
- e = defaultdict(list)
- for key in d.keys():
- truck = d[key]
- truck_ordered = truck.sort(key=lambda x:x['timestamp']) # order truck time
- # get position and time difference. Calculuate speed.
- no_entries = len(truck)
- count = 0
- len_n1 = len(truck)
- for entry_n1 in range(len_n1):
- time_temp_n1 = (truck.__getitem__(entry_n1))['timestamp'] # get time
- position_temp_n1 = (truck.__getitem__(entry_n1))['position'] # get position
- if count == 0:
- e[key].append({'speed':None,'timestamp':time_temp_n1}) # first time entry, set speed to None.
- count = 1
- else:
- time_temp_n2 = (truck.__getitem__(entry_n1 + 1))['timestamp']
- position_temp_n2 = (truck.__getitem__(entry_n1 + 1))['position']
- # get spatial difference
- x_diff = abs(position_temp_n2['x'] - position_temp_n1['x'])
- y_diff = abs(position_temp_n2['y'] - position_temp_n1['y'])
- distance = math.sqrt((x_diff * x_diff) + (y_diff * y_diff))
- # get temporal difference
- time_diff = abs((time_temp_n1 - time_temp_n2).total_seconds())
- # calculate speed
- speed = round((distance / time_diff),1) # round to 1 decimal place
- e[key].append({'speed':speed,'timestamp':time_temp_n1})
- count = count + 1
- # Break loop
- if count == len_n1 - 1:
- break
- return e
import codewars_test as test import solution # or from solution import example # test.assert_equals(actual, expected, [optional] message) @test.describe("Example") def test_group(): @test.it('test find_furthest_west') def test_cases(): d = data_dict() #e = find_furthest_west(d) # for testing, get furthest west #print(e) test.assert_equals(find_furthest_west(d), 'T789') @test.it('test get_latest_snapshot') def test_get_latest_snapshot(): d = data_dict() snapshot = latest_snapshot() # For testing #print(snapshot) # get latest snapshot. #test = get_latest_snapshot(d) # get latest for each truck in list d. #print(test) # compare latest snapshot entries with the latest truck entries in data dict test.assert_equals(get_latest_snapshot(d), snapshot) @test.it('test get_counts') def test_get_count(): d = data_dict() the_counts = counts() # for testing #print(the_counts) #print(get_counts(d)) # get the number of times a truck is in d. test.assert_equals(get_counts(d), the_counts) @test.it('test calculate_speeds') def test_calculate_speeds(): d = data_dict() the_speeds = speeds() # for testing #print(the_speeds) #print("===") #print(calculate_speeds(d)) #print("+++") test.assert_equals(calculate_speeds(d), the_speeds)
- import codewars_test as test
- import solution # or from solution import example
- # test.assert_equals(actual, expected, [optional] message)
- @test.describe("Example")
- def test_group():
- @test.it('test find_furthest_west')
- def test_cases():
- d = data_dict()
- #e = find_furthest_west(d) # for testing, get furthest west
- #print(e)
- test.assert_equals(find_furthest_west(d), 'T789')
- @test.it('test get_latest_snapshot')
- def test_get_latest_snapshot():
- d = data_dict()
- snapshot = latest_snapshot()
- # For testing
- #print(snapshot) # get latest snapshot.
- #test = get_latest_snapshot(d) # get latest for each truck in list d.
- #print(test)
- # compare latest snapshot entries with the latest truck entries in data dict
- test.assert_equals(get_latest_snapshot(d), snapshot)
- @test.it('test get_counts')
- def test_get_count():
- d = data_dict()
- the_counts = counts()
- # for testing
- #print(the_counts)
- #print(get_counts(d)) # get the number of times a truck is in d.
- test.assert_equals(get_counts(d), the_counts)
- @test.it('test calculate_speeds')
- def test_calculate_speeds():
- d = data_dict()
- the_speeds = speeds()
- # for testing
- #print(the_speeds)
- #print("===")
- #print(calculate_speeds(d))
- #print("+++")
- test.assert_equals(calculate_speeds(d), the_speeds)