Welcome, guest | Sign In | My Account | Store | Cart

A suggestion of an odometer implementation. Each "roll" in the odometer is defined by the caller. It is a list holding any objects, only the length of the list is important.

Can be good to have if something need to be tested in all possible combinations.

Python, 107 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
def odometer(syms=range(10), rolls=2, start=0, stop=None):
    """
    Logic exercise. For each roll, if the previous roll rolled over,
    roll the roll.

    The range of "values" is defined by syms, it is a list with any
    objects. Yield all possible combinations being len(syms)**rolls.

    Examples:

    >>> Hex = range(10) + ['A', 'B', 'C', 'D', 'E', 'F']
    >>> odo = odometer(Hex, stop=16)
    >>> for om in odo:
    ...     print om
    ... 
    [0, 0]
    [0, 1]
    [0, 2]
    [0, 3]
    [0, 4]
    [0, 5]
    [0, 6]
    [0, 7]
    [0, 8]
    [0, 9]
    [0, 'A']
    [0, 'B']
    [0, 'C']
    [0, 'D']
    [0, 'E']
    [0, 'F']
    >>> odo = odometer(Hex, start=250, stop=256)
    >>> for om in odo:
    ...     print om
    ... 
    ['F', 'A']
    ['F', 'B']
    ['F', 'C']
    ['F', 'D']
    ['F', 'E']
    ['F', 'F']
    >>> odo = odometer(['haz', 'the', 'code'], rolls=3)
    >>> fmt = '{} {} {}?'
    >>> for om in odo:
    ...     print fmt.format(om[0].capitalize(), *om[1:])
    ... 
    Haz haz haz?
    Haz haz the?
    Haz haz code?
    Haz the haz?
    Haz the the?
    Haz the code?
    Haz code haz?
    Haz code the?
    Haz code code?
    The haz haz?
    The haz the?
    The haz code?
    The the haz?
    The the the?
    The the code?
    The code haz?
    The code the?
    The code code?
    Code haz haz?
    Code haz the?
    Code haz code?
    Code the haz?
    Code the the?
    Code the code?
    Code code haz?
    Code code the?
    Code code code?

    """
    
    base = len(syms)
    combinations = base**rolls

    # The odometer is to be reversed on delivery.
    odo = [syms[0] for i in range(rolls)]

    # Odometer start setting:
    curval = start
    for i in range(rolls):
        j = curval % base
        odo[i] = syms[j]
        curval = curval // base

    curval = start
    while curval < (stop or combinations):
        # Consider roll 0 to be rightmost.
        yield odo[-1::-1]
        for roll, sym in enumerate(odo[:]):
            i = syms.index(sym)
            if i < base - 1:
                odo[roll] = syms[i + 1]
                # Could roll the roll w/o roll-over, next value:
                break
            else:
                odo[roll] = syms[0]
                # There was a roll-over, next roll.
        curval += 1

if __name__ == '__main__':
    import doctest
    doctest.testmod()
Created by Tomas Nordin on Sat, 27 Sep 2014 (MIT)
Python recipes (4591)
Tomas Nordin's recipes (6)

Required Modules

  • (none specified)

Other Information and Tasks