epitools 0.5.134 → 0.5.137
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.
- checksums.yaml +4 -4
- data/Rakefile +5 -7
- data/VERSION +1 -1
- data/lib/epitools/autoloads.rb +1 -1
- data/lib/epitools/browser/cache.rb +1 -1
- data/lib/epitools/browser.rb +4 -4
- data/lib/epitools/clitools.rb +11 -4
- data/lib/epitools/core_ext/array.rb +2 -1
- data/lib/epitools/core_ext/date.rb +84 -0
- data/lib/epitools/core_ext/io.rb +8 -0
- data/lib/epitools/core_ext/misc.rb +5 -0
- data/lib/epitools/core_ext/numbers.rb +54 -12
- data/lib/epitools/core_ext/object.rb +4 -1
- data/lib/epitools/core_ext/string.rb +156 -5
- data/lib/epitools/core_ext.rb +2 -0
- data/lib/epitools/fraction.rb +131 -0
- data/lib/epitools/hexdump.rb +1 -1
- data/lib/epitools/mimemagic_tables.rb +1266 -1266
- data/lib/epitools/minimal.rb +2 -3
- data/lib/epitools/path.rb +33 -18
- data/lib/epitools/pretty_backtrace.rb +1 -1
- data/lib/epitools/rash.rb +1 -1
- data/lib/epitools/term.rb +73 -15
- data/spec/core_ext_spec.rb +53 -3
- data/spec/fraction_spec.rb +53 -0
- data/spec/numwords_spec.rb +2 -5
- data/spec/path_spec.rb +14 -4
- data/spec/sys_spec.rb +5 -0
- data/spec/zopen_spec.rb +37 -37
- metadata +8 -9
- data/lib/epitools/ratio.rb +0 -78
- /data/spec/{browser_spec.rb → manual/browser_spec.rb} +0 -0
- /data/spec/{wm_spec.rb → manual/wm_spec.rb} +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#
|
|
2
|
+
# A fraction! (Like a Rational, but ... uh ... in pure Ruby!)
|
|
3
|
+
#
|
|
4
|
+
# Can be compared, added, multiplied, simplified, "percent"ed, "to_f"ed, and printed/inspected.
|
|
5
|
+
#
|
|
6
|
+
class Fraction
|
|
7
|
+
|
|
8
|
+
attr_accessor :first, :last
|
|
9
|
+
|
|
10
|
+
alias_method :top, :first
|
|
11
|
+
alias_method :bottom, :last
|
|
12
|
+
|
|
13
|
+
alias_method :numerator, :first
|
|
14
|
+
alias_method :denominator, :last
|
|
15
|
+
|
|
16
|
+
#
|
|
17
|
+
# `first` is the top part of the fraction, `last` is the bottom (eg: `first/last`)
|
|
18
|
+
#
|
|
19
|
+
def initialize(first, last=1)
|
|
20
|
+
@first = first
|
|
21
|
+
@last = last
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.[](*args)
|
|
25
|
+
new(*args)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
include Comparable
|
|
29
|
+
|
|
30
|
+
def <=>(other)
|
|
31
|
+
to_f <=> other.to_f
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Returns a string representation: "a/b"
|
|
36
|
+
#
|
|
37
|
+
def to_s
|
|
38
|
+
"#{@first}/#{@last}"
|
|
39
|
+
end
|
|
40
|
+
alias_method :fraction, :to_s
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# Returns the fraction as a float. (eg: Fraction[1,2].to_f == 0.5)
|
|
44
|
+
#
|
|
45
|
+
def to_f
|
|
46
|
+
if @last == 0
|
|
47
|
+
raise ZeroDivisionError
|
|
48
|
+
else
|
|
49
|
+
@first.to_f / @last
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# Returns a string representing the number in percent
|
|
55
|
+
#
|
|
56
|
+
def percent
|
|
57
|
+
"%0.1f%%" % (to_f * 100)
|
|
58
|
+
end
|
|
59
|
+
alias_method :to_percent, :percent
|
|
60
|
+
|
|
61
|
+
#
|
|
62
|
+
# "#<Fraction: 1/2>"
|
|
63
|
+
#
|
|
64
|
+
def inspect
|
|
65
|
+
"#<Fraction: #{to_s}>"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
# Adds together the tops and bottoms of the fractions.
|
|
70
|
+
#
|
|
71
|
+
# Example: For the fractions `a/c` and `b/d`, returns `a+b/c+d`
|
|
72
|
+
#
|
|
73
|
+
def +(r)
|
|
74
|
+
case r
|
|
75
|
+
when Integer
|
|
76
|
+
self + Fraction[r]
|
|
77
|
+
when Fraction
|
|
78
|
+
Fraction[ r.last*first + r.first*last, r.last*last ]
|
|
79
|
+
else
|
|
80
|
+
raise TypeError.new("Sorry, I can't add a Fraction and a #{r.class}. :(")
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
#
|
|
85
|
+
# Multiply the fractions
|
|
86
|
+
#
|
|
87
|
+
def *(v)
|
|
88
|
+
case v
|
|
89
|
+
when Integer
|
|
90
|
+
Fraction[ v*first, v*last ]
|
|
91
|
+
when Fraction
|
|
92
|
+
Fraction[ v.first*first, v.last*last ]
|
|
93
|
+
else
|
|
94
|
+
raise TypeError.new("I don't know how to multiply a Fraction and a #{v.class}. Sorry. :(")
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def simplify
|
|
99
|
+
require 'prime'
|
|
100
|
+
|
|
101
|
+
# factor the numerator and denominator into hashes of { factor => exponent } pairs
|
|
102
|
+
n_fact, d_fact = [numerator, denominator].map { |n| Prime.prime_division(n).to_h }
|
|
103
|
+
|
|
104
|
+
# cancel out common factors by subtracting exponents
|
|
105
|
+
d_fact.each do |v, d_exp|
|
|
106
|
+
if n_exp = n_fact[v]
|
|
107
|
+
if n_exp < d_exp
|
|
108
|
+
d_fact[v] = d_exp - n_exp
|
|
109
|
+
n_fact[v] = 0
|
|
110
|
+
else
|
|
111
|
+
n_fact[v] = n_exp - d_exp # <= if n_exp == d_exp, this is 0, which covers the 3rd case
|
|
112
|
+
d_fact[v] = 0
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# multiply the simplified factors back into full numbers
|
|
118
|
+
simp_n, simp_d = [n_fact, d_fact].map { |h| h.map{ |n, exp| n ** exp }.reduce(:*) }
|
|
119
|
+
|
|
120
|
+
Fraction[simp_n, simp_d]
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
#####################################################################################
|
|
126
|
+
#
|
|
127
|
+
# Fraction(a,b) is a wrapper for Fraction[a,b]
|
|
128
|
+
#
|
|
129
|
+
def Fraction(*args)
|
|
130
|
+
Fraction.new(*args)
|
|
131
|
+
end
|
data/lib/epitools/hexdump.rb
CHANGED