Search code examples
functional-programmingocamlmorse-code

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


Bonjour.I am struggling with the 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. 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.

I created a function (as demonstrated below), however each time I pass it an argument, I always get an error:

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 " " ;

Solution

  • 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.

    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.