64
\$\begingroup\$

In the card game Magic: the Gathering there are five different colours, which represent loose affiliations of cards, White (W), Blue (U), Black (B), Red (R) and Green (G). These are often arranged in a pentagon as follows:

  W
G   U
 R B

Both in the lore of MtG as well as in many card mechanics, adjacent colours in this pentagon are usually considered allies, and non-adjacent (sort of opposite) colours are considered enemies.

In this challenge, you'll be given two colours and should determine their relationship.

The Challenge

You're given any two distinct characters from the set BGRUW. You may take these as a two-character string, a string with a delimiter between the characters, two separate character values, two singleton strings, two integers representing their code points, or a list or set type containing two characters/strings/integers.

Your output should be one of two distinct and consistent values of your choice, one which indicates that the two colours are allies and one which indicates that they are enemies. One of those two values may be no output at all.

You may write a program or a function and use any of the our standard methods of receiving input and providing output.

You may use any programming language, but note that these loopholes are forbidden by default.

This is , so the shortest valid answer – measured in bytes – wins.

Test Cases

There are only 20 possible inputs, so I'll list them all.

Friends:

WU   UB   BR   RG   GW   UW   BU   RB   GR   WG

Foes:

WB   UR   BG   RW   GU   BW   RU   GB   WR   UG
\$\endgroup\$
  • 32
    \$\begingroup\$ Up next: implement the core rules :P \$\endgroup\$ – Captain Man Mar 14 '17 at 14:56
  • 11
    \$\begingroup\$ @CaptainMan i will upvote you if you can make it fit in a 30k character post :) \$\endgroup\$ – Walfrat Mar 14 '17 at 15:58
  • \$\begingroup\$ @Walfrat 30k? Should be possible \$\endgroup\$ – Not that Charles Mar 15 '17 at 21:03
  • 2
    \$\begingroup\$ @IvanKolmychek from the most unexpected alliances comes the most unexpected outcomes. \$\endgroup\$ – aluriak Mar 19 '17 at 1:59
  • 1
    \$\begingroup\$ Fun fact: Magic: The gathering is turing complete :) \$\endgroup\$ – lol Mar 20 '17 at 8:04

45 Answers 45

2
\$\begingroup\$

///, 40 bytes

//i//R///G///W///U///B///i/1/WUBRGWGRBUW

Try it online!

Since /// has no other way of taking input, you need to put your input after the first /. An example of checking WG:

/WG/i//R///G///W///U///B///i/1/WUBRGWGRBUW

Itflabtijtslwi, 52 bytes

GGjGGGGkGG/jk/i//R///G///W///U///B///i/1/WUBRGWGRBUW

Try it online!

Outputs a 1 if they are allies, otherwise outputs nothing.

The funny part is that it is actually a shorter answer than some "real" languages have.

You may be thinking, "You're not allowed to code the input in the program!" But you are allowed to do so if the language has no other way of getting input, as said here: meta.codegolf.stackexchange.com/a/10553/64159.

Thanks to Ørjan Johansen for the help with the Itflabtijtslwi port and making the interpreter. Very much.

\$\endgroup\$
  • \$\begingroup\$ Ah, okay. Didn't know about that. \$\endgroup\$ – Rɪᴋᴇʀ Mar 14 '17 at 15:29
  • \$\begingroup\$ The itflabtijtslwi won't work, first a GG...GG command only reads a single character, secondly it substitutes the other way around. Try something like GGjGGGGkGG/jk/i/. \$\endgroup\$ – Ørjan Johansen Mar 16 '17 at 4:47
  • \$\begingroup\$ @ØrjanJohansen I made the edit, is that correct? Also, is there an online interpreter for itflabtijtslwi? I could not find one. \$\endgroup\$ – Comrade SparklePony Mar 16 '17 at 13:48
  • \$\begingroup\$ Try it online! Stripped my Perl one into a TIO header/footer. Still large for comments. :( \$\endgroup\$ – Ørjan Johansen Mar 16 '17 at 15:02
  • 1
    \$\begingroup\$ Sure. I just added the TIO hack to the Esolang wiki to make it official :) \$\endgroup\$ – Ørjan Johansen Mar 16 '17 at 15:10
2
\$\begingroup\$

Python 2, 56 46 28 Bytes

print input()in"WUBRGWGRBUW"

Takes input as a string and returns True or False if it is in the string b. Try it here! Thanks to @Григорий Перельман for removing 10 bytes! Thanks @SparklePony for removing another 18 bytes!

\$\endgroup\$
2
\$\begingroup\$

Brain-Flak, 78 bytes

(([(({}[{}]))]<>)){({}())<>}([]()(([])[]([][][]({}{}({}))))){{}}{}({()<{{}}>})

Try it online!

This improves on DJMcMayhem's answer by streamlining the comparisons. It also uses the negative absolute value directly instead of using extra instructions to reach the positive absolute value.

\$\endgroup\$
1
\$\begingroup\$

Batch, 62 bytes

@set s=WUBRGWGRBUW
@call set t=%%s:%1=%%
@if %s%==%t% echo 1

Outputs 1 for foes, nothing for friends.

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 42 34 32 bytes

'WUBRGWGRBUW'.indexof($args)-ge0

Try it online!

Input is as a single string (e.g., RG), that is stringified $args and used as the .indexof() parameter for the color string. If the substring is not found, -1 is returned, so testing whether the result is -greater-than-or-equal to 0 suffices for a truthy/falsey output.

Saved two more bytes thanks to Philipp Leiß.

\$\endgroup\$
1
\$\begingroup\$

S.I.L.O.S, 53 bytes

loadLine
a=get 256
b=get 257
a*b
a%103
a%2
printInt a

Try it online!

Input as a commmand line argument Please do note that this uses the method from the most upvoted answer

\$\endgroup\$
1
\$\begingroup\$

PHP, 45 Bytes

I know if I use a mod solution from someone else, that I can do it much shorter.

the absolute difference mod 17 mod 5 is 1 or 2

<?=abs(ord($t=$argv[1])-ord($t[1]))%17%5+1&2;

golfed down by @Titus from 64 Bytes

<?=in_array((abs(ord(($t=$argv[1])[0])-ord($t[1]))%17)%5,[1,2]);

PHP, 72 Bytes

the absolute difference mod 17 foes contains a digit between 3 and 5

<?=preg_match("#^[^3-5]+$#",(abs(ord(($t=$argv[1])[0])-ord($t[1]))%17));

PHP, 88 Bytes

the absolute difference mod 17 friends have a digit sum of 2 or 7

<?=in_array(array_sum(str_split((abs(ord(($t=$argv[1])[0])-ord($t[1]))%17))),[2,7])?1:0;

PHP >= 7.1, 81 Bytes

$p=strpos($s=WUBRG,($i=$argv[1])[0]);echo$i[1]==$s[$p!=4?$p+1:0]|$i[1]==$s[$p-1];

http://sandbox.onlinephpfunctions.com/code/9136a36084ecb5b397466e839210b50a88d8fe98

\$\endgroup\$
  • \$\begingroup\$ Oh well ... stolen arithmetics: echo ord($argn)*ord($argn[1])%51<9; is another 9 bytes shorter (35 bytes). \$\endgroup\$ – Titus Mar 15 '17 at 4:27
1
\$\begingroup\$

Java 8, 17 16 14 bytes

This is simply a Java lambda version of the same arithmetic solution everyone else is using. Takes two integral/character arguments containing the color codes as ASCII. Returns true if they are friends, false if foes.

Golfed:

a->b->a*b%51<9

Ungolfed:

import java.util.function.*;

public class MagicTheGatheringFriendsOrFoes {

  private static final char[][] FRIENDS = new char[][] { { 'W', 'U' }, { 'U', 'B' }, { 'B', 'R' }, { 'R', 'G' },
      { 'G', 'W' }, { 'U', 'W' }, { 'B', 'U' }, { 'R', 'B' }, { 'G', 'R' }, { 'W', 'G' } };

  private static final char[][] FOES = new char[][] { { 'W', 'B' }, { 'U', 'R' }, { 'B', 'G' }, { 'R', 'W' },
      { 'G', 'U' }, { 'B', 'W' }, { 'R', 'U' }, { 'G', 'B' }, { 'W', 'R' }, { 'U', 'G' } };

  public static void main(String[] args) {
    System.out.println("Friends: expect true");
    for (char[] friends : FRIENDS) {
      boolean result = f().apply(Integer.valueOf(friends[0])).apply(Integer.valueOf(friends[1]));
      System.out.println("(" + friends[0] + "," + friends[1] + ") = " + result);
    }

    System.out.println();
    System.out.println("Foes: expect false");
    for (char[] foes : FOES) {
      boolean result = f().apply(Integer.valueOf(foes[0])).apply(Integer.valueOf(foes[1]));
      System.out.println("(" + foes[0] + "," + foes[1] + ") = " + result);
    }
  }

  private static Function<Integer, IntFunction<Boolean>> f() {
    return a -> b -> a * b % 51 < 9;
  }
}
\$\endgroup\$
  • \$\begingroup\$ "This is simply a Java lambda version of the same arithmetic solution everyone else is using." I believe you're only the third person using it. ;) \$\endgroup\$ – Martin Ender Mar 14 '17 at 8:08
  • \$\begingroup\$ You can remove the final ; as it's not part of the function itself. Also, you can curry it: a->b->a*b%51<9 for 14 bytes total. \$\endgroup\$ – Olivier Grégoire Mar 16 '17 at 9:59
  • \$\begingroup\$ Finally, you counted 1 byte too much: your answer is 16 bytes, but you say it's 17. \$\endgroup\$ – Olivier Grégoire Mar 16 '17 at 10:06
  • \$\begingroup\$ @OlivierGrégoire you are correct, the trailing ; should not be counted. As far as currying, I can't quite get that to compile no matter how I set up the second function. What approach should I take here? \$\endgroup\$ – user18932 Mar 16 '17 at 13:28
  • \$\begingroup\$ interface FunctionA { FunctionB apply(int a); } interface FunctionB { boolean apply(int b); } then you use it like this: FunctionA f = a->b->a*b%51<9;. \$\endgroup\$ – Olivier Grégoire Mar 16 '17 at 13:45
1
\$\begingroup\$

bash, 23 bytes

[[ WUBRGWGRBUW =~ $1 ]]

Exits/returns 0 (success/true) if friends, 1 (failure/false) if enemies.

This works by using the input string (for example, WU) as a regular expression using bash's builtin [[, which tests various things, in this case, the =~ operator of [[ is used to see if the first string WUBRGWGRBUW matches the regex (input string). Since the regex is not anchored by default, so long as the input string occurs anywhere in the "checked" string, [[ returns the status code 0, meaning the test result was true. If the input character pair did not occur anywhere in the string, it returns status code 1, meaning the test result was false. The tested string is a concatenation of all possible adjacent friend characters, so it's matched only by the friend-pair inputs.

Test:

for pair in WU UB BR RG GW UW BU RB GR WG WB UR BG RW GU BW RU GB WR UG
do
  bash -c '[[ WUBRGWGRBUW =~ $1 ]]' - $pair
  echo $pair $?
done
\$\endgroup\$
1
\$\begingroup\$

OIL, 77 bytes

Third-worst answer, but hey, it's OIL. Commented for clarity (remove spaces and C++-style comments for execution)

WU //storage, this just nops
UB
BR
RG
GW
UW
BU
RB
GR
WG
5  // read user input into line 10 (overwriting this line)
10
10 // test if what's in line 10 (the user input) &
10
0  // is identical to what's in line 0 (the first string) *
26 // if so, jump to line 26 (marked with %)
17 // else, jump to the next line
8  // increment line 14 (marked with *)
14
10 // test if line 14 is identical to
14
11 // what's in line 11 (a "10")
27 // if so, we checked all strings; so jump to line 27 (marked with $)
24 // else jump to the next line
6  // jump to line 12 (marked with &)
12
4  // print what's in line 4 ("GW" ≙ friend) %
4  // print what's in line 0 ("WU" ≙ foe) $

Prints GW if the colours are allies, WU otherwise (and if any unexpected input occurs).

\$\endgroup\$
1
\$\begingroup\$

Brain-Flak, 90 bytes

(<({}[{}])>)([[]()]((([])[][][])[][])){([({}<>)])<>}{}<>({<({}<>({}))>(){[()](<{}>)}{}<>})

Try it online!

This beats the previous Brain-Flak answer by swapping getting the absolute value of the difference with creating negative copies of the differences to check. It also has slightly better number generation and difference checking

\$\endgroup\$
0
\$\begingroup\$

Pyth, 16 bytes

gx+J"WUBRGW"_JzZ

Test suite available online.

Explanation

gx+J"WUBRGW"_JzZ
   J"WUBRGW"      store string in variable J
  +         _J    concat J and reversed J
 x            z   get index of input in this string
g              Z  return if index >= 0 (will be -1 if not found)
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 20 bytes

a=>b=>(a-b)%9%5%3!=0

let F = a=>b=>(a-b)%9%5%3!=0
let ch = [87, 85, 66, 82, 71];

console.log('Friends:');
console.log('WU/UW', F(ch[0])(ch[1]), F(ch[1])(ch[0]));
console.log('UB/BU', F(ch[1])(ch[2]), F(ch[2])(ch[1]));
console.log('BR/RB', F(ch[2])(ch[3]), F(ch[3])(ch[2]));
console.log('RG/GR', F(ch[3])(ch[4]), F(ch[4])(ch[3]));
console.log('GW/WG', F(ch[4])(ch[0]), F(ch[0])(ch[4]));

console.log('Foes:');
console.log('WB/BW', F(ch[0])(ch[2]), F(ch[2])(ch[0]));
console.log('UR/RU', F(ch[1])(ch[3]), F(ch[3])(ch[1]));
console.log('BG/GB', F(ch[2])(ch[4]), F(ch[4])(ch[2]));
console.log('RW/WR', F(ch[3])(ch[0]), F(ch[0])(ch[3]));
console.log('GU/UG', F(ch[4])(ch[1]), F(ch[1])(ch[4]));

Takes input as ascii character codes, passed in as F(a)(b) (one character each). Returns true for friends, false for foes.

Thanks to Mistah Figgins for the modulo idea.

\$\endgroup\$
0
\$\begingroup\$

QBIC, 29 bytes

;?instr(@WUBRG`+@W`+_fB|,A)>0

Explanation:

;       Gets the color combination as one strintg, "UG"
?       Print --> will eventually yield -1 for allies and 0 otherwise
instr(  Get the index of one string in antother. 
@WUBRG` The string to be searced is all allies, (@...` creates a string called B$)
+@W`      and an extra 'W' that we don't want to flip (prevents 'WW')
+_fB|    and all allies flipped --> WUBRGWGRBUW
,A)    The string to look for: "UG"
>0     If A is found in B+G+fB, this is >0, and PRINT will show -1 (QBasic's TRUE value)
       It prints 0 in all other cases.

This would be two bytes shorter if we could say that any positive value is true, and 0 is false...

\$\endgroup\$
0
\$\begingroup\$

C#, 37 Bytes

(string s)=>"GWUBRGRBUWG".Contains(s)
\$\endgroup\$

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.