On the Subject of Wire Sequences

This challenge is from a game, Keep Talking And Nobody Explodes.

It's hard to say how this mechanism works. The engineering is pretty impressive, but there must have been an easier way to manage nine wires. — from the manual

Input

Exactly 9 "wires", each which is labeled 'A', 'B', or 'C', and is colored red, blue, or black.

Input format and type doesn't matter, as long as they uniquely identify the wires. In particular, the alphabets can be encoded arbitrarily, so can the colors.

Objective and Output

Output the indices of the wires that needs to be cut. The output format and type doesn't matter either, as long as they uniquely identify the wires to be cut.

Which wire to cut?

If the wire has color $$\X\$$ and it's the $$\N\$$th wire of that color that you have seen so far, look at the entry of color $$\X\$$ on row $$\N\$$ of the table. If and only if the wire's label is listed on that entry, it is to be cut.

$$\begin{array}{c|ccc} & \text{Red} & \text{Blue} & \text{Black} \\ \hline \text{1st} & \text{C} & \text{B} & \text{A, B, or C} \\ \text{2nd} & \text{B} & \text{A or C} & \text{A or C} \\ \text{3rd} & \text{A} & \text{B} & \text{B} \\ \text{4th} & \text{A or C} & \text{A} & \text{A or C} \\ \text{5th} & \text{B} & \text{B} & \text{B} \\ \text{6th} & \text{A or C} & \text{B or C} & \text{B or C} \\ \text{7th} & \text{A, B, or C} & \text{C} & \text{A or B} \\ \text{8th} & \text{A or B} & \text{A or C} & \text{C} \\ \text{9th} & \text{B} & \text{A} & \text{C} \end{array}$$

Example

Assuming the wires are 1-indexed, and given the following input:

Blue  C
Blue  C
Black C
Black B
Black A
Red   C
Blue  C
Black A
Black A


The 1st wire is the 1st blue wire, which is not connected to B, so leave it.
The 2nd wire is the 2nd blue wire, which is connected to A or C, so cut it.
The 3rd wire is the 1st black wire, so cut it.
The 4th wire is the 2nd black wire, which is not connected to A nor C, so leave it.
The 5th wire is the 3rd black wire, which is not connected to B, so leave it.
The 6th wire is the 1st red wire, which is connected to C, so cut it.
The 7th wire is the 3rd blue wire, which is not connected to B, so leave it.
The 8th wire is the 4th black wire, which is connected to A or C, so cut it.
The 9th wire is the 5th black wire, which in not connected to B, so leave it.

So the output is [2,3,6,8].

• The example really needs to refer back to the table to be clear. If I understand correctly, you leave the 1st wire because it is the 1st blue wire and because its label isn't B. Similarly, you cut the 2nd wire because it is the 2nd blue wire and its label is one of A or C. – Dingus Aug 30 '20 at 3:03
• @Dingus Yeah, that's right. – Dannyu NDos Aug 30 '20 at 3:11
• The table should be explained better. Maybe something like "Look at each wire in turn. If the wire has color X and it's the Nth wire of that color that you have seen so far, look at the entry of color X on row N of the table. If the wire's label is listed on that entry, then you should cut it." – Zgarb Aug 30 '20 at 6:50
• @Zgarb Thanks!! (Funny thing is, this is why so many people exploded while playing the game.) – Dannyu NDos Aug 30 '20 at 6:51
• I'm all for flexible I/O formats but I think the acceptable values should always be clearly specified for that kind of challenge, as it's pretty easy to put all or part of the data in there. (For instance, here is a 38-byte JS answer.) – Arnauld Aug 31 '20 at 16:33

Jelly,  27  25 bytes

ċṪ$Ƥżḅ3Ʋị“µỵƓṢ⁴ż]¶:ɼ’ḃ7¤&  A dyadic Link accepting a list of the wire colours on the left and a list of the wire labels on the right which yields a list of indicators of whether to cut each wire. Inputs:  Red : 1 A : 1 Blue : 2 B : 2 Black : 3 C : 4  Outputs:  Cut : non-zero (truthy) Don't cut : zero (falsey)  Try it online! Here is an easier to use version accepting the colours, RBK (red, blue, black), on the first line and the labels, ABC on the second line, which yields a list of wire numbers to cut. How? ċṪ$Ƥżḅ3Ʋị“...’ḃ7¤& - Link: colours, labels
Ƥ               -   for prefixes:
$- last two links as a monad - f(prefix): Ṫ - tail -> current wire's colour ċ - count -> number of such wires seen before ż - zip with (colours) 3 - three ḅ - convert (zip result items) from base (3) X = the indexes to check in the flattened table ¤ - nilad followed by link(s) as a nilad: “...’ - 41650313607423351764917 7 - seven ḃ - bijective-base -> [4,2,7,2,5,5,1,2,2,5,1,5,2,2,2,5,6,6,7,4,3,3,5,4,2,1,4] Y = the flattened table as bitmasks of labels to cut ị - (each of X) index into (Y) & - (that) bitwise AND with (labels) (vectorises)  JavaScript (ES6), 75 74 67 bytes Expects a list of [color, label] pairs, using 0-2 for both. Returns a binary array describing which wires must be cut. a=>a.map(([c,w])=>(m[c]/=8)>>w&1,m=[334844576,228136272,611931512])  Try it online! 63 bytes We can save a few bytes by taking A=1, B=2, C=4 and returning a list of zero / non-zero values. a=>a.map(([c,w])=>w&=m[c]/=8,m=[334844576,228136272,611931512])  Try it online! How? Each color is encoded as a bit mask describing the wire labels for the 1st to the 9th appearance.  # | 9 8 7 6 5 4 3 2 1 (0) Label | CBA CBA CBA CBA CBA CBA CBA CBA CBA --- -------+----------------------------------------- Red | 010 011 111 101 010 101 001 010 100 000 -> 334844576 Blue | 001 101 100 110 010 001 010 101 010 000 -> 228136272 Black | 100 100 011 110 010 101 010 101 111 000 -> 611931512  Whenever a color appears, we right-shift the corresponding bit mask by 3 positions (by dividing it by 8) and we test the bit 0, 1 or 2 according to the label. Retina 0.8.2, 119 bytes s(\d)(?<=(\1.*?)+)$1$#2 %(23|4|26|19)A|(22|1[136]|03|5|06|29)B|(2[148]|04|6|17|09)C|(07|28)[AB]|([10]2|18)[AC]|01|27  Try it online! Takes input as list of digit + letter pairs where the digit is 2 for Red, 1 for Blue and 0 for Black. Output is a list of whether each wire should be cut. Explanation: s(\d)(?<=(\1.*?)+)$1$#2  After each digit insert its cumulative appearance count. %(23|4|26|19)A|(22|1[136]|03|5|06|29)B|(2[148]|04|6|17|09)C|(07|28)[AB]|([10]2|18)[AC]|01|27  For each wire check whether it needs to be cut. Rust, 89 bytes |w|w.scan([0;3],|a,&(c,l)|{a[c]+=1;Some(b"TGjEQBMERBuFgCkDJD"[2*a[c]-2+c/2]>>c%2*3+l&1)})  Try it online! Explanation: Both colors and labels are encoded as numbers from 0-2. The output is a number for every wire: 1 if it should be cut, 0 otherwise. The b"TG...D" string contains a binary encoding of the above table. The labels to be cut in every cell is transformed into a 3-bit mask. Three of these masks can be packed into two bytes (Red and Blue in the first byte and Black in the second byte). The 6-th bit (which is unused) is also set, to make all the characters ASCII printable (to not need escape sequences or raw strings). J, 61 bytes Takes in values as Red Blue Black -> 0 1 2, A B C -> 0 1 2 transposed, so color stands above letter in the matrix. Returns a bit-mask of wires to be cut. (9 3 3$-.#:2005405163341131167346014x){::~(1#.{:=}:)\@{.|:@,]


Try it online!

How it works

The table is encoded in (9 3 3\$-.#:2005405163341131167346014x). Convert the long number to base 2, negate it, and reshape to 9 3 3. With a index like 4 1 1 (5th blue B) we get a 1, corresponding to cut. I use the negated form so we have a leading 1. Fun fact: the table razed to a list in base 2 412446475888127182066337 is prime!

t{::~(1#.{:=}:)\@{.|:@,]
{.      the first row (colors)
\@        for each prefix (1, 1 1, 1 1 2, …)
{:=}:           compare last element to all other
1#.                and count the occurrences
,] prepend this to the original list
|:@   and transpose it
t{::~                    get the corresponding bit of the table


Charcoal, 33 bytes

⭆θ§”)∧∨⦃↧dＧ↓◨h↓WK”⍘⁺№Ｅ…θκ§λ⁰§ι⁰ι³


Try it online! Link is to verbose version of code. Takes input as list of digit + letter pairs where the digit is 2 for Red, 1 for Blue and 0 for Black. Output is a binary string of whether each wire should be cut. Explanation:

 θ                      Input list
⭆                       Map over elements and join
”...”                Compressed binary lookup table
§                     Cyclically indexed by
№             Count of
§ ⁰   First character of
ι    Current entry in
… κ         Prefix of
θ          Input list
Ｅ            Map over entries
§ ⁰      First character of
λ       Inner entry
⁺              Concatenated with
ι  Current entry
⍘             ³ Interpreted as base 3
Implicitly print


As an example, the last wire from the example, 0A, is the fifth black wire, therefore there are four wires in the prefix, resulting in a string 40A. This converts as 4 * 9 + 0 * 3 + A, where the letters are decoded using a=10, ... z=35, A=36, ... Z=61, resulting in a final total of 72. The use of uppercase letters here just requires the entire lookup table to be rotated by 36 bits, so it's not necessary to encode the letters.

Python 3, 92 bytes

def f(w):
m,i=[41855572,28517034,76491439],1
for c,t in w:t&m[c]and print(i);i+=1;m[c]>>=3


Takes input as a list of (color, wire) tuples. Color is coded red=0, blue=1, and black=2. Wires are coded A=1, B=2, and C=4. So the example is

[(1, 4), (1, 4), (2, 4), (2, 2), (2, 1), (0, 4), (1, 4), (2, 1), (2, 1)]


m is the encoded table. The 1st row is encoded in the least significant bits. In binary:

table = [
#   9   8   7   6   5   4   3   2   1   <- table row
#  CBA CBA CBA CBA CBA CBA CBA CBA CBA
0b_010_011_111_101_010_101_001_010_100,
0b_001_101_100_110_010_001_010_101_010,
0b_100_100_011_110_010_101_010_101_111
]


After checking a color/label combination, the table column is shifted by 3 bits so that it doesn't need to keep track of the 1st red wire, 2nd red wire, etc.

05AB1E, 32 bytes

ε•1ä)eι()2×rK•b3ô3ô¯yн©¢è®èyθè®ˆ


Input as a pair of [color, wire], where the colors are red=2, blue=1, black=0 and wires are A=0, B=1, C=2. Outputs a list of 0s and 1s, where the 1s are the position of the wires we should cut.

Try it online.

Explanation:

ε                   # Map over each pair y of the (implicit) input:
•1ä)eι()2×rK•      #  Push compressed integer 2199241953913589502631010
b                 #  Convert it to binary: 111010001101101010010010100101100101010010010011011101110001111001101110001100010
3ô               #  Split it into parts of size 3: ["111","010","001","101","101","010","010","010","100","101","100","101","010","010","010","011","011","101","110","001","111","001","101","110","001","100","010"]
3ô             #  Split that list into parts of size 3 again: [["111","010","001"],["101","101","010"],["010","010","100"],["101","100","101"],["010","010","010"],["011","011","101"],["110","001","111"],["001","101","110"],["001","100","010"]]
¯            #  Push the global array
yн          #  Get the first item of the pair
©         #  Store it in variable ® (without popping)
¢        #  Count the amount of times it occurs in the global array
è       #  Use that to index into the list of triplets
®      #  Push the first item of variable ® again
è     #  Use that to index into the triplet
yθ   #  Push the last item of the pair
è  #  Use that to index into the binary-string
®ˆ        #  Add the first item of variable ® to the global array
# (after which the resulting list is output implicitly)


See this 05AB1E tip of mine (section How to compress large integers?) to understand why •1ä)eι()2×rK• is 2199241953913589502631010.

C (gcc), 107 bytes

_,O;P(int*T){for(int R[3]={O=0};9>O++;"T+R&%*{9+*"[_/7]>>_%7&1&&printf("%d ",O))_=*T+R[*T++/3]++*9+*T++;}


Try it online!

Takes an array of { color 1, label 1, color 2, label 2, ...

Each entry of table is encoded in three triplets of bits , one for each color, where each bit represent a label

    r b bla        RedBluBla
abcabcabc
1st c b abc     -> 001010111
2   b ac ac     -> 010101101
3   a b b       -> 100010010
4   ac a ac     -> 101100101
5   b b b       -> 010010010
6   ac bc bc    -> 101011011
7   abc c ab    -> 111001110
8   ab ac c     -> 110101001
9   b a c       -> 010100001


Then all bits are joined, spilt by 7 , reversed and converted to a string T+R&%*{9+*.

To get the the target bit position we multiply by 9 the table line we need and we add color value and label value.

Then we divide by 7 to get the character we need in the encoded string and we shift back by modulo 7