Jump to content
BrainDen.com - Brain Teasers
  • 0


unreality
 Share

Question

Here's the challenge: write a little code snippet in java or just generic pseudocode or even just describe your algorithm (you don't even have to know programming, I can just convert your algorithm for you!) that plays ROCK PAPER SCISSORS against an enemy... that enemy is another algorithm!

THE GAME

We all know the game rock paper scissors could use a little strategy... sure there is some psychological merit to it, but most of it is luck. Well, that's about to change.... you will create a deterministic algorithm that will battle against other algorithms for the ultimate title of ROCK PAPER SCISSORS CHAMPION!!! There will be no randomness functions, no chance, no luck. It's about skill. Is your algorithm a simple numerical ninja? Or is it a complex meta-algorithm that attempts to counterguess the enemy's strategy? MAY THE BEST ALGORITHM WIN!!!!!

TECHNICAL SPECS

Your algorithm has access to three different inputs: it has an array of all the moves its used previously. This array is called a. There is another array, b, that contains the moves used by the enemy in this match. You also have a variable, i, that denotes the round number (i=0 is the first round, i=1 is the next round, then i=2, etc).

Right now I have the global var numRounds set to 50. Ie, there will be 50 rounds before we see whose won more games. Let me know if you think that number should be something else.

0 = ROCK

1 = PAPER

2 = SCISSORS

[rock beats scissors, scissors beats paper, paper beats rock]

the arrays a & b are of the datatype int and hold zeroes, ones and twos up to a or b. a and all values after that in the array is NULL, same with b. So the array is only defined from a[0] to a[i-1] or equivalent for b.

For the very first round, i=0, there will be nothing in the arrays. So if your algorithm uses previous data to make future decisions, you'll need to have some primer value for i=0

For anyone interested, here is my java code that runs all this:



// ROCK PAPER SCISSORS CONTEST FOR BRAINDEN

//  BY UNREALITY

//    ENJOY

import java.util.Scanner;

public class ropasc

{

    public static int numGames = 50;

// rock: 0

// paper: 1

// scissors: 2


    private int[] myTurns; private String myName;



    public ropasc(String name)

    {

        myName = name;

        myTurns = new int[numGames];

    }


    public int[] get()

    {

        return myTurns;

    }


    public String getName()

    {

        return myName;

    }


    public int next(int[] enemy, int i)

    {

        int x=0;

        if (myName=="Test1") x = test1(myTurns, enemy, i);

        if (myName=="Test2") x = test2(myTurns, enemy, i);

        if (myName=="Test3") x = test3(myTurns, enemy, i);

        // etc. Could use "java.lang.reflect.*" to do this more elegantly but this way is simpler

        myTurns[i] = x;

        return x;

    }


    public int test1(int[] a, int[] b, int i)

    {

        if (i==0) return 2;

        return b[i-1];

    }


    public int test2(int[] a, int[] b, int i)

    {

        return i % 3;

    }


    public int test3(int[] a, int[] b, int i)

    {

        int sum = 0;

        for (int z=0; z<i; z++)

        {

            sum += (a[z] + b[z]);

        }

        sum %= 3;

        return sum;

    }


    public static String conv(int k)

    {

            if (k==0) return "ROCK";

            if (k==1) return "PAPER";

            if (k==2) return "SCISSORS";

            return "";

    }


    public static void main(String[] args)

    {


        String na = "", nb = "";

     /*   String na = "Test1"; // these two lines

        String nb = "Test2"; // will be the only ones changed to switch who is fighting whom */

        // how about, instead get user input?

        Scanner inp = new Scanner(System.in);

        System.out.print("\n\nFirst Algorithm: ");

        na = inp.next();

        System.out.print("\nSecond Algorithm: ");

        nb = inp.next();


        System.out.print(na + " vs " + nb + "\n\n");

        ropasc rps1 = new ropasc(na);

        ropasc rps2 = new ropasc(nb);

        int res1 = 0, res2 = 0, win1 = 0, win2 = 0, result = 2;

        for (int i=0; i< numGames; i++)

        {

            res1 = rps1.next(rps2.get(), i);

            res2 = rps2.next(rps1.get(), i);

            result = (2+res1+res2) % 3;

            if (result==1) win2++;

            if (result==0) win1++;

            System.out.println(conv(res1) + " vs " + conv(res2));

        }

        String zprint ="";

        if (win1>win2) zprint = rps1.getName() + " wins " + win1 + " games to " + win2 + "!!!\n";

        if (win1<win2) zprint = rps2.getName() + " wins " + win2 + " games to " + win1 + "!!!\n";

        if (win1==win2) { zprint = "Both players won " + win1 + " games! The match was a tie\n"; } else { zprint += "There were " + (numGames - win1 - win2) + " ties\n"; }

        System.out.print(zprint);

    }

}

New entrants will be like this:

public int nameOfAlgorithmint[] a, int[] b, int i)

{

// body here

}

and will be inserted into the program after the algorithm method for test3

All algorithms must return one of these three integers: 0 (ROCK), 1 (PAPER), 2 (SCISSORS)!!!

good luck and post here with remarks, questions, etc.... let's get a signup list?

1) Unreality

2) ...

should we shoot for eight people?

REMEMBER YOU DONT NEED TO KNOW PROGRAMMING... you just need to make a killer algorithm that's a whiz at R/P/S :) I can write the actual code for it for you if you want!

Link to comment
Share on other sites

  • Answers 257
  • Created
  • Last Reply

Top Posters For This Question

Recommended Posts

  • 0

you'll have to program that yourself, (or provide a description of what you want your program to do to unreality) the only things you'll get are your moves a[ ], your opponents moves b[ ], and the number of rounds so far i.

Edited by phillip1882
Link to comment
Share on other sites

  • 0

currently there are 6 algos ready to go for T3:

phillip! plasmid! unreality! darthnoob! dawh! MrApple!

I know Izzy is planning to work on hers; I haven't heard from Medji; jazzship and Framm18 are new to the game but I'm not sure at what point in progress they have made; I know that SomeGuy is interested but I haven't heard from him in some time since he asked some questions about how to program it, so maybe he has made some progress; JarZe is planning on using his original jarze unless he thinks of something in the meantime

The ones in the above that I currently haven't had contact with in a while are jazzship, Framm18 and SomeGuy, so I'll give them a quick PM to see where they are at :D

Thanks everyone for doing this crazy thing for these tournaments ;D

Link to comment
Share on other sites

  • 0

All that talk of "algorithm defeaters" earlier gave me an idea. This might be a sort of way to judge how "novel" a new algorithm is compared to the other ones.

Behold, the T2 defeater!

BTW, it would DEFINITELY be cheating to use this trick of invoking the rpsgo() function within an actual T3 entry, so don't even think about it! This is purely to gauge how original a new algorithm is.

        if (algoNum==36) // T2 defeater

        {

          int alg, round, alg_score, max_score = -1, defeater_play = ROCK;

          int[] T2_index = new int[] { 2, 4, 14, 15, 10, 11, 19, 20, 12, 18, 30, 13, 29, 17, 21, 28, 24, 25, 5, 22, 23, 31 };


          // For each algorithm from T2 ....

          for (alg=0; alg<22; alg++) {

            // For each round that you have data for, see what

            //   the algorithm in question would have played for that round

            // Tally how many times you would guess correctly if you assume

            //   that you're up against the algorithm in question

            alg_score = 0;

            for (round=0; round<i; round++) {

              if (b[round] == rpsgo(T2_index[alg], round, b, a)) alg_score++;

            }


            // If the algorithm is the one that best predicts what your

            //   opponent actually played, then play whatever would beat

            //   that algorithm's next move

            if (alg_score > max_score) {

              defeater_play = (rpsgo(T2_index[alg], i, b, a) + 1) % 3;

              max_score = alg_score;

            }

          }

          return defeater_play;

        }

Edited by plasmid
Link to comment
Share on other sites

  • 0

Interesting!! I entered it (as algo #46) - do you want it tested in some away against T2 programs or similar-to-T2 programs or something? Obviously this is just a recreational exercise [cuz remember no electronically testing a T3 algo before the big tourney - which btw should be coming up soon, I'm just waiting to hear some more from jazzship, Izzy and maybe some others - we already have 10 algos entered into T3]

Link to comment
Share on other sites

  • 0

Interesting!! I entered it (as algo #46) - do you want it tested in some away against T2 programs or similar-to-T2 programs or something? Obviously this is just a recreational exercise [cuz remember no electronically testing a T3 algo before the big tourney - which btw should be coming up soon, I'm just waiting to hear some more from jazzship, Izzy and maybe some others - we already have 10 algos entered into T3]

I already tested it out against the old T2 algorithms to make sure it works. As you would expect, it beat every one of them, with a total of 2159 wins, 24 ties, and 17 losses.

This algo could expand on a question that came up earlier of how a program geared specifically to defeat one algorithm might do in a general matchup against other algorithms. The twist is that this algorithm is geared to beat a smattering of different algorithm types. It might be neat to see how it does against the new T3 algorithms as a side exercise, and see if it really does end up showing how "novel" a new algorithm is in any sort of intuitively meaningful way, but I don't think I'd include it as one of the participants in the big T3 tourney for scoring purposes. Especially if we're going with the idea of having one algorithm per person... cuz I really like my current plasmid! algorithm.

Edited by plasmid
Link to comment
Share on other sites

  • 0

I replied to your message unreality. In the conversation section.

I think I might sit this one out. My original algorithm was full of randomness, so I would have to think of something new.

yeah that's what I was referring to. All algos are deterministic in that their only decision input is the a[], b[] and i variables. We've established that randomness is sub-optimal anyway. I'm sure you can think of a new implimentation :) Maybe a version 2.0. There's no rush

Link to comment
Share on other sites

  • 0

I wrote the code for my program, and when I get a chance I'll send it to you, and I'll just need you to check over damageControl to see if you did that right (unless I give it a shot and try to decipher it) and then run it against your version of the code and hope it does 100 ties! (also, the format of my code is a little different just so that NetBeans wouldn't yell at me and put everything in red. E.g., I initialized i and a[] and, well, you'll see, but it will only take a second to delete that stuff)

Link to comment
Share on other sites

  • 0

I know this has been inactive for a little while but I hope you guys don't mind waiting; darth and I have both been pretty busy but we're getting kinks in his algo straightened out, then T3 will be ready to rumble with the following contestants:

34 (phillip!)

35 (plasmid!)

36 (unreality!)

39 (darthnoob!)

40 (dawh!)

41 (MrApple!)

42 (Framm!)

43 (SomeGuy!)

44 (jazzship!)

45 (jarze!)

These 10 contestants will match up for a final battle unlike any other :P I'll also release the full & final code for all to see

Actually jazzship's is incomplete cuz his had randomness and he was gong to redo it; I'll PM him about that. And I'll see if Izzy wants to join in too.

BUt anyway... soon, soon :P

Link to comment
Share on other sites

  • 0

once again I apologize, I hope nobody minds waiting so long for the T3 results. We've been trying to get Gmaster's program running without much like - if you guys want, in the meantime, I can run the results with all the other algos as partial results

Some of us other programmers might be able to give it a shot if you PM us a description. Unfortunately I'm working overnight Monday, but I know I'm not the only other programmer on this topic.

Link to comment
Share on other sites

  • 0

Some of us other programmers might be able to give it a shot if you PM us a description. Unfortunately I'm working overnight Monday, but I know I'm not the only other programmer on this topic.

Yes, since we've already submitted our code, and this is BD, we should be happy to help out. :thumbsup: I'd be willing to take a look at it if you and he don't mind. One of us programmers might be able to unstick it.

Link to comment
Share on other sites

  • 0

I guess the tournament has sorta been put on hold? or is it dead... i know i didn't have a very good algorithm in T3, but it would still be interesting to see the results some time. I'm all for the rejuvination of this thread! :thumbsup:

Link to comment
Share on other sites

  • 0

here's the code of the 8 programs


else if (algoNum==34) //phillip!

            {

              int[] best;

   int start = 0, index = 0;

   int size = i, ties = 0;

   best = new int[2];

   if(i == 0) return SCISSORS;

   if(i == 1) return PAPER;

   if(i == 2) return ROCK;

   if(i == 3) return SCISSORS;

   if(i == 4) return ROCK;

   if(i == 5) return PAPER;

   while(size >1){

      for(int k = 0; k < 2; k++){

         for( int j = size*k/2 +start; j < size*(k+1)/2 +start; j++){

            if (a[j] == b[j]) ties += 1;

            else{

               if (a[j] == ROCK && b[j] == PAPER) best[k] += 1;

               if (a[j] == PAPER && b[j] == SCISSORS) best[k] += 1;

               if (a[j] == SCISSORS && b[j] == ROCK) best[k] += 1;


               if (a[j] == ROCK && b[j] == SCISSORS) best[k] -= 1;

               if (a[j] == PAPER && b[j] == ROCK) best[k] -= 1;

               if (a[j] == SCISSORS && b[j] == PAPER) best[k] -= 1;

           }


        }

     }

     int x = 0;

     if(best[0] < best[1]){

        x = 1;

     }

     else if(best[0] == best[1]){

        x = ties%2;

     }

     if(x == 1){

        start += size/2;

     }

     size = size/2;

     best[0] = 0;

     best[1] = 0;

  }     

  return b[start];

            }




            else if (algoNum==35) //plasmid!

            {

             // For the first two rounds, just play whatever

            if (i==0) return PAPER;

            if (i==1) return SCISSORS;


            // For subsequent rounds,

            // First, look for any earlier rounds where BOTH (1) you played your

            //   move from round i-1, and (2) the opponent played his move from

            //   round i-1

            // Take a tally of what the opponent played afterward

            int tally[] = {0,0,0};

            for (int round = 0; round < i-1; round++) {

              if ( (a[round] == a[i-1]) && (b[round] == b[i-1]) ) tally[b[round+1]]++;

            }


            // And if he has a favorite move to play in that situation, beat it

            if ( (tally[SCISSORS] > tally[PAPER]) && (tally[SCISSORS] > tally[ROCK]) ) return ROCK;

            if ( (tally[PAPER] > tally[SCISSORS]) && (tally[PAPER] > tally[ROCK]) ) return SCISSORS;

            if ( (tally[ROCK] > tally[PAPER]) && (tally[ROCK] > tally[SCISSORS]) ) return PAPER;


            // In case of tie, look at all prior rounds where EITHER you played your

            //   move from round i-1 OR the opponent played his move from round

            //   i-1, and add to the tally of what the opponent plays afterward

            for (int round = 0; round < i-1; round++) {

              if ( (a[round] == a[i-1]) || (b[round] == b[i-1]) ) tally[b[round+1]]++;

            }


            // Then play whatever beats his most common follow-up. In case there's

            //   not a clear favorite, just pick something

            if ( (tally[SCISSORS] > tally[PAPER]) && (tally[SCISSORS] > tally[ROCK]) ) return ROCK;

            if (tally[PAPER] > tally[ROCK]) return SCISSORS;

            return PAPER;

            }










            else if (algoNum==36) //unreality!

            {

                if (i==0) return SCISSORS; /* people started with ROCK in T1 so most people in T2 started with PAPER, this is to defeat those that start with PAPER or at least tie those who start with SCISSORS */

                if (i==1) return (b[0]+2)%3; /* if they expect me to beat what they played first, I'll beat THAT. This move will only lose if they play the same move twice in a row */

                if (i==2) return (b[1]+2)%3; /* same reasoning */

                // now for my algorithm

                ArrayList<Integer> vooma = new ArrayList<Integer>(50);

                ArrayList<Integer> voomb = new ArrayList<Integer>(50);

                ArrayList<Integer> checka = new ArrayList<Integer>(50);

                ArrayList<Integer> checkb = new ArrayList<Integer>(50);

                for (int goback = i / 2; goback > 0; goback--)

                {

                    vooma.clear(); voomb.clear();

                    for (int kk=i-goback; kk<i; kk++) { vooma.add(a[kk]); voomb.add(b[kk]); }

                    for (int startcheck=0; startcheck< i-goback-1; startcheck++)

                    {

                        checka.clear(); checkb.clear();

                        for (int jj=startcheck; jj<startcheck+goback; jj++) { checka.add(a[jj]); checkb.add(b[jj]); }

                        if (vooma.equals(checka) && voomb.equals(checkb)) return ((b[startcheck+goback]+1)%3);

                    }

                }

                // nothing was found to match, so play my last move that won

                for (int zz=i-1; zz>0; zz--)

                {

                    if ((3 + a[zz] - b[zz]) == 1) return a[zz];

                }

                // no winning moves??? (excluding i=0)

                return ROCK;

            }

            else if (algoNum==37) // pattern_seeker_defeater

            {


                if(i == 0)

            return(PAPER);

            int predicted = -1;

            int success = 0;

            Vector<Integer> patt = new Vector<Integer>();

            for(int j = 0; j < i; j++) {

                int move = a[j];

                if(patt.contains(move)) {

                    int idx = patt.indexOf(move)+1;

                    if(idx < patt.size()) {

                        predicted = patt.get(idx);

                    }

                }

                patt.add(move);


                if(j < i-1 && predicted == a[j+1])

                success++;

            }

            if(success > i/2) {

                int move = a[i-1];

                int idx = patt.indexOf(move)+1;

                if(idx > 0 && idx < patt.size())

                    return((patt.get(idx)+2)%3);

                }

                return((a[i-1]+2)%3);


            }







            else if (algoNum==40) //dawh!

            {

                if(i == 0)

                return(ROCK);

        int predicted = -1;

        int success = 0;

        int wins = 0;

        int losses = 0;

        Vector<Integer> patt = new Vector<Integer>();

        for(int j = 0; j < i; j++) {

                int move = b[j];

                int myMove = a[j];

                if(move == ROCK && myMove == SCISSORS ||

                                move == SCISSORS && myMove == PAPER ||

                                move == PAPER && myMove == ROCK)

                        losses++;

                if(myMove == ROCK && move == SCISSORS ||

                                myMove == SCISSORS && move == PAPER ||

                                myMove == PAPER && move == ROCK)

                        wins++;


                if(patt.contains(move)) {

                        int idx = patt.indexOf(move)+1;

                        if(idx < patt.size()) {

                                predicted = patt.get(idx);

                        }

                }

                patt.add(move);


                if(j < i-1 && predicted == b[j+1])

                        success++;

        }

        int myMove = (b[i-1]+1)%3;

        if(success > i/2) {

                int move = b[i-1];

                int idx = patt.indexOf(move)+1;

                if(idx > 0 && idx < patt.size())

                        myMove = (patt.get(idx)+1)%3;

        }

        //If we are losing by more than five,

        //assume we are being anticipated and reanticipate them

        if(losses > wins + 5)

                myMove = (myMove - 1)%3;

        return(myMove);

            }






            else if (algoNum==41) //MrApple!

            {

                String convert = "Rock Paper Scissors";

                char[] car = convert.toCharArray();

                return ((car[i/8] >>> (7 - (i % 8))) % 2);

            }






            else if (algoNum==42) //Framm!

            {

                if (i/3 == 0) return i%3;

                int toti = i/3 + 1, ht = 0, maxhtreach = 3, multer = 1, rows = -1;

                while (toti > 0) {

                    ht += multer; toti -= ht; rows++;

                    if (ht == maxhtreach) { maxhtreach++; multer = -1; }

                    if (ht == 1) { multer = 1; }

                }

                return (i+rows)%3;

            }






            else if (algoNum==43) //SomeGuy!

            {

                int r=0,p=0,s=0;

                for (int einkil=0; einkil<i; einkil++) {

                    if (a[einkil]==ROCK) r++;

                    if (a[einkil]==PAPER) p++;

                    if (a[einkil]==SCISSORS) s++;

                }

                if (r<p && r<s) return ROCK;

                if (p<r && p<s) return PAPER;

                if (s<r && s<p) return SCISSORS;


                r=0; s=0; p=0;

                for (int einkil=0; einkil<i; einkil++) {

                    if (b[einkil]==ROCK) r++;

                    if (b[einkil]==PAPER) p++;

                    if (b[einkil]==SCISSORS) s++;

                }

                if (r>p && r>s) return ROCK;

                if (p>r && p>s) return PAPER;

                if (s>r && s>p) return SCISSORS;

                return ROCK;

            }







            else if (algoNum==45) //jarze!

            {

                // for now same as jarze

                if (i==0) return ROCK;

                return (b[i-1]+1)%3;

            }



This line just allows me to run those all at once:

else if (nextln.equals("y")) // T3

        {

            algos = new int[]{ 34, 35, 36, 40, 41, 42, 43, 45 };

        }

and here are the constants involved:

public static final int ROCK = 0;

public static final int PAPER = 1;

public static final int SCISSORS = 2;

public static final int ROUNDS = 100;

the ones we are really missing is jazzship (whose program is still incomplete) and darthnoob. Izzy never got around to submitting one either

Okay so I ran the results but it was halted by an error at this line:

// First, look for any earlier rounds where BOTH (1) you played your

// move from round i-1, and (2) the opponent played his move from

// round i-1

// Take a tally of what the opponent played afterward

int tally[] = {0,0,0};

for (int round = 0; round < i-1; round++) {

if ( (a[round] == a[i-1]) && (b[round] == b[i-1]) ) tally[b[round+1]]++;

}

The problem is ArrayOutOfBoundsException [-1] on the line I bolded

this is in the program "plasmid!" written by plasmid. I've spent some time thinking about it and the program itself is solid and cannot return error by itself (above this code is two lines that return stuff in the case of i==0 and i==1) and "plasmid!" plays out successfully against other programs.

My conclusion is that this part:

tally[b[round+1]++

is the problem child because the opponent has played a move that is not 0, 1 or 2 (instead -1 somehow) and so tally[-1] is returning an error. The opponent at the time was "dawh!"

Dawh, is there any way your program could return a -1 value? I have to go but I'll be back sometime today and I'll put in a debugger that will tell us at what round b[round+1] is evaluating to -1

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...