Compatibilidade com vampiros

28

Um fato pouco conhecido sobre os vampiros é que eles devem beber o sangue da vítima que possui um tipo de sangue compatível de doador. A matriz de compatibilidade para vampiros é a mesma que a matriz doadora / receptora regular de glóbulos vermelhos . Isso pode ser resumido na seguinte tabela da Cruz Vermelha Americana

Type    You Can Give Blood To    You Can Receive Blood From
A+      A+, AB+                  A+, A-, O+, O-
O+      O+, A+, B+,AB+           O+, O-
B+      B+, AB+                  B+, B-, O+, O-
AB+     AB+                      everyone
A-      A+, A-, AB+, AB-         A-, O-
O-      everyone                 O-
B-      B+, B-, AB+, AB-         B-  O-
AB-     AB+, AB-                 AB-, A-, B-, O-

Desafio

Escreva uma função ou programa que use um tipo de sangue como entrada e produz duas listas:

  1. a lista não ordenada de tipos que podem receber doação do tipo de entrada
  2. a lista não ordenada de tipos que podem doar para o tipo de entrada

Se você escrever uma função, forneça também um programa de teste para chamar essa função com alguns exemplos, para que eu possa testá-la facilmente. Nesse caso, o programa de teste não conta para a sua pontuação.

Entrada

A entrada deve ser uma sequência que represente exatamente um dos 8 tipos possíveis de glóbulos vermelhos O− O+ A− A+ B− B+ AB− AB+. A entrada pode ser fornecida pelos métodos normais (STDIN, argumentos da linha de comando, argumentos da função, etc.).

Se qualquer outra entrada for fornecida, o programa / função deve retornar uma saída vazia ou gerar um erro. Normalmente, a verificação estrita de entradas não é boa em questões de , mas, considerando as implicações de morte ou morte por erro no tipo sanguíneo, devo adicionar essa regra.

Saída

A saída será duas listas de tipos sanguíneos legíveis por humanos, em qualquer formato adequado ao seu idioma. Nos casos especiais em que uma das listas de saída contém todos os 8 tipos, essa lista pode opcionalmente ser substituída por uma única lista de itens everyone.

A saída normal irá para um dos locais normais (STDOUT, retorno de função, etc.).

Outras regras

  • As brechas padrão são proibidas
  • Você pode usar as bibliotecas de terceiros pré-existentes necessárias, desde que elas não sejam projetadas explicitamente para esse fim.

Exemplos

  • Para entrada AB-, as duas listas de saída seriam:{AB+, AB-}, {AB-, A-, B-, O-}
  • Para entrada AB+, as duas listas de saída seriam: {AB+}, {O−, O+, A−, A+, B−, B+, AB−, AB+}ou{AB+}, {everyone}

Nota pessoal: considere doar sangue, se puder. Sem a transfusão que recebi há alguns anos, talvez eu não esteja aqui hoje, então sinto-me muito grata por aqueles que podem doar!

Trauma Digital
fonte
@ MartinBüttner Na verdade, vou aceitar os dois. Muito provavelmente, o segundo formulário produzirá um código mais curto na maioria dos idiomas, mas talvez haja algum caso especial em que o uso do primeiro formulário possa ser mais curto.
Digital Trauma
3
Relacionado tangencialmente - esta resposta brilhante worldbuilding.stackexchange.com/a/11203/2094
Digital Trauma
1
Esse fato não é tão pouco conhecido .
deixou de girar no sentido anti-
1
@leftaroundabout Obrigado - Um pouco de Fry e Laurie sempre foram os meus favoritos!
Digital Trauma
1
Um vampiro exigente, não é? Drácula está virando em seu caixão. Além disso, o título soa como o nome de uma banda de goth-rock aposentada.
precisa

Respostas:

9

Clipe , 69

*cTx\{fFx`Tf[tFtx}T`[Fx[y!VVx"O-"Vy"O-"}[TC"A+ B+ AB+ O+ A- B- AB- O-

Entrada: AB-

Saída: {{"AB+", "AB-"}, {"A-", "B-", "AB-", "O-"}}

Explicação

Um tipo de sangue xpode dar yse todos xos antígenos estiverem incluídos y. O programa define a função Fcomo se xpode dar ye Tcomo a lista de tipos.

*cTx                 .- If T contains x (the input)         -.
    \                .- Print                               -.
     {             ` .- a list of                           -.
      fFx`T          .- filter each t in T with F(x,t)      -.
           f[tFtx}T  .- filter each t in T with F(t,x)      -.

[Fx[y              } .- F is a function of x and y          -.
     !V              .- all letters of ... are included in ...   -.
       Vx"O-"        .- x, with O and - removed             -.
             Vy"O-"  .- y, with O and - removed             -. 

[TC"A+ B+ AB+ O+ A- B- AB- O-   .- T is the list of types -.
Ypnypn
fonte
6

Java 8, 373

import java.util.*;void f(String s){List<String>l=new ArrayList(Arrays.asList("A+,B+,AB+,O+,A-,B-,AB-,O-".split(","))),m=new ArrayList(l);int i=l.contains(s)?1:0/0;l.removeIf(x->g(s,x)<1);m.removeIf(x->g(x,s)<1);System.out.print(l+","+m);}int g(String s,String t){for(char c:s.replaceAll("O|-","").toCharArray())if(!t.replaceAll("O|-","").contains(""+c))return 0;return 1;}

Explicação

void f(String s) {
    List<String> l = new ArrayList(Arrays.asList("A+,B+,AB+,O+,A-,B-,AB-,O-".split(","))),
                 m = new ArrayList(l);
    int i = l.contains(s) ? 1 : 0 / 0;
    l.removeIf(x -> g(s, x) < 1);
    m.removeIf(x -> g(x, s) < 1);
    System.out.print(l + "," + m);
}

int g(String s, String t) {
    for (char c : s.replaceAll("O|-", "").toCharArray()) {
        if (!t.replaceAll("O|-", "").contains("" + c)) {
            return 0;
        }
    }
    return 1;
}

Execute-o aqui: http://repl.it/e98/1

Observe que staticfoi necessário adicionar a cada método para chamá-los do método principal.

Ypnypn
fonte
2
Eu adicionei um link para um programa de fácil execução para você. Edite o parâmetro de string dentro da chamada de função no método principal para ver as saídas das outras entradas.
mbomb007
5

Pyth, 61 59 50

L-{b"O-"M!-yGyHJmsd*c"A O B AB"d"+-"I}zJfgzTJfgYzJ

Execute-o aqui.

Explicação:

L-{b"O-"                         Create function y(b) that makes a set from b's 
                                 characters minus O and -.
M!-yGyH                          Create function g(G,H) that checks if y(G) is 
                                 a subset of y(H).
J                                Assign to J...
 msd                             The concatenation of every element in...
    *c"A O B AB"d"+-"            The Cartesian product of A O B AB and + -.
I}zJ                             If input in J then...
    fgzTJ                        Print all elements e in J if g(input, e).
    fgYzJ                        Print all elements e in J if g(e, input).
orlp
fonte
@ user23013 Obrigado pela edição. Definitivamente deveria ter sido cartesiano :) #
2112 orlp
4

CJam, 64 bytes

"AB"_a+'O+"+-"m*:s:TT{}+Tqa#=a+T4=f&_)f{\-!}\)f-:!]{T]z::*La-p}/

A m*:sparte vem da resposta de Martin, CJam . (Ainda não li as outras partes.)

Ainda haverá alguns problemas sérios, porque eles nunca terão certeza sobre a ordem das duas listas. E Block ArrayList &pode ser implementado em versões posteriores do CJam.

Explicação

"AB"_a+'O+         " Generate ['A 'B \"AB\" 'O]. ";
"+-"m*:s:T         " Generate the list of blood types and store in T. ";
T{}+
    Tqa#           " Find the input in T. ";
=                  " Find the blood type by the index.
                     If not found, return a block to cause an error. ";
a+                 " Append the verified input to T. ";
T4=                " AB+. ";
f&                 " Intersect each blood type with AB+. ";
_)f{\-!}           " Check emptiness of input - each item. ";
\)f-:!             " Check emptiness of each item - input. ";
]{                 " For both lists: ";
    T]z::*         " Replace items in T where there is a 0 with empty strings. ";
    La-            " Remove empty strings. ";
    p              " Print. ";
}/
jimmy23013
fonte
3

Javascript, 167

p=function(t){o="";if((x=(l="O- O+ B- B+ A- A+ AB- AB+".split(" ")).indexOf(t))<0)return;n=2;while(n--){y=8;while(y--)if([y,x][n]-(y&x)==0)o+=" "+l[y];o+=";"}return o}

ungolfed:

function p(btype){
    output = "";
    btypeList = "O- O+ B- B+ A- A+ AB- AB+".split(" ");

    btypeInt = btypeList.indexOf(btype);
    // thus we have the scheme
    // btypeInt = 0b(has A antigen)(has B antigen)(has rhesus antigen)

    if(btypeInt < 0) // i.e. broken blood type string
        return;

    for(receiving = 7; receiving >= 0; receiving--)
        if(giving - (receiving & btypeInt) == 0)
            // i.e. the receiving person has at least all the antigens of our donor
            output += " " + btypeList[receiving];

    output += ";";

    for(giving = 7; giving >= 0; giving--)
        if(btypeInt - (receiving & btypeInt) == 0)
            // i.e. the giving person has no antigens that our patient doesn't have
            output += " " + btypeList[receiving];

    return output;
}

função de teste:

function tester(){
    btypeList = "O- O+ B- B+ A- A+ AB- AB+".split(" ");
    for(i=0; i<8; i++){
        console.log("Patient is " + btypeList[i])
        console.log(p(btypeList[i]))
    }
    console.log("Erroneous blood type => returns void:")
    console.log(p("asdf"))
}

A codificação do tipo sanguíneo no binário tem a vantagem de que outro antígeno (por exemplo, o antígeno Kell ) é facilmente incorporado ao código, apenas adicionando outro bit.


Doe sangue em Zurique, CH: Blutspende Zürich

Niklaus Messerli
fonte
Você pode usar em "O-O+B-B+A-A+AB-AB+".match(/\w+\W/g)vez de "O- O+ B- B+ A- A+ AB- AB+".split(" ")salvar 2 caracteres.
Oriol
Ou você pode salvar exatamente o mesmo, transformando o delimitador em um número "O-1O+1B-1B+1A-1A+1AB-1AB+".split(1)e usar a =>função também deve economizar alguns.
Vermelho-X
Sim, mas o @ Oriol's pode ser reduzido ainda mais na expressão regular por 1 caractere:/\w+./g
manatwork
Sempre use por (;;) em vez de enquanto (). Pelo menos o mesmo comprimento, mas pode ser mais curto. n=2;while(n--)=>for(n=2;n--;)
edc65
Em suma, muito inteligente. Pode ser reduzido para 147 usando truques de golfe padrão:http://jsfiddle.net/j2hep8e8/2/
edc65
2

CJam, 94 bytes

Uau, isso é longo ... enquanto eu acho que provavelmente poderia usar essa abordagem abaixo de 80, acho que poderia ter me saído melhor primeiro computando a matriz e depois escolhendo a linha e coluna corretas. Enfim, aqui está:

'O'A'B"AB"]:A"+-"m*:sq_a@&!!*_)'++_&\"AB"&A{1$\-!},\;\m*::+p)'-+_&\"AB"&A1>{1$-!},'O+\;\m*::+p

Teste aqui.

Vou adicionar uma explicação quando terminar o golfe.

Martin Ender
fonte
2

Groovy, 115

x={i=(l=('O-O+B-B+A-A+AB-AB+'=~/\w+./)[0..7]).indexOf(it);f=(0..7).&findAll;i<0?[]:[l[f{!(~it&i)}],l[f{!(it&~i)}]]}

A idéia é codificar A, B e fator de rhesus como um bit cada. Podemos então inverter os bits para obter todos os antígenos do lado receptor e usá-lo para verificar se não há anticorpos correspondentes no lado doador. É mais ou menos o mesmo que a solução JavaScript existente.

Execução de amostra

groovy> println x("AB+") 
groovy> println x("AB-") 
groovy> println x("A+") 
groovy> println x("A-") 
groovy> println x("B+") 
groovy> println x("B-") 
groovy> println x("O+") 
groovy> println x("O-") 
groovy> println x("X") 

[[AB+], [O-, O+, B-, B+, A-, A+, AB-, AB+]]
[[AB-, AB+], [O-, B-, A-, AB-]]
[[A+, AB+], [O-, O+, A-, A+]]
[[A-, A+, AB-, AB+], [O-, A-]]
[[B+, AB+], [O-, O+, B-, B+]]
[[B-, B+, AB-, AB+], [O-, B-]]
[[O+, B+, A+, AB+], [O-, O+]]
[[O-, O+, B-, B+, A-, A+, AB-, AB+], [O-]]
[]
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
fonte
2

Prolog, 119 110 bytes

u(A,B):-member(A:B,[a:ab,b:ab,o:a,o:b,o:ab]);A=B,member(A,[a,ab,b,o]).
g(X,Y):-(X= -A;X=A),(Y= -B;Y=B),u(A,B).

Observações :

  1. Os tipos sanguíneos têm as seguintes propriedades: toda vez que você tem um -(por exemplo a-), você pode doar para as mesmas pessoas que têm um equivalente positivo do seu grupo (por exemplo a), bem como o equivalente negativo (por exemplo, adá para ab, a-dá para abe ab-) Com base nessa propriedade, e abusando um pouco das notações para fazer uso dos operadores de menos e mais, podemos fatorar muitos casos. Por favor me diga se você acha aceitável . Se você preferir ter a sintaxe original (postfix), aqui está uma versão sem golfe:

    blood(X):-member(R,['a+','o+','b+','ab+','a-','b-','ab-']).
    give('o-',R):-blood(R).
    give(X,X):-blood(X).
    give('a+','ab+').
    give('b+','ab+').
    give('o+','a+').
    give('o+','b+').
    give('o+','ab+').
    give('a-','a+').
    give('a-','ab+').
    give('a-','ab-').
    give('b-','b+').
    give('b-','ab+').
    give('b-','ab-').
    give('ab-','ab+').
    
  2. Como é o Prolog, o ambiente interativo permite consultar tudo conforme solicitado (veja o exemplo abaixo). É verdade que não temos listas estritamente como saída, mas isso é equivalente. Também lidamos naturalmente com casos de erro como conseqüência.

Exemplo

donors(X,L) :- findall(Y,g(Y,X),L).
receivers(X,L) :- findall(Y,g(X,Y),L).

test :-
    member(X,[a,o,b,ab,-a,-o,-b,-ab]),
    donors(X,D),
    receivers(X,R),
    writeln(X:give_to(R):receive_from(D)),
    fail.
test.

Então, executamos test:

a : give_to([ab, a]) : receive_from([o, a])
o : give_to([a, b, ab, o]) : receive_from([o])
b : give_to([ab, b]) : receive_from([o, b])
ab : give_to([ab]) : receive_from([a, b, o, ab])
-(a) : give_to([+(ab), +(a), -(ab), -(a)]) : receive_from([-(o), -(a)])
-(o) : give_to([+(a), +(b), +(ab), +(o), -(a), -(b), -(ab), -(o)]) : receive_from([-(o)])
-(b) : give_to([+(ab), +(b), -(ab), -(b)]) : receive_from([-(o), -(b)])
-(ab) : give_to([+(ab), -(ab)]) : receive_from([-(a), -(b), -(o), -(ab)])

... que, sem formatação adequada, é a mesma matriz que a dada na pergunta.

Detalhes

O predicado g/2é o relacionamento doar :g(X,Y) significa que pessoas do tipo sanguíneo X podem dar sangue a pessoas do tipo Y sanguíneo .

Encontre receptores para o grupo a :

[eclipse]: g(a,R).    

R = ab
Yes (0.00s cpu, solution 1, maybe more) ? ;

R = a
Yes (0.00s cpu, solution 2)

Encontre receptores para orange_juice (deve falhar):

[eclipse] g(orange_juice,L).

No (0.00s cpu)

Encontre doadores para O- :

[eclipse] g(X,-o).

X = -(o)
Yes (0.00s cpu)

Quem pode dar o que? :

[eclipse] g(X,Y).

.... 27 answers ....

Não entramos em um loop de recursão infinito (foi o caso em testes preliminares).

coredump
fonte
1

Python, 187 bytes

Abordagem diferente:

def D(a,b):X=lambda c:c in a and 1-(c in b);return(X('A')+X('B')+X('+'))<1
T="O- O+ A- A+ B- B+ AB- AB+".split()
X=lambda t:(0,([u for u in T if D(t,u)],[u for u in T if D(u,t)]))[t in T]

Provavelmente pode ser jogado um pouco mais.

Teste:

for t in T + ["zz"]:
    print t, X(t)

Saída:

O- (['O-', 'O+', 'A-', 'A+', 'B-', 'B+', 'AB-', 'AB+'], ['O-'])
O+ (['O+', 'A+', 'B+', 'AB+'], ['O-', 'O+'])
A- (['A-', 'A+', 'AB-', 'AB+'], ['O-', 'A-'])
A+ (['A+', 'AB+'], ['O-', 'O+', 'A-', 'A+'])
B- (['B-', 'B+', 'AB-', 'AB+'], ['O-', 'B-'])
B+ (['B+', 'AB+'], ['O-', 'O+', 'B-', 'B+'])
AB- (['AB-', 'AB+'], ['O-', 'A-', 'B-', 'AB-'])
AB+ (['AB+'], ['O-', 'O+', 'A-', 'A+', 'B-', 'B+', 'AB-', 'AB+'])
zz 0
Claudiu
fonte
1

Ruby, 237 232 223 221 210 207 bytes

Corrigimos algumas barras invertidas estranhas nas expressões regulares e o fizemos imprimir apenas as listas, em vez de armazená-las em variáveis ​​e depois imprimi-las. Às vezes você sente falta das coisas óbvias ao tentar jogar golfe!

o=->b{Regexp.new b.gsub(?O,?.).gsub(?+,'.?\\\+').gsub'-','.?(\W)'};b=gets.chop;t=["A+","B+","AB+","O+","A-","B-","AB-","O-"];exit if !t.include? b;p t.reject{|x|!x.match o.(b)};p t.reject{|x|!b.match o.(x)}

Ungolfed:

#!/usr/bin/ruby
b=gets.chomp;
types = ["A+","A-","B+","B-","AB+","AB-","O+","O-"];
exit if !types.include?(b);
regex1 = Regexp.new b.gsub("O",".").gsub('+','.?\\\+').gsub('-','.?(\\\+|\\\-)')
donate = types.reject {|x|!x.match(regex1)};
p donate;
receive = types.reject {|x| regex2 = Regexp.new x.gsub("O",".").gsub('+','.?\\\+').gsub('-','.?(\\\+|\\\-)'); !b.match(regex2)};
p receive;

Basicamente, construo uma expressão regular personalizada para o tipo de sangue inserido para verificar se você pode doar para outro tipo de sangue. Eu, então, percorro os tipos sanguíneos, aplico a mesma regex a eles e verifico se eles podem doar para o especificado.

Provavelmente isso pode ser ainda mais diminuído. Esta é a minha primeira vez tentando código de golfe, heh.

Mewy
fonte
1

Python 2, 168 bytes

Este é o mesmo método da resposta de Blackhole. Sai com um erro se o parâmetro não for encontrado na lista de tipos.

def f(t):l='A+ O+ B+ AB+ A- O- B- AB-'.split();c=[9,15,12,8,153,255,204,136];i=l.index(t);print[s for s in l if c[i]&1<<l.index(s)],[s for s in l if c[l.index(s)]&1<<i]

Menos golfe:

def f(t):
    l = 'A+ O+ B+ AB+ A- O- B- AB-'.split()
    c = [9, 15, 12, 8, 153, 255, 204, 136]
    i = l.index(t)
    x = [s for s in l if c[i] & 1 << l.index(s)]
    y = [s for s in l if c[l.index(s)] & 1 << i]
    print x, y

Execute-o aqui: http://repl.it/eaB

Eu também tentei algumas outras pequenas alterações, mas não consegui mais ...

#172 bytes
def f(t):l='A+ O+ B+ AB+ A- O- B- AB-'.split();c=[9,15,12,8,153,255,204,136];a=lambda x:l.index(x);i=a(t);print[s for s in l if c[i]&1<<a(s)],[s for s in l if c[a(s)]&1<<i]

#171 bytes
def f(t):l='A+ O+ B+ AB+ A- O- B- AB-'.split();c=[9,15,12,8,153,255,204,136];a=lambda x:l.index(x);print[s for s in l if c[a(t)]&1<<a(s)],[s for s in l if c[a(s)]&1<<a(t)]
mbomb007
fonte
1

PHP (287 bytes):

Sim, isso é bastante longo, mas funciona como esperado.

Pode ser possível reduzir muito:

!preg_match('@^(AB?|B|O)[+-]$@',$t=$_GET[T])&&die("$t invalid");$S=array_flip($D=split(0,'O+0A+0B+0AB+0O-0A-0B-0AB-'));$L=[[1230,40],[13,1504],[23,2604],[3,$r=12345670],[$r,4],[1537,54],[2637,64],[37,7564]];for($j=0;$j<2;){foreach(str_split($L[$S[$t]][$j++])as$v)echo$D[$v].' ';echo'
';}

Isso não é fácil de ler e não foi fácil de escrever.

Funciona como pretendido, produzindo os que você pode fornecer e os que pode receber em outra linha.

Isso requer um parâmetro de URL T=com o tipo

Ismael Miguel
fonte
1

CJam, 80 bytes

Isso ainda é muito longo. Provavelmente posso cortar de 4 a 5 bytes a mais.

U1023_XKC30D]2/La+"AB"a"OAB"1/+:Mr):P;a#=_P"+-":G&+!!{AfbMff=G1/Pf|]z{~m*:s}%}*`

Para qualquer entrada inválida, imprime uma matriz vazia ou gera um erro.

Experimente on-line aqui ou execute todo o conjunto de testes

Optimizer
fonte
O XKCD no começo é pretendido?
Ypnypn
@Ypnypn implorando? Eu não pretendia inicialmente, mas acabou assim. Talvez o mundo esteja tentando nos dizer algo ...
Optimizer
Desculpe, eu quis dizer começar .
Ypnypn
1

APL, 66

(↓⊃∧/(↓t∘.∊v)(≥,[.5]≤)¨t∊⊃v⌷⍨v⍳⊂⍞)/¨⊂v←,'+-'∘.,⍨('O'∘,,⊂)2↑t←'AB+'

Experimente aqui.

jimmy23013
fonte
Talvez sejam 66 caracteres, mas definitivamente não são 66 bytes. A pergunta não diz o que é usado para pontuar.
orlp
1
@orlp code-golf é pontuado em bytes por padrão (veja a tag wiki ). Mas é dito que há uma página de código APL em que um caractere é um byte. Porém, não sei exatamente qual página de código APL é usada atualmente.
jimmy23013
@orlp "bytes", mas não "UTF-8 bytes". Aqui está uma página de código que contém todos esses caracteres.
22815 Martin Ender19:
1

C, 224

#define d(x)for(i=0;i<8;i++)if((i x j)==j)printf("%s%s%s%c ",i&2?"A":"",i&4?"B":"",i&6?"":"0","-+"[i&1]);puts("");
main(i,j){char d[4],*c=&d;scanf("%s",c);j=(c[2]?c++,2:0)+(c[1]-'+'?0:1)+(*c>='A'?2:0)+(*c>'A'?2:0);d(&)d(|)}

De-golfed mostra:

/* j = 1*(has+) + 2*(hasA) + 4*(hasB) */
#define d(x) for(i=0;i<8;i++) \
                 if((i x j)==j) \
                      printf("%s%s%s%c ",i&2?"A":"",i&4?"B":"",i&6?"":"0","-+"[i&1]); \
             puts("");

main(i,j)
{
    char d[4], *c=&d;
    scanf("%s",c);

    j= (c[2]? (c++,2):0)            /* ABx */
            + (c[1]-'+'?0:1)
            + (c[0]>='A'?2:0)
            + (c[0]>'A'?2:0);

    // print possible receipients, and then donators
    d(&)
    d(|)
}
pawel.boczarski
fonte
1

PHP - 215 212 206 bytes

function($t){$c=[9,15,12,8,153,255,204,136];if(($a=array_search($t,$l=split(1,'A+1O+1B+1AB+1A-1O-1B-1AB-')))===!1)die;foreach($l as$k=>$v){if($c[$a]&1<<$k)$x[]=$v;if($c[$k]&1<<$a)$y[]=$v;}var_dump($x,$y);}

Aqui está a versão não destruída:

function ($type)
{
    $typesList = ['A+', 'O+', 'B+', 'AB+', 'A-', 'O-', 'B-', 'AB-'];
    $donationCompatibilityList = [
        0b00001001,
        0b00001111,
        0b00001100,
        0b00001000,
        0b10011001,
        0b11111111,
        0b11001100,
        0b10001000,
    ];

    $idType = array_search($type, $typesList);
    if ($idType === false) {
        die;
    }

    $canGiveToList = [];
    $canReceiveFromList = [];
    foreach ($typesList as $currentIdType => $currentType)
    {
        if ($donationCompatibilityList[$idType] & 1 << $currentIdType ) {
            $canGiveToList[] = $currentType;
        }

        if ($donationCompatibilityList[$currentIdType ] & 1 << $idType) {
            $canReceiveFromList[] = $currentType;
        }
    }

    var_dump($canGiveToList, $canReceiveFromList);
}

Obrigado ao manatwork por economizar 4 bytes.

Blackhole
fonte
A divisão por truque inteiro trabalha em PHP também: explode(1,'A+1O+1B+1AB+1A-1O-1B-1AB-'). E como não mantemos necessariamente bons hábitos de codificação, às vezes usamos recursos obsoletos, como a split()função.
manatwork
@manatwork Bem avistado! Eu editei minha resposta, obrigado.
Blackhole
0

Perl, 107 112

Finalmente, a codificação dos nomes dos tipos em números deu o código mais curto.

#!perl -p
$x=y/AB+/421/r%9;@a=grep{~$x&$_%9||push@b,$_;!($x&~($_%9))}map{("$_-",$_.1)}0,2,4,42;$_="@a
@b";y/421/AB+/

Versão mais antiga

#!perl -p
$x=y/AB+/421/r%9;@a=grep!($x&~$_),0..7;@b=grep!(~$x&$_),0..7;$_="@a
@b";s/\d/(map{("$_+","$_-")}0,A,B,AB)[$&]/eg
nutki
fonte
0

Pyth, 58

Parcialmente o mesmo que a solução da orlp , mas um pouco diferente e completamente auto-projetada.

M&n+eGeH"+-"!f!}T+H\OPGJsm,+d\++d\-c"O A B AB"dfgzYJfgZzJJ

Explicação

M                          create a function g(G,H) that returns
  n+eGeH"+-"                 G[-1] + H[-1] is not "+-"
 &                          and
            !f!}T+H\OPG      chars of G[:-1] not in H + "O" is falsy (empty)
J                          J =
 s                          merge
  m                          map
   ,+d\++d\-                  lambda d: (d + "+", d + "-")
            c"O A B AB"d      over ["O", "A", "B", "AB"]
fgzYJ                      print all J's items x where g(input, x)
fgZzJ                      print all J's items x where g(x, input)
PurkkaKoodari
fonte
0

J, 120 bytes

   f=.3 :';"1(2 8$,(s-:"*<y,'' '')#8 2 8$#:213472854600871062656691437010712264449x)#s=.<;.2''A+ B+ AB+ O+ A- B- AB- O- '''

   f 'A+'
A+ AB+      
A+ O+ A- O- 

   f 'AB-'
AB+ AB-      
A- B- AB- O- 

A função falha em entradas inválidas. O grande número decimal é a codificação da matriz de compatibilidade completa.

(Solução muito longa por vários motivos.)

Experimente online aqui.

randomra
fonte