1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
{ The Computer Language Shootout
http://shootout.alioth.debian.org
contributed by Marc Weustink
}
program chameneos;
{$mode objfpc}{$h-}
uses
PThreads;
type
TColor = (Blue, Red, Yellow, Faded);
var
waitfirst,
waitsecond : TSemaphore;
first,second : TColor;
MeetingsLeft : Integer;
ThreadInfo : array[0..3] of record
Id: TThreadId;
StartColor: TColor;
Count: Integer;
end;
function Complement(c1,c2:TColor):TColor;
begin
if c2=Faded then
begin
result:=Faded;
exit;
end;
if c1=c2 then
begin
result:=c1;
exit;
end;
case c1 of
Blue :
if c2=Red then
result:=Yellow
else
result:=Red;
Red :
if c2=Blue then
result:=Yellow
else
result:=Blue;
Yellow :
if c2=Blue then
result:=Red
else
result:=Blue;
else
result:=c1;
end;
end;
function OtherCreaturesColor(me:TColor):TColor;
const
firstcall : boolean = true;
begin
result:=Faded;
sem_wait(waitfirst);
if firstCall then
begin
if MeetingsLeft>0 then
begin
first:=me;
firstcall:=false;
sem_post(waitfirst);
sem_wait(waitsecond);
result:=second;
dec(MeetingsLeft);
end;
sem_post(waitfirst);
end
else
begin
firstcall:=true;
second:=me;
result:=first;
sem_post(waitsecond);
end;
end;
function ThreadFunc(AIndex: PtrInt): Pointer; cdecl;
var
Meetings : Integer;
me,other : TColor;
begin
me := ThreadInfo[AIndex].StartColor;
Meetings := 0;
while (me<>Faded) do
begin
other:=OtherCreaturesColor(me);
if other=Faded then
break;
inc(Meetings);
me:=Complement(me,other);
end;
ThreadInfo[AIndex].Count := Meetings;
result:=nil;
end;
const
COLOR: array[0..3] of TColor = (Blue, Red, Yellow, Blue);
var
n: Integer;
Attr: TThreadAttr;
p: Pointer;
begin
Val(paramstr(1), MeetingsLeft, n);
if n <> 0 then exit;
sem_init(waitfirst,0,1);
sem_init(waitsecond,0,0);
pthread_attr_init(Attr);
pthread_attr_setdetachstate(Attr, 0);
pthread_attr_setstacksize(Attr, 1024 * 16);
for n := 0 to 3 do begin
ThreadInfo[n].Count := 0;
ThreadInfo[n].StartColor := COLOR[n];
pthread_create(ThreadInfo[n].Id, Attr, TStartRoutine(@ThreadFunc), Pointer(n));
end;
for n := 0 to 3 do
pthread_join(ThreadInfo[n].Id, p);
WriteLN(ThreadInfo[0].Count + ThreadInfo[1].Count + ThreadInfo[2].Count + ThreadInfo[3].Count);
end.
|