mnemonicker 0.0.1

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,5 @@
1
+ # Mnemonicker History
2
+
3
+ ## 0.0.1 - 14 April 2013 (3feddee)
4
+
5
+ * Initial release
@@ -0,0 +1,71 @@
1
+ Mnemonicker
2
+ ===========
3
+
4
+ An encoder and decoder for the [mnemonic major system][major-system] for
5
+ remembering numbers.
6
+
7
+ [major-system]: https://en.wikipedia.org/wiki/Mnemonic_major_system
8
+
9
+ Usage
10
+ -----
11
+
12
+ ```
13
+ > gem install mnemonicker
14
+ > mnemonicker
15
+
16
+ Commands
17
+
18
+ encode [number] - Suggest words that can represent the number
19
+ decode [*words] - Convert words to numbers
20
+ update - Download latest wordlist
21
+ help - This output
22
+
23
+ System
24
+
25
+ Each number maps to a group of similar sounds, which you can then make
26
+ a sentence out of that is easier to remember than the numbers themself.
27
+
28
+ # | Sound | Way to remember
29
+ --+-----------+---------------------------
30
+ 0 | s, z | z is the first letter of zero
31
+ 1 | t, th, t | t & d have one downstroke
32
+ 2 | n | n has two downstrokes
33
+ 3 | m | m has three downstrokes
34
+ 4 | r | r is the last character of four
35
+ 5 | l | L is the roman numeral for 50
36
+ 6 | sh, ch, j | I just remember this one
37
+ 7 | k | K contains two sevens back to back
38
+ 8 | f, v | Script f looks like an 8
39
+ 9 | p, b | p and b both very similar shape to 9
40
+
41
+ Any sounds not in this list (vowels, "w", "h", "x") are "free" and do not
42
+ represent anything.
43
+
44
+ > mnemonicker encode 314
45
+ emitter
46
+ matter
47
+ meter
48
+ mother
49
+ motor
50
+ > mnemonicker decode mother
51
+ 314
52
+ > mnemonicker decode a man a plan a canal panama
53
+ 32952725923
54
+ ```
55
+
56
+ Known Issues
57
+ ------------
58
+
59
+ Mnemonicker uses the [Double Metaphone][double-metaphone] phonetic encoding algorithm, which causes some limitations:
60
+
61
+ * Does not decode long words correctly. For instance, "hindquarters" and
62
+ "manufacturing" are both a number of digits short.
63
+ * Certain words with odd pronunciation (such as "enough") are incorrectly
64
+ decoded.
65
+
66
+ Additionally, the current word list is somewhat anemic.
67
+
68
+ That said, the goal of this project is to spark your imagination. Only you can
69
+ combine words in a way that is memorable to you!
70
+
71
+ [double-metaphone]: https://en.wikipedia.org/wiki/Metaphone
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mnemonicker/cli'
4
+
5
+ result = Mnemonicker::CLI.run(*ARGV)
6
+
7
+ exit(1) unless result
@@ -0,0 +1,2 @@
1
+ require 'mnemonicker/major_system'
2
+ require 'mnemonicker/word_list'
@@ -0,0 +1,100 @@
1
+ require 'json'
2
+ require 'fileutils'
3
+ require 'net/http'
4
+
5
+ require 'rubyfish'
6
+
7
+ require 'mnemonicker/major_system'
8
+ require 'mnemonicker/word_list'
9
+
10
+ module Mnemonicker
11
+ class CLI
12
+ def self.run(*args)
13
+ cmd = args.shift
14
+ cmd ||= 'help'
15
+ cmd = cmd[0].upcase + cmd[1..-1]
16
+ handler = Commands.const_get(cmd)
17
+ handler.new.process(*args)
18
+ rescue NameError
19
+ Commands::Help.new.process
20
+ end
21
+ end
22
+
23
+ module Commands
24
+ class Update
25
+ def process
26
+ Mnemonicker::WordList.new('cli').update do |file, count|
27
+ puts "%s...%i words" % [file, count]
28
+ end
29
+ end
30
+ end
31
+
32
+ class Encode
33
+ def process(number)
34
+ tried = false
35
+ list = WordList.new('cli')
36
+ wordlist = begin
37
+ list.fetch
38
+ rescue WordList::ListNotFound
39
+ if tried
40
+ raise
41
+ else
42
+ tried = true
43
+ $stderr.puts "No word list found, downloading..."
44
+ list.update
45
+ retry
46
+ end
47
+ end
48
+
49
+ candidates = wordlist['words'][number]
50
+
51
+ puts candidates.sort if candidates
52
+ true
53
+ end
54
+ end
55
+
56
+ class Decode
57
+ def process(*words)
58
+ words.each do |word|
59
+ puts MajorSystem.word_to_number(word)
60
+ end
61
+ end
62
+ end
63
+
64
+ class Help
65
+ def process
66
+ $stderr.puts <<-EOS
67
+
68
+ Commands
69
+
70
+ encode [number] - Suggest words that can represent the number
71
+ decode [*words] - Convert words to numbers
72
+ update - Download latest wordlist
73
+ help - This output
74
+
75
+ System
76
+
77
+ Each number maps to a group of similar sounds, which you can then make
78
+ a sentence out of that is easier to remember than the numbers themself.
79
+
80
+ # | Sound | Way to remember
81
+ --+-----------+---------------------------
82
+ 0 | s, z | z is the first letter of zero
83
+ 1 | t, th, t | t & d have one downstroke
84
+ 2 | n | n has two downstrokes
85
+ 3 | m | m has three downstrokes
86
+ 4 | r | r is the last character of four
87
+ 5 | l | L is the roman numeral for 50
88
+ 6 | sh, ch, j | I just remember this one
89
+ 7 | k | K contains two sevens back to back
90
+ 8 | f, v | Script f looks like an 8
91
+ 9 | p, b | p and b both very similar shape to 9
92
+
93
+ Any sounds not in this list (vowels, "w", "h", "x") are "free" and do not
94
+ represent anything.
95
+
96
+ EOS
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,43 @@
1
+ module Mnemonicker
2
+ class MajorSystem
3
+ MAPPINGS = {
4
+ 'S' => 0,
5
+ '0' => 1,
6
+ 'T' => 1,
7
+ 'D' => 1,
8
+ 'N' => 2,
9
+ 'M' => 3,
10
+ 'R' => 4,
11
+ 'L' => 5,
12
+ 'J' => 6,
13
+ 'K' => 7,
14
+ 'F' => 8,
15
+ 'V' => 8,
16
+ 'P' => 9,
17
+ 'B' => 9,
18
+ 'X' => 6,
19
+ 'A' => nil,
20
+ 'W' => nil,
21
+ 'H' => nil
22
+ }
23
+
24
+ def self.word_to_number(word)
25
+ # Metaphone is insufficient since it has a maximum length of six, which
26
+ # does not work for long words like "hindquarters" or "manufacturing".
27
+ #
28
+ # Best phonetic algorithm I have found though.
29
+ metaphone = RubyFish::DoubleMetaphone.phonetic_code(word)[0]
30
+ metaphone.gsub!(/KS$/, "") # fox => FKS => F
31
+ metaphone.gsub!(/RNK$/, "RK") # turing => TRNK => TRK
32
+ n = ""
33
+ metaphone.each_char do |c|
34
+ if MAPPINGS.has_key?(c)
35
+ n << MAPPINGS[c].to_s if MAPPINGS[c]
36
+ else
37
+ raise "No mapping for #{c}"
38
+ end
39
+ end
40
+ n
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ module Mnemonicker
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,46 @@
1
+ module Mnemonicker
2
+ class WordList < Struct.new(:key)
3
+ class ListNotFound < RuntimeError; end
4
+
5
+ def fetch
6
+ JSON.parse(File.read(cache_file))
7
+ rescue
8
+ raise ListNotFound
9
+ end
10
+
11
+ def update(&block)
12
+ wordlist = {
13
+ version: 1,
14
+ fetched_at: Time.now.utc,
15
+ 'words' => {}
16
+ }
17
+ index = fetch_url('index.html')
18
+ index.lines.each do |line|
19
+ line = line.chomp
20
+ words = fetch_url(line)
21
+ words.lines.each do |word|
22
+ word = word.chomp
23
+ number = MajorSystem.word_to_number(word)
24
+ wordlist['words'][number] ||= []
25
+ wordlist['words'][number] << word
26
+ end
27
+ if block
28
+ block.call(line, words.lines.count)
29
+ end
30
+ end
31
+
32
+ FileUtils.mkdir_p(File.dirname(cache_file))
33
+ File.open(cache_file, "w") {|f| f.write wordlist.to_json }
34
+ end
35
+
36
+ private
37
+
38
+ def cache_file
39
+ File.expand_path("~/.mnemonicker/#{key}.json")
40
+ end
41
+
42
+ def fetch_url(file)
43
+ Net::HTTP.get('xaviershay.github.io', '/mnemonicker-wordlist/' + file)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/mnemonicker/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Xavier Shay"]
6
+ gem.email = ["contact@xaviershay.com"]
7
+ gem.description =
8
+ %q{An aid for remembering numbers}
9
+ gem.summary = %q{
10
+ Encoder and decoder for the mnemonic major system for remembering numbers.
11
+ }
12
+ gem.homepage = "http://github.com/xaviershay/mnemonicker"
13
+
14
+ gem.executables = []
15
+ gem.required_ruby_version = '>= 1.9.0'
16
+ gem.files = Dir.glob("{test,lib}/**/*.rb") + %w(
17
+ README.md
18
+ HISTORY.md
19
+ mnemonicker.gemspec
20
+ )
21
+ gem.test_files = Dir.glob("test/**/*.rb")
22
+ gem.name = "mnemonicker"
23
+ gem.require_paths = ["lib"]
24
+ gem.bindir = "bin"
25
+ gem.executables << "mnemonicker"
26
+ gem.version = Mnemonicker::VERSION
27
+ gem.has_rdoc = false
28
+ gem.add_dependency 'rubyfish'
29
+ end
@@ -0,0 +1,29 @@
1
+ require 'minitest/autorun'
2
+
3
+ require 'mnemonicker/cli'
4
+
5
+ class MajorSystemTest < MiniTest::Unit::TestCase
6
+ {
7
+ wikipedia: { # From https://en.wikipedia.org/wiki/Mnemonic_major_system
8
+ "action" => '762',
9
+ "ghost" => '701',
10
+ 'missile' => '305',
11
+ 'mossy' => '30',
12
+ 'sail' => '05',
13
+ },
14
+ exceptions: {
15
+ "fox" => '8',
16
+ "turing" => '147',
17
+ },
18
+ known_bugs: {
19
+ "enough" => '27', # Should be 28
20
+ 'hindquarters' => '217' # Should be 2174140
21
+ }
22
+ }.each do |label, examples|
23
+ examples.each do |word, number|
24
+ define_method("test_#{label}_#{word}") do
25
+ assert_equal number, Mnemonicker::MajorSystem.word_to_number(word)
26
+ end
27
+ end
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mnemonicker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Xavier Shay
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rubyfish
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: An aid for remembering numbers
31
+ email:
32
+ - contact@xaviershay.com
33
+ executables:
34
+ - mnemonicker
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - test/major_system_test.rb
39
+ - lib/mnemonicker/cli.rb
40
+ - lib/mnemonicker/major_system.rb
41
+ - lib/mnemonicker/version.rb
42
+ - lib/mnemonicker/word_list.rb
43
+ - lib/mnemonicker.rb
44
+ - README.md
45
+ - HISTORY.md
46
+ - mnemonicker.gemspec
47
+ - bin/mnemonicker
48
+ homepage: http://github.com/xaviershay/mnemonicker
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: 1.9.0
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.23
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Encoder and decoder for the mnemonic major system for remembering numbers.
72
+ test_files:
73
+ - test/major_system_test.rb