Vampire Compatibility

28

1

A little known fact about vampires is that they must drink the blood of victim that has a compatible donor blood type. The compatibility matrix for vampires is the same as the regular red blood cell donor/recipient matrix. This can be summarized by the following American Red Cross table

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-

Challenge

Write a function or program that takes a blood type as input and outputs two lists:

  1. the unordered list of types that may receive donation of the input type
  2. the unordered list of types that may give donation to the input type

If you write a function, then please also provide a test program to call that function with a few examples, so I can easily test it. In this case, the test program would not count towards your score.

Input

Input must be a string representing exactly one of the 8 possible red blood cell types O− O+ A− A+ B− B+ AB− AB+. Input may be given via the normal methods (STDIN, command-line args, function args, etc).

If any other input is given then the program/function must return empty output or throw an error. Normally strict input-checking is not great in questions, but I felt given the life-death implications of getting blood types wrong that I should add this rule.

Output

Output will be two human-readable lists of blood types in whatever format is suitable for your language. In the special cases where one of the output list contains all 8 types, this list may optionally be replaced with a single item list containing everyone.

Normal output will go to one of the normal places (STDOUT, function return, etc).

Other rules

  • Standard loopholes are banned
  • You may use whatever pre-existing 3rd party libraries you need, so long as they are not designed explicitly for this purpose.

Examples

  • For input AB-, the two output lists would be: {AB+, AB-}, {AB-, A-, B-, O-}
  • For input AB+, the two output lists would be: {AB+}, {O−, O+, A−, A+, B−, B+, AB−, AB+} or {AB+}, {everyone}

Personal note: Please consider donating blood if you are able to. Without the transfusion I received a few years ago, I might not be here today, so I feel very grateful towards those who are able to donate!

Digital Trauma

Posted 2015-03-19T18:58:25.683

Reputation: 64 644

@MartinBüttner Actually I will accept both. Most likely the 2nd form will yield shorter code in most languages, but perhaps there will be some special case where using the first form could be shorter. – Digital Trauma – 2015-03-19T19:14:07.943

3

Tangentially related - this brilliant answer http://worldbuilding.stackexchange.com/a/11203/2094

– Digital Trauma – 2015-03-19T19:19:26.727

Half the answers so far are function-only answers. Please also consider this meta question: http://meta.codegolf.stackexchange.com/questions/4909/function-only-answers-to-function-or-program-questions-should-provide-a-test-pro

– Digital Trauma – 2015-03-19T21:30:09.337

1That fact is not so little-known. – ceased to turn counterclockwis – 2015-03-21T09:28:00.837

1@leftaroundabout Thanks - A Bit of Fry and Laurie has always been a favourite of mine! – Digital Trauma – 2015-03-23T00:09:36.197

Does anyone know if this array c=[9,15,12,8,153,255,204,136] can be encoded as a unicode string? Such that I could iterate with ord(c[i])? – mbomb007 – 2015-04-01T17:00:00.487

@mbomb007 See what the shell can give you printf %02x 9 15 12 8 153 255 204 136 | xxd -p -r. Also consider the hex representations of these numbers? Can you multiply by 17? – Digital Trauma – 2015-04-01T17:28:30.450

1A picky vampire, eh? Dracula is turning in his casket. Also, the title sounds like the name of a retired goth-rock-band. – Renae Lider – 2015-06-19T20:11:28.790

Answers

9

Clip, 69

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

Input: AB-

Output: {{"AB+", "AB-"}, {"A-", "B-", "AB-", "O-"}}

Explanation

A blood type x can give to y if all of x's antigens are included in y. The program defines the function F as whether x can give to y, and T as the list of types.

*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

Posted 2015-03-19T18:58:25.683

Reputation: 10 485

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;}

Explanation

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;
}

Run it here: http://repl.it/e98/1

Note that static had to be added to each method to call them from the main method.

Ypnypn

Posted 2015-03-19T18:58:25.683

Reputation: 10 485

2I added a link to an easily-run program for you. Edit the string parameter inside the function call in the main method to see the other inputs' outputs. – mbomb007 – 2015-03-19T21:02:09.193

5

Pyth, 61 59 50

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

Run it here.

Explanation:

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

Posted 2015-03-19T18:58:25.683

Reputation: 37 067

@user23013 Thanks for the edit. It definitely should've been Cartesian :) – orlp – 2015-03-20T14:31:58.727

4

CJam, 64 bytes

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

The m*:s part comes from Martin's CJam answer. (I didn't read the other parts yet.)

There will be still some serious problems because they'll be never sure about the order of the two lists. And Block ArrayList & might be implemented in later versions of CJam.

Explanation

"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

Posted 2015-03-19T18:58:25.683

Reputation: 34 042

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;
}

testing function:

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"))
}

Encoding the blood type in binary has the advantage that another antigen (e.g. the Kell antigen) is easily incorporated into the code by just adding another bit.


Donate blood in Zurich, CH: Blutspende Zürich

Niklaus Messerli

Posted 2015-03-19T18:58:25.683

Reputation: 61

You can use "O-O+B-B+A-A+AB-AB+".match(/\w+\W/g) instead of "O- O+ B- B+ A- A+ AB- AB+".split(" ") to save 2 chars. – Oriol – 2015-03-19T23:21:50.650

Or you can save exactly the same by making the delimiter a number "O-1O+1B-1B+1A-1A+1AB-1AB+".split(1) and using => function should save some too. – red-X – 2015-03-20T10:28:57.747

Yes, but @Oriol's can be further shortened in the regular expression by 1 character: /\w+./g – manatwork – 2015-03-20T10:31:16.730

Always use for(;;) instead of while(). At least same length, but can be shorter. n=2;while(n--) => for(n=2;n--;) – edc65 – 2015-03-20T10:59:43.253

All in all, very clever. Can be shortened to 147 using standard golf tricks: http://jsfiddle.net/j2hep8e8/2/ – edc65 – 2015-03-20T11:52:06.770

Thanks for the hints everyone! I won't update my entry as these aren't my own contributions, but learning new tricks is always nice ;) – Niklaus Messerli – 2015-03-20T13:43:04.033

2

CJam, 94 bytes

Wow, this is long... while I think I could probably golf this approach below 80, I think I might have done better by first computing the matrix and then simply picking out the correct row and column. Anyway, here it is:

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

Test it here.

I'll add an explanation when I'm done golfing.

Martin Ender

Posted 2015-03-19T18:58:25.683

Reputation: 184 808

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).

Remarks:

  1. Blood types have the following properties: everytime you have a - (e.g. a-), you can give to the same people as the one who have positive equivalent of your group (e.g. a), as well as their negative counterpart (e.g. a gives to ab, so a- gives to ab and ab-). Based on this property, and abusing the notations a little bit to make use of the minus and plus operators, we can factor a lot of cases. Please tell me if you find it acceptable. If you prefer having the original (postfix) syntax, here is a non-golfed version:

    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. This is Prolog, so the interactive environment allows to query everything as requested (see example below). Granted, we don't have lists strictly as an output, but this is equivalent. We also naturally handle error cases as a consequence.

Example

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.

Then, we execute 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)])

... which, without proper formatting, is the same matrix as the one given in the question.

Details

The predicate g/2 is the give relationship: g(X,Y) means people of blood type X may give blood to people of blood type Y.

Find receivers for group a:

[eclipse]: g(a,R).    

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

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

Find receivers for orange_juice (should fail):

[eclipse] g(orange_juice,L).

No (0.00s cpu)

Find donors for O-:

[eclipse] g(X,-o).

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

Who can give what? :

[eclipse] g(X,Y).

.... 27 answers ....

We do not go into an infinite recursion loop (it was the case in preliminary tests).

coredump

Posted 2015-03-19T18:58:25.683

Reputation: 6 292

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)}]]}

The idea is to encode A, B and rhesus factor as one bit each. We can then inverse the bits to get all the antigens on the receiving side and use it to check that there is no corresponding antibodies on the giving side. This is more or less the same as the existing JavaScript solution.

Sample execution

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̷̰̀ĥ̷̳

Posted 2015-03-19T18:58:25.683

Reputation: 5 683

1

Ruby, 237 232 223 221 210 207 bytes

Fixed some extraneous backslashes in the regular expressions and made it so it just prints out the lists as opposed to storing them to variables and then printing them. Sometimes you miss the obvious things when trying to golf!

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;

Basically, I construct a custom regular expression for the blood type entered to check if you can donate to another blood type. I then iterate through the blood types and apply that same regex to them and check if they can donate to the one specified.

This can probably be golfed down even more. This is my first time attempting code golf, heh.

Mewy

Posted 2015-03-19T18:58:25.683

Reputation: 389

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);}

Here is the ungolfed version:

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);
}

Thanks to manatwork for saving 4 bytes.

Blackhole

Posted 2015-03-19T18:58:25.683

Reputation: 2 362

The split by integer trick works in PHP too: explode(1,'A+1O+1B+1AB+1A-1O-1B-1AB-'). And as we not necessarily keep up with nice coding habits, sometimes we use deprecated features, like the split() function.

– manatwork – 2015-03-20T11:16:25.620

@manatwork Well spotted! I've edited my answer, thanks. – Blackhole – 2015-03-20T21:31:54.210

1

Python 2, 168 bytes

This is the same method as Blackhole's answer. Exits with an error if the parameter is not found in the list of types.

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]

Less golfed:

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

Run it here: http://repl.it/eaB

I also tried a couple other slight changes, but couldn't get it any shorter...

#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

Posted 2015-03-19T18:58:25.683

Reputation: 21 944

1

Python, 187 bytes

Different approach:

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]

Can probably be golfed a bit more.

Test:

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

Output:

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

Posted 2015-03-19T18:58:25.683

Reputation: 3 870

1

PHP (287 bytes):

Yeah, this is pretty long, but it works as expected.

It may be possible to shorten a lot:

!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'
';}

This is not easy to read and was't easy to write.

It works as intended, outputting the ones you can give to and the ones you can receive from on another line.

This requires a URL parameter T= with the type.

Ismael Miguel

Posted 2015-03-19T18:58:25.683

Reputation: 6 797

1

CJam, 80 bytes

This is still too long. Probably I can shave off 4 to 5 bytes more.

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

For any invalid input, either prints an empty array, or throws an error.

Try it online here or run the whole test suite

Optimizer

Posted 2015-03-19T18:58:25.683

Reputation: 25 836

Is the XKCD in the begging intended? – Ypnypn – 2015-03-20T19:33:44.077

@Ypnypn begging ? I did not intend to initially, but it turned out like that. Maybe the world is trying to tell us something... – Optimizer – 2015-03-20T20:21:45.980

Sorry, I meant beginning. – Ypnypn – 2015-03-22T19:17:30.203

1

APL, 66

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

Try it here.

jimmy23013

Posted 2015-03-19T18:58:25.683

Reputation: 34 042

Maybe that's 66 characters, but definitely not 66 bytes. The question doesn't say what's used to score though. – orlp – 2015-03-20T11:58:57.097

1

@orlp [tag:code-golf] is scored in bytes by default (see the tag wiki). But it is said there is an APL code page where one character is one byte. I don't know exactly which APL code page is used nowadays, though.

– jimmy23013 – 2015-03-20T12:06:11.477

@orlp "bytes", but not "UTF-8 bytes". Here is a code page containing all of these characters.

– Martin Ender – 2015-03-20T19:39:24.597

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 it shows:

/* 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

Posted 2015-03-19T18:58:25.683

Reputation: 1 243

0

05AB1E, 29 bytes

„ABD`'O)„+-âJÐIkVāY&èê,āY~èê,

Try it online!

Grimmy

Posted 2015-03-19T18:58:25.683

Reputation: 12 521

0

Perl, 107 112

Finally encoding the type names in numbers gave the shorter code.

#!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+/

Older version

#!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

Posted 2015-03-19T18:58:25.683

Reputation: 3 634

0

Pyth, 58

Partly the same as orlp's solution, but somewhat different and completely self-designed.

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

Explanation

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

Posted 2015-03-19T18:58:25.683

Reputation: 16 699

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- 

The function fails on invalid inputs. The big decimal number is the encoding of the full compatibility matrix.

(Very long solution for multiple reasons.)

Try it online here.

randomra

Posted 2015-03-19T18:58:25.683

Reputation: 19 909