Hashed up Sequencing – Perl weekly challenge, week 14
It’s been 4 weeks; well past time to blog again; this time for Perl Weekly Challenge 014
What the Van Eck?
The first challenge for me this week was to go to the Wikipedia page, read what it was saying, and try to figure out exactly what the Van Eck sequence is.
This was at 10pm and I’d spent all day learning to adapt to Fedora after installing that on my new laptop (and discovering while trying to attach a NASalike via SSH to my existing workstation that I’d set up SSH to immediately launch a docker container that sandboxed my user into my home directory, thus causing nothing to work as expected). After some heavy screen glaring I managed to arrive at a re-interpretation as three rules:
- a0 = 0
- an + 1 = an - am when m is the largest index < n of a having am = an
- an + 1 = 0 when the conditions for m cannot be met.
This was sufficient for me to then confuse myself into tyring to store the next m and n pair for a given value of a in a hash and fill everything up with 0 in a gather / take loop.
I did a lot of filling everything up with 0.
I replaced this first implementation (sorry, I didn’t save this source so you could all laugh at it) with an eager list generation that would count back from the current n to 0 instead:
This works, but is quite slow, probably mainly because of the eager list
generation. A keen observer might also notice that Van_Eck[max(0, $n-1)...0]:k
is a bit silly, given that getting the keys of a list that you’ve generated by
specifying the keys of another list is just going to give you the same list
you’ve specified back, so I may as well have written (max(0, $n-1)...0)
, but I
went to bed and discovered this the next morning instead, laughed out loud, and
fixed it; my 7 year old daughter also thought it funny.
This didn’t solve the speed issue though (even if said problem was only
noticeable when you gave the program an obscene upper bound), so I revisited
using a hash to find the highest index the same as an and the
sleep-having version of myself quickly realised that I only needed to store one
index per hash element, and whether such an m existed could be determined
using the :exists
adverb.
After a little bit of failing to realise I never needed to explicitly update
%m{0}
(and thus filling everything up with 0 again) I finally managed to come
up with something that wouldn’t stall massively when asked to find 2000 elements
in the sequence:
Worth noting is that $n
is always one behind the index of the current value
being taken.
Spelling with the United States
Perl 6 makes the meat of this almost trivial. Create a set of the states’
abbreviations (I zipped these into a hash of the states’ names for later
reference), sort all the even length words you have (e.g.
/usr/share/dict/words
) into longest to shortest order, then find the first list
element where a comb of 2-letter sequences of the word is a subset of the
abbreviations.
Using the hash of abbreviation => name I then print out which states spelt the word and the word itself.
Apparently, the longest spellable word in the British English dictionary on my system is cacogalactia, which apparently means that California, Colorado, Georgia, Louisiana, Connecticut & Iowa are together states of bad milk…
What time is it in … ?
This week’s optional API challenge was to Find the given city current time using the Geo DB Cities API.
The Geo DB Cities API has an endpoint that doesn’t require an API key, which is a refreshing change. The documentation on what that end point is seemed to be non-existent, though; after some hunting around in the network panel of Firefox on their demo pages I found what appeared to be it.
I elected again (Ah, I did the optional challenge in
week 12,
but didn’t blog that one) to use Cro::Http::Client
to do the heavy lifting of
HTTP connections, and don’t seem to be able to find a URL encoding function for
it, so I reused the routine I put together for this last time, but with support
for turning spaces into +
:
Pretty trivial, but I in no way endorse this as a complete solution for input sanitation. Someone please tell me if I’ve missed something that does this in a more bulletproof manner.
Cro::Http::Client
is pretty straightforward to use. You can create a defined
instance of it or not, then use the get
method (or post
, or request
as
appropriate) to access the data you require. This creates a promise that
includes various methods for getting the response, including body
which will
automatically convert JSON into Perl 6 structures for you. This itself returns a
Promise, which seems a bit awkward, although I’m sure there’s a reason for it.
Which brings me onto a new gripe, which is that chaining Promises together feels
awkward; I feel like using a Promise
in sink context at the end of a then
block should chain automatically like it does in ECMAScript6, but it seems they
don’t, so I end up with awkward chains like:
or worse:
Maybe I’ve missed something? Maybe I’ve spent too long in the browser… I guess
given that in Diwali await
no longer blocks a thread, it may as well be
written as:
This is particularly relevant in this case, because when you have a city name, you have to make an API call to turn that into an ID, and then you can call the dateTime endpoint on that city ID, so that’s 4 Promises.
I’m also struggling with error handling inside then
blocks. I want to fail
,
but end up with internal MoarVM errors (tried to unwind entire stack…). I guess
I have quite a bit to learn there, but didn’t feel like following it to the
bitter end this time around.
For information on your privacy including GDPR details, see Github's privacy statement.