13
\$\begingroup\$

The challenge, should you accept it, is to determine how much you win in the Bingo Golf Flax Lottery. Based on but not equal to the BingoFlax lottery

The input is two lists of numbers (positive non-zero integers).

The first list always contains 24 potentially non-unique numbers that make up your board, a 5 x 5 grid of numbers from the list in reading order: Left to right, top to bottom. The mid cell is always a free cell (a "wild card") that matches any number and this is why the board input is 24 numbers and not 25 (=5*5). Note: the same number may appear more than once.

The second input list is of any length. These are numbers that may or may not match numbers on your board.

Matching numbers may or may not end up making one or more winning patterns on your board.

The type of winning pattern if any determine how much you win.

If more than one winning pattern emerge, only the one with the most prize money matter. Don't sum up the patterns.

The winning patterns and their prize money are:

enter image description here

Your program or function should return 500000, 10000, 1000, 500, 200, 100, 50, 30 or 0 for no winning pattern.



Example 1:

Input: 5 21 34 51 74 3 26 39 60 73 2 28 59 67 12 30 33 49 75 10 17 40 50 66
and: 33 10 7 12 60 49 23 38 15 75 40 30
Winning pattern: horizontal line.
Result: 50

enter image description here



Example 2:

Input: 5 21 34 51 74 3 26 39 60 73 2 28 59 67 12 60 33 49 75 10 17 40 50 66
and: 33 10 7 12 60 49 23 12 15 75 40 97 74 99
Two winning patterns: horizontal and forward diagonal since the mid cell is always free – only the most winning counts
Note: 60 appear twice on the board and since 60 is called from the second list both 60's counts as a match. The one 60 in the call list matches all 60's on the board.
Result: 500

enter image description here



Example 3:

Input: 9 13 4 42 67 24 17 1 7 19 22 10 30 41 8 12 14 20 39 52 25 3 48 64
and: 9 2 4 13 11 67 42 24 41 50 19 22 39 64 52 48 3 25
Almost border, but missing 8. You still win 100 for the vertical line at the right edge.
Result: 100

enter image description here

This is Code Golf, shortest answer wins.

\$\endgroup\$
6
  • 4
    \$\begingroup\$ The last one has a vertical line. \$\endgroup\$
    – Tbw
    Jan 13 at 7:27
  • \$\begingroup\$ @Tbw – You're right. Corrected now. \$\endgroup\$
    – Kjetil S
    Jan 13 at 13:11
  • \$\begingroup\$ So for the second example, if the diagonal only had 60s, then you couldn't win with just 60, you'd need a second number? \$\endgroup\$
    – Neil
    Jan 13 at 14:51
  • \$\begingroup\$ And in that case, does that number need to be one that's not already on your grid? \$\endgroup\$
    – Neil
    Jan 13 at 14:53
  • \$\begingroup\$ @Neil – don't think I understand the question. If the 74 and 10 on the board in example 2 also was 60's, then that diagonal would be complete with just one number in the second input list if that number was 60. \$\endgroup\$
    – Kjetil S
    Jan 13 at 19:32

10 Answers 10

6
\$\begingroup\$

Excel ms365, 355,349,331,328 322 bytes

  • -6 thanks to xigoi's tip to apply scientific notation;
  • -18 due to change of regex-patterns;
  • -3 due to the trick to multiply by 100 after recursion is done given by quarague;
  • -6 deleted rf-string notation. Patterns no longer include backslashes.

Currently in Beta, use =PY() to open the python interpreter. I'm probably embarrasing myself here trying Python script but here goes:

import re
max([s[1]if re.match(s[0],re.sub('(?=.{12}$)','1',''.join([str(+(x in xl("B1:B14").values))for x in xl("A1:A24")[0]])))else 0 for s in[['1{6}(...11){3}1+$',5e3],['(1...1.1.1...){2}1',1e2],['.{6}(111..){3}',10],['.(...1){5}',5],['1(.{5}1){4}',2],['.*(1....){4}1',1],['(.{5})*1{5}',.5],['1...1.*1...1$',.3]]])*100

enter image description here

\$\endgroup\$
4
  • 2
    \$\begingroup\$ I don’t know how much Excel cares about ints vs. floats, but couldn’t you shorten 500000 => 5e5, etc.? \$\endgroup\$
    – xigoi
    Jan 13 at 11:54
  • 2
    \$\begingroup\$ I was unfamiliar with that syntax, but I just gave it a try and Excel seems to be fine with it! Thanks. I'll try to apply this tip @xigoi \$\endgroup\$
    – JvdV
    Jan 13 at 11:57
  • 1
    \$\begingroup\$ I think you can save one more byte by removing one zero from all prices (-4 bytes for the 4 prizes without scientific notation) and then applying *10 at the end +3 bytes. \$\endgroup\$
    – quarague
    Jan 15 at 12:46
  • \$\begingroup\$ @quarague a neat little trick, thanks. Figured I'd multiply by a 100 instead and save 3 bytes! \$\endgroup\$
    – JvdV
    Jan 15 at 13:20
4
\$\begingroup\$

Python 3, 263 257 250 bytes

lambda a,e:next((P[p]*c for p in P if all(a[k]in e for k in range(24)if p>>k&1)),0)
c=10.
P={16541247:5e5,9077073:1e4,235968:1e3,557328:5e2,8519745:2e2,541729:c,1083458:c,2162820:c,4329736:c,8659472:c,31:5,992:5,15360:5,507904:5,16252928:5,8912913:3}

Try it online!

Hardcodes the matches into a dictionary (can be improved).

How it works?

P actually represents the following dictionary:

P = {
    0b1111110001100011000111111: 500000, # Border
    0b1000101010001000101010001: 10000,  # Cross
    0b0000001110011100111000000: 1000,   # Picture
    0b0000100010001000100010000: 500,    # Forward diagonal
    0b1000001000001000001000001: 200,    # Backward diagonal
    0b0000100001000010000100001: 100,    # Any vertical line
    0b0001000010000100001000010: 100,
    0b0010000100001000010000100: 100,
    0b0100001000010000100001000: 100,
    0b1000010000100001000010000: 100,
    0b0000000000000000000011111: 50,     # Any horizontal line
    0b0000000000000001111100000: 50,
    0b0000000000111110000000000: 50,
    0b0000011111000000000000000: 50,
    0b1111100000000000000000000: 50,
    0b1000100000000000000010001: 30,     # All corners
}

where each key is a mask to the actual grid. The 5 least-significant bits are the first row, the following 5 are the second row, and so on.

The dictionary is ordered by score, so the first entry matched will always evaluate to the highest score possible.

The solution is a function that accepts two arguments: a list of integers of length 24 containing the actual numbers to be matched, and a list of integers of variable length containing the expected matching numbers.

That said, the algorithm is as follows: for every pattern on Patterns, check for each 1-bit if their corresponding element on a is present on e. If they all match, then return the score associated with p.

If no pattern is matched, return 0.


-6 bytes by simplifying the score constants, altering @Joao-3's magnificent idea a little bit by keeping them integers.

-7 bytes by simplifying a bit more the score constants, now making them floats.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ You can save -6 bytes by using scientific notation on 1000, 10000 and 500000 (yes it's 500000 and not 50000), although that makes them floats \$\endgroup\$
    – Joao-3
    Jan 13 at 13:12
  • \$\begingroup\$ @Arnauld Sorry, I'm not used with playing bingo. I'm currently just ignoring the "free" cell: if 4 numbers are drawn and they match the cells on positions 5x1, 4x2, 2x4 and 1x5, I consider it a forward diagonal and score it 500; I don't check 3x3 because it wasn't given in the input board (of only 24 numbers, as provided in the problem). Is that right? \$\endgroup\$
    – enzo
    Jan 13 at 13:50
  • 3
    \$\begingroup\$ @Arnauld my interpretation is the free cell can match any number, including one of the other ones already on the board. From the second example, a single number in the call sequence can be used twice on the board if that number appears twice (so you don’t need two 60s to colour in both 60s on the board) \$\endgroup\$ Jan 13 at 14:37
  • 1
    \$\begingroup\$ @NickKennedy I think you're right. I was overcomplicating this. \$\endgroup\$
    – Arnauld
    Jan 13 at 14:53
3
\$\begingroup\$

Jelly, 74 bytes

aṚḣ3ZƲ⁺FUḄ“¢Ị×O‘=&¥TṪ‘+Ị?5
e€ŒHj1s5µ,Z;ŒD,ŒdƊ§ŻŻ5eⱮTṪ»Çị“<d¥¥¦¥Þd‘HḢ;×\ƊŻ¤

A pair of links which is called as a dyad with the board as the left argument and the call sequence as the right. Returns a float containing the score.

This works by checking each of the possibilities programmatically. I started an alternative version (here) which uses a lookup table, but it’s already 65 bytes without converting to the score and so would be longer.

The test suite builds a sequence of sequences that yield every possible score for a given board (though the source sequence was constructed manually). The set-wise symmetric difference operator (œ^) is used in the footer to allow individual cells on the board to be toggled off as well as on since, for example, it’s otherwise not possible to build from a backwards diagonal to a forwards without ending up with a cross.

Explanation

aṚḣ3ZƲ⁺FUḄ“¢Ị×O‘=&¥TṪ‘+Ị?5                       # ‎⁡Helper link: takes a 5x5 grid of binary digits and returns 2, 7, 8, 9 for all corners, picture, cross, border respectively and 1 if none of those
     Ʋ                                           # ‎⁢Following as a monad:
aṚ                                               # ‎⁣- And with reverse
  ḣ3                                             # ‎⁤- First three rows
    Z                                            # ‎⁢⁡- Transpose
      ⁺                                          # ‎⁢⁢Repeat the above monad again
       F                                         # ‎⁢⁣Flatten
        U                                        # ‎⁢⁤Reverse
         Ḅ                                       # ‎⁣⁡Convert from binary digits
          “¢Ị×O‘=&¥                              # ‎⁣⁢For each of 1, 176,  17, 79, bitwise and with the result of the previous step and check if unchanged ( &Ƒ= would also work for the same bytes)
                   T                             # ‎⁣⁣Indices of truthy values
                    Ṫ                            # ‎⁣⁤Tail (will be zero if no truthy values)
                     ‘+Ị?5                       # ‎⁤⁡If 1 or zero, increment by 1, otherwise increment by 5
‎⁤⁢
e€ŒHj1s5µ,Z;ŒD,ŒdƊ§ŻŻ5eⱮTṪ»Çị“<d¥¥¦¥Þd‘HḢ;×\ƊŻ¤  # ‎⁤⁣Main link
e€                                               # ‎⁤⁤For each number on left, check whether present in right argument
  ŒH                                             # ‎⁢⁡⁡Split into two pieces of equal length (both will be 12 binary digits)
    j1                                           # ‎⁢⁡⁢Join with 1
      s5                                         # ‎⁢⁡⁣Split into pieces of length 5
        µ                                        # ‎⁢⁡⁤Start a new monadic chain
         ,Z                                      # ‎⁢⁢⁡Pair with its transpose
           ;ŒD,ŒdƊ                               # ‎⁢⁢⁢Concatenate with the major diagonals paired with the minor diagonals
                  §                              # ‎⁢⁢⁣Sums of innermost lists
                   ŻŻ                            # ‎⁢⁢⁤Prepend with zero twice (to offset the lists by two)
                     5eⱮ                         # ‎⁢⁣⁡Check which of these lists include a 5 (so a complete line)
                        TṪ                       # ‎⁢⁣⁢Last truthy index
                          »Ç                     # ‎⁢⁣⁣Max of this and the result of calling the helper link on the same 5x5 binary grid
                            ị                 ¤  # ‎⁢⁣⁤Index into the following called as a nilad:
                             “<d¥¥¦¥Þd‘          # ‎⁢⁤⁡- [60,100,4,4,5,4,20,100]
                                       H         # ‎⁢⁤⁢- Half
                                        Ḣ;×\Ɗ    # ‎⁢⁤⁣- Head (30) Concatenated to the result of cumulative product of the other values
                                             Ż   # ‎⁢⁤⁤- Prepend zero
💎

Created with the help of Luminespire.

\$\endgroup\$
3
\$\begingroup\$

APL+WIN, 216 186 bytes

30 bytes saved with better board compression Prompts for vector of first numbers followed by second

⌈/0,(25=+⌿a=(a←((25⍴2)⊤33080895 18157905 473536 1118480 17043521 17825809),(⍉10 25⍴(∊25⍴¨(⍳¨5)=5⍴¨s),,⊃s∘.=5⍴¨s←⍳5))×⍉16 25⍴(r∊⎕)+(r←(12↑n),0,12↓n←⎕)=0)/10×5E4 1E3 1E2 50 20,3,(5⍴10),5⍴5

Try it online! Thanks to Dyalog Classic

\$\endgroup\$
3
\$\begingroup\$

R, 269 224 bytes

\(x,y,`/`=c,z=x%in%y,`?`=diag,s=sapply,`~`=max)~.5/1/2/5/.3/10/100/5e3*(s(list(w<-matrix(z[1:12]/1/z[13:24],5),t(w),?w,?v=w[,5:1]),\(r)~rowSums(t(r))>4)/s(1/176/17/79,\(n)!~(m=n%/%2^(0:14)%%2)>m*((u=w*v)&u[5:1,])[1:3,]))*100

Attempt This Online!

A function that takes the board as the first argument and the call sequence as the second argument and returns the score.

Thanks to @pajonk for saving three bytes!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think you don't need the additional /0 at the end. Also, you have an extraneous space in ==m* ((. \$\endgroup\$
    – pajonk
    Jan 13 at 18:58
3
\$\begingroup\$

JavaScript (ES6), 205 bytes

Expects (board)(drawn_numbers), where board is an array of 24 integers and drawn_numbers is a set of integers.

a=>s=>(m=~a.reduce((t,v,k)=>t|s.has(v)<<k+k/12,4096))&33080895?m&18157905?m&473536?m&1118480?m&17043521?a.map(h=v=(_,i)=>v|=!(h|=!(m&31<<i%5*5),m&1082401<<i))|v?100:h?50:m&17825809?0:30:200:500:1e3:1e4:5e5

Try it online!


JavaScript (ES7), 212 bytes

Expects (board)(drawn_numbers), where board is an array of 24 integers and drawn_numbers is a set of integers.

a=>s=>"5115211111555553"[a.map((v,k)=>t|=s.has(v)<<k+k/12,t=4096),x=[33080895,18157905,473536,1118480,17043521,..."0"+17**6+8,17825809].findIndex(n=>!(~t&(n>9?n:n<6?1082401<<n:31<<n*5+2)))]*10**("661"[x]^3-x/9)|0

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Retina 0.8.2, 224 bytes

\b(\d+)\b(?=.*;.*\b(\1)\b)?(,|;.*)
$#2
13=`
1
1{6}(...11){3}1111
500000
(1...1.1.1...){2}1
10000
.{6}(111..){3}....
1000
....(1...){5}.
500
(1.{5}){4}1
200
.*(1....){4}1.*
100
(.{5})*1{5}(.{5})*
50
1...1.{15}1...1
30
.{25}
0

Try it online! Takes input as two lists of comma separated integers separated by a semicolon but link is to test suite that takes input in the example format for convenience. Explanation:

\b(\d+)\b(?=.*;.*\b(\1)\b)?(,|;.*)
$#2

Turn the first list into a bitmask of which integers are present in the second list and delete the second list.

13=`
1

Insert a 1 before the thirteenth bit. This simplifies the patterns below.

1{6}(...11){3}1111
500000
(1...1.1.1...){2}1
10000
.{6}(111..){3}....
1000
....(1...){5}.
500
(1.{5}){4}1
200
.*(1....){4}1.*
100
(.{5})*1{5}(.{5})*
50
1...1.{15}1...1
30
.{25}
0

Score according to the first matched pattern.

\$\endgroup\$
3
\$\begingroup\$

JavaScript (Node.js), 197 193 bytes

a=>s=>[17825809,31,1082401,17039425,1118480,473536,18153809,33080895].map(g=(v,i,p)=>p.map(j=>g=v&~a.reduce((t,v,k)=>t|s.has(v)<<k+k/12,4096)>>j%7*'051'[i]?g:[.3,.5,1,2,5,10,100,5e3][i]*100))|g

Try it online!

a=>s=>             // Entry
[17825809,31,1082401,17039425,1118480,473536,18153809,33080895]    // Pattern
.map(g=(v,i,p)=>   // For each. Init g to NaN
p.map(j=>g=        // Loop position
v&~a.reduce((t,v,k)=>t|s.has(v)<<k+k/12,4096)    // Arnauld's converter, outside is empty
>>j%7*'051'[i]     // j%7 == [1,2,0,6,4,5,3,1] covering [0,1,2,3,4]
?g:[.3,.5,1,2,5,10,100,5e3][i]*100    // If found then write to g
))|g               // Output. NaN => 0
\$\endgroup\$
0
3
\$\begingroup\$

05AB1E, 73 64 bytes

å2ä`1š«D•1MÖ•₂вès5ô©Å/D®Å\DŠ«®Dø®4Fćˆøí}˜¯˜)P30₄;т·4°50x₄6°;)ć*à

Outputs 500 as 500.0 and 500000 as 5.0e5. If integers are mandatory, a trailing ï (cast to integer) can be added for +1 byte.

Try it online or verify all test cases.

Explanation:

å               # Check for each value in the first (implicit) input-list whether it's
                # in the second (implicit) input-list, resulting in a list of 1s/0s
                # Insert the free middle cell:
2ä              #  Split it into two equal-sized parts
  `             #  Pop and push both lists to the stack
   1š           #  Prepend a 1 to the top/second list
     «          #  Merge the lists back together
                # Corners:
D               #  Duplicate the list
 •1MÖ•          #  Push compressed integer 70848
      ₂в        #  Convert it to base-26 as list: [4,0,20,24]
        è       #  Index it into the list
                # Main diagonal:
s               #  Swap so the list is at the top again
 5ô             #  Convert it to a 5x5 matrix
   ©            #  Store this matrix in variable `®` (without popping)
    Å/          #  Pop and push the main diagonal
                # Main anti-diagonal:
D               #  Duplicate the main diagonal
®               #  Push matrix `®` again
 Å\             #  Pop and push the main anti-diagonal
                # Cross:
D               #  Duplicate the main anti-diagonal
 Š              #  Triple-swap
  «             #  Merge the duplicated main diagonal/anti-diagonal togther
                # Rows:
®               #  Push matrix `®` again
                # Columns:
D               #  Duplicate it
 ø              #  Zip/transpose; swapping rows/columns
                # Picture:
®               #  Push matrix `®` again
 4F             #  Loop 4 times:
   ć            #  Extract head; push the remainder-matrix and first row separately
    ˆ           #  Pop and add the first row to the global array
    øí          #  Rotate the matrix once clockwise:
    ø           #   Zip/transpose; swapping rows/columns
     í          #   Reverse each inner list
  }˜            #  After the loop: flatten the remaining 3x3 center matrix
                # Borders:
¯               #  Push the global array
 ˜              #  Flatten it as well
)               # Wrap everything on the stack into a list
 P              # Take the product of each inner-most lists
30              # Push 30
  ₄;            # Push 500 (1000 halved)
    т·          # Push 200 (100 doubled)
      4°        # Push 10000 (10**4)
        50      # Push 50
          x     # Push 100 (double the 50 without popping)
           ₄    # Push 1000
            6°; # Push 500000 (10**6 halved)
)               # Wrap everything on the stack into a list again
 ć              # Extract its head with the checks
  *             # Multiply the values at the same positions in the two lists together
   à            # Pop and push the flattened maximum
                # (which is output implicitly as result)

See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand why •1MÖ• is 70848 and •1MÖ•₂в is [4,0,20,24].

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 112 bytes

I∨⌈EΦ⦃³⁰=__N⁵⁰”61∧V÷⊗P&Πï⁹K∕⬤Y⪪S”¹⁰⁰”{⊟∨✳⎇¡§_⁸ξ↷⊖⮌”²⁰⁰??^^⊘φ]W[Oφ_&8_×χφ=7ZN⊘×φφ YG ⦄⊙⪪⭆ιΦ⍘⁺³²℅λ²ξ²⁴⬤λ∨Iν№η§θξκ⁰

Attempt This Online! Link is to verbose version of code. Explanation: Creates a dictionary mapping scores to strings representing bitmaps of entries that are not part of the winning pattern, then filters them on winning entries, and outputs the highest key, or 0 if no entries win.

The best I could do without lookup tables was 123 bytes:

≔⪪⪫⪪⭆θ№ηι¹²1⁵θI∨⌈Φ⁺⁺Eθ⟦⁵⁰ι⟧Eθ⟦¹⁰⁰⭆θ§λκ⟧⪪⟦²⁰⁰⭆θ§ικ⊘φ⭆θ§ι⁻⁴κ³⁰⭆θΦι¬∨﹪κ⁴﹪μ⁴φ⭆θΦι∧﹪κ⁴﹪μ⁴×χφ⭆θΦι⁼↔⁻μ²↔⁻μ²⊘×φφ⭆θΦι¬∧﹪κ⁴﹪μ⁴⟧²I⌊⊟ι⁰

Try it online! Link is to verbose version of code. Explanation: Converts the first input to a string of binary digits representing whether the number is present or absent, inserts a 1 in the middle, splits it into a square array, then generates a list of pairs of scores and cells required by that score, filters on those pairs where all of the cells are present, then outputs the highest score, or 0 if there was no win. The pairs for scores of 50 and 100 are generated separately from the others and concatenated later. The pair for 200 comes before 30 because it saves a byte.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.