mnemonicker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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