summaryrefslogtreecommitdiff
path: root/src/_posts/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.adoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/_posts/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.adoc')
-rw-r--r--src/_posts/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.adoc465
1 files changed, 0 insertions, 465 deletions
diff --git a/src/_posts/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.adoc b/src/_posts/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.adoc
deleted file mode 100644
index 6dd01a6..0000000
--- a/src/_posts/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.adoc
+++ /dev/null
@@ -1,465 +0,0 @@
----
-tags: Hackerrank Perl6 Python Python3 Programming Raku
-description: >
- A number of solutions to Hackerrank challenges in both the Python 3 and the
- Perl 6 programming languages. Compare the results and see which language
- works best for you!
----
-= Hackerrank solutions: Python 3 and Perl 6 (part 1)
-:toc: preamble
-
-I recently started at a new company, for which I will have to write Python 3
-code. To make sure I still know how to do basic stuff in Python, I started to
-work on some https://www.hackerrank.com/[Hackerrank challenges]. In this post,
-I will show solutions to some challenges to show the differences. I hope that I
-can show that Perl doesn't have to be the "write only" language that many
-people make it out to be.
-
-[NOTE]
-====
-I am _much_ more proficient in the Perl 6 programming language than in Python
-(2 or 3), so I might not always use the most optimal solutions in the Python
-variants. Suggestions are welcome via email, though I most likely won't update
-this post with better solutions. I ofcourse also welcome feedback on the Perl 6
-solutions!
-====
-
-== Challenges
-
-The challenges covered in this post are the
-https://www.hackerrank.com/domains/algorithms?filters%5Bsubdomains%5D%5B%5D=warmup[warmup
-challenges] you are recommended to solve when you make a new account. The code
-around the function I'm expected to solve won't be included, as this should be
-irrelevant (for now). Additionally, I may rename the sub to conform to
-https://en.wikipedia.org/wiki/Letter_case#Special_case_styles[kebab-case], as
-this is more readable (in my opinion), and allowed in Perl 6.
-
-=== Solve Me First
-
-This challenge is just a very simple example to introduce how the site works.
-It required me to make a simple `a + b` function.
-
-[source,py3]
-----
-def solveMeFirst(a,b):
- return a+b
-----
-
-The Perl 6 variant isn't going to very different here.
-
-[source,perl6]
-----
-sub solve-me-first ($a, $b) {
- $a + $b
-}
-----
-
-For those not familiar with Perl 6, the `$` in front of the variable names is
-called a https://docs.perl6.org/language/glossary#index-entry-Sigil[Sigil], and
-it signals that the variable contains only a single value.
-
-You may have noticed that there's also no `return` in the Perl 6 variant of
-this example. In Perl 6, the last statement in a block is also the implicit
-return value (just like in Perl 5 or Ruby).
-
-=== Simple Array Sum
-
-For this challenge I had to write a function that would return the sum of a
-list of values. Naturally, I wanted to use a `reduce` function, but Python 3
-does not support these. So I wrote it with a `for` loop instead.
-
-[source,py3]
-----
-def simpleArraySum(ar):
- sum = 0
-
- for i in ar:
- sum += i
-
- return sum
-----
-
-Perl 6 does have a `reduce` function, so I would use that to solve the problem
-here.
-
-[source,perl6]
-----
-sub simple-array-sum (@ar) {
- @ar.reduce(sub ($a, $b) { $a + $b })
-}
-----
-
-Here you can see a different sigil for `@ar`. The `@` sigil denotes a list of
-scalars in Perl 6. In most other languages this would simply be an array.
-
-This code can be written even shorter, however. Perl 6 has
-https://docs.perl6.org/language/operators#index-entry-%5B%2B%5D_%28reduction_metaoperators%29[reduction
-meta-operators]. This allows you to put an operator between brackets, like
-`[+]`, to apply a certain operator as a reduce function.
-
-[source,perl6]
-----
-sub simple-array-sum (@ar) {
- [+] @ar
-}
-----
-
-[NOTE]
-====
-After publishing this post I have learned that both Python 3 and Perl 6 have a
-`.sum` function that can also be called on the array, simplifying the code in
-both languages.
-====
-
-=== Compare the Triplets
-
-This challenge provides you with 2 lists of 3 elements each. The lists should
-be compared to one another, and a "score" should be kept. For each index, if
-the first list contains a larger number, the first list's score must be
-incremented. Similarly, if the second list contains a larger number on that
-index, the second list's score must be incremented. If the values are equal, do
-nothing.
-
-[source,py3]
-----
-def compareTriplets(a, b):
- scores = [0, 0]
-
- for i in range(3):
- if a[i] > b[i]:
- scores[0] += 1
-
- if a[i] < b[i]:
- scores[1] += 1
-
- return scores
-----
-
-I learned that Python 3 has no `++` operator to increment a value by 1, so I
-had to use `+= 1` instead.
-
-[source,perl6]
-----
-sub compare-triplets (@a, @b) {
- my @scores = [0, 0];
-
- for ^3 {
- @scores[0]++ if @a[$_] > @b[$_];
- @scores[1]++ if @a[$_] < @b[$_];
- }
-}
-----
-
-In Perl 6, the `^3` notation simply means a range from 0 to 3, non-inclusive,
-so `0`, `1`, `2`, meaning it will loop 3 times. The `$_` is called the
-__topic__, and in a `for` loop it is the current element of the iteration.
-
-Both of these loops could use a `continue` (or `next` in Perl 6) to skip the
-second `if` in case the first `if` was true, but for readability I chose not
-to.
-
-[NOTE]
-====
-After publishing this post I learned that Python 3 also supports the inline if
-syntax, just like Perl 6, so I could've used this in Python 3 as well.
-====
-
-=== A Very Big Sum
-
-In this challenge, you need to write the function body for `aVeryBigSum`, which
-gets an array of integers, and has to return the sum of this array. Both Python
-3 and Perl 6 handle the large integers transparently for you, so I was able to
-use the same code as I used for the simple array sum challenge.
-
-[source,py3]
-----
-def aVeryBigSum(ar):
- sum = 0
-
- for i in ar:
- sum += i
-
- return sum
-----
-
-And for Perl 6 using the `[+]` reduce meta-operation.
-
-[source,perl6]
-----
-sub a-very-big-sum (@ar) {
- [+] @ar
-}
-----
-
-=== Plus Minus
-
-The next challenge gives a list of numbers, and wants you to return the
-fractions of its elements which are positive, negative or zero. The fractions
-should be rounded down to 6 decimals. I made a counter just like in the
-*Compare the Triplets* challenge, and calculated the fractions and rounded them
-at the end.
-
-[source,py3]
-----
-def plusMinus(arr):
- counters = [0, 0, 0]
-
- for i in arr:
- if (i > 0):
- counters[0] += 1
- continue
-
- if (i < 0):
- counters[1] += 1
- continue
-
- counters[2] += 1
-
- for i in counters:
- print("%.6f" % (i / len(arr)))
-----
-
-For the Perl 6 solution, I went for a `given/when`, `map` and the `fmt`
-function to format the fractions.
-
-[source,perl6]
-----
-sub plus-minus (@arr) {
- my @counters = [0, 0, 0];
-
- for @arr -> $i {
- given $i {
- when * > 0 { @counters[0]++ }
- when * < 0 { @counters[1]++ }
- default { @counters[2]++ }
- }
- }
-
- @counters.map({ $_.fmt("%.6f").say });
-}
-----
-
-You may notice a number of statements do not have a terminating `;` at the end.
-In Perl 6, this is not needed if it's the last statement in a block (any code
-surrounded by a `{` and `}`.
-
-The `given/when` construct is similar to a `switch/case` found in other
-languages (but not Python, sadly), but uses the
-https://docs.perl6.org/language/operators#index-entry-smartmatch_operator[smartmatch
-operator] implicitly to check if the statements given to `when` are `True`. The
-`*` is the https://docs.perl6.org/type/Whatever[Whatever operator], which in
-this case will get the value of `$i`.
-
-Lastly, he `$_` in the `map` function is similar to inside a `for` loop,
-it's the current element. Since the code given to `map` is inside a block,
-there's no need for a `;` after `say` either.
-
-=== Staircase
-
-This challenge gives you an integer 𝓃, and you're tasked with "drawing" a
-staircase that is 𝓃 high, and 𝓃 wide at the base. The staircase must be made
-using `#` characters, and for the spacing you must use regular spaces.
-
-It seems that in Python, you _must_ specify the `i in` part oft the `for i in
-range`. Since I don't really care for the value, I assigned it to `_`.
-
-[source,py3]
-----
-def staircase(n):
- for i in range(1, n + 1):
- for _ in range(n - i):
- print(" ", end="")
-
- for _ in range(i):
- print("#", end="")
-
- print("")
-----
-
-In Perl 6, there's also a `print` function, which is like `say`, but does not
-append a `\n` at the end of the string. The `for` loop in Perl 6 allows for
-just a range to operate as expected. The `..` operator creates a range from the
-left-hand side up to the right hand side, inclusive.
-
-[source,perl6]
-----
-sub staircase ($n) {
- for 1..$n -> $i {
- print(" ") for 0..($n - $i);
- print("#") for ^$i;
- print("\n");
- }
-}
-----
-
-=== Mini-Maxi Sum
-
-Here you will be given 5 integers, and have to calculate the minimum and
-maximum values that can be calculated using only 4 of them.
-
-I sort the array, and iterate over the first 4 values to calculate the sum and
-print it. I then do the same but sort it in reverse for the sum of the 4
-highest values.
-
-[source,py3]
-----
-def miniMaxSum(arr):
- arr.sort()
- sum = 0
-
- for i in range(4):
- sum += arr[i]
-
- print(str(sum) + " ", end="")
-
- arr.sort(reverse=True)
- sum = 0
-
- for i in range(4):
- sum += arr[i]
-
- print(str(sum))
-----
-
-Perl 6 has immutable lists, so calling `sort` on them will return a new list
-which has been sorted. I can call `reverse` on that list to get the highest
-number at the top instead. `head` allows me to get the first 4 elements in a
-functional way. You've already seen the meta-reduce operator `[+]`, which will
-get me the sum of the 4 elements I got from `head`. I wrap the calculation in
-parenthesis so I can call `print` on the result immediately.
-
-[source,perl6]
-----
-sub mini-maxi-sum (@arr) {
- ([+] @arr.sort.head(4)).print;
- print(" ");
- ([+] @arr.sort.reverse.head(4)).print;
-}
-----
-
-=== Birthday Cake Candles
-
-In this challenge, you're given a list of numbers. You must find the highest
-number in the list, and return how often that number occurs in the list.
-
-It's fairly straightforward, I keep track of the current largest value as
-`size`, and a `count` that I reset whenever I find a larger value than I
-currently have.
-
-[source,py3]
-----
-def birthdayCakeCandles(ar):
- size = 0
- count = 0
-
- for i in ar:
- if i > size:
- size = i
- count = 0
-
- if i == size:
- count += 1
-
- return count
-----
-
-The Perl 6 variant does not differ in how it solves the problem, apart from
-having a very different syntax of course.
-
-[source,perl6]
-----
-sub birthday-cake-candles (@ar) {
- my ($size, $count) = (0, 0);
-
- for @ar {
- if ($_ > $size) {
- $size = $_;
- $count = 0;
- }
-
- $count++ if $size == $_;
- }
-
- $count;
-}
-----
-
-[NOTE]
-====
-On IRC, someone showed me a clean solution in Python 3: `return
-ar.count(max(ar))`. This feels like a much cleaner solution than what I had
-created.
-====
-
-=== Time Conversion
-
-This is the final challenge of this section on Hackerrank, and also this post.
-You're given a timestamp in 12-hour AM/PM format, and have to convert it to a
-24-hour format.
-
-I split the AM/PM identifier from the actual time by treating the string as a
-list of characters and taking two slices, one of the last two characters, and
-one of everything _but_ the last two characters. Then I split the time into
-parts, and convert the first part (hours) to integers for calculations. Next I
-set the hours to 0 if it's set to 12, and add 12 hours if the timestamp was
-post meridiem. Finally, I convert the hours back to a string with leading
-zeroes, and join all the parts together to form a timestamp again.
-
-[source,py3]
-----
-def timeConversion(s):
- meridiem = s[-2:]
- hours = int(s[:2])
- rest = s[2:-2]
-
- if (hours > 11):
- hours = 0
-
- if (meridiem.lower() == "pm"):
- hours += 12
-
- return ("%02d:%s" % (hours, rest))
-----
-
-The Perl 6 solution again doesn't differ much from the Python solution in terms
-of the logic it's using to get the result. The biggest difference is that in
-Perl 6, strings can't be accessed as lists, so I use the `substr` method to
-extract the parts that I want. The first one starts at `*-2`, which means 2
-places before the end. The others get a
-https://docs.perl6.org/type/Range[`Range`] as argument, and will get the
-characters that exist in that range.
-
-[source,perl6]
-----
-sub time-conversion ($s) {
- my $meridiem = $s.substr(*-2);
- my $hours = $s.substr(0..2).Int;
- my $rest = $s.substr(2..*-2);
-
- $hours = 0 if $hours > 11;
- $hours += 12 if $meridiem.lc eq "pm";
-
- sprintf("%02d:%s", $hours, $rest);
-}
-----
-
-The `.Int` method converts the `Str` object into an `Int` object, so we can
-perform calculations on it. The `eq` operator checks specifically for
-https://docs.perl6.org/routine/eq[__string equality__]. Since Perl 6 is a
-https://en.wikipedia.org/wiki/Gradual_typing[gradually typed programming
-language], there's a dedicated operator to ensure that you're checking string
-equality correctly.
-
-== Wrap-up
-
-These challenges were just the warm-up challenges I was given after creating a
-new account and choosing Python as a language to use. I intend to write up more
-posts like this, for the near future I'll stick to Python 3 challenges since I
-want to get better at that specific language for work.
-
-This is also the first post in which I have tried this format to show off two
-languages side-by-side, and to highlight differences in how you can accomplish
-certain (relatively simple) tasks with them. If you have suggestions to improve
-this format, do not hesitate to contact me. I am always open for feedback,
-preferably via email. You can find my contact details on the link:/[homepage].
-