Skip to content

Commit

Permalink
Added duplicate key tracking. Improved handling of random number gene…
Browse files Browse the repository at this point in the history
…rator.
  • Loading branch information
mburrough committed Apr 17, 2017
1 parent 7e1c88f commit c62ee86
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

/keyProb/bin/Debug
/keyProb/obj/Debug
*.suo
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Known Limitations
-----------------
1. The simulation only considers a basic lock system with one operator key and one master key. Things like multi-level-masters or multiple shear lines are not supported.
1. Maximum Adjacent Cut / Minimum Opposite Cut Specifications (MACS / MOCS) are not supported.
1. Duplicate keys are not tracked/excluded.
1. There is no input validation on the variables to KeyTest. Program assumes you provide sane values.

**No guarantee is made to the accuracy of this calculation. This program is a hypothetical simulation, and not designed to assess any particular brand or model of real world lock/key system. To be used for entertainment purposes only.**

Expand Down
64 changes: 47 additions & 17 deletions keyProb/KeyTest.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;

namespace keyProb
{
class KeyTest
{
private Random rnd;
private int[] master;
int TestedKeys;
List<int[]> TestedKeys;
private int Buffer;
private int PinCount;
private int Depths;
Expand All @@ -20,13 +21,13 @@ class KeyTest
* depths - number of possible cut depths per pin
* buffer - number of pins disallowed around master. 0 means a pin wafer of size 1 is allowed. Must be >= 0.
**/
public KeyTest(int pinCount, int depths, int buffer)
public KeyTest(int pinCount, int depths, int buffer, Random random)
{
rnd = new Random();
rnd = random;
PinCount = pinCount;
Depths = depths;
Buffer = buffer;
TestedKeys = 0;
TestedKeys = new List<int[]>();
GenerateMaster();
BuildTestMap();
}
Expand All @@ -40,13 +41,13 @@ public KeyTest(int pinCount, int depths, int buffer)
* buffer - number of pins disallowed around master. 0 means a pin wafer of size 1 is allowed. Must be >= 0.
* masterKey - if you want to test against a specific master key, instead of a randomly generated one, provide one here.
**/
public KeyTest(int pinCount, int depths, int buffer, int[] masterKey)
public KeyTest(int pinCount, int depths, int buffer, int[] masterKey, Random random)
{
rnd = new Random();
rnd = random;
PinCount = pinCount;
Depths = depths;
Buffer = buffer;
TestedKeys = 0;
TestedKeys = new List<int[]>();
master = masterKey;
BuildTestMap();
}
Expand Down Expand Up @@ -143,36 +144,65 @@ public int Simulation()
{
AddKey(GenerateValidKey());
} while (!checkFinished());
Console.WriteLine("Done in {0} keys.", TestedKeys);
Console.WriteLine("Done in {0} keys.", TestedKeys.Count);
Console.WriteLine();
return TestedKeys;
int ret = TestedKeys.Count;
TestedKeys.Clear();
return ret;
}

//Create a new operator key. Key must not have any pins equal to master, nor any +/- buffer from master.
private int[] GenerateValidKey()
{
int[] key = new int[PinCount];

for (int i = 0; i < PinCount; i++)
{
do
do {
for (int i = 0; i < PinCount; i++)
{
key[i] = rnd.Next(Depths);
} while (!isValid(i, key[i]));
}
do
{
key[i] = rnd.Next(Depths);
} while (!isValid(i, key[i]));
}
} while (!unique(key));

Console.Write("Key" + TestedKeys + ": \t");
Console.Write("Key" + TestedKeys.Count + ": \t");
for(int i=0; i<PinCount; i++)
{
Console.Write(key[i] + " ");
}
Console.WriteLine();

TestedKeys++;
TestedKeys.Add(key);

return key;
}

//Check if the current key has been already tested
private bool unique(int[] key)
{
foreach (int[] testedKey in TestedKeys)
{
bool dup = true;
for (int i = 0; i < testedKey.Length; i++)
{
if (key[i] != testedKey[i])
{
dup = false;
break;
}
}

if (dup) //Key matched an existing key on each pin. Not unique.
{
return false;
}
}

//Made it through all keys with no matches. It is unique.
return true;
}

//Check if a given pin value is too close to the master value
private bool isValid(int pos, int val)
{
Expand Down
8 changes: 5 additions & 3 deletions keyProb/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ class Program
{
static void Main(string[] args)
{
int tests = 10000; //How many tests to run
int tests = 1000; //How many tests to run
int pinPositions = 7; //How many key stacks in this lock
int depths = 6; //How many possible cut depths per pin.
int buffer = 0; //How many cuts on either side of master are illegal. (E.g. disallow pin 'wafers' of this size).
Random r = new Random(); //Pass in random so we don't keep regenerate it each test run, which can lead to issues with the random values.

//Create a specific master key set to all 0's.
int[] m = new int[pinPositions];
for (int i = 0; i < m.Length; i++)
m[i] = 0;
Expand All @@ -20,8 +22,8 @@ static void Main(string[] args)
Stopwatch stopwatch = Stopwatch.StartNew();
for (int tries = 0; tries < tests; tries++)
{
KeyTest k = new KeyTest(pinPositions, depths, buffer);
//KeyTest k = new KeyTest(pinPositions, depths, buffer, m); // Optionally, provide a fixed master to test
KeyTest k = new KeyTest(pinPositions, depths, buffer, r);
//KeyTest k = new KeyTest(pinPositions, depths, buffer, m, r); // Optionally, provide a fixed master to test
total += k.Simulation();
}
stopwatch.Stop();
Expand Down

0 comments on commit c62ee86

Please sign in to comment.