Showing posts with label Ryan Guill. Show all posts
Showing posts with label Ryan Guill. Show all posts

Wednesday, 22 March 2017

Code puzzle: find any match from an array of regex patterns

G'day:
I'm being slightly cheeky as I'm hijacking someone else's question / puzzle from the CFML Slack channel that we were discussing last night. Don't worry, that'll be the last mention of CFML in this article, and indeed the question itself was asking for a JS solution. But it's a generic code puzzle.

Let's say one has a string, and an array of regex patterns one wants to check for in said string. A number of solutions were offered, using a number of techniques. And it even branched away from JS into Clojure (thanks Sean).

How would you go about doing it?

The input data is:

patterns = ["Savvy", "Smart", "Sweet"]
testForPositive = "Super Savvy"
testForNegative = "Super Svelt"

And in these cases we want true and false to be returned, respectively.

Note that the patterns there need to be considered regular expressions, not simple strings. The example data is just using simple strings for the sake of clarity.

Initially I was gonna do something like this:

function matchesOne(str, patterns) {
    var onePattern = new RegExp(patterns.join("|"));
    return str.search(onePattern) > -1;
}

Here I'm joining all the patterns into one big pattern, and searching for that. I was slightly hesitant about this as it's loading the complexity into the regex operation, which I felt perhaps wasn't ideal. Also it's not very clever: if any of the individual patterns had a | in them: this'd break. Scratch that.

Ryan Guill seeded the idea of approaching it from the other direction. Using the array as an array, and using one of JS's array higher-order functions to do the trick. We saw examples using find and filter, but I reckoned some was the best option here:

function matchesOne(str, patterns) {
    return patterns.some(pattern => str.search(pattern) > -1);
}


I'm happy with that.

The ante was raised next: write a function which returned the position of the first match (not just a boolean as to whether there was a match or not).

To me this was a reduction operation: take an array and - given some algorithm applied to each element - return a final single value.

I tried, but I could not make it very clean. This is what I got:

function firstMatch(str, patterns) {
    return patterns.reduce(function(first, pattern){
        var thisMatch = str.search(pattern);
        return first == -1 ? thisMatch : thisMatch == -1 ? first : Math.min(first, thisMatch);
    }, -1);
}


I'm happy with the reduce approach, but I'm really not happy with the expression to identify the lowest match (or continue to return -1 if no match is found):

first == -1 ? thisMatch : thisMatch == -1 ? first : Math.min(first, thisMatch)


To be clear, if we expanded that out, the logic is:

if (first == -1) {
    return thisMatch;
}
if (thisMatch == -1) {
    return first;
}
return Math.min(first, thisMatch);

That's actually "cleaner", but I still think I'm missing a trick.

So the puzzle to solve here is: what's a clever (but also Clean - in the RC Martin sense) way returning the lowest non -1 value of first and thisMatch, or fall back to -1 if all else fails.

Using this code (or some approximation thereof):

function firstMatch(str, patterns) {
    return patterns.reduce(function(first, pattern){
        var thisMatch = str.search(pattern);
        // return result of your code here
    }, -1);
}

console.log(firstMatch("Super Savvy", ["Savvy", "Smart", "Sweet"]));
console.log(firstMatch("Super Svelt", ["Savvy", "Smart", "Sweet"]));


One should get 6 and -1 for the respective "tests".

Use any language you like.

Oh and hey... if you have any interesting solutions for the two functions themselves, feel free to post 'em too.


Righto.

--
Adam

Friday, 4 November 2016

Another Friday code puzzle on the Slack Channel

G'day:
Another perennial CFML community participant, Ryan Guill, has posted this week's Friday code puzzle, over on the #friday-puzzle subchannel of the #CFML Slack channel.

Don't worry about the fact it's on the #CFML channel: it's open to anyone who wants to participate (you will need to join the channel though! I'll check with Ryan if it's OK to post the direct link to the Gist for it... update... yes it is OK. Here it is: friday-puzzle-leaderboard.md (gist)).

Here's a summary of the challenge:

Challenge:

Create a function that takes an array of objects that contain a name and a date counts instances of the name for a score. Output a leaderboard of the top 10 scores. Combine the same scores together so that if, for example, first place is 20 points and two people have 20 points, show them both in first place. The order of the names in the same place are not important. Next would still be second place. For this challenge, the dates do not matter.

(but see the actual Gist for more expectations: that's just the summary).

I for one would like to see how various different languages might approach this. On the other hand, I'm pretty rammed at the moment so dunno if I will find time to actually participate, meself.

Anyway, go on... give it a blast.

Righto.

--
Adam



Tuesday, 16 February 2016

A more professional CFML blog: Ryan Guill

G'day:
(more professional than this one, I mean ;-)

Good news, CFML community: Ryan Guill has started blogging. It's @ http://ryanguill.com/.

He's off to a flying start with eight articles already:
If you don't know Ryan already, I can tell you he really knows his stuff, and is a great bloke, so what he writes will be worth reading.

Righto.

--
Adam

Saturday, 25 July 2015

JavaScript: expectations re-adjusted re Promises

G'day:
First off a proactive apology. I generally sit in the pub on my Saturday afternoons in Galway (every second weekend), and write some ballocks on this blog. I think we're all used to that. I'm doing that now, but prior to kicking off with the writing I have already been sitting around for two hours watching the All Blacks play the Springboks in a hard-fought, narrow-margined 20-27 victory to NZ. And this entailed drinking four pints of Guinness as the build-up and match was under way, and I'm tucking into my fifth now. So f*** knows how coherent this article will be. The up-side is that I wrote the code for this beforehand :-S

OK, so the framing for this article is the previous article: "JavaScript: getting my brain around Promises", and my admission here is that I didn't actually get my brain entirely around JavaScript promises. I set my bar slightly too high (or: just wrong) for how I'd expect JavaScript to work, as it turns out. I'm spoilt by CFML, I guess. I'll update key points of that article, but make sure to read that one first as it's still mostly all right (IMO), and this article just clarifies a coupla points I didn't quite "get" last time.

My chief misapprehension was that JavaScript Promises themselves imparted some manner of asynchronicity to code execution, but this is not the case. They are just a handling mechanism for other code which itself is asynchronous. Once I wrote some code that respected that, things made more sense to me.

Here are some examples of how Promises help streamlining async code.

Saturday, 27 June 2015

CFML: Slack

G'day:
Ages ago I encouraged ppl to join us on the ##coldfusion IRC channel ("I... aaaah... see"). Thanks to the likes of Ryan, Dan and Sean, I was introduced to the new #cfml slack channel last night, which seems to be mostly like IRC, but given a C21st treatment to the UI & UX. So I think I'll probably migrate over there.

If you're a CFML dev of any stripe, get yerself over there. There's separate sub-channels for ColdFusion and Lucee (and FW/1), and - trust me - it's the most expedient way of a) getting help with CFML issues; b) networking with other CFML community members. If yer a CFML dev you should be wanting to do both of those things.

CFML: I did not realise one cannot nest threads in CFML

G'day:
This is peer-group pressure at work. On IRC, Sean mentioned that in CFML (ColdFusion, Railo, Lucee... I have to admit I didn't think to look at OpenBD), one cannot nest thread calls. I was really surprised by this for a coupla reason:
  1. I was sure I would have - at some point - tried to do this. Even by accident.
  2. I couldn't see a good reason why.
Not that I doubted Sean, but he sugggested I did some investigation and write it up. I'm en route to Galway right now (ie: as I type I'm flying over Ireland), and I've had enough time to finish my previous article ("PHP: getting PHP 5 and PHP 7 running side by side on the same machine (a better way)"), and write the code for this article. So here goes.

Monday, 1 December 2014

Hammers and screws (and when not to use a list in CFML)

G'day:
I hope Salted (/Ross) and Ryan don't mind me pinching our IRC conversation for a blog article, but... well... too bad if they do. It's done now. This is it.

Ross was asking "whats the most efficient way to remove the first two items in a list and get back the remainder", which made my eyes narrow and decide there's probably something to get to the bottom of here. Because he mentioned "lists". And these should - in general - be avoided in CFML.



After some back and forth with Ryan, Ross settled on:

listtoarray(foo," "), arrayslice(bar,3), arraytolist(bar," ")


(pseudo code, obviously).

Now... I think lists are overused in CFML, and - indeed - they are a bit rubbish. Having a string of data and then using one character (OK, or "some characters ~") from the string as a delimiter is seldom going to work, especially with the default delimiter of comma. Because in really a lot of situations, commas are actually part of the data. And same with any other char-based delimiter (except say characters specifically intended to be delimiters like characters 28-31 (file, group record and unit separators, respectively). I really don't think lists should generally be part of a solution to anything.

With this in mind, I decided to check what was going on. This is copy-and-pasted from the IRC log (spelling and formatting addressed, otherwise it's unabridged):

16:36 <adam_cameron> Salted: first question that should be asked... why is it a list in the first place? Do you have any control over it?
16:36 <Salted> no, it's returned from a postcode lookup service
16:36 <Salted> I'm fairly certain that the address string will always have the postcode first so [p1] [pt2] [line1]
16:37 <Salted> it's not a list its a string but I'm treating it as a space delimited list for these purposes...
16:37 <adam_cameron> so it's a string? Not a list per se?
16:37 <adam_cameron> ok
16:37 <Salted> indeed
16:37 <adam_cameron> So what you actually want is everything after the second space?
16:37 <Salted> essentially yes
16:37 <adam_cameron> Not a list with the first two elements dropped off
16:37 <Salted> in this instance what you've mentioned is one and the same, if I treat it as a list
16:38 <adam_cameron> well literally, yes. However once you start treating it as a list, you're thinking about it wrong
16:39 <Salted> I don't see how thats different from thinking of strings as char arrays, for example
16:40 <Salted> "my name is ross" is both a char array of 14 elements and a list of 4 elements
16:40 <adam_cameron> because you start trying to use list functions on it
16:40 <adam_cameron> Which makes your code shit


My point here - one that Ross doesn't entirely agree with - is that just because one can use a string as a list, doesn't mean - semantically - it is a list. And one should try to keep one's code as semantically clear as possible.

What Ross has here is not a space-separated list. Later in the conversation I extracted form him what the actual data was like, and this was a sample:

X1 2YZ Apartment 1903, 10 Random Street Suburbia, OURTOWN


What we have here is... a mess. It can be assessed in a number of ways:

  • a post code part followed by an address part
  • a post code followed by a street address followed by a city
  • a post code followed by the street part of the address, the suburb part of the address, and the city part of the address
But what it isn't is a space- (or comma-, or anything-) separated list. So one should not solve this problem using lists.

One should look at the actual requirement, and solve that.

Thursday, 20 November 2014

Railo "unexpected" behaviour: opinions solicited

G'day:
This will be one of those really quick ones as I have precisely 19min of lunchtime left to write it.

Ryan Guill found some oddness with Railo yesterday, with code like this:

function tikiOtinga(required string s required numeric i){
    writeDump(arguments);
}

(his example wasn't in Maori, but hey).

Can you spot what's wrong with it?

Friday, 15 November 2013

Synthesised accessors & variable scope

G'day:
Whilst vegetating at home last night, I had a look at some code Ryan Guill had posted on the ColdFusion IRC channel. It relates to ColdFusion's ability to automatically create accessors on CFC properties, if told to do so. He was seeing some "unexpected" behaviour.

Friday, 1 November 2013

CFML: More on inappropriate use of <cfinclude>

G'day:
I didn't expect to be revisiting this topic - let's face it, it's definitely "slow news day" material - but Ryan Guill, who I chat to on IRC, put me onto this one, and it was intriguing enough to follow-up.

And it's a slow news day.

So previously I wrote this article: "<cfinclude> and JavaScript", which discussed what happens when a non-CFM file gets included.

Disclaimer:

Just in case it's not abundantly apparent from the title of the article or the observations I make as I go: I do not mean this exercise to suggest I recommend the practice detailed below.


Ryan's variation on this is what happens when including a CFC file. Interesting. So I tried that: