### Perl Weekly Challenge: Week 258

#### Challenge 1:

Count Even Digits Number

You are given a array of positive integers, `@ints`.

Write a script to find out how many integers have even number of digits.

##### Example 1
``````Input: @ints = (10, 1, 111, 24, 1000)
Output: 3

There are 3 integers having even digits i.e. 10, 24 and 1000.
``````
##### Example 2
``````Input: @ints = (111, 1, 11111)
Output: 0
``````
##### Example 3
``````Input: @ints = (2, 8, 1024, 256)
Output: 1
``````

Raku once again comes through with a one-liner.

``````@*ARGS.grep({\$_.chars %% 2}).elems.say
``````

(Full code on Github.)

Using the command-line arguments as input, we filter them with `.grep()`, finding the length of each one with `.chars()` and seeing if it is evenly divisible by two with the `%%` operator. Then we count how many we found with `.elems()` and output the result with `.say()`.

The Perl version is slightly longer because we don't have `%%` and have to do an explicit comparison to 0 instead.

``````say scalar grep {(length \$_) % 2 == 0} @ARGV
``````

(Full code on Github.)

#### Challenge 2:

Sum of Values

You are given an array of integers, `@ints` and an integer `\$k`.

Write a script to find the sum of values whose index binary representation has exactly `\$k` number of `1-bit` set.

##### Example 1
``````Input: @ints = (2, 5, 9, 11, 3), \$k = 1
Output: 17

Binary representation of index 0 = 0
Binary representation of index 1 = 1
Binary representation of index 2 = 10
Binary representation of index 3 = 11
Binary representation of index 4 = 100

So the indices 1, 2 and 4 have total one 1-bit sets.
Therefore the sum, \$ints[1] + \$ints[2] + \$ints[3] = 17
``````
##### Example 2
``````Input: @ints = (2, 5, 9, 11, 3), \$k = 2
Output: 11
``````
##### Example 3
``````Input: @ints = (2, 5, 9, 11, 3), \$k = 0
Output: 2
``````

Raku can do this one (albeit very long) line but I've spread it out to make it more intelligable.

I'm assuming `\$k` is the first command-line argument and `@ints` is all the rest.

We start by getting the indices of each element in `@ints` with what has become one of my favorite methods of late, `.keys()`.

``````@ints
.keys
``````

Then each index is converted to binary via `.map()` and `.base(2)`

``````.map({ \$_.base(2) })
``````

Now we can find which indices meet the specs' criterion. We do this with a call to `.grep()` which...

``````.grep({
``````

...splits the index into its' constituent digits with `.comb()`,,,

``````    \$_
.comb
``````

...finds the digits which are 1's with another `.grep()`...

``````    .grep({ \$_ == 1 })
``````

... counts how many 1's there were with `.elems()` and compares that number to `\$k`.

``````    .elems == \$k
})
``````

Now we know which indices we need, we can find the values of their respective elements by transforming them with `.map()`. We have to prefix `0b` to each index in order for it to be recognized as a binary number literal.

``````.map({ @ints["0b\$_"] })
``````

Then we add up all the values with `.sum()`...

``````.sum
``````

...and print the result.

``````.say;
``````

(Full code on Github.)

Perl works the same way although the visual order of the operations is reversed. And we have to provide our own `sum()` function.

``````say sum(
``````

Unfortunately, it seems that Perl does not allow you to use a binary literal as an array index so it has to first be converted back into base 10 with the badly named `oct()`.

``````map { \$ints[oct "0b\$_"] }
grep { scalar (grep { \$_ == 1 } (split //, \$_)) == \$k }
``````

We don't have `.base()` either but `sprintf('%b')` can do the conversion for us.

``````map { sprintf '%b', \$_ } keys @ints
);
``````

(Full code on Github.)