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

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Вопрос по скрипту для генерации паролей. (http://forum.oszone.net/showthread.php?t=345160)

SoulGood 12-05-2020 15:34 2920855

Вопрос по скрипту для генерации паролей.
 
Доброго времени всем.
Подскажите пожалуйста, как будет выглядеть код батника, если необходимо сгенерировать все возможные пароли без повторов, содержащие данный набор символов и букв:
0123456789abcdefghijklmnopqrstuvwxyz
Длина пароля - 6 букв и цифр.
С сохранением всех сгенерированных паролей в файл.
Перепробовал не один батник. Но то, генерация рандомная по кол-ву цифр, то скрипт генерирует по одному паролю.

Dreamer_UFA 12-05-2020 16:13 2920863

Принципиально батник ?
Есть прекрасные программы для генерации паролей.

Сам юзаю VipNet Password Generator. Посмотрите, может перекроет ваши потребности

SoulGood 12-05-2020 16:37 2920866

Dreamer_UFA, На сколько я понял, в ней нет нужного функционала. За ответ спасибо.

DJ Mogarych 12-05-2020 17:25 2920871

Powershell:
Код:

$c = 0
$pass = do {
(get-random (([char[]](0..255) -cmatch '[a-z]' |get-random -Count 3) + `
([char[]](0..255) -cmatch '[0-9]' |Get-Random -count 3)) -count 6) -join ''
$c++
} until ($c -eq 100)

$pass > C:\temp\pass.txt


Foreigner 12-05-2020 18:48 2920883


powershell, правда вне задания (все комбинации перебора строки)

Код:

0..99 | foreach { (New-Guid).Guid.Substring(0,6) }
Код:

Add-Type -Assembly System.Web

0..99 | foreach { [Web.Security.Membership]::GeneratePassword(6,0) }


Iska 12-05-2020 19:36 2920899

Коллеги, не надо ничего «генерировать». Нужно просто составить все возможные комбинации.

megaloman 12-05-2020 19:44 2920900

Цитата:

Цитата SoulGood
если необходимо сгенерировать все возможные пароли без повторов »

то поставленная задача прктически повторяет эту решенную.
Вот та задача с выводом результатов в файл и с Вашим набором символов.
Код:

@Echo Off
        Set "S=0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z"
        Set /A M=6
        Set "FileOut=Z:\Box_Out\FileOut.txt"

        Set /A N=10
        For %%@ In (a b c d e f g h i j k l m n o p q r s t u v w x y z) Do Set /A N+=1 &Call Set "@V%%N%%=%%%%%%%%@"

        Set /A MM=%M%+10
        Set "Com="
        Set "Rez=Echo "
        FOR /L %%$ IN (11,1,%MM%) DO Call Set "Com=%%Com%%For %%@V%%$%% In (%S%) Do " &Call Set "Rez=%%Rez%%%%@V%%$%%"
        >"%FileOut%" (%Com%%Rez%)
Exit /B

Упрощенный вариант для 6 символов в строке
Код:

@Echo Off
        Set "Simb=0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z"
        Set "FileOut=Z:\Box_Out\FileOut.txt"
       
        >"%FileOut%" (For %%i In (%Simb%) Do For %%j In (%Simb%) Do For %%k In (%Simb%) Do For %%l In (%Simb%) Do For %%m In (%Simb%) Do For %%n In (%Simb%) Do Echo %%i%%j%%k%%l%%m%%n)
Exit /B

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

Лабораторка? :maniac:

YuS_2 12-05-2020 20:36 2920907

Цитата:

Цитата Iska
Нужно просто составить все возможные комбинации. »

Посчитаем:
powershell
Код:

function get-factorial([int]$num = 1) {
        switch ($num -le 1) {
                $true { $num }
                $false {$num*(get-factorial(--$num))}
        }
}

# количество комбинаций
$n = '0123456789abcdefghijklmnopqrstuvwxyz'
$m = 6

$C = (get-factorial $n.length)/((get-factorial $m)*(get-factorial ($n.length - $m)))
$C

1947792 - число комбинаций...
Количество потраченного времени будет зависеть от скорости перебора комбинаций.
Допустим, 10 в секунду. Тогда:
Код:

$C/10/60/60/24
2,25438888888889 дней непрерывного перебора... как-то так :yes:

megaloman 12-05-2020 22:10 2920914

YuS_2,
Цитата:

Цитата YuS_2
1947792 »

С комбинаторикой у меня отношения напряженные, но, ИМХО, у Вас вкралась ошибка.
Мы имеем тридцатишестиричную систему исчисления.
Я посчитал тупо: =35*36^0+35*36^1+35*36^2+35*36^3+35*36^4+35*36^5=2 176 782 335
Если в секунду 100000 строк, то 2 176 782 335/100000/60/60=6 час
Строка 6 символов занимает 8 байт. Файл 8*2 176 782 335=17 414 258 680=16Гб
:mail1:

Fors1k 12-05-2020 23:37 2920921

Цитата:

Цитата megaloman
ИМХО, у Вас вкралась ошибка »

Вот, можете проверить:
Код:

Param(
    $m=6, # Размер комбинации
    $n=36 # Количество используемых элементов
)cls

function Get-Possibility{param($m,$n)$i,$j=1,1

    ($n-$m+1)..$n|%{$i*=$_};
    1..$m|%{$j*=$_} ; $i/$j

}

"Вариантов сочетаний: "+(Get-Possibility $m $n)


#Вариантов сочетаний: 1947792


megaloman 12-05-2020 23:48 2920922

Fors1k_m, так каждый может! Вы мне Мурку сбацайте! Дайте формулу, а не программу.

Fors1k 12-05-2020 23:54 2920923

Вложений: 1
Цитата:

Цитата megaloman
Дайте формулу »


megaloman 13-05-2020 00:51 2920926

Fors1k_m, давайте упростим задачу: есть символы 0 1 2 3 4 5 6 7 8 9 a b c d e f
То есть имеем 16 цифр стандартной шестнадцатиричной системы.
Всевозможные комбинации этих цифр можно получить элементарным счетом:
000000 000001 000002 ... 00000f 000010 ... ffffff
Возьмите любой калькулятор, который переводит числа из шестнадцатиричной системы в десятичную, и переведите в десятичную число:
ffffff=16 777 215
То есть вот это количество уникальных чисел от 000000 до ffffff
То есть символов (16) гораздо меньше рассматриваемых в предложенной задаче (36), а чисел намного больше, чем насчитали Вы 1 947 792 для бОльшего числа символов. То есть, Ваше число вычислено некорректно.
Похоже, и я ошибаюсь на 1 (не учитываю в подсчете 000000)

Кстати, вот калькулятор, можете там напрямую перевести число ZZZZZZ тридцатишестиричной системы в десятичную.

Fors1k 13-05-2020 01:41 2920928

Кстати, так как мы говорим о паролях, то ab и ba это разные наборы данных, а значит количество возможных уникальных комбинаций здесь будет не 1 947 792, а 1 402 410 240.
Вычисление
Код:

Param(
    $m = 6, # Размер комбинации
    $n = 36 # Количество используемых элементов
)cls

function Get-Possibility($m,$n)
{
    $i,$j=1,1;1..$n|%{$i*=$_;}
    1..($n-$m)|%{$j*=$_};$i/$j
}

"Вариантов размещений: "+(Get-Possibility $m $n)



Итог:
Замер для(1/1000) 1 402 411 комбинаций показал:
Время: 12сек.
Размер файла:10,7MB
Для полного объема вариантов ориентировочно будет:
Время: 3ч.20мин
Размер файла:10,45GB

YuS_2 13-05-2020 08:09 2920935

Цитата:

Цитата megaloman
С комбинаторикой у меня отношения напряженные, но, ИМХО, у Вас вкралась ошибка. »

Возможно, делал по памяти, "на скорую руку"... но ошибка, скорее всего, при исправлении, приведет к большим значениям
Цитата:

Цитата megaloman
Дайте формулу, а не программу. »

Например, вот

Цитата:

Цитата Fors1k_m
Кстати, так как мы говорим о паролях, то ab и ba это разные наборы данных, а значит количество возможных уникальных комбинаций »

Точно! Вот и ошибка моя нашлась, нам нужны размещения, а не сочетания... :)

Код:

function get-factorial([int]$num = 1) {
        switch ($num -le 1) {
                $true { $num }
                $false {$num*(get-factorial(--$num))}
        }
}

# количество размещений
$n = '0123456789abcdefghijklmnopqrstuvwxyz'
$m = 6

$A = (get-factorial $n.length)/(get-factorial ($n.length - $m))
$A

1402410240

YuS_2 13-05-2020 08:47 2920939

Цитата:

Цитата Fors1k_m
Замер для(1/1000) »

Где-то в замерах ошибка, ибо:
скорость - 1000 комбинаций в секунду (такая скорость точно реальна?)
1402410240/1000/60/60/24 = 16,2316 дней

Fors1k 13-05-2020 09:24 2920942

Цитата:

Цитата YuS_2
скорость - 1000 комбинаций в секунду »

Почему 1000 в секунду?) Перебор 1 402 411 Комбинаций занял 12сек.
Скорость=1 402 411 Комбинаций / 12 сек= 116 867 комбинаций в секунду. Но у меня ещё комп очень старый(Intel LGA775), думаю у других побыстрее будет.
Так как 1 402 411 - это одна тысячная от общего количества, то для всех вариантов время=12*1000/60/60=3 часа 20 минут.

Fors1k 13-05-2020 10:17 2920945

Кстати, так как набор символов неисчерпаем, то количество возможных уникальных комбинаций для данной задачи будет не 1 402 410 240, а 2 176 782 336.
Вычисление:
Код:

Param(
    $m=6, # Размер комбинации
    $n=36 # Количество используемых элементов
)cls

function Get-FullPossibility($m, $n)
{
    $i=$j=$k=$z=1;($n-$m+1)..$n|%{$i*=$_};1..$m|
    ForEach{$j*=$_};1..$n|%{$k*=$_;};1..($n-$m)|
    ForEach-Object{$z*=$_};$p=[Math]::Pow($n,$m)

    Write-Output @{
        "Вариантов сочетаний " = ($i/$j)
        "Вариантов размещений" = ($k/$z)
        "Вариантов размещений с повторами" = $p
    }|FT -AutoSize
}

Get-FullPossibility $m $n

Код:

Name                            Value   
----                            -----   
Вариантов сочетаний              1947792 
Вариантов размещений            1402410240
Вариантов размещений с повторами 2176782336

Итог:
Замер для(1/1000) 2 176 783 комбинаций показал:
Время: 18сек.
Размер файла:16,6MB
Для полного объема вариантов ориентировочно будет:
Время: 5ч.
Размер файла:16,2GB

megaloman 13-05-2020 10:25 2920946

YuS_2, Fors1k_m,
Следите за руками, никакого мошенничества!
Доводим задачу до маразма: набор символов 0123456789, надо посчитать, сколько чисел содержится в диапазоне от 000000 до 999999.
Считаем: раз два три четыре пять .... МИЛЬЁН! (если приплюсовать 000000)
Вот результаты скрипта YuS_2, (цитирую с минимальными изменениями для приведенного случая):
Код:

function get-factorial([int]$num = 1) {
        switch ($num -le 1) {
                $true { $num }
                $false {$num*(get-factorial(--$num))}
        }
}

# количество размещений
$n = '0123456789'
$m = 6

$A = (get-factorial $n.length)/(get-factorial ($n.length - $m))
$A

=151200
Если на клетке слона прочтешь надпись: буйвол, — не верь глазам своим.
Кстати, если длина строки =2 (00 - 99) Ваш скрипт декларирует 90. - что-то в консерватории надо менять.
Мой суперноут 2007 года выпуска по скрипту
Код:

@Echo Off
rem        Set "Simb=0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z"
        Set "Simb=0 1 2 3 4 5 6 7 8 9"
        Set "FileOut=Z:\Box_Out\FileOut.txt
       
        >"%FileOut%" Echo %time%       
        >>"%FileOut%" (For %%i In (%Simb%) Do For %%j In (%Simb%) Do For %%k In (%Simb%) Do For %%l In (%Simb%) Do For %%m In (%Simb%) Do For %%n In (%Simb%) Do Echo %%i%%j%%k%%l%%m%%n)
        >>"%FileOut%" Echo %time%       
Exit /B

выдал результат:
Код:

9:58:10,67       
000000
000001
000002

......

999997
999998
999999
9:58:46,80

То есть, 1 000 000/36=28 000 строк/сек и мои отпотолочные предположения о 100 000 строк/сек не такие уж невероятные, а то и весьма скромные
Fors1k_m, Ура, конСЕКСус!
Цитата:

Цитата Fors1k_m
2 176 782 336 »


Busla 13-05-2020 11:00 2920950

Цитата:

Цитата YuS_2
1947792 - число комбинаций... »

megaloman прав, вы посчитали размещение без повторений - количество вариантов перемешать символы в строке
впрочем, я опоздал со своим комментарием

Fors1k 13-05-2020 11:27 2920958

Цитата:

Цитата Busla
Цитата:

Цитата YuS_2
1947792 - число комбинаций... »

вы посчитали размещение без повторений »

Это результат расчета количества сочетаний.

Iska 13-05-2020 11:30 2920959

Busla, а вот тут вопрос — как именно трактовать авторское:
Цитата:

Цитата SoulGood
без повторов »

:).

YuS_2 13-05-2020 12:08 2920961

Цитата:

Цитата Fors1k_m
Почему 1000 в секунду? »

:dont-know , где-то попалась на глаза цифра, вот и подумалось...

Цитата:

Цитата Fors1k_m
так как набор символов неисчерпаем »

Хмм, это чего? набор из 36 символов - что тут неисчерпаемого, поясните?

Цитата:

Цитата megaloman
надо посчитать, сколько чисел содержится в диапазоне от 000000 до 999999. »

Цитата:

Цитата megaloman
Считаем: раз два три четыре пять .... МИЛЬЁН! (если приплюсовать 000000) »

комбинаторика - раздел математики, следовательно наука точная. Если результаты не сходятся, значит в наличии ошибка... либо в формулах (что маловероятно, ибо доказываются), либо в расчетах (что гораздо более вероятно).
При анализе, достаточно ясно вырисовывается картинка, что за основу расчетов была взята формула не предполагающая наличие повторов символов, в этом моя ошибка.
В общем, формула выбрана неверно, следовательно, количество допустимых сочетаний комбинаций будет ещё больше...
Смотрим:
Код:

function get-factorial([int]$num = 1) {
        switch ($num -le 1) {
                $true { $num }
                $false {$num*(get-factorial(--$num))}
        }
}

$n = '0123456789abcdefghijklmnopqrstuvwxyz'
$m = 6

# количество уникальных сочетаний C = n!/m!*(n-m)!
$C = (get-factorial $n.length)/((get-factorial $m)*(get-factorial ($n.length - $m)))
$C

# количество неуникальных сочетаний C = (n+m-1)!/m!*(n-1)!
$Cr = (get-factorial ($n.length + $m - 1))/((get-factorial $m)*(get-factorial ($n.length - 1)))
$Cr

# количество уникальных размещений A = n!/(n-m)!
$A = (get-factorial $n.length)/(get-factorial ($n.length - $m))
$A

# количество неуникальных размещений A = n^m
$Ar = [math]::pow($n.length,$m)
$Ar

И получаем 2176782336 - неуникальных размещений.
Козьма Прутков, конечно же, совершенно прав. :)

Цитата:

Цитата megaloman
Кстати, если длина строки =2 (00 - 99) Ваш скрипт декларирует 90. - что-то в консерватории надо менять. »

Поменяем и получим то, что и должно быть - 100, просто находили мы не то, что следовало из-за ошибочного выбора формулы... :)

Цитата:

Цитата Busla
прав, вы посчитали размещение без повторений »

совершенно верно... пока писал ответ с перерывами на обед, тут уже всё разжевали без меня... :)
Ну да и пусть тоже будет...

Цитата:

Цитата Iska
как именно трактовать авторское »

в самом широком смысле, то есть - как душе угодно :)
Поэтому, видимо и требуются все варианты...

Fors1k 13-05-2020 12:16 2920965

Цитата:

Цитата Iska
как именно трактовать »

Так как речь идет о паролях, то по логике подразумевается уникальность(отсутствие повторов) самих паролей, что бы пароль от аккаунта Пети на подошел к аккаунту Коли.

Так, например, код из поста 5
Цитата:

Цитата Foreigner
все комбинации перебора строки»
Код:

0..99 | foreach { (New-Guid).Guid.Substring(0,6) }

сработает неверно для имеющейся задачи, так как выдаст неуникальные значения:
Код:

$pass=0..1296 | foreach { (New-Guid).Guid.Substring(0,2) }
cls
"Повторов: "+($pass.Count-($pass|sort -U).count)

#~Повторов: 1042

Повторы символов внутри пароля не влияют на его уникальность(ab != aa).

Цитата:

Цитата YuS_2
Хмм, это чего? набор из 36 символов - что тут неисчерпаемого, поясните? »

Исчерпаемый пул:
Набор символов - материальные шары в корзине. Если мы взяли шар с буквой 'a' в качестве первого символа, то в корзине его больше нет, и на месте второго символа он уже не окажется.
Так мы получим 1 402 410 240 вариантов.

Неисчерпаемый пул:
Набор символов - набор символов в переменной. Если мы взяли букву 'a' в качестве первого символа, то из переменной она никуда не пропадает, следовательно имеет возможность оказаться на месте и второго символа.
Так мы получим 2 176 782 336 вариантов.

YuS_2 13-05-2020 12:35 2920967

Цитата:

Цитата Fors1k_m
Неисчерпаемый пул »

Мысль понял, спасибо.

Foreigner 13-05-2020 12:52 2920968

Fors1k_m
Цитата:

Код:

$pass=0..1296 | foreach { (New-Guid).Guid.Substring(0,2) }

А если в подстроку взять только первый символ, как скоро он повторится?


Код:

0..1296 | % { (New-Guid).Guid.Substring(0,6) } | group | ? Count -gt 1
Не возвращает ни одной группы. Потому, что они все, 1297 групп, из одного элемента

Fors1k 13-05-2020 13:25 2920971

Цитата:

Цитата Foreigner
Код:

0..1296 | % { (New-Guid).Guid.Substring(0,6) } | group | ? Count -gt 1
Не возвращает ни одной группы. Потому, что они все, 1297 групп, из одного элемента »

1296 - это максимальное количество вариантов для комбинации из двух символов.(Код для проверки)

Так что либо нужно считать для комбинаций из двух:
Код:

cls;0..1296 | % { (New-Guid).Guid.Substring(0,2) } | group | ? Count -gt 1
Либо для комбинации из шести добавьте хотя бы один нолик количеству вариантов:
Код:

cls;0..12960 | % { (New-Guid).Guid.Substring(0,6) } | group | ? Count -gt 1

Jeffers 13-05-2020 13:30 2920975

Код:

cls;0..12960 | % { (New-Guid).Guid.Substring(0,6) } | group | ? Count -gt 1
Код:

Count Name                      Group
----- ----                      -----
    2 14a6c0                    {14a6c0, 14a6c0}
    2 6c8ceb                    {6c8ceb, 6c8ceb}
    2 f75d25                    {f75d25, f75d25}
    2 4d6e03                    {4d6e03, 4d6e03}

У меня вышло 4 повтора.

Foreigner 13-05-2020 13:57 2920978

Цитата:

Цитата Fors1k_m
1296 - это максимальное количество вариантов для комбинации из двух символов »

Это не перебор символов, из множества а их генерация. Естественно, что они могут повторяться. К тому же это лишь подстрока GUID (32 символа без дефисов).
12961 вариант из шести символов выдал три повтора, две сотых процента. Но это важно вообще? Возьми из массива только уникальные елементы.

Foreigner 13-05-2020 14:19 2920981

Pади интереса:
Код:

0..12960 | % { (get-random $([char[]]'0123456789abcdefghijklmnopqrstuvwxyz') -count 6) -join '' } | group | ? count -gt 1
Не выдал повторов с шести попыток.

Fors1k 13-05-2020 14:24 2920982

Цитата:

Цитата Foreigner
Естественно, что они могут повторяться.
..это важно вообще? »

Конечно важно, так как:
1. Я уже говорил о фундаментальном смысле уникальности паролей.
2. Такую задачу четко поставил автор:
Цитата:

Цитата SoulGood
необходимо сгенерировать пароли без повторов »

Цитата:

Цитата Foreigner
Возьми из массива только уникальные елементы. »

Это не решит задачу:
Цитата:

Цитата SoulGood
необходимо сгенерировать все возможные пароли»




Цитата:

Цитата Foreigner
Pади интереса:
Код:

0..12960 | % { (get-random $([char[]]'0123456789abcdefghijklmnopqrstuvwxyz') -count 6) -join '' } | group | ? count -gt 1
Не выдал повторов с шести попыток. »

Если монетка 9 раз упала орлом вверх орлом, это не значит, что на десятый бросок не будет решки.

Pади интереса:
Код:

$rep=0;$k=0
while($rep -lt 1){$k++
    $pass=1..12960|foreach { (get-random $([char[]]'0123456789abcdefghijklmnopqrstuvwxyz') -count 6) -join '' }
    $rep=($pass.Count-($pass|sort -U).count)
}
"Первый повтор встречается на $k попытке"

Код:

Первый повтор встречается на 11 попытке

megaloman 13-05-2020 19:28 2921009

Цитата:

Цитата Iska
... а вот тут вопрос — как именно трактовать авторское: Цитата SoulGood:без повторов »

и все возможные комбинации. Имхо, ушли от темы: обсуждаем число комбинаций и рандомную генерацию. Я до сих пор понимал полный набор символов от 000000 до zzzzzz, однако тут звучит идея, что в строке не должно быть повторяющихся символов. Есть ли эффективный алгоритм получения такого набора?
Вот решение "в лоб" для 6 символов в строке
Код:

@Echo Off
        Set "Simb=0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z"
rem        Set "Simb=0 1 2 3 4 5 6 7 8 9"
        Set "FileOut=Z:\Box_Out\FileOut.txt
       
        >"%FileOut%" (
                Call Echo %%time%%       
                For %%i In (%Simb%) Do (
                        For %%j In (%Simb%) Do (
                                If Not %%j==%%i For %%k In (%Simb%) Do (
                                        If Not %%k==%%i If Not %%k==%%j For %%l In (%Simb%) Do (
                                                If Not %%l==%%i If Not %%l==%%j If Not %%l==%%k For %%m In (%Simb%) Do (
                                                        If Not %%m==%%i If Not %%m==%%j If Not %%m==%%k If Not %%m==%%l For %%n In (%Simb%) Do (
                                                                If Not %%n==%%i If Not %%n==%%j If Not %%n==%%k If Not %%n==%%l If Not %%n==%%m Echo %%i%%j%%k%%l%%m%%n
                                                        )
                                                )       

                                        )
                                )
                        )
                )
                Call Echo %%time%%       
        )
Exit /B

Для отладки брал набор из 10 символов. Результат:
Код:

20:05:18,03       
012345
012346
012347
012348
012349
012354

.....

987645
987650
987651
987652
987653
987654
20:05:34,92

151200 строк
Для 36 символов не берусь оценить время
Вообще-то задача достаточно бессмысленая, разве что как лаба. Практически надо генерировать пароль рандомным образом для каждого конкретного случая, и вероятность того, что пароли совпадут, достаточно низкая

alpap 13-05-2020 21:45 2921020

Цитата:

Цитата megaloman
генерировать пароль рандомным образом для каждого конкретного случая, и вероятность того, что пароли совпадут, достаточно низкая »

правильно
Код:

@echo off
set "nA=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
set "l=6"&:[длина пароля]
set "n=10"&:[количество вариантов]
set "f=keys.log"
 
setlocal enabledelayedexpansion
 for /l %%n in (1 1 %n%) do (
  for /l %%n in (1 1 %l%) do call :#
  >>"%f%" echo:
 )
endlocal
pause& exit
 
:#
 set /a r=%random%%%36
 set "s=!nA:~%r%,1!"
 >>"%f%" <nul set /p=%s%
exit /b


Fors1k 14-05-2020 14:17 2921100

Цитата:

Цитата megaloman
Есть ли эффективный алгоритм получения такого набора? »

Код:

param(
    $pathOut = 'C:\temp\test.txt',
    $symbols = '0123456789'
)cls

$file=New-Object IO.StreamWriter ([IO.File]::Open($pathOut,'Create'))
[string[]]$sym=$symbols.ToCharArray()
(Measure-Command{
foreach($a in $sym){
foreach($b in (diff $sym ($a)).InputObject){
foreach($c in (diff $sym ($a,$b)).InputObject){
foreach($d in (diff $sym ($a,$b,$c)).InputObject){
foreach($e in (diff $sym ($a,$b,$c,$d)).InputObject){
foreach($f in (diff $sym ($a,$b,$c,$d,$e)).InputObject){

    $file.Writeline("$a$b$c$d$e$f");$i++
     
}}}}}}$file.Close()
}).TotalSeconds
"Комбинаций: $i"

По скорости получается 8,03 сек.

YuS_2 14-05-2020 16:26 2921124

Цитата:

Цитата Fors1k_m
По скорости получается 8,03 сек »

если только цифры, то можно так https://rosettacode.org/wiki/Combinations#PowerShell
для [Powershell.CSharp]::Combinations(6,10)
TotalMilliseconds : 72,4355

megaloman 14-05-2020 17:53 2921135

Цитата:

Цитата Fors1k_m
По скорости получается 8,03 сек. »

Все познаётся в корректном сравнении на одной и той же машине.
На моём суперкомпе Ваш код делается 13', мой - 17', слегка его соптимизировал - 9'
Демонстрирую:
Код:

@Echo Off
        Set "S=0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z"
        Set "S=0 1 2 3 4 5 6 7 8 9"
        Set "FileOut=Z:\Box_Out\FileOutNew.txt"

        SetLocal EnableExtensions EnableDelayedExpansion
       
        >"%FileOut%" (
                Call Echo %%time%%       
                For %%i In (%S%) Do (
                        Set "S1=!S:%%i=!" &For %%j In (!S1!) Do (
                                Set "S2=!S1:%%j=!" &For %%k In (!S2!) Do (
                                        Set "S3=!S2:%%k=!" &For %%l In (!S3!) Do (
                                                Set "S4=!S3:%%l=!" &For %%m In (!S4!) Do (
                                                        Set "S5=!S4:%%m=!" &For %%n In (!S5!) Do Echo %%i%%j%%k%%l%%m%%n
                                                )       

                                        )
                                )
                        )
                )
                Call Echo %%time%%
        )
Exit /B

Ссылку от YuS_2 не рассматривал - по условию в общем случае символы могут быть не обязательно цифры

Foreigner 15-05-2020 02:37 2921189

Прямой перебор по индексу:
Код:


$y = 6          # длина комбинации
$x = 0..9      # количество элементов

[array] $code = "for (`$c0 = 0; `$c0 -le $($y - 1); `$c0++) {"

for ($i = 1; $i -le ($y - 1); $i++)
{
    $code += "for (`$c$i = 0; `$c$i -le $($x.count-1); `$c$i++) {"
}

$res =
for ($i = 0; $i -le ($y - 1); $i++)
{
    "`$(`$c$i)"
}

$code += '"' + ($res -join '') + '"'
$code += "}" * $y
$code = $code -join "`n"

iex $($code) | sc test.txt

# 600000 записей

Обычная запись, через set-content выдаёт:
Код:

0 139 > measure-command { .\2 }


Days              : 0
Hours            : 0
Minutes          : 0
Seconds          : 10
Milliseconds      : 853
Ticks            : 108537147
TotalDays        : 0,000125621697916667
TotalHours        : 0,00301492075
TotalMinutes      : 0,180895245
TotalSeconds      : 10,8537147
TotalMilliseconds : 10853,7147

Наверное со стримрайтером будет быстрее.

Fors1k 15-05-2020 03:44 2921191

Цитата:

Цитата Foreigner
# 600000 записей »

Количество комбинаций не может быть 600 000 для "по 6 из 10". (код для проверки)
Ошибка в первом for:
Цитата:

Цитата Foreigner
[array] $code = "for (`$c0 = 0; `$c0 -le $($y - 1); `$c0++) {" »

$($y - 1) нужно заменить на $($x.count-1).

Кстати, что бы не писать все время -1, можно исользовать -lt:
Код:

for ($c0 = 0; $c0 -lt $x.count; $c0++)
Теперь получится верное количество. На моем олд пк результат 43 сек.

Foreigner 15-05-2020 09:03 2921198

Fors1k_m,
Вы код поправьте.
Выдает ворох ошибок:
Код:

C:\Users\user\Desktop\3.ps1:16 знак:22                                   
+    $file.Writeline("$a$b$c$d$e$f");$i++                               
+                      ~                                                 
Отсутствует '')'' в списке параметров функции.                           
C:\Users\user\Desktop\3.ps1:16 знак:24                                   
+    $file.Writeline("$a$b$c$d$e$f");$i++                               
+                        ~~~~~~~~~~~~~~~~~                               
Непредвиденная лексема "$b$c$d$e$f");$i++                               
                                                                         
}}}}}}$file.Close()                                                     
}).TotalSeconds                                                         
"Комбинаций:" в выражении или операторе.                                 
C:\Users\user\Desktop\3.ps1:16 знак:26                                   
+    $file.Writeline("$a$b$c$d$e$f");$i++                               
+                          ~~~~~~~~~~~~~~~                               
Непредвиденная лексема "$c$d$e$f");$i++                                 
                                                                         
}}}}}}$file.Close()                                                     
}).TotalSeconds                                                         
"Комбинаций:" в выражении или операторе.                                 
C:\Users\user\Desktop\3.ps1:16 знак:28                                   
+    $file.Writeline("$a$b$c$d$e$f");$i++                               
+                            ~~~~~~~~~~~~~                               
Непредвиденная лексема "$d$e$f");$i++                                   
                                                                         
}}}}}}$file.Close()                                                     
}).TotalSeconds                                                         
"Комбинаций:" в выражении или операторе.                                 
C:\Users\user\Desktop\3.ps1:16 знак:30                                   
+    $file.Writeline("$a$b$c$d$e$f");$i++                               
+                              ~~~~~~~~~~~                               
Непредвиденная лексема "$e$f");$i++                                     
                                                                         
}}}}}}$file.Close()                                                     
}).TotalSeconds                                                         
"Комбинаций:" в выражении или операторе.                                 
C:\Users\user\Desktop\3.ps1:16 знак:32                                   
+    $file.Writeline("$a$b$c$d$e$f");$i++                               
+                                ~~~~~~~~~                               
Непредвиденная лексема "$f");$i++                                       
                                                                         
}}}}}}$file.Close()                                                     
}).TotalSeconds                                                         
"Комбинаций:" в выражении или операторе.                                 
C:\Users\user\Desktop\3.ps1:16 знак:34                                   
+    $file.Writeline("$a$b$c$d$e$f");$i++                               
+                                  ~~~~~~~                               
Непредвиденная лексема "");$i++                                         
                                                                         
}}}}}}$file.Close()                                                     
}).TotalSeconds                                                         
"" в выражении или операторе.                                           
C:\Users\user\Desktop\3.ps1:20 знак:2                                   
+ "Комбинаций: $i"                                                       
+  ~~~~~~~~~~~                                                           
Непредвиденная лексема "Комбинаций:" в выражении или операторе.         
C:\Users\user\Desktop\3.ps1:20 знак:16                                   
+ "Комбинаций: $i"                                                       
+                ~                                                       
В строке отсутствует завершающий символ: ".                             
    + CategoryInfo          : ParserError: (:) [], ParseException       
    + FullyQualifiedErrorId : MissingEndParenthesisInFunctionParameterList
                                                                         
 0 144 >


Fors1k 15-05-2020 09:54 2921202

Цитата:

Цитата Foreigner
Вы код поправьте.
Выдает ворох ошибок: »

Скопировал код прямо из поста. Запуск кода

У megaloman тоже работает:
Цитата:

Цитата megaloman
Ваш код делается 13' ...»

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

megaloman 15-05-2020 10:08 2921204

У меня тоже был ворох ошибок, обновил PowerShell до 5.1

Foreigner 15-05-2020 11:57 2921225

Вложений: 1

megaloman:
Цитата:

обновил PowerShell до 5.1
Код:

$host.version.tostring()
5.1.18362.752

Код:

$host.version.tostring()
7.0.0


YuS_2 15-05-2020 13:05 2921242

Цитата:

Цитата Foreigner
Прямой перебор по индексу: »

надо не числа, а символы
для чисел, есть более быстродействующее решение...

Цитата:

Цитата megaloman
обновил PowerShell до 5.1 »

а ещё лучше, установить параллельно powershell core v 7.0
У него много оптимизаций было... и циклы там работают быстрее, примерно в 2 раза

Foreigner 15-05-2020 13:36 2921250

Цитата:

Цитата YuS_2
надо не числа, а символы »

А какая разница? Индекс он что для чисел, что для символов... число
А то, что есть способы быстрее, то кто бы спорил.

YuS_2 15-05-2020 16:59 2921278

Цитата:

Цитата Foreigner
А какая разница? Индекс он что для чисел, что для символов... »

Если производится замер быстродействия, то он будет некорректен, ибо работа с символами приводит к замедлению... да и топик сам не про числа-индексы ведь.
Тем не менее, Ваш способ достаточно интересный, возьму "на вооружение" :)

Foreigner 15-05-2020 20:04 2921314

Цитата:

Цитата YuS_2
ибо работа с символами приводит к замедлению... »

В данном случае скрипт работает только с индексами массива, а они [int]
Запустите с буквенно-цифровым вариантом, разницы нет, зависит только от количества циклов:
Скрытый текст

Код:

$cmb = 4
$arr = 'a','b','c','d',2,0

$code =
for ($i = 0; $i -le ($cmb - 1); $i++)
{
    "for (`$c$i = 0; `$c$i -le $($arr.Length - 1); `$c$i++) {"
}

$res =
for ($i = 0; $i -le ($cmb - 1); $i++)
{
    "`$(`$arr[`$c$i])"
}

$code += '"' + ($res -join '') + '"'
$code += "}" * $cmb
$code = $code -join "`n"

# $code  # проверка сгенерированного кода

Invoke-Expression $($code) | Set-Content test.txt


PS. Не претендую на самый быстрый и логически правильный вариант

YuS_2 16-05-2020 04:57 2921358

Цитата:

Цитата Foreigner
Запустите с буквенно-цифровым вариантом, разницы нет »

Совсем другое дело...

Вот ещё вариант ... правда он чуть медленнее, хоть и с одним циклом всего.
Код:

param (
        [string]$n = 'abcdefghij',
        [int]$m = 6
)

function combinations ([int]$x, [string]$y, [int]$lim) {
        $chararr = $y.tochararray()
        for ($j=0;$j -lt $lim;$j++){
                $k = [string[]]"$j".padleft($x,'0').tochararray()
                -join $chararr[$k]
        }
}

$z = [math]::pow($n.length,$m)

combinations $m $n $z |set-content out_test.txt


YuS_2 16-05-2020 17:05 2921423

Ну и напоследок, победитель нашего конкурса генераторов прямого перебора :) :yes: :
Код:

param(
        [string]$str = 'abcdefghij',
        [int] $lim = 6,
        [string]$path = '.\arrangement_wr_csharp_2.txt'
)

add-type @"
using System;
using System.Collections.Generic;
public class Arrangement
{
        static String Convert(string sym, int num, int tLen) {
                var sym0 = sym[0];
                var len = sym.Length;
                var res = "";
                int ind;
                while (num > 0) {
                        ind = num%len;
                        num = num/len;
                        res = sym[ind] + res;
                }
                return res.PadLeft(tLen, sym0);
        }
        public static IEnumerable<String> ArrangWithRep(string sym, int len){
                for (var i = 0; i < Math.Pow(sym.Length, len); i++)
                yield return Convert(sym, i, len);
        }
}
"@
measure-command{
$file = new-object io.streamwriter ([io.file]::open($path,'Create'))
foreach ($item in ([arrangement]::arrangwithrep($str,$lim))){
        $file.writeline($item)
}
$file.close()
} | out-file time_arrangement_wr_csharp_2.txt

TotalSeconds : 4,6773432

Iska 16-05-2020 22:45 2921465

YuS_2, подозреваю, что на чистом C, без .Net, будет ещё шустрее.

YuS_2 17-05-2020 08:06 2921482

Цитата:

Цитата Iska
на чистом C, без .Net, будет ещё шустрее. »

сложно сказать... тут ведь скрипты из шелл-ов сравниваем...

Fors1k 17-05-2020 16:35 2921515

Ну и совсем напоследок, абсолютный победитель нашего конкурса генераторов прямого перебора :clever-ma :dance: :
Код:

param(
    $pathOut = 'C:\temp\test.txt',
    $Symbols = 'abcdefghij',
    $Length  = 6
)cls

function Get-Combinations($pathOut,$Symbols,$Length){$cmd=@"
using System;using System.IO;
public class Combiner{
    public static string Combinations(string[] sym, string writePath){
        using (StreamWriter fs=new StreamWriter(writePath, false, System.Text.Encoding.Default)){
            foreach (string i in sym){//do`nfs.WriteLine (i/*i*/);}//end
        }return "Done!";}}
"@;[string[]]$sym=$Symbols.ToCharArray()
for($i=1;$i -lt $Length;$i++){$cmd=$cmd -Replace '//do', "`nforeach (string i$i in sym){//do"
$cmd=$cmd -Replace '//end', "}//end";$cmd=$cmd.Replace('/*i*/', "+i$i/*i*/")
}Add-Type $cmd;[Combiner]::Combinations($sym,$pathOut)}


(Measure-Command{

    Get-Combinations $pathOut $Symbols $Length

}).TotalSeconds

TotalSeconds : 0,2987353
еще
'abcdefghij0123' = 1,978599
'0123456789abcdefghij' = 17,4350418

megaloman 17-05-2020 18:26 2921524

Из любопытства сравнил на своём ноуте:
скрипт PS Fors1k_m
скрипт PS YuS_2
скрипт CMD Megaloman
макрос VBA Excel
скрипт Vbs

Код:

6-0123456789
Fors1k_m        PS        1.2s
Megaloman        vba Exc        4.3s       
YuS_2                PS        4.7s
Megaloman        vbs        9.3s       
Megaloman        CMD        43s       

6-0123456789abcdef
Fors1k_m        PS        10.6s
Megaloman        vba Exc        38s       
YuS_2                PS        124s
Megaloman        vbs        151s

VBS (vba) прямой перебор
Код:

'Sub rrr2()
    Symb = "abcdefghij"
    Symb = "0123456789abcdef"
'    Symb = "0123456789"
    N = 6
    FileOut = "Z:\Box_Out\6-0123456789abcdef_vbs_line.txt"
   
    T = Timer
   
    NS = Len(Symb)
    ReDim Smb(NS - 1)
   
    For i = 1 To NS
        Smb(i - 1) = Mid(Symb, i, 1)
    Next
   
    Set F = CreateObject("Scripting.FileSystemObject").CreateTextFile(FileOut, True)
    Call SortLine(N, Smb, F, 0, "")
    F.Close
   
    MsgBox Timer - T
'End Sub
Sub SortLine(ii, SS, F, NN, sOut)
    NN1 = NN + 1
   
    If NN1 = ii Then
        For Each i In SS
            sOut1 = sOut1 + sOut + i + vbCrLf
        Next
        F.Write sOut1
    Else
        For Each i In SS
            sOut1 = sOut + i
            Call SortLine(ii, SS, F, NN1, sOut1)
        Next
    End If
End Sub

и, дополнительно,
VBS генератор строк с уникальными символами
Код:

'Sub rrr()
    Symb = "0123456789abcdef"
    N = 6
    FileOut = "Z:\Box_Out\vbs_uni_6-0123456789abcdef.txt"
   
    T = Timer
   
    NS = Len(Symb)
    For i = 1 To NS
        Smb = Smb + vbTab + Mid(Symb, i, 1)
    Next
   
    Set F = CreateObject("Scripting.FileSystemObject").CreateTextFile(FileOut, True)
    Call Sort(N, Smb, F, 0, "")
    F.Close
   
    MsgBox Timer - T
'End Sub

Sub Sort(ii, SS, F, NN, sOut)
    MS = Split(Mid(SS, 2), vbTab)
    NN1 = NN + 1
   
    If NN1 = ii Then
        For Each i In MS
            sOut1 = sOut1 + sOut + i + vbCrLf
        Next
        F.Write sOut1
    Else
        For Each i In MS
            sOut1 = sOut + i
            SS1 = Replace(SS, vbTab + i, "")
            Call Sort(ii, SS1, F, NN1, sOut1)
        Next
    End If
End Sub


YuS_2 17-05-2020 19:07 2921535

Цитата:

Цитата Fors1k_m
абсолютный победитель »

это да.
Цитата:

Цитата Fors1k_m
TotalSeconds : 0,2987353 »

зависит от конфигурации железа и от версии PS...
при прочих равных, PS 5.1
TotalSeconds : 4,5936197
TotalSeconds : 1,049038
быстрее в 4,6 раз

для '0123456789abcdefghij'
TotalSeconds : 306,0904845
TotalSeconds : 42,464878
быстрее в 7,2 раз

т.е. с увеличением числа символов целевого набора, разница существенно возрастает...
а по сути:
64000000 - 42,5сек
считаем для 36 - 6:
2176782336 - 1445 сек/60= 24 мин.
уже более-менее вменяемый результат, который можно ещё ускорить, если использовать железо получше и PS v7.0

для 10^6 в PS 7.0
TotalSeconds : 3,4414547
TotalSeconds : 0,5906468

для 64000000 в PS 7.0
TotalSeconds : 214,1145746
TotalSeconds : 25,2777355

- как-то так...
файл, кстати, получается 488,2Мб

Цитата:

Цитата megaloman
Из любопытства сравнил на своём ноуте: »

а powershell какой версии? Лучше для сравнения с vbs использовать 7.0

megaloman 17-05-2020 19:19 2921537

YuS_2,
Цитата:

Цитата YuS_2
а powershell какой версии? »

5.1.14409.1005
Цитата:

Цитата YuS_2
Лучше для сравнения с vbs использовать 7.0 »

Подозреваю, разница будет еще больше.

YuS_2 17-05-2020 19:23 2921539

Цитата:

Цитата megaloman
Подозреваю, разница будет еще больше. »

можно сравнить, выше добавил тест для 20^6 и PS 7.0, на том же железе...

---------------
вот, собственно, практический результат для задачи из шапки:
36^6, PS v7.0, скрипт
TotalSeconds : 888,1523298
файл - 16,2Гб

Fors1k 17-05-2020 20:40 2921549

Цитата:

Цитата YuS_2
зависит от конфигурации железа »

Мое железо 2008г выпуска.
Интересно увидеть результат у кого-нибудь на современном пк.
Цитата:

Цитата YuS_2
если использовать PS v7.0 »

Скачал из интереса PS v7. Результат и правда изменился:

10^6 = 2,1835635
36^6 = 391,1104797

VBS (vba) от megaloman, на моем железе:
10^6 = 3,387438

YuS_2 17-05-2020 20:53 2921550

Цитата:

Цитата Fors1k_m
10^6 = 2,1835635 »

не сходится, должно быть гораздо быстрее... у меня 0,5 сек. Ваш скрипт...

Fors1k 17-05-2020 21:00 2921551

Цитата:

Цитата YuS_2
не сходится »

Похоже, результат замера для какого-то другого количества символов скопировал)
Запустил еще раз:
10^6 = 0,2484363


Время: 08:49.

Время: 08:49.
© OSzone.net 2001-