# Problem with a "Random algorithm"

## Recommended Posts

Hi, I'm working in a new program, what the program do is:

- It opens a .txt file with a list of names (something about 5 or 6 names);

- Read this names, and sort this names randomly on the week days, throughout all the days of the month, except weekends;

- But, if the name already gets a position, it just get a new position when all the names gone;

My problem is, how do I do the to sort the names randomly? How to do a "Random Algorithm"?

Thanks, and sorry about my english!

##### Share on other sites

Something like this might work. You'd have to setup a loop to load the results of Get_Names into an array of available dates. There might be an easier way to go about it, with so few names. This routine is tuned more for large lists.

```#include<Array.au3>
Global \$names_count = 6, \$names[\$names_count + 1] = ["", "John", "Mary", "Bill", "Pat", "Debbie", "Mortimer"]
Global \$names_control[\$names_count + 1], \$names_random[\$names_count + 1]

Get_Names()
_ArrayDisplay(\$names_random)
Exit

;-------------------------------------------------------------------------------
Func Get_Names()
For \$i=1 To \$names_count
\$names_control[\$i] = \$i
Next
For \$i = 1 To \$names_count - 1
\$new = Random(\$i, \$names_count, 1)
\$names_random[\$i] = \$names[\$names_control[\$new]]
\$names_control[\$new] = \$names_control[\$i]
Next
\$names_random[\$names_count] = \$names[\$names_control[\$names_count]]
EndFunc```

Edit: moved loop to reset control array to be inside function

Edited by Spiff59

##### Share on other sites

anunes,

Have a look at this:

```#include <Array.au3>

Global \$aNames[6]
Global \$aRandom[6]
Global \$aSorted[6]

; Create dummy list of names
For \$i = 0 To 5
\$aNames[\$i] = Chr(\$i + 65)
Next

; Copy the names to another array - that way the original is untouched
\$aSorted = \$aNames
\$iCount = 0

Do
; Transfer random names to the Random array
\$iRandomIndex = Random(0, UBound(\$aSorted) - 1, 1)
\$aRandom[\$iCount] = \$aSorted[\$iRandomIndex]
; Delete that name from the array
_ArrayDelete(\$aSorted, \$iRandomIndex)
\$iCount +=1

Until \$iCount = 5

; Add the final name - because Random will not work if both Min and Max = 0
\$aRandom[5] = \$aSorted[0]

; Show result
_ArrayDisplay(\$aRandom)```

M23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

##### Share on other sites

anunes,

Have a look at this:

```#include <Array.au3>

Global \$aNames[6]
Global \$aRandom[6]
Global \$aSorted[6]

; Create dummy list of names
For \$i = 0 To 5
\$aNames[\$i] = Chr(\$i + 65)
Next

; Copy the names to another array - that way the original is untouched
\$aSorted = \$aNames
\$iCount = 0

Do
; Transfer random names to the Random array
\$iRandomIndex = Random(0, UBound(\$aSorted) - 1, 1)
\$aRandom[\$iCount] = \$aSorted[\$iRandomIndex]
; Delete that name from the array
_ArrayDelete(\$aSorted, \$iRandomIndex)
\$iCount +=1

Until \$iCount = 5

; Add the final name - because Random will not work if both Min and Max = 0
\$aRandom[5] = \$aSorted[0]

; Show result
_ArrayDisplay(\$aRandom)```

M23

M23, your program works fine when I executed the script, but, when I tried to change it, it's occours an error... here's the script

```#include <Array.au3>

Global \$aNames[6]
Global \$aRandom[6]
Global \$aSorted[6]
Dim \$sSource

\$sSource = FileOpenDialog("Abrir arquivo", @WorkingDir, "Arquivo texto (*.txt)")

; Create dummy list of names
;~ For \$i = 0 To 5
;~     \$aNames[\$i] = Chr(\$i + 65)
;~ Next

; Copy the names to another array - that way the original is untouched
\$aSorted = \$aNames
\$iCount = 0

Do
; Transfer random names to the Random array
\$iRandomIndex = Random(0, UBound(\$aSorted) - 1, 1)
\$aRandom[\$iCount] = \$aSorted[\$iRandomIndex]
; Delete that name from the array
_ArrayDelete(\$aSorted, \$iRandomIndex)
\$iCount +=1

Until \$iCount = 5

; Add the final name - because Random will not work if both Min and Max = 0
\$aRandom[5] = \$aSorted[0]

; Show result
_ArrayDisplay(\$aRandom)```

But, when the script read from the file, it doesn't create an array... So occours the error saying: "Subscript used with non-Array variable.:"

How can I try to fix it?

Edited by anunes

##### Share on other sites

anunes,

Try using FileReadToArray - AutoIt then creates the array for you. But beware - the first element in the array is the count, so you will either have to delete that element or adapt the script to not use it.

M23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

##### Share on other sites

anunes,

Try using FileReadToArray - AutoIt then creates the array for you. But beware - the first element in the array is the count, so you will either have to delete that element or adapt the script to not use it.

M23

I adapt the script to not use that element. But, there's some way to create an array with the right size, without know previously your size?

Something like this:

- I have a list of names, but I don't know how much names there's in there...

So I use _FileReadToArray, get the first element and create an array with this size. Is it possible?

##### Share on other sites

anunes,

```name1 @CRLF
name2 @CRLF etc```

All you need to do is to put these lines into your code (after making sure File.au3 is included!):

```\$sSource = FileOpenDialog("Abrir arquivo", @WorkingDir, "Arquivo texto (*.txt)")

And AutoIt does it all for you! But remember the first element is the count!

M23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

##### Share on other sites

anunes,

```name1 @CRLF
name2 @CRLF etc```

All you need to do is to put these lines into your code (after making sure File.au3 is included!):

```\$sSource = FileOpenDialog("Abrir arquivo", @WorkingDir, "Arquivo texto (*.txt)")

And AutoIt does it all for you! But remember the first element is the count!

M23

It's already done! Trying to complete the program, another doubt I'll continue in this topic!

Thanks M23

##### Share on other sites

It's already done! Trying to complete the program, another doubt I'll continue in this topic!

Thanks M23

My program is almost done, but need only one thing.

```#include <Array.au3>
#include <File.au3>
#include <Excel.au3>
#include <Date.au3>

\$arquivoFonte = FileOpenDialog("Abrir arquivo", @WorkingDir, "Arquivo texto (*.txt)")
\$numeroLinhas = _FileCountLines(\$arquivoFonte)

Global \$vetorNomes[\$numeroLinhas + 1]
Global \$vetorAleatorio[\$numeroLinhas + 1]
Global \$vetorDistribuicao[\$numeroLinhas + 1]
Global \$vetorNovo[\$numeroLinhas]
Global \$vetorNovo2[\$numeroLinhas]

; Copia os nomes prum outro vetor - assim não mexe no vetor original
; Copy the names to another array - that way the original is untouched
\$vetorDistribuicao = \$vetorNomes
\$i = 1
Do

; Transfere nomes aleatórios para o vetor Aleatorio
; Transfer random names to the Random array
\$vetorNomesAleatorios = Random(1, UBound(\$vetorDistribuicao) - 1, 1)
\$vetorAleatorio[\$i] = \$vetorDistribuicao[\$vetorNomesAleatorios]

; Deleta o nome que já foi escolhido do vetor
; Delete that name from the array
_ArrayDelete(\$vetorDistribuicao, \$vetorNomesAleatorios)
\$i = \$i + 1

Until \$i = \$numeroLinhas

; Adiciona o nome final - porque a função Random não funciona se o Min e o Max forem iguais a 0
; Add the final name - because Random will not work if both Min and Max = 0
\$vetorAleatorio[\$numeroLinhas] = \$vetorDistribuicao[1]

; Show result
;~  _ArrayDisplay(\$vetorAleatorio)

\$i = 0
While \$i < \$numeroLinhas
\$vetorNovo[\$i] = \$vetorAleatorio[\$i + 1]
\$i = \$i + 1
WEnd

\$x = 1
\$arquivoExcel = _ExcelBookNew()
\$dia = 1
\$mes = 3
\$ano = 2009
\$diafinal = 31
\$mesfinal = 12

While \$mes <> \$mesfinal Or \$dia <> \$diafinal + 1

\$dia = \$dia + 1
\$dia = \$dia + 2
EndIf

\$data_checa = \$ano & "/" & \$mes & "/" & \$dia
If _DateIsValid(\$data_checa) = 0 Then
\$mes = \$mes + 1
\$dia = 1
\$dia = 2
\$dia = 3
EndIf
EndIf

\$data = \$dia & "/ " & \$mes & "/" & \$ano
_ExcelWriteCell(\$arquivoExcel, \$data, \$x, 1)
_ExcelWriteArray(\$arquivoExcel, 1, 3, \$vetorNovo, 1)

\$dia = \$dia + 1
\$x = \$x + 1

WEnd```

Here's the code, it's just a simple test I was doing. Wath the program do is:

- It gets the file.txt with the names (one by line), randomize the list and write it on Execel;

But it just write 1 time the randomized list, wath I need is:

- Open the list and complete the dates with the names, it is, when the first randomized list finish to be writed, then it randomize again the same list an write, over and over again, until it complete the Excel date lines;

##### Share on other sites

My program is almost done, but need only one thing.

```#include <Array.au3>
#include <File.au3>
#include <Excel.au3>
#include <Date.au3>

\$arquivoFonte = FileOpenDialog("Abrir arquivo", @WorkingDir, "Arquivo texto (*.txt)")
\$numeroLinhas = _FileCountLines(\$arquivoFonte)

Global \$vetorNomes[\$numeroLinhas + 1]
Global \$vetorAleatorio[\$numeroLinhas + 1]
Global \$vetorDistribuicao[\$numeroLinhas + 1]
Global \$vetorNovo[\$numeroLinhas]
Global \$vetorNovo2[\$numeroLinhas]

; Copia os nomes prum outro vetor - assim não mexe no vetor original
; Copy the names to another array - that way the original is untouched
\$vetorDistribuicao = \$vetorNomes
\$i = 1
Do

; Transfere nomes aleatórios para o vetor Aleatorio
; Transfer random names to the Random array
\$vetorNomesAleatorios = Random(1, UBound(\$vetorDistribuicao) - 1, 1)
\$vetorAleatorio[\$i] = \$vetorDistribuicao[\$vetorNomesAleatorios]

; Deleta o nome que já foi escolhido do vetor
; Delete that name from the array
_ArrayDelete(\$vetorDistribuicao, \$vetorNomesAleatorios)
\$i = \$i + 1

Until \$i = \$numeroLinhas

; Adiciona o nome final - porque a função Random não funciona se o Min e o Max forem iguais a 0
; Add the final name - because Random will not work if both Min and Max = 0
\$vetorAleatorio[\$numeroLinhas] = \$vetorDistribuicao[1]

; Show result
;~  _ArrayDisplay(\$vetorAleatorio)

\$i = 0
While \$i < \$numeroLinhas
\$vetorNovo[\$i] = \$vetorAleatorio[\$i + 1]
\$i = \$i + 1
WEnd

\$x = 1
\$arquivoExcel = _ExcelBookNew()
\$dia = 1
\$mes = 3
\$ano = 2009
\$diafinal = 31
\$mesfinal = 12

While \$mes <> \$mesfinal Or \$dia <> \$diafinal + 1

\$dia = \$dia + 1
\$dia = \$dia + 2
EndIf

\$data_checa = \$ano & "/" & \$mes & "/" & \$dia
If _DateIsValid(\$data_checa) = 0 Then
\$mes = \$mes + 1
\$dia = 1
\$dia = 2
\$dia = 3
EndIf
EndIf

\$data = \$dia & "/ " & \$mes & "/" & \$ano
_ExcelWriteCell(\$arquivoExcel, \$data, \$x, 1)
_ExcelWriteArray(\$arquivoExcel, 1, 3, \$vetorNovo, 1)

\$dia = \$dia + 1
\$x = \$x + 1

WEnd```

Here's the code, it's just a simple test I was doing. Wath the program do is:

- It gets the file.txt with the names (one by line), randomize the list and write it on Execel;

But it just write 1 time the randomized list, wath I need is:

- Open the list and complete the dates with the names, it is, when the first randomized list finish to be writed, then it randomize again the same list an write, over and over again, until it complete the Excel date lines;

The problem was solved doing a simple loop. Thanks!

## Create an account

Register a new account