9
\$\begingroup\$

Your task is simple: tell me who wins the battle of the letters.

The troops

There are three different "troops" in this battle, summarized by this table.

name | health | damage
   A       25       25
   B      100        5
   C       10       50

You may use any three unique characters to represent the the troops, but must specify if they are not these letters.

The battle

Suppose we have a sample battle:

ABC # army 1
CBA # army 2

Each army repeatedly fires at the leftmost unit, until it is dead; then they move to the troop to the right and repeat. So army 2 attacks A in army 1 until A is dead, then move to B, then C. Army 1 attacks C first, then B, then A. Assume the armies attack at the same time, and thus troops will always fire if they were alive before the round and can kill each other at the same time. They fire in order from left to right.

The battle would play out as so:

ABC
CBA

BC # A (25 hp) killed by C (-50 hp), B (100 hp) attacked by B (-5 hp) and A (-25 hp), has 70 hp
BA # C (10 hp) killed by A (-25 hp), B (100 hp) attacked by B (-5 hp) and C (-50 hp), has 45 hp

BC # B (70 hp) attacked by B (-5 hp) and A (-25 hp), has 40 hp
A  # B (45 hp) killed by B (-5 hp) and C (-50 hp)

BC # B (40 hp) attacked by A (-25 hp), has 15 health
   # A (25 hp) killed by B (-5 hp) and C (-50 hp), army 2 dead

Therefore, army 1 wins the battle!

Input

Two strings, the first representing army 1 and the second army 2. They are not necessarily the same size (because who said it would be a fair fight?)

Output

Any three unique, constant values to represent army 1 winning, army 2 winning, or the unlikely event of a tie. Yes, it is possible for the last troops to kill each other, ending in a tie.

Battles

ABC
CBA
Army 1

CCCCC
CCCCC
Tie

CABCAB
ABBABBA
Army 2

Standard loopholes apply. You must submit a full program.

This is , shortest solution wins.

\$\endgroup\$
  • \$\begingroup\$ "constant" Why? \$\endgroup\$ – CalculatorFeline Jun 1 '17 at 2:53
  • \$\begingroup\$ Also, A beats B and C ties B and A ties C. Changing either of A's values to 20 would make it tie B. \$\endgroup\$ – CalculatorFeline Jun 1 '17 at 2:57
  • 2
    \$\begingroup\$ Are we allowed to use a different input representation? Say, 012 instead of ABC? \$\endgroup\$ – Grimmy Jun 1 '17 at 9:19
  • \$\begingroup\$ @Grimy: Yes, I will edit the post. \$\endgroup\$ – Neil A. Jun 1 '17 at 17:21
3
\$\begingroup\$

Pyth 145 97 bytes

=Y.d[,\A,25 25,\B,*TT5,\C,T*5T)Km=G@YdzJm=H@YdwW&KJMX0hG_smedH gKJ gJKI<hhK0=tK)I<hhJ0=tJ;?K1?J2Z

A little less naive than before.

Try it online!

Explanations:

Let's cut the program in several parts.

=Y.d[,\A,25 25,\B,*TT5,\C,T*5T)

     ,\A,25 25                     Create this list: ['A', [25, 25]]
              ,\B,*TT5             Create this list: ['B', [100, 5]]
                      ,\C,T*5T     Create this list: ['C', [10, 50]]
  .d[                         )    From the three lists, create a dictionary whose keys are the letters, and values are the inner lists
=Y                                 Assign to the variable Y

The dictionary Y is: {'A': [25, 25], 'C': [10, 50], 'B': [100, 5]}. Then:

Km=G@YdzJm=H@YdwMX0hG_smedH

 m=G@Ydz                           For all letters in first input string, make a copy of Y[letter]. Make a list of all those values...
K                                  ...and assign the list to the variable K
         m=H@Ydw                   For all letters in second input string, make a copy of Y[letter]. Make a list of all those values...
        J                          ...and assign the list to the variable J
                MX0hG_smedH        Create a function g which takes two lists of couples, and subtract the sum of the second elements of the couples of the second list from the first element of the first couple of the first list

At this point, K is a list of couples that represents the first army. Each couple of this list is a letter of the army, and is (health, damage) for that letter. J is exactly the same, but for the second army. g is a function which takes two armies, and deals the damage made by the second army to the first one. Now:

W&KJ gKJ gJKI<hhK0=tK)I<hhJ0=tJ;

W&KJ                               While K not empty and J not empty
     gKJ                           Call g(K,J). That computes the damages to first army
         gJK                       Call g(J,K). That computes the damages to second army
            I<hhK0=tK)             If the first army's first letter is dead, remove it
                      I<hhJ0=tJ    If the second army's first letter is dead, remove it
                               ;   End of while loop

When the while loop is over, K and J have their final value. If they are both empty, it's a tie; otherwise the non-empty army win. That is handled by the last piece of code:

?K1?J2Z

?K1                                If K non-empty, display 1. Else...
   ?J2                             ...if J non-empty, display 2. Else...
      Z                            ...display zero

That's it!

|improve this answer|||||
\$\endgroup\$
2
\$\begingroup\$

Haskell, 199 193 179 176 171 bytes

a!b=(t<$>a)?(t<$>b)
t v=[(5,5),(20,1),(2,10)]!!(fromEnum v-65)
m=sum.map snd
f=filter((>0).fst)
[]?[]=0
[]?_=2
_?[]=1
a@((c,d):e)?b@((h,i):j)=f((c-m b,d):e)?f((h-m a,i):j)

Try it online!

Small trick: divided all the army stats by 5.

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

C#, 446 Bytes

using System.Linq;(c,d)=>{int z=c.Length,v=d.Length,j=0,k=0,l=0,m=0,q=0;int[]e=(c+d).Select(x=>x!='A'?x=='B'?100:10:25).ToArray(),f=e.Skip(z).ToArray();e=e.Take(z).ToArray();int[]g=(c+d).Select(x=>x!='A'?x=='B'?5:100:25).ToArray(),h=g.Skip(z).ToArray();g=g.Take(z).ToArray();try{for(;;){for(q=l;q<z;q++){if(e[j]<=0)j++;e[j]-=h[q];}for(q=k;q<v;q++){if(f[m]<=0)m++;f[m]-=g[q];}if(e[k]<=0)k++;if(f[l]<=0)l++;}}catch{}return k-z>=l-v?k-z>l-v?0:2:1;};

Formatted version:

         (c, d) => {
                int z = c.Length, v = d.Length, j = 0, k = 0, l = 0, m = 0, q = 0;

                int[] e = (c + d).Select(x => x != 'A' ? x == 'B' ? 100 : 10 : 25).ToArray(), f = e.Skip(z).ToArray();
                e = e.Take(z).ToArray();

                int[] g = (c + d).Select(x => x != 'A' ? x == 'B' ? 5 : 100 : 25).ToArray(), h = g.Skip(z).ToArray();
                g = g.Take(z).ToArray();

                try {
                    for (;;) {
                        for (q = l; q < z; q++) {
                            if (e[j] <= 0) j++; e[j] -= h[q];
                        }
                        for (q = k; q < v; q++) {
                            if (f[m] <= 0) m++; f[m] -= g[q];
                        }
                        if (e[k] <= 0) k++; if (f[l] <= 0) l++;
                    }
                }
                catch {
                }

                return k - z >= l - v ? k - z > l - v ? 0 : 2 : 1;
            };

Outputs 1 if army1 wins , 2 for army2 and 0 for tie

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Can you add a formatted/expanded version? 446 bytes is high even for C# I'm sure there will be some improvements. \$\endgroup\$ – TheLethalCoder Jun 1 '17 at 13:34
  • \$\begingroup\$ For starters you have multiple lines declaring int[] I think you can combine them, ``<=0` is the same as <1 surely? Do you need the try-catch? \$\endgroup\$ – TheLethalCoder Jun 2 '17 at 8:15
0
\$\begingroup\$

Javascript (ES6) - 316 269 Bytes

I'm sure this can be golfed like hell, but this is what I've come up with :) I managed to shave off 47 bytes though!

Outputs 0 for tie, 1 for Team 1 and 2 for Team 2.

l=(d,f)=>{for(t=[d,f].map(g=>g.split``.map(k=>[[25,100,10],[25,5,50]].map(m=>m[k.charCodeAt()-65])));(w=t.map(g=>g.some(k=>0<k[0])))[0]&&w[1];)t.forEach((g,k,m)=>m[k].sort(o=>0>o[0])[0][0]-=m[+!k].filter(o=>0<o[0]).reduce((o,p)=>o+p[1],0));return w[0]||w[1]?w[0]?1:2:0}

Readable:

function ltt(a,b){
    t=[a,b].map(x=>x.split``.map(c=>[[25,100,10],[25,5,50]].map(e=>e[c.charCodeAt()-65])))
    while((w=t.map(_=>_.some(x=>x[0]>0)))[0]&&w[1]){
        t.forEach((y,i,n)=>n[i].sort(j=>j[0]<0)[0][0]-=n[+!i].filter(x=>x[0]>0).reduce((h,v)=>h+v[1],0))
    }
    return(!w[0]&&!w[1])?0:(w[0])?1:2
}

Demo:

l=(d,f)=>{for(t=[d,f].map(g=>g.split``.map(k=>[[25,100,10],[25,5,50]].map(m=>m[k.charCodeAt()-65])));(w=t.map(g=>g.some(k=>0<k[0])))[0]&&w[1];)t.forEach((g,k,m)=>m[k].sort(o=>0>o[0])[0][0]-=m[+!k].filter(o=>0<o[0]).reduce((o,p)=>o+p[1],0));return w[0]||w[1]?w[0]?1:2:0}

var prnt=(g,h)=>{
  n=l(g,h);
  return(n==0)?"Tie!":`Team ${n} wins!`
}

console.log("ABCB - ABC: " + prnt("ABCB","ABC"));
console.log("BAAA - BBC: " + prnt("BAAA","BBC"));
console.log("AAAA - BBC: " + prnt("AAAA","BBC"));
console.log("ABC - BBC: " + prnt("ABC","BBC"));
console.log("ABC - CBA: " + prnt("ABC","CBA"));

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Just noticed that current version can't evaluate ties, which the 316 byte version could. I'll look into it \$\endgroup\$ – Hankrecords Jun 5 '17 at 10:53

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.