我有一些莫尔斯密码,在字母之间失去了空格,我的挑战是找出信息是什么。到目前为止,我已经有点迷失了,因为可能有大量的组合。
这是我收到的所有信息。
输出将是英语-..-...-...-...-..-.-.-.-.-..-.-.-.-.-.-.-.-.-.-..-...-.
有人有聪明的解决方案吗?
发布于 2011-12-04 13:07:18
这并不是一个容易的问题,因为正如鲁哈克所指出的,对于给定的信息,有许多可行的句子。例如,‘杰克和吉尔上山’的编码和‘杰克和吉尔走凿’相同的编码。由于这两个句子都是语法句子,而且每个单词都是常见的,因此在不深入研究自然语言处理的情况下,如何选择一个或另一个(或40141055989476564163599不同的英语单词序列中的任何一个与这条信息具有相同编码的不同序列)并不明显。
无论如何,这里有一个动态规划的解决方案来解决寻找最短句子的问题(如果有平数的话,用最少的字符)。它还可以计算与给定消息具有相同编码的句子总数。它需要一个文件中的英文单词字典。
接下来的增强应该更好地衡量句子的可能性:也许是单词频率,莫尔斯中的假阳性率(例如,"I“是一个常见的单词,但它经常出现在摩尔斯代码序列的其他序列中)。棘手的部分将是制定一个好的分数函数,可以表达的方式,它可以计算,使用动态规划。
MORSE = dict(zip('ABCDEFGHIJKLMNOPQRSTUVWXYZ', [
'.-', '-...', '-.-.', '-..', '.', '..-.', '--.', '....',
'..', '.---', '-.-', '.-..', '--', '-.', '---', '.--.',
'--.-', '.-.', '...', '-', '..-', '...-', '.--', '-..-',
'-.--', '--..'
]))
# Read a file containing A-Z only English words, one per line.
WORDS = set(word.strip().upper() for word in open('dict.en').readlines())
# A set of all possible prefixes of English words.
PREFIXES = set(word[:j+1] for word in WORDS for j in xrange(len(word)))
def translate(msg, c_sep=' ', w_sep=' / '):
"""Turn a message (all-caps space-separated words) into morse code."""
return w_sep.join(c_sep.join(MORSE[c] for c in word)
for word in msg.split(' '))
def encode(msg):
"""Turn a message into timing-less morse code."""
return translate(msg, '', '')
def c_trans(morse):
"""Construct a map of char transitions.
The return value is a dict, mapping indexes into the morse code stream
to a dict of possible characters at that location to where they would go
in the stream. Transitions that lead to dead-ends are omitted.
"""
result = [{} for i in xrange(len(morse))]
for i_ in xrange(len(morse)):
i = len(morse) - i_ - 1
for c, m in MORSE.iteritems():
if i + len(m) < len(morse) and not result[i + len(m)]:
continue
if morse[i:i+len(m)] != m: continue
result[i][c] = i + len(m)
return result
def find_words(ctr, i, prefix=''):
"""Find all legal words starting from position i.
We generate all possible words starting from position i in the
morse code stream, assuming we already have the given prefix.
ctr is a char transition dict, as produced by c_trans.
"""
if prefix in WORDS:
yield prefix, i
if i == len(ctr): return
for c, j in ctr[i].iteritems():
if prefix + c in PREFIXES:
for w, j2 in find_words(ctr, j, prefix + c):
yield w, j2
def w_trans(ctr):
"""Like c_trans, but produce a word transition map."""
result = [{} for i in xrange(len(ctr))]
for i_ in xrange(len(ctr)):
i = len(ctr) - i_ - 1
for w, j in find_words(ctr, i):
if j < len(result) and not result[j]:
continue
result[i][w] = j
return result
def shortest_sentence(wt):
"""Given a word transition map, find the shortest possible sentence.
We find the sentence that uses the entire morse code stream, and has
the fewest number of words. If there are multiple sentences that
satisfy this, we return the one that uses the smallest number of
characters.
"""
result = [-1 for _ in xrange(len(wt))] + [0]
words = [None] * len(wt)
for i_ in xrange(len(wt)):
i = len(wt) - i_ - 1
for w, j in wt[i].iteritems():
if result[j] == -1: continue
if result[i] == -1 or result[j] + 1 + len(w) / 30.0 < result[i]:
result[i] = result[j] + 1 + len(w) / 30.0
words[i] = w
i = 0
result = []
while i < len(wt):
result.append(words[i])
i = wt[i][words[i]]
return result
def sentence_count(wt):
result = [0] * len(wt) + [1]
for i_ in xrange(len(wt)):
i = len(wt) - i_ - 1
for j in wt[i].itervalues():
result[i] += result[j]
return result[0]
msg = 'JACK AND JILL WENT UP THE HILL'
print sentence_count(w_trans(c_trans(encode(msg))))
print shortest_sentence(w_trans(c_trans(encode(msg))))发布于 2011-12-01 23:16:24
保持三样东西:到目前为止的单词列表,到目前为止的单词W,以及当前符号C。
现在,给出一个新的符号,比方说'-',我们用它扩展C(在这种情况下,我们得到‘.-’)。如果C是一个完整的字母(在本例中是' W '),我们可以选择将它添加到W中,或者通过添加更多的符号来继续扩展该字母。如果我们扩展W,我们可以选择将它添加到S(如果它是一个有效的单词),或者继续扩展它。
这是一种搜索,但大多数路径都会很快终止(只要W不是任何单词的有效前缀,就可以停止,而且只要C不是任何字母的前缀,就可以停止)。
为了提高效率,您可以使用动态编程来避免冗余工作,并使用尝试有效地测试前缀。
代码是什么样子的?省略函数“is_word”(测试字符串是否为英语单词)和“is_word_prefix”函数(测试字符串是否为任何有效单词的开头),如下所示:
morse = {
'.-': 'A',
'-...': 'B',
etc.
}
def is_morse_prefix(C):
return any(k.startswith(C) for k in morse)
def break_words(input, S, W, C):
while True:
if not input:
if W == C == '':
yield S
return
i, input = input[0], input[1:]
C += i
if not is_morse_prefix(C):
return
ch = morse.get(C, None)
if ch is None or not is_word_prefix(W + ch):
continue
for result in break_words(input, S, W + ch, ''):
yield result
if is_word(W + ch):
for result in break_words(input, S + ' ' + W + ch, '', ''):
yield result
for S in break_words('....--', [], '', ''):
print Shttps://stackoverflow.com/questions/8349136
复制相似问题