koremutake 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ 0.1:
2
+ Project started (2008-05-02)
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2008 Gunnar Wolf <gwolf@gwolf.org>
2
+
3
+ The Koremutake project is hereby licensed under this license. This
4
+ license is known as "The MIT License".
5
+
6
+ Permission is hereby granted, free of charge, to any person
7
+ obtaining a copy of this software and associated documentation
8
+ files (the "Software"), to deal in the Software without
9
+ restriction, including without limitation the rights to use,
10
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the
12
+ Software is furnished to do so, subject to the following
13
+ conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,6 @@
1
+ ./Manifest.txt
2
+ ./CHANGELOG
3
+ ./LICENSE
4
+ ./README
5
+ ./lib/koremu.rb
6
+ koremutake.gemspec
data/README ADDED
@@ -0,0 +1,72 @@
1
+ = koremu.rb - Ruby implementation of the Koremutake Memorable Random Strings
2
+
3
+ == SYNOPSIS
4
+
5
+ require 'koremu'
6
+
7
+ ks = KoremuString.new('KOREMUTAKE')
8
+ puts ks.to_ki # 10610353957
9
+ puts ks.to_ka.join(',') # 39,67,52,78,37
10
+
11
+ ki = KoremuFixnum.new(1248594)
12
+ puts ki.to_ks # SUHITU
13
+ puts ki.to_ka .join(',') # 76,26,82
14
+
15
+ ka = KoremuArray.new([50,15,20,13])
16
+ puts ka.to_ks # MIFOGIFE
17
+ puts ka.to_ki # 105105933
18
+
19
+ == DESCRIPTION
20
+
21
+ For us humans, it's always easier to remember a pronounceable string,
22
+ even if it is meaningless, than to remember a long number. Koremutake
23
+ is a system you can use to translate any number (of course,
24
+ particularly suited at long numbers) to a sequence of
25
+ syllables. Typical uses of Koremutake strings are auto-generated user
26
+ passwords or URLs.
27
+
28
+ This module is based in Leon Brocard's String::Koremutake Perl
29
+ module, available at
30
+ http://search.cpan.org/dist/String-Koremutake/lib/String/Koremutake.pm
31
+ which is, in turn, based upon Shorl
32
+ (http://shorl.com/koremutake.php). Koremutake is a «way to express
33
+ any large number as a sequence of syllables», and the general idea
34
+ is based in Sean B. Palmer's «Memorable Random String» term,
35
+ http://infomesh.net/2001/07/MeRS/
36
+
37
+ == WHAT IS VALID KOREMUTAKE?
38
+
39
+ Koremutake consists of 128 valid syllables. They do not, of course,
40
+ represent all of the valid syllables in any random human language -
41
+ They are meanly <i>meant to encode integers</i>, not to transform
42
+ text into strings. If you try to transform regular text, <i>lots of
43
+ information will be lost in the process</i>
44
+
45
+ All of the syllables end with a vowel. The valid vowels are A, E, I,
46
+ O, U and Y. The consonant particles are B, D, F, G, H, J, K, L, M,
47
+ N, P, R, S, T, V, BR, DR, FR, GR, PR, ST and TR (TR has only TRA and
48
+ TRE).
49
+
50
+ Koremutake is represented with uppercase letters (and that's what it
51
+ returns), but will recognize lowercase as well.
52
+
53
+ == AUTHOR
54
+
55
+ This module was written by Gunnar Wolf <gwolf@gwolf.org>, Instituto
56
+ de Investigaciones Económicas, UNAM.
57
+
58
+ Copyright (c) 2008 Gunnar Wolf <gwolf@gwolf.org>
59
+
60
+ == LICENSING INFORMATION
61
+
62
+ This module is under a MIT license. For further information, please
63
+ check the LICENSE file.
64
+
65
+ = Getting the code
66
+
67
+ The module project's home page can be found at
68
+ http://rubyforge.org/projects/koremutake/
69
+
70
+ The project's Git repository can be anonymously cloned from:
71
+
72
+ git clone git://rubyforge.org/koremutake.git
@@ -0,0 +1,295 @@
1
+ require 'delegate'
2
+
3
+ module Koremutake #:nodoc:
4
+ Vowels = %W(A E I O U Y)
5
+ Phonemes = %W(BA BE BI BO BU BY DA DE DI DO DU DY FA FE FI
6
+ FO FU FY GA GE GI GO GU GY HA HE HI HO HU HY JA JE JI JO JU JY KA KE
7
+ KI KO KU KY LA LE LI LO LU LY MA ME MI MO MU MY NA NE NI NO NU NY PA
8
+ PE PI PO PU PY RA RE RI RO RU RY SA SE SI SO SU SY TA TE TI TO TU TY
9
+ VA VE VI VO VU VY BRA BRE BRI BRO BRU BRY DRA DRE DRI DRO DRU DRY FRA
10
+ FRE FRI FRO FRU FRY GRA GRE GRI GRO GRU GRY PRA PRE PRI PRO PRU PRY
11
+ STA STE STI STO STU STY TRA TRE)
12
+
13
+ protected
14
+ def nums_to_phonemes
15
+ unless @nums_to_phonemes
16
+ @nums_to_phonemes = {}
17
+ num = 0
18
+ Phonemes.each {|phon| @nums_to_phonemes[num] = phon; num += 1}
19
+ end
20
+ @nums_to_phonemes
21
+ end
22
+
23
+ def phonemes_to_nums
24
+ unless @phonemes_to_nums
25
+ @phonemes_to_nums = {}
26
+ nums_to_phonemes.map {|k,v| @phonemes_to_nums[v] = k}
27
+ end
28
+ @phonemes_to_nums
29
+ end
30
+ end
31
+
32
+ # = KoremuStringFunctions
33
+ #
34
+ # The following functions are either available through the
35
+ # KoremuString class, or can be included in other classes. For
36
+ # example, maybe the most natural use would be by including them in
37
+ # the String class. You can include them by typing this in your
38
+ # initialization:
39
+ #
40
+ # class String; include KoremuStringFunctions; end
41
+ #
42
+ # This way, any arbitrary string can be treated as a KoremuString:
43
+ #
44
+ # puts 'fefifofu'.to_ki # 27494288
45
+ # puts 'fefifofu'.to_ka # [13, 14, 15, 16]
46
+ #
47
+ # If you choose not to extend String, you can use KoremuString as a
48
+ # regular class, initializing it with the string in question:
49
+ #
50
+ # ks = KoremuString.new('fefifofu')
51
+ #
52
+ module KoremuStringFunctions
53
+ include Koremutake
54
+ # Returns an array (<b>not</b> a KoremuArray - A regular Array)
55
+ # where each of the elements is one of the tokens of the
56
+ # string. When tokenizing, any particle which does not conform a
57
+ # Koremutake syllable <i>will be dropped</i> (with a warning being
58
+ # issued), thus:
59
+ #
60
+ # irb(main):017:0> Koremutake.new('KoremuFixnum').tokenize
61
+ # Invalid Koremutake phoneme 'XNU'
62
+ # => ["KO", "RE", "MU", "FI"]
63
+ #
64
+ # Please refer to the WHAT IS VALID KOREMUTAKE section in the
65
+ # general documentation for koremu.rb for further information.
66
+ def tokenize
67
+ str = self || ''
68
+ rel = phonemes_to_nums
69
+ buf = ''
70
+ res = []
71
+
72
+ str.upcase.split(//).each do |chr|
73
+ buf << chr
74
+ next unless Vowels.include?(chr)
75
+ if Phonemes.include?(buf)
76
+ res << buf
77
+ else
78
+ warn "Invalid Koremutake phoneme '#{buf}'"
79
+ end
80
+ buf = ''
81
+ end
82
+
83
+ if str.size > 0 and ! Vowels.include?(str[-1,1].upcase)
84
+ warn "The received string does not end in a valid syllable: #{str[-1,1].upcase}"
85
+ end
86
+
87
+ if res[0] == Phonemes[0] and res.size > 1
88
+ warn "Dropping leading zero (#{Phonemes[0]}) syllables from #{res} (#{res.size})"
89
+ res.shift while res[0] == Phonemes[0]
90
+ end
91
+ res
92
+ end
93
+
94
+ # Check if the given KoremuString is valid, returning true or
95
+ # false. If it is <i>not</i> valid, it can still be used -
96
+ # Non-recognized characters will just be dropped, so:
97
+ #
98
+ # puts KoremuString.new('Koremu Take').to_ki # 10610353957
99
+ # puts KoremuString.new('Koremu Take').to_ki.to_ks # KOREMUTAKE
100
+ #
101
+ # However, a syllable should be atomic - It should not be split:
102
+ #
103
+ # puts KoremuString.new('Korem Utake').to_ki.to_ks # KORETAKE
104
+ #
105
+ # Note that the 'BA' particle has a particularity - If it is at the
106
+ # beginning of the string, it should be dropped, as it means 0. Keep
107
+ # in mind Koremutake is mainly a way to represent numbers.
108
+ # i. e. 'BABABABABABE' == 1 == 'BE'. Therefore, a string starting
109
+ # with 'BA' and with more characters is considered valid.
110
+ def valid?
111
+ return false if self.upcase[0,2] == 'BA' and self.size > 2
112
+ self.tokenize.join == self.upcase
113
+ end
114
+
115
+ # Returns the numeric representation of the KoremuString as a
116
+ # KoremuFixnum (why <tt>to_ki</tt>? as an analogy to Ruby's own
117
+ # <tt>to_i</tt>, which returns a Fixnum)
118
+ def to_ki
119
+ self.to_ka.to_ki
120
+ end
121
+
122
+ # Returns the KoremuArray representation of the KoremuString.
123
+ def to_ka
124
+ rel = phonemes_to_nums
125
+ arr = self.tokenize.map { |phoneme| rel[phoneme] }
126
+ arr = [0] if arr.empty?
127
+
128
+ KoremuArray.new(arr)
129
+ end
130
+ end
131
+
132
+ # = KoremuFixnumFunctions
133
+ #
134
+ # The following functions are either available through the
135
+ # KoremuFixnum class, or can be included in other classes. For
136
+ # example, maybe the most natural use would be by including them in
137
+ # the Fixnum class. You can include them by typing this in your
138
+ # initialization:
139
+ #
140
+ # class Fixnum; include KoremuFixnumFunctions; end
141
+ #
142
+ # This way, any arbitrary string can be treated as a KoremuString:
143
+ #
144
+ # puts 27494288.to_ks # FEFIFOFU
145
+ # puts 27494288.to_ka # [13, 14, 15, 16]
146
+ #
147
+ # If you choose not to extend Fixnum, you can use KoremuFixnum as a
148
+ # regular class, initializing it with the number in question:
149
+ #
150
+ # ks = KoremuFixnum.new(1024**4 + 1024**3 + 1024**2 + 1024) # JIBUBAPUDIBA
151
+ #
152
+ module KoremuFixnumFunctions
153
+ include Koremutake
154
+ def initialize(val) #:nodoc:
155
+ raise InvalidKoremutake, 'Negative values not defined' if val < 0
156
+ val = val.to_i || 0
157
+ super(val)
158
+ end
159
+
160
+ # Returns the KoremuArray representation of the KoremuFixmum
161
+ def to_ka
162
+ raise InvalidKoremutake, 'Negative values not defined' if self < 0
163
+ return KoremuArray.new([0]) if self == 0
164
+ res = KoremuArray.new
165
+ num = self
166
+ while num > 0
167
+ res.unshift num%128
168
+ num = KoremuFixnum.new(num/128)
169
+ end
170
+ res
171
+ end
172
+
173
+ # Returns the KoremuString representatiion of the KoremuFixnum
174
+ def to_ks
175
+ self.to_ka.to_ks
176
+ end
177
+ end
178
+
179
+ # = KoremuArrayFunctions
180
+ #
181
+ # The following functions are either available through the
182
+ # KoremuArray class, or can be included in other classes. For
183
+ # example, maybe the most natural use would be by including them in
184
+ # the Array class. You can include them by typing this in your
185
+ # initialization:
186
+ #
187
+ # class Array; include KoremuArrayFunctions; end
188
+ #
189
+ # This way, any arbitrary array can be treated as a KoremuArray:
190
+ #
191
+ # puts [10,50,120,3].to_ks # DUMISTABO
192
+ # puts [10,50,120,3].to_ki # 21806083
193
+ #
194
+ # If a KoremuArray includes any invalid element, it will be ignored
195
+ # and skipped - The elements should all be integers between 0 and 128:
196
+ #
197
+ # irb(main):004:0> KoremuArray.new([1,2,10,100,1000]).to_ks.to_ka
198
+ # Invalid Koremutake element '1000'
199
+ # => [1, 2, 10, 100]
200
+ #
201
+ # If you choose not to extend Array, you can use KoremuArray as a
202
+ # regular class:
203
+ #
204
+ # ks = KoremuArray.new([39, 67, 52, 78, 37]) # KOREMUTAKE
205
+ #
206
+ # Notice the array should be given as the first element in the
207
+ # initialization. This is to keep consistency with the built-in Array
208
+ # behaviour.
209
+ module KoremuArrayFunctions
210
+ include Koremutake
211
+ # Check if the given KoremuArray is valid, returning true or
212
+ # false. If it is <i>not</i> valid, it can still be used -
213
+ # Non-recognized elements will just be dropped, so:
214
+ #
215
+ # puts KoremuArray.new([39, 67, 52, 200, 78, 37]).to_ki # 10610353957
216
+ # puts KoremuArray.new([39, 67, 52, 78, 37]).to_ki # 10610353957
217
+ #
218
+ # puts KoremuArray.new([39, 67, 52, 200, 78, 37]).to_ks # KOREMUTAKE
219
+ # puts KoremuArray.new([39, 67, 52, 78, 37]).to_ks # KOREMUTAKE
220
+ #
221
+ # In both cases, the '200' is dropped (and a warning issued, of
222
+ # course).
223
+ #
224
+ # Remember that Koremutake is a way to represent numbers - Thus,
225
+ # although zeros are valid, they would be collapsed at the beginning
226
+ # - i.e. [0, 0, 0, 0, 1] would become [1]. So, as there is
227
+ # potentially information loss, 0 is not valid as a first element.
228
+ def valid?
229
+ self.each do |elem|
230
+ return false unless valid_elem?(elem)
231
+ end
232
+ return false if self[0] == 0
233
+ true
234
+ end
235
+
236
+ # Returns the KoremuString representation of the KoremuArray
237
+ def to_ks
238
+ rel = nums_to_phonemes
239
+ ks = KoremuString.new('')
240
+
241
+ # Drop any stream of leading zeroes. However, be consistent: We
242
+ # are representing values. Return a 0 if we have no value yet
243
+ self.shift while self[0] == 0
244
+ self << 0 if self.empty?
245
+
246
+ self.each do |num|
247
+ unless valid_elem?(num)
248
+ warn "Invalid Koremutake element '#{num}'"
249
+ next
250
+ end
251
+ ks << rel[num]
252
+ end
253
+ ks
254
+ end
255
+
256
+ # Returns the KoremuFixnum representation of the KoremuArray
257
+ def to_ki
258
+ res = 0
259
+ self.each do |num|
260
+ unless valid_elem?(num)
261
+ warn "Invalid Koremutake element '#{num}'"
262
+ next
263
+ end
264
+ res *= 128
265
+ res += num
266
+ end
267
+ KoremuFixnum.new(res)
268
+ end
269
+
270
+ private
271
+ def valid_elem?(elem) #:nodoc:
272
+ return false unless elem.is_a? Fixnum
273
+ return false if elem < 0 or elem > 127
274
+ true
275
+ end
276
+ end
277
+
278
+ # Please refer to the KoremuStringFunctions for documentation
279
+ class KoremuString < String
280
+ include KoremuStringFunctions
281
+ end
282
+
283
+ # Please refer to the KoremuArrayFunctions for documentation
284
+ class KoremuArray < Array
285
+ include KoremuArrayFunctions
286
+ end
287
+
288
+ # Please refer to the KoremuFixnumFunctions for documentation
289
+ class KoremuFixnum < DelegateClass(Fixnum)
290
+ include KoremuFixnumFunctions
291
+ end
292
+
293
+ # Just an exception class, nothing to see here, move on...
294
+ class InvalidKoremutake < Exception
295
+ end
@@ -0,0 +1,80 @@
1
+ require 'koremu'
2
+ require 'test/unit'
3
+
4
+ class KoremutakeConversionsTest < Test::Unit::TestCase
5
+ def test_basic_definitions
6
+ assert Koremutake::Phonemes.size == 128
7
+ end
8
+
9
+ def test_array_validations
10
+ # KoremuArrays should only accept as valid integer (Fixnum)
11
+ # elements between 0 and 127. 0 should not be the first value.
12
+ assert(! KoremuArray.new([5, 10, -5]).valid?,
13
+ "Negative values passed as valid")
14
+ assert(! KoremuArray.new([0, 15, 130]).valid?,
15
+ "Array started with 0 passed as valid")
16
+ assert(! KoremuArray.new([17, 20, 85, :foo]).valid?,
17
+ "Array with non-fixnum value passed as valid")
18
+ assert(! KoremuArray.new([120, 125, 128, 127]).valid?,
19
+ "Array with values over 127 passed as valid")
20
+ assert(KoremuArray.new([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110,
21
+ 120, 127]).valid?,
22
+ "Perfectly valid array reported as invalid")
23
+ end
24
+
25
+ # def test_tokenizer
26
+
27
+ # end
28
+
29
+ # def test_zero_handling
30
+ # # Are empty/zero values correctly and consistently handled?
31
+ # arr = KoremuArray.new()
32
+ # str = KoremuString.new('')
33
+ # num = KoremuFixnum.new(0)
34
+
35
+ # assert num.to_ka == arr, "Zero not correctly converted to empty array"
36
+ # assert num.to_ks == str
37
+
38
+ # assert str.to_ki == num
39
+ # assert str.to_ka == arr
40
+
41
+ # assert arr.to_ki == num
42
+ # assert arr.to_ks == str
43
+ # end
44
+
45
+ def test_from_random_fixnum
46
+ 100.times do
47
+ num = KoremuFixnum.new rand(100000)
48
+ assert(num == num.to_ka.to_ki,
49
+ "Fixnum #{num} unsuccessfully converted back from Array")
50
+ assert(num == num.to_ks.to_ki,
51
+ "Fixnum #{num} unsuccessfully converted back from String")
52
+ end
53
+ end
54
+
55
+ def test_from_random_array
56
+ 100.times do
57
+ arr = KoremuArray.new
58
+ # Ensure we don't even try to work with empty arrays
59
+ (1+rand(5)).times {arr << rand(127)}
60
+
61
+ # 0 as a first element is not valid
62
+ arr.shift while arr[0] == 0 and arr.size > 1
63
+ assert(arr == arr.to_ki.to_ka,
64
+ "Array #{arr.join('-')} unsuccessfully converted back from Fixnum")
65
+ assert(arr == arr.to_ks.to_ka,
66
+ "Array #{arr.join('-')} unsuccessfully converted back from String")
67
+ end
68
+ end
69
+
70
+ def test_from_random_string
71
+ 100.times do
72
+ str = KoremuString.new
73
+ rand(10).times {str << Koremutake::Phonemes[rand(Koremutake::Phonemes.size)]}
74
+ assert(str = str.to_ki.to_ks,
75
+ "String #{str} unsuccessfully converted back from Fixnum")
76
+ assert(str = str.to_ka.to_ks,
77
+ "String #{str} unsuccessfully converted back from Array")
78
+ end
79
+ end
80
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: koremutake
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gunnar Wolf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-05-21 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: "For us humans, it's always easier to remember a pronounceable string, even if it is meaningless, than to remember a long number. Koremutake is a system you can use to translate any number (of course, particularly suited at long numbers) to a sequence of syllables. Typical uses of Koremutake strings are auto-generated user passwords or URLs. This module is based in Leon Brocard's String::Koremutake Perl module, available at http://search.cpan.org/dist/String-Koremutake/lib/String/Koremutake.pm which is, in turn, based upon Shorl (http://shorl.com/koremutake.php). Koremutake is a \xC2\xABway to express any large number as a sequence of syllables\xC2\xBB, and the general idea is based in Sean B. Palmer's \xC2\xABMemorable Random String\xC2\xBB term, http://infomesh.net/2001/07/MeRS/"
17
+ email: gwolf@gwolf.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - test/koremutake_conversions_test.rb
26
+ - lib/koremu.rb
27
+ - Manifest.txt
28
+ - LICENSE
29
+ - README
30
+ - CHANGELOG
31
+ has_rdoc: true
32
+ homepage: http://koremutake.rubyforge.org/
33
+ post_install_message:
34
+ rdoc_options:
35
+ - --line-numbers
36
+ - --inline-source
37
+ - charset
38
+ - utf-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project: koremutake
56
+ rubygems_version: 1.2.0
57
+ signing_key:
58
+ specification_version: 2
59
+ summary: Ruby implementation of the Koremutake Memorable Random Strings
60
+ test_files: []
61
+