g | x | w | all
Bytes Lang Time Link
097Uiua241009T165913Znyxbird
214Haskell241008T215612Zcolossus
053Vyxal240919T084455Zemanresu
427Matlab150108T194928Zflawr
100Dyalog APL150113T024301Zngn
257J150110T222549ZJay Bosa
204J150112T191330Zɐɔıʇǝɥʇu
nan150109T180024ZFryAmThe
276JavaScript150108T143909ZBlackhol
269Python 2150108T012428Zfeersum

Uiua, 97 bytes

⨬"none"(⊂:"nontransitive"⨬("Grime-"|""|"strongly ")+1×)⊸⌵:∩(×=3⊃⌵±/+≡(±/+♭/⊞(±-))⊏⍉⊟⤙↻1⇡3)≡♭≡⊞+..

Try it! (← commented explanation)

Takes input as a 3x6 array

Essentially, we generate the two-throws as their own (3x36) array, and get every possible win and loss for 0 against 1, 1 against 2, and 2 against 0 as -1/0/1. If you take the sign of the sum, you end up with a 3-element list with the signs for wins and losses (ie. [1 `1 1]). If the absolute value of the sum isn't three, there's no cycle, and if there is, the sign of the sum tells you which direction it's in. So, we can use ×=3⊃⌵± to turn the list into -1 for a counterclockwise cycle, 1 for a clockwise cycle, or 0 for no cycle. After that you can switch twice (once to see if the one-throws make a cycle, and once to see if and how the two-throws make a cycle.)

I think this is golfable? The :s and .s seem like they might be replaceable somehow.

Haskell, 214 bytes

a#b=sum[signum$p-q|p<-a,q<-b]>0
(a!b)c=a#b&&b#c&&c#a
n="nontransitive"
d a=[i+j|i<-a,j<-a]
h(w,x,y,z)|w&&y||x&&z="strongly "++n|w&&z||x&&y="Grime-"++n|w||x=n|1>0="none"
(a?b)c=h(a!b$c,c!b$a,d a!d b$d c,d c!d b$d a)

Try it online!

The a#b operator returns True if a beats b. Step one is double iterating over both lists, subtracting their results, running those through signum. That gives us a 1, 0, or -1 for each possible result of rolling A and B where 1 represents A winning, -1 is B winning, and 0 is a tie. If the sum of all these results is positive that means A wins more than it loses.

The (a!b)c operator returns True if A beats B, B beats C, and C beats A.

The d function doubles up a die by double iterating over it and adding the results. Basically creates a 36 sided die with every possible result of two rolls.

In the h function w will be true if the die cycle forward, x will be true if the dice cycle backward, and y and z are the same but for the doubled dice. We then check for the double cases first, then checking for a simple nontransitive relationship, and finally return "none" if all else fails.

Finally we have (a?b)c which takes our three dice and passes h the required flags.

Vyxal, 53 bytes

ƛẊṠ;"ƛǔ¨£ǒ-±ṠṠ±₌≈h*;3βȧ`Gr⋏≬-

ġƈ `↵`⟑¢›≤ive`+‛»≤pǏǔi

Try it Online!

A bit of a mess, but I'm pretty happy with it.

The main "trick" this answer uses is the following: By checking whether each dice beats the next, we get an array of signs -1/0/1, which will be [-1, -1, -1] if we have a decreasing cycle and [1, 1, 1] if we have an increasing cycle. This can then be turned into -1/1 for cycles and 0 otherwise by multiplying the first item by whether all items are the same. Since I'm performing this check for both the dice and their doubled rolls, this results in a pair of signs with the following possibilities:

The clever part is converting these into base 3 and taking the absolute value. Then, none maps to 0 or 1, Grime-nontransitive maps to 2, nontransitive maps to 3 and strongly nontransitive maps to 4. From here it's easy to index into a list.

ƛ  ;                                      # Over each dice
 ẊṠ                                       # Sum all pairs from it, giving the distribution of two rolls of each
    "                                     # Pair these with the original dice
     ƛ               ;                    # Over both the original and doubled dice,
                                          # Calculate the winner of each pair:
      ǔ¨£                                 # Over each pair of dice
         ǒ-±                              # Compare all pairs of values from each
            ṠṠ±                           # Sum and take the sign
                                          # This results in [1, 1, 1] if increasing cycle, [-1, -1, -1] if decreasing cycle
                  *                       # Multiply
                 h                        # The first item
               ₌≈                         # By whether they're all equal
                                          # Giving 1/-1 for cycles, 0 otherwise
                                          # Now we have [0, x] if none, [1,-1] / [-1,1] if Grime,
                                          # [1,1]/[-1,-1] if strong and [1,0]/[-1,0] otherwise 
                   3βȧ                    # Convert to base 3 and take the absolute value, giving
                                          # 0/1->none, 2->grime, 3->nontransitive, 4->strong
                                    i   i # Index into
                      `...`↵              # ["Grime-","","strongly "]
                            `...`+        # + "nontransitive"
                                  ‛»≤p    # With "none" prepended
                                      Ǐǔ  # twice

Matlab (427)

It is not that short and I am sure it can be golfed a lot more, I just tried to solve this challenge because I thought it was a very fun task, so thanks @MartinBüttner for creating this challenge!

a=input();b=input();c=input();
m = 'non';l=@(a)ones(numel(a),1)*a;n=@(a,b)sum(sum(l(a)>l(b)'));g=@(a,b)n(a,b)>n(b,a);s=@(a,b,c)sum([g(a,b),g(b,c),g(c,a)]);
x=s(a,b,c);y=s(a,c,b);if x~=3 && y~=3;m=[m,'e'];else m=[m,'transitive'];o=ones(6,1);a=o*a;a=a+a';a=a(:)';b=o*b;b=b+b';b=b(:)';c=o*c;c=c+c';c=c(:)';u=s(a,b,c);
v=s(a,c,b);if u==3|| v==3;if x==3&&u==3 || y==3&&v==3 m=['strongly ',m];else m=['Grime-',m];end;end;end;disp(m);

Here the full length code with some comments if you want to try to understand what's going on. I included some test cases hare and excluced the input commands:

%nontransitive
% a = [1 2 2 4 6 6];
% b = [1 2 3 5 5 5];
% c = [2 3 4 4 4 4];

%none
% a = [1 2 3 4 5 6];
% b = [6 5 4 3 2 1];
% c = [1 3 5 2 4 6];

%grime nontransitive
% a = [3 3 3 3 3 6];
% b = [2 2 2 5 5 5];
% c = [1 4 4 4 4 4];

%strongly nontransitive
% a = [2 2 2 5 5 5];
% b = [2 3 3 3 5 5];
% c = [1 1 4 5 5 5];

m = 'non';

l=@(a)ones(numel(a),1)*a;
n=@(a,b)sum(sum(l(a)>l(b)'));
%input as row vector, tests whether the left one beats the right one:
g=@(a,b)n(a,b)>n(b,a);
s=@(a,b,c)sum([g(a,b),g(b,c),g(c,a)]);
%if one of those x,y has the value 3, we'll have intransitivity
x=s(a,b,c); 
y=s(a,c,b);
if x~=3 && y~=3 %nontransitive
    m=[m,'e'];
else %transitive
    m=[m,'transitive'];
    o=ones(6,1);
    a=o*a;a=a+a';a=a(:)'; %all possible sums of two elements of a
    b=o*b;b=b+b';b=b(:)';
    c=o*c;c=c+c';c=c(:)';
    u=s(a,b,c);
    v=s(a,c,b);

    %again: is u or v equal to 3 then we have transitivity
    if u==3 || v==3 %grime OR strongly
        % if e.g. x==3 and u==3 then the 'intransitivity' is in the same
        % 'order', that means stronlgy transitive
        if x==3 && u==3 || y==3 && v==3%strongly
            m=['strongly ',m];
        else %grime
            m=['Grime-',m];
        end   
    end
end

disp(m);

Dyalog APL, 107 100 bytes

{({+/×+/¨,¨×⍵∘.-¨1⌽⍵}{3≠|a←⍺⍺⍵:1⋄a=b←⍺⍺∘.+⍨¨⍵:2⋄3+a=-b}⍵)⊃(⊂'none'),'strongly '⍬'Grime-',¨⊂'nontransitive'}

{T←{+/×+/¨∊¨×⍵∘.-¨1⌽⍵}⋄3≠|S←T⍵:'none'⋄N←'nontransitive'⋄S=D←T∘.+⍨¨⍵:'strongly ',N⋄S=-D:'Grime-',N⋄N}

(Thanks @Tobia for this simpler, shorter, better solution)

Basics:

T is a function that returns 3 if A beats B, B beats C, and C beats A; -3 if the exact opposite is the case; and something inbetween otherwise. In detail:

Then handle the cases in turn:

J - 311 257 bytes

Update (13 Jan 2015):

g=:4 :'(+/,x>/y)>+/,y>/x'
h=:4 :'(,+/~x)g,+/~y'
f=: 3 :0
'a b c'=:y
if. (b g a)*(c g b)*a g c do.
a=.2{y
c=.0{y
end.
'none'([`]@.((a g b)*(b g c)*c g a))((''([`]@.((b h a)*(c h b)*a h c))'Grime-')([`]@.((a h b)*(b h c)*c h a))'strongly '),'nontransitive'
)

Explanation: Using Gerunds, simplify the if.s to @.s.

Older version:

First try at both coding in J as well as golfing.

g=:4 :'(+/,x>/y)>+/,y>/x'
h=:4 :'(,+/~x)g,+/~y'
f=: 3 :0
'a b c'=:y
if. (b g a)*(c g b)*a g c do.
a=.2{y
c=.0{y
end.
if. (a g b)*(b g c)*c g a do.
if. (a h b)*(b h c)*c h a do.
'strongly nontransitive'
elseif. (b h a)*(c h b)*a h c do.
'Grime-nontransitive'
elseif. do.
'nontransitive'
end.
else.
'none'
end.
)

Run it using a syntax similar to following (extra spaces for clarity):

f 3 6 $          1 1 9 17 17 21, 1 5 5 13 21 21, 5 5 13 13 13 17

Explanation:

g is defined as a diad taking two arrays that tells if first dice beats second dice
h is defined as a diad taking two arrays that tells if throwing twice and summing, does first dice beat second
f is a monad that takes a table and returns a string with the right answer

Edit: Fix a mistake in Grime-nontransitive condition (replacing , with *)

J (204)

Way too long, could probably be golfed a lot by having a more efficient system for picking the right string.

f=:3 :'(<,>)/"1+/"2>"1,"2(<,>)/L:0{(,.(1&|.))y'
n=:'nontransitive'
d=:3 :0
if.+/*/a=.f y do.+/*/b=.f<"1>,"2+/L:0{,.~y if.a-:b do.'strongly ',n elseif.a-:-.b do.'Grime-',n elseif.do.n end.else.'none'end.
)

Pyth 129 133

Lmsd^b2Msmsm>bkGHDPNK-ghNeNgeNhNR?^tZ<KZKZAGHmsdCm,PkP,yhkyekm,@Qb@QhbUQ?"none"|!G%G3s[*!+GH"Grime-"*qGH"strongly ""nontransitive

Try it here, or at least you could, but the online eval doesn't seem to like lists of lists :( If you want to try it there, manually store a list of 3 dice into a variable not used by the program and then replace all instances of Q with that variable. A sample initialization:

J[[3 3 3 3 3 6)[2 2 2 5 5 5)[1 4 4 4 4 4))

This passes all of Martin's test cases, I haven't the heart go through all of Peter's cases :P

Explanation (this is gonna be a doozy)

Lmsd^b2

Pretty simple, makes a function y that returns the sum of each Cartesian pair of values in an iterable. Equivalent to: def y(b):return map(lambda d:sum(d),product(b,repeats=2)). This is used to create many-sided dies that simulate throwing the regular dies twice.

Msmsm>bkGH

Defines a function g of 2 arguments that returns how many times a die beats another. Equivalent to def g(G,H):return sum(map(lambda k:sum(map(lambda b:b>k,G)),H).

DPNK-ghNeNgeNhNR?^tZ<KZKZ

Defines a funtion P that takes a list of two dice as its argument. This returns -1 if the first die 'loses', 0 for a tie and 1 if the first die 'wins'. Equivalent to:

def P(N):
 K=g(N[0],N[-1]) - g(N[-1],N[0])
 return -1**(K<0) if K else 0

The AGH assigns acts like a python 2-tuple assignment. Essentially G,H=(result)

msdCm,PkP,yhkyekm,@Qb@QhbUQ

Going to explain backwards through the maps. m,@Qb@QhbUQ iterates over b=0..2 and generates 2-tuples of dice with index b and index b+1. This gives us dice (A,B),(B,C),(C,A) (pyth automatically mods indexes by the length of the list).

Next, m,PkP,yhkyek iterates over the result of the previous map, with each dice pair being stored in k over each run. Returns tuple(P(k),P(tuple(y(k[0]),y(k[-1])))) for each value. That boils down to `((A beats B?, 2*A beats 2*B), (B beats C?, 2*B beats..)).

Finally, msdC sums the values of the previous map after it has been zipped. The zip causes all of the single dice 'beats' values in the first tuple, and the double dice values in the second.

?"none"|!G%G3s[*!+GH"Grime-"*qGH"strongly ""nontransitive

A gross thing that prints out the results. If G is 0 or not divisible by 3, this catches bot +/- 3, (|!G%G3), prints none, otherwise prints the sum of the follwing list: [not(G+H)*"Grime",(G==H)*"strongly ","nontransitive"]. I think the booleans are fairly self-explanatory with regard to the definitions in the question. Do note that G cannot be zero here, as that is caught by the previous check.

JavaScript - 276 bytes

function(l){r=function(i){return l[i][Math.random()*6|0]};p=q=0;for(i=0;j=(i+1)%3,i<3;++i)for(k=0;k<1e5;++k){p+=(r(i)>r(j))-(r(i)<r(j));q+=(r(i)+r(i)>r(j)+r(j))-(r(i)+r(i)<r(j)+r(j))}alert((a=Math.abs)(p)>5e3?((a(q)>5e3?p*q>0?'strongly ':'Grime-':'')+'nontransitive'):'none')}

I'm not really good in probability, so to be sure of my results, I prefer to just throw the dice hundreds of thousands times.

The expression evaluates to a function, that should be called with only one argument: an array of three arrays of integers. Check the Fiddle to be able to run the code by yourself.

Here is the ungolfed version:

function (diceList) {
    var getRandomValue = function (idDie) {
        return diceList[idDie][Math.floor(Math.random() * 6)];
    };

    var probabilitySimpleThrow = 0;
    var probabilityDoubleThrow = 0;

    for (var idDieA = 0; idDieA < 3; ++idDieA)
    {
        var idDieB = (idDieA + 1) % 3;
        for (var idThrow = 0; idThrow < 1e5; ++idThrow)
        {
            probabilitySimpleThrow += getRandomValue(idDieA) > getRandomValue(idDieB);
            probabilitySimpleThrow -= getRandomValue(idDieA) < getRandomValue(idDieB);

            probabilityDoubleThrow += getRandomValue(idDieA) + getRandomValue(idDieA) > getRandomValue(idDieB) + getRandomValue(idDieB);
            probabilityDoubleThrow -= getRandomValue(idDieA) + getRandomValue(idDieA) < getRandomValue(idDieB) + getRandomValue(idDieB);
        }
    }

    if (Math.abs(probabilitySimpleThrow) > 5e3) {
        if (Math.abs(probabilityDoubleThrow) > 5e3) {
            if (probabilitySimpleThrow * probabilityDoubleThrow > 0) {
                var result = 'strongly ';
            }
            else {
                var result = 'Grime-';
            }
        }
        else {
            var result = '';
        }

        result += 'nontransitive';
    }
    else {
        var result = 'none';
    }

    alert(result);
}

Python 2, 269

Here's a nice little expression that evaluates to a function. It accepts three lists of integers. Passes all test cases.

lambda A,B,C,w=lambda A,B:cmp(sum(cmp(a,b)for a in A for b in B),0),x=lambda A,B:cmp(sum(cmp(a+c,b+d)for a in A for b in B for c in A for d in B),0): (w(A,B)==w(B,C)==w(C,A)!=0)*((x(A,B)==x(B,C)==x(C,A))*["","strongly ","Grime-"][x(A,B)*w(A,B)]+"nontransitive")or"none"