Is there any way to do this? If you can’t, is there any way to do a random operation that has not been done yet? I am trying make a script that can find every possible equation that can be made from a set of numbers and operations.
Hello.
This should work:
set nmbrs to {1, 2, 3, 4, 5, 5, 6, 6}
set ops to {"-", "+", "/", "*"}
on calc(num1, op, num2)
if op = "/" and num2 ≠0 then
log num1 & "/" & num2 & " = " & (num1 / num2)
else if op = "*" then
log num1 & "*" & num2 & " = " & (num1 * num2)
else if op = "-" then
log num1 & "-" & num2 & " = " & (num1 - num2)
else if op = "+" then
log num1 & "+" & num2 & " = " & (num1 + num2)
else
log "Div/0"
end if
end calc
repeat 5 times
set num1 to some item of nmbrs
set num2 to some item of nmbrs
set op to some item of ops
calc(num1, op, num2)
end repeat
I added what kind of operation performed in the log statements, to make it more interresting.
Hi.
You’d have to be a bit more precise about what you meant by “every possible equation that can be made from a set of numbers and operations.” eg. A fixed number of numbers and/or operators per equation? Operators only used once each per equation?
To answer the question about non-repeating random choices, you can either keep making random choices until you hit on one which hasn’t been made before (not recommended, though perhaps not too disastrous with a limited number of choices) or do something like this:
-- A list of operators, each represented textually to make this possible.
set ops to {"-", "+", "/", "*"} -- Thanks to McUsr II. ;)
set c to (count ops)
-- Set up a list of consecutive integers from 1 to the number of operators.
set ints to {}
repeat with i from 1 to c
set end of ints to i
end repeat
-- Pick the operators randomly, one at a time and once only.
repeat c times
-- Choose an integer at random from the integer list.
set n to some integer of ints -- 'some number' also works, should you have more than 2 ^ 29 - 1 operators. ;)
-- Get the operator (ie. text) indexed by the integer in the operator list.
set thisOp to item n of ops
log thisOp -- Or take an appropriate action associated with the operator the text represents.
-- Eliminate the chosen integer from the integer list (index = the integer itself) with a non-integer.
set item n of ints to missing value
end repeat
what i meant by this would be something like you give the script a couple of numbers and operations and it makes all possible equations
example 1, 5, 2, 3 and +, -,*
15-2+3 = (answer here)
1-2+35 = (answer here)
etc.
in a dialog or something
Hello.
The solution is kind of cheating, but then again, I don’t have to invent a whole machinery in AppleScript, hopefully this solution works for you. if you need to raise something to a power, then [b][/b] is the operator (2**14 = 16384), and % is the modulus operator (4%3=1).
on main()
set paper to {}
set oldClip to the clipboard as record
set equation to " 2+14*7-12*8 "
set the clipboard to equation
repeat
tell application (path to frontmost application as text)
try
set equation to text returned of (display dialog "Enter a computation: " default answer equation with title "Simple Calc")
-- Command "." cancels.
on error
exit repeat
end try
end tell
try
-- use the line below if you want to calculate solely on integers.
-- set answer to do shell script "/bin/bash -c \"echo $(( " & equation & ")) \""
-- Use the line below if you want to perform calculations on decimal numbers
-- "." is then the Decimal separator you must use!
set answer to do shell script " echo '" & equation & "' | bc"
set the clipboard to answer
on error
set answer to ""
end try
if answer = "" then
set displayText to "The equation: " & equation & " isn't wellformed."
else
set displayText to equation & " = " & answer
set end of paper to displayText
set the clipboard to answer
end if
tell application (path to frontmost application as text)
display alert displayText
end tell
end repeat
if length of paper > 0 then
try
set answ to button returned of (display dialog "Do you want to paste your computations to the clipboard?" buttons {"No", "Yes"} cancel button 1 default button 2 with title "Simple Calc")
on error
set answ to "No"
end try
if answ = "Yes" then
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, return}
set paper to paper as text
set AppleScript's text item delimiters to tids
set the clipboard to paper
else
set the clipboard to oldClip
end if
else
set the clipboard to oldClip
end if
end main
main()
I am not sure if you are aware of it, so I’ll just mention, that you can perform calculations like that in the Spotlight search bar, it knows about powers (^), logarithms, (ln), and e (Exp), if it gets out of hand, then you can open the calculation in Calculator, which has “paper”, nifty!
Edit
I added a dialog, so it is easier to enter calculations. Hit Cmd -“.” to cancel the “data entry” dialog to quit.
I now store any wellformed calculation onto the clipboard, so you can use the previous result in the next calculation, by pasting it into the “data-entry” dialog.
I also added an opportunity to save the calculations to the clipboard upon quit, so that you can paste the equations with the results somewhere else, otherwise, I restore the clipboard to the contents it had before we started to compute equations.
You may note that I have wrapped it all into a main() handler, I have done that, to be pretty much sure, that the “paper” list is clear when we start, because variable that are declared at the top level, in a script, gets stored with the script, in this particular case, I have to start afresh, for the list to have the correct contents, and I chose this approach out of several other alternatives.
I still only works with integers, and that is a big constraint.
Edit++
I changed it to work with floating point numbers, NB the decimal separator is you must use is “.”, and the exponentiation operator has changed from ** to ^, now you should also be able to use parenthesis to signify the order in which operations are performed, it is still a very coarse thing, but it is now at least usable for practical purposes other than integers.
This page with ‘bc’ examples shows how and what kind of operations it can perform.
OK. So what’s really needed is an “all permutations” process rather than an “random choice” one, although random choice could then be used to determine the order in which the permutations were presented to the user.
The script below just lists the equations in permutation order. Each permutation is unique, but there are many which are mathematically identical, such as:
1+3-52 = (answer here)
1+3-25 = (answer here)
3+1-25 = (answer here)
3+1-52 = (answer here)
I can’t think of a convenient way to weed out such duplicates at the moment.
-- The numbers and operators (in text form) to use this time.
set nums to {1, 5, 2, 3}
set ops to {"+", "-", "*"}
-- Generate all possible permutations of the numbers.
set allNumPerms to allPermutations(nums)
-- Assuming there's one fewer operators than numbers, arrange the number permutations round the operators to create a text containing all the equations.
set allEquations to ""
set c to (count nums)
repeat with thisPerm in allNumPerms
set equation to ""
repeat with i from 1 to c - 1
set equation to equation & item i of thisPerm & item i of ops
end repeat
set allEquations to allEquations & (equation & item c of thisPerm & " = (answer here)" & return)
end repeat
set allEquations to text 1 thru -2 of allEquations
-- Display the results in a form where the user can enter the answers.
display dialog "Do these sums:" default answer allEquations
on allPermutations(theList)
(*
allPermutations() by Nigel Garvey, 2004.
Returns a list containing all possible permutations of a given list.
Not recommended for lists of more than about 8 items, owing to the number of permutations generated!
Based on Sedgewick's "Improved version of Heap's method (recursive)" algorithm.
*)
script o
property workList : missing value
property permutations : {}
property r : count theList -- index of the rightmost item
property m : r - 1 -- index of the middle item of the last three
on prmt(l)
-- l is the index of the leftmost item affected by this iteration
set n to r - l + 1 -- n is the number of list items affected by this iteration (l thru r)
if n = 3 then
-- These six permutations are hard-coded to reduce low-level recursion
copy my workList to the end of my permutations
set {v1, v2, v3} to items l thru r of my workList
set item m of my workList to v3
set item r of my workList to v2
copy my workList to the end of my permutations
set item l of my workList to v2
set item r of my workList to v1
copy my workList to the end of my permutations
set item m of my workList to v1
set item r of my workList to v3
copy my workList to the end of my permutations
set item l of my workList to v3
set item r of my workList to v2
copy my workList to the end of my permutations
set item m of my workList to v2
set item r of my workList to v1
copy my workList to the end of my permutations
else
-- Precalculate some values for the repeat
set lPlus1 to l + 1 -- parameter for next-level recursions
set nIsEven to (n mod 2 = 0) -- true if n is even
set x to r -- the default index with which to swap if n is odd
-- Get all permutations of items (l +1) thru r with the current item l
prmt(lPlus1)
-- Repeat with successive values of item l
repeat with i from r to lPlus1 by -1
-- If n is even, swap items l and i, otherwise default to swapping items l and r
if nIsEven then set x to i
tell item x of my workList
set item x of my workList to item l of my workList
set item l of my workList to it
end tell
prmt(lPlus1)
end repeat
end if
end prmt
end script
if o's r < 3 then
-- Special-case lists of less than three items
copy theList to the beginning of o's permutations
if o's r is 2 then set the end of o's permutations to the reverse of the beginning of o's permutations
else
-- Otherwise use the recursive handler
copy theList to o's workList
o's prmt(1)
end if
return o's permutations
end allPermutations
Hello Nigel.
Amazing, both your script, and also the difference in perceiving the problem.
What if you used this:
set answer to do shell script "/bin/bash -c \"echo $(( " & equation & ")) \""
, and built up a list with the answers during the course as you created the permutations. Then afterwards you could check the corresponding operations for having the same operators and the same numbers.
I just sense, that it should work out correctly, since pieces that contains the same numbers, and the same operators must necessarily be perceived as the “same” equation. -At least there are two expressions, that contains the same bits, and gives the same result, so at least the “commutatively equal” expressions, can be eliiminated.
Here’s another version of the script in post #6, based on the fact that nightfury2986’s example also has the operators in different permutions. (Depending on the operators and whether or not they’re unique, this could have mathematical implications.) The order of the resulting set of equations is randomised using the method from post #3. [Edit: now changed to the use of ‘random number’ and an in-place shuffle.] The hope is that this will produce a more “interesting” random result and that any mathematic duplicates will be less noticeable. The number of possible permutations with four numbers and three operators is 144, so the text is simply returned here instead of being displayed.
Further edit: the equations now include their results instead of “(answer here)”.
-- The numbers and operators (in text form) to use this time.
set nums to {1, 5, 2, 3}
set ops to {"+", "-", "*"}
-- Generate all possible permutations of the numbers and of the operators.
set allNumPerms to allPermutations(nums)
set allOpPerms to allPermutations(ops)
-- Assuming there's one fewer operators than numbers, arrange the number permutations round the operator permutations to create a list containing all the possible equations.
set allEquations to {}
set c to (count nums)
repeat with thisOpPerm in allOpPerms
repeat with thisPerm in allNumPerms
set equation to ""
repeat with i from 1 to c - 1
set equation to equation & item i of thisPerm & item i of thisOpPerm
end repeat
set equation to equation & item c of thisPerm
set end of allEquations to equation & " = " & (run script equation)
end repeat
end repeat
-- Randomise the list of equations.
repeat with i from (count allEquations) to 1 by -1
set n to (random number from 1 to i)
tell item i of allEquations
set item i of allEquations to item n of allEquations
set item n of allEquations to it
end tell
end repeat
-- Coerce the randomised list to a return-delimited text.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set allEquations to allEquations as text
set AppleScript's text item delimiters to astid
return allEquations
on allPermutations(theList)
(*
allPermutations() by Nigel Garvey, 2004.
Returns a list containing all possible permutations of a given list.
Not recommended for lists of more than about 8 items, owing to the number of permutations generated!
Based on Sedgewick's "Improved version of Heap's method (recursive)" algorithm.
*)
script o
property workList : missing value
property permutations : {}
property r : count theList -- index of the rightmost item
property m : r - 1 -- index of the middle item of the last three
on prmt(l)
-- l is the index of the leftmost item affected by this iteration
set n to r - l + 1 -- n is the number of list items affected by this iteration (l thru r)
if n = 3 then
-- These six permutations are hard-coded to reduce low-level recursion
copy my workList to the end of my permutations
set {v1, v2, v3} to items l thru r of my workList
set item m of my workList to v3
set item r of my workList to v2
copy my workList to the end of my permutations
set item l of my workList to v2
set item r of my workList to v1
copy my workList to the end of my permutations
set item m of my workList to v1
set item r of my workList to v3
copy my workList to the end of my permutations
set item l of my workList to v3
set item r of my workList to v2
copy my workList to the end of my permutations
set item m of my workList to v2
set item r of my workList to v1
copy my workList to the end of my permutations
else
-- Precalculate some values for the repeat
set lPlus1 to l + 1 -- parameter for next-level recursions
set nIsEven to (n mod 2 = 0) -- true if n is even
set x to r -- the default index with which to swap if n is odd
-- Get all permutations of items (l +1) thru r with the current item l
prmt(lPlus1)
-- Repeat with successive values of item l
repeat with i from r to lPlus1 by -1
-- If n is even, swap items l and i, otherwise default to swapping items l and r
if nIsEven then set x to i
tell item x of my workList
set item x of my workList to item l of my workList
set item l of my workList to it
end tell
prmt(lPlus1)
end repeat
end if
end prmt
end script
if o's r < 3 then
-- Special-case lists of less than three items
copy theList to the beginning of o's permutations
if o's r is 2 then set the end of o's permutations to the reverse of the beginning of o's permutations
else
-- Otherwise use the recursive handler
copy theList to o's workList
o's prmt(1)
end if
return o's permutations
end allPermutations
Hello Nigel.
I didn’t see the randomizing at first. The unordering provides a good variety.
Yeah. I hope it gives nightfury2986 something with which to work.
I’ve been thinking about the randomisation process though. I used the integer-list method because AppleScript’s ‘some’ reference is so much faster than the StandardAdditions’s ‘random number’ ” even without referencing the list variable ”that you can add in the times taken to build the integer list and then replace its integers with missing values and still finish ahead of ‘random number’! With the 144-item lists here though, the difference is only .005 seconds on my machine, so I’ve decided to simplify things by dispensing with both the integer list and the additional list for the rearranged equations. Instead there’s an in-place rearrangement of the original equation list, using ‘random number’ to decide the swaps. Edited in post #8 above.
ok thanks! but, i actually wanted the (answer here) to be an answer, and it was 2 AM so i really didn’t want to do math
so i just put an (answer here) >.< sorry for the confusion
Hello. I actually read the code in a hurry, and just sort of ran it, sort of without thinking.
So I ran back, and wrote what a good idea it was to permute from left to right, for us that read from left to right, then the left side changes the most often, and maybe that camouflages the ordering that is there?
I also had fun with counting the number of combinations, since the permuted list is really combinations of permutatins, 4*3^2 (Cartesian product).
It was an interesting thread.
I think the algorithm in Sedgewick’s booklet changed from the left. But after I transcribed it for AppleScript, I did a from-the-right version too, which I much preferred precisely because of the more ordered look of the results! I couldn’t immediately lay my hands on either script today, but eventually tracked down the from-the-right version in an old post to the MACSCRPT mailing list. That’s the version used above.
Luckily, the day’s work wasn’t wasted. The change only required a small adjustment in the code populating the equation list. That’s now done in the script in post #8.
Thanks!