Score a game of Load, Defend and Shoot
Jelly, 33 32 24 bytes
Zæ%1.»0$+¥\>-‘żZḅ3Ff5,7Ḣ
This prints 5 instead of -1, and 7 instead of 1. Try it online! or verify all test cases.
How it works
Zæ%1.»0$+¥\>-‘żZḅ3Ff5,7Ḣ Main link. Argument: A (digit list array)
Z Zip; group corresponding digits.
æ%1. Map the digits in (-1.5, 1.5].
This replaces [1, 2, 3] with [1, -1, 0].
\ Cumulatively reduce the pairs by doing the following.
»0$ Take the maximum of the left value and 0, i.e., replace
a -1 with a 0.
+¥ Add the modified left value to the right value.
This computes the available ammo after each action. An
ammo of -1 indicates a cheating attempt.
>- Compare the results with -1.
‘ Increment. And unilateral cheating attempt is now [1, 2]
or [2, 1], where 1 signals the cheater and 2 the winner.
żZ Pair each result with the corr., original digits.
ḅ3 Convert each pair from base 3 to integer.
This maps [1, 2] and [2, 1] to 5 and 7.
F Flatten the resulting, nested list.
f5,7 Discard all but 5's and 7's.
Ḣ Grab the first element (5 or 7).
If the list is empty, this returns 0.
Pyth, 48 46 49 47 bytes
.xhfT|M.e,-FmgF.b/<dhkY2S2Q?}b_BS2-FbZ.b,NYCQ)0
Try it here!
Thanks to @isaacg for saving 2 4 bytes!
Takes input as a 2-tuple with the list of the moves of player A first and the moves of player B second. Output is the same as in the challenge.
Explanation
Short overview
- First we group the moves of both players together, so we get a list of 2-tuples.
- Then we map each of those tuples to another 2-tuple in the form
[cheating win, fair win]
with the possible values-1, 0, 1
for each of it, to indicate if a player won at this point (-1, 1
) or if the game goes on (0
) - Now we just need to get the first tuple which is not
[0,0]
, and take the first non-zero element of it which indicates the winner
Code breakdown
.xhfT|M.e,-FmgF.b/<dhkY2S2Q?}b_BS2-FbZ.b,NYCQ)0 # Q = list of the move lists .b,NYCQ # pair the elements of both input lists .e # map over the list of pairs with # b being the pair and k it's index m Q # map each move list d .b 2S2 # map over [1,2], I can't use m because it's # lambda variable conflicts with the one from .e <dhk # d[:k+1] / Y # count occurences of 1 or 2 in this list -F # (count of 1s)-(count of 2s), indicates cheating win ?}b_BS2 # if b is (1,2) or (2,1) -Fb # take the difference, indicates fair win Z # else 0, no winner yet , # pair those 2 values |M # For each resulting pair, take the first one if # its not zero, otherwise the second one fT # filter all zero values out .xh # try to take the first value which indicates the winner )0 # if thats not possible because the list is empty # output zero to indicate a draw