There is a rectangular 2D array containing viruses denoted by 'v', antidote1 denoted by 'a', and antidote2 denoted by 'b' (there are no values other than 'v', 'a' and 'b').

Antidote1 can kill neighboring viruses in horizontal and vertical directions only, but antidote2 can kill neighboring(if any) viruses in horizontal, vertical and diagonal directions.

Once the antidotes are activated, how many viruses will remain at the end?




Output: 4



Output: 1



Output: 0



Output: 3

  • 2
    \$\begingroup\$ I appreciate your edits @Grimy - Also nice challenge :) \$\endgroup\$ – pixma140 Jul 30 '19 at 9:24
  • 2
    \$\begingroup\$ @KevinCruijssen, it is not irregular shaped. \$\endgroup\$ – Kiara Dan Jul 30 '19 at 9:33
  • 4
    \$\begingroup\$ May we take 3 (distinct) arbitrary values instead of "v", "a", and "b"? \$\endgroup\$ – att Jul 30 '19 at 9:52
  • 2
    \$\begingroup\$ do the anti-viruses wrap around (ie, "a" in bottom row would remove a "v" in top row)? \$\endgroup\$ – Brian Jul 30 '19 at 12:46
  • 2
    \$\begingroup\$ @Kiara Dan I would advise not allowing any 3 distinct values, as it keeps some character in the challenge, as well as possible forced cleverness with code points of the letters. \$\endgroup\$ – lirtosiast Jul 31 '19 at 7:14

Python 3, 135 bytes

f=lambda x:j(eval(2*'(eval(p)for s in zip(*'+'x))))')).count('v')

Try it online!

-2 bytes thanks to Kevin Cruijssen


Replaces all 'v' to 'b' if found next to 'b'. Next, replaces all 'v' to 'c' if found next to 'a'. A second iteration with the transposed version of the array clears all vertical and diagonal viruses. Finally, it will return the remaining number of 'v's.

As a more readable recursive function (155 bytes)

| improve this answer | |
  • 3
    \$\begingroup\$ You can remove the space after y>1else. Nice approach though. At first I wasn't sure how this deals with the diagonal b, but that seems to work just fine due to your replacements. :) +1 from me. \$\endgroup\$ – Kevin Cruijssen Jul 30 '19 at 10:08
  • \$\begingroup\$ @KevinCruijssen Thanks! The diagonals are taken care of by replacing 'v' with 'a' if they are next to 'b'. In the second iteration, the adjacent 'v's are then removed. \$\endgroup\$ – Jitse Jul 30 '19 at 10:10
  • 3
    \$\begingroup\$ For the following input, output should be 3, but its returning 4 :bvb bav vab vvv vvb vvv vvv bva vav \$\endgroup\$ – Kiara Dan Jul 30 '19 at 10:43
  • 1
    \$\begingroup\$ 164 bytes by using j=''.join in your fixed version \$\endgroup\$ – Kevin Cruijssen Jul 30 '19 at 12:32
  • 1
    \$\begingroup\$ @KevinCruijssen Found an even shorter one, but your suggestion saves another byte! \$\endgroup\$ – Jitse Jul 30 '19 at 12:39

JavaScript (ES7), 108 bytes

Takes input as a matrix of characters.


Try it online!

Similar to my original answer, but doing V>'a'>(x-X)**2+y*y-2 is actually 1 byte shorter than using the hexa trick described below. ¯\_(ツ)_/¯

JavaScript (ES7), 109 bytes

Takes input as a matrix of characters.


Try it online!


The quadrance of two points \$A_1=(x_1,y_1)\$ and \$A_2=(x_2,y_2)\$ is defined as:


Considering integer coordinates, it looks as follows:

$$\begin{matrix} &8&5&4&5&8\\ &5&2&1&2&5\\ &4&1&\bullet&1&4\\ &5&2&1&2&5\\ &8&5&4&5&8 \end{matrix}$$


  • a type A antidote located at \$A_1\$ is able to kill a virus located at \$A_2\$ if \$Q(A_1,A_2)<2\$
  • a type B antidote located at \$A_1\$ is able to kill a virus located at \$A_2\$ if \$Q(A_1,A_2)<3\$

Conveniently, this exclusive upper bound (\$2\$ or \$3\$) can be obtained by converting the antidote character from hexadecimal to decimal and subtracting \$8\$:

  • \$\text{A}_{16} - 8_{10} = 2_{10}\$
  • \$\text{B}_{16} - 8_{10} = 3_{10}\$


f =                      // named function, because we use it to test if a character
                         // is below or above 'm'
m => (                   // m[] = input matrix
  g = (                  // g is a recursive function taking:
    y,                   //   y = offset between the reference row and the current row
    X,                   //   X = reference column
    V                    //   V = reference value, prefixed with '0x'
  ) =>                   //
    m.map(r =>           // for each row r[] in m[]:
      r.map((v, x) =>    //   for each value v at position x in r[]:
        V ?              //     if V is defined:
          v > f &        //       if v is equal to 'v'
          (x - X) ** 2 + //       and the quadrance between the reference point and
          y * y          //       the current point
          < V - 8 ?      //       is less than the reference value read as hexa minus 8:
            r[x] = n--   //         decrement n and invalidate the current cell
          :              //       else:
            0            //         do nothing
        :                //     else:
          v < f ?        //       if v is either 'a' or 'b':
            g(           //         do a recursive call:
              -y,        //           pass the opposite of y
              x,         //           pass x unchanged
              '0x' + v   //           pass v prefixed with '0x'
            )            //         end of recursive call
          :              //       else:
            n++          //         increment n
      ) | y++            //   end of inner map(); increment y
    )                    // end of outer map()
  )(n = 0)               // initial call to g with y = n = 0
  | n                    // return n
| improve this answer | |
  • \$\begingroup\$ thanks @Arnauld, can you also explain the code? \$\endgroup\$ – Kiara Dan Jul 30 '19 at 11:23
  • 3
    \$\begingroup\$ @KiaraDan Done. \$\endgroup\$ – Arnauld Jul 30 '19 at 12:45

05AB1E, 33 30 29 bytes


Try it online or verify a few more test cases.

Port of @Jitse's Python 3 answer, so make sure to upvote him!
-1 byte thanks to @Jitse.


The legacy version has the advantage of being able to zip/transpose a string-list, where the new version would need an explicit S and J, since it only works with character-lists. But, the new version is still 3 bytes shorter by using €Â in combination with a shorter compressed string. In the legacy version, would only keep the last value on the stack inside the map, but in the new version, it will keep all values on the stack inside the map.

2F                  # Loop 2 times:
  .•s¯}˜?•          #  Push compressed string "vbvabbca"
   2ô               #  Split it into parts of size 2: ["vb","va","bb","ca"]
     €Â             #  Bifurcate (short for duplicate & reverse copy) each:
                    #   ["vb","bv","va","av","bb","bb","ca","ac"]
       2ä           #  Split it into two parts:
                    #   [["vb","bv","va","av"],["bb","bb","ca","ac"]]
         `          #  Push both those lists separated to the stack
          .:        #  Replace all strings once one by one in the (implicit) input-string
            S       #  Then split the entire modified input to a list of characters
             ¶¡     #  Split that list by newlines into sublists of characters
               ø    #  Zip/transpose; swapping rows/columns
                J   #  Join each inner character-list back together to a string again
                 »  #  And join it back together by newlines
}'v¢               '# After the loop: count how many "v" remain

See this 05AB1E tip of mine (section How to compress strings not part of the dictionary?) to understand why .•s¯}˜?• is "vbvabbca".

| improve this answer | |
  • \$\begingroup\$ You don't need bc => ba if you apply bv => ba before av => ac. Thus .•6øнãI• (compressed form of `"bvavbaac") is enough, saving 2 bytes. \$\endgroup\$ – Grimmy Jul 30 '19 at 15:22
  • \$\begingroup\$ @Grimy It results in 1 instead of 3 for the last test case however. \$\endgroup\$ – Kevin Cruijssen Jul 30 '19 at 15:28
  • 1
    \$\begingroup\$ @KevinCruijssen two replacement steps instead of three seems to do the trick after all \$\endgroup\$ – Jitse Jul 31 '19 at 7:44
  • \$\begingroup\$ @Jitse Thanks. The compression string is 2 bytes shorter, but I do now need .: (replace all once) instead of : (keep replacing all until it is no longer present). Still -1, though. :) Thanks for letting me know. \$\endgroup\$ – Kevin Cruijssen Jul 31 '19 at 8:40

Java 10, 211 209 bytes

m->{int i=m.length,j,c=0,f,t,I,J;for(;i-->0;)for(j=m[i].length;j-->0;c+=m[i][j]>98?f/9:0)for(f=t=9;t-->0;)try{f-=m[I=i+t/3-1][J=j+t%3-1]==98||Math.abs(I-i+J-j)==1&m[I][J]<98?1:0;}catch(Exception e){}return c;}

Modification of my answer for the All the single eights challenge.
-2 bytes thanks to @ceilingcat.

Try it online.


m->{                           // Method with char-matrix parameter & int return-type
  int i=m.length,              //  Amount of rows
      j,                       //  Amount of columns
      c=0,                     //  Virus-counter, starting at 0
      f,                       //  Flag-integer
      t,I,J;                   //  Temp-integers
  for(;i-->0;)                 //  Loop over the rows of the matrix
    for(j=m[i].length;j-->0    //   Inner loop over the columns
        ;c+=                   //     After every iteration: increase the counter by:
            m[i][j]>98         //      If the current cell contains a 'v'
             f/9               //      And the flag is 9:
                               //       Increase the counter by 1
            :0)                //      Else: leave the counter unchanged by adding 0
      for(f=t=9;               //    Reset the flag to 9
          t-->0;)              //    Loop `t` in the range (9, 0]:
         try{f-=               //     Decrease the flag by:
           m[I=i+t/3-1]        //      If `t` is 0, 1, or 2: Look at the previous row
                               //      Else-if `t` is 6, 7, or 8: Look at the next row
                               //      Else (`t` is 3, 4, or 5): Look at the current row
            [J=j+t%3-1]        //      If `t` is 0, 3, or 6: Look at the previous column
                               //      Else-if `t` is 2, 5, or 8: Look at the next column
                               //      Else (`t` is 1, 4, or 7): Look at the current column
            ==98               //      And if this cell contains a 'b'
                               //      Or if a vertical/horizontal adjacent cell
              &m[I][J]<98?     //      contains an 'a'
               1               //       Decrease the flag by 1
            :0;                //      Else: leave the flag unchanged by decreasing with 0
         }catch(Exception e){} //     Catch and ignore any ArrayIndexOutOfBoundsExceptions,
                               //     which is shorter than manual checks
  return c;}                   //  And finally return the virus-counter as result
| improve this answer | |

Charcoal, 39 bytes


Try it online! Link is to verbose version of code. Explanation:


Join the input strings with \r characters and draw the result to the canvas.


Clear the number of live virii.


Loop over the characters in the input.


If the current character is a virus and there are no adjacent bs in any direction or as orthogonally then increment the number of live virii.


Repeat with the next character.


Clear the canvas and print the total number of live virii.

| improve this answer | |

Perl (-00lp), 82 bytes

Using regex to replace v by space, then count the vs

/;$,="(|..{@-})";$;="(|.{@-,@+})";$_=s/(a$,|b$;)\Kv|v(?=$,a|$;b)/ /s?redo:y/v//


| improve this answer | |

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