DEV Community

Discussion on: Daily Challenge #43 - Boardgame Fight Resolver

Collapse
 
willsmart profile image
willsmart • Edited

I'm surprised no-one has used the age old xor-the-second-bit-of-the-first-characters-and-xor-the-fifth-bit-of-first-and-second-characters trick 😉

In C:

const char *defenderWins(const char *attacker, const char *defender) {
    return (((attacker[0] ^ defender[0]) & 2) | ((attacker[1] ^ defender[0]) & 0x10)) == 0x12;
}

Clearly, this doesn't really need any testing, but here's an exhaustive dump, err, full set of trials, just to be pedantic

#include <stdio.h>

const char *winner(const char *attacker, const char *defender) {
    return (((attacker[0] ^ defender[0]) & 2) | ((attacker[1] ^ defender[0]) & 0x10)) == 0x12 ? defender : attacker;
}

int main()
{
    const char *teams[] = { "archers","swordsmen", "pikemen", "cavalry" };
    const size_t teamCount=sizeof(teams)/sizeof(*teams);

    for (int attackeri = 0; attackeri<teamCount; ++attackeri) {
        for (int defenderi = 0; defenderi<teamCount; ++defenderi) {
            const char *attacker = teams[attackeri];
            const char *defender = teams[defenderi];
            printf("%s -> %s : %s wins\n", attacker, defender, winner(attacker,defender));
        }
    }
    return 0;
}

prints:

archers -> archers : archers wins
archers -> swordsmen : archers wins
archers -> pikemen : archers wins
archers -> cavalry : cavalry wins
swordsmen -> archers : archers wins
swordsmen -> swordsmen : swordsmen wins
swordsmen -> pikemen : swordsmen wins
swordsmen -> cavalry : swordsmen wins
pikemen -> archers : pikemen wins
pikemen -> swordsmen : swordsmen wins
pikemen -> pikemen : pikemen wins
pikemen -> cavalry : pikemen wins
cavalry -> archers : cavalry wins
cavalry -> swordsmen : cavalry wins
cavalry -> pikemen : pikemen wins
cavalry -> cavalry : cavalry wins
Collapse
 
avalander profile image
Avalander

Care to explain how it works? I don't get it 😅

Collapse
 
willsmart profile image
willsmart

Sure thing. It's a "don't look behind the curtain" kind of thing 🧙‍♂️
here's the rest of the code...

const a = [
  'archers',
  'swordsmen', 'pikemen', 'cavalry'
]
let i1 = 2,
  i2 = 1,
  i3 = 3,
  i4 = 3,
  i5 = 2,
  i6 = 2,
  i7 = 2,
  i8 = 2

winner_mank = (s1, s2) => ((s1.charCodeAt(i1) >> i3) ^ ((s2.charCodeAt(i2)) >> i4)) & ((s1.charCodeAt(i5) >> i7) ^ ((s2.charCodeAt(i6)) >> i8)) & 1 ? s2 : s1

winner_good = (s1, s2) => a.indexOf(s1) == (a.indexOf(s2) + 1) % 4 ? s2 : s1

verify = () => {
  for (const s1 of a) {
    for (const s2 of a) {
      if (winner_good(s1, s2) != winner_mank(s1, s2)) return
    }
  }
  console.log({
    i1,
    i2,
    i3,
    i4,
    i5,
    i6,
    i7,
    i8
  })
  debugger
  return true
}

for (i1 = 0; i1 < 7; i1++) {
  for (i2 = 0; i2 < 7; i2++) {
    for (i3 = 0; i3 < 8; i3++) {
      for (i4 = 0; i4 < 8; i4++) {
        for (i5 = 0; i5 < 7; i5++) {
          for (i6 = 0; i6 < 7; i6++) {
            for (i7 = 0; i7 < 8; i7++) {
              for (i8 = 0; i8 < 8; i8++) {
                verify()
              }
            }
          }
        }
      }
    }
  }
}

winner_mank is reducible to the one posted when i1=i3=0, i2=i4=1, i5=1,i7=0, i6=i8=4. And I felt it was may as well be in C.
I was lying about the age old trick thing. Upside is it's really really quick, downsides are all the other things 😂