How much is my dice matrix worth?

21

Input

A non-empty binary matrix consisting of 3x3 sub-matrices put side by side.

Task

Your task is to identify valid dice patterns (as described below) among the 3x3 sub-matrices. Each valid pattern is worth the value of the corresponding dice. Invalid patterns are worth 0.

Output

The sum of the valid dice values.

Dice patterns

$$\begin{align} &1:\pmatrix{\color{gray}0,\color{gray}0,\color{gray}0\\\color{gray}0,1,\color{gray}0\\\color{gray}0,\color{gray}0,\color{gray}0} &&2:\pmatrix{1,\color{gray}0,\color{gray}0\\\color{gray}0,\color{gray}0,\color{gray}0\\\color{gray}0,\color{gray}0,1}\text{or}\pmatrix{\color{gray}0,\color{gray}0,1\\\color{gray}0,\color{gray}0,\color{gray}0\\1,\color{gray}0,\color{gray}0}\\ &3:\pmatrix{1,\color{gray}0,\color{gray}0\\\color{gray}0,1,\color{gray}0\\\color{gray}0,\color{gray}0,1}\text{or}\pmatrix{\color{gray}0,\color{gray}0,1\\\color{gray}0,1,\color{gray}0\\1,\color{gray}0,\color{gray}0} &&4:\pmatrix{1,\color{gray}0,1\\\color{gray}0,\color{gray}0,\color{gray}0\\1,\color{gray}0,1}\\ &5:\pmatrix{1,\color{gray}0,1\\\color{gray}0,1,\color{gray}0\\1,\color{gray}0,1} &&6:\pmatrix{1,\color{gray}0,1\\1,\color{gray}0,1\\1,\color{gray}0,1}\text{or}\pmatrix{1,1,1\\\color{gray}0,\color{gray}0,\color{gray}0\\1,1,1} \end{align}$$

Example

The expected output for the following matrix is 14 because it contains the dice 5, 6 and 3, followed by an invalid pattern (from left to right and from top to bottom).

$$\pmatrix{1,0,1,1,1,1\\ 0,1,0,0,0,0\\ 1,0,1,1,1,1\\ 1,0,0,0,0,0\\ 0,1,0,0,1,0\\ 0,0,1,0,1,0}$$

Rules

  • Both the width and the height of the matrix are guaranteed to be multiples of 3.
  • You must ignore sub-matrices that are not properly aligned on the grid (see the 3rd test case). More formally and assuming 0-indexing: the coordinates of the top-left cell of each sub-matrix to be considered are of the form \$(3x, 3y)\$.
  • This is .

Test cases

// 0
[ [ 1,0,0 ],
  [ 0,0,1 ],
  [ 1,0,0 ] ]

// 2
[ [ 0,0,1 ],
  [ 0,0,0 ],
  [ 1,0,0 ] ]

// 0 (0 + 0)
[ [ 0,0,1,0,1,0 ],
  [ 0,0,0,1,0,0 ],
  [ 0,0,1,0,1,0 ] ]

// 9 (3 + 3 + 3)
[ [ 1,0,0,0,0,1,1,0,0 ],
  [ 0,1,0,0,1,0,0,1,0 ],
  [ 0,0,1,1,0,0,0,0,1 ] ]

// 6 (6 + 0)
[ [ 1,0,1 ],
  [ 1,0,1 ],
  [ 1,0,1 ],
  [ 1,0,1 ],
  [ 1,0,0 ],
  [ 1,0,1 ] ]

// 14 (5 + 6 + 3 + 0)
[ [ 1,0,1,1,1,1 ],
  [ 0,1,0,0,0,0 ],
  [ 1,0,1,1,1,1 ],
  [ 1,0,0,0,0,0 ],
  [ 0,1,0,0,1,0 ],
  [ 0,0,1,0,1,0 ] ]

// 16 (1 + 2 + 3 + 4 + 0 + 6)
[ [ 0,0,0,1,0,0,1,0,0 ],
  [ 0,1,0,0,0,0,0,1,0 ],
  [ 0,0,0,0,0,1,0,0,1 ],
  [ 1,0,1,1,1,1,1,0,1 ],
  [ 0,0,0,1,0,1,1,0,1 ],
  [ 1,0,1,1,1,1,1,0,1 ] ]

Arnauld

Posted 2018-08-03T11:53:46.920

Reputation: 111 334

Answers

5

Python 3, 195 189 bytes

-6 bytes thanks to @Jo King

lambda m:sum({16:1,257:2,68:2,273:3,84:3,325:4,341:5,455:6,365:6}.get(int(''.join(str(e)for c in m[3*i:][:3]for e in c[3*j:][:3]),2),0)for i in range(len(m)//3)for j in range(len(m[0])//3))

Try it online! (189) Try it online! (195)

Human readable version:

# 3x3 part matrix to dice, beginning at coordinates 3*i, 3*j
def single_matrix_to_dice(matrix, i, j):
    # Example: matrix = [[0, 0, 0], [0, 1, 0], [0, 0, 0]], i=0, j=0 (result is 1)

    matrix_string = ''.join(
        str(e) for column in matrix[3*i:3*i+3] 
        for entry in column[3*j:3*j+3]
    ) # Slicing the matrix so that only the valid entries remain, here '000010000'

    # Interpreting the matrix string as binary number, here 16
    binary_number = int(matrix_string,2)

    # binary representations of all valid dice rolls
    dct = {16:1,257:2,68:2,273:3,84:3,325:4,341:5,455:6,365:6}

    return dct.get(binary_number, 0)

def f(matrix):
    return sum(
        single_matrix_to_dice(matrix, i, j) for i in range(len(m)//3) 
        for j in range(len(m[0])//3))
    ) # len(m)/3 would generate a float, so len(m)//3 is used

Black Owl Kai

Posted 2018-08-03T11:53:46.920

Reputation: 980

I wonder if you could shorten this slightly by doing the same operation on the transpose of the matrix as well. That way you could remove all of the duplicate entries in your map that add 6 bytes each. Just need to add the transpose step in <18 bytes – Easton Bornemeier – 2018-08-03T16:07:50.563

188 bytes. – Jonathan Frech – 2018-08-03T16:30:37.410

Get rid of both instances of //3 and use '0'+''.join... to save two bytes :) – Jonathan Allan – 2018-08-03T16:44:55.750

...combine that with enumerate to save two more: here

– Jonathan Allan – 2018-08-03T16:49:37.543

2165 bytes. – Jonathan Frech – 2018-08-03T17:09:52.627

Possible 162 bytes.

– Jonathan Frech – 2018-08-03T17:13:35.840

5

R, 134 bytes

function(m,d=dim(m)/3-1){for(a in 0:d)for(b in 0:d[2])F=F+sum(y<-m[1:3+a*3,1:3+b*3])*sum(y*2^(8:0))%in%utf8ToInt("āDđTŅŕLJŭ");F}

Try it online!

I noticed I had the same idea of @Heteira

History :

  • 171 : -10 bytes thanks to @JayCe !
  • 161 : -3 bytes thanks to @Giuseppe !
  • 158 : -13 bytes saved !
  • 145 : -2 bytes thanks to @Giuseppe!
  • 143 : -6 bytes saved !
  • 137 : -3 bytes thanks to @JayCe!

digEmAll

Posted 2018-08-03T11:53:46.920

Reputation: 4 599

1save 5 bytes by compressing the list of numbers - link with examples too long to post as a comment – JayCe – 2018-08-03T15:47:21.543

13 more bytes using dim – JayCe – 2018-08-03T15:53:11.550

more black magic for two more bytes – JayCe – 2018-08-03T16:16:18.560

Great idea reordering the values, thanks a lot ! – digEmAll – 2018-08-03T17:39:02.587

you can save 3 bytes using a in 1:d instead of a in 1:d[1] although it will give a warning. – Giuseppe – 2018-08-03T17:47:42.283

Another 13 bytes saved ! – digEmAll – 2018-08-03T20:00:35.950

1There's an extra pair of parentheses around (2^(8:0)) which can be removed. – Giuseppe – 2018-08-03T20:07:53.677

Yup! Also another 6 bytes moving -1 to function arguments – digEmAll – 2018-08-03T20:14:27.337

1

I add forgotten to cat the output of intToUtf8: save 3 bytes

– JayCe – 2018-08-07T18:38:30.807

4

Perl 6, 113 105 97 94 bytes

{sum (|@_[*;^3+3*$_]for ^@_[0]).rotor(9).map:{"@āđŅŕLJ@@DT@@ŭ".ords.first(:2[$_],:k)%7}}

Try it online!

Splits up the matrix into sub matrices of 3x3, converts the nine 1s and 0s to base 2 and then indexes it into a list of integers for the value.

Explanation:

{  #Start anonymous code block
  sum   # Sum of all
     (|@_[*;^3+3*$_]   # Get the n*3 to n*3+3th elements in every sub-list
           for ^@_[0]) # For n in the range 0 to width (divide by 3 to avoid warnings)
     .rotor(9)  # Split this list into groups of 9 (split the dice up)
     .map:{     # And map each die to 
        "@āđŅŕLJ@@DT@@ŭ".ords  # In the list of integers
           .first(      # The first appearance of 
               :2[$_],  # The dice converted from a list of 0s and 1s to base 2
                 :k     # Returning the index
             )%7        # And modulo by 7 to get the alternate versions of 2, 3 and 6
          }
}

Jo King

Posted 2018-08-03T11:53:46.920

Reputation: 38 234

4

Jelly,  29 28 bytes

-1 thanks to Mr. Xcoder (use to replace ṢṪ)

s€3ZẎs3µZU,ƊṀṙ1FḄ“°€⁼-Ḍ?‘i)S

A monadic link.

Try it online! Or run the tests.

How?

s€3ZẎs3µZU,ƊṀṙ1FḄ“°€⁼-Ḍ?‘i)S - Link: list of lists of 1s and 0s
s€3                          - split each into threes
   Z                         - transpose
    Ẏ                        - tighten
     s3                      - split into threes -> the sub-matrices in column-major order
       µ                  )  - for each sub-matrix, say D:
           Ɗ                 -   last three links as a monad:
        Z                    -     transpose D
         U                   -     reverse each -> D rotated a quarter turn clockwise
          ,                  -     pair with D
            Ṁ                -   get the maximum of the two orientations
             ṙ1              -   rotate left by one (to ensure FḄ will yield integers <256 for all non-zero valued D)
               F             -   flatten
                Ḅ            -   convert from binary
                         i   -   first 1-based index in (0 if not found):
                 “°€⁼-Ḍ?‘    -     code-page indices list = [128,12,140,45,173,63]
                           S - sum

For example when a sub-matrix is:

[[1,0,1],
 [1,0,1],
 [1,0,1]]

Then ZU,Ɗ yields:

[[[1, 1, 1],
  [0, 0, 0],
  [1, 1, 1]],   ...which has maximum (Ṁ):    ...and after ṙ1:
 [[1, 0, 1],                   [[1, 1, 1],         [[0, 0, 0],
  [1, 0, 1],                    [0, 0, 0],          [1, 1, 1],
  [1, 0, 1]]]                   [1, 1, 1]]          [1, 1, 1]]

...which flattens to [0, 0, 0, 1, 1, 1, 1, 1, 1], which, converting from binary, is 63 which is the sixth entry in the code-page index list “°€⁼-Ḍ?‘ (? being byte 3F in Jelly's code-page)

Jonathan Allan

Posted 2018-08-03T11:53:46.920

Reputation: 67 804

might work instead of ṢṪ for -1. – Mr. Xcoder – 2018-08-03T15:47:37.967

...yes it will (I thought I was saving over using M >.<). Can something clever be done with ŒṪ I wonder... – Jonathan Allan – 2018-08-03T15:52:05.647

3

Japt -x, 36 bytes

Now it's getting interesting. I'm sure can be golfed down even more

ò3 ®®ò3Ãy f@"0ıtŵġdťƍǧ"øºXm¬¬Í+H)d
c

Try it online!

Luis felipe De jesus Munoz

Posted 2018-08-03T11:53:46.920

Reputation: 9 639

2

Retina 0.8.2, 90 bytes

+`(...)(.+¶)(...)(.+¶)(...)
$1¶$3¶$5¶$2$4
¶

M!`.{9}
G`111000111|(101){3}|(.)0(.0).0\3\2
1

Try it online! Explanation:

+`(...)(.+¶)(...)(.+¶)(...)
$1¶$3¶$5¶$2$4

Repeatedly remove \$3\times 3\$ blocks from each \$3\times n\$ row until all rows have 3 columns.

¶

M!`.{9}

Join all the blocks together and then split back up into rows of 9 columns.

G`111000111|(101){3}|(.)0(.0).0\3\2

Only keep valid dice patterns (two patterns for 6, then one matches any number from 0 to 5, although 0 of course will not contribute to the count below.)

1

Count the pips on the valid dice.

Neil

Posted 2018-08-03T11:53:46.920

Reputation: 95 035

1

Ruby, 151 bytes

->m{m.each_slice(3).flat_map{|r|r.transpose.each_slice(3).map{|d|" \x10āđŅŕLJ  DT  ŭ".chars.map(&:ord).index(d.flatten.join.to_i 2)&.%7}-[p]}.sum}

Try it online!

A lambda accepting a 2d array of ints (or strings, I guess). Takes inspiration from Jo King's answer. I feel like slicing the dice out of the input matrix took a lot of space, so I may well be outgolfed. Fortunately, dealing with nils only cost me a handful of bytes.

Ungolfed:

->m{
  m.each_slice(3).flat_map{|r|             # Split into groups of 3 rows
    r.transpose.each_slice(3).map{|d|      # Split into groups of 3 columns
      " \x10āđŅŕLJ  DT  ŭ".chars.map(&:ord) # [0,16,257,273,325,341,455,0,0,68,84,0,0,365]
        .index(                            # Find in that array
          d.flatten.join.to_i 2            #   the die flattened into a bitstring (nil if not found)
        )&.%7                              # Safe-modulo 7 (leaves nils as nil)
    }-[p]                                  # Remove nils
  }.sum                                    # Add 'em up
}

benj2240

Posted 2018-08-03T11:53:46.920

Reputation: 801

1

Clojure, 197 bytes

#(apply +(for[R[range]i(R 0(count %)3)j(R 0(count(% 0))3)](case(apply +(map *(iterate(partial * 2)1)(for[x(R 3)y(R 3)]((%(+ i x))(+ j y)))))16 1 257 2 68 2 273 3 84 3 325 4 3 4 1 5 455 6 365 6 0)))

I should have come up with something smarter.

NikoNyrh

Posted 2018-08-03T11:53:46.920

Reputation: 2 361

1

Python 2, 159 bytes

f=lambda a:a>[]and sum(u'ȀāDđTŅȀŕȀLJŭ'.find(unichr(int(J(J(map(str,r[i:i+3]))for r in a[:3]),2)))/2+1for i in range(0,len(a[0]),3))+f(a[3:])
J=''.join

Try it online!

Hat tip to Jonathan Frech for the unicode encoding approach.

Chas Brown

Posted 2018-08-03T11:53:46.920

Reputation: 8 959