Ad
Code
Diff
  • def find_multiples_of_4_and_6(n):
        for i in range(n):
            if not (i % 4 and i % 6):
                yield i
    
    • find_multiples_of_4_and_6 = lambda n : [i for i in range(n) if not (i % 4 and i % 6)]
    • def find_multiples_of_4_and_6(n):
    • for i in range(n):
    • if not (i % 4 and i % 6):
    • yield i

Form follows function

Code
Diff
  • def find_multiples_of_4_and_6(n): 
        return [i for i in range(n) if not (i % 4 and i % 6)]
    • def find_multiples(n):
    • return sum(0 if i % 4 and i % 6 else i for i in range(n))
    • def find_multiples_of_4_and_6(n):
    • return [i for i in range(n) if not (i % 4 and i % 6)]

"Don't bore us, get to the chorus" - Dave Grohl (Flipped the ternary)

"Drop that Zero" - Denise Lasalle (Truth implied by presence)

Code
Diff
  • def spawn_to_range(a, x, n):
        return a[:a.index(x)] + [x]*n + a[a.index(x)+1:] if len(a) else []
    • def spawn_to_range(a, x, n):
    • return [] if(len(a)==0) else a[0:a.index(x)] + [x]*n + a[a.index(x)+1:]
    • return a[:a.index(x)] + [x]*n + a[a.index(x)+1:] if len(a) else []

Refactored the data-gen methods to use some lambdas and a Datastruct that should make the whole block easier to read and easier to update/extend later.

Refactored calculate_speeds. Instead of re-iterating through the list v 4 times for each loop around data.items(), we loop just once, by appending to t and then using an 'Accumulator' class (Diff), we can achieve the same results and make it easier to read.

The Diff class extends list and overrides the append method, 'shifting' a and b each time a new value is added and appending the difference instead.

Could go further with additional dataclasses for speed and position, but I felt liket his hit a nice 'balance' of readability and effort.

Code
Diff
  • """Test equipment positions."""
    from __future__ import annotations
    
    import datetime as dt
    import functools
    import random
    from collections import defaultdict
    from dataclasses import dataclass
    from typing import Any
    from unittest import TestCase
    
    
    @dataclass
    class Position:
        """3D Coordinate data class"""
        x: float
        y: float
        z: float
    
    
    # Helper λ for building consistent datetime objects since we're constraining everything to the same day/hour/minute
    to_datetime = lambda s: dt.datetime(2022, 1, 1, hour=12, minute=0, second=s)
    
    
    def data_dict() -> defaultdict[str, Any]:
        """Return all equipment positions."""
        d = defaultdict(list)
    
        # λ for ease when updating or adding new mocked data
        add_data = lambda k, s, p: d[k].append({'position': p, 'timestamp': to_datetime(s)})
    
        add_data('T123', 0, Position(42, 24, 0.42))
        add_data('T456', 0, Position(21.0, 34, 0.289))
        add_data('T789', 0, Position(17, 39, 0.789))
        add_data('T456', 3, Position(91.0, 114, 0.489))
        add_data('T123', 1, Position(43, 25, 0.43))
        add_data('T789', 6, Position(19., 79, 0.991))
        add_data('T123', 2, Position(46, 29, 0.44))
        add_data('T456', 4, Position(24.0, 37, 0.297))
        add_data('T123', 3, Position(49.0, 32, 0.451))
        add_data('T789', 7, Position(23., 81, 1.103))
    
        return d
    
    
    def latest_snapshot() -> dict[str, Any]:
        """Return a snapshot of latest equipment."""
    
        return {
            'T123': {'position': Position(49.0, 32, 0.451), 'timestamp': to_datetime(3)},
            'T456': {'position': Position(24.0, 37, 0.297), 'timestamp': to_datetime(4)},
            'T789': {'position': Position(23.0, 81, 1.103), 'timestamp': to_datetime(7)},
        }
    
    
    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)
    
        # λ for updating or adding new mocked data
        add_speed = lambda k, t, s: d[k].append({'speed': s, 'timestamp': to_datetime(t)})
    
        add_speed('T123', 3, round(4.242654947082074, 1))
        add_speed('T123', 2, round(5.00000999999, 1))
        add_speed('T123', 1, round(1.4142489172702237, 1))
        add_speed('T123', 0, None)
        add_speed('T456', 4, round(102.0687849638664, 1))
        add_speed('T456', 3, round(35.43388209045123, 1))
        add_speed('T456', 0, None)
        add_speed('T789', 7, round(4.473538196997986, 1))
        add_speed('T789', 6, round(6.6750796998987205, 1))
        add_speed('T789', 0, None)
    
        return d
    
    
    def find_furthest_west(data: defaultdict) -> str:
        """
        Find the name of the truck that is furthest west. That is,
        the truck with the smallest easting position component.
        """
        f = lambda v: min([x['position'].x for x in v])
        return functools.reduce(lambda a, b: a if f(data[a]) < f(data[b]) else b, data.keys())
    
    
    def get_latest_snapshot(data: defaultdict) -> dict[str, Any]:
        """
        Return a snapshot of the latest positional updates for the
        equipment.
        """
        return {k: v[-1] for k, v in data.items()}
    
    
    def get_counts(data: defaultdict) -> dict[str, int]:
        """Return a dict of trucks and the times they have provided updates."""
        return {k: len(v) for k, v in data.items()}
    
    
    class Diff(list):
        """A utility class that creates a list of the differences between consecutive pair of numbers that are appended"""
        a = b = None
    
        def append(self, c):
            self.a, self.b = self.b, c
            if self.a is not None:
                super().append(self.b - self.a)
    
    
    def calculate_speeds(data: defaultdict) -> defaultdict[str, Any]:
        """Return a dict of equipment and the speeds they are travelling at."""
        out = defaultdict(list)
    
        for k, v in data.items():
            t = []
            dt = Diff()
            dx = Diff()
            dy = Diff()
    
            for x in v:
                t.append(x['timestamp'])
                dt.append(x["timestamp"].second)
                dx.append(x["position"].x)
                dy.append(x["position"].y)
    
            dd = [(a ** 2 + b ** 2) ** 0.5 for a, b in zip(dx, dy)]
            s = [a / b for a, b in zip(dd, dt)]
            for speed, timestamp in zip(s[::-1], t[::-1]):
                out[k].append({'speed': round(speed, 1), 'timestamp': timestamp})
            out[k].append({'speed': None, 'timestamp': t[0]})
    
        return out
    
    • """Test equipment positions."""
    • from __future__ import annotations
    • from collections import defaultdict
    • import datetime as dt
    • import functools
    • import random
    • from collections import defaultdict
    • from dataclasses import dataclass
    • from typing import Any
    • from unittest import TestCase
    • @dataclass
    • class Position:
    • """3D Coordinate data class"""
    • x: float
    • y: float
    • z: float
    • # Helper λ for building consistent datetime objects since we're constraining everything to the same day/hour/minute
    • to_datetime = lambda s: dt.datetime(2022, 1, 1, hour=12, minute=0, second=s)
    • 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)})
    • # λ for ease when updating or adding new mocked data
    • add_data = lambda k, s, p: d[k].append({'position': p, 'timestamp': to_datetime(s)})
    • add_data('T123', 0, Position(42, 24, 0.42))
    • add_data('T456', 0, Position(21.0, 34, 0.289))
    • add_data('T789', 0, Position(17, 39, 0.789))
    • add_data('T456', 3, Position(91.0, 114, 0.489))
    • add_data('T123', 1, Position(43, 25, 0.43))
    • add_data('T789', 6, Position(19., 79, 0.991))
    • add_data('T123', 2, Position(46, 29, 0.44))
    • add_data('T456', 4, Position(24.0, 37, 0.297))
    • add_data('T123', 3, Position(49.0, 32, 0.451))
    • add_data('T789', 7, Position(23., 81, 1.103))
    • return d
    • def latest_snapshot() -> dict[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)},
    • 'T123': {'position': Position(49.0, 32, 0.451), 'timestamp': to_datetime(3)},
    • 'T456': {'position': Position(24.0, 37, 0.297), 'timestamp': to_datetime(4)},
    • 'T789': {'position': Position(23.0, 81, 1.103), 'timestamp': to_datetime(7)},
    • }
    • 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': round(4.242654947082074, 1), 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=3)})
    • d['T123'].append({'speed': round(5.00000999999, 1), 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=2)})
    • d['T123'].append({'speed': round(1.4142489172702237, 1), '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': round(102.0687849638664, 1), 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=4)})
    • d['T456'].append({'speed': round(35.43388209045123, 1), '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': round(4.473538196997986, 1), 'timestamp': dt.datetime(2022, 1, 1, hour=12, minute=0, second=7)})
    • d['T789'].append({'speed': round(6.6750796998987205, 1), '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)})
    • # λ for updating or adding new mocked data
    • add_speed = lambda k, t, s: d[k].append({'speed': s, 'timestamp': to_datetime(t)})
    • add_speed('T123', 3, round(4.242654947082074, 1))
    • add_speed('T123', 2, round(5.00000999999, 1))
    • add_speed('T123', 1, round(1.4142489172702237, 1))
    • add_speed('T123', 0, None)
    • add_speed('T456', 4, round(102.0687849638664, 1))
    • add_speed('T456', 3, round(35.43388209045123, 1))
    • add_speed('T456', 0, None)
    • add_speed('T789', 7, round(4.473538196997986, 1))
    • add_speed('T789', 6, round(6.6750796998987205, 1))
    • add_speed('T789', 0, None)
    • return d
    • def find_furthest_west(data: defaultdict) -> str:
    • """
    • Find the name of the truck that is furthest west. That is,
    • the truck with the smallest easting position component.
    • """
    • f = lambda v: min([x['position']['x'] for x in v])
    • f = lambda v: min([x['position'].x for x in v])
    • return functools.reduce(lambda a, b: a if f(data[a]) < f(data[b]) else b, data.keys())
    • def get_latest_snapshot(data: defaultdict) -> dict[str, Any]:
    • """
    • Return a snapshot of the latest positional updates for the
    • equipment.
    • """
    • return {k: v[-1] for k, v in data.items()}
    • def get_counts(data: defaultdict) -> dict[str, int]:
    • """Return a dict of trucks and the times they have provided updates."""
    • return {k : len(v) for k, v in data.items()}
    • return {k: len(v) for k, v in data.items()}
    • class Diff(list):
    • """A utility class that creates a list of the differences between consecutive pair of numbers that are appended"""
    • a = b = None
    • def append(self, c):
    • self.a, self.b = self.b, c
    • if self.a is not None:
    • super().append(self.b - self.a)
    • def calculate_speeds(data: defaultdict) -> defaultdict[str, Any]:
    • """Return a dict of equipment and the speeds they are travelling at."""
    • out = defaultdict(list)
    • diff = lambda x: [b - a for a, b in zip(x, x[1:])]
    • for k, v in data.items():
    • t = [x['timestamp'] for x in v]
    • dt = diff([x["timestamp"].second for x in v])
    • dx = diff([x["position"]["x"] for x in v])
    • dy = diff([x["position"]["y"] for x in v])
    • t = []
    • dt = Diff()
    • dx = Diff()
    • dy = Diff()
    • for x in v:
    • t.append(x['timestamp'])
    • dt.append(x["timestamp"].second)
    • dx.append(x["position"].x)
    • dy.append(x["position"].y)
    • dd = [(a ** 2 + b ** 2) ** 0.5 for a, b in zip(dx, dy)]
    • s = [a / b for a, b in zip(dd, dt)]
    • for speed, timestamp in zip(s[::-1], t[::-1]):
    • out[k].append({'speed': round(speed, 1), 'timestamp': timestamp})
    • out[k].append({'speed': None, 'timestamp': t[0]})
    • return out
    • return out