zxcvbn-ruby 1.2.0 → 1.2.2

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -1
  3. data/README.md +1 -1
  4. data/lib/zxcvbn/clock.rb +11 -0
  5. data/lib/zxcvbn/crack_time.rb +4 -2
  6. data/lib/zxcvbn/data.rb +6 -4
  7. data/lib/zxcvbn/dictionary_ranker.rb +2 -0
  8. data/lib/zxcvbn/entropy.rb +38 -33
  9. data/lib/zxcvbn/feedback.rb +2 -0
  10. data/lib/zxcvbn/feedback_giver.rb +2 -0
  11. data/lib/zxcvbn/match.rb +2 -0
  12. data/lib/zxcvbn/matchers/date.rb +11 -8
  13. data/lib/zxcvbn/matchers/dictionary.rb +3 -1
  14. data/lib/zxcvbn/matchers/digits.rb +2 -0
  15. data/lib/zxcvbn/matchers/l33t.rb +6 -2
  16. data/lib/zxcvbn/matchers/new_l33t.rb +7 -4
  17. data/lib/zxcvbn/matchers/regex_helpers.rb +2 -0
  18. data/lib/zxcvbn/matchers/repeat.rb +3 -1
  19. data/lib/zxcvbn/matchers/sequences.rb +4 -2
  20. data/lib/zxcvbn/matchers/spatial.rb +5 -3
  21. data/lib/zxcvbn/matchers/year.rb +3 -1
  22. data/lib/zxcvbn/math.rb +3 -0
  23. data/lib/zxcvbn/omnimatch.rb +3 -1
  24. data/lib/zxcvbn/password_strength.rb +5 -3
  25. data/lib/zxcvbn/score.rb +3 -1
  26. data/lib/zxcvbn/scorer.rb +11 -7
  27. data/lib/zxcvbn/version.rb +1 -1
  28. data/lib/zxcvbn.rb +2 -0
  29. metadata +6 -102
  30. data/.github/workflows/ci.yml +0 -23
  31. data/.gitignore +0 -18
  32. data/.rspec +0 -1
  33. data/CODE_OF_CONDUCT.md +0 -130
  34. data/Gemfile +0 -10
  35. data/Guardfile +0 -26
  36. data/Rakefile +0 -22
  37. data/spec/dictionary_ranker_spec.rb +0 -12
  38. data/spec/feedback_giver_spec.rb +0 -212
  39. data/spec/matchers/date_spec.rb +0 -109
  40. data/spec/matchers/dictionary_spec.rb +0 -30
  41. data/spec/matchers/digits_spec.rb +0 -15
  42. data/spec/matchers/l33t_spec.rb +0 -87
  43. data/spec/matchers/repeat_spec.rb +0 -18
  44. data/spec/matchers/sequences_spec.rb +0 -21
  45. data/spec/matchers/spatial_spec.rb +0 -20
  46. data/spec/matchers/year_spec.rb +0 -15
  47. data/spec/omnimatch_spec.rb +0 -24
  48. data/spec/scorer_spec.rb +0 -5
  49. data/spec/scoring/crack_time_spec.rb +0 -106
  50. data/spec/scoring/entropy_spec.rb +0 -216
  51. data/spec/scoring/math_spec.rb +0 -135
  52. data/spec/spec_helper.rb +0 -54
  53. data/spec/support/js_helpers.rb +0 -34
  54. data/spec/support/js_source/adjacency_graphs.js +0 -8
  55. data/spec/support/js_source/compiled.js +0 -1188
  56. data/spec/support/js_source/frequency_lists.js +0 -10
  57. data/spec/support/js_source/init.coffee +0 -63
  58. data/spec/support/js_source/init.js +0 -95
  59. data/spec/support/js_source/matching.coffee +0 -444
  60. data/spec/support/js_source/matching.js +0 -685
  61. data/spec/support/js_source/scoring.coffee +0 -270
  62. data/spec/support/js_source/scoring.js +0 -390
  63. data/spec/support/matcher.rb +0 -35
  64. data/spec/tester_spec.rb +0 -99
  65. data/spec/zxcvbn_spec.rb +0 -24
  66. data/zxcvbn-ruby.gemspec +0 -33
@@ -1,135 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Zxcvbn::Math do
4
- include Zxcvbn::Math
5
-
6
- def data
7
- Zxcvbn::Data.new
8
- end
9
-
10
- describe '#bruteforce_cardinality' do
11
- context 'when empty password' do
12
- it 'should return 0 if empty password' do
13
- expect(bruteforce_cardinality('')).to eql 0
14
- end
15
- end
16
-
17
- context 'when password is one character long' do
18
- context 'and a digit' do
19
- it 'should return 10' do
20
- (0..9).each do |digit|
21
- expect(bruteforce_cardinality(digit.to_s)).to eql 10
22
- end
23
- end
24
- end
25
-
26
- context 'and an upper case character' do
27
- it 'should return 26' do
28
- ('A'..'Z').each do |character|
29
- expect(bruteforce_cardinality(character)).to eql 26
30
- end
31
- end
32
- end
33
-
34
- context 'and a lower case character' do
35
- it 'should return 26' do
36
- ('a'..'z').each do |character|
37
- expect(bruteforce_cardinality(character)).to eql 26
38
- end
39
- end
40
- end
41
-
42
- context 'and a symbol' do
43
- it 'should return 33' do
44
- %w|/ [ ` {|.each do |symbol|
45
- expect(bruteforce_cardinality(symbol)).to eql 33
46
- end
47
- end
48
- end
49
- end
50
-
51
- context 'when password is more than one character long' do
52
- context 'and only digits' do
53
- it 'should return 10' do
54
- expect(bruteforce_cardinality('123456789')).to eql 10
55
- end
56
- end
57
-
58
- context 'and only lowercase characters' do
59
- it 'should return 26' do
60
- expect(bruteforce_cardinality('password')).to eql 26
61
- end
62
- end
63
-
64
- context 'and only uppercase characters' do
65
- it 'should return 26' do
66
- expect(bruteforce_cardinality('PASSWORD')).to eql 26
67
- end
68
- end
69
-
70
- context 'and only symbols' do
71
- it 'should return 33' do
72
- expect(bruteforce_cardinality('/ [ ` {')).to eql 33
73
- end
74
- end
75
-
76
- context 'and a mixed of character types' do
77
- it 'should add up every character type cardinality' do
78
- expect(bruteforce_cardinality('p1SsWorD!')).to eql 95
79
- end
80
- end
81
- end
82
- end
83
-
84
- describe '#average_degree_for_graph' do
85
- context 'when keyboard is qwerty' do
86
- it 'returns the correct average degree over all keys' do
87
- expect(average_degree_for_graph('qwerty')).to eql 4.595744680851064
88
- end
89
- end
90
-
91
- context 'when keyboard is dvorak' do
92
- it 'returns the correct average degree over all keys' do
93
- expect(average_degree_for_graph('dvorak')).to eql 4.595744680851064
94
- end
95
- end
96
-
97
- context 'when keyboard is keypad' do
98
- it 'returns the correct average degree over all keys' do
99
- expect(average_degree_for_graph('keypad')).to eql 5.066666666666666
100
- end
101
- end
102
-
103
- context 'when keyboard is mac keypad' do
104
- it 'returns the correct average degree over all keys' do
105
- expect(average_degree_for_graph('mac_keypad')).to eql 5.25
106
- end
107
- end
108
- end
109
-
110
- describe '#starting_positions_for_graph' do
111
- context 'when keyboard is qwerty' do
112
- it 'returns the correct average degree over all keys' do
113
- expect(starting_positions_for_graph('qwerty')).to eql 94
114
- end
115
- end
116
-
117
- context 'when keyboard is dvorak' do
118
- it 'returns the correct average degree over all keys' do
119
- expect(starting_positions_for_graph('dvorak')).to eql 94
120
- end
121
- end
122
-
123
- context 'when keyboard is keypad' do
124
- it 'returns the correct average degree over all keys' do
125
- expect(starting_positions_for_graph('keypad')).to eql 15
126
- end
127
- end
128
-
129
- context 'when keyboard is mac keypad' do
130
- it 'returns the correct average degree over all keys' do
131
- expect(starting_positions_for_graph('mac_keypad')).to eql 16
132
- end
133
- end
134
- end
135
- end
data/spec/spec_helper.rb DELETED
@@ -1,54 +0,0 @@
1
- require 'bundler/setup'
2
- require 'rspec'
3
- require 'zxcvbn'
4
-
5
- Dir[Pathname.new(File.expand_path('../', __FILE__)).join('support/**/*.rb')].each {|f| require f}
6
-
7
- RSpec.configure do |config|
8
- config.include JsHelpers
9
- end
10
-
11
- TEST_PASSWORDS = [
12
- 'zxcvbn',
13
- 'qwER43@!',
14
- 'Tr0ub4dour&3',
15
- 'correcthorsebatterystaple',
16
- 'coRrecth0rseba++ery9.23.2007staple$',
17
-
18
- 'D0g..................',
19
- 'abcdefghijk987654321',
20
- 'neverforget13/3/1997',
21
- '1qaz2wsx3edc',
22
-
23
- 'temppass22',
24
- 'briansmith',
25
- 'briansmith4mayor',
26
- 'password1',
27
- 'viking',
28
- 'thx1138',
29
- 'ScoRpi0ns',
30
- 'do you know',
31
-
32
- 'ryanhunter2000',
33
- 'rianhunter2000',
34
-
35
- 'asdfghju7654rewq',
36
- 'AOEUIDHG&*()LS_',
37
-
38
- '12345678',
39
- 'defghi6789',
40
-
41
- 'rosebud',
42
- 'Rosebud',
43
- 'ROSEBUD',
44
- 'rosebuD',
45
- 'ros3bud99',
46
- 'r0s3bud99',
47
- 'R0$38uD99',
48
-
49
- 'verlineVANDERMARK',
50
-
51
- 'eheuczkqyq',
52
- 'rWibMFACxAUGZmxhVncy',
53
- 'Ba9ZyWABu99[BK#6MBgbH88Tofv)vs$w'
54
- ]
@@ -1,34 +0,0 @@
1
- require 'mini_racer'
2
- require 'json'
3
-
4
- module JsHelpers
5
- class JsMethodInvoker
6
- JS_SOURCE_PATH = Pathname(File.expand_path('../js_source/', __FILE__))
7
-
8
- def initialize
9
- @ctx = MiniRacer::Context.new
10
- @ctx.eval(JS_SOURCE_PATH.join('compiled.js').read)
11
- end
12
-
13
- def eval(string)
14
- @ctx.eval(string)
15
- end
16
-
17
- def eval_convert_object(string)
18
- serialized = eval("JSON.stringify(#{string})")
19
- JSON.parse(serialized)
20
- end
21
- end
22
-
23
- def method_invoker
24
- $method_invoker ||= JsMethodInvoker.new
25
- end
26
-
27
- def run_js(javascript)
28
- method_invoker.eval_convert_object(javascript)
29
- end
30
-
31
- def js_zxcvbn(password)
32
- run_js("zxcvbn('#{password}')")
33
- end
34
- end
@@ -1,8 +0,0 @@
1
- var qwerty = {"!": ["`~", null, null, "2@", "qQ", null], "\"": [";:", "[{", "]}", null, null, "/?"], "#": ["2@", null, null, "4$", "eE", "wW"], "$": ["3#", null, null, "5%", "rR", "eE"], "%": ["4$", null, null, "6^", "tT", "rR"], "&": ["6^", null, null, "8*", "uU", "yY"], "'": [";:", "[{", "]}", null, null, "/?"], "(": ["8*", null, null, "0)", "oO", "iI"], ")": ["9(", null, null, "-_", "pP", "oO"], "*": ["7&", null, null, "9(", "iI", "uU"], "+": ["-_", null, null, null, "]}", "[{"], ",": ["mM", "kK", "lL", ".>", null, null], "-": ["0)", null, null, "=+", "[{", "pP"], ".": [",<", "lL", ";:", "/?", null, null], "/": [".>", ";:", "'\"", null, null, null], "0": ["9(", null, null, "-_", "pP", "oO"], "1": ["`~", null, null, "2@", "qQ", null], "2": ["1!", null, null, "3#", "wW", "qQ"], "3": ["2@", null, null, "4$", "eE", "wW"], "4": ["3#", null, null, "5%", "rR", "eE"], "5": ["4$", null, null, "6^", "tT", "rR"], "6": ["5%", null, null, "7&", "yY", "tT"], "7": ["6^", null, null, "8*", "uU", "yY"], "8": ["7&", null, null, "9(", "iI", "uU"], "9": ["8*", null, null, "0)", "oO", "iI"], ":": ["lL", "pP", "[{", "'\"", "/?", ".>"], ";": ["lL", "pP", "[{", "'\"", "/?", ".>"], "<": ["mM", "kK", "lL", ".>", null, null], "=": ["-_", null, null, null, "]}", "[{"], ">": [",<", "lL", ";:", "/?", null, null], "?": [".>", ";:", "'\"", null, null, null], "@": ["1!", null, null, "3#", "wW", "qQ"], "A": [null, "qQ", "wW", "sS", "zZ", null], "B": ["vV", "gG", "hH", "nN", null, null], "C": ["xX", "dD", "fF", "vV", null, null], "D": ["sS", "eE", "rR", "fF", "cC", "xX"], "E": ["wW", "3#", "4$", "rR", "dD", "sS"], "F": ["dD", "rR", "tT", "gG", "vV", "cC"], "G": ["fF", "tT", "yY", "hH", "bB", "vV"], "H": ["gG", "yY", "uU", "jJ", "nN", "bB"], "I": ["uU", "8*", "9(", "oO", "kK", "jJ"], "J": ["hH", "uU", "iI", "kK", "mM", "nN"], "K": ["jJ", "iI", "oO", "lL", ",<", "mM"], "L": ["kK", "oO", "pP", ";:", ".>", ",<"], "M": ["nN", "jJ", "kK", ",<", null, null], "N": ["bB", "hH", "jJ", "mM", null, null], "O": ["iI", "9(", "0)", "pP", "lL", "kK"], "P": ["oO", "0)", "-_", "[{", ";:", "lL"], "Q": [null, "1!", "2@", "wW", "aA", null], "R": ["eE", "4$", "5%", "tT", "fF", "dD"], "S": ["aA", "wW", "eE", "dD", "xX", "zZ"], "T": ["rR", "5%", "6^", "yY", "gG", "fF"], "U": ["yY", "7&", "8*", "iI", "jJ", "hH"], "V": ["cC", "fF", "gG", "bB", null, null], "W": ["qQ", "2@", "3#", "eE", "sS", "aA"], "X": ["zZ", "sS", "dD", "cC", null, null], "Y": ["tT", "6^", "7&", "uU", "hH", "gG"], "Z": [null, "aA", "sS", "xX", null, null], "[": ["pP", "-_", "=+", "]}", "'\"", ";:"], "\\": ["]}", null, null, null, null, null], "]": ["[{", "=+", null, "\\|", null, "'\""], "^": ["5%", null, null, "7&", "yY", "tT"], "_": ["0)", null, null, "=+", "[{", "pP"], "`": [null, null, null, "1!", null, null], "a": [null, "qQ", "wW", "sS", "zZ", null], "b": ["vV", "gG", "hH", "nN", null, null], "c": ["xX", "dD", "fF", "vV", null, null], "d": ["sS", "eE", "rR", "fF", "cC", "xX"], "e": ["wW", "3#", "4$", "rR", "dD", "sS"], "f": ["dD", "rR", "tT", "gG", "vV", "cC"], "g": ["fF", "tT", "yY", "hH", "bB", "vV"], "h": ["gG", "yY", "uU", "jJ", "nN", "bB"], "i": ["uU", "8*", "9(", "oO", "kK", "jJ"], "j": ["hH", "uU", "iI", "kK", "mM", "nN"], "k": ["jJ", "iI", "oO", "lL", ",<", "mM"], "l": ["kK", "oO", "pP", ";:", ".>", ",<"], "m": ["nN", "jJ", "kK", ",<", null, null], "n": ["bB", "hH", "jJ", "mM", null, null], "o": ["iI", "9(", "0)", "pP", "lL", "kK"], "p": ["oO", "0)", "-_", "[{", ";:", "lL"], "q": [null, "1!", "2@", "wW", "aA", null], "r": ["eE", "4$", "5%", "tT", "fF", "dD"], "s": ["aA", "wW", "eE", "dD", "xX", "zZ"], "t": ["rR", "5%", "6^", "yY", "gG", "fF"], "u": ["yY", "7&", "8*", "iI", "jJ", "hH"], "v": ["cC", "fF", "gG", "bB", null, null], "w": ["qQ", "2@", "3#", "eE", "sS", "aA"], "x": ["zZ", "sS", "dD", "cC", null, null], "y": ["tT", "6^", "7&", "uU", "hH", "gG"], "z": [null, "aA", "sS", "xX", null, null], "{": ["pP", "-_", "=+", "]}", "'\"", ";:"], "|": ["]}", null, null, null, null, null], "}": ["[{", "=+", null, "\\|", null, "'\""], "~": [null, null, null, "1!", null, null]};
2
-
3
- var dvorak = {"!": ["`~", null, null, "2@", "'\"", null], "\"": [null, "1!", "2@", ",<", "aA", null], "#": ["2@", null, null, "4$", ".>", ",<"], "$": ["3#", null, null, "5%", "pP", ".>"], "%": ["4$", null, null, "6^", "yY", "pP"], "&": ["6^", null, null, "8*", "gG", "fF"], "'": [null, "1!", "2@", ",<", "aA", null], "(": ["8*", null, null, "0)", "rR", "cC"], ")": ["9(", null, null, "[{", "lL", "rR"], "*": ["7&", null, null, "9(", "cC", "gG"], "+": ["/?", "]}", null, "\\|", null, "-_"], ",": ["'\"", "2@", "3#", ".>", "oO", "aA"], "-": ["sS", "/?", "=+", null, null, "zZ"], ".": [",<", "3#", "4$", "pP", "eE", "oO"], "/": ["lL", "[{", "]}", "=+", "-_", "sS"], "0": ["9(", null, null, "[{", "lL", "rR"], "1": ["`~", null, null, "2@", "'\"", null], "2": ["1!", null, null, "3#", ",<", "'\""], "3": ["2@", null, null, "4$", ".>", ",<"], "4": ["3#", null, null, "5%", "pP", ".>"], "5": ["4$", null, null, "6^", "yY", "pP"], "6": ["5%", null, null, "7&", "fF", "yY"], "7": ["6^", null, null, "8*", "gG", "fF"], "8": ["7&", null, null, "9(", "cC", "gG"], "9": ["8*", null, null, "0)", "rR", "cC"], ":": [null, "aA", "oO", "qQ", null, null], ";": [null, "aA", "oO", "qQ", null, null], "<": ["'\"", "2@", "3#", ".>", "oO", "aA"], "=": ["/?", "]}", null, "\\|", null, "-_"], ">": [",<", "3#", "4$", "pP", "eE", "oO"], "?": ["lL", "[{", "]}", "=+", "-_", "sS"], "@": ["1!", null, null, "3#", ",<", "'\""], "A": [null, "'\"", ",<", "oO", ";:", null], "B": ["xX", "dD", "hH", "mM", null, null], "C": ["gG", "8*", "9(", "rR", "tT", "hH"], "D": ["iI", "fF", "gG", "hH", "bB", "xX"], "E": ["oO", ".>", "pP", "uU", "jJ", "qQ"], "F": ["yY", "6^", "7&", "gG", "dD", "iI"], "G": ["fF", "7&", "8*", "cC", "hH", "dD"], "H": ["dD", "gG", "cC", "tT", "mM", "bB"], "I": ["uU", "yY", "fF", "dD", "xX", "kK"], "J": ["qQ", "eE", "uU", "kK", null, null], "K": ["jJ", "uU", "iI", "xX", null, null], "L": ["rR", "0)", "[{", "/?", "sS", "nN"], "M": ["bB", "hH", "tT", "wW", null, null], "N": ["tT", "rR", "lL", "sS", "vV", "wW"], "O": ["aA", ",<", ".>", "eE", "qQ", ";:"], "P": [".>", "4$", "5%", "yY", "uU", "eE"], "Q": [";:", "oO", "eE", "jJ", null, null], "R": ["cC", "9(", "0)", "lL", "nN", "tT"], "S": ["nN", "lL", "/?", "-_", "zZ", "vV"], "T": ["hH", "cC", "rR", "nN", "wW", "mM"], "U": ["eE", "pP", "yY", "iI", "kK", "jJ"], "V": ["wW", "nN", "sS", "zZ", null, null], "W": ["mM", "tT", "nN", "vV", null, null], "X": ["kK", "iI", "dD", "bB", null, null], "Y": ["pP", "5%", "6^", "fF", "iI", "uU"], "Z": ["vV", "sS", "-_", null, null, null], "[": ["0)", null, null, "]}", "/?", "lL"], "\\": ["=+", null, null, null, null, null], "]": ["[{", null, null, null, "=+", "/?"], "^": ["5%", null, null, "7&", "fF", "yY"], "_": ["sS", "/?", "=+", null, null, "zZ"], "`": [null, null, null, "1!", null, null], "a": [null, "'\"", ",<", "oO", ";:", null], "b": ["xX", "dD", "hH", "mM", null, null], "c": ["gG", "8*", "9(", "rR", "tT", "hH"], "d": ["iI", "fF", "gG", "hH", "bB", "xX"], "e": ["oO", ".>", "pP", "uU", "jJ", "qQ"], "f": ["yY", "6^", "7&", "gG", "dD", "iI"], "g": ["fF", "7&", "8*", "cC", "hH", "dD"], "h": ["dD", "gG", "cC", "tT", "mM", "bB"], "i": ["uU", "yY", "fF", "dD", "xX", "kK"], "j": ["qQ", "eE", "uU", "kK", null, null], "k": ["jJ", "uU", "iI", "xX", null, null], "l": ["rR", "0)", "[{", "/?", "sS", "nN"], "m": ["bB", "hH", "tT", "wW", null, null], "n": ["tT", "rR", "lL", "sS", "vV", "wW"], "o": ["aA", ",<", ".>", "eE", "qQ", ";:"], "p": [".>", "4$", "5%", "yY", "uU", "eE"], "q": [";:", "oO", "eE", "jJ", null, null], "r": ["cC", "9(", "0)", "lL", "nN", "tT"], "s": ["nN", "lL", "/?", "-_", "zZ", "vV"], "t": ["hH", "cC", "rR", "nN", "wW", "mM"], "u": ["eE", "pP", "yY", "iI", "kK", "jJ"], "v": ["wW", "nN", "sS", "zZ", null, null], "w": ["mM", "tT", "nN", "vV", null, null], "x": ["kK", "iI", "dD", "bB", null, null], "y": ["pP", "5%", "6^", "fF", "iI", "uU"], "z": ["vV", "sS", "-_", null, null, null], "{": ["0)", null, null, "]}", "/?", "lL"], "|": ["=+", null, null, null, null, null], "}": ["[{", null, null, null, "=+", "/?"], "~": [null, null, null, "1!", null, null]};
4
-
5
- var keypad = {"*": ["/", null, null, null, "-", "+", "9", "8"], "+": ["9", "*", "-", null, null, null, null, "6"], "-": ["*", null, null, null, null, null, "+", "9"], ".": ["0", "2", "3", null, null, null, null, null], "/": [null, null, null, null, "*", "9", "8", "7"], "0": [null, "1", "2", "3", ".", null, null, null], "1": [null, null, "4", "5", "2", "0", null, null], "2": ["1", "4", "5", "6", "3", ".", "0", null], "3": ["2", "5", "6", null, null, null, ".", "0"], "4": [null, null, "7", "8", "5", "2", "1", null], "5": ["4", "7", "8", "9", "6", "3", "2", "1"], "6": ["5", "8", "9", "+", null, null, "3", "2"], "7": [null, null, null, "/", "8", "5", "4", null], "8": ["7", null, "/", "*", "9", "6", "5", "4"], "9": ["8", "/", "*", "-", "+", null, "6", "5"]};
6
-
7
- var mac_keypad = {"*": ["/", null, null, null, null, null, "-", "9"], "+": ["6", "9", "-", null, null, null, null, "3"], "-": ["9", "/", "*", null, null, null, "+", "6"], ".": ["0", "2", "3", null, null, null, null, null], "/": ["=", null, null, null, "*", "-", "9", "8"], "0": [null, "1", "2", "3", ".", null, null, null], "1": [null, null, "4", "5", "2", "0", null, null], "2": ["1", "4", "5", "6", "3", ".", "0", null], "3": ["2", "5", "6", "+", null, null, ".", "0"], "4": [null, null, "7", "8", "5", "2", "1", null], "5": ["4", "7", "8", "9", "6", "3", "2", "1"], "6": ["5", "8", "9", "-", "+", null, "3", "2"], "7": [null, null, null, "=", "8", "5", "4", null], "8": ["7", null, "=", "/", "9", "6", "5", "4"], "9": ["8", "=", "/", "*", "-", "+", "6", "5"], "=": [null, null, null, null, "/", "9", "8", "7"]};
8
-