whatcanGOwrong
This commit is contained in:
+332
@@ -0,0 +1,332 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of "The Computer Language Benchmarks Game" nor the
|
||||
name of "The Computer Language Shootout Benchmarks" nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* The Computer Language Benchmarks Game
|
||||
http://shootout.alioth.debian.org/
|
||||
|
||||
contributed by Michael Barker
|
||||
based on a Java contribution by Luzius Meisser
|
||||
|
||||
convert to C by dualamd
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
enum Colour
|
||||
{
|
||||
blue = 0,
|
||||
red = 1,
|
||||
yellow = 2,
|
||||
Invalid = 3
|
||||
};
|
||||
|
||||
const char* ColourName[] = {"blue", "red", "yellow"};
|
||||
const int STACK_SIZE = 32*1024;
|
||||
|
||||
typedef unsigned int BOOL;
|
||||
const BOOL TRUE = 1;
|
||||
const BOOL FALSE = 0;
|
||||
|
||||
int CreatureID = 0;
|
||||
|
||||
|
||||
enum Colour doCompliment(enum Colour c1, enum Colour c2)
|
||||
{
|
||||
switch (c1)
|
||||
{
|
||||
case blue:
|
||||
switch (c2)
|
||||
{
|
||||
case blue:
|
||||
return blue;
|
||||
case red:
|
||||
return yellow;
|
||||
case yellow:
|
||||
return red;
|
||||
default:
|
||||
goto errlb;
|
||||
}
|
||||
case red:
|
||||
switch (c2)
|
||||
{
|
||||
case blue:
|
||||
return yellow;
|
||||
case red:
|
||||
return red;
|
||||
case yellow:
|
||||
return blue;
|
||||
default:
|
||||
goto errlb;
|
||||
}
|
||||
case yellow:
|
||||
switch (c2)
|
||||
{
|
||||
case blue:
|
||||
return red;
|
||||
case red:
|
||||
return blue;
|
||||
case yellow:
|
||||
return yellow;
|
||||
default:
|
||||
goto errlb;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errlb:
|
||||
printf("Invalid colour\n");
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* convert integer to number string: 1234 -> "one two three four" */
|
||||
char* formatNumber(int n, char* outbuf)
|
||||
{
|
||||
int ochar = 0, ichar = 0;
|
||||
int i;
|
||||
char tmp[64];
|
||||
|
||||
const char* NUMBERS[] =
|
||||
{
|
||||
"zero", "one", "two", "three", "four", "five",
|
||||
"six", "seven", "eight", "nine"
|
||||
};
|
||||
|
||||
ichar = sprintf(tmp, "%d", n);
|
||||
|
||||
for (i = 0; i < ichar; i++)
|
||||
ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] );
|
||||
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
|
||||
struct MeetingPlace
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
int meetingsLeft;
|
||||
struct Creature* firstCreature;
|
||||
};
|
||||
|
||||
struct Creature
|
||||
{
|
||||
pthread_t ht;
|
||||
pthread_attr_t stack_att;
|
||||
|
||||
struct MeetingPlace* place;
|
||||
int count;
|
||||
int sameCount;
|
||||
|
||||
enum Colour colour;
|
||||
int id;
|
||||
|
||||
BOOL two_met;
|
||||
BOOL sameid;
|
||||
};
|
||||
|
||||
|
||||
void MeetingPlace_Init(struct MeetingPlace* m, int meetings )
|
||||
{
|
||||
pthread_mutex_init( &m->mutex, 0 );
|
||||
m->meetingsLeft = meetings;
|
||||
m->firstCreature = 0;
|
||||
}
|
||||
|
||||
|
||||
BOOL Meet( struct Creature* cr)
|
||||
{
|
||||
BOOL retval = TRUE;
|
||||
|
||||
struct MeetingPlace* mp = cr->place;
|
||||
pthread_mutex_lock( &(mp->mutex) );
|
||||
|
||||
if ( mp->meetingsLeft > 0 )
|
||||
{
|
||||
if ( mp->firstCreature == 0 )
|
||||
{
|
||||
cr->two_met = FALSE;
|
||||
mp->firstCreature = cr;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct Creature* first;
|
||||
enum Colour newColour;
|
||||
|
||||
first = mp->firstCreature;
|
||||
newColour = doCompliment( cr->colour, first->colour );
|
||||
|
||||
cr->sameid = cr->id == first->id;
|
||||
cr->colour = newColour;
|
||||
cr->two_met = TRUE;
|
||||
|
||||
first->sameid = cr->sameid;
|
||||
first->colour = newColour;
|
||||
first->two_met = TRUE;
|
||||
|
||||
mp->firstCreature = 0;
|
||||
mp->meetingsLeft--;
|
||||
}
|
||||
}
|
||||
else
|
||||
retval = FALSE;
|
||||
|
||||
pthread_mutex_unlock( &(mp->mutex) );
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
void* CreatureThreadRun(void* param)
|
||||
{
|
||||
struct Creature* cr = (struct Creature*)param;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if ( Meet(cr) )
|
||||
{
|
||||
while (cr->two_met == FALSE)
|
||||
sched_yield();
|
||||
|
||||
if (cr->sameid)
|
||||
cr->sameCount++;
|
||||
cr->count++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour colour )
|
||||
{
|
||||
cr->place = place;
|
||||
cr->count = cr->sameCount = 0;
|
||||
|
||||
cr->id = ++CreatureID;
|
||||
cr->colour = colour;
|
||||
cr->two_met = FALSE;
|
||||
|
||||
pthread_attr_init( &cr->stack_att );
|
||||
pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE );
|
||||
pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) );
|
||||
}
|
||||
|
||||
/* format meeting times of each creature to string */
|
||||
char* Creature_getResult(struct Creature* cr, char* str)
|
||||
{
|
||||
char numstr[256];
|
||||
formatNumber(cr->sameCount, numstr);
|
||||
|
||||
sprintf( str, "%u%s", cr->count, numstr );
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
void runGame( int n_meeting, int ncolor, const enum Colour* colours )
|
||||
{
|
||||
int i;
|
||||
int total = 0;
|
||||
char str[256];
|
||||
|
||||
struct MeetingPlace place;
|
||||
struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct Creature) );
|
||||
|
||||
MeetingPlace_Init( &place, n_meeting );
|
||||
|
||||
/* print initial color of each creature */
|
||||
for (i = 0; i < ncolor; i++)
|
||||
{
|
||||
printf( "%s ", ColourName[ colours[i] ] );
|
||||
Creature_Init( &(creatures[i]), &place, colours[i] );
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* wait for them to meet */
|
||||
for (i = 0; i < ncolor; i++)
|
||||
pthread_join( creatures[i].ht, 0 );
|
||||
|
||||
/* print meeting times of each creature */
|
||||
for (i = 0; i < ncolor; i++)
|
||||
{
|
||||
printf( "%s\n", Creature_getResult(&(creatures[i]), str) );
|
||||
total += creatures[i].count;
|
||||
}
|
||||
|
||||
/* print total meeting times, should equal n_meeting */
|
||||
printf( "%s\n\n", formatNumber(total, str) );
|
||||
|
||||
/* cleaup & quit */
|
||||
pthread_mutex_destroy( &place.mutex );
|
||||
free( creatures );
|
||||
}
|
||||
|
||||
|
||||
void printColours( enum Colour c1, enum Colour c2 )
|
||||
{
|
||||
printf( "%s + %s -> %s\n",
|
||||
ColourName[c1],
|
||||
ColourName[c2],
|
||||
ColourName[doCompliment(c1, c2)] );
|
||||
}
|
||||
|
||||
void printColoursTable(void)
|
||||
{
|
||||
printColours(blue, blue);
|
||||
printColours(blue, red);
|
||||
printColours(blue, yellow);
|
||||
printColours(red, blue);
|
||||
printColours(red, red);
|
||||
printColours(red, yellow);
|
||||
printColours(yellow, blue);
|
||||
printColours(yellow, red);
|
||||
printColours(yellow, yellow);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int n = (argc == 2) ? atoi(argv[1]) : 600;
|
||||
|
||||
printColoursTable();
|
||||
printf("\n");
|
||||
|
||||
const enum Colour r1[] = { blue, red, yellow };
|
||||
const enum Colour r2[] = { blue, red, yellow,
|
||||
red, yellow, blue,
|
||||
red, yellow, red, blue };
|
||||
|
||||
runGame( n, sizeof(r1) / sizeof(r1[0]), r1 );
|
||||
runGame( n, sizeof(r2) / sizeof(r2[0]), r2 );
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user