13
\$\begingroup\$

Related: Deck Names Friends or Foes Paying for Spells

The Magic: the Gathering card game has five colours of magical mana: white (W), blue (U), black (B), red (R), and green (G). Cards can be any of the \$2^5=32\$ subsets of these colours. Hereafter 'colours' refer just to the initials W, U, B, R, G.

The order that these colours present themselves on cards follows a method using the colours arranged as a pentagon:

  W
G   U
 R B

The order seeks to minimise the gaps between colours when read clockwise around the pentagon, while making the gaps equal sizes. Ties are broken by starting with W. There are only eight arrangements with rotational symmetry;

  • no colours: C or ''
  • one colour: W, U, B, R, G
  • two adjacent colours: WU, UB, BR, RG, GW
  • two opposite colours: WB, UR, BG, RW, GU
  • three adjacent colours: WUB, UBR, BRG, RGW, GWU
  • three opposite colours: WBG, URW, BGU, RWB, GUR
  • four colours: WUBR, UBRG, BRGW, RGWU, GWUB
  • all five colours, start from the top: WUBRG

Challenge

You challenge is to create a function/program, which when given a set of colours, outputs their correct order.

This is code golf, so your solution should be as short as possible!

Input

Input format is flexible. As long as it is not relying on the order given, anything is acceptable. Some examples:

  • Binary number or bit string of length 5
  • A string/array containing each colour, either a substring of 'WUBRG' or arbitrary order
  • A set or dictionary for each colour

Output

Output must follow standard output methods to output a string/array of the colours. For the case of no colours, an empty string/array or C (colourless) is allowed. Otherwise output must match an entry from the list below. Case doesn’t matter.

For your convenience, here is a list of all possible combinations

C
W
U
B
R
G
WU
UB
BR
RG
GW
WB
UR
BG
RW
GU
WUB
UBR
BRG
RGW
GWU
WBG
URW
BGU
RWB
GUR
WUBR
UBRG
BRGW
RGWU
GWUB
WUBRG
\$\endgroup\$
13
  • 4
    \$\begingroup\$ Is this a kolmogorov-complexity question which we need to output the code block on the last of post? I'm not sure If I understood it correctly. But since you mentioned Input, I would prefer no. So maybe add some testcases here? \$\endgroup\$
    – tsh
    May 16 at 2:02
  • 2
    \$\begingroup\$ Are we allowed to output digits or some other arbitrary characters instead of W, U, B, R, G? \$\endgroup\$
    – Arnauld
    May 16 at 8:30
  • \$\begingroup\$ Could you explain how "The order seeks to minimise the gaps between colours when read clockwise around the pentagon, while making the gaps even." leads to BGU (which has two gaps of size two when read clockwise) rather than UBG (which has only a single gap of size two when read clockwise)? \$\endgroup\$ May 16 at 13:36
  • \$\begingroup\$ @JonathanAllan UBG has a gap of size one as well as a gap of size two; they are unequal (not "even"). \$\endgroup\$
    – m90
    May 16 at 13:52
  • 4
    \$\begingroup\$ Thank you for the clarification about the output format. Note that this invalidates a few answers. \$\endgroup\$
    – Arnauld
    May 16 at 21:46

9 Answers 9

8
\$\begingroup\$

Vyxal, 11 bytes

sṖµ¯5%₍≈⌐;t

Try it Online!

I think this works? Takes a list of 0, 1, 2, 3, 4. Fixed for +1 byte thanks to @KevinCruijssen.

s           # Sort (annoying edgecase)
 Ṗµ      ;t # The maximal permutation by...
   ¯        # Differences
    5%      # Modulo 5
      ₍     # Sort primarily by...
       ≈    # All differences are the same
      ₍     # And secondarily by...
        ⌐   # 1 - the list = minimal value.
\$\endgroup\$
3
  • \$\begingroup\$ OP clarified that when all five letters are input, the output must be in the order WUBRG, so your solution doesn't work for it I'm afraid (nor does my 05AB1E port of you). :/ \$\endgroup\$ May 17 at 6:08
  • \$\begingroup\$ A leading (sort and rotate once towards the left) should fix that edge-case, but maybe you see something shorter? \$\endgroup\$ May 17 at 6:13
  • \$\begingroup\$ @KevinCruijssen Thanks for the help! I think just a regular sort works, since the order of the permutations only matters for that case? \$\endgroup\$
    – emanresu A
    May 17 at 6:16
6
\$\begingroup\$

JavaScript (ES10), 71 bytes

Expects a bitmask in UWGRB order (from most to least significant bit). Returns an array of characters.

n=>[...s="BRGWU"].flatMap(_=>n>>++k%5&1?s[k%5]:[],k=1950448093/n/n%5|0)

Try it online!


JavaScript (ES10), 75 bytes

Expects a bitmask in RBUWG order (from most to least significant bit). Returns an array of characters.

n=>[...s="GWUBR"].flatMap(_=>n>>++k%5&1?s[k%5]:[],k=~~"204122031"[n%19%13])

Try it online!

How?

We build the output by adding characters from the string "GWUBR" according to the bits that are set in the input, starting at a valid position, going from left to right and wrapping.

Fortunately, the starting position is quite flexible. For instance, for the expected output "GW", we can start anywhere except at W because U, B and R are discarded anyway. This allows to increase the number of consistent collisions in the lookup table and make it a little more compact.

Below is a summary of all acceptable starting positions for each pattern, along with the position which is actually chosen.

  n | pattern | acceptable  | i=n%19%13 | ~~"204122031"[i]
----+---------+-------------+-----------+------------------
  0 | ""      | [0,1,2,3,4] |      0    |        2
  1 | "G"     | [0,1,2,3,4] |      1    |        0
  2 | "W"     | [0,1,2,3,4] |      2    |        4
  3 | "GW"    | [1,2,3,4]   |      3    |        1
  4 | "U"     | [0,1,2,3,4] |      4    |        2
  5 | "GU"    | [2,3,4]     |      5    |        2
  6 | "WU"    | [0,2,3,4]   |      6    |        0
  7 | "GWU"   | [2,3,4]     |      7    |        3
  8 | "B"     | [0,1,2,3,4] |      8    |        1
  9 | "BG"    | [0,1,2]     |      9    |        0
 10 | "WB"    | [0,3,4]     |     10    |        0
 11 | "WBG"   | [0]         |     11    |        0
 12 | "UB"    | [0,1,3,4]   |     12    |        0
 13 | "BGU"   | [2]         |      0    |        2
 14 | "WUB"   | [0,3,4]     |      1    |        0
 15 | "GWUB"  | [3,4]       |      2    |        4
 16 | "R"     | [0,1,2,3,4] |      3    |        1
 17 | "RG"    | [0,1,2,3]   |      4    |        2
 18 | "RW"    | [1,2,3]     |      5    |        2
 19 | "RGW"   | [1,2,3]     |      0    |        2
 20 | "UR"    | [0,1,4]     |      1    |        0
 21 | "GUR"   | [4]         |      2    |        4
 22 | "URW"   | [1]         |      3    |        1
 23 | "RGWU"  | [2,3]       |      4    |        2
 24 | "BR"    | [0,1,2,4]   |      5    |        2
 25 | "BRG"   | [0,1,2]     |      6    |        0
 26 | "RWB"   | [3]         |      7    |        3
 27 | "BRGW"  | [1,2]       |      8    |        1
 28 | "UBR"   | [0,1,4]     |      9    |        0
 29 | "UBRG"  | [0,1]       |     10    |        0
 30 | "WUBR"  | [0,4]       |     11    |        0
 31 | "WUBRG" | [0]         |     12    |        0
\$\endgroup\$
4
\$\begingroup\$

JavaScript (Node.js), 258 247 bytes

s=>(c="WUBRG",p=[0,1,2,3].map(i=>(t=>t.slice(i)+t.slice(0,i))(s.sort(m=(x,y)=>c.indexOf(x)-c.indexOf(y)).join``)).filter(x=>new Set([...x.slice(1)].map((z,k)=>(x=>(m(x,z)+5)%5)(x[k]))).size==1),({"WG":"GW","WR":"RW","UG":"GU"})[q=p+p?p[0]:s+p]||q)

Try it online!

\$\endgroup\$
3
  • 8
    \$\begingroup\$ Could I get a reason for the downvote? \$\endgroup\$ May 16 at 2:13
  • \$\begingroup\$ I didn't downvote but potential reasons are: 1. Code is quite long, more than 3 times longer than another Javascript answer (I know you were first) 2. No explanation. I love seeing explanations for code. \$\endgroup\$ May 21 at 1:05
  • \$\begingroup\$ @LevelRiverSt Yeah, the length makes it look a lot worse than it is. This solves it "manually", while Arnauld uses some clever bitwise stuff to implement a lookup table. So this is more of trying more to optimize a specific approach. As for the explanation, fair enough, I'm lazy about doing those :p \$\endgroup\$ May 21 at 2:46
3
\$\begingroup\$

x86-64 machine code, 37 bytes

6B CE 21 B8 47 52 42 55 B2 57 BE FD F7 FD 55 D3 E6 45 18 C0 C1 C0 08 86 D0 D1 D9 78 ED 73 F3 AA 84 C0 75 EE C3

Try it online!

Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes in RDI an address at which to place the result, as a null-terminated byte string, and takes the input bitmask in ESI (W=1, U=2, B=4, R=8, G=16).

In assembly:

f: imul ecx, esi, 33

ECX := 33 * ESI. Transfer the bitmask from ESI to ECX while duplicating bits 0–4 into bits 5–9.

mov eax, ('U'<<24|'B'<<16|'R'<<8|'G')
mov dl, 'W'

Put the colour letters in these registers.

a: mov esi, 0b01010101111111011111011111111101
shl esi, cl

Place this value in ESI, then shift it left by the low 5 bits of ECX. The last bit shifted out goes into CF; a 0 indicates a correct arrangement.

.byte 0x45      # REX.RB
ws: sbb al, al

These combine to form sbb r8l, r8l (subtract R8L+CF from R8L). The value of R8L becomes -CF, and SF is set from its sign bit, equalling CF.

n: rol eax, 8
xchg al, dl

Together, these instructions rotate the five colour letters, while SF remains unchanged.

rcr ecx, 1

Rotate ECX (holding the bitmask) and CF together right by 1; the low bit of ECX goes into CF. Also, SF still remains unchanged.

js a

Jump back if SF=1.

w: jnc ws

At this point, the correct arrangement has been found, and it remains to produce the string from it. Jump if CF (which is the bit just taken off the bitmask) is 0.

stosb

(If it is 1) Add AL to the output string, advancing the pointer.

test al, al
jnz ws

Jump back if AL is nonzero.

ret

(If AL is zero) Return.

Both of the jumps within the output section lead to ws: sbb al, al, which sets AL to 0 (as CF will be zero, from the rcr or from the test), to end the string instead of repeating the letter when it comes back around.


Input 0 is a special case. shl by 0 does not change the flags, but CF will be 0 from the imul to indicate a correct arrangement. Nothing will be written for a while, and all the letters will be replaced with null bytes. Eventually, a 1 bit rotated into the top of ECX by rcr ecx, 1 (from CF becoming 1 from the rol eax, 8) will make its way to the bottom and then back into CF, resulting in outputting a null byte and returning.

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

Python, 171 bytes

lambda s,g="WUBRG":[min([[e,p]for p in permutations(s)if len(set(e:=[(g.find(p[i+1])-g.find(p[i]))%5 for i in range(len(s)-1)]))<2])[1],g][len(s)>4]
from itertools import*

Attempt This Online!

Works similarly to @emanresuA's answer, but derived independently. Takes a string as input, outputs a list

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

Python, 106 bytes

f=lambda s,t=0:(2*"WUBRG")[x:x+len(y):1-t]if~(x:=(2*s).find(y:=(s.count("1")*"01"[~t:])[-t:]))else f(s,~t)

Attempt This Online!

Test harness shamelessly stolen from @jezza_99. Expects a binary string indicating which of "WUBRG" are present.

How?

Counts "1"s in the input, for example 3 "1"s. Then checks for the patterns "111" and "10101" in 2*input where the factor 2 is to simulate wrap around. Finally, finds the same index in 2*"WUBRG" and cuts out the corresponding letters.

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

R, 84 bytes

\(i)chartr("0-4","WUBRG",Find(\(j)all(i%in%j),Map(\(j)seq(j%%5,,j%/%5,,i)%%5,5:24)))

Attempt This Online!

Takes input as a vector of numbers 0-4, outputs a vector of letters.

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

05AB1E, 11 13 bytes

{ÀœΣ¥5%(DËš}θ

Port of @emanresuA's Vyxal answer, so make sure to upvote him/her as well!
+2 bytes to correct the output when all five values are input

Uses 1,2,3,4,5 for W,U,B,R,G respectively.

Try it online or verify all test cases.

Explanation:

           # Fix the output of the edge-case when all five values are input:
{          #  Sort the (implicit) input-list
 À         #  Rotate it once towards the left
œ          # Get all permutations of this list
 Σ         # Sort this list of lists by:
  ¥        #  Get the differences of the current list
   5%      #  Modulo-5 for the negative values
     (     #  Negate all of these values
      D    #  Duplicate it
       Ë   #  Check if all values in the copy are the same
        š  #  Prepend this 0 or 1 to the list of negative differences
 }θ        # After the sort_by: pop and push the last value
           # (the `Σ...}θ` basically acted as a max_by builtin)
           # (after which the result is output implicitly)
\$\endgroup\$
2
  • \$\begingroup\$ If you use 0, 1, 2, 3, 4 I think the rotate isn't necessary? (or does modulo not work with that?) \$\endgroup\$
    – emanresu A
    May 17 at 21:20
  • \$\begingroup\$ @emanresuA The modulo is on the forward differences, not on the input-values itself. So it shouldn't really matter if we use 0-4, 1-5, or even 6-10. Here the modified test suite with 0-based values and just the sort without rotate. The problem is that the five possible rotational symmetric lists (1,2,3,4,5/2,3,4,5,1/3,4,5,1,2/4,5,1,2,3/5,1,2,3,4) all have the same values within the sorting algorithm (1,-1,-1,-1,-1), so we need to put the 1,2,3,4,5 at the end before the stable sort. \$\endgroup\$ May 17 at 21:29
0
\$\begingroup\$

Charcoal, 26 25 bytes

⊟ΦEχ⭆θ§UBRGW⁺ι×μ⊕‹ι⁵⬤ι№θλ

Try it online! Link is to verbose version of code. Explanation: Generates all cyclic slices of UBRGW with step of either 2 or 1 having the length of the input and outputs the last that is a permutation of the input.

   χ                        Predefined variable `10`
  E                         Map over implicit range
     θ                      Input string
    ⭆                       Map over characters
       UBRGW                Literal string `UBRGW`
      §                     Cyclically indexed by
             ι              Outer value
            ⁺               Plus
               μ            Inner index
              ×             Times
                  ι         Outer value
                 ‹          Is less than
                   ⁵        Literal integer `5`
                ⊕           Incremented
 Φ                          Filtered where
                     ι      Current string
                    ⬤       All characters satisfy
                       θ    Input string
                      №     Contains
                        λ   Current character
⊟                           Take the last element (smallest delta)
                            Implicitly print

For input strings of lengths 1 to 5 the following strings are generated:

  1. U B R G W U B R G W
  2. UR BG RW GU WB UB BR RG GW WU
  3. URW BGU RWB GUR WBG UBR BRG RGW GWU WUB
  4. URWB BGUR RWBG GURW WBGU UBRG BRGW RGWU GWUB WUBR
  5. URWBG BGURW RWBGU GURWB WBGUR UBRGW BRGWU RGWUB GWUBR WUBRG

In the case of strings of length 1 the same string is generated twice so it doesn't matter which is picked while in the case of strings of length 2 or 3 all 10 permutations are generated so there is only one matching the input but in the case of strings of length 4 or 5 there would be multiple matching strings; in the case of 4 the first five are invalid and in the case of 5 the first nine are invalid so that the last matching string is the correct output as desired.

\$\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.