Jump to content

Problem with a "Random algorithm"


anunes
 Share

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!

Link to comment
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
Link to comment
Share on other sites

  • Moderators

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)

Ask if anything is unclear.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
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)

Ask if anything is unclear.

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)")
$aNames = FileRead($sSource)

; 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
Link to comment
Share on other sites

  • Moderators

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

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
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?

Link to comment
Share on other sites

  • Moderators

anunes,

I assume your file is already in the form of:

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)")
_FileReadToArray($sSource, $aNames)

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

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

anunes,

I assume your file is already in the form of:

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)")
_FileReadToArray($sSource, $aNames)

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

Link to comment
Share on other sites

  • 2 weeks later...

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]

    _FileReadToArray($arquivoFonte, $vetorNomes)

    ; 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]

    ; Mostra o resultado
    ; 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
    
    $diadasemana = _DateToDayOfWeek($ano, $mes, $dia)
    
    If $diadasemana = 1 Then
        $dia = $dia + 1
    ElseIf $diadasemana = 7 Then
        $dia = $dia + 2
    EndIf
    
    $data_checa = $ano & "/" & $mes & "/" & $dia
    If _DateIsValid($data_checa) = 0 Then
        $mes = $mes + 1
        $dia = 1
        $diadasemana = _DateToDayOfWeek($ano, $mes, $dia)
        If $diadasemana = 1 Then 
            $dia = 2
        ElseIf $diadasemana = 7 Then
            $dia = 3
        EndIf
    EndIf
    
    $diadasemana = _DateToDayOfWeek($ano, $mes, $dia)
    $data = $dia & "/ " & $mes & "/" & $ano
    _ExcelWriteCell($arquivoExcel, $data, $x, 1)
    _ExcelWriteCell($arquivoExcel, _DateDayOfWeek($diadasemana), $x, 2)
    _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;

Sorry about the bad english, if you not understand something, please, ask, and correct me in PM!

Link to comment
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]

    _FileReadToArray($arquivoFonte, $vetorNomes)

    ; 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]

    ; Mostra o resultado
    ; 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
    
    $diadasemana = _DateToDayOfWeek($ano, $mes, $dia)
    
    If $diadasemana = 1 Then
        $dia = $dia + 1
    ElseIf $diadasemana = 7 Then
        $dia = $dia + 2
    EndIf
    
    $data_checa = $ano & "/" & $mes & "/" & $dia
    If _DateIsValid($data_checa) = 0 Then
        $mes = $mes + 1
        $dia = 1
        $diadasemana = _DateToDayOfWeek($ano, $mes, $dia)
        If $diadasemana = 1 Then 
            $dia = 2
        ElseIf $diadasemana = 7 Then
            $dia = 3
        EndIf
    EndIf
    
    $diadasemana = _DateToDayOfWeek($ano, $mes, $dia)
    $data = $dia & "/ " & $mes & "/" & $ano
    _ExcelWriteCell($arquivoExcel, $data, $x, 1)
    _ExcelWriteCell($arquivoExcel, _DateDayOfWeek($diadasemana), $x, 2)
    _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;

Sorry about the bad english, if you not understand something, please, ask, and correct me in PM!

The problem was solved doing a simple loop. Thanks!
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...