# Daily Challenge #299 - Time to Grille!

A grille cipher was a technique for encrypting plaintext by writing it onto a sheet of paper through a pierced sheet. The earliest known use is from the mathematician Girolamo Cardano in 1550. His proposal was for a rectangular stencil allowing single letters, syllables, or words to be written, then later read. The written fragments of the plaintext could be further disguised by filling the gaps between the fragments with benign words or letters.

Write a function that accepts two inputs: `message` and `code`. Code is a non-negative integer and should be converted to binary. Overlay the code converted to binary and the message to reveal the result.

### Example

``````Grille("abcdef", 5)  => "df"

* convert 5 to binary:
000101

* overlay message and code:
message : abcdef
code    : 000101
----------------
result  : df
``````

### Tests

`Grille("0abc", 2)`

`Grille("abcde", 32)`

`Grille("abcd", 1)`

Good luck!

This challenge comes from dcieslak on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

### Discussion  ''

JS

``````
const dec2bin = dec => (dec >>> 0).toString(2);

const Grille = (message, code) => {
return codeToBinary.split("")
.map((binaryLetter, index) => binaryLetter === "1" ? index : '')
.filter(String)
.map(index => message.charAt(index)).join("")
}

`````` Ilyes Chouia

This is the solution in PHP, but I'm not sure if it's 100% correct since there aren't enough test cases and the test cases provided above don't have the result so they're pretty much useless.
anyway, here's my attempt:

``````function grille(\$message, \$code)
{
\$letters = '';
\$code = array_filter(str_split(sprintf("%06d", decbin(\$code))), function(\$x) {
return \$x == 1;
});
\$code = array_keys(\$code);
foreach(str_split(\$message) as \$index => \$letter){
if(in_array(\$index, \$code)){
\$letters .= \$letter;
}
}
return \$letters;
}
`````` peter279k

Here is the simple solution with Python:

``````def grille(message, code):
bin_number = bin(code)[2:]
bin_number_len = len(bin_number)

if len(message) <= 1:
return ''
if len(message) > bin_number_len:
bin_number = ('0' * (len(message) - bin_number_len)) + bin_number

index = 0
result = ''
while index < len(message):
if bin_number[index] == '1':
result += message[index]
index += 1

if len(message) < bin_number_len:
if len(result) == len(message):
return result
else:
return ''

return result

`````` agtoever

Python 3-liner with test cases and TIO link.
Apart from some type conversions, itertools.compress does the job.

``````import itertools
filterlist = lambda value, length: map(int, bin(value)[2:].zfill(length))
grille = lambda string, grille: ''.join(itertools.compress(string, filterlist(grille, len(string))))

cases = [
('abcdef', 5),
('0abc', 2),
('abcde', 32),
('abcd', 1)
]
for case in cases:
print(f'grille{case} has filter {list(filterlist(case, len(case)))} and outcome: {grille(*case)}')
``````

Try it online! Rafael Acioly

Scala solution

``````def grille(text: String, code: Int) = {
val letters = text.split("")
val digits = code.toBinaryString.map(_.asDigit)

val res = letters.toList.reverse.zipAll(digits, 0, 0)

(res collect { case (i, v) if v != 0 => i }).mkString("")
}
`````` Bianca Power

ruby

``````def grille(message, code)
output = ""

# convert code to binary
binary_code = code.to_s(2)

# prepend the appropriate number of zeros to match length of message
while message.length > binary_code.length
binary_code.prepend('0')
end

# combine messages and binary_code into a hash
arrays_hash = Hash[message.split("").zip(binary_code.split(""))]

# if the value is 1, add the key to the output string
arrays_hash.each do |k, v|
if v == "1"
output << k
end
end

return output
end
`````` Michael Kohl

Ruby allows string interpolation in format strings, which makes generating `binary_code` easier:

``````binary_code = "%0#{message.length}d" % code.to_s(2)
``````

Ruby 2.7 also added a handy `filter_map` method, which can simplify the second half of your method:

``````message.chars.zip(binary_code.chars).filter_map { |c, i| c if i == "1" }
`````` Hao

Another JavaScript solution, using binary operations:

``````const Grille = (str, bin) => [...str].filter((_, i) => 1 << (str.length-i-1) & bin).join('');
``````