ruby-fizzbuzz 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +3 -0
- data/AUTHORS +1 -0
- data/CHANGES +19 -0
- data/CHANGES.rdoc +19 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +202 -0
- data/README +5 -0
- data/README.rdoc +7 -0
- data/Rakefile +78 -0
- data/TODO +22 -0
- data/VERSION +1 -0
- data/bin/fizzbuzz +106 -0
- data/ext/fizzbuzz/common.h +71 -0
- data/ext/fizzbuzz/extconf.rb +40 -0
- data/ext/fizzbuzz/fizzbuzz.c +473 -0
- data/ext/fizzbuzz/fizzbuzz.h +233 -0
- data/lib/fizzbuzz.rb +94 -0
- data/lib/fizzbuzz/bignum.rb +90 -0
- data/lib/fizzbuzz/integer.rb +90 -0
- data/lib/fizzbuzz/version.rb +35 -0
- metadata +133 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
/* :enddoc: */
|
2
|
+
|
3
|
+
/*
|
4
|
+
* common.h
|
5
|
+
*
|
6
|
+
* Copyright 2012-2013 Krzysztof Wilczynski
|
7
|
+
*
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
* you may not use this file except in compliance with the License.
|
10
|
+
* You may obtain a copy of the License at
|
11
|
+
*
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
*
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
* See the License for the specific language governing permissions and
|
18
|
+
* limitations under the License.
|
19
|
+
*/
|
20
|
+
|
21
|
+
#if !defined(_COMMON_H)
|
22
|
+
#define _COMMON_H 1
|
23
|
+
|
24
|
+
#include <stdint.h>
|
25
|
+
#include <ruby.h>
|
26
|
+
|
27
|
+
#if defined(__cplusplus)
|
28
|
+
extern "C" {
|
29
|
+
#endif
|
30
|
+
|
31
|
+
#if !(defined(INT8_MIN) || defined(INT8_MAX))
|
32
|
+
typedef signed char int8_t;
|
33
|
+
#endif
|
34
|
+
|
35
|
+
#if !(defined(UINT8_MIN) || defined(UINT8_MAX))
|
36
|
+
typedef unsigned char uint8_t;
|
37
|
+
#endif
|
38
|
+
|
39
|
+
#if defined(UNUSED)
|
40
|
+
# undef(UNUSED)
|
41
|
+
#endif
|
42
|
+
|
43
|
+
#define UNUSED(x) (void)(x)
|
44
|
+
|
45
|
+
#if !defined(CSTR2RVAL)
|
46
|
+
# define CSTR2RVAL(x) ((x) == NULL ? Qnil : rb_str_new2(x))
|
47
|
+
#endif
|
48
|
+
|
49
|
+
#if !defined(RVAL2CBOOL)
|
50
|
+
# define RVAL2CBOOL(x) (RTEST(x))
|
51
|
+
#endif
|
52
|
+
|
53
|
+
#if !defined(CBOOL2RVAL)
|
54
|
+
# define CBOOL2RVAL(x) ((x) ? Qtrue : Qfalse)
|
55
|
+
#endif
|
56
|
+
|
57
|
+
#if !defined(HAVE_LONG_LONG)
|
58
|
+
# define TYPE2NUM LONG2NUM
|
59
|
+
# define NUM2TYPE NUM2LONG
|
60
|
+
#else
|
61
|
+
# define TYPE2NUM LL2NUM
|
62
|
+
# define NUM2TYPE NUM2LL
|
63
|
+
#endif
|
64
|
+
|
65
|
+
#if defined(__cplusplus)
|
66
|
+
}
|
67
|
+
#endif
|
68
|
+
|
69
|
+
#endif /* _COMMON_H */
|
70
|
+
|
71
|
+
/* vim: set ts=8 sw=4 sts=2 et : */
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
# :enddoc:
|
4
|
+
|
5
|
+
#
|
6
|
+
# extconf.rb
|
7
|
+
#
|
8
|
+
# Copyright 2012-2013 Krzysztof Wilczynski
|
9
|
+
#
|
10
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
11
|
+
# you may not use this file except in compliance with the License.
|
12
|
+
# You may obtain a copy of the License at
|
13
|
+
#
|
14
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
15
|
+
#
|
16
|
+
# Unless required by applicable law or agreed to in writing, software
|
17
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
18
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
19
|
+
# See the License for the specific language governing permissions and
|
20
|
+
# limitations under the License.
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'mkmf'
|
24
|
+
|
25
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
26
|
+
|
27
|
+
$LDFLAGS << " %s" % ENV['LDFLAGS'] if ENV['LDFLAGS']
|
28
|
+
|
29
|
+
$CFLAGS << " %s" % ENV['CFLAGS'] if ENV['CFLAGS']
|
30
|
+
$CFLAGS << ' -std=c99 -g -Wall -Wextra -pedantic'
|
31
|
+
|
32
|
+
have_header('ruby.h') or missing('ruby.h')
|
33
|
+
|
34
|
+
dir_config('fizzbuzz')
|
35
|
+
|
36
|
+
create_header
|
37
|
+
create_makefile('fizzbuzz/fizzbuzz')
|
38
|
+
|
39
|
+
# vim: set ts=2 sw=2 sts=2 et :
|
40
|
+
# encoding: utf-8
|
@@ -0,0 +1,473 @@
|
|
1
|
+
/* :stopdoc: */
|
2
|
+
|
3
|
+
/*
|
4
|
+
* fizzbuzz.c
|
5
|
+
*
|
6
|
+
* Copyright 2012-2013 Krzysztof Wilczynski
|
7
|
+
*
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
* you may not use this file except in compliance with the License.
|
10
|
+
* You may obtain a copy of the License at
|
11
|
+
*
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
*
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
* See the License for the specific language governing permissions and
|
18
|
+
* limitations under the License.
|
19
|
+
*/
|
20
|
+
|
21
|
+
/* :startdoc: */
|
22
|
+
|
23
|
+
#include <fizzbuzz.h>
|
24
|
+
|
25
|
+
ID id_at_start, id_at_stop;
|
26
|
+
VALUE rb_cFizzBuzz = Qnil;
|
27
|
+
|
28
|
+
void Init_fizzbuzz(void);
|
29
|
+
|
30
|
+
static VALUE fizzbuzz_evaluate(VALUE value);
|
31
|
+
static VALUE fizzbuzz_values(VALUE object, return_type_t type,
|
32
|
+
direction_t direction);
|
33
|
+
|
34
|
+
/*
|
35
|
+
* call-seq:
|
36
|
+
* FizzBuzz.new( start, stop ) -> self
|
37
|
+
*
|
38
|
+
* Returns a new _FizzBuzz_.
|
39
|
+
*
|
40
|
+
* The given +start+ and +stop+ values must be of an integer type and
|
41
|
+
* will establish a +range+ within which calculation of any relevant
|
42
|
+
* _FizzBuzz_ results will have place.
|
43
|
+
*
|
44
|
+
* Example:
|
45
|
+
*
|
46
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xb6fd3b38 @stop=100, @start=1>
|
47
|
+
* fb = FizzBuzz.new(-100,-1) #=> #<FizzBuzz:0xb72d5700 @stop=-1, @start=-100>
|
48
|
+
* fb = FizzBuzz.new(-15, 15) #=> #<FizzBuzz:0xb6fd0460 @stop=15, @start=-15>
|
49
|
+
*
|
50
|
+
* The given value of +stop+ must always be greater than or equal to the
|
51
|
+
* given value of +start+, otherwise raises an +ArgumentError+ exception.
|
52
|
+
*
|
53
|
+
* Will raise a +TypeError+ exception if given value of either +start+
|
54
|
+
* or +stop+ is not an integer type.
|
55
|
+
*
|
56
|
+
* See also:
|
57
|
+
*
|
58
|
+
* FizzBuzz::fizzbuzz
|
59
|
+
*/
|
60
|
+
VALUE
|
61
|
+
rb_fb_initialize(int argc, VALUE *argv, VALUE object)
|
62
|
+
{
|
63
|
+
VALUE start, stop;
|
64
|
+
|
65
|
+
rb_scan_args(argc, argv, "20", &start, &stop);
|
66
|
+
|
67
|
+
CHECK_TYPE(start, errors[E_INVALID_START_TYPE]);
|
68
|
+
CHECK_TYPE(stop, errors[E_INVALID_STOP_TYPE]);
|
69
|
+
|
70
|
+
CHECK_BOUNDARY(start, stop, errors[E_BAD_VALUE_START]);
|
71
|
+
|
72
|
+
rb_ivar_set(object, id_at_start, start);
|
73
|
+
rb_ivar_set(object, id_at_stop, stop);
|
74
|
+
|
75
|
+
return object;
|
76
|
+
}
|
77
|
+
|
78
|
+
/*
|
79
|
+
* call-seq:
|
80
|
+
* fizzfuzz.start -> integer
|
81
|
+
*
|
82
|
+
* Returns the current value for +start+.
|
83
|
+
*
|
84
|
+
* Example:
|
85
|
+
*
|
86
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xf726b48c @stop=100, @start=1>
|
87
|
+
* fb.start #=> 1
|
88
|
+
*/
|
89
|
+
VALUE
|
90
|
+
rb_fb_get_start(VALUE object)
|
91
|
+
{
|
92
|
+
return rb_ivar_get(object, id_at_start);
|
93
|
+
}
|
94
|
+
|
95
|
+
/*
|
96
|
+
* call-seq:
|
97
|
+
* fizzfuzz.start= (integer) -> integer
|
98
|
+
*
|
99
|
+
* Sets the current value of +start+ if given new value is lower or equal
|
100
|
+
* to the current value of +stop+, or raises an +ArgumentError+ exception
|
101
|
+
* otherwise.
|
102
|
+
*
|
103
|
+
* Examples:
|
104
|
+
*
|
105
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xf726f03c @stop=100, @start=1>
|
106
|
+
* fb.start #=> 1
|
107
|
+
* fb.start = 15 #=> 15
|
108
|
+
* fb.start #=> 15
|
109
|
+
*
|
110
|
+
* Will raise a +TypeError+ exception if given value is not an integer type.
|
111
|
+
*/
|
112
|
+
VALUE
|
113
|
+
rb_fb_set_start(VALUE object, VALUE value)
|
114
|
+
{
|
115
|
+
VALUE stop = rb_ivar_get(object, id_at_stop);
|
116
|
+
|
117
|
+
CHECK_TYPE(value, errors[E_INVALID_START_TYPE]);
|
118
|
+
CHECK_BOUNDARY(value, stop, errors[E_BAD_VALUE_START]);
|
119
|
+
|
120
|
+
return rb_ivar_set(object, id_at_start, value);
|
121
|
+
}
|
122
|
+
|
123
|
+
/*
|
124
|
+
* call-seq:
|
125
|
+
* fizzfuzz.stop -> integer
|
126
|
+
*
|
127
|
+
* Returns the current value for +stop+.
|
128
|
+
*
|
129
|
+
* Example:
|
130
|
+
*
|
131
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xf7272bec @stop=100, @start=1>
|
132
|
+
* fb.stop #=> 100
|
133
|
+
*/
|
134
|
+
VALUE
|
135
|
+
rb_fb_get_stop(VALUE object)
|
136
|
+
{
|
137
|
+
return rb_ivar_get(object, id_at_stop);
|
138
|
+
}
|
139
|
+
|
140
|
+
/*
|
141
|
+
* call-seq:
|
142
|
+
* fizzfuzz.start= (integer) -> integer
|
143
|
+
*
|
144
|
+
* Sets the current value of +stop+ if given new value is greater or equal
|
145
|
+
* to the current value of +start+, or raises an +ArgumentError+ exception
|
146
|
+
* otherwise.
|
147
|
+
*
|
148
|
+
* Example:
|
149
|
+
*
|
150
|
+
* fb = FizzBuzz.new(1, 100) #=> #<FizzBuzz:0xf727679c @stop=100, @start=1>
|
151
|
+
* fb.stop #=> 100
|
152
|
+
* fb.stop = 15 #=> 15
|
153
|
+
* fb.stop #=> 15
|
154
|
+
*
|
155
|
+
* Will raise a +TypeError+ exception if given value is not an integer type.
|
156
|
+
*/
|
157
|
+
VALUE
|
158
|
+
rb_fb_set_stop(VALUE object, VALUE value)
|
159
|
+
{
|
160
|
+
VALUE start = rb_ivar_get(object, id_at_start);
|
161
|
+
|
162
|
+
CHECK_TYPE(value, errors[E_INVALID_STOP_TYPE]);
|
163
|
+
CHECK_BOUNDARY(start, value, errors[E_BAD_VALUE_STOP]);
|
164
|
+
|
165
|
+
return rb_ivar_set(object, id_at_stop, value);
|
166
|
+
}
|
167
|
+
|
168
|
+
/*
|
169
|
+
* call-seq:
|
170
|
+
* fizzbuzz.to_a -> array
|
171
|
+
*
|
172
|
+
* Returns an array containing results upon calculating an appropriate
|
173
|
+
* values for a given range from +start+ to +stop+.
|
174
|
+
*
|
175
|
+
* Example:
|
176
|
+
*
|
177
|
+
* fb = FizzBuzz.new(1, 15) #=> #<FizzBuzz:0xf727fd60 @stop=15, @start=1>
|
178
|
+
* fb.to_a #=> [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
|
179
|
+
*
|
180
|
+
* See also: FizzBuzz::fizzbuzz
|
181
|
+
*/
|
182
|
+
VALUE
|
183
|
+
rb_fb_array(VALUE object)
|
184
|
+
{
|
185
|
+
return fizzbuzz_values(object, R_TYPE_ARRAY, D_LOOP_FORWARD);
|
186
|
+
}
|
187
|
+
|
188
|
+
/*
|
189
|
+
* call-seq:
|
190
|
+
* fizzbuzz.each {|value| block } -> self
|
191
|
+
* fizzbuzz.each -> an Enumerator
|
192
|
+
*
|
193
|
+
* Calls the block once for each subsequent value for a given range
|
194
|
+
* from +start+ to +stop+, passing the value as a parameter to the block.
|
195
|
+
*
|
196
|
+
* If no block is given, an +Enumerator+ is returned instead.
|
197
|
+
*
|
198
|
+
* Example:
|
199
|
+
*
|
200
|
+
* fb = FizzBuzz.new(1, 15) #=> #<FizzBuzz:0xf722f8ec @stop=15, @start=1>
|
201
|
+
* fb.each {|value| puts "Got #{value}" }
|
202
|
+
*
|
203
|
+
* Produces:
|
204
|
+
*
|
205
|
+
* Got 1
|
206
|
+
* Got 2
|
207
|
+
* Got Fizz
|
208
|
+
* Got 4
|
209
|
+
* Got Buzz
|
210
|
+
* Got Fizz
|
211
|
+
* Got 7
|
212
|
+
* Got 8
|
213
|
+
* Got Fizz
|
214
|
+
* Got Buzz
|
215
|
+
* Got 11
|
216
|
+
* Got Fizz
|
217
|
+
* Got 13
|
218
|
+
* Got 14
|
219
|
+
* Got FizzBuzz
|
220
|
+
*
|
221
|
+
* See also: FizzBuzz#reverse_each
|
222
|
+
*/
|
223
|
+
VALUE
|
224
|
+
rb_fb_enumerator(VALUE object)
|
225
|
+
{
|
226
|
+
return fizzbuzz_values(object, R_TYPE_ENUMERATOR, D_LOOP_FORWARD);
|
227
|
+
}
|
228
|
+
|
229
|
+
/*
|
230
|
+
* call-seq:
|
231
|
+
* fizzbuzz.reverse_each {|value| block } -> self
|
232
|
+
* fizzbuzz.reverse_each -> an Enumerator
|
233
|
+
*
|
234
|
+
* Calls the block once for each subsequent value for a given range
|
235
|
+
* from +start+ to +stop+ in an <i>reverse order</i>, passing the value
|
236
|
+
* as a parameter to the block.
|
237
|
+
*
|
238
|
+
* Example:
|
239
|
+
*
|
240
|
+
* If no block is given, an +Enumerator+ is returned instead.
|
241
|
+
*
|
242
|
+
* fb = FizzBuzz.new(1, 15) #=> #<FizzBuzz:0xb7308664 @stop=15, @start=1>
|
243
|
+
* fb.reverse_each {|value| puts "Got #{value}" }
|
244
|
+
*
|
245
|
+
* Produces:
|
246
|
+
*
|
247
|
+
* Got FizzBuzz
|
248
|
+
* Got 14
|
249
|
+
* Got 13
|
250
|
+
* Got Fizz
|
251
|
+
* Got 11
|
252
|
+
* Got Buzz
|
253
|
+
* Got Fizz
|
254
|
+
* Got 8
|
255
|
+
* Got 7
|
256
|
+
* Got Fizz
|
257
|
+
* Got Buzz
|
258
|
+
* Got 4
|
259
|
+
* Got Fizz
|
260
|
+
* Got 2
|
261
|
+
* Got 1
|
262
|
+
*
|
263
|
+
* See also: FizzBuzz#each
|
264
|
+
*/
|
265
|
+
VALUE
|
266
|
+
rb_fb_reverse_enumerator(VALUE object)
|
267
|
+
{
|
268
|
+
return fizzbuzz_values(object, R_TYPE_ENUMERATOR, D_LOOP_REVERSE);
|
269
|
+
}
|
270
|
+
|
271
|
+
/*
|
272
|
+
* call-seq:
|
273
|
+
* FizzBuzz.is_fizz?( integer ) -> true or false
|
274
|
+
*
|
275
|
+
* Returns +true+ if a given integer value is divisible by *three* (given
|
276
|
+
* value is a _Fizz_), or +false+ otherwise.
|
277
|
+
*
|
278
|
+
* Example:
|
279
|
+
*
|
280
|
+
* FizzBuzz.is_fizz?(3) #=> true
|
281
|
+
* FizzBuzz.is_fizz?(5) #=> false
|
282
|
+
* FizzBuzz.is_fizz?(15) #=> false
|
283
|
+
*
|
284
|
+
* Will raise a +TypeError+ exception if given value is not an integer type.
|
285
|
+
*
|
286
|
+
* See also: FizzBuzz::[]
|
287
|
+
*/
|
288
|
+
VALUE
|
289
|
+
rb_fb_is_fizz(VALUE object, VALUE value)
|
290
|
+
{
|
291
|
+
UNUSED(object);
|
292
|
+
CHECK_TYPE(value, errors[E_INVALID_TYPE]);
|
293
|
+
|
294
|
+
return CBOOL2RVAL(IS_FIZZ(value));
|
295
|
+
}
|
296
|
+
|
297
|
+
/*
|
298
|
+
* call-seq:
|
299
|
+
* FizzBuzz.is_buzz?( integer ) -> true or false
|
300
|
+
*
|
301
|
+
* Returns +true+ if a given integer value is divisible by *five* (given
|
302
|
+
* value is a _Buzz_), or +false+ otherwise.
|
303
|
+
*
|
304
|
+
* Example:
|
305
|
+
*
|
306
|
+
* FizzBuzz.is_buzz?(3) #=> false
|
307
|
+
* FizzBuzz.is_buzz?(5) #=> true
|
308
|
+
* FizzBuzz.is_buzz?(15) #=> false
|
309
|
+
*
|
310
|
+
* Will raise a +TypeError+ exception if given value is not an integer type.
|
311
|
+
*
|
312
|
+
* See also: FizzBuzz::[]
|
313
|
+
*/
|
314
|
+
VALUE
|
315
|
+
rb_fb_is_buzz(VALUE object, VALUE value)
|
316
|
+
{
|
317
|
+
UNUSED(object);
|
318
|
+
CHECK_TYPE(value, errors[E_INVALID_TYPE]);
|
319
|
+
|
320
|
+
return CBOOL2RVAL(IS_BUZZ(value));
|
321
|
+
}
|
322
|
+
|
323
|
+
/*
|
324
|
+
* call-seq:
|
325
|
+
* FizzBuzz.is_fizzbuzz?( integer ) -> true or false
|
326
|
+
*
|
327
|
+
* Returns +true+ if a given integer value is divisible by both *three*
|
328
|
+
* and *five* (given value is a _FizzBuzz_), or +false+ otherwise.
|
329
|
+
*
|
330
|
+
* Example:
|
331
|
+
*
|
332
|
+
* FizzBuzz.is_fizzbuzz?(3) #=> false
|
333
|
+
* FizzBuzz.is_fizzbuzz?(5) #=> false
|
334
|
+
* FizzBuzz.is_fizzbuzz?(15) #=> true
|
335
|
+
*
|
336
|
+
* Will raise a +TypeError+ exception if given value is not an integer type.
|
337
|
+
*
|
338
|
+
* See also: FizzBuzz::[]
|
339
|
+
*/
|
340
|
+
VALUE
|
341
|
+
rb_fb_is_fizzbuzz(VALUE object, VALUE value)
|
342
|
+
{
|
343
|
+
UNUSED(object);
|
344
|
+
CHECK_TYPE(value, errors[E_INVALID_TYPE]);
|
345
|
+
|
346
|
+
return CBOOL2RVAL(IS_FIZZBUZZ(value));
|
347
|
+
}
|
348
|
+
|
349
|
+
/*
|
350
|
+
* call-seq:
|
351
|
+
* FizzBuzz[ integer ] -> integer or string
|
352
|
+
*
|
353
|
+
* Returns _Fizz_ if the given value is divisible by *three*, _Buzz_
|
354
|
+
* if the given value is divisible by *five* and _FizzBuzz_ if the
|
355
|
+
* given value is divisible by both *three* and *five*, or the given
|
356
|
+
* integer value otherwise.
|
357
|
+
*
|
358
|
+
* Example:
|
359
|
+
*
|
360
|
+
* FizzBuzz[1] #=> 1
|
361
|
+
* FizzBuzz[3] #=> "Fizz"
|
362
|
+
* FizzBuzz[5] #=> "Buzz"
|
363
|
+
* FizzBuzz[15] #=> "FizzBuzz"
|
364
|
+
*
|
365
|
+
* Will raise a +TypeError+ exception if given value is not an integer type.
|
366
|
+
*
|
367
|
+
* See also: FizzBuzz::is_fizz?, FizzBuzz::is_buzz? and FizzBuzz::is_fizzbuzz?
|
368
|
+
*/
|
369
|
+
VALUE
|
370
|
+
rb_fb_square(VALUE object, VALUE value)
|
371
|
+
{
|
372
|
+
UNUSED(object);
|
373
|
+
CHECK_TYPE(value, errors[E_INVALID_TYPE]);
|
374
|
+
|
375
|
+
return fizzbuzz_evaluate(value);
|
376
|
+
}
|
377
|
+
|
378
|
+
/* :enddoc: */
|
379
|
+
|
380
|
+
static VALUE
|
381
|
+
fizzbuzz_evaluate(VALUE value)
|
382
|
+
{
|
383
|
+
int8_t score;
|
384
|
+
|
385
|
+
VALUE result = Qnil;
|
386
|
+
|
387
|
+
if (ZERO_P(value)) {
|
388
|
+
return value;
|
389
|
+
}
|
390
|
+
|
391
|
+
score = SCORE_VALUE(value);
|
392
|
+
|
393
|
+
switch(score) {
|
394
|
+
case 0:
|
395
|
+
result = value;
|
396
|
+
break;
|
397
|
+
case 1:
|
398
|
+
result = CSTR2RVAL(words[score - 1]);
|
399
|
+
break;
|
400
|
+
case 2:
|
401
|
+
result = CSTR2RVAL(words[score - 1]);
|
402
|
+
break;
|
403
|
+
case 3:
|
404
|
+
result = CSTR2RVAL(words[score - 1]);
|
405
|
+
break;
|
406
|
+
}
|
407
|
+
|
408
|
+
return result;
|
409
|
+
}
|
410
|
+
|
411
|
+
static VALUE
|
412
|
+
fizzbuzz_values(VALUE object, return_type_t type, direction_t direction)
|
413
|
+
{
|
414
|
+
VALUE i = Qnil;
|
415
|
+
|
416
|
+
VALUE array = Qnil;
|
417
|
+
VALUE value = Qnil;
|
418
|
+
|
419
|
+
VALUE start = rb_ivar_get(object, id_at_start);
|
420
|
+
VALUE stop = rb_ivar_get(object, id_at_stop);
|
421
|
+
|
422
|
+
if (WANT_ARRAY(type)) {
|
423
|
+
array = rb_ary_new();
|
424
|
+
}
|
425
|
+
else {
|
426
|
+
RETURN_ENUMERATOR(object, 0, 0);
|
427
|
+
}
|
428
|
+
|
429
|
+
if (LOOP_FORWARD(direction)) {
|
430
|
+
for (i = start; LESS_EQUAL(i, stop); i = INCREASE(i)) {
|
431
|
+
value = fizzbuzz_evaluate(i);
|
432
|
+
WANT_ARRAY(type) ? rb_ary_push(array, value) : rb_yield(value);
|
433
|
+
}
|
434
|
+
}
|
435
|
+
else {
|
436
|
+
for (i = stop; GREATER_EQUAL(i, start); i = DECREASE(i)) {
|
437
|
+
value = fizzbuzz_evaluate(i);
|
438
|
+
WANT_ARRAY(type) ? rb_ary_push(array, value) : rb_yield(value);
|
439
|
+
}
|
440
|
+
}
|
441
|
+
|
442
|
+
return WANT_ARRAY(type) ? array : object;
|
443
|
+
}
|
444
|
+
|
445
|
+
void
|
446
|
+
Init_fizzbuzz(void)
|
447
|
+
{
|
448
|
+
id_at_start = rb_intern("@start");
|
449
|
+
id_at_stop = rb_intern("@stop");
|
450
|
+
|
451
|
+
rb_cFizzBuzz = rb_define_class("FizzBuzz", rb_cObject);
|
452
|
+
|
453
|
+
rb_include_module(rb_cFizzBuzz, rb_mEnumerable);
|
454
|
+
|
455
|
+
rb_define_method(rb_cFizzBuzz, "initialize", RUBY_METHOD_FUNC(rb_fb_initialize), -1);
|
456
|
+
|
457
|
+
rb_define_method(rb_cFizzBuzz, "start", RUBY_METHOD_FUNC(rb_fb_get_start), 0);
|
458
|
+
rb_define_method(rb_cFizzBuzz, "start=", RUBY_METHOD_FUNC(rb_fb_set_start), 1);
|
459
|
+
rb_define_method(rb_cFizzBuzz, "stop", RUBY_METHOD_FUNC(rb_fb_get_stop), 0);
|
460
|
+
rb_define_method(rb_cFizzBuzz, "stop=", RUBY_METHOD_FUNC(rb_fb_set_stop), 1);
|
461
|
+
|
462
|
+
rb_define_method(rb_cFizzBuzz, "to_a", RUBY_METHOD_FUNC(rb_fb_array), 0);
|
463
|
+
rb_define_method(rb_cFizzBuzz, "each", RUBY_METHOD_FUNC(rb_fb_enumerator), 0);
|
464
|
+
rb_define_method(rb_cFizzBuzz, "reverse_each", RUBY_METHOD_FUNC(rb_fb_reverse_enumerator), 0);
|
465
|
+
|
466
|
+
rb_define_singleton_method(rb_cFizzBuzz, "is_fizz?", RUBY_METHOD_FUNC(rb_fb_is_fizz), 1);
|
467
|
+
rb_define_singleton_method(rb_cFizzBuzz, "is_buzz?", RUBY_METHOD_FUNC(rb_fb_is_buzz), 1);
|
468
|
+
rb_define_singleton_method(rb_cFizzBuzz, "is_fizzbuzz?", RUBY_METHOD_FUNC(rb_fb_is_fizzbuzz), 1);
|
469
|
+
|
470
|
+
rb_define_singleton_method(rb_cFizzBuzz, "[]", RUBY_METHOD_FUNC(rb_fb_square), 1);
|
471
|
+
}
|
472
|
+
|
473
|
+
/* vim: set ts=8 sw=4 sts=2 et : */
|