简体   繁体   English

(Invalid_argument“索引超出范围”)同时将单词编码为摩尔斯电码

[英](Invalid_argument "index out of bounds") while encoding a word to a Morse code

Bonjour.I am struggling with the function code_word . Bonjour.我正在努力解决 function code_word The purpose of this function is to take a message of type string and the Morse alphabet itself on the input, and it should return an encoded word of the same type on the output.这个 function 的目的是在输入上获取字符串类型的消息和莫尔斯字母本身,它应该在 output 上返回相同类型的编码字。 For instance:例如:

code_mot: string->(char * string)list -> string 
code_word "SOS" alphabet;;
-: string list = ["... --- ..."]

PS: Each encoded letter of the word have to be separated by the space. PS:单词的每个编码字母都必须用空格分隔。

I created a function (as demonstrated below), however each time I pass it an argument, I always get an error:我创建了一个 function(如下所示),但是每次我传递一个参数时,我总是得到一个错误:

Exception: (Invalid_argument "index out of bounds")

To be honest I have tried all possible combinations to solve this problem.老实说,我已经尝试了所有可能的组合来解决这个问题。 Nonetheless, I didn't find a suitable solution.Due to this I would like to ask for help: What is the source of an error and how can I fix it?尽管如此,我没有找到合适的解决方案。因此,我想寻求帮助:错误的根源是什么,我该如何解决?

let alphabet =
  [ ('A', "._" ); ('B', "_..." ); ('C', "_._.") ;
    ('D', "_.." ); ('E', "." ); ('F', ".._." );
    ('G', "__." ); ('H', "...." );( 'I', ".." );
    ('J', ".___" ); ('K', "_._" ); ('L', "._.." );
    ('M', "__" );  ('N', "_." ); ('O', "___" );
    ('P', ".__."); ( 'Q', "__._" );( 'R', "._.") ;
    ('S', "..." ); ('T', "_" ); ('U', ".._" );
    ('V', "..._" ); ('W', ".__" ); ('X', "_.._") ;
    ('Y', "_.__" ); ('Z', "__.." )
   ];;

let code_word s alpha = 
  let rec cw_aux s i alpha word = 
    match alpha with 
    | [] -> word
    | (cha, l)::r -> 
      if s.[i] = cha then 
        cw_aux s (i+1) alpha (l^" "^word)
      else
        cw_aux s (i+1) r word
  in
  cw_aux s 0 alpha " " ;

Your code needs to iterate over two things: the incoming string, and the list of morse codes.您的代码需要遍历两件事:传入的字符串和莫尔斯电码列表。 But you have only one termination condition, the end of the morse code list.但是你只有一个终止条件,莫尔斯电码表的结尾。 In other words, you're not checking anywhere for when you reach the end of the string.换句话说,您不会在任何地方检查何时到达字符串的末尾。 Thus your recursive calls with (i + 1) will eventually reach past the end of the string and cause your error.因此,您使用(i + 1)进行的递归调用最终将超过字符串的末尾并导致您的错误。

It seems to me that you also have the problem that you have merged your two searches.在我看来,您也有合并两个搜索的问题。 It's not true that you want to move along to the next character in the string when you don't find a code for the current char of the string.当您没有找到字符串的当前字符的代码时,您想要移动到字符串中的下一个字符是不正确的。

In other words, this call looks wrong to me:换句话说,这个调用在我看来是错误的:

cw_aux s (i+1) r word

It's not the case that you want to move along to the next character of the incoming string here.您不想在此处移动到传入字符串的下一个字符。 You want to find the correct code for the current character first.您想首先找到当前字符的正确代码。

This is a great place to use a Map to map characters to Morse codes.这是使用Map到 map 字符到摩尔斯电码的好地方。 Then it's just a matter of mapping each character in your string to that character's binding in the map.然后只需将字符串中的每个字符映射到 map 中该字符的绑定即可。 By letting library functions handle looping over the string, the index error cannot happen.通过让库函数处理对字符串的循环,索引错误不会发生。

You could just use List.assoc with your list, but that's O(n) while lookups in a map are O(log n).您可以将List.assoc与您的列表一起使用,但这是 O(n),而 map 中的查找是 O(log n)。 For simple purposes, there's likely little practical difference, but for larger strings, it will matter.出于简单的目的,可能几乎没有实际差异,但对于较大的字符串,这将很重要。

module CMap = Map.Make (Char)

Then, using your list of tuples:然后,使用您的元组列表:

let alphabet =
  [ ('A', "._" ); ('B', "_..." ); ('C', "_._.");
    ('D', "_.." ); ('E', "." ); ('F', ".._." );
    ('G', "__." ); ('H', "...." );( 'I', ".." );
    ('J', ".___" ); ('K', "_._" ); ('L', "._.." );
    ('M', "__" );  ('N', "_." ); ('O', "___" );
    ('P', ".__."); ( 'Q', "__._" );( 'R', "._.");
    ('S', "..." ); ('T', "_" ); ('U', ".._" );
    ('V', "..._" ); ('W', ".__" ); ('X', "_.._");
    ('Y', "_.__" ); ('Z', "__.." )
   ]

We can create a map from the mappings you've created with a bit of help from the Seq (sequence) module.Seq (序列)模块的帮助下,我们可以根据您创建的映射创建 map。

let map = alphabet |> List.to_seq |> CMap.of_seq

(Note that the |> operator allows us to write the above, rather than CMap.of_seq (List.to_seq alphabet) . This becomes more helpful in the following code.) (注意|>运算符允许我们编写上面的代码,而不是CMap.of_seq (List.to_seq alphabet) 。这在下面的代码中变得更有帮助。)

Now, really we just need to map an input string to the Morse code for each character.现在,实际上我们只需要 map 每个字符的摩尔斯电码输入字符串。 To do that we'll turn a string int a sequence, map, and then convert to a list.为此,我们将字符串转换为序列 map,然后转换为列表。

"Hello" 
|> String.to_seq 
|> Seq.map Char.uppercase_ascii
|> Seq.map (fun ch -> CMap.find ch map) 
|> List.of_seq

Result:结果:

["...."; "."; "._.."; "._.."; "___"]

You would now simply need to join these together into a single string.您现在只需将它们连接成一个字符串。

You might still received a Not_found exception if you try to encode a string which includes characters for which there are not Morse code mappings.如果您尝试对包含没有摩尔斯电码映射的字符的字符串进行编码,您可能仍会收到Not_found异常。 You'd either want to handle this exeception, or add more Morse code bindings to your map.您要么想要处理此异常,要么向 map 添加更多摩尔斯电码绑定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM