1

#!/usr/bin/env ruby

2

#==========================================================================

3


4

def x_apply_binary_operator_t1(x_identity_element,ar_in,

5

func_operator_that_might_be_noncommutative)

6

# This code is is a slightly edited version of the

7

# kibuvits_s_concat_array_of_strings(...) core.

8

# The comments and explanations are mostly there.

9

#

10

# May be the following link works:

11

# https://github.com/martinvahi/mmmv_devel_tools/blob/master/src/bonnet/lib/kibuvits_ruby_library/src/include/kibuvits_str_concat_array_of_strings.rb

12

#

13

# If the next link works properly, then there

14

# might be some demos for string concatenation at

15

# https://github.com/martinvahi/mmmv_notes/tree/master/mmmv_notes/phenomenon_scrutinization/string_concatenation

16

#

17

# The general idea is that from memory

18

# allocation point of view multiplication

19

# is similar to string concatenation. An example:

20

#

21

# new_string="100"+"000" # == "100000"

22

# new_number= 100 *1000 # == 100000

23

#

24

#

25

cl=ar_in.class

26

if cl!=Array

27

raise(Exception.new("ar_in.class=="+cl.to_s+

28

", but it is expected to be Array.\n"))

29

end # if

30

cl=func_operator_that_might_be_noncommutative.class

31

if cl!=Proc

32

raise(Exception.new("func_operator_that_might_be_noncommutative.class=="+cl.to_s+

33

", but it is expected to be Proc.\n"))

34

end # if

35

#

36

func_oper=func_operator_that_might_be_noncommutative

37

i_n=ar_in.size

38

if i_n<3

39

if i_n==2

40

x_out=func_oper.call(ar_in[0],ar_in[1])

41

return x_out

42

else

43

if i_n==1

44

# For the sake of consistency one

45

# wants to make sure that the returned

46

# string instance always differs from those

47

# that are within the ar_in.

48

x_out=func_oper.call(x_identity_element,ar_in[0])

49

return x_out

50

else # i_n==0

51

x_out=x_identity_element

52

return x_out

53

end # if

54

end # if

55

end # if

56

x_out=x_identity_element # needs to be inited to the x_identity_element

57

ar_1=ar_in

58

b_ar_1_equals_ar_in=true # to avoid modifying the received Array

59

ar_2=Array.new

60

b_take_from_ar_1=true

61

b_not_ready=true

62

i_reminder=nil

63

i_loop=nil

64

i_ar_in_len=nil

65

i_ar_out_len=0 # code after the while loop needs a number

66

x_1=nil

67

x_2=nil

68

x_3=nil

69

i_2=nil

70

while b_not_ready

71

# The next ifstatement is to avoid copying temporary

72

# strings between the ar_1 and the ar_2.

73

if b_take_from_ar_1

74

i_ar_in_len=ar_1.size

75

i_reminder=i_ar_in_len%2

76

i_loop=(i_ar_in_leni_reminder)/2

77

i_loop.times do i

78

i_2=i*2

79

x_1=ar_1[i_2]

80

x_2=ar_1[i_2+1]

81

x_3=func_oper.call(x_1,x_2)

82

ar_2<<x_3

83

end # loop

84

if i_reminder==1

85

x_3=ar_1[i_ar_in_len1]

86

ar_2<<x_3

87

end # if

88

i_ar_out_len=ar_2.size

89

if 1<i_ar_out_len

90

if b_ar_1_equals_ar_in

91

ar_1=Array.new

92

b_ar_1_equals_ar_in=false

93

else

94

ar_1.clear

95

end # if

96

else

97

b_not_ready=false

98

end # if

99

else # b_take_from_ar_1==false

100

i_ar_in_len=ar_2.size

101

i_reminder=i_ar_in_len%2

102

i_loop=(i_ar_in_leni_reminder)/2

103

i_loop.times do i

104

i_2=i*2

105

x_1=ar_2[i_2]

106

x_2=ar_2[i_2+1]

107

x_3=func_oper.call(x_1,x_2)

108

ar_1<<x_3

109

end # loop

110

if i_reminder==1

111

x_3=ar_2[i_ar_in_len1]

112

ar_1<<x_3

113

end # if

114

i_ar_out_len=ar_1.size

115

if 1<i_ar_out_len

116

ar_2.clear

117

else

118

b_not_ready=false

119

end # if

120

end # if

121

b_take_from_ar_1=!b_take_from_ar_1

122

end # loop

123

if i_ar_out_len==1

124

if b_take_from_ar_1

125

x_out=ar_1[0]

126

else

127

x_out=ar_2[0]

128

end # if

129

else

130

# The x_out has been inited to "".

131

if 0<i_ar_out_len

132

raise Exception.new("This function is flawed."+

133

"\n GUID='1e84a70239cb458b8728f24371c06ed7'\n\n")

134

end # if

135

end # if

136

return x_out

137

end # x_apply_binary_operator_t1

138


139


140

def i_factorial_t1(i_n)

141

if defined? KIBUVITS_b_DEBUG

142

if KIBUVITS_b_DEBUG

143

bn=binding()

144

# Allowing the i_n to be a Bignum is a bit crazy in 2014,

145

# but may be in the future that might not be that crazy.

146

kibuvits_typecheck bn, [Fixnum,Bignum], i_n

147

kibuvits_assert_is_smaller_than_or_equal_to(bn,0,i_n,

148

"\n GUID='4289c48117934f01b3e5e2700090bed7'\n\n")

149

end # if

150

else

151

# It's up to the final implementers to figure out,

152

# what, if any, input verification must take place here,

153

# but, for the time being:

154

cl=i_n.class

155

if cl!=Fixnum

156

if cl!=Bignum

157

raise(Exception.new("i_n.class=="+cl.to_s+

158

", but it is expected to be of some whole number type."))

159

end # if

160

end # if

161

if i_n<0

162

raise(Exception.new("i_n=="+i_n.to_s+" < 0 ,"+

163

"but factorials are defined for positive numbers."))

164

end # if

165

end # if

166

i_out=1 # factorial(0)==1

167

return i_out if i_n==0

168

func_star=lambda do x_a,x_b

169

x_out=x_a*x_b

170

return x_out

171

end # func_star

172

ar_n=Array.new

173

# For i_n==2, the ar_n==[0,1,2], ar_n.size==3 .

174

# To avoid multiplication with 0, ar_n[0]==1 .

175

# Therefore, for i_n==2, ar_n==[1,2] .

176

i_n.times{i ar_n<<(i+1)} # i starts from 0

177

x_identity_element=1

178

i_out=x_apply_binary_operator_t1(

179

x_identity_element,ar_n,func_star)

180

return i_out

181

end # i_factorial_t1

182


183

class Fixnum

184

def factorial

185

i_out=i_factorial_t1(self)

186

return i_out

187

end # factorial

188

end # class Fixnum

189


190

class Bignum

191

def factorial

192

i_out=i_factorial_t1(self)

193

return i_out

194

end # factorial

195

end # class Bignum

196


197

#

198


199

def i_factorial_old_style(i_n)

200

i_factorial=1

201

return i_factorial if (i_n==0)(i_n==1)

202

i_n.times do i

203

i_factorial=i_factorial*(i+1)

204

end # loop

205

return i_factorial

206

end # i_factorial_old_style

207


208

if ARGV.size==0

209

puts "\n\nFirst console argument must be a whole number.\n\n"

210

exit

211

end # if

212

i_n=ARGV[0].to_i

213

b_both=false

214

b_old=true

215

b_old=false if 1<ARGV.size

216

b_both=true if ARGV.size==3

217


218

if b_old

219

i_factorial=i_factorial_old_style(i_n)

220

s_result=i_factorial.to_s

221

if s_result.length<10

222

puts "\n\n Factorial of "+i_n.to_s+" by the simplistic algorithm is:\n"+

223

s_result+"\n\n"

224

else

225

puts "\n\n Factorial of "+i_n.to_s+" by the simplistic algorithm \n"+

226

"has a length of "+s_result.length.to_s+"\n\n"

227

end # if

228

else

229

if b_both

230

i_factorial_old=i_factorial_old_style(i_n)

231

i_factorial_new=i_n.factorial

232

if i_factorial_old!=i_factorial_new

233

puts "\n\nThere's a flaw somewhere.\n\n"

234

else

235

puts "\n\nThe results of the proposed algorithm and the \n"+

236

"simplistic algorithm match.\n\n"

237

end # if

238

else

239

i_factorial=i_n.factorial

240

s_result=i_factorial.to_s

241

if s_result.length<10

242

puts "\n\n Factorial of "+i_n.to_s+" by the proposed algorithm is:\n"+

243

i_factorial.to_s+"\n\n"

244

else

245

puts "\n\n Factorial of "+i_n.to_s+" by the proposed algorithm \n"+

246

"has a length of "+s_result.length.to_s+"\n\n"

247

end # if

248

end # if

249

end # if

250


251


252

#==========================================================================
