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:
seedbefore creating rotorsrandom()when creating a tuple of lengthrotor_countseedinside eachStandardRotor.__init__seedbefore creatingused keyssamplewhen 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