I'm building an elaborate Enigma machine, and when creating my plugs, I want to be get a random sample of even length from the characters available to my machine's rotors. Easy enough. The issue here is that I'm using seed(rng_seed)
just before used_keys = set(sample(free_keys, 2 * plug_count))
, which I would expect to give the same set every time. It does not. I do not understand why I'm seeing this behavior.
Here are the relevant bits:
from random import random, sample, seed
from typing import Set, Tuple
from enigma.rotor import StandardRotor
# from enigma.plug import Plug
class EnigmaMachine:
STEP = 1
def __init__(self, rotor_count: int, plug_count: int, rng_seed: int, step: int = None):
if rotor_count < 1:
raise ValueError('rotor_count expected be an integer '
'greater than zero, got {}'.format(rotor_count))
# Generate rotors
seed(rng_seed)
seeds = tuple(random() for _ in range(rotor_count))
self.__rotors = tuple(StandardRotor(rng_seed=seeds[i]) for i in range(rotor_count))
# Generate plugs
free_keys = self.keys
if plug_count > 2 * len(free_keys):
raise ValueError('Maximum plugs allowed is {}, got {}'.format(len(free_keys) // 2,
plug_count))
seed(rng_seed)
used_keys = set(sample(free_keys, 2 * plug_count))
# TODO: why won't seed affect sample?
free_keys -= used_keys
print(free_keys)
print(used_keys)
self.__step = step or EnigmaMachine.STEP
@property
def keys(self) -> Set[str]:
return set(self.__rotors[0].cipher)
Inside StandardRotor.__init__
, I'm also using seed
, which you can see is potentially called many times.
In summary, here's all the places I'm using anything from random
:
seed
before creating rotorsrandom()
when creating a tuple of lengthrotor_count
seed
inside eachStandardRotor.__init__
seed
before creatingused keys
sample
when creating a subset offree_keys
After I get this working, I expect to use random.sample
to pull pairs out of used_keys
and create Plugs from them. I haven't shown them here, but they're very basic and simply take two different characters as inputs.
FYI, I've also tried refactoring this to import Random
, create an instance of random inside init with r = Random()
, then prefixing all my random commands with r.
, such as r.seed
and r.sample
. This made no difference.
Aucun commentaire:
Enregistrer un commentaire