Number logic

I am trying to write a script to take a list of numbers, each row would look like (1 - 3 - 5 - 7 - 10). Each row would be 5 or 6 numbers. based on the list, I need to print out:

  1. most frequent numbers
  2. most frequent combination. For example, (1 - 3) appears 10 times, (1 - 5 - 10) appears 20 times…etc
  3. numbers don’t have to be in sequence. for example, for ( 1 - 2 - 3 - 7 - 10) and (1 - 3 - 4 - 10 - 11) we have ( 1 - 3 - 10) appearing twice.

It would be nice to limit script to 5 or 6 numbers. I would like to run 3 numbers as well. For the 3 numbers however, I would like to have options to look up frequency based on a exact order, or any combination.

Any help or suggestions to start are greatly appreciated.

You don’t say what the largest number in any list could be, but the possible combinations of 5 positive or negative integers less than or equal to an absolute value of 11 is rather large if order isn’t important (though your examples show them in absolute value order).

the range for the 5 numbers is 1 - 39.
the range for each of the 3 numbers is 1-9. for example, 5 - 7 - 5 or 9 - 0 - 8 or 1 - 1 - 1…etc

I have two subroutines which 1) sorts a list (qsort) and 2) sorts a list of lists (sortListofLists). With these two subroutines the task didn’t seem that difficult no matter what amount of numbers you have in a row or the number of rows. The numbers don’t even have to be in order initially. The sorting takes care of all that. The final output is a list of lists sorted so that the numbers with the highest rate of occurrence are at the beginning.

The output of this script is {{3, 3}, {11, 2}, {10, 2}, {1, 2}, {9, 1}, {7, 1}, {5, 1}, {4, 1}, {2, 1}}
This means the number 3 occurs 3 times, the number 11 occurs 2 times, etc

set initialListOfLists to {{1, 2, 3, 7, 10}, {1, 3, 4, 10, 11}, {9, 3, 5, 11}}

-- first make the list of lists into one list so we can sort it
set combinedList to {}
repeat with aList in initialListOfLists
	set combinedList to combinedList & aList
end repeat

-- sort the combined list
Qsort(combinedList, 1, -1)

-- iterate the sorted list and compile the number of times each value occurs
set countOfList to count of combinedList
set i to 1
set finalStats to {}
repeat until i is greater than countOfList
	set thisValue to item i of combinedList
	if (i + 1) is greater than countOfList then -- this happens if the last value is unique
		set end of finalStats to {thisValue, 1}
		exit repeat
	else
		repeat with j from (i + 1) to countOfList
			if item j of combinedList is not equal to thisValue then exit repeat
			if j is countOfList then -- this happens if the last value is not unique
				set j to j + 1
				exit repeat
			end if
		end repeat
	end if
	set end of finalStats to {thisValue, (j - i)}
	set i to j
end repeat

-- sort the final stats and reverse it so the highest number of occurrences is shown first in the finalStats
set sortedFinalStats to sortListofLists(finalStats, 2)
set theReverse to reverse of sortedFinalStats



(*========== SUBROUTINES ============*)
on sortListofLists(array, sortItemNum) --> I modified a bublesort routine to make it work with a list of lists
	repeat with i from length of array to 2 by -1 -- go backwards
		repeat with j from 1 to i - 1 -- go forwards
			if (item sortItemNum of (item j of array)) > (item sortItemNum of (item (j + 1) of array)) then
				tell array to set {item j, item (j + 1)} to {item (j + 1), item j}
			end if
		end repeat
	end repeat
	return array
end sortListofLists

on Qsort(theList, l, r)
	-- Qsort sorts a list
	-- the authors of Qsort are Arthur Knapp and Nigel Garvey
	-- the script can be found in item 2 of http://bbs.applescript.net/viewtopic.php?id=17340
	script o
		property cutoff : 10
		property p : theList
		
		on qsrt(l, r)
			set i to l
			set j to r
			set v to my p's item ((l + r) div 2)
			
			repeat while (j > i)
				set u to my p's item i
				repeat while (u < v)
					set i to i + 1
					set u to my p's item i
				end repeat
				
				set w to my p's item j
				repeat while (w > v)
					set j to j - 1
					set w to my p's item j
				end repeat
				
				if (i > j) then
				else
					set my p's item i to w
					set my p's item j to u
					set i to i + 1
					set j to j - 1
				end if
			end repeat
			
			if (j - l < cutoff) then
			else
				qsrt(l, j)
			end if
			
			if (r - i < cutoff) then
			else
				qsrt(i, r)
			end if
		end qsrt
		
		on isrt(l, r)
			set x to l
			set z to l + cutoff - 1
			if (z > r) then set z to r
			
			set v to my p's item x
			repeat with y from (x + 1) to z
				if (my p's item y < v) then
					set x to y
					set v to my p's item y
				end if
			end repeat
			
			tell my p's item l
				set my p's item l to v
				set my p's item x to it
			end tell
			
			set u to my p's item (l + 1)
			repeat with i from (l + 2) to r
				set v to my p's item i
				if (v < u) then
					set my p's item i to u
					repeat with j from (i - 2) to l by -1
						if (v < my p's item j) then
							set my p's item (j + 1) to my p's item j
						else
							set my p's item (j + 1) to v
							exit repeat
						end if
					end repeat
				else
					set u to v
				end if
			end repeat
		end isrt
	end script
	
	set listLen to (count theList)
	if (listLen > 1) then -- otherwise the handler will error
		-- Translate negative indices
		if (l < 0) then set l to listLen + l + 1
		if (r < 0) then set r to listLen + r + 1
		
		if (r = l) then
			-- No point in sorting just one item
		else
			-- Transpose transposed indices
			if (l > r) then
				set temp to l
				set l to r
				set r to temp
			end if
			
			if (r - l < o's cutoff) then
				-- Skip the Quicksort if cutoff or less items
			else
				o's qsrt(l, r)
			end if
			o's isrt(l, r)
		end if
	end if
	
	return -- the original name of your list is the returned value
end Qsort

This is great. couple of changes I like to make to the script:

  1. accept a text files with numbers instead of adding these numbers to the script. For example, to read a text file with numbers on lines.
    for example:
    2 - 4 - 6 - 10 - 19
    1 - 9 - 34 - 45 - 46


    etc

  2. can we track frequency of combination the same way it’s done for individual numbers. for example, when we have {1, 2, 3, 7, 10}, {1, 3, 4, 10, 11} → {1,3,10} came twice. {1,3} came twice, {3,10} came twice …etc

  3. for the set of 3 numbers, I am interested in tracking frequency of (exact order and combination). for example, for the sets {1-2-3}{1-2-3}{1-3-2} → {1-2-3} showed up twice in the exact order, and 3 times as a combination.

Sure, but I don’t want to write the whole script. My script is to give you a start and some ideas. I’d rather you become a better programmer, so take my ideas and make them better. Then post what you come up with and everyone can help you make it better.

Here’s an idea about how to accomplish your #1 task. The following reads a file and breaks it up according to its lines. Then use text item delimiters to change 1 - 2 - 3 into {1,2,3} for each line. Then put them together so they’re in the right form for the rest of the script.

set theText to paragraphs of (read (choose file))

Do you have any ideas how to accomplish your #2 and #3 tasks? Maybe you need preset lists and then check each line against those preset lists? Maybe dynamically figure it out? I’m not sure. For example, if you had a list such as {1, 2, 3, 4, 5} how would you go about breaking that down into all of its number combinations? Once you can do that, then you can do the same for each 5-number list. Once all of the lists are broken up then you can compare and count them. Write some code and we can work on it.

fair enough. how I would trace actions in this script. can you do this in script editor? do you recommend other applications?
I will need to know how the starting script behaves to modify and attempt to write some codes. any suggestions on debugging/tracing applications for mac scripts?

Script editor can do this. At any point in the script, when you want to know a value, log it. Then in script editor change the bottom of the window to “event log” and you will see all what’s going on. For example run this in script editor and look at the event log… notice how the logged stuff is listed when it runs.

set theList to {1, 2, 3, 4, 5}
log "the first item is: " & item 1 of theList
set anotherList to {6, 7, 8}
log item 3 of anotherList
set combinedList to theList & anotherList
log combinedList

Also, under the window menu you have something called “event log history”. Check that out too.

that’s interesting. however the script keep running, apparently I am not logging in the right places.
any way, on the 3 item, I have some ideas how to approach this:

if I am reading from a text file, sorting the text file using a text editor like bbedit should do that job. this way, I can find the frequency of duplicate items!
however, I am still trying to figure out how to handle combination for items 2 and 3.

OK, here’s how to get all of the 2 item combinations from a list…

set aList to {1, 2, 3, 4, 5}

set twoNumberCombinations to {}
repeat with i from 1 to count of aList
	set thisItemCombos to {}
	repeat with j from 1 to count of aList
		if j is not i then
			set thisCombo to item i of aList & item j of aList
			set end of thisItemCombos to thisCombo
		end if
	end repeat
	set twoNumberCombinations to twoNumberCombinations & thisItemCombos
end repeat
return twoNumberCombinations

Building on the 2 number combinations… here’s 3 number combinations (I think!)… it’s getting complicated!

set aList to {1, 2, 3, 4, 5}

set threeNumberCombinations to {}
repeat with i from 1 to count of aList
	set thisItemCombos to {}
	repeat with j from 1 to count of aList
		if j is not i then
			repeat with k from 1 to count of aList
				if k is not j and k is not i then
					set thisCombo to item i of aList & item j of aList & item k of aList
					set end of thisItemCombos to thisCombo
				end if
			end repeat
		end if
	end repeat
	set threeNumberCombinations to threeNumberCombinations & thisItemCombos
end repeat
threeNumberCombinations

Then you can combine the two and three scripts to do it all at one time like so…

set aList to {1, 2, 3, 4, 5}

set twoCombos to {}
set threeCombos to {}
repeat with i from 1 to count of aList
	set twoReset to {}
	set threeReset to {}
	repeat with j from 1 to count of aList
		if j is not i then
			set thisTwo to item i of aList & item j of aList
			set end of twoReset to thisTwo
			repeat with k from 1 to count of aList
				if k is not j and k is not i then
					set thisThree to item i of aList & item j of aList & item k of aList
					set end of threeReset to thisThree
				end if
			end repeat
		end if
	end repeat
	set twoCombos to twoCombos & twoReset
	set threeCombos to threeCombos & threeReset
end repeat
set allCombos to twoCombos & threeCombos

I just ran the new piece of script, and not sure if that accomplishes what I was trying to do. I think the script just displays what combination we can get from a given set of number, not sure how to build on that!
here’s an example, maybe that would help.
if we have {1,2,3,4,7} and {1,3,6,7,10} and {2,4,6,7,11}
I am trying to find out what combinations of numbers appear more frequently, and how many times. so, based on the example the results should be:
{1,3} appeared 2 times
{1,3,7} appeared 2 times
{4,7} appeared 2 times
{2,4} appeared 2 times
{1} appeared 2 times
{7} appeared 3 times


etc

The idea is to first get all of the number combinations for one line of numbers. That’s what we’re doing now.

Once we can get them for one line, then we get them for all of the lines. Then finally, once we have all of them we can compare them to each other to count up the duplicates. That’s how I envision accomplishing your final goal of counting them. But we have to go one step at a time first.

So the next step is for you to take the last script, and see if you can add the ability to get 4-number and 5-number combinations to it. It’s the same thing but you need to add another repeat loop inside of the “k” repeat loop. That will be all of the possible combinations for one line of numbers.