Kapz Posted December 20, 2007 Share Posted December 20, 2007 (edited) I added a post about randomizing it on the second page. I am working on a complex sorting script in my lab and I've been having some trouble trying to figure out how to tackle the program with AutoIt. I basically have a long list of possible combinations (576 elements) that I need to split into 6 smaller lists (96 elements). Each element consists of a short array of 6 different letters. The first half of the array (list element) consists of 3 letters made up of any combination of 4 letters (A,B,C, or D) but none of the letters may repeat in that instance. The second half of the array also consists of 3 letters made up of any combination of 4 other letters (E,F,G, or H) with no repeating letters for that element . Here are some possible examples: ABCEFG DBCEFG CADHEF If my math is correct, that should make 576 possible combinations assuming order matters (4 letters x 3 letters x 2 letters in the first half multiplied by 4 letters x 3 letters x 2 letters in the second half). The sort function will start out with a long list of 576 of these unique elements which is will try to split up into 6 smaller lists consisting of 96 elements. Here's the complex sort part. The smaller lists need to be counterbalanced so that there are an equal number of A's, B's, C's, D's, E's, F's, G's, and H's in them. I already know every possible combination and have written all 576 of them out in Excel, I just need to find a way to have a fancy sort script split it up so everything is counterbalanced. I have already written it out by hand using 3 possible letters rather than 4 for 4 spots (a 4 character array for each element) rather than 6 so I know its doable. Any help would be greatly appreciated! Edited January 2, 2008 by Kapz Link to comment Share on other sites More sharing options...
weaponx Posted December 20, 2007 Share Posted December 20, 2007 Easy: Do PuzzledLook() Until $forever Link to comment Share on other sites More sharing options...
Developers Jos Posted December 20, 2007 Developers Share Posted December 20, 2007 Its a nice challenge and thought i had some logic for it but didn;t work as yet .... SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
weaponx Posted December 20, 2007 Share Posted December 20, 2007 Okay I think you are using the term "array" too loosely.Each element consists of a short array of 6 different letters.I'm assuming you mean "string" and not an actual array???The first half of the array (list element) consists of 3 letters made up of any combination of 4 letters (A,B,C, or D) but none of the letters may repeat in that instance. The second half of the array also consists of 3 letters made up of any combination of 4 other letters (E,F,G, or H) with no repeating letters for that element .Again when you say "first half of the array" are you meaning first half of the string? Link to comment Share on other sites More sharing options...
Developers Jos Posted December 20, 2007 Developers Share Posted December 20, 2007 (edited) This script generated the combinations that is talked about. They need to be split into 6 stacks of 96 record in which each letter appear 72 timers ... FileDelete("test.txt") ; each char (8) needs to be in each file(6) 72 times Dim $Counters[8][6] Dim $A1[4] = ["A", "B", "C", "D"] Dim $A2[4] = ["E", "F", "G", "H"] $count = 0 For $x1 = 0 To 3 For $x2 = 0 To 3 For $x3 = 0 To 3 For $y1 = 0 To 3 For $y2 = 0 To 3 For $y3 = 0 To 3 ; Ensure different characters If $x1 = $x2 Or $x1 = $x3 Or $x2 = $x3 Then ContinueLoop If $y1 = $y2 Or $y1 = $y3 Or $y2 = $y3 Then ContinueLoop ; Check the counters to ensure that each char is only 72 times in each file FileWriteLine("test.txt", $A1[$x1] & $A1[$x2] & $A1[$x3] & $A2[$y1] & $A2[$y2] & $A2[$y3]) Next Next Next Next Next Next Edited December 20, 2007 by Jos SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
Monamo Posted December 20, 2007 Share Posted December 20, 2007 (edited) Wow.... (eyes begin to refocus) OK, I dig the concept of this one. I've got a few process flow thoughts running in my head now on how to pull it off, I'll post whatever snippets I come up with.Edit: lol, nm - apparently in the time it took me to read the description, Jos tore right through the issue (and much simpler, cleaner code than I would have had). Edited December 20, 2007 by Monamo - MoChr(77)& Chr(97)& Chr(100)& Chr(101)& Chr(32)& Chr(121)& Chr(97)& Chr(32)& Chr(108)& Chr(111)& Chr(111)& Chr(107)-------I've told you 100,000 times not to exaggerate!-------Don't make me hit you with my cigarette hand...-------My scripts:Random Episode Selector, Keyboard MouseMover, CopyPath v2.1, SmartRename for XP,Window Tracer[sup]New![/sup] Link to comment Share on other sites More sharing options...
weaponx Posted December 20, 2007 Share Posted December 20, 2007 I was on the right track too until Jos posted so I will try to work with his version. There are question marks floating over my head. Link to comment Share on other sites More sharing options...
weaponx Posted December 20, 2007 Share Posted December 20, 2007 (edited) Do I get a prize?EDIT: All fixed nowexpandcollapse popup#include <array.au3> Dim $masterArray[1000][2] $size = 96 Dim $subArray1[$size] Dim $subArray2[$size] Dim $subArray3[$size] Dim $subArray4[$size] Dim $subArray5[$size] Dim $subArray6[$size] ; each char (8) needs to be in each file(6) 72 times Dim $A1[4] = ["A", "B", "C", "D"] Dim $A2[4] = ["E", "F", "G", "H"] $count = 0 For $x1 = 0 To 3 For $x2 = 0 To 3 For $x3 = 0 To 3 For $y1 = 0 To 3 For $y2 = 0 To 3 For $y3 = 0 To 3 ; Ensure different characters If $x1 = $x2 Or $x1 = $x3 Or $x2 = $x3 Then ContinueLoop If $y1 = $y2 Or $y1 = $y3 Or $y2 = $y3 Then ContinueLoop ; Check the counters to ensure that each char is only 72 times in each file $masterArray[$count][0] = $A1[$x1] & $A1[$x2] & $A1[$x3] & $A2[$y1] & $A2[$y2] & $A2[$y3] ;$masterArray[$count][1] = Asc($A1[$x1]) + Asc($A1[$x2]) + Asc($A1[$x3]) + Asc($A2[$y1]) + Asc($A2[$y2]) + Asc($A2[$y3]) $masterArray[$count][1] = GenerateChecksum($masterArray[$count][0]) $count += 1 Next Next Next Next Next Next Redim $masterArray[$count][2] _ArraySort ($masterArray, 0,0,0,2,1) ;_Arraydisplay($masterArray) $X = 0 For $multiplier = 0 to 15 For $Y = 1 to 6 ConsoleWrite("::::::::::::::::::::::::::::::::::::::::::::::ARRAY " & $Y & @CRLF & @CRLF) For $Z = 1 to 6 $element = $Z + ($multiplier * 6) -1 Switch $Y Case 1 $subArray1[$element] = $masterArray[$X][0] Case 2 $subArray2[$element] = $masterArray[$X][0] Case 3 $subArray3[$element] = $masterArray[$X][0] Case 4 $subArray4[$element] = $masterArray[$X][0] Case 5 $subArray5[$element] = $masterArray[$X][0] Case 6 $subArray6[$element] = $masterArray[$X][0] EndSwitch ConsoleWrite("Y: " & $Y & " Z: " & $Z & " X: " & $X & @CRLF) ConsoleWrite("Element: " & $element & @CRLF) $X += 1 Next Next Next VerifyCounts($subArray1) ;_Arraydisplay($subArray1) ;_Arraydisplay($subArray2) ;exit ;_Arraydisplay($subArray3) ;_Arraydisplay($subArray4) ;_Arraydisplay($subArray5) ;_Arraydisplay($subArray6) Func VerifyCounts($theArray) $dictionaryObj = ObjCreate("Scripting.Dictionary") For $X = 0 to Ubound($theArray) - 1 $tempArray = StringSplit($theArray[$X], "") For $Y = 1 to $tempArray[0] $dictionaryObj.Item($tempArray[$Y]) = $dictionaryObj.Item($tempArray[$Y]) + 1 Next Next #include <GUIConstants.au3> GUICreate("Character Occurrences", 200) ; will create a dialog box that when displayed is centered GUISetState (@SW_SHOW) ; will display an empty dialog box $listview = GUICtrlCreateListView ("Character | Occurrences",10,10,180,380,$LVS_SORTASCENDING) For $key In $dictionaryObj.Keys() GUICtrlCreateListViewItem($key & "|" & $dictionaryObj.Item($key),$listview) Next ; Run the GUI until the dialog is closed While 1 $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Then ExitLoop Wend EndFunc Func GenerateChecksum($theString) $checksum = 0 $tempArray = StringSplit($theString, "") For $X = 1 to $tempArray[0] Switch $tempArray[$X] Case "A" $checksum += 2 Case "B" $checksum += 4 Case "C" $checksum += 8 Case "D" $checksum += 16 Case "E" $checksum += 32 Case "F" $checksum += 64 Case "G" $checksum += 128 EndSwitch Next Return $checksum EndFuncExplanation:1. All possible strings are placed into a 2 dimensional array. Dimension 1 is the string itself and dimension 2 is a "checksum" of the string which should always be the same if you were to shuffle the string.2. The array is sorted by the checksum, which effectively gives you 16 different checksums times 36 elements. To distribute an equal amount of elements from each checksum we will form the 6 arrays by taking 6 elements from each checksum "group".3. A loop is run through the master array in 16 sections, each section being a unique checksum. Each section will be read in sub-sections of 36 elements and said elements are copied into their respective array. Edited December 20, 2007 by weaponx Link to comment Share on other sites More sharing options...
Developers Jos Posted December 20, 2007 Developers Share Posted December 20, 2007 Did you check the count in each Array for A,B,C,D,E and F ? Don't think they are 72 in each array . SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
Developers Jos Posted December 20, 2007 Developers Share Posted December 20, 2007 Think this one is what is wanted..... was a nice brain buster expandcollapse popupFileDelete("Segment0.txt") FileDelete("Segment1.txt") FileDelete("Segment2.txt") FileDelete("Segment3.txt") FileDelete("Segment4.txt") FileDelete("Segment5.txt") ; each char (8) needs to be in each file(6) 72 time Dim $Counters[8][6] Dim $A1[4] = ["A", "B", "C", "D"] Dim $A2[4] = ["E", "F", "G", "H"] $count = 0 For $x1 = 0 To 3 For $x2 = 0 To 3 For $x3 = 0 To 3 For $y1 = 0 To 3 For $y2 = 0 To 3 For $y3 = 0 To 3 ; Ensure different characters If $x1 = $x2 Or $x1 = $x3 Or $x2 = $x3 Then ContinueLoop If $y1 = $y2 Or $y1 = $y3 Or $y2 = $y3 Then ContinueLoop ; Check the counters to ensure that each char is only 72 times in each file $LowestNr = 9999 $LowestFl = 6 $sf = 0 Dim $Full[6] =[0,0,0,0,0,0] ; keep track of full tables Dim $Lowest[6] =[99,99,99,99,99,99]; Find lowest count in tables Dim $Total[6] =[0,0,0,0,0,0] ; Find total counts of the whole table For $f = 0 To 5 For $c = 0 To 7 If $c < 4 Then $tc = $A1[$c] If $c > 3 Then $tc = $A2[$c - 4] If StringInStr($A1[$x1] & $A1[$x2] & $A1[$x3] & $A2[$y1] & $A2[$y2] & $A2[$y3], $tc) Then $Total[$f] += $Counters[$c][$f] ; Found full table ? If $Counters[$c][$f] > 71 Then $full[$f] = 1 ContinueLoop 2 EndIf ; tack lowest count If $Counters[$c][$f] < $Lowest[$f] Then $Lowest[$f] = number($Counters[$c][$f]) EndIf Next Next ; store result in table with lowest count and lowest total count $lows = 99 $LowestFl = 6 $Totals = 999 For $x = 0 to 5 If $full[$x] <> 1 and $Lowest[$x] <= $lows and $Totals > $Total[$x] then $lows = $Lowest[$x] $Totals = $Total[$x] $LowestFl = $x EndIf Next If $LowestFl < 6 Then ; Update the counters of the found table For $c = 0 To 7 If $c < 4 Then $tc = $A1[$c] If $c > 3 Then $tc = $A2[$c - 4] If StringInStr($A1[$x1] & $A1[$x2] & $A1[$x3] & $A2[$y1] & $A2[$y2] & $A2[$y3], $tc) Then $Counters[$c][$LowestFl] += 1 EndIf Next FileWriteLine("Segment" & $LowestFl & ".txt", $A1[$x1] & $A1[$x2] & $A1[$x3] & $A2[$y1] & $A2[$y2] & $A2[$y3]) Else ConsoleWrite("Error not able to assign this combo:" & $A1[$x1] & $A1[$x2] & $A1[$x3] & $A2[$y1] & $A2[$y2] & $A2[$y3]) EndIf Next Next Next Next Next Next Consolewrite("###################################" & @CRLF) Consolewrite("### Checkking the counts table ####" & @CRLF) Consolewrite("###################################" & @CRLF) For $f = 0 To 5 For $c = 0 To 7 ConsoleWrite($Counters[$c][$f] & " ") Next ConsoleWrite(@CRLF) Next SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
weaponx Posted December 20, 2007 Share Posted December 20, 2007 Did you check the count in each Array for A,B,C,D,E and F ? Don't think they are 72 in each array . I see what you mean. I guess I assumed there was a balanced number of each checksum after the sort (96 each times 6). I will try to fix it. Link to comment Share on other sites More sharing options...
The Ape Posted December 20, 2007 Share Posted December 20, 2007 Jos... weaponx... That code looks like fine art. Sorry... couldn't help myself. FixJaw.comTriad-Art.com Link to comment Share on other sites More sharing options...
weaponx Posted December 20, 2007 Share Posted December 20, 2007 The script I posted is all good now. 72 instances of each character in each array. Link to comment Share on other sites More sharing options...
Kapz Posted December 21, 2007 Author Share Posted December 21, 2007 Wow, that is amazing! I thought about different ways to approach the problem and I even wrote it out by hand to make sure it was doable using 3 letters for both halves (A,B,C and E,F,G) instead of 4 letters with only 4 possible spots instead of 6 in the string....and that worked. When I tried to use a 6 letter string with 4 possible characters for each half, it became much mroe complicated. I will test the code today, but thank you so very much in advance, you guys are freaken awesome! Link to comment Share on other sites More sharing options...
Kapz Posted December 21, 2007 Author Share Posted December 21, 2007 Thank you so very much for your help Jos and everyone else, the script worked perfectly! Now, on to fun experiments in the lab! Link to comment Share on other sites More sharing options...
Kapz Posted January 2, 2008 Author Share Posted January 2, 2008 This may seem very simple but I was wondering if the script could be modified to randomize what each of the 6 groups consists of? For example, the first group may have something like ABCEFG but that will never exist in the second group unless the program can be randomized to move things around into different groups. I know this is possible, I'm just not sure of an easy way to accomplish it with the script that Jos came up with? Maybe if the original list that is created is randomised first and then sorted into 6 groups? Thanks again for all of yalls help! Link to comment Share on other sites More sharing options...
weaponx Posted January 2, 2008 Share Posted January 2, 2008 I'm not really sure about what you are wanting. We have 2 pools of characters from which strings are formed, ABCD and EFGH. Are you saying you want to scramble those so it can be like DEAH BGCF??? Link to comment Share on other sites More sharing options...
Kapz Posted January 3, 2008 Author Share Posted January 3, 2008 I'm not really sure about what you are wanting. We have 2 pools of characters from which strings are formed, ABCD and EFGH. Are you saying you want to scramble those so it can be like DEAH BGCF???Let me provide a brief example of what I'm referring to. So below are two of the 6 groups with only a few items instead of 96:ABCEFGBDAEFGBCAHGEABCFEGCDBHEFADCGEHSo any one of the three combinations in the first group will never exist in the second group (ex: ABCEFG) since everything has to be counter-balanced within that group (same number of A's, same number of G's ,etc). However, you could switch up the groups by swapping the first element (ABCEFG) in group one with the first element in group 2 (ABCFEG) since they have the exact same element, just a different order. This will allow for the 6 groups to exist with everything counterbalanced within the groups. I'm just not sure how to accomplish this with the script. Does it make more sense to do this as it creates the list or would it be better to create another script that can go through and swap items out, further randomizing the lists within each of the 6 groups (of 96 elements)?Thanks! Link to comment Share on other sites More sharing options...
Kapz Posted January 4, 2008 Author Share Posted January 4, 2008 Here is the script that I came up with to accomplish what I was looking for, maybe the code can explain it better than I can with words. Sorry if my code is a bit rusty, I'm sure there is a prettier and more efficient way to accomplish this. Thanks! expandcollapse popup#include <File.au3> FileOpen("Segment0.txt", 1) FileOpen("Segment1.txt", 1) FileOpen("Segment2.txt", 1) FileOpen("Segment3.txt", 1) FileOpen("Segment4.txt", 1) FileOpen("Segment5.txt", 1) ;randomization loop max $max = 1000 ;counter of voided loops ($max - $s1 = true number of loops) $s1 = 0 ;Loop to call swap function with random list picking For $count = 1 to $max $t1 = int(random(0,5)) $t2 = int(random(0,5)) If $t1 = $t2 Then $s1 = $s1 + 1 Else Swap("Segment" & $t1 & ".txt","Segment" & $t2 & ".txt") EndIf Next ;Close all files when done FileClose("Segment0.txt") FileClose("Segment1.txt") FileClose("Segment2.txt") FileClose("Segment3.txt") FileClose("Segment4.txt") FileClose("Segment5.txt") ;Check to make sure that there are 72 occurences of each unique letter within each txt file check("Segment0.txt") check("Segment1.txt") check("Segment2.txt") check("Segment3.txt") check("Segment4.txt") check("Segment5.txt") ;Write out the number of voided loops ConsoleWrite($s1) ;Swap function to swap out one element in a txt file with a similiar element in another txt file Func Swap($list1, $list2) $stop = 0 For $d = 1 to 96 $rand2 = int(Random(1,96)) $y1 = FileReadLine($list2, $rand2) For $c = 1 to 96 $rand = int(Random(1,96)) $x1 = FileReadLine($list1, $rand) $num = StringRegExp($x1, StringLeft($y1,1)) $num = $num + StringRegExp($x1, StringRight(StringLeft($y1,2),1)) $num = $num + StringRegExp($x1, StringRight(StringLeft($y1,3),1)) $num = $num + StringRegExp($x1, StringRight(StringLeft($y1,4),1)) $num = $num + StringRegExp($x1, StringRight(StringLeft($y1,5),1)) $num = $num + StringRegExp($x1, StringRight(StringLeft($y1,6),1)) ;If match has identical letters but not necessarily in the same order then replace and exit loop If $num = 6 Then _FileWriteToLine ($list1, $rand, $y1 ,1) _FileWriteToLine ($list2, $rand2, $x1 ,1) $stop = $stop + 1 ExitLoop EndIF $num = 0 Next If $stop = 1 Then ExitLoop EndIf Next EndFunc Func Check($checklist) $A = 0 $B = 0 $C = 0 $D = 0 $E = 0 $F = 0 $G = 0 $H = 0 For $t = 1 to 96 If StringRegExp(FileReadLine($checklist,$t), "A") = 1 Then $A = $A + 1 EndIf If StringRegExp(FileReadLine($checklist,$t), "B") = 1 Then $B = $B + 1 EndIf If StringRegExp(FileReadLine($checklist,$t), "C") = 1 Then $C = $C + 1 EndIf If StringRegExp(FileReadLine($checklist,$t), "D") = 1 Then $D = $D + 1 EndIf If StringRegExp(FileReadLine($checklist,$t), "E") = 1 Then $E = $E + 1 EndIf If StringRegExp(FileReadLine($checklist,$t), "F") = 1 Then $F = $F + 1 EndIf If StringRegExp(FileReadLine($checklist,$t), "G") = 1 Then $G = $G + 1 EndIf If StringRegExp(FileReadLine($checklist,$t), "H") = 1 Then $H = $H + 1 EndIf Next ConsoleWrite("A=" & $A & " | B=" & $B & " | C=" & $C & " | D=" & $D & " | E=" & $E & " | F=" & $F & " | G=" & $G & " | H=" & $H & @CRLF) EndFunc Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now