I’m assuming that this was a typo, and that it should have read ‘here is my final computer BINGO. All I need is to sort the final list of numbers called’. And that is the British ‘sort’ ( meaning to resolve or complete the list of Bingo numbers ) rather than any actually sorting.
I approached this similarly, avoiding a ‘called numbers’ list. But randomizing the entire set of possible bingo calls at the beginning doesn’t seem like the programatic equivalent of pulling balls from the shaker. I decided to ‘remove the balls’ from the list as they are ‘called’. It seemed more in keeping with the game to me.
Here’s another solution to the task. It uses two repeats, but handles the randomisation and sorting in one go if the source list in order. (The numbers in the returned list are in the same order as in the source list.) It relies on the fact that the bingo numbers here are text, whereas the integers used to index them aren’t.
set bingo_numbers to {"B01", "B02", "B03", "B04", "B05", "B06", "B07", "B08", "B09", "B10", "B11", "B12", "B13", "B14", "B15"}
set numberRequired to 8
copy bingo_numbers to called_numbers
repeat with i from 1 to (count called_numbers)
set item i of called_numbers to i
end repeat
repeat numberRequired times
set i to some integer of called_numbers
set item i of called_numbers to item i of bingo_numbers
display alert (result)
end repeat
return text of called_numbers
Paul, you may be correct, but if so what does the OP mean when he states:
On a side note, after I get the list of numbers called in order, can I sort the list numerically, the variable numbers called
Well done, Nigel! Below is my version, which is similar but not nearly as elegant. By my testing your version is the fastest yet.
set bingo_numbers to {"B01", "B02", "B03", "B04", "B05", "B06", "B07", "B08", "B09", "B10", "B11", "B12", "B13", "B14", "B15"} as list
set countOfBingoNumbers to count of bingo_numbers
set called_numbers to {}
set count_of_called_numbers to 0
set desiredNumber to 8
repeat countOfBingoNumbers times
set the end of called_numbers to ""
end repeat
repeat
set randomIndex to random number from 1 to countOfBingoNumbers
set randomChoice to item randomIndex of bingo_numbers
if randomChoice is not in called_numbers then
set item randomIndex of called_numbers to randomChoice
set count_of_called_numbers to count_of_called_numbers + 1
end if
if count_of_called_numbers = desiredNumber then exit repeat
end repeat
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {" "}
set called_numbers to words of (text items of called_numbers as text)
set AppleScript's text item delimiters to saveTID
I did a bit of reading on the Bingo game, and all Bingo numbers consist of one letter of the word Bingo-- followed by the number 01 to 15 for the letter B, 16 to 30 for the letter I, and so on. As a result, it makes better sense not to do a traditional sort and instead to return all “B” Bingo numbers with a numerical sub-sort, followed by all “I” Bingo numbers with a numerical subsort, and so on. If one uses a list of all 75 Bingo numbers in their correct order, that’s exactly what Nigel’s script does.
However, the game appears to continue until someone yells “Bingo”, and imposing an 8-number limit would seem inadvisable. So, my modification of Nigel’s script is:
set bingo_numbers to {"B01", "B02", "B03", "B04", "B05", "B06", "B07", "B08", "B09", "B10", "B11", "B12", "B13", "B14", "B15", "I16", "I17", "I18", "I19", "I20", "I21", "I22", "I23", "I24", "I25", "I26", "I27", "I28", "I29", "I30", "N31", "N32", "N33", "N34", "N35", "N36", "N37", "N38", "N39", "N40", "N41", "N42", "N43", "N44", "N45", "G46", "G47", "G48", "G49", "G50", "G51", "G52", "G53", "G54", "G55", "G56", "G57", "G58", "G59", "G60", "O61", "O62", "O63", "O64", "OG5", "O66", "O67", "O68", "O69", "070", "071", "072", "073", "074", "075"}
copy bingo_numbers to called_numbers
set bingo_numbers_count to (count bingo_numbers)
repeat with i from 1 to bingo_numbers_count
set item i of called_numbers to i
end repeat
repeat bingo_numbers_count times
set i to some integer of called_numbers
set item i of called_numbers to item i of bingo_numbers
set buttonReturned to button returned of (display alert (result) buttons {"End", "Continue"})
if buttonReturned is "End" then exit repeat
end repeat
return text of called_numbers
It’s like the Lottery. Each player’s card only contains a subset of the possible numbers.
But I think the point of the task may have been lost in all the different contributions and healthy discussion its inspired here. Shawn’s “final computer BINGO” does indeed select all seventy-five items from the source list in a random order, the fact that dialogs were only appearing for a subset of them being a bug in the original script. But in post #4, he also asks how to sort the returned list. Clearly it would be simpler just to sort the original list. So the random selection and the sorting could be separate coding exercises on his part rather than an attempt to produce an integrated and actually useful script.
Thanks Nigel. I agree wholeheartedly that this is a coding exercise only, and hopefully we will hear back from Shawn as to his sorting requirements.
Once again as a coding exercise, I couldn’t help but wonder how one might script a Bingo card, and I have included my suggestion below. The timing result was one millisecond.
set theColumns to getColumns()
set bingoCard to getBingoCard(theColumns)
on getColumns()
set theColumns to {}
repeat with i from 1 to 61 by 15
set aColumn to {}
repeat with j from i to i + 14
set end of aColumn to j
end repeat
set aColumn to getShuffledColumn(aColumn)
set end of theColumns to aColumn
end repeat
set item 3 of item 3 of theColumns to "**" -- "**" is a free square
return theColumns
end getColumns
on getBingoCard(theList)
set text item delimiters to {" "}
set theString to "B I N G O" & linefeed
repeat with i from 1 to 5
set aList to {}
repeat with j from 1 to 5
set end of aList to item i of item j of theList
end repeat
set theString to theString & (aList as text) & linefeed
end repeat
set text item delimiters to {""}
return theString
end getBingoCard
on getShuffledColumn(theNumbers)
set shuffledNumbers to {}
repeat until (count shuffledNumbers) is 5
set aNumber to (text -2 thru -1 of ("0" & (some item of theNumbers)))
if aNumber is not in shuffledNumbers then set end of shuffledNumbers to aNumber
end repeat
return shuffledNumbers
end getShuffledColumn
Indeed. This script (refined from @robertfern script) properly selects 8 random items from 15 element list. But, still your script in post #3 gives the exact mathematical solution + better speed than all others. Also, I don’t understand why it is faster than other plain AppleScript solutions. I tested without display alert.
Paul, you may be correct, but if so what does the OP mean when he states:
On a side note, after I get the list of numbers called in order, can I sort the list numerically, the variable numbers called
This does sound like a request for an actual sort.
In Bingo, once someone calls out “BINGO!” the “dealer” has to confirm that the card column/row/etc matches the called numbers. The claimant calls out each of their matched values and the dealer compares these to the called values. A sorted list of the called values would aid in this check.
But, still your script in post #3 gives the exact mathematical solution + better speed than all others. Also, I don’t understand why it is faster than other plain AppleScript solutions.
Hi KniazidisR.
I hadn’t tested any of the scripts for speed. But the post #3 script (simply a fix for Shawn’s in post #1) uses AppleScript’s built-in some specifier to make the random choices, whereas many of the other contributions use the StandardAdditions’s random number command. Being built-in, some executes faster than a call to an OSAX, where communication time’s a factor. But it’s limited to choosing items from lists and doesn’t generate actual numbers like random number does. Nor can the range from which the choice is made be specified.
The beauty of Nigel’s last version and mine is that the list is populated in order so there’s no need for sorting. (Nigel’s does it better and faster).
Here’s a different, but similar script.
This one builds a deck of cards, shuffles it, then deals seven five-card hands
set handSize to 5
set numberOfHands to 7
set unShuffledDeck to DeckOfCards()
set shuffledDeck to ShuffleDeck(unShuffledDeck)
set theHands to DealTheCards(shuffledDeck, handSize, numberOfHands)
on DealTheCards(shuffledDeck, handSize, numberOfHands)
set theHands to {}
repeat numberOfHands times
set the end of theHands to {}
end repeat
set x to 1
repeat handSize times
set y to 1
repeat numberOfHands times
set the end of item y of theHands to item x of shuffledDeck
set x to x + 1
set y to y + 1
end repeat
end repeat
return theHands
end DealTheCards
on ShuffleDeck(unShuffledDeck)
copy unShuffledDeck to blankDeck
repeat with i from 1 to (count unShuffledDeck)
set item i of blankDeck to i
end repeat
set x to 0
set shuffledDeck to {}
repeat 52 times
set x to x + 1
set i to some integer of blankDeck
set item i of blankDeck to ""
set thisCard to item i of unShuffledDeck
set the end of shuffledDeck to thisCard
end repeat
return text of shuffledDeck
end ShuffleDeck
on DeckOfCards()
set cardSuits to words of "Clubs Diamonds Hearts Spades"
set theDeck to {}
repeat with thisSuit in cardSuits
set x to 1
repeat 13 times
if x = 1 then
set thisCard to "Ace"
else if x = 11 then
set thisCard to "Jack"
else if x = 12 then
set thisCard to "Queen"
else if x = 13 then
set thisCard to "King"
else
set thisCard to x as text
end if
set thisCard to thisCard & " of " & thisSuit
set the end of theDeck to thisCard
set x to x + 1
end repeat
end repeat
return theDeck
end DeckOfCards
But randomizing the entire set of possible bingo calls at the beginning doesn’t seem like the programatic equivalent of pulling balls from the shaker
Why not? at least from a end-result perspective they are the same.
My script essentially puts all the balls in a random order, then pops them off one by one - essentially saying ‘this is the order the balls are going to come out in’
A ‘traditional’ model pulls the balls out one at a time. In a physical world you know the ball hasn’t been used before, and can’t be used again, but that’s not the same with the scripted approaches.
Either way, the result at the end of the day is a randomized order of balls. The difference is that with my approach you know, for sure, that a ball has not been called before, so there’s no extra checking involved.
I have no justification for my perspective on the sorting all the values up-front vs repeatedly selecting random values. There is no testable difference between the two methods. None of this is truly random in any case. I just prefer the real-world-parity of randomly selecting the next value at the time it is needed and removing it from the pool of available choices. I suppose it’s a bit of skeuomorphic programing.
The only functional difference in the two methods that I can conceive of is that one has predetermined and stored the results. Bingo hackers could exploit this! I know that is ridiculous, but I did enjoy typing “Bingo hackers”!
Bingo hackers aside, I’m too lazy to type in all 75 bingo numbers.
So here’s Nigel’s solution with the numbers generated automatically.
If I were doing this for real (setting up an AppleScript bingo game) I would use myriad tables and display the updated called numbers with every draw. (Rows would be numbers called, columns would be “B I N G O”
Buttons would be Call Next Number and “BINGO” (if someone calls Bingo there would be an option to continue (false bingo), quit or start a fresh round)
set numberRequired to 25
set bingo_numbers to GetBingoNumbers()
copy bingo_numbers to called_numbers
repeat with i from 1 to (count bingo_numbers)
set item i of called_numbers to i
end repeat
repeat numberRequired times
set i to some integer of called_numbers
set item i of called_numbers to item i of bingo_numbers
end repeat
return text of called_numbers
on GetBingoNumbers()
set bingoLetters to characters of "BINGO"
set bingoNumbers to {}
set x to 0
repeat with thisLetter in bingoLetters
repeat 15 times
set x to x + 1
set the end of bingoNumbers to thisLetter & "-" & x as text
end repeat
end repeat
return bingoNumbers
end GetBingoNumbers
Good ideal with a continuation option Ed!
Compact Bingo caller with sorted Bingo confirmation dialog and resumable calling after a false Bingo.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "GameplayKit"
use scripting additions
set randomSource to current application's GKARC4RandomSource's new()
set bingoCalls to (randomSource's arrayByShufflingObjectsInArray:{"B - 1", "B - 2", "B - 3", "B - 4", "B - 5", "B - 6", "B - 7", "B - 8", "B - 9", "B - 10", "B - 11", "B - 12", "B - 13", "B - 14", "B - 15", "I - 16", "I - 17", "I - 18", "I - 19", "I - 20", "I - 21", "I - 22", "I - 23", "I - 24", "I - 25", "I - 26", "I - 27", "I - 28", "I - 29", "I - 30", "N - 31", "N - 32", "N - 33", "N - 34", "N - 35", "N - 36", "N - 37", "N - 38", "N - 39", "N - 40", "N - 41", "N - 42", "N - 43", "N - 44", "N - 45", "G - 46", "G - 47", "G - 48", "G - 49", "G - 50", "G - 51", "G - 52", "G - 53", "G - 54", "G - 55", "G - 56", "G - 57", "G - 58", "G - 59", "G - 60", "O - 61", "O - 62", "O - 63", "O - 64", "O - 65", "O - 66", "O - 67", "O - 68", "O - 69", "O - 70", "O - 71", "O - 72", "O - 73", "O - 74", "O - 75"}) as list
repeat with i from 1 to length of bingoCalls
set bingoCallResults to button returned of (display dialog return & return & tab & tab & tab & tab & tab & tab & item i of bingoCalls & return & return buttons {"BINGO!", "Call Again"} default button "Call Again")
if bingoCallResults is "BINGO!" and checkBingo(i, bingoCalls) is true then exit repeat
end repeat
on checkBingo(i, bingoCalls)
set theArray to arrayWithArray_(items 1 thru i of bingoCalls) of NSArray of current application
set calledBingoNumbers to (sortedArrayUsingSelector_("localizedStandardCompare:") of theArray) as list
set AppleScript's text item delimiters to return
if button returned of (display dialog "Called bingo numbers:" & return & return & calledBingoNumbers as text buttons {"We have a winner", "false positive"} default button "false positive") is "We have a winner" then return true
return false
end checkBingo
thank you everyone for all the help, here is one more problem
I have the random choice, says its B6
I look in a folder for a graphic named B6.jpg
all I need to do it OPEN the B6.jpg…this code is not working,
tell application "Finder"
set this_ball to every item in folder GFX_FOLDER whose name starts with randomChoice
-- this_ball = "Macintosh HD:Users:shawnbrady:Desktop:Bingo Balls GFX:B11.jpg"
-- open file this_ball DOES NOT WORK
end tell
tell application "Finder"
open document file (randomChoice & ".jpg") of folder "Bingo Balls GFX" of desktop
end tell
it tells me I dont have permission, I DO, I open GET INFO, I have permission, what the…