summaryrefslogtreecommitdiff
path: root/spec/map_decoding_spec.rb
blob: 032ca04a73e8b55cedd5c6c3f95ff7d712e86afd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<<-DOC
A top secret message containing uppercase letters from 'A' to 'Z' has been encoded as numbers using the following mapping:

'A' -> 1
'B' -> 2
...
'Z' -> 26
You are an FBI agent and you need to determine the total number of ways that the message can be decoded.

Since the answer could be very large, take it modulo 10^9 + 7.

Example

For message = "123", the output should be

mapDecoding(message) = 3.

"123" can be decoded as "ABC" (1 2 3), "LC" (12 3) or "AW" (1 23), so the total number of ways is 3.

Input/Output

[time limit] 4000ms (rb)
[input] string message

A string containing only digits.

Guaranteed constraints:

0 ≤ message.length ≤ 105.

[output] integer

The total number of ways to decode the given message.
DOC

describe "map_decoding" do
  <<-THINK
  "abc"

   |1|2|3|
  1|a|b|c|
  2|L|W|-|
  3|-|-|-|

  |1|2|3|
  |2|2|1|

  10122110
  10|12|21|10
  10|12|2|1|10
  10|1|22|1|10
  10|1|2|21|10
  10|1|2|2|1|10

  [1, 2, 3]

  [1], [2, 3]  [1, 2, 3]
  [2], [3]     [2], [3]
  [3]          [3]


  THINK
  def map_decoding(message)
    puts [message].inspect
    if message.size == 1
      return (0..26).include?(message[0].to_i - 1) ? 1 : 0
    end

    count = 0
    results = []
    (message.size - 1).downto(0) do |i|
      tail = message[i].to_i
      combined = message[i-1..i].to_i
      head = message[i - 1].to_i

      if tail == 0
        return 0 if combined < 0 || combined >= 26
        results.push(combined)
      else
        if head >= 0 && head < 26
          count += 1
          results << tail
        end
      end
      puts results.inspect

      i += 1
    end

    modulo = (10 ** 9) + 7
    count % modulo
  end

  def decode(chars, rest = [])
    #puts [chars, rest].inspect
    return chars if rest.empty?

    results = []
    first = rest[0]
    results.push(decode([first], rest[1..rest.size]))

    second = rest[1]
    results.push(decode([first + second], rest[2..rest.size])) if second
    results
  end

  def map_decoding(message)
    decode([], message.chars)
  end

  # dp[n] = dp[n - 1] + dp[n - 2] if [x,y] <= 26
  # dp[n] = dp[n - 1]
  def map_decoding(message)
    puts message.inspect
    dp = [1]

    return message[0].to_i > 0 ? 1 : 0 if message.size == 1

    1.upto(message.size - 1) do |n|
      x, y = message[n - 1], message[n]
      z = (x + y).to_i
      puts [x, y].join.inspect
      if x != "0" && z <= 26
        dp[n] = dp[n - 1] + dp[n - 2]
      else
        if y.to_i > 0
          dp[n] = dp[n - 1]
        else
          dp[n] = 0
        end
      end
      puts dp.inspect
    end
    modulo = (10 ** 9) + 7
    dp.last % modulo
  end

  [
    { message: "123", expected: 3 },
    { message: "12", expected: 2 },
    { message: "0", expected: 0 },
    { message: "1", expected: 1 },
    { message: "11", expected: 2 },
    { message: "301", expected: 0 },
    { message: "1001", expected: 0 },
    { message: "10122110", expected: 5 },
    { message: "", expected: 1 },
    { message: "11115112112", expected: 104 },
    { message: "2871221111122261", expected: 233 },
    { message: "1221112111122221211221221212212212111221222212122221222112122212121212221212122221211112212212211211", expected: 782204094 },
  ].each do |x|
    it do
      expect(map_decoding(x[:message])).to eql(x[:expected])
    end
  end
end