| Bytes | Lang | Time | Link |
|---|---|---|---|
| 105 | Zsh | 250223T115457Z | roblogic |
| 202 | APLNARS | 250222T145450Z | Rosario |
| 188 | Kotlin 2.0+ | 250221T092145Z | Joon Yor |
| 151 | Python 3 | 230203T220157Z | DaveM552 |
| 036 | Jelly | 230202T175456Z | The Thon |
| 157 | Python 3 | 230131T192952Z | The Thon |
| 038 | Japt mR | 230131T123507Z | Shaggy |
| 225 | C gcc | 230201T004136Z | ErikF |
| 094 | Raku | 230201T192610Z | Sean |
| 120 | Bash + GNU utils | 230201T173800Z | Digital |
| 049 | Pip | 230201T162852Z | DLosc |
| 132 | JavaScript ES6 | 230131T094505Z | Arnauld |
| 032 | 05AB1E | 230201T074322Z | Kevin Cr |
| 029 | Vyxal J | 230131T081618Z | lyxal |
| 046 | APL Dyalog Extended | 230131T212637Z | Adá |
| 211 | QBasic | 230131T204812Z | DLosc |
| 039 | Pyth | 230131T154423Z | CursorCo |
| 123 | Factor | 230131T122340Z | chunes |
| 049 | Charcoal | 230131T100830Z | Neil |
Zsh, 105 bytes
repeat $1 {A=(B I N G O `(for i ({1..75..15})shuf -i$i-$[i+14] -n5)|rs -t 5`)
A[18]=free;<<<$A|rs 6;echo}
APL(NARS), 202 chars
next←1
r←n rndu w;t
r←∅⋄→0×⍳(w<n)∨(n≤0)∨(w≥1E9)∨w≤0⋄r←⍬
next←2147483648∣12345+next×1103515245
t←1+w∣⌊next÷65536⋄→2×⍳t∊r⋄r,←t⋄→2×⍳0<n-←1
f←{⍪{M←⊃(15×0..4)+{5 rndu ⍵}¨15×⍵⍴1⋄M[3;3]←⊂'free'⋄⍉'BINGO',M}¨⍵⍴5}
//7+13+36+38+41+67 rndu would return n random numbers in 1..w without repetition, or ∅ if n>w. Reference is the function rand in the book "The C Language" Brian W. Kernignan, Dennis M. Ritchie. This seems ok even if I m not 100% sure.
test:
f 3
B I N G O
8 26 35 48 74
1 17 31 60 67
12 21 free 47 75
7 20 44 58 61
13 28 42 51 71
B I N G O
1 28 40 57 64
10 23 45 55 62
9 20 free 52 72
3 29 39 48 70
13 30 34 46 73
B I N G O
10 20 39 59 67
14 29 42 58 63
12 23 free 60 68
5 25 41 51 72
3 21 31 52 66
f 1
B I N G O
15 30 34 50 73
7 16 44 46 72
13 24 free 47 67
3 18 38 58 69
10 26 35 52 66
Kotlin 2.0+, 188 bytes
fun b(x:Int)=repeat(x){println("\nB I N G O");val c=List(5){(it*15+1..it*15+15).shuffled().take(5)};repeat(5){i->println((0..4).joinToString(" "){if(i==2&&it==2)"free"else"${c[it][i]}"})}}
I take advantage of shuffled() to randomize numbers but not have duplicates, also saves an import of Kotlin's random; aside from that I just print the columns of the 2d vector c but print free if I get to the center of the 2d vector which is c[2][2]
Python 3, 151 bytes
from random import *
print("B I N G O")
x=lambda n:n*15+randint(0,15)
[print(*[*("free"if(i==2 and j==2)else x(j)for j in range(5))])for i in range(5)]
Jelly, 38 36 bytes
75s15Ẋ€ḣ€5Z“ƝM»€3¦€3¦“BINGO”ṭṚK€Y⁷Ṅ)
Most of the credit goes to @cairdcoinheringaahing and @UnrelatedString for helping me in chat.
- -2 thanks to UnrelatedString
This can probably be a bit shorter, though.
Explanation
75 # 75 (implicit range)
s15 # Split into 15 parts
Ẋ€ # Random permutation of each
ḣ€5 # First 5 elements of each
Z # Transpose
“ƝM» # Replace ↓ with "free"
€3¦€3¦ # The third item in the third item (1-indexed)
“BINGO” # Push "BINGO"
ṭṚ # Append and reverse (i.e. prepend)
K€ # Join each by spaces
Y⁷ # Join by newlines and append a newline
Ṅ # Print
) # Repeat input number of times
Python 3, 198 166 157 bytes
lambda n:exec('m=["BINGO",*map(list,zip(*[sample(range(i,i+15),5)for i in range(1,75,15)])),""];m[3][2]="free";[print(*i)for i in m];'*n)
from random import*
(ATO isn't working right now so I switched to TIO)
- -32 thanks to tsh
This can probably be golfed a bit more.
Japt -mR, 39 38 bytes
75õ òF Ëö¤v5Ãg2Èh2`fe`ÃÕi"BINGO"¬ m¸·
75õ òF Ëö¤v5Ãg2Èh2`fe`ÃÕi"BINGO"¬ m¸· :Implicit map of range [0,input)
75õ :Range [1,75]
ò :Partitions of length
F : 15
Ë :Map
ö¤ : Shuffle
v5 : First 5 elements
à :End map
g2 :Modify the element at 0-based index 2 by
È :Passing it through the following function
h2 : Replace the element at 0-based index 2 with
`fe` : Compressed string "free"
à :End modification
Õ :Transpose
i :Prepend
"BINGO"¬ : "BINGO", split into an array
m :Map
¸ : Join with spaces
· :Join with newlines
:Implicit output joined with newlines
C (gcc), 262 225 bytes
- -37 thanks to c--
a[6][5]={L"BINGO"};f(n,i,j,k,r){--n&&puts("",f(n));for(j=5;j--;)for(k=i=0;k||++i<6;k||(a[i][j]=r))for(r=j*15+rand(k=i)%15+1;--k&&a[k][j]-r;);for(i=0;i<6;i+=puts(""))for(j=0;j<5;)printf(i*j-9?i?"%d ":"%c ":"free ",a[i][j++]);}
Ungolfed (` used instead of literal tab character):
a[6][5]={L"BINGO"}; // bingo array, with header
f(n, // number of cards to generate
i,j, // row and column
k, // random number row checker
r // random number
) {
--n && puts("",f(n)); // recursively print cards, adding newline
for(j=5;j--;) // for each column
for(k=i=0;k||++i<6;k||(a[i][j]=r)) // for each row (redo duplicates)
for(r=j*15+rand(k=i)%15+1;--k&&a[k][j]-r;); // detect duplicates
for(i=0;i<6;i+=puts("")) // mark middle item as free; print board
for(j=0;j<5;)
printf(i*j-9?i?"%d`":"%c`":"free`",a[i][j++]);
}
Raku, 94 bytes
{join "
",({S:13th/\d+/free/}((<B I N G O>,|[Z] (1..75).rotor(15)».pick(5)).join("
"))xx$_)}
(1..75).rotor(15)splits the range 1-75 into five subranges of size 15: 1-15, 16-30, etc.».pick(5)selects five distinct random elements from each of those subranges.[Z]reduces that list of lists of random choices with theZip operator. It effectively transposes the matrix, so the 1-15 selections are in the first column instead of the first row.<B I N G O>,|...prepends the header row to the lists of numbers..join("\n")joins the rows with newlines, producing a Bingo board as a single string. The actual code uses a single newline character between the quotes to save a byte.S:13th/\d+/free/changes the thirteenth occurrence of a number in that string tofree.xx $_replicates the preceding process a number of times given by the input argument$_, producing a list of board strings.join "\n\n"joins those boards together with two newlines between them.
Bash + GNU utils, 120
for((;j++<$1;));{
for((;++i<75;));{
a+=" <(shuf -i$i-$[i+=14] -n5)"
}
eval paste$a|sed '1iB I N G O
3s/\w*/free/3
$a
'
}
Pip, 50 49 bytes
La{Y ZSH*\,75CH5y@2@2:"free"P_JsPBnMyH5PE"BINGO"}
Explanation
La{...}
Given command-line argument a, loop that many times:
Y ZSH*\,75CH5
\,75 ; Inclusive range from 1 to 75
CH5 ; Chop into 5 equal sections
SH* ; Randomly shuffle each section
Z ; Transpose
Y ; Yank that result into the y variable
y@2@2:"free" ; Set the element of y at index 2,2 to the string "free"
P_JsPBnMyH5PE"BINGO"
yH5 ; Take the first 5 elements of y
PE"BINGO" ; Prepend the element "BINGO"
M ; Map to each:
_Js ; Join on spaces
PBn ; and push a newline to the end of the resulting string
P ; Print that list, concatenated, with a trailing newline
JavaScript (ES6), 132 bytes
f=N=>(F=n=>N?n<30?F[k=n%5]^(F[k]|=1<<(v=Math.random()*15))?(n++-17?"_BINGO"[n]||k*15-~v:'free')+`
`[k>>2]+F(n):F(n):`
`+f(N-1):n)``
Commented
f = N => ( // outer function taking the number N of grids
F = n => // inner function taking a counter n
N ? // if there's still a grid to process:
n < 30 ? // if n is less than 30:
F[k = n % 5] // k is the column index in [0..4]
^ // if F[k] is not equal to its updated value
( F[k] |= 1 << ( // where the floor(v)-th bit is set
v = // where v is
Math.random() // randomly picked in [0,15[
* 15 //
)) ? // then:
( n++ - 17 ? // if this is not the center cell:
"_BINGO"[n] // append either a BINGO letter (if n <= 5)
|| // or
k * 15 - ~v // the number k * 15 + floor(v + 1)
: // else:
'free' // append the word 'free'
) + //
` \n`[k >> 2] + // append a line-feed if k = 4,
// or a space otherwise
F(n) // append the result of a recursive call to F
: // else:
F(n) // try again
: // else:
`\n` + // append a line-feed followed by
f(N - 1) // the result of a recursive call to f
: // else:
n // stop the recursion
)`` // initial call to F with n zero'ish
05AB1E, 32 bytes
F75L5äε.r5£N<i'€²2ǝ}}ø‘Èß‘Sš»,¶?
Explanation:
F # Loop the (implicit) input-integer amount of times:
75L # Push a list in the range [1,75]
5ä # Split it into five equal-sized parts
ε # Map over each part:
.r # Randomly shuffle the list
5£ # Then only keep the first 5 integers
N<i # If the index is 2:
'€² '# Push dictionary string "free"
2ǝ # Insert it at (0-based) index 2 into the quintuplet-list
}} # Close both the if-statement and map
ø # Zip/transpose the matrix; swapping rows/columns
‘Èß‘ # Push dictionary string "BINGO"
S # Convert it to a list of characters: ["B","I","N","G","O"]
š # Prepend it to the matrix
» # Join each inner list by spaces; and then each string by newlines
, # Pop and print it with trailing newline
¶? # And print an additional newline character
See this 05AB1E tip of mine (section How to use the dictionary?) to understand why '€² is "free" and ‘Èß‘ is "BINGO".
Vyxal J, 29 bytes
(‛₆ṫ⇧Ṅ75ɾ15ẇƛÞ℅5Ẏ;∩2≬2‛λċȦV⁋¶
Explained (old)
( # input times:
75ɾ15ẇ # push the range [1, 75] split into chunks of 15 items
ƛÞ℅5Ẏ; # to each: random_permutation[:5]
∩ # transpose
2≬2‛λċȦV # tos[2][2] = "free"
‛₆ṫ⇧p # .prepend("BINGO")
vṄ⁋ # .map(" ".join(x)).join("\n")
¶+, # + "\n" (then print)
APL (Dyalog Extended), 46 bytes
Full program. Prompts for n.
('BINGO'{'free'}¨@3@4⍤⍪(15×…4)+⍤1⍉)⍤2↑5?¨⎕5⍴15
⎕5⍴15 prompt for n and join that 5, then use that as dimensions for an array of 15s
5?¨ for each 15, get 5 random numbers in the range 1 through that, without replacement
↑ mix this matrix of lists into an n-by-5-by-5 array with each row being a randome 5-of-15
(…)⍤2 on each layer:
⍉ transpose, so the 5-of-15 rows become columns
(…)+⍤1 add the following to each row:
…4 the numbers 0 through 4
15× fifteen multiplied by those
'BINGO'…⍤⍪ prepend a row of the given letters, then:
…@4 at row 4:
…@3 at column 3:
{…}¨ replace each value (though there's only one) with:
'free' the given word
QBasic, 211 bytes
DIM b(5,5)
RANDOMIZE TIMER
INPUT n
FOR i=1TO n
ERASE b
?
?"B","I","N","G","O
FOR r=0TO 4
FOR c=0TO 4
4x=INT((c+RND)*15+1)
FOR p=0TO r
IF x=b(p,c)GOTO 4
NEXT p
IF(r=2)*(c=2)THEN?"free",ELSE?x,:b(r,c)=x
NEXT c,r,i
Try it at Archive.org! Example run:
Explanation/ungolfed
DIM b(5, 5)
RANDOMIZE TIMER
INPUT n
Declare b as a 5x5 array; we'll use this to track already-selected numbers and avoid duplicates. Seed the pseudo-random number generator using the current time. Prompt the user for the number of cards n.
FOR i = 1 TO n
Loop n times:
ERASE b
PRINT
PRINT "B", "I", "N", "G", "O"
Set all values in b to zero. Print a blank line followed by the B I N G O header. The commas in the PRINT statements separate the items by tabs, using a default tab stop of 14 columns.
FOR r = 0 TO 4
FOR c = 0 TO 4
Loop over rows 0 through 4; for each row, loop over columns 0 through 4.
4 x = INT((c + RND) * 15 + 1)
Label this as line number 4, which we'll use as a GOTO target later. Set x to be a random integer, greater than or equal to c*15+1, and less than (c+1)*15+1.
FOR p = 0 TO r
IF x = b(p, c) THEN GOTO 4
NEXT p
Loop over each previous row p. If x equals the value in array b at row p, column c, go back to line 4 and generate a new random number.
IF (r = 2) * (c = 2) THEN
PRINT "free",
ELSE
PRINT x,
b(r, c) = x
END IF
If both r and c are 2, print the string "free"; otherwise, print x and set the appropriate value in the b array to x. In both cases, end the print statement with a tab rather than a newline.
NEXT c, r, i
Close all the FOR loops.
Astute readers may have noticed this doesn't print a newline at the end of each row. Because of the size of the default tab stop, it just so happens that the sixth column wraps to the next line, so printing a newline explicitly is unnecessary (and, in fact, results in unwanted blank lines). This might be bending the I/O requirements a bit. If an explicit newline must be printed, modify the B I N G O line by adding ", at the end, and add a line containing ? in between the FOR r and FOR c headers.
Pyth, 39 bytes
VQkjd"BINGO"jjL\ Cc5X%3s.SMc5S75y6"free
Explanation
# implicitly assign Q = eval(input())
VQ # for N in range(Q):
k # print a newline
jd"BINGO" # print BINGO joined on spaces
S75 # range(1,76)
c5 # split into 5 equal parts
.SM # randomly shuffle each part
s # join the parts back together
%3 # take every third element
X y6"free # replace the 12th element with "free"
c5 # split into 5 equal parts again
C # transpose
jL\ # join each part on whitespace, converting all elements to strings
j # join on newlines and print
Factor, 123 bytes
[ [ "free"2 75 [1,b] 15 group [ 5 sample ] map flip
[ third set-nth ] keep "BINGO"1 group prefix simple-table. nl ] times ]
[ ... ] timesDo something a number of times.
"free" ! "free"
2 ! "free" 2
75 ! "free" 2 75
[1,b] ! "free" 2 { 1 2 ... 75 }
15 ! "free" 2 { 1 2 ... 75 } 15
group ! "free" 2 { { 1 2 .. 15 } { 16 17 .. 30 } ... { 61 62 .. 75 } }
[ 5 sample ] map ! "free" 2 {
! { 9 13 14 1 5 }
! { 26 24 25 27 22 }
! { 32 38 41 31 33 }
! { 54 59 55 49 57 }
! { 75 74 70 71 63 }
! }
flip ! "free" 2 {
! { 9 26 32 54 75 }
! { 13 24 38 59 74 }
! { 14 25 41 55 70 }
! { 1 27 31 49 71 }
! { 5 22 33 57 63 }
! }
[ third set-nth ] keep ! {
! { 9 26 32 54 75 }
! { 13 24 38 59 74 }
! { 14 25 "free" 55 70 }
! { 1 27 31 49 71 }
! { 5 22 33 57 63 }
! }
"BINGO" ! { ... } "BINGO"
1 group ! { ... } { "B" "I" "N" "G" "O" }
prefix ! {
! { "B" "I" "N" "G" "O" }
! { 9 26 32 54 75 }
! { 13 24 38 59 74 }
! { 14 25 "free" 55 70 }
! { 1 27 31 49 71 }
! { 5 22 33 57 63 }
! }
simple-table. ! output to stdout
nl ! newline
Charcoal, 54 52 49 bytes
FN«≔⪪BINGO¹θF²⁵⊞θ⎇⁼κ¹²free‽⁻⁺×¹⁵﹪κ⁵…¹¦¹⁶θ⟦E⪪θ⁵⪫κ
Try it online! Link is to verbose version of code. Explanation: Now inspired by @Arnauld's answer.
FN«
Input n and loop that many times.
≔⪪BINGO¹θ
Start with a list of BINGO as separate characters which will make up the first row.
F²⁵
Loop 25 times.
⊞θ⎇⁼κ¹²free‽⁻⁺×¹⁵﹪κ⁵…¹¦¹⁶θ
Put the word free in the middle cell, otherwise take a random element of the appropriate numeric range for the cell but subtracting all of the numbers generated so far, and push the result to the list.
⟦E⪪θ⁵⪫κ
Split into rows of five cells, join the rows on spaces and output the resulting board double-spaced from the next board.
