Virus vs Antidotes code golf [closed]

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?

Input:

vv
vv

Output: 4

Input:

av
vv

Output: 1

Input:

vvv
vbv
vvv

Output: 0

Input:

bvb
bav
vab
vvv
vvb
vvv
vvv
bva
vav

Output: 3

closed as unclear what you're asking by manatwork, Embodiment of Ignorance, flawr, Sriotchilism O'Zaic, Luis felipe De jesus MunozJul 30 at 13:45

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

• I appreciate your edits @Grimy - Also nice challenge :) – pixma140 Jul 30 at 9:24
• @KevinCruijssen, it is not irregular shaped. – Kiara Dan Jul 30 at 9:33
• May we take 3 (distinct) arbitrary values instead of "v", "a", and "b"? – attinat Jul 30 at 9:52
• do the anti-viruses wrap around (ie, "a" in bottom row would remove a "v" in top row)? – Brian Jul 30 at 12:46
• @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. – lirtosiast Jul 31 at 7:14

Python 3, 135 bytes

j=''.join
p='j(s)'+4*'.replace("%s%s","%s%s")'%(*'vbbbbvbbavacvaca',)
f=lambda x:j(eval(2*'(eval(p)for s in zip(*'+'x))))')).count('v')

Try it online!

-2 bytes thanks to Kevin Cruijssen

Explanation

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)

• 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. – Kevin Cruijssen Jul 30 at 10:08
• @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. – Jitse Jul 30 at 10:10
• For the following input, output should be 3, but its returning 4 :bvb bav vab vvv vvb vvv vvv bva vav – Kiara Dan Jul 30 at 10:43
• 164 bytes by using j=''.join in your fixed version – Kevin Cruijssen Jul 30 at 12:32
• @KevinCruijssen Found an even shorter one, but your suggestion saves another byte! – Jitse Jul 30 at 12:39

JavaScript (ES7), 108 bytes

Takes input as a matrix of characters.

f=m=>(g=(y,X,V)=>m.map(r=>r.map((v,x)=>V?v>f&V>'a'>(x-X)**2+y*y-2?r[x]=n--:0:v<f?g(-y,x,v):n++)|y++))(n=0)|n

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.

f=m=>(g=(y,X,V)=>m.map(r=>r.map((v,x)=>V?v>f&(x-X)**2+y*y<V-8?r[x]=n--:0:v<f?g(-y,x,'0x'+v):n++)|y++))(n=0)|n

Try it online!

How?

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

$$Q(A_1,A_2)=(x_2−x_1)^2+(y_2−y_1)^2$$

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}$$

Therefore:

• 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}\$$

Commented

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
• thanks @Arnauld, can you also explain the code? – Kiara Dan Jul 30 at 11:23
• @KiaraDan Done. – Arnauld Jul 30 at 12:45

05AB1E, 3330 29 bytes

2F.•s¯}˜?•2ô€Â2ä.:S¶¡øJ»}'v¢

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

Explanation:

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".

• 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. – Grimy Jul 30 at 15:22
• @Grimy It results in 1 instead of 3 for the last test case however. – Kevin Cruijssen Jul 30 at 15:28
• @KevinCruijssen two replacement steps instead of three seems to do the trick after all – Jitse Jul 31 at 7:44
• @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. – Kevin Cruijssen Jul 31 at 8:40

Java 10, 211 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>8?1: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.

Try it online.

Explanation:

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>8?              //      And the flag is 9:
1                //       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'
||Math.abs(I-i+J-j)==1
//      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

Charcoal, 39 bytes

ＷＳ⊞υι≔⪫υ⸿θＰθ≔⁰ηＦθ«≧⁺›⁼ιv⁺№ＫＭb№ＫＶaηι»⎚Ｉη

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.

≧⁺›⁼ιv⁺№ＫＭb№ＫＶaη

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.

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//

TIO