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

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

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.

This is a great place to use a Map to map characters to Morse codes. Then it's just a matter of mapping each character in your string to that character's binding in the 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). 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.
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.)
Now, really we just need to map an input string to the Morse code for each character. To do that we'll turn a string int a sequence, map, and then convert to a list.
"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. You'd either want to handle this exeception, or add more Morse code bindings to your map.

Related

Compare Master data with elements present in the XML

<MasterData>
<Name>AA</Name>
<EmpId>123</EmpId>
<AccountNo>111</AccountNo>
<IFSC>ABC</IFSC>
<AccountData>
<AccountNo>111</AccountNo>
<IFSC>ABC</IFSC>
</AccountData>
<AccountData>
<AccountNo>222</AccountNo>
<IFSC>DEF</IFSC>
</AccountData>
</MasterData>
I have an xml like this in my database,I have a requirement to check the combination of AccountNo+IFSC present in the MasterData(not under the AccountData section) and compare with all documents present in the collection and check whether its matching to the data present in the AccountData section,If its matching identify the URI of the document.
First identify the unique combination of AccountNo+IFSC from Masterdata section and then check whether this combination present under any of the AccountData section, there are more elements in this xml other than AccountNo and IFSC
If you had range indexes on the AccountNo and IFSC elements, then you could:
retrieve the set of values from AccountNo, IFSC, and a cts:uri-reference() with cts:value-tuples().
create a map using a composite key with the AccountNo and IFSC values and the URIs as the values for those map entries
prune any entry that only has one URI associated
return the map that will have the set of URIs corresponding to each combo of AccountNo and IFSC value
Something like this:
let $accountNumber-IFSC :=
cts:value-tuples(
(
cts:element-reference(xs:QName("AccountNo")),
cts:element-reference(xs:QName("IFSC")),
cts:uri-reference()
)
)
let $map := map:new()
let $_create_map_value_to_uris := for $co-occurrence in $accountNumber-IFSC
let $key := concat($co-occurrence[1], " ", $co-occurrence[2])
let $value := (map:get($map, $key), $co-occurrence[3])
return map:put($map, $key, $value)
let $_prune_single_uri :=
for $key in map:keys($map)
let $value := map:get($map, $key)
where not(tail($value))
return
map:put($map, $key, ())
return
$map
If you just wanted the list of URIs, you can invert the map: -$map and return it's keys: return map:keys(-$map)
If you had a range-index on the EmpId you could pivot on that instead of the document URIs.
Using the Optic API functions, you can do something similar with element-range indexes:
import module namespace op = "http://marklogic.com/optic" at "/MarkLogic/optic.xqy";
op:from-lexicons(
map:entry("AccountNo", cts:element-reference(xs:QName("AccountNo")))
=> map:with("IFSC", cts:element-reference(xs:QName("IFSC")))
=> map:with("URI", cts:uri-reference())
)
=> op:group-by(
("IFSC", "AccountNo"),
(
op:group-concat("URIs", "URI", map:entry("separator", ", ")),
op:count("count", op:col("URI"))
)
)
=> op:where(op:gt(op:col("count"), 1))
=> op:result()

decrypt MCRYPT_RIJNDAEL_128 ECB using openSSL [duplicate]

I have this mcrypt_encrypt call, for a given $key, $message and $iv:
$string = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv);
I'd like to change the mcrypt_encrypt call to an openssl_encrypt one, to future-proof this.
By having $mode = 'des-ede3-cbc' or $mode = '3DES'; and $options = true I get the more similar response, but not identical. Is there other way to call it to get a perfect match?
I am getting this (base64_encoded) for a lorem-ipsum $message+$key combinations, so I am starting to believe one function or the other are padding somewhat the message before encrypting...
for mcrypt:
"Y+JgMBdfI7ZYY3M9lJXCtb5Vgu+rWvLBfjug2GLX7uo="
for for openssl:
"Y+JgMBdfI7ZYY3M9lJXCtb5Vgu+rWvLBvte4swdttHY="
Tried using $options to pass OPENSSL_ZERO_PADDING, but passing anything but 1 (OPENSSL_RAW_DATA, or true) results in an empty string ...
Neither using OPENSSL_ZERO_PADDING nor OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING work... :(
I'm using "OpenSSL 1.0.2g 1 Mar 2016".
Already read this q&a, but it does not help me. Not the only one with padding troubles, but no solution in sight so far. Second answer talks about adding padding to mcrypt call, I would really want to remove padding from openssl encryption call...
mcrypt_encrypt zero-pads input data if it's not a multiple of the blocksize. This leads to ambiguous results if the data itself has trailing zeroes. Apparently OpenSSL doesn't allow you to use zero padding in this case, which explains the false return value.
You can circumvent this by adding the padding manually.
$message = "Lorem ipsum";
$key = "123456789012345678901234";
$iv = "12345678";
$message_padded = $message;
if (strlen($message_padded) % 8) {
$message_padded = str_pad($message_padded,
strlen($message_padded) + 8 - strlen($message_padded) % 8, "\0");
}
$encrypted_mcrypt = mcrypt_encrypt(MCRYPT_3DES, $key,
$message, MCRYPT_MODE_CBC, $iv);
$encrypted_openssl = openssl_encrypt($message_padded, "DES-EDE3-CBC",
$key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);
printf("%s => %s\n", bin2hex($message), bin2hex($encrypted_mcrypt));
printf("%s => %s\n", bin2hex($message_padded), bin2hex($encrypted_openssl));
This prints both as equal.
4c6f72656d20697073756d => c6fed0af15d494e485af3597ad628cec
4c6f72656d20697073756d0000000000 => c6fed0af15d494e485af3597ad628cec
mcrypt_encrypt uses zeroes to pad message to the block size. So you can add zeroes to the tail of your raw data, and then encrypt the block.
Using OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING should work. If it doesn't, then you can remove padding from the decrypted data by yourself.

Symfony Invalid parameter format, : given

I need create multiply search by years. From request I get string like 2017,2018 and then I want get Questions which createdAt, between from start year and end year. I have query builder with part, and I'am not understand why I have this error
if ($paramFetcher->get('years')) {
$orXSearch = $qb->expr()->orX();
$yearData = trim($paramFetcher->get('years'));
foreach (explode(',', $yearData) as $key => $id) {
if (!$id) {
continue;
}
$orXSearch
->add($qb->expr()->between('q.createdAt', ':'.$key.'dateFrom', ':'.$key.'dateTo'));
$date = $this->additionalFunction->validateDateTime($id, 'Y');
$first = clone $date;
$first->setDate($date->format('Y'), 1, 1);
$first->setTime(0, 0, 0);
$last = clone $date;
$last->setDate($date->format('Y'), 12, 31);
$last->setTime(23, 59 , 59);
$qb
->setParameter($key.'dateFrom', $first->format('Y-m-d H:i:s'))
->setParameter($key.'dateTo', $last->format('Y-m-d H:i:s'));
}
$qb->andWhere($orXSearch);
}
error:
symfony Invalid parameter format, : given, but :<name> or ?<num> expected.
In your foreach loop, you’re looping over the result of an explode operation which yields a numeric array, i.e. $key will always have a numeric value.
Hence, your parameter placeholder is colon + number + string, i.e. :1dateFrom. This is not allowed. Either you reference a string value with a colon + string placeholder (:foo), or you reference a numeric value with a question mark + number value (?1).
Your problem is easy to solve: Simply add any letter between the colon and the number, and you’re good:
->add($qb->expr()->between(
'q.createdAt',
':x'.$key.'dateFrom',
':x'.$key.'dateTo'
));

Create windows of results per alphabet

My XML file is here.
I would like to get the results of all movie titles by alphabet in the following manner:
<window>
<title>Alpha</title>
<title>Abel</title>
<window>
<title><babylon</title>
...
<window>
...
<window>
...
I am using tumbling feature in the following code:
for tumbling window $w in db:open("movies","movies.xml")/movies/movie/title
start at $s when fn:true()
only end at $e when not starts-with($e,substring($s, 1, 1))
return <window>{ $w/../title }</window>
Basically, I am trying to extract first character of each words and grouping them together.
However, It says incomplete FLWOR expression.
A group by would be more appropriate here:
for $title in //title
order by $title
group by $g := substring($title, 1,1)
return element { $g } {
$title
}
when you really want to use tumbling you could use the start and next variables to create groups:
for tumbling window $w in //title
start $first when true()
end next $next when substring($first, 1,1) != substring($next,1,1)
return <window>{ $w }</window>

How to query the custom fields by language in wordpress?

For each post, there is a custom field name "Function", the key/value pair is like this:
Key : Functions
Value : <!--en-->Nourishing Yin and invigorating the vital essence of kidneys.<!--:--><!--tw-->滋陰補腎。<!--:-->
The problem is if I simply use get_post_meta , it return string of both language, how can I get the value based on the language?
I am using qTranslate right now, Thanks.
Updated (the code):
$custom_fields = get_post_custom(get_the_ID());
$function = get_post_custom_values('Functions', get_the_ID());
You can simply fetch the strings considering comments as prefix and suffix -
After you get the custom field value,
e.g.
$function = "<!--en-->Nourishing Yin and invigorating the vital essence of kidneys.<!--:--><!--tw-->滋陰補腎。<!--:-->";
$arr = explode("<!--:-->", $function);
$new_arr = array();
foreach($arr as $a ){
if(!empty($a)){
$lang = str_replace( "-->", "", substr($a, 4, 5) );
$str = substr($a, 9);
$new_arr[$lang] = $str;
}
}
Now $new_arr will have key/value pairs like array(language_code => sentence).
If you do print_r($new_arr);
It will give output as follows:
Array ( [en] => Nourishing Yin and invigorating the vital essence of kidneys. [tw] => 滋陰補腎。 )
Now you can identify the strings using their respective language codes.

Resources