функция для генерации 26 (AZ) * 26 (AZ) * 26 (AZ) - PullRequest
1 голос
/ 22 июля 2010

Я хотел бы создать функцию, которая будет генерировать строку из трех символов после каждого цикла.

В алфавите 26 символов, и я хотел бы создать совершенно уникальные 3-х символьные клавиши (A-Z).

Вывод будет 17 576 уникальных 3-х символьных клавиш (A-Z) - без учета регистра.

Может кто-нибудь дать мне представление о том, как создать более элегантную функцию без случайного генерирования ключей и проверки на наличие дубликатов ключей?

Возможно ли

Спасибо.

Ответы [ 4 ]

9 голосов
/ 22 июля 2010

Если я правильно прочитал ваш вопрос, вы хотите иметь функцию, которая возвращает ключ вида «ABC», где каждая буква выбирается случайным образом, но одна и та же комбинация букв никогда не выдается дважды.

Вы имеете в виду, что никогда не выдается дважды за выполнение кода или никогда не выдается дважды «никогда»?

В любом случае я бы посмотрел на генерацию всех возможных комбинаций, их перетасовку и последующее сохранение в массиве элементов или в файле./ база данных в зависимости от ваших потребностей.Вам также нужно будет сохранить индекс, который вы просто увеличиваете каждый раз при выдаче ключа.

<?php
  private $keys = array();
  private $keyIndex = -1;

  function generateKeys()
  {
      $this->keys = array();
      $this->keyIndex = -1;

      for ($i=1; $i<=26; $i++)
      {
         for ($j=1; $j<=26; $j++)
         {
            for ($k=1; $k<=26; $k++)
            {
                $this->keys[] = sprintf('%c%c%c', 64+$i, 64+$j, 64+$k);
            }
         }
      }

      shuffle($this->keys);

      return $this->keys;
  }

  function getKey()
  {
      $this->keyIndex++;
      return $this->keys[$this->keyIndex];
  }

?>
2 голосов
/ 22 июля 2010

var используйте любую математическую библиотеку, чтобы сгенерировать случайное число от 0 до 26 в кубе - 1, затем присвойте буквы на основе значения этого случайного целого числа ...

в дальнейшем обратный слеш представляет целое числоделение, то есть отбрасывание любого дробного остатка

первый символ = ascii (65 + целочисленный модуль 26)
второй символ = ascii (65 + (целое число \ 26) модуль 26
третий символ = ascii (65 + ((целое число \ 26) \ 26) модуль 26

ааа, спасибо @Graphain Я понимаю, что вы хотите исключить любые шансы выбрать ту же комбинацию из трех символов снова ... ну, вот вам путь...

  1. Создать коллекцию (Список?), Содержащую 676 (26 * 26) 32-битных целых чисел, все они инициализированы в 2 ^ 26-1 (поэтому биты 0-25 все установлены = 1).Поместите 26 из этих целых чисел в каждый из 26 внутренних словарей, чтобы они превратились в словарь из 26 словарей, в каждом из которых есть 26 из этих целых чисел. Маркируйте внутренние словари AZ. Внутри каждого внутреннего массива маркируйте целые числа AZ.* Случайно выбрать один из 26 внешних массивов (это устанавливает первый символ).
  2. Из выбранного массива случайным образом выберите один из его внутренних массивов.Это устанавливает второй символ.
  3. Затем случайным образом выбирают число от 0 до n (где n - количество бит в целом числе, которые все еще установлены в 1) ... Какой бит в числе определяетпоследний символ.
  4. Установить этот бит на ноль
  5. Если все биты в целом числе были установлены в ноль, удалить целое число из массива
  6. Если этот внутренний массив теперь пуст,(все целые числа пропали) удалите его из внешнего массива.
  7. Повторяйте с шага 2, пока внешний массив не опустеет или вы не устанете ...

Вот пример кода (не тестировался)):

 public class RandomAlphaTriplet
 {
    private static readonly Dictionary<char, Dictionary<char, int>> vals =
         new Dictionary<char, Dictionary<char, int>>();
    const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static readonly Random rnd = new Random(DateTime.Now.Millisecond);

    private const int initVal = 0x3FFFFFF;
    static RandomAlphaTriplet()
    {
        foreach (var c in chars)
            vals.Add(c, chars.ToDictionary(
                ic => ic, ic => initVal));
    }
    public static string FetchNext()
    {
        var c1 = chars[rnd.Next(vals.Count)];
        var inrDict = vals[c1];
        var c2 = chars[rnd.Next(inrDict.Count)];
        var intVal = inrDict[c2];
        var bitNo = rnd.Next(BitCount(intVal));
        var bitPos = 0;
        while (bitNo > 0)
        {
            if ((intVal & 0x0001) > 0) bitNo--;
            bitPos++;
            intVal <<= 1;
        }
        var c3 = chars[bitPos];
        inrDict[c2] &= ~(1 << bitPos);
        if (inrDict[c2] == 0) inrDict.Remove(c2);
        if (vals[c1].Count == 0) vals.Remove(c1);
        return string.Concat(c1, c2, c3);
    }
    private static int BitCount(int x)
    { return ((x == 0) ? 0 : ((x < 0) ? 1 : 0) + BitCount(x << 1)); }
} 
0 голосов
/ 22 июля 2010

Эмм, разве это не «простая» комбинаторная математика? (Выберите все комбинации из 3 из 26? Или перестановки из 3 из 26?)

0 голосов
/ 22 июля 2010

Я могу сделать это только с одним ключом, если вы заинтересованы. (Я не знаю, возможно ли вообще не иметь ключа для проверки на дублирование). function getAlpha($Index) { $Alphabets = 'abcdefghijklmnopqrstuvwxyz'; $Char = substr($Alphabets, $Index, 1); return $Char; } function getRandom($Index) { $RandOne = $Index % 26; $RandTwo = ($Index / 26 ) % 26; $RandThree = ($Index / 26*26) % 26; $AlphaOne = getAlpha($RandOne); $AlphaTwo = getAlpha($RandTwo); $AlphaThree = getAlpha($RandThree); $Rand = $AlphaOne.$AlphaTwo.$AlphaThree; return $Rand; } $Rands = array(); function getRandom() { global $Rands; while (true) { $RandNum = rand(0, 26*26*26 - 1); if (isset($Rands[$RandNum])) continue; $Rand = getRandom($RandNum); $Rands[$RandNum] = $Rand; return $Rand; } }

Для поиска нужен только один ключ.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...