Create number sequences

Hi all,

I have a list of 200 numbers (not sequential). I need to get all the 2, 3 and 4 combinations of numbers in the list, for example

List = {153, 154, 155, 181, 182, 183, 184, 185, 208…}
2 = {{153,154}, {153,155}, {153,181}, {153,182}…} etc
3 = {{153,154, 155}, {153,155, 181}, {153,181, 182}, {153,182, 183}…} etc

(the number sequences should be in the order they are in the list - not every permutation)

I have so far come up with the following (I have commented out some of the group for reasons explained below)

script so
	property myList : {153, 154, 155, 181, 182, 183, 184, 185, 208, 209, 210, 211, 212, 213, 236, 237, 238, 239, 240, 241, 242, 263, 264, 265, 266, 267, 268, 269, 270, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497}--, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 600, 601, 602, 603, 604, 605, 606, 607, 629, 630, 631, 632, 633, 634, 635, 656, 657, 658, 659, 660, 661, 662, 686, 687, 688, 689, 690, 715}
end script

set allOptions to my getSets(so's myList, 2)

on getSets(myList, noOfInts)
	set resultsList to {}
	repeat with i from 1 to ((count myList) - (noOfInts - 1))
		set baseValue to item i of myList
		repeat with q from (i + 1) to ((count myList) - (noOfInts - 2))
			set mySet to baseValue & items q thru (q + (noOfInts - 2)) of myList
			set end of resultsList to mySet
		end repeat
	end repeat
	return resultsList
end getSetss

A couple of things to note
a) it’s really slow. For sets of 2 on a list of ~140, it’s OK - takes about 1:40 and results in 9730 pairs, but then gets exponentially slower. On the full set, it still hadn’t finished after 10 minutes. My go to method of speeding up lists with a script object hasn’t helped.
b) it’s not even a full list of variants. In the end result should there should be more variation.

I realise the final result (especially for groups of 4) will be large, but is there a better/more efficient method for doing this?

Appreciate any help you can offer

Ian

You can try something along the lines of…



set the_command to quoted form of "
import itertools
stuff = [153, 154, 155, 181, 182, 183, 184, 185, 208, 209, 210, 211, 212, 213, 236, 237, 238, 239, 240, 241, 242, 263, 264, 265, 266, 267, 268, 269, 270, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497]

for L in range(2, 5):
	for subset in itertools.combinations(stuff, L):
		print(subset)
"
try
	return do shell script "python -c " & the_command
on error err_mess
	return err_mess
end try

Hello adayzdone

It seems that there is a problem.

Your script returns combos of two digits and combos of three.
Must I understand that the greater value in the passed range is not treated ?

I tried to run the script with the range (2, 5) but Script Editor crashed.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) mardi 15 septembre 2015 17:06:23

Hi Yvan. You’re right, it should have been 2,5. It takes 40 seconds in script debugger, crashed script editor. Oh well.

Maybe a bug report to file.
Too busy to switch in 10.11 for test.

Curious details :
when it crashed, I decided to send the report to Apple. Alas the Console claimed :

2015/09/15 17:04:38,973 SubmitDiagInfo[351]: Connection to https://radarsubmissions.apple.com/submit failed. statusCode: 500 error: (null)
2015/09/15 17:04:38,973 SubmitDiagInfo[351]: Failed to submit problem report file:///Users//Library/Logs/DiagnosticReports/Script%20Editor_2015-09-15-170414_**.crash

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) mardi 15 septembre 2015 17:27:47

This edit should be considerably faster. It took ~2.5 seconds to complete on my machine.

set myList to {153, 154, 155, 181, 182, 183, 184, 185, 208, 209, 210, 211, 212, 213, 236, 237, 238, 239, 240, 241, 242, 263, 264, 265, 266, 267, 268, 269, 270, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 600, 601, 602, 603, 604, 605, 606, 607, 629, 630, 631, 632, 633, 634, 635, 656, 657, 658, 659, 660, 661, 662, 686, 687, 688, 689, 690, 715}


set noOfInts to 2
set resultsList to {}
repeat with i from 1 to ((count myList) - (noOfInts - 1))
	set baseValue to item i of myList
	repeat with q from (i + 1) to ((count myList) - (noOfInts - 2))
		set mySet to baseValue & items q thru (q + (noOfInts - 2)) of myList
		set my resultsList's end to mySet
	end repeat
end repeat
resultsList

Edit: I tested all 200, not the limited version.

Thanks for all of your replies

I tried the python version and it ran first time and then crashed Script Debugger.

Marc, your edit worked wonders!

my resultsList's end

Is this the same as referring to a script object on the way out (instead of the input)?

Ian

Hi Ian.

In Marc’s version of your script, ‘my resultsList’ references the variable ‘resultsList’ as a property of the script, instead of indicating it directly. This, for certain esoteric reasons, speeds up the action when accessing the items and properties of the list the variable contains. Although not explicitly defined as a property, ‘resultsList’ is effectlvely one in Marc’s code by virtue of being a variable used in the run handler. The same goes for ‘myList’, of course, and you could speed up the script even more by using references to that too:

set mySet to baseValue & items q thru (q + (noOfInts - 2)) of my myList

If you wanted to keep your original plan of a script object and a handler, you could set up another script object within the handler to use as a local reference object for the two lists. (Or you could just use a local object for ‘resultsList’ and reference ‘myList’ through ‘so’, which is global in this case. But I haven’t done so below.)

A less spectacular efficiency, but a good practice to remember, would be to count the list only once, before getting into the repeats:

script so
	property myList : {153, 154, 155, 181, 182, 183, 184, 185, 208, 209, 210, 211, 212, 213, 236, 237, 238, 239, 240, 241, 242, 263, 264, 265, 266, 267, 268, 269, 270, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 600, 601, 602, 603, 604, 605, 606, 607, 629, 630, 631, 632, 633, 634, 635, 656, 657, 658, 659, 660, 661, 662, 686, 687, 688, 689, 690, 715}
end script

set allOptions to getSets(so's myList, 2)

on getSets(myList, noOfInts)
	script o
		property lst : myList
		property resultsList : {}
	end script
	
	set listLen to (count myList)
	repeat with i from 1 to (listLen - (noOfInts - 1))
		set baseValue to item i of o's lst
		repeat with q from (i + 1) to (listLen - (noOfInts - 2))
			set mySet to baseValue & items q thru (q + (noOfInts - 2)) of o's lst
			set end of o's resultsList to mySet
		end repeat
	end repeat
	return o's resultsList
end getSets

Hello Nigel

Just a question :
Are you sure that the script calculate the count of items at every steps of the loop ?

I have a vague remembrance of an opposite statement saying that the count is evaluated only once.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) mercredi 16 septembre 2015 14:34:47

You’re right, but there are two repeat loops – Nigel’s code saves counting each time a new inner loop is started.

Thanks for the extra info Nigel. It is better as a handler so I can pass different size groups. Noted on the efficiency - I normally look out for performing calculations more than once, but missed it here

Ian

Hi Yvan.

Shane’s already answered the question with regard to this script. But yes, you’re quite right that when used in the parameters of ‘from . to’ or ‘times’ repeats, commands are only executed once, to set the repeat targets. Conversely, in ‘while’ or ‘until’ repeats, they’re executed on every iteration to test the exit conditions:

set myList to {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
set a to 0

repeat until (a > (count myList))
	set a to a + 1
	set myList to rest of myList
end repeat

return a
--> 6 (not 11)

@ Shane, @ Nigel

Thanks to both of you. Glad to read that my memory is not too bad.

At this time a script is available to treat combos of 2 numbers.
The original message asked for combos of 2, combos of 3 and combos of 4 :rolleyes:

Does one of you has an idea to explain why the script build upon Python crash under Script Editor but behave well under Script Debugger?
If I have time available, to-morrow I will try to run it in ASObjC Explorer.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) mercredi 16 septembre 2015 22:34:54

Yvan,

It crashed Script Debugger for me.

Ian

Which one crashed SD for you ?
Is it the script posted by adayzdone with no change or a version with a greater list of numbers, or a version in which the range was corrected replacing (2, 4) by (2, 5) ?

adayzdone is helping for years so I’m sure that he ran the posted script before posting it.

It would be interesting to know exactly why OS, which SD and which Python are used by both of you.
A single difference may explain the different behaviors.

Yvan KOENIG running Yosemite 10.10.5 in French (VALLAURIS, France) jeudi 17 septembre 2015 11:02:33

Yvan,

I tried it more than once in Script Debugger. The first time it seemed to hang for 25 seconds, then completed (i.e. showed the result) after about 32 seconds, then the application just hung and was unresponsive. Second time, it doesn’t complete, just goes to Application not responding.
OS: 10.10.5 - Macbook Pro Retina (Mid 2015) 16gb
Script Debugger 5.0.10
Python: 2.7.10

I wasn’t having a go at adayzdone at all. It was a reply to your comment that it only affected Script Editor.

Ian