Powering to the origin
Weekly challenge 349 — 24 November 2025
Week 349: 24 Nov 2025
You are given an instruction string made up of U (up), D (down), L (left) and R (right). Write a script to return true if, following the instructions, you meet the starting point (0,0).
Example 1 Input: $path = 'ULD' Output: false (-1,1) <- (0,1) | ^ v | (-1,0) (0,0) Example 2 Input: $path = 'ULDR' Output: true (-1,1) <- (0,1) | ^ v | (-1,0) -> (0,0) Example 3 Input: $path = 'UUURRRDDD' Output: false (0,3) -> (1,3) -> (2,3) -> (3,3) ^ | | v (0,2) (3,2) ^ | | v (0,1) (3,1) ^ | | v (0,0) (3,0) Example 4 Input: $path = 'UURRRDDLLL' Output: true (0,2) -> (1,2) -> (2,2) -> (3,2) ^ | | v (0,1) (3,1) ^ | | v (0,0) <- (1,0) <- (1,1) <- (3,0) Example 5 Input: $path = 'RRUULLDDRRUU' Output: true (0,2) <- (1,2) <- (2,2) | ^ v | (0,1) (2,1) | ^ v | (0,0) -> (1,0) -> (2,1)
It pays to read the small print! My first reading was that we were to apply all the instructions and say whether we were back at the origin. There are some very concise ways to do that based on it boiling down to:
count of Us == count of Ds && count of Rs == count of Ls
But that's not what it says, as illustrated by example 5: we are to stop if at any intermediate point we are back at the origin.
So this boils down to applying the moves one by one and
checking for $x == 0 && $y == 0, and of course that can easily
be coded with something like:
if ($c eq 'U') {$y ++} elsif ($c eq 'D') ...
But that's rather messy. My next thought was to have 4
mini subroutines such as sub U { $y ++ } and then just
cycle though the instructions doing &$c(). But there are
two snags to that.
The first is that in order for the
mini-subs to use the global (to them) values of $x
and $y, those have to be declared outside the main
sub meeting_point, which doesn't look nice.
The second is that Perl is rightly suspicious of calling
a sub whose name is derived from dirty data, and while that
can be overcome with no strict I don't think that
is good practice.
So I have gone with a hash of operations corresponding
to each direction, so that, for example, $shift{'U'} is the
string $y++. I can then simply eval($shift{$_})
for each instruction, stopping if I am back at (0, 0).
This is neat and tidy - and works - but eval is a
lot slower than a sub call, and would not be a good
choice if the string was very long - say millions of characters.
But I tried it with a million random characters from UDLR
and it only took 20 seconds and returned 'false', so had made
all million moves. So that's probably good enough.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2025-11-24 use utf8; # Week 349 - task 2 - Meeting point use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; meeting_point('ULD'); meeting_point('ULDR'); meeting_point('UUURRRDDD'); meeting_point('UURRRDDLLL'); meeting_point('RRUULLDDRRUU'); sub meeting_point { my (@moves, %shift, $x, $y); # initialise @moves = split('', $_[0]); %shift = (R => '$x++', L => '$x--', U => '$y++', D => '$y--'); $x = $y = 0; # apply moves for (@moves) { eval($shift{$_}); last if ($x == 0 and $y == 0); } say qq[\nInput: $_[0]]; say qq[Output: ] . ($x == 0 && $y == 0 ? 'true' : 'false'); }
Input: ULD Output: false Input: ULDR Output: true Input: UUURRRDDD Output: false Input: UURRRDDLLL Output: true Input: RRUULLDDRRUU Output: true
Any content of this website which has been created by Peter Campbell Smith is in the public domain