Half-reverse a binary string
Python 2, 64 69 bytes
def f(s):p=(s+s).find(s,1);return[s[~p::-1],s+s[:p]][len(s)/p%2]
Ungolfed:
def f(s):
p = (s+s).find(s,1)
n = len(s)/p
return s[:p][::1|n%-2] * -~(n-1^1)
This finds the string's period, i.e. the minimal p
such that s
is a string of length p
repeated n
times (I found a golfy method on SO). Then if n
is odd, it adds one more repetition of the period. If n
is even, it removes one repeat of the period and reverses it.
Thanks to @Sp3000 for helping to implement the function mapping between 1<->2, 3<->4, etc.
Perl, 49 47 bytes
Includes +2 for -lp
Based on @feersum's very nice algorithm
Run with input on STDIN, e.g.
perl -lp halfreverse.pl <<< "101001"
halfreverse.pl
:
/^(.+?)((\1\1?)*)$/;$_=$3eq$1?reverse$2:$_.$1
Explanation
/^ $/ Match the complete input string
(.+?) Non-greedy match. Try only one digit at the start,
if that doesn't work try 2, then 3 etc. The string
being tried is remembered in backreference \1
((\1\1?)*) Try to repeat \1 as many times as possible but
prefer in groups of 2. Fall back to only 1 at the
end of the string if the trailing part has an odd
number of \1 (so the total count is even)
$3eq$1 So the last match $3 equals the first match $1
? if and only if the total count is even
reverse$2 If total count is even drop the first instance of
: \1 and reverse
$_.$1 If total count is odd extend $_ by one instance
$_= Assign result