I keep getting the error below when running my code.
My Code:
class Integer
def num_digits
Math.log10(self).to_i + 1
end
def p(t)
case t
when 3
return self * (self + 1) / 2
when 4
return self**2
when 5
return self * ((3 * self) - 1) / 2
when 6
return self * ((2 * self) - 1)
when 7
return self * ((5 * self) - 3) / 2
when 8
return self * ((3 * self) - 2)
end
end
end
$p3 = [], $p4 = [], $p5 = [], $p6 = [], $p7 = [], $p8 = []
$polygonals = [$p3, $p4, $p5, $p6, $p7, $p8]
(3..8).each_with_index do |t, index|
i = 1
until i == 150
$polygonals[index] << i.p(t)
i += 1
end
end
$polygonals.each { |array| array.reject! { |x| x.num_digits != 4 } }
Error:
`block (2 levels) in <main>': undefined method `num_digits' for []:Array (NoMethodError)
However, if I change the last line of code to:
$polygonals.each { |array| array.each { |x| x.reject! { |y| y.num_digits != 4 } } }
I get the error:
`block (2 levels) in <main>': undefined method `reject!' for 1:Fixnum (NoMethodError)
How can x be type array in the first case and type Fixnum in the second?
The commas on this line
$p3 = [], $p4 = [], $p5 = [], $p6 = [], $p7 = [], $p8 = []
Don't do what you think. In ruby
a = 1,2
sets a to [1,2], so this is setting $p3 to
[[], [], [], [], [], []]
If you put those assignments on separate lines or use ; rather than commas then those variables will be initialised to what you expect.
Edit
The reason for your failure is shown below:
irb(main):072:0> $polygonals = [$p3, $p4, $p5, $p6, $p7, $p8]
=> [[[], [], [], [], [], []], [], [], [], [], []]
Observe how does your first element look like. Not exactly as you would have expected, right?
Actually you have both. See how your $polygonals[0] look like:
irb(main):066:0> $polygonals[0]=> [[], [1, 4, 9, 16, 25, 36, 49, 64,
81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484,
529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225,
1296, 1369, 1444, 1521,1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209,
2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364,
3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761,
4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400,
6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921,8100, 8281, 8464,
8649, 8836, 9025, 9216, 9409, 9604, 9801, 10000, 10201, 10404, 10609,
10816, 11025, 11236, 11449, 11664, 11881, 12100, 12321, 12544, 12769,
12996, 13225, 13456, 13689, 13924, 14161,14400, 14641, 14884, 15129,
15376, 15625, 15876, 16129, 16384, 16641, 16900, 17161, 17424, 17689,
17956, 18225, 18496, 18769, 19044, 19321, 19600, 19881, 20164, 20449,
20736, 21025, 21316, 21609, 21904, 22201], [1, 5, 12, 22, 35, 51, 70,
92, 117, 145, 176, 210, 247, 287, 330, 376, 425, 477, 532, 590, 651,
715, 782, 852, 925, 1001, 1080, 1162, 1247, 1335, 1426, 1520, 1617,
1717, 1820, 1926, 2035, 2147, 2262, 2380, 2501, 2625, 2752, 2882,
3015, 3151, 3290, 3432, 3577, 3725, 3876, 4030, 4187, 4347,4510, 4676,
4845, 5017, 5192, 5370, 5551, 5735, 5922, 6112, 6305, 6501, 6700,
6902, 7107, 7315, 7526, 7740, 7957, 8177, 8400, 8626, 8855, 9087,
9322, 9560, 9801, 10045, 10292, 10542, 10795, 11051, 11310, 11572,
11837, 12105, 12376, 12650, 12927, 13207, 13490, 13776, 14065, 14357,
14652, 14950, 15251, 15555, 15862, 16172, 16485, 16801, 17120, 17442,
17767, 18095, 18426, 18760, 19097, 19437, 19780,20126, 20475, 20827,
21182, 21540, 21901, 22265, 22632, 23002, 23375, 23751, 24130, 24512,
24897, 25285, 25676, 26070, 26467, 26867, 27270, 27676, 28085, 28497,
28912, 29330, 29751, 30175, 30602, 31032, 31465, 31901, 32340, 32782,
33227], [1, 6, 15, 28, 45, 66, 91, 120, 153, 190, 231, 276, 325, 378,
435, 496, 561, 630, 703, 780, 861, 946, 1035, 1128, 1225, 1326, 1431,
1540, 1653, 1770, 1891, 2016, 2145, 2278, 2415, 2556, 2701, 2850,
3003, 3160, 3321, 3486, 3655, 3828, 4005, 4186, 4371, 4560, 4753,
4950, 5151, 5356, 5565, 5778, 5995, 6216, 6441, 6670, 6903, 7140,
7381, 7626, 7875, 8128, 8385,8646, 8911, 9180, 9453, 9730, 10011,
10296, 10585, 10878, 11175, 11476, 11781, 12090, 12403, 12720,13041,
13366, 13695, 14028, 14365, 14706, 15051, 15400, 15753, 16110, 16471,
16836, 17205, 17578, 17955, 18336, 18721, 19110, 19503, 19900, 20301,
20706, 21115, 21528, 21945, 22366, 22791, 23220, 23653, 24090, 24531,
24976, 25425, 25878, 26335, 26796, 27261, 27730, 28203, 28680, 29161,
29646, 30135,30628, 31125, 31626, 32131, 32640, 33153, 33670, 34191,
34716, 35245, 35778, 36315, 36856, 37401, 37950, 38503, 39060, 39621,
40186, 40755, 41328, 41905, 42486, 43071, 43660, 44253], [1, 7, 18,
34, 55, 81, 112, 148, 189, 235, 286, 342, 403, 469, 540, 616, 697,
783, 874, 970, 1071, 1177, 1288, 1404,1525, 1651, 1782, 1918, 2059,
2205, 2356, 2512, 2673, 2839, 3010, 3186, 3367, 3553, 3744, 3940,
4141, 4347, 4558, 4774, 4995, 5221, 5452, 5688, 5929, 6175, 6426,
6682, 6943, 7209, 7480, 7756, 8037, 8323, 8614, 8910, 9211, 9517,
9828, 10144, 10465, 10791, 11122, 11458, 11799, 12145, 12496, 12852,
13213, 13579, 13950, 14326, 14707, 15093, 15484, 15880, 16281, 16687,
17098, 17514, 17935, 18361, 18792, 19228, 19669, 20115, 20566, 21022,
21483, 21949, 22420, 22896, 23377, 23863, 24354, 24850, 25351,25857,
26368, 26884, 27405, 27931, 28462, 28998, 29539, 30085, 30636, 31192,
31753, 32319, 32890, 33466, 34047, 34633, 35224, 35820, 36421, 37027,
37638, 38254, 38875, 39501, 40132, 40768, 41409, 42055, 42706, 43362,
44023, 44689, 45360, 46036, 46717, 47403, 48094, 48790, 49491, 50197,
50908, 51624, 52345, 53071, 53802, 54538, 55279], [1, 8, 21, 40, 65,
96, 133, 176, 225, 280, 341, 408, 481, 560,645, 736, 833, 936, 1045,
1160, 1281, 1408, 1541, 1680, 1825, 1976, 2133, 2296, 2465, 2640,
2821, 3008, 3201, 3400, 3605, 3816, 4033, 4256, 4485, 4720, 4961,
5208, 5461, 5720, 5985, 6256, 6533, 6816,7105, 7400, 7701, 8008, 8321,
8640, 8965, 9296, 9633, 9976, 10325, 10680, 11041, 11408, 11781,
12160, 12545, 12936, 13333, 13736, 14145, 14560, 14981, 15408, 15841,
16280, 16725, 17176, 17633, 18096,18565, 19040, 19521, 20008, 20501,
21000, 21505, 22016, 22533, 23056, 23585, 24120, 24661, 25208, 25761,
26320, 26885, 27456, 28033, 28616, 29205, 29800, 30401, 31008, 31621,
32240, 32865, 33496, 34133, 34776, 35425, 36080, 36741, 37408, 38081,
38760, 39445, 40136, 40833, 41536, 42245, 42960, 43681, 44408, 45141,
45880, 46625, 47376, 48133, 48896, 49665, 50440, 51221, 52008, 52801,
53600, 54405,55216, 56033, 56856, 57685, 58520, 59361, 60208, 61061,
61920, 62785, 63656, 64533, 65416, 66305], 1, 3, 6, 10, 15, 21, 28,
36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253,
276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666,
703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225,
1275, 1326, 1378, 1431, 1485, 1540, 1596, 1653, 1711, 1770, 1830,
1891, 1953, 2016, 2080, 2145, 2211, 2278, 2346, 2415, 2485, 2556,
2628, 2701, 2775, 2850, 2926, 3003,3081, 3160, 3240, 3321, 3403, 3486,
3570, 3655, 3741, 3828, 3916, 4005, 4095, 4186, 4278, 4371, 4465,
4560, 4656, 4753, 4851, 4950, 5050, 5151, 5253, 5356, 5460, 5565,
5671, 5778, 5886, 5995, 6105, 6216, 6328, 6441, 6555, 6670, 6786,
6903, 7021, 7140, 7260, 7381, 7503, 7626, 7750, 7875, 8001, 8128,8256,
8385, 8515, 8646, 8778, 8911, 9045, 9180, 9316, 9453, 9591, 9730,
9870, 10011, 10153, 10296,10440, 10585, 10731, 10878, 11026, 11175]
And this is how your $polygonals[1] look like:
irb(main):067:0> $polygonals[1]=> [1, 4, 9, 16, 25, 36, 49, 64, 81,
100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529,
576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296,
1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209,
2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364,
3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761,
4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400,
6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281,
8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801, 10000, 10201, 10404,
10609, 10816, 11025, 11236, 11449, 11664, 11881, 12100, 12321, 12544,
12769, 12996, 13225, 13456, 13689, 13924, 14161, 14400, 14641, 14884,
15129, 15376, 15625, 15876, 16129, 16384, 16641, 16900, 17161, 17424,
17689, 17956,18225, 18496, 18769, 19044, 19321, 19600, 19881, 20164,
20449, 20736, 21025, 21316, 21609, 21904, 22201]
First off, it's generally considered bad practice to extend core classes such as Integer. You should only do this in special circumstances, where you are providing generic, useful behaviour that your application can use throughout.
The two methods you have written are both bad examples of when to do this:
class Integer
def num_digits
Math.log10(self).to_i + 1
end
end
Why bother with such a mathematical technique (123.num_digits == 3) when you could just do something like: 123.to_s.length == 3?
def p(t)
case t
when 3
return self * (self + 1) / 2
# ...
when 8
return self * ((3 * self) - 2)
end
end
end
What the heck is this?! What does p mean, why does the method only work for integers 3..8 (otherwise it returns nil)? I'm guessing it's to do with calculating polygonal numbers, in which case you should name it as such. This has no place in the Integer class; just make it a separate method, and name it better:
def rename_me(x, y) # What are x and y? What IS this method? Use real words!
case y
when 3
x * (x + 1) / 2
# ...
when 8
x * ((3 * x) - 2)
end
end
Next, never use global variables, unless you have a very good reason to. In ruby, variable names starting with $ are global. Instead of $polygonals, just define variables like polygonals.
Next, learn how to define variables in ruby. Writing code like x = 1, y = 2 is not doing what you think; that's actually setting x == [1, 2] and y == 2. The intention here is that a possible shorthand for defining variables is: x, y = 1, 2 which sets x == 1 and y == 2 - but I wouldn't generally recommend 1-line definitions like this; just put it on 2 lines.
With all of this in mind, here is how I would write your full code in a more "ruby way":
def rename_me(x, y) # What are x and y? What IS this method? Use real words!
case y
when 3
x * (x + 1) / 2
# ...
when 8
x * ((3 * x) - 2)
end
end
polygonals = ([(1..149)] * 6)
.map.with_index do |range, index|
range
.map { |x| rename_me(x, index + 3) }
.select { |x| x.to_s.length == 4 }
end
However (!!) you should use better variables names than I have above. Don't just call things x etc, unless they are just scratch variables; e.g. using i as an index can be OK sometimes.