CodeWars 6 Kyu: Reverse or rotate?
I wrote my Javascript "hello world" on Thursday, so I'm definitely a JS beginner. I do have some experience in Python though, so I'm not a complete novice to programming in general.
Question
The input is a string
str
of digits. Cut the string into chunks (a chunk here is a substring of the initial string) of sizesz
(ignore the last chunk if its size is less thansz
).If a chunk represents an integer such as the sum of the cubes of its digits is divisible by 2, reverse that chunk; otherwise rotate it to the left by one position. Put together these modified chunks and return the result as a string.
If
sz
is<= 0
or if str is empty return""
sz
is greater(>)
than the length ofstr
it is impossible to take a chunk of sizesz
hence return""
.Examples:
revrot("123456987654", 6) --> "234561876549"
revrot("123456987653", 6) --> "234561356789"
revrot("66443875", 4) --> "44668753"
revrot("66443875", 8) --> "64438756"
revrot("664438769", 8) --> "67834466"
revrot("123456779", 8) --> "23456771"
revrot("", 8) --> ""
revrot("123456779", 0) --> ""
revrot("563000655734469485", 4) --> "0365065073456944"
Solution
function revrot(str, sz)
{
ln = str.length;
if(sz < 1 || !str || sz > ln) return "";
const test = s => Array.prototype.reduce.call(s, (acc, val) => acc + Number(val) ** 3, 0) % 2 === 0;
const reverse = s => s.split("").reverse().join("");
const rotate = s => s.slice(1) + s.slice(0, 1);
let arr = [];
for(let i = 0; i < ln; i += sz) arr.push(i+sz <= ln ? str.slice(i, i+sz) : "")
return arr.map(x => test(x) ? reverse(x) : rotate(x)).join("");
}
1 Answer 1
Towards optimization and restructuring
One of downsides of the initial revrot
approach is that all nested functions test
, reverse
and rotate
will be redundantly recreated on each revrot
call.
Instead - define them as top-level functions with meaningful names.
Next, the program lacks 2 edge cases:
when input string contains one single digit and size of required chunk is also
1
(ex.revrot("3", 1)
). It's worth to catch that case immediately and return the unchanged input stringwhen input string contains non-digit character
The intermediate arr
array with for
loop and slice
calls (to get all chunks) is replaced with convenient String.match
call on dynamic regex pattern new RegExp(`.{${size}}`, 'g')
(matches substrings of specific length/size)
The final optimized approach:
const testCubes = s => Array.prototype.reduce.call(s, (acc, val) => acc + Number(val) ** 3, 0) % 2 === 0;
const strReverse = s => [...s].reverse().join("");
const rotateLeft = s => s.slice(1) + s.slice(0, 1);
function revrot(str, size) {
let len = str.length;
if (size < 1 || !str || size > len) return "";
if (len === 1 && size === 1) return str;
if (/\D/.test(str)) {
throw Error("Invalid numeric string");
}
let pat = new RegExp(`.{${size}}`, 'g');
return str.match(pat).map(x =>
testCubes(x) ? strReverse(x) : rotateLeft(x)
).join("");
}
console.log(revrot("123456987654", 6));
console.log(revrot("123456987653", 6));
console.log(revrot("66443875", 8));
console.log(revrot("563000655734469485", 4));
console.log(revrot("1", 1));
console.log(revrot("6644-d3875", 8));
-
\$\begingroup\$ Your answer seams to contradict its self. You say don't nest functions yet you declare one inside
map
. Anyways modern JS engines cache functions.. There is no overhead associated with nested functions and it is good practice to encapsulate function within the scope they are used in. -1 \$\endgroup\$Blindman67– Blindman672019年12月23日 22:27:44 +00:00Commented Dec 23, 2019 at 22:27 -
\$\begingroup\$ @Blindman67, I don't agree regarding nested functions and don't want wasting my time for such doubtful debates. \$\endgroup\$RomanPerekhrest– RomanPerekhrest2019年12月24日 05:51:38 +00:00Commented Dec 24, 2019 at 5:51
-
\$\begingroup\$ "...doubtful debate.."? This is not a "debate".A performance test is all that is needed to show that moving the functions out makes no difference (a little slower due to longer scope chain lookups). Additionally I down voted because your function, is a good 25% slower than the OP's, throws a un-required error (feature creep) The error is inconsistent
revrot("aa",1)
throws whilerevrot("a",1)
does not and for ill formed args should be aRangeError
. Also and not part of down vote but your edge cases missed the most obvious optimizationif (size === 1) { return str }
\$\endgroup\$Blindman67– Blindman672019年12月24日 13:33:50 +00:00Commented Dec 24, 2019 at 13:33
Explore related questions
See similar questions with these tags.