Calculating Pi (from International Obfuscated C Code Contest)

Can someone explain to me how the following program calculates Pi from its own area? It's a winner entry of the International Obfuscated C Contest.
link: http://www.cise.ufl.edu/~manuel/obfuscate/pi.c

#define _ F-->00 || F-OO--;
long F=00,OO=00;
main(){F_OO();printf("%1.3f\n", 4.*-F/OO/OO);}F_OO()
{
_-_-_-_
_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_
_-_-_-_
}

(The preceding white spaces in each line are deleted by the forum posting system, otherwise the program body looks like a perfect circle. Please do check the provided web link to look at the program.)

I find it amazing but don't understand. I'm pretty sure that F counts the number of "_" characters, and OO counts the number of lines, i.e. the size of the square. Therefore 4*F/OO/OO is an approximation for Pi. But I have no idea how F and OO are actually counted in the program.

(The "void" keyword is omitted from "void main" and "void F_OO", as permitted in traditional C)

Thanks in advance to anyone who takes the time and effort to analyse this puzzle for me.
Last edited on
It seems to take advantage of short-circuit evaluation.

Preprocessed and reformatted:
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
 long F = 00, OO = 00;

main (){
	F_OO ();
	printf ("%1.3f\n", 4. * -F / OO / OO);
}

F_OO () {
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	
	F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;
	-F-- > 00 || F - OO--;

} 
Thanks very much, but I have no problem understanding why the program looks like this after preprocessing. My problem is I that can't even understand the preprocessed code.
In particular, I'm not sure about operator precedences regarding "--", ">" and "||". I would be very grateful if someone could post a detailed anatomy of the program.
-F-- > 00 || F - OO--; is just an obfuscated way of saying
1
2
3
F--;
if (F<0)
	OO--;

The F- after the || does nothing. It's there only to complete the "foo".
Thanks very much. Your reply was very helpful and pointed me to the right direction. I played with the code in a compiler and finally I was able to understand it. However, you made two mistakes in your explanation:
1. I found "F--" is evaluated after the "if" statement.
2. With the logical OR operator ||, the right hand side is only evaluated if the left hand side evaluated to false, in contrary to what you have said.

Therefore -F-- > 00 || F - OO--; is equivalent to
1
2
3
if (!(F<0))      // this statement will always evaluate to false
              OO--;
F--;


On the other hand, F-- > 00 || F - OO--; is equivalent to
1
2
3
if (!(F>0))      // this statement will always evaluate to  true
              OO--;
F--;


So the "_" character at the beginning of each line decreases both F and OO by 1, whereas every "-_" pair decreases F by 1 but leaves OO unchanged.

In this way, after the function F_OO finishes, -F is the number of "_" characters, i.e. the area of the circle. -OO is the number of lines, i.e. the size of the square. Therefore -4*F/OO/OO gives Pi.
Last edited on
Topic archived. No new replies allowed.