use warnings; use strict; my $s = @ARGV ? $ARGV[0] : "82665409266027476709324472"; use List::Util qw"min"; sub zip { my($p, $x, $y) = @_; map { scalar &$p($$x[$_], $$y[$_]) } 0 .. min(@$x - 1, @$y - 1); } sub zipadj2 { my($p, @y) = @_; zip $p, [@y[0 .. @y - 2]], [@y[1 .. @y - 1]]; } sub scanr1 (&@) { my($p, @y) = @_; my @r = my $m = pop @y; for my $y (reverse @y) { unshift @r, ($m = &$p($y, $m)); } @r; } sub maxind { my(@y) = @_; my($p, $m) = (0, $y[0]); for my $i (1 .. @y - 1) { if ($m < $y[$i]) { ($p, $m) = ($i, $y[$i]); } } wantarray ? ($p, $m) : $p; } my @s = split //, $s; my @d = map { do { no integer; $_ % 10 } } zipadj2 sub { my($a, $w) = @_; $a - $w }, @s; my $lu = sub { my($k) = @_; my($p, $m) = maxind scanr1 sub { my($x, $y) = @_; $x * (1 + $y) }, map { $k == $_ } @d; $p, $m + 1; }; my($p1, $l1) = &$lu(1); # decreasing my($p9, $l9) = &$lu(9); # increasing my($p, $l) = $l9 <= $l1 ? ($p1, $l1) : ($p9, $l9); print "The longest subsequence you want starts at position ", $p, " and has length ", $l, " and its contents are (", join("", @s[$p .. $p + $l - 1]), ").\n"; my $v = $s; substr $v, $p + $l, 0, ")"; substr $v, $p, 0, "("; print "In context, it's here: ", $v, ".\n"; __END__ #### import Data.Char (digitToInt, intToDigit); import Data.List (elemIndex); import Data.Maybe (fromJust); import System (getArgs); egin :: String; egin = "82665409266027476709324472"; zipadj2 :: (a -> a -> b) -> [a] -> [b]; zipadj2 p y = zipWith p (init y) (tail y); main = do { args <- getArgs; let { ss = head (args ++ [egin]); s = map digitToInt ss; d = map (flip mod 10) (zipadj2 (-) s); gr x y = x * succ y; lu k = let { h = scanr1 gr (map (fromEnum . (k ==)) d :: [Int]); mh = maximum h; } in (fromJust (elemIndex mh h), succ mh); pl1@(_, l1) = lu 1; pl9@(_, l9) = lu 9; (p, l) = if l9 <= l1 then pl1 else pl9; fs = map intToDigit; }; putStr ("The longest subsequence you want starts at position " ++ show p ++ " and has length " ++ show l ++ " and its contents are (" ++ fs (take l (drop p s)) ++ ").\n" ++ "In context, it's here: " ++ fs (take p s) ++ "(" ++ fs (take l (drop p s)) ++ ")" ++ fs (drop l (drop p s)) ++ ".\n"); };