I was fiddling around with the Evolution of Trust and thought of this.
Warning: I recommend you go check it out first before attempting this challenge.

Summary for people who haven’t played

A quick summary of what it says on the site: there is a machine. If you put in one coin, your opponent gets three coins (and vice versa). You can either Cooperate (put in a coin) or Cheat (don't put in a coin).


Given the name of a strategy (copycat, alwayscheat, alwayscooperate, grudger or detective) and the number of rounds, return/output a list of truthy (Cooperate) and falsey (Cheat) values that, when put against that strategy, will give you the maximum possible amount of coins. (I'm using Y for cooperate and N for cheat in my examples)

For clarification, check the Input and Output section.

Quick info for people who have played

The amount of rounds is given in the input. There are no mistakes, and the rewards for Cooperating/Cheating are the same as the site - see the image below.

See https://i.sstatic.net/qyEIQ.jpg

Yes, this is basically a Prisoner's Dilemma - Nicky Case says this in the “feetnotes” of the game.
Also, "Cheat" is basically the same as Defect.

The characters

  • Copycat copycat
  • Always Cooperate alwayscooperate
  • Always Cheat alwayscheat
  • Grudger grudger
  • Detective detective

The characters' strategies from the site

  • Copycat: Hello! I start with Cooperate, and afterwards, I just copy whatever you did in the last round. Meow
  • Always Cheat: the strong shall eat the weak (always cheats)
  • Always Cooperate: Let's be best friends! <3 (always cooperates)
  • Grudger: Listen, pardner. I'll start cooperatin', and keep cooperatin', but if y'all ever cheat me, I'LL CHEAT YOU BACK 'TIL THE END OF TARNATION. (cooperates until you cheat once, then cheats you back for the rest of the game)
  • Detective: First: I analyze you. I start: Cooperate, Cheat, Cooperate, Cooperate. If you cheat back, I'll act like Copycat. If you never cheat back, I'll act like Always Cheat, to exploit you. Elementary, my dear Watson.

Input and Output

Input is the name of the strategy and the amount of rounds in any order you specify, in a list, or a space-separated string.

Output is a list of truthy (Cooperate) and falsey (Cheat) values that, when put against the strategy, gives you the most amount of points.

Test cases

"grudger 3" => "YYN" or [<2 truthy values>, falsey]
"detective 5" => "NNNYN" or [<3 falsey values,> truthy, falsey]
"alwayscheat 7" => "NNNNNNN" or [<7 falsey values>]
"alwayscooperate 99" => <insert 99 N's here> or [<99 falsey values>]
"copycat 7" => "YYYYYYN" or [<6 truthy values>, falsey]
"detective 4" => "NNNN" (4 N's) or [<4 falsey values>]
"alwayscheat 999" => 999 N's or [<999 falsey values>]
"grudger 1" => "N" or [falsey]

Easy copy paste:

grudger 3
detective 5
alwayscheat 7
alwayscooperate 99
copycat 7
detective 4
alwayscheat 999
grudger 1


  • This is , shortest answer wins, tiebreaks sorted by time(stamp) created
  • Standard loopholes are not allowed, unless they are creative (e.g. asking for list input and using the fact that it is a list to shorten your code). No extra points are given for this


  • \$\begingroup\$ Is shorter detective allowed as input? \$\endgroup\$
    – l4m2
    Commented Sep 20, 2021 at 11:02
  • \$\begingroup\$ What do you mean? Please clarify. \$\endgroup\$
    – W D
    Commented Sep 20, 2021 at 11:18
  • \$\begingroup\$ For reference, here is our current consensus about answering your own challenge. \$\endgroup\$
    – Arnauld
    Commented Sep 20, 2021 at 11:57
  • 4
    \$\begingroup\$ This will be a nice KotH challenge. \$\endgroup\$
    – Wasif
    Commented Sep 20, 2021 at 17:05
  • \$\begingroup\$ @l4m2 I haven’t heard from you for a while, so I’ll leave detective as it is now. @Arnauld got it, thanks. @wasif Good idea, I’ll add it to the sandbox some day. \$\endgroup\$
    – W D
    Commented Sep 20, 2021 at 20:01

7 Answers 7


Jelly, 13 bytes

An OP accepted, but somewhat rule-bending, 13 byter since all the integers are now wrapped in lists - so it only works if we may assume any truthy/falsey operator will vectorise - that can be fixed for 1 byte for a different 14 to my original, e.g. add F.)


A dyadic Link that accepts the opponent classification on the left and the number of turns to play on the right and yields a list of wrapped integers (non-zeros are truthy in Jelly, while zeros are falsey).

Try it online! Or see the test-suite.


There are, for the purpose of our choices, only three classes of opponent here:

  1. If we face alwayscheat or alwayscooperate we should always cheat
  2. If we face grudger or copycat we should cooperate until our penultimate turn and then cheat on our final turn.
  3. If we face detective we should cooperate from the fourth turn (if it is not our last turn) until our penultimate turn and then cheat on our final turn.
M_5+Ṡ$×<¥ⱮḊ;0 - Link: opponent, turns
M             - maximal indices
                -> alwayscheat:[5] alwayscooperate:[5] grudger:[3] copycat:[4] detective:[8]
                       ^               ^                 ^            ^               ^
 _5           - subtract five
                -> alwayscheat:[0] alwayscooperate:[0] grudger:[-2] copycat:[-1] detective:[3]
   +Ṡ$        - add the sign of that (call this "category")
                -> alwayscheat:[0] alwayscooperate:[0] grudger:[-3] copycat:[-2] detective:[4]
         Ɱ    - map (across turn in [1..turns]) with:
        ¥     -   last two links as a dyad, f(category, turn)
       <      -     (category) less than (turn)?
      ×       -     (category) multipied by (that)
          Ḋ   - dequeue
           ;0 - concatenate a zero

14: OḢ%4C×4×<¥ⱮḊ;0

And another 14: OḢ%4ȯ7B¤Ṭo¥@’ṁ

  • 1
    \$\begingroup\$ The 13-byte submission should be fine. +1 for good creativity \$\endgroup\$
    – W D
    Commented Sep 20, 2021 at 20:04

05AB1E, 17 15 bytes


First input is the amount of rounds, second input the strategy of the opponent.
Output is a list of 1s/0s.

Try it online or verify all test cases.


There are three different output variations based on the input \$n\$:

  • detective: \$N(\min(n-1,3))Y(n-4)N(1)\$
  • grudger/copycat: \$Y(n-1)N(1)\$
  • alwayscheat/alwayscooperate: \$N(n)\$

So in my program I create these three possible lists first; convert the string input to an index-integer; and use it to output the correct list of the three.

Å0         # Push a list with the first (implicit) input amount of 0s: [0,0,...,0,0]
D          # Duplicate this list
ā          # Push a list in the range [1, length] (without popping the list)
 4›        # Check for each whether it's larger than 4 (0 if <=4; 1 if >4)
   À       # Rotate it once left: [0,0,0, 1,1,...,1,1, 0]
ā          # Push a list in the range [1, length] (without popping the list)
 ¤         # Get its last value (without popping)
  Ê        # Check for each that it's NOT equal to this integer: [1,1,...,1,1, 0]
    )      # Wrap all four lists on the stack into a list
     I     # Push the input-string
      C    # Convert it from a binary-string to an integer
       θ   # Only leave its final digit
        è  # Use that to 0-based modulair index into the list of lists
           # (after which this list is output implicitly as result)

C on strings basically gets the index of each characters in the string 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzǝʒαβγδεζηθвимнт ΓΔΘιΣΩ≠∊∍∞₁₂₃₄₅₆ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~Ƶ€Λ‚ƒ„…†‡ˆ‰Š‹ŒĆŽƶĀ‘’“”–—˜™š›œćžŸā¡¢£¤¥¦§¨©ª«¬λ®¯°±²³\nµ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ•, and then converts this list of indices to a base-2 integer.

String C θ Modulair index Resulting list
detective 21282 2 2 [0,0,0, 1,1,...,1,1, 0]
grudger 5893 3 3 [1,1,...,1,1, 0]
copycat 5607 7 3 [1,1,...,1,1, 0]
alwayscheat 87191 1 1 [0,0,...,0,0]
alwayscooperate 1397550 0 0 [0,0,...,0,0]

Python 2, 50 48 bytes

lambda a,b:(hash(a)%5%4*[0]+[a>'b']*b)[:b-1]+[0]

Try it online!

name hash(name) hash(name)%5%4 name>'b' pattern
grudger -2066041371107544871 0 True N{0}Y{b-1}N
detective -4897940859603653632 3 True N{3}Y{b-4}N
alwayscheat 5996996683077751943 3 False N{3}N{b-4}N
alwayscooperate 6213961190923822520 0 False N{0}N{b-1}N
copycat 8335118083446687010 0 True N{0}Y{b-1}N
  • 1
    \$\begingroup\$ hash(a)%755%4*[0] also works, but that's sadly just as long \$\endgroup\$
    – Arnauld
    Commented Sep 20, 2021 at 15:08
  • 1
    \$\begingroup\$ @Arnauld but hash(a)%5%4*[0] works, because alwayscheat continues with N/0 anyway \$\endgroup\$
    – ovs
    Commented Sep 21, 2021 at 10:55

Ruby, 48 44 42 bytes

Based on OP's answer


Try it online!

[p]*(~a.ord%4) could be [p]*3*a.sum[2] or [p]*(a.hex/74) instead for the same length.


Python 3, 45 bytes

lambda o,r:([len(o)<8]*3+[o>'c']*r)[:r-1]+[0]

Try it online!

The easiest way to group detective with alwayscooperate and alwayscheat was based on text length, while the easiest to group detective with copycat and grudger was alphabetically.

This might internally generate a list that is too long, but that gets trimmed down in the end.


JavaScript (ES6),  42  41 bytes

Expects (strategy)(rounds). Returns a string of 0's and 1's.


Try it online!


(                // main function taking:
  s,             //   s = strategy string
  i = 14         //   i = internal counter
) =>             //
g = b =>         // g is a recursive function taking b = number of rounds
  --b &&         //   decrement b; if b = 0, stop and return a final 0
  [              //   singleton array:
    s > g &      //     yield 1 if the strategy is not 'always[something]'
                 //     (i.e. it's greater than 'b...')
    !s[++i >> 1] //     and the character in s at floor(++i / 2) is not
                 //     defined, which is:
                 //       - always true for 'copycat' and 'grudger'
                 //       - true only after 3 turns for 'detective'
  ]              //   end of array, implicitly coerced to a string
  + g(b)         //   append the result of a recursive call

This is based on OP's original answer (now deleted).


Java 11, 76 71 70 bytes


-5 bytes thanks to @Arnauld
-1 byte thanks to @ovs

Input as a character-array and integer, output as a String of 1s/0s.

Try it online.


s->n->                          // Method with character-array and integer parameters
                                // and String return
                                //  Return the following String:
  (1-                           //   Subtract 1 by:
     s[6]                       //    The 7th unicode value of the input-array
         %2                     //    Modulo-2
           +"")                 //   Convert that 0 or 1 to a String
               .repeat(n>3?     //   If `n` is larger than 3:
                           3    //    Repeat it 3 times
                          :     //   Else:
                           n-1) //    Repeat it `n-1` times instead
  +                             //   Concat:
   (s[0]                        //    The 1st unicode value of the input-array
        /98                     //    Integer-divided by 98
           +"")                 //    Convert that 0 or 1 to a String
                .repeat(n>4?    //    If `n` is larger than 4:
                            n-4 //     Repeat it `n-4` times
                           :    //    Else:
                            0)  //     Don't repeat it at all
  +0                            //   And concat an additional trailing "0"
String s[6] s[6]%2 1-s[6]%2 s[0] s[0]/98
detective 105 (i) 1 0 100 (d) 1
grudger 114 (r) 0 1 103 (g) 1
copycat 116 (t) 0 1 99 (c) 1
alwayscheat 99 (c) 1 0 97 (a) 0
alwayscooperate 99 (c) 1 0 97 (a) 0
  • 1
    \$\begingroup\$ 71 bytes \$\endgroup\$
    – Arnauld
    Commented Sep 21, 2021 at 11:19
  • 1
    \$\begingroup\$ I think s[0]/98 works instead of s[1]%5%3. \$\endgroup\$
    – ovs
    Commented Sep 21, 2021 at 12:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.