There was a funny post on Twitter a couple of days ago about a recent event where the "Dutch government was forced to release the source code of their DigiD digital authentication iOS app" with this piece of C# code:
Some very funny discussions continued, with comments about how good or bad this code is, and how one might rewrite it in various ways. I thought it would be a fun opportunity to show a few variations of this simple function in Factor.
Implementations
A direct translation of this code, might use cond which is basically a sequence of if
statements:
: get-percentage-rounds ( percentage -- str ) { { [ dup 0.0 <= ] [ drop "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪" ] } { [ dup 0.0 0.1 between? ] [ drop "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪" ] } { [ dup 0.1 0.2 between? ] [ drop "🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪" ] } { [ dup 0.2 0.3 between? ] [ drop "🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪" ] } { [ dup 0.3 0.4 between? ] [ drop "🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪" ] } { [ dup 0.4 0.5 between? ] [ drop "🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪" ] } { [ dup 0.5 0.6 between? ] [ drop "🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪" ] } { [ dup 0.6 0.7 between? ] [ drop "🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪" ] } { [ dup 0.7 0.8 between? ] [ drop "🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪" ] } { [ dup 0.8 0.9 between? ] [ drop "🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪" ] } [ drop "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵" ] } cond ;
But since this is a series of if
statements checked sequentially, you can just check the upper bounds. And since we only care about the argument for the comparison, we can use cond-case:
: get-percentage-rounds ( percentage -- str ) { { [ 0.0 <= ] [ "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪" ] } { [ 0.1 <= ] [ "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪" ] } { [ 0.2 <= ] [ "🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪" ] } { [ 0.3 <= ] [ "🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪" ] } { [ 0.4 <= ] [ "🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪" ] } { [ 0.5 <= ] [ "🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪" ] } { [ 0.6 <= ] [ "🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪" ] } { [ 0.7 <= ] [ "🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪" ] } { [ 0.8 <= ] [ "🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪" ] } { [ 0.9 <= ] [ "🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪" ] } [ drop "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵" ] } cond-case ;
One suggestion was to generate a substring based on the input — with the somewhat negative aspect that it allocates memory for the returned string when called:
: get-percentage-rounds ( percentage -- str ) 10 * 10 swap - >integer dup 10 + "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪" subseq ;
But another way would be to just index into the possible results, using quoted words to reduce the amount of tokens involved — resulting in this fairly aesthetic result:
: get-percentage-rounds ( percentage -- str ) 10 * ceiling >integer qw{ ⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪ 🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪ 🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪ 🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪ 🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪ 🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪ 🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪ 🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪ 🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪ 🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪ 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 } nth ;
It's always fun to see different ways to solve problems. In the Twitter thread, that includes using binary search, building the output character-by-character, generating solutions using ChatGPT, one-liners in Python, pattern matching, unit testing, and discussions of edge cases and naming conventions.
No comments:
Post a Comment