koremutake 0.1.0

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.
@@ -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
+