Skip to content

Instantly share code, notes, and snippets.

@vividsnow
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vividsnow/d699187a4aef63d0ffaa to your computer and use it in GitHub Desktop.
Save vividsnow/d699187a4aef63d0ffaa to your computer and use it in GitHub Desktop.
integer value fold wrap in interval
use strict; use warnings;
use feature 'say';
use List::MoreUtils 'minmax';
# usage: fold_wrap.pl 10 4 8
say "wrap: ".wrap(@ARGV);
say "fold: ".fold(@ARGV);
sub wrap {
use integer;
my ($pos, $mn, $mx) = ($_[0], minmax $_[1], $_[2]||0);
return $mn if $mn == $mx;
return $pos if $pos >= $mn && $pos <= $mx;
my $l = 1 + abs $mx - $mn;
my $d = (my $down = $pos < $mn) ? $mn - $pos : $pos - $mx;
return $down ? $mn : $mx if (my $m = $d % $l) == 0;
$m--;
$down ? $mx - $m : $mn + $m }
sub fold {
use integer;
my ($pos, $mn, $mx) = ($_[0], minmax $_[1], $_[2]||0);
return $mn if $mn == $mx;
return $pos if $pos >= $mn && $pos <= $mx;
my $l = abs $mx - $mn;
my $d = (my $down = $pos < $mn) ? $mn - $pos : $pos - $mx;
my $m = $d % $l;
my $is_odd = $d / $l % 2;
( $is_odd ? $down : !$down ) ? $mx - $m : $mn + $m }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment