Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [решено] Вернуть рандомную фразу (http://forum.oszone.net/showthread.php?t=144586)

FlatX007 09-07-2009 07:32 1162656

Вернуть рандомную фразу
 
Как вернуть рандомное число извесно, а как вернуть "фразу" из рандомных букв ?

У меня предположение я не пробовал ещё - нужно вернуть рандомное число от 1 до 33 и к каждой цифре приравнять букву из алфавита по порядковому номеру, потом "сумировать" комбинации. Если так то пример ненадо я сам придумаю.

Меня интересует есть ли другой способ ;)

amel27 09-07-2009 10:56 1162799

FlatX007, а что подразумевается под фразой "из рандомных букв"?.. как раз то, что описано ниже ;)

FlatX007 09-07-2009 12:00 1162850

wesadczgcgjbnzytuyiuopmjouitfhg - "фраза" из рандомных букв что непонятного ?

proxy 09-07-2009 12:15 1162861

Цитата:

Цитата FlatX007
У меня предположение я не пробовал ещё - нужно вернуть рандомное число от 1 до 33 и к каждой цифре приравнять букву из алфавита по порядковому номеру, потом "сумировать" комбинации. Если так то пример ненадо я сам придумаю. »

помойму это единственный вариант, после генерации либо:
- StringMid
- Chr
- либо извращения, выборка из массива...

amel27 09-07-2009 12:19 1162870

FlatX007, все как раз понятно: "вернуть фразу из рандомных букв" это то же самое, что:

Цитата:

вернуть рандомное число от 1 до 33 и к каждой цифре приравнять букву из алфавита по порядковому номеру, потом "сумировать" комбинации
т.е. это не "способ", а другая формулировка той же задачи :)
сравни с формулировкой: "вернуть рандомную фразу из заданных букв" - это уже другая задача


P.S. это не флуд, а занудство ;) ...сам сказал - другие способы не интересуют

proxy 09-07-2009 12:23 1162875

Давайте закидаем Амеля27 снежками :tomato2: - он много знает ... :happy:

FlatX007 09-07-2009 14:38 1162981

Цитата:

Цитата amel27
amel27 »

Цитата:

Цитата FlatX007
Меня интересует есть ли другой способ »

Цитата:

Цитата amel27
..сам сказал - другие способы не интересуют »

Где логика ? :tomato: :tomato:

Creat0R 09-07-2009 14:48 1162989

Код:

$sRandomString = _StringGetRandomString(15, 20, 1)

MsgBox(64, 'Title', $sRandomString)

Func _StringGetRandomString($iMin=1, $iMax=1, $iOnly_ASCII=0)
    If $iMax < $iMin Then Return SetError(1, 0, 0)

    Local $iRandom, $sRet_Str = ''
    Local $iMin_Rndm = 33, $iMax_Rndm = 255
    If $iOnly_ASCII Then Dim $iMin_Rndm = 97, $iMax_Rndm = 122

    For $i = 1 To Random($iMin, $iMax, 1)
        $sRet_Str &= Chr(Random($iMin_Rndm, $iMax_Rndm, 1))
    Next

    Return
$sRet_Str
EndFunc


FlatX007 09-07-2009 15:19 1163008

некак непойму зачем эти строчки
Код:

    Local $iMin_Rndm = 33, $iMax_Rndm = 255
    If $iOnly_ASCII Then Dim $iMin_Rndm = 97, $iMax_Rndm = 122


proxy 09-07-2009 15:40 1163022

Цитата:

Цитата Creat0R
If $iOnly_ASCII Then Dim $iMin_Rndm = 97, $iMax_Rndm = 122 »

Dim тут для того, что бы объявить заново переменные $iMin_Rndm и $iMax_Rndm.
а так как это можно сдлеать в одну строчку, то можно не расписывать:
Код:

If $iOnly_ASCII Then
      $iMin_Rndm = 97
      $iMax_Rndm = 122
EndIf

Хитро ;) Только есть ли скрытый смысл в использование Dim? Может тот же Local?

А $iMin_Rndm = 97 и $iMax_Rndm = 122 - это значит произвести выборку только среди английского алфавита маленьких букавак: a-z

Creat0R 09-07-2009 15:50 1163031

Цитата:

Цитата proxy
есть ли скрытый смысл в использование Dim? »

Какой скрытый смысл? переменные уже объявлены в локальном скупе, а Dim позволяет присвоить значение нескольким переменным сразу, при этом не меняя локального скупа.

FlatX007 09-07-2009 15:54 1163036

Так оно работает и без Local $iMin_Rndm = 33, $iMax_Rndm = 255

А если убрать строчку If $iOnly_ASCII Then Dim $iMin_Rndm = 97, $iMax_Rndm = 122 - то получается гинератор крокозябр :) просто несталкивался с функцией Chr на практике - вот и задаю глупые вопросы.

proxy 09-07-2009 15:57 1163039

Цитата:

Цитата Creat0R
при этом не меняя локального скупа. »

вот эотго не понимаю.

чем это:
Цитата:

Local $iMin_Rndm = 33, $iMax_Rndm = 255
If $iOnly_ASCII Then Dim $iMin_Rndm = 97, $iMax_Rndm = 122
т.е. при этом, не будут объявляться новые переменные, т.к. будет определенно, что они уже существуют и им просто будет присвоенно новое значение?

будет отличаться от этого:
Цитата:

Local $iMin_Rndm = 33, $iMax_Rndm = 255
If $iOnly_ASCII Then Local $iMin_Rndm = 97, $iMax_Rndm = 122
а в этом случае, невзирая, что эти переменные уже существуют, они снова будут объявленны и им будет присвоенно соотсвтевующее значение...

так?

Creat0R 09-07-2009 16:02 1163043

Цитата:

Цитата FlatX007
Так оно работает и без Local $iMin_Rndm = 33, $iMax_Rndm = 255 »

Ну попробуй вместо 1 поставить 0 при вызове функции (последний параметр) ;)

Цитата:

Цитата FlatX007
если убрать строчку If $iOnly_ASCII Then Dim $iMin_Rndm = 97, $iMax_Rndm = 122 - то получается гинератор крокозябр »

Не надо ничего убирать, это можно сделать и через параметр $iOnly_ASCII = 0. Если он будет равен 1, то будет гинерировать только ASCII символы.

Цитата:

Цитата proxy
чем это:
Цитата:Local $iMin_Rndm = 33, $iMax_Rndm = 255
If $iOnly_ASCII Then Dim $iMin_Rndm = 97, $iMax_Rndm = 122
будет отличаться от этого:
Цитата:Local $iMin_Rndm = 33, $iMax_Rndm = 255
If $iOnly_ASCII Then Local $iMin_Rndm = 97, $iMax_Rndm = 122
? »

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

proxy 09-07-2009 16:05 1163047

Цитата:

Цитата Creat0R
Ничем, оба варианта работают одинаково. Я вот другого не понимаю, зачем придираться к этим мелочам, не в этом же суть функции. »

нееее. я не придираюсь - я изучаю, мнеж не понятно. думал что в этом есть реально смысл, который я непомниаю. я бы Local написал бы без задней мысли...а тут Dim - вот и удивился ....)

Creat0R 09-07-2009 16:18 1163056

proxy,

Из справки:

Цитата:

The difference between Dim, Local and Global is the scope in which they are created:
Dim = Local scope if the variable name doesn't already exist globally (in which case it reuses the global variable!)
Global = Forces creation of the variable in the Global scope
Local = Forces creation of the variable in the Local/Function scope

You should use Local or Global, instead of Dim, to explicitly state which scope is desired for a variable/constant/array.
Т.е в нашем случае, оно не играет особой роли, вот если бы эти переменные были заранее объявлены глобально, то Local в функции создал бы точно такие переменные с локальным скупом, а Dim оставил бы скуп как есть, только переназначил бы значения.

amel27 09-07-2009 16:58 1163091

Цитата:

Цитата FlatX007
Где логика »

ладно, проехали... ;)

Максимально случайным будет только первый вызов Random(), случайность всех последующих вызовов будет существенно ниже – реальная величина зависит от применяемого алгоритма генератора СЧ. Т.к. максимально целое случайное число является 31-разрядным, длина максимально-случайного слова вычисляется формулой 31*ln2/lnN, где N – кол-во букв в алфавите. Для 33 русских букв одного регистра - это слово из 6 букв. Т.е. для максимально случайной фразы мы должны генерировать не по одной букве, а по 6-символьным последовальностям, при этом каждые 5 битов числа будут кодировать одну букву.

P.S. вся эта “нудь” имеет смысл только при решении задач типа генераторов паролей, чтобы точно знать РЕАЛЬНУЮ сложность сгенерированного пароля

FlatX007 09-07-2009 19:40 1163236

Нащёт моего примера в шапке я и так знаю
Цитата:

Цитата amel27
Максимально случайным будет только первый вызов Random(), »

- поэтому и попросил помочь. :Р а из формулы я ничего непонял.

amel27 11-07-2009 02:56 1164422

FlatX007, можно уменьшить кол-во вызовов Random():
Код:

$p = _GetRandomString(10)
$e = @extended

ConsoleWrite("Password: "& $p &@CRLF)
ConsoleWrite("Skipped : "& $e &" chars"&@CRLF)

Func _GetRandomString($iLen, $sABC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_@")
    Local $iABC = StringLen($sABC), $sOut = ""
    Local $iBit = Int(Log($iABC)/Log(2)) ; бит на символ
    Local $iMsk = BitShift(1,-$iBit) -1  ; битовая маска
    Local $iChr = Int(31/$iBit)          ; символов на одно случайное число

        While 1
        $iRnd = Random(1, 0x7FFFFFFF, 1)
        For $i=1 To $iChr
            $sOut
&= StringMid($sABC, BitAND($iRnd, $iMsk)+1, 1)
            If StringLen($sOut)>=$iLen Then Return SetError(0, $iABC-$iMsk-1,$sOut)
            $iRnd = BitShift($iRnd, $iBit)
        Next
    WEnd
EndFunc

ADD: кол-во символов должно быть равно степени двойки (32, 64,...), иначе строка обрезается до ближайшей такой

tweakos 11-07-2009 05:42 1164456

FlatX007, Есть способ гораздо проще:
Код:

$1=random("65","95")
$2=random("65","95")
$3=random("65","95")
$4=random("65","95")
$5=random("65","95");здесь записываем необходимое кол-во рандомных цифр
$result=(chr($1)&chr($2)&chr($3)&chr($4)&chr($5));обьеденяем фразу ,посредством chr переводим цифру в букву


Creat0R 11-07-2009 08:53 1164529

Цитата:

Цитата tweakos
Есть способ гораздо проще: »

Это то что я делаю в своём примере. Но по всей видимости, простота не нужна :)

tweakos 11-07-2009 11:22 1164600

Цитата:

Цитата Creat0R
Это то что я делаю в своём примере. Но по всей видимости, простота не нужна »

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

amel27 11-07-2009 13:20 1164662

Цитата:

Цитата Creat0R
по всей видимости, простота не нужна »

угу, такие случаи надо оговаривать заранее...

На самом деле, MT19937, используемый в AutoIT - алгоритм ПСЕВДОслучайных чисел, где ВСЯ последовательность полностью задаётся ОДНИМ входным 32-х битным числом - чем больше у нас "в кармане" сгенерированных чисел из одной последовательности, тем ближе мы к оценке исходного "ключа". Сам "ключ" обычно генерится на основе показаний внутренних часов. Отсюда понятно, что для серьезных задач штатный генератор не подходит - только для тестирования своего кода... кстати, по указанному линку есть полезная сравнительная табличка разных алгоритмов.

P.S. Т.о., максимальное "пространство атаки" составляет у нас всего 32 бита и не зависит от длины пароля!

P.P.S. Генератор случайных чисел в Windows оказался не случайным :)

Creat0R 11-07-2009 19:47 1164969

amel27, Кстати, это (не надёжность генерации СЧ) и видно с простого примера, где два раза подряд возвращается одно и то же, якобы случайное число, и причём с разных процессов:

Код:

Run(@AutoItExe & ' /AutoIt3ExecuteLine "MsgBox(262144+64, ''Random Test 1'', ''Random: '' & Random(1, 5))"')
Run(@AutoItExe & ' /AutoIt3ExecuteLine "MsgBox(262144+64, ''Random Test 2'', ''Random: '' & Random(1, 5))"')

WinWait('Random Test 2')

WinMove('Random Test 1', 'Random: ', (@DesktopWidth/2)-200, (@DesktopHeight/2)-40)
WinMove('Random Test 2', 'Random: ', (@DesktopWidth/2)+100, (@DesktopHeight/2)-40)


amel27 12-07-2009 08:13 1165277

Creat0R, я тоже это заметил при отладке UDF: для того, чтобы каждый процесс имел свою уникальную "случайную последовательность", пауза между запусками должна быть больше определенного интервала (~500мс)

Мне вообще не нравится, как реализован Rundom() в AutoIT. ИМХО программист сам должен выполнять инициализацию случайной последовательности, как это делается в других языках... Иначе вся работа Rundom() оказывается жестко привязана к времени запуска скрипта - глупость несусветная, вся фишка "воспроизводимости" коту под хвост... Кроме того, создается ложный миф "случайности" полученных чисел.

amel27 12-07-2009 18:23 1165657

собственно, метод, рекомендуемый Microsoft (тот самый CryptoAPI):
Код:

ConsoleWrite(_Crypto_GetRandomString(12, 7) &@CRLF)

; =============================================================================
; _Crypto_GetRandomString($iLen[, $iFlag])
; -----------------------------------------------------------------------------
; Получение случайной символьной строки заданной длины
;
; $iLen      : длина получаемой строки
; $iFlag      : какие символы используются при генерации строки
;            : 1  - цифры
;            : 2  - большие английские буквы
;            : 4  - малые английские буквы
;            : 8  - основные спецсимволы
;            : 16 - дополнительные спецсимволы
;            : 32 - русские буквы
;
; При успехе  : возвращает бинарную строку
;
; При неудаче : пустая строка:
;            :  @error, @extended - код ошибки _Crypto_GetRandomBinary()
;
;            : AutoIT v3.3.0.0
; =============================================================================

Func _Crypto_GetRandomString($iLen, $iFlag = 15)
    Local $iMid, $sABC = "", $sOut = ""
    If BitAND($iFlag,1)  Then $sABC &= "0123456789"
    If BitAND($iFlag,2)  Then $sABC &= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    If BitAND($iFlag,4)  Then $sABC &= "abcdefghijklmnopqrstuvwxyz"
    If BitAND($iFlag,8)  Then $sABC &= "~!@#$%^&*()_"
    If BitAND($iFlag,16) Then $sABC &= '`+-=",.<>/?\|[]{};:'&"'"
    If BitAND($iFlag,32) Then $sABC &= 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя'
    Local $iABC = StringLen($sABC)
    Local $bPWD = _Crypto_GetRandomBinary($iLen)
    If @error Then Return SetError(@error, @extended, $sOut) ; Ошибка _Crypto_GetBinary

    For $i=1 To BinaryLen($bPWD)
        $iMid = Int(BinaryMid($bPWD,$i,1))*$iABC/0x100+1
        $sOut &= StringMid($sABC, $iMid, 1)
    Next
    Return
$sOut
EndFunc ; ==> _Crypto_GetRandomString

; =============================================================================
; _Crypto_GetRandomBinary($iLen)
; -----------------------------------------------------------------------------
; Получение случайной строки байтов заданной длины
;
; $iLen      : количество байтов в бинарной строке
;
; При успехе  : возвращает бинарную строку
;
; При неудаче : возвращаемое значение не является бинарной строкой:
;            :  @error=1, @extended=1 - ошибка открытия advapi32.dll
;            :  @error=1, @extended=2 - ошибка открытия kernel32.dll
;            :  @error=2 - RunTime ошибка API, @extended - код ошибки
;
;            : AutoIT v3.3.0.0
; =============================================================================

Func _Crypto_GetRandomBinary($iLen)
    Local $phProv = DllStructCreate("ulong_ptr"), $aRet
    Local $pbBuffer = DLLStructCreate("byte[" & $iLen & "]")
    ; Открытие DLL
    Local $hAdvApi = DllOpen("advapi32.dll"), $hKernel = DllOpen("kernel32.dll")
    If $hAdvApi=-1 Then Return SetError(1, 1, DllClose($hKernel)) ; Ошибка открытия advapi32.dll
    If $hKernel=-1 Then Return SetError(1, 2, DllClose($hAdvApi)) ; Ошибка открытия kernel32.dll
    ; Создание описателя криптохранилища

    $aRet = DllCall($hAdvApi, "int", "CryptAcquireContext", _
        "ptr", DllStructGetPtr($phProv), "ptr", 0, "ptr", 0, "dword", 1, "dword", 0xF0000000)
    If $aRet[0]=0 Then $aRet = DllCall($hKernel, "int", "GetLastError")
    If UBound($aRet)=1 And $aRet[0]=0x80090016 Then
        $aRet = DllCall($hAdvApi, "int", "CryptAcquireContext", _
            "ptr", DllStructGetPtr($phProv), "ptr", 0, "ptr", 0, "dword", 1, "dword", 0xF0000008)
        If $aRet[0]=0 Then $aRet = DllCall($hKernel, "int", "GetLastError")
    EndIf
    If
UBound($aRet)>1 Then
        ; Генерация случайной последовательности байтов
        $aRet = DllCall($hAdvApi, "int", "CryptGenRandom", _
            "ptr", DllStructGetData($phProv, 1), "dword", $iLen, "ptr", DllStructGetPtr($pbBuffer))
        If $aRet[0]=0 Then $aRet = DllCall($hKernel, "int", "GetLastError")
        ; Закрытие описателя криптохранилища
        DllCall($hAdvApi, "long", "CryptReleaseContext", _
            "ulong_ptr", DllStructGetData($phProv, 1), "dword", 0)
    EndIf
    DllClose($hKernel)
    DllClose($hAdvApi)

    If UBound($aRet)=1 Then Return SetError(2, $aRet[0], 0) ; Ошибка API RunTime
    Return DllStructGetData($pbBuffer, 1) ; Возврат строки
EndFunc ; ==> _Crypto_GetRandomBinary


Creat0R 12-07-2009 22:58 1165855

amel27, Что-то у меня функция возвращает ошибку (@error = 1, @extended = 1)...

amel27 13-07-2009 09:42 1166074

Creat0R, у меня вроде нормально, попробуй измененный вариант... а вообще, в таких случаях нужно проверить UDF для бинарной строки - там возвращается расширенный код ошибки GetLastError()

ADD: т.к. первая UDF лишь враппер - сделал возврат ошибок одинаковым

Creat0R 13-07-2009 15:36 1166436

Цитата:

Цитата amel27
попробуй измененный вариант »

@error = 2
@extended = 87

:dont-know

Мда, это под AutoIt 3.2.8.1 :blush2: - Под 3.3.0.0 нормально работает. Интересно, а под 3.2.8.1 можно функцию подстроить? У меня просто есть ещё пару старых проектов на этой версии, из за этого у меня и была включена эта версия, как раз сейчас работаю над одним из них (проектов).

Creat0R 13-07-2009 15:55 1166461

Оно работает в обеих версиях если заменить "ulong_ptr" на "long" (или на "ptr"). Но насколько оно будет надёжно?

P.S
Кстати, а таким же методом, можно сделать UDF-аналог на Random(), т.е чтобы более надёжно возвращать случайное число?

amel27 13-07-2009 19:08 1166641

Цитата:

Цитата Creat0R
работает в обеих версиях если заменить "ulong_ptr" на "long" (или на "ptr"). Но насколько оно будет надёжно? »

AFAIK "ulong_ptr" отличается от "ulong" только автоматичеким определением разрядности - для переносимости кода между 32 и 64-битным AutoIT... мне почему-то кажется, что одного этого маловато будет, на 64-бит пока не тестил... :unsure:

Цитата:

Цитата Creat0R
таким же методом, можно сделать UDF-аналог на Random(), т.е чтобы более надёжно возвращать случайное число? »

да можно конечно... но ИМХО в такой замене нет нужды: назначение штатного генератора обычно совсем другое - моделирование, тестирование и отладка - в этом случае его предсказуемость и воспроизводимость как нельзя кстати, при "сбое" всегда можно "перезапустить" случайную последовательность и отловить баг... Потому я и говорю о странном позиционировании Random() в AutoIT, надо-то всего ничего - добавить один необязательный параметр для инициализации генератора.

математик из меня никудышный... вроде похоже на правду:
Код:

For $i=1 To 1000
    ConsoleWrite(_Random() &@CRLF)
Next

Func
_Random($iMin=0, $iMax=1, $iFlag=0)
    Local $bBIN, $iOut
    Local $tMAX = DllStructCreate("uint")
    Local $tBIN = DllStructCreate("byte[4];byte[4]")
    Local $tRND = DllStructCreate("uint64", DllStructGetPtr($tBIN))
    Do
        $bBIN = _Crypto_GetRandomBinary(4)
    Until ($bBIN<>Binary(0)) And ($bBIN<>Binary(-1))

    DllStructSetData($tBIN, 1, $bBIN)
    DllStructSetData($tMAX, 1, 0xFFFFFFFF)

    If $iFlag=0 Then $iOut = DllStructGetData($tRND,1)*($iMax-$iMin)/DllStructGetData($tMAX,1)
    If $iFlag  Then $iOut = Int(DllStructGetData($tRND,1)*($iMax-$iMin+1)/DllStructGetData($tMAX,1))

    Return $iOut + $iMin
EndFunc


Creat0R 13-07-2009 23:22 1166847

Цитата:

Цитата amel27
в этом случае его предсказуемость и воспроизводимость как нельзя кстати, при "сбое" всегда можно "перезапустить" случайную последовательность и отловить баг... »

Random() можно использовать в качестве отладчика багов? это для меня что-то новое, можно подробнее плиз?

Цитата:

Цитата amel27
надо-то всего ничего - добавить один необязательный параметр для инициализации генератора. »

Может на этот счёть запостить Feature Request?

Цитата:

Цитата amel27
математик из меня никудышный... вроде похоже на правду »

Ага, мне бы таким никудышным математиком стать :cool:

Спасибо за _Random().

amel27 14-07-2009 08:25 1167030

Цитата:

Цитата Creat0R
можно подробнее плиз? »

не в качестве отладчика, а при отладке... навскидку два варианта:

- на время тестирования кода, использующего криптоалгоритмы, можно заменить случайный генератор на псевдослучайный, т.к. последний работает во много раз быстрее;

- проверка устойчивости форм ввода (Web, GUI) к всевозможным "неправильным" данным - когда нет возможности перебрать ВСЕ возможные комбинации, можно сгенерировать последовательность случайных ... т.е. проверка способности входных регулярных выражений фильтовать "спам";

- вообще, во всех случаях, где НЕ нужна криптостойкость, но нужны скорость/воспроизводимость

Цитата:

Цитата Creat0R
Может на этот счёть запостить Feature Request? »

подумаю... надо же еще предложить как оформить... хотя, если ты проникся необходимостью, можешь и сам отправить (меня английский грузит)... для сравнения: в VB случайная последовательность инициализируется Randomize(), а само число возвращается ф-цией RND()

Цитата:

Цитата Creat0R
Спасибо за _Random() »

спасибо FlatX007 за хороший вопрос ;)


Время: 14:47.

Время: 14:47.
© OSzone.net 2001-2025