18
\$\begingroup\$

Your task is, to count how many pluses I have.

What Pluses?

  • The no plus: 0 Points
-
  • The naïve Plus: 1 Point
+
  • The double Plus: 2 Points
 +
+++
 +
  • The mega double plus: 3 Points
    +
   +++
    +
 +  +  +
+++++++++
 +  +  +
    +
   +++
    +

Pluses of higher order than 3 must be ignored.

Rules

  • Input will only consist of two characters - and +, and it will always be rectangular.
  • Input can be a string, an array or a binary matrix (then + is 1 and - is 0).
  • Output must be the sum of all detected pluses (trailing newline/ whitespace allowed).
  • Pluses can overlap (see Examples below)
  • Default I/O rules apply
  • Default Loop holes apply

Examples

-+-
+-+
+--

Out: 4

-+-
+++
+++

Out: 9 (7 naïve pluses and 1 double plus)

++++++
++++++
++++++
++++++

Out: 40 (24 naïve pluses and 8 double pluses)

----+-----
+--+++----
----++----
-+--+--++-
+++++++++-
-+--+--++-
----+-+---
---+++----
+---++++++

Out: 49 (36 naïve pluses, 5 double pluses and 1 mega double plus)

++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
++++++++++

Out: 208 (90 naïve pluses, 56 double pluses and 2 mega double plus)

\$\endgroup\$
10
  • 1
    \$\begingroup\$ sandbox \$\endgroup\$
    – math
    Jun 24 at 10:35
  • \$\begingroup\$ Could you add a test case where one or more intersections of a "mega double plus" overlap, thereby invalidating it? \$\endgroup\$
    – Shaggy
    Jun 24 at 14:00
  • \$\begingroup\$ I'm not entirely sure what Shaggy means, but I would suggest a test case with the same dimensions as the last one but with all pluses--my current Jelly solution is incredibly wrong for that input \$\endgroup\$ Jun 24 at 14:45
  • \$\begingroup\$ @Shaggy and Unrelated String I'll do it tommorow, but I don't know too what Shaggy meant \$\endgroup\$
    – math
    Jun 24 at 18:57
  • 1
    \$\begingroup\$ @simonalexander2005 If you mean something like this, then I think it is still valid, space doesn't mean -. I am adding just the second testcase suggested by Unrelated String for now. \$\endgroup\$
    – math
    Jun 25 at 8:02

11 Answers 11

15
\$\begingroup\$

MATL, 29 28 24 bytes

z2Y6ttX*,GbZ+5Mz=z]yytvs

Input is a binary matrix with 1 for '+' and 0 for '-'.

Try it online! Or verify all test cases.

Explanation

Convolution is the key to success

z       % Implicit input. Number of nonzeros. This is the number of naive pluses
2Y6     % Push [0 1 0; 1 1 1; 0 1 0] (predefined literal): pattern of double plus
ttX*    % Duplicate twice. Kronecker product: pattern of mega-double plus
,       % Do twice
  G     %   Push input again
  b     %   Bubble up third-topmost entry in the stack. This moves either the
        %   double of mega-double pattern to top
  Z+    %   2D convolution, maintaining size
  5M    %   Push the last input to the last function again: the pattern
  z     %   Number of nonzeros. This gives 5 or 25 for double or mega-double
  =     %   Equal? Element-wise. This detects if the result of the convolution
        %   equals the number of ones in the pattern, which implies that the
        %   pattern has been found
  z     %   Number of nonzeros. This is how many times the pattern has been found  
]       % End
yyt     % Duplicate the top two elements, then the top element. This effectively
        % gives weight 2 and 3 to double and mega-double pluses
vs      % Concatenate all stack contents. Sum. Implicit display
\$\endgroup\$
0
9
\$\begingroup\$

JavaScript (ES6),  146 ... 140  137 bytes

Expects a binary matrix.

m=>m.map((r,y)=>r.map((c,x)=>t+=c+=(g=(X,k=6)=>k>>8||(m[y+Y+k%5%3]||0)[x-X+k%27%4]&g(X,k+46))(Y=0)&&2+3*g(Y=3)*g(-3)*g``*g(0,Y=6)),t=0)|t

Try it online!

How?

Helper function

The helper function \$g\$ tests whether there's a 'Double Plus' inside the \$3\times3\$ submatrix whose top-left corner is located at position \$(x-X,y+Y)\$.

We start with \$k=6\$ and add \$46\$ to \$k\$ after each iteration. The relative coordinates in the submatrix are given by:

$$\begin{align}&dx=(k\bmod 27)\bmod 4\\ &dy=(k\bmod 5)\bmod 3\end{align}$$

  k | k%27 | dx=k%27%4 | k%5 | dy=k%5%3 | (dx, dy)          | 0 1 2
----+------+-----------+-----+----------+--------------  ---+-------
  6 |   6  |     2     |  1  |     1    | (+2, +1) (A)    0 | - C -
 52 |  25  |     1     |  2  |     2    | (+1, +2) (B)    1 | E D A
 98 |  17  |     1     |  3  |     0    | (+1, +0) (C)    2 | - B -
144 |   9  |     1     |  4  |     1    | (+1, +1) (D)
190 |   1  |     1     |  0  |     0    | (+1, +0) (C)
236 |  20  |     0     |  1  |     1    | (+0, +1) (E)

The cell at \$(+1, +0)\$ is tested twice, which is not an issue.

The next value of \$k\$ is \$282\$ which triggers the test k >> 8 and stops the recursion.

g = (X, k = 6) =>    // g is a recursive function taking X and a counter k
  k >> 8 || (        //   if k = 282, stop the recursion and return 1
    ( m[ y + Y +     //   otherwise, test the cell located at
         k % 5 % 3 ] //   row y + Y + ((k mod 5) mod 3)
      || 0           //
    )[ x - X +       //   and column x - X + ((k mod 27) mod 4)
       k % 27 % 4 ]  //
  )                  //
  & g(X, k + 46)     //   do a recursive call with k + 46

Main function

NB: Among many different possible choices, the initial value of \$k\$ in \$g\$ was forced to \$6\$ so that it allows us to do g(0, Y = 6) in the main function without breaking anything.

m =>                 // m[] = input matrix
m.map((r, y) =>      // for each row r[] at position y in m[]:
  r.map((c, x) =>    //   for each cell c at position x in r[]:
    t +=             //     add to t:
    c +=             //       1 point if c = 1
      g(Y = 0) && 2  //       2 points if there's a Double Plus at (x, y)
      + 3 *          //       3 points if there are also Double Pluses at:
      g(Y = 3) *     //         (x - 3, y + 3)
      g(-3) *        //         (x + 3, y + 3)
      g`` *          //         (x, y + 3)
      g(0, Y = 6)    //         (x, y + 6)
  ),                 //   end of inner map()
  t = 0              //   start with t = 0
) | t                // end of outer map(); return t
\$\endgroup\$
9
  • \$\begingroup\$ Output for the last test case seems to be off by three. Yours outputs 208 while the actual result is 205 \$\endgroup\$
    – user100690
    Jun 25 at 8:10
  • \$\begingroup\$ @RecursiveCo. The correct answer is 208. (Now fixed by the OP.) \$\endgroup\$
    – Arnauld
    Jun 25 at 9:20
  • \$\begingroup\$ ES6, 138 bytes: m=>m.map((r,y)=>r.map((c,x)=>t+=c+=(g=X=>k=k>8||(325>>k|(m[y+Y+k/3|0]||0)[x-X+k++%3])&g(X))(Y=0)&&2+3*g(Y=3)*g(-3)*g``*g(!(Y=6))),k=t=0)|t; ES2020, 135 bytes: m=>m.map((r,y)=>r.map((c,x)=>t+=c+=(g=X=>k=k>8||(325>>k|m[y+Y+k/3|0]?.[x-X+k++%3])&g(X))(Y=0)&&2+3*g(Y=3)*g(-3)*g``*g(!(Y=6))),k=t=0)|t \$\endgroup\$
    – tsh
    Jun 25 at 9:49
  • \$\begingroup\$ 137: m=>m.map((r,y)=>r.map((c,x)=>t+=c+=(g=X=>k=k>8||(325>>k|(m[y+Y+k/3|0]||0)[x-X+k++%3])&g(X))(Y=0)&&2+3*g(Y=3)*g(-3)*g``*g(0,Y=6)),k=t=0)|t \$\endgroup\$
    – tsh
    Jun 25 at 10:04
  • \$\begingroup\$ @tsh Nice optimization. I was trying to find a version of g that directly tests the relevant points rather than iterating over all of them. The result is also 137 bytes for now. \$\endgroup\$
    – Arnauld
    Jun 25 at 10:57
8
+50
\$\begingroup\$

Jelly, 33 bytes

×3\€ḊṖ
ZÇZaÇḤ
ÇJ%3ZƙƲ⁺€Ç€€a3,,ÇFS

Try it online!

:/

I want to say this is very golfable, but the entire approach is probably not the ideal one. Now agrees with Luis Mendo's MATL solution on a test case I made up, and at the cost of only one byte so that's cool I guess

×3\€ḊṖ    Helper link 1: detect centers of +++
   €      For each row,
 3\       reduce over overlapping windows of length 3:
×         multiply.
    ḊṖ    Remove the first and last rows.

ZÇZaÇḤ    Helper link 2: detect double plus centers
   aÇ     Keep the horizontal (centers of) +++es which align with
ZÇZ       the vertical (centers of) +++es,
     Ḥ    and double.

ÇJ%3ZƙƲ⁺€Ç€€a3,,ÇFS    Main link: sum each tier of plus
Ç                      Get the matrix of double plus centers.
     ƙƲ                Group rows by
 J%3                   their indices mod 3
    Z                  and transpose each group;
       ⁺€              do it again to each group.
          €€           For each group in each group,
         Ç             detect the double plus pattern,
            a3         and replace the 16s with 3s.
              ,        Pair the result with the input,
               ,Ç      pair that pair with the double pluses,
                 FS    then flatten that all and return the sum.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ nice, but I can't vote anymore. \$\endgroup\$
    – math
    Jun 24 at 12:27
8
\$\begingroup\$

R, 141 bytes

function(m)sum(m,a<-f(m,n<-nrow(m))*2,f(a,n,3)*3,na.rm=T)
f=function(m,n,k=1)sapply(n*k+seq(!m),function(i)all(i%%n>1,m[i+k*c(0,1,-1,n,-n)]))

Try it online!

This can probably be improved by a lot.

The helper function f scans the matrix. For each cell, it counts 1 iff the cell and the cells at distance k in each of the 4 directions are all worth 1. For k=1, this corresponds to checking the 4 neighbours, and creates a which encodes the centres of the double pluses. We then run f on a with k=3 to find the triple pluses. The entries near the edges end up as NA; they are ignored thanks to na.rm=T.

\$\endgroup\$
6
\$\begingroup\$

J, 80 69 60 bytes

[:+/@,[,2 3*((;[:,./^:2#"{~)#:2 7 2)4 :'y(x-:x&*);._3~$x'&><

Try it online!

-9 thanks to xash

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Two small golfs for -9 \$\endgroup\$
    – xash
    Jun 25 at 17:23
  • 1
    \$\begingroup\$ btw. nice solution with the inline 4 : \$\endgroup\$
    – xash
    Jun 25 at 17:30
  • \$\begingroup\$ Very nice, thanks! \$\endgroup\$
    – Jonah
    Jun 25 at 17:30
  • \$\begingroup\$ For showing previous scores, it makes more sense to use <strike>num</strike> \$\endgroup\$ Jul 2 at 13:09
  • \$\begingroup\$ I don’t like how that looks as much even though i agree it’s semantically more accurate. \$\endgroup\$
    – Jonah
    Jul 2 at 14:06
5
\$\begingroup\$

Charcoal, 71 bytes

WS⊞υιυFLυFLθ«Jκι¿⁼⁷LΦ⪫KVKKΣλ3»FLυFLθ«Jκι¿∧⁼3KK⬤urdl‹1⊟KD⁴✳λ6»≔Σ⪫KAωθ⎚Iθ

Try it online! Link is to verbose version of code. Takes input as a binary matrix of newline-terminated strings. Explanation:

WS⊞υιυ

Read in the matrix and print it to the canvas.

FLυFLθ«Jκι

Loop over all of the cells.

¿⁼⁷LΦ⪫KVKKΣλ3»

If this cell and all of its neighbours are 1s or 3s then change this cell to a 3.

FLυFLθ«Jκι

Loop over all of the cells again.

¿∧⁼3KK⬤urdl‹1⊟KD⁴✳λ6»

If this cell is a 3 and all of the cells 3 away in all four orthogonal directions are greater than 1 then change this cell to a 6.

≔Σ⪫KAωθ⎚Iθ

Take the sum of the grid, clear the canvas, and output the sum in decimal.

\$\endgroup\$
5
\$\begingroup\$

Python 3.8 (pre-release), 150 149 145 bytes

lambda a:len(x("\+",a)+2*x((d:="\+(?="+(s:="\W"*~-a.find("\n"))+3*"\+"+s+"\+)..")[:-2],a)+3*x(d+f"(?={3*s+3*d+3*s+d})",a))
import re
x=re.findall

Try it online!

Input is a multiline string

Thanks to @Tipping Octopus for -1 byte Thanks to @Neil for -4 bytes

Ungolfed version

import re
def f(a):
  s="\W"*(a.find("\n") - 1)
  d=f"\+(?={s}\+\+\+{s}\+).."

  return len(re.findall("\+", a) +
             2 * re.findall(d[:-2], a) +
             3 * re.findall(d + f"(?={3*s + 3*d + 3*s + d})", a)
            )

Try it online!

How it works :

I created a regex that can detect double plusses and mega-double-pluses

  • s="\W"*~-a.find("\n") stock in s the string \W\W...\W whose length is equal to the number of character of a line minus 1. (\W matches any non-word character including \n)

  • d=f"\+(?={s}\+\+\+{s}\+).." is the pattern for double plus (+ .. wich will be removed on the double plus check)

  • re.findall(<pattern>, a) returns a list containing all the matches of pattern.

  • len(re.findall()+2*re.findall()+3*re.findall() concatenate theses lists and return the length

\$\endgroup\$
3
  • 1
    \$\begingroup\$ -1 byte \$\endgroup\$ Jun 24 at 21:27
  • 1
    \$\begingroup\$ "\W%r"%{a.find("\n")-1} can be "\W"*~-a.find("\n"). \$\endgroup\$
    – Neil
    Jun 25 at 9:52
  • \$\begingroup\$ @Neil and Tipping Octopus, thanks for suggestions \$\endgroup\$
    – Jakque
    Jun 25 at 14:49
4
\$\begingroup\$

Ruby, 135 bytes

->a{i=0;[1,186,0x101c04125ff490407010].sum{|s|a.each_cons(y=3**i).sum{|w|w.transpose.each_cons(y).count{|z|z.join.to_i(2)&s==s}}*i+=1}}

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Jelly, 37 bytes

Zœs3Ɗ⁺€aZ$2ịP))
3*³ṡZ€ṡ€ɗÇ⁸¡
3’Ç×Ɗ€FS

Try it online!

A full program taking a Boolean matrix as its argument and printing the number of pluses. This is extensible to higher degrees of plus by changing the 3 at the beginning of the last line to a higher number. For example, here is a version that goes up to mega-mega-mega double pluses in a matrix of 82x82 1s.

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

JavaScript (ES2020), 136 bytes

m=>m.map((r,y)=>r.map((c,x)=>t+=(d=X=>D=Y=>e+2?m[Y+e--%3%2]?.[X+e%2]*D(Y):e=3)(x)(y,e=3)?D(y-3)*D(y+3)*d(x-3)(y)*d(x+3)(y)?6:3:c),t=0)|t

f=

m=>m.map((r,y)=>r.map((c,x)=>t+=(d=X=>D=Y=>e+2?m[Y+e--%3%2]?.[X+e%2]*D(Y):e=3)(x)(y,e=3)?D(y-3)*D(y+3)*d(x-3)(y)*d(x+3)(y)?6:3:c),t=0)|t


testcases = `
-+-
+-+
+--

-+-
+++
+++

++++++
++++++
++++++
++++++

----+-----
+--+++----
----++----
-+--+--++-
+++++++++-
-+--+--++-
----+-+---
---+++----
+---++++++

++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
++++++++++
`.trim().split('\n\n').map(s => s.split('\n').map(r => [...r].map(c => c === '+' ? 1 : 0)));

testcases.forEach(t => { console.log(f(t)); });

m=> // input 0-1 [m]atrix
m.map((r,y)=> // for each [y]-th [r]ow
r.map((c,x)=> // for each [x]-th [c]eil
t+= // [t]otal points add...
(d=X=> // Check if [d]ouble plus exist on [X], [Y]
D=Y=>e+2?         // for [e]ach 3, 2, 1,  0, -1
m[Y+e--%3%2]?.    //         Y+ 0, 0, 1,  0, -1
[X+e%2]           //         X+ 0, 1, 0, -1,  0
                  // check if certain position is a plus sign
*D(Y,e)           // return 0 or NaN as falsy
:e=3              // return 3 as truthy
)
(x)(y,e=3)? // Is [x][y] a double plus?
D(y-3)*D(y+3)*d(x-3)(y)*d(x+3)(y)? // Is [x][y] a double double plus?
6:3:c // assign different points
),
t=0 // initial [t]otal points to 0
)|t // return total points
\$\endgroup\$
1
\$\begingroup\$

Perl 5 (-00p), 125 bytes

/(....)?(..)?(.)
/;($a,$:,$;,$,)=map"."x$_,@-;/(1$,111$,1)(?{$x+=2})($;(1..1..1)$:1{9}$:(?3)$;(?1)(?{$x+=3}))?^/s;$_=y/1//+$x

Try it online!

Using 1 instead of + and using regex to match pluses.

Or 124 bytes using }{ at the end trick

/(....)?(..)?(.)
/;($a,$:,$;,$,)=map"."x$_,@-;$\=y/1//;/(1$,111$,1)(?{$\+=2})($;(1..1..1)$:1{9}$:(?3)$;(?1)(?{$\+=3}))?^/s}{

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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