TASK #1 › Reverse Integer
Submitted by: Mohammad S Anwar
You are given an integer $N.
Write a script to reverse the given integer and print the result. Print 0 if the result doesn’t fit in 32-bit signed integer.
The number 2,147,483,647 is the maximum positive value for a 32-bit signed binary integer in computing.
Example 1:
Input: 1234
Output: 4321
Example 2:
Input: -1234
Output: -4321
Example 3:
Input: 1231230512
Output: 0
32 bit in 2020??
Looks easy for me because .flip method... but actually needed more time to get used to 32-bit singed integer
To express a signed integer in 8 bit, one precious bit needs to be sacrificed to express both positive and negative value. and somehow positive-side seems to decide to give their be-loved single bit to negative-team. (of course there is a reason)
I'm not a computer scientist.. I don't understand them all, but more interestingly 2³¹ - 1
(2147483647) is also a prime number. Let's listen what Raku is about to say 🎤
> is-prime(2³¹ - 1).raku.say
Bool::True
Okay Raku told us in formal way but we can simply understand it as "True".
Flip
> 123.flip
321
looks like a solution. done. however we need to filter the result.
the number seen as above can be rewritten like below as well.
> 1 +< 32 -1 # when positive integer
2147483647
negative don't need to subtract 1 from the number
So when we have "1231230512", flip the string and compare it with (2³¹ - 1). don't we?
> "1231230512".flip
2150321321
> 2150321321 < 2³¹ - 1
False
oh... a something have changed my mind.
Overflow
My laptop is 64bit machine I don't really need to worry about 32 bit but.. maybe this is one more hidden task. writing the solution as if we are using 32 bit machine. so we cannot make a number above (2³¹ - 1) because after that we will get negative value. What a temper it is.
So thinking about the limit we can maybe compare the number as a string
String Comparison is Not The Same Thing
One more problem we have is that string comparison is not acting as like a integer one.
for example
> 123 <=> 456
Less
> "123" cmp "456"
Less
> 45 <=> 123
Less
> "45" cmp "123"
More # ????
So I decided to compare the length of both numbers before string comparison. and I had got another problem.
300
> 300.flip # or "300".flip or 300.Str.flip
003
003 means 3 and the length of the "300" is 3 but length of "3" is now "1" again. So starting all the Persian must be destroyed. (What a racist !!!👿) and I used the regular expression here.
> S/^0+// with (300.Str.flip)
3
📚 S//
Subroutines I Made
To check limitation, I made a subroutine to get the number(absoulte)
sub abslim (Str $n, $bit = 32) {
(1 +< $bit.pred) - ($n.substr(^1) ne "-")
}
To reverse(or flip) the string ..
sub rev-int ( Int $n --> Str ) {
("","-")[+($n < 0)] ~ $n.abs.flip
}
I applied abs before flip to handle negative value as well. and get a side effect of removing any "+" sign mark before proceeding.
and prepend the "-" sign if needed.
To filter the number I used a little twisted syntax by using List or Hash because sometimes I missed the functional programming style declaration of a variable(actually a function).
sub filter32bit( Str $nstr ) {
# assume this is 32bit machine
# so this will get a reversed string (with sign prepended)
# and compare it with limit value as strings
my $lstr = abslim($nstr).Str;
my $nstr-abs = S/^0+// # remove zeroes in the beginging. for better cmp.
with $nstr.subst("-",""); # disgard the sign as well.
say "[FLTR] ",($nstr-abs gt $nstr ?? "-" !! ""),$lstr if $d;
# better read bottom up
($nstr.Int but "0",
$nstr.Int)[
( Less => True,
Same => $nstr lt $lstr,
More => False,
).Hash.{$nstr-abs.chars <=> $lstr.chars} ]
}
Final Code
I applied 📚∘ infix for my curiosity. so looks more unusual but it was fun!!!
our $d is export = False; # `export' is needed to use globaly
sub rev-int ( Int $n --> Str ) {
("","-")[+($n < 0)] ~ $n.abs.flip
}
# return absoulte value of limitation in 32 bit (without sign)
# with check sign of $n
sub abslim (Str $n, $bit = 32) {
(1 +< $bit.pred)-($n.substr(^1) ne "-")
}
sub filter32bit( Str $nstr ) {
# assume this is 32bit machine
# so this will get a reversed string (with sign prepended)
# and compare it with limit value as strings
my $lstr = abslim($nstr).Str;
my $nstr-abs = S/^0+// # remove zeroes in the beginging. for better cmp.
with $nstr.subst("-",""); # disgard the sign as well.
say "[FLTR] ",($nstr-abs gt $nstr ?? "-" !! ""),$lstr if $d;
# better read bottom up
($nstr.Int but "0",
$nstr.Int)[
( Less => True,
Same => $nstr lt $lstr,
More => False,
).Hash.{$nstr-abs.chars <=> $lstr.chars} ]
}
sub dmsg-tap (Any $a) { say("[DBG",$++,"] $a"); $a;};
multi MAIN (Int:D \N, Bool:D :$v = False) {
# side effect?: when use multi with MAIN (even though has a MAIN declared),
# raku gives a simple help message with invalid args.
my @solution-chain = &filter32bit, &rev-int;
my @speaker = ($v
?? |(&dmsg-tap) xx @solution-chain.elems # say each step
!! &say); # or just result
my @app-chain = (roundrobin @speaker, @solution-chain).flat;
if $v {
$d = True;
"the chain of subroutines looks like ...".say;
for (reverse @app-chain).kv -> $i, $r {
say "$i: {$r.raku}";
}
"and answer is ...\n".say;
}
([∘] @app-chain)(N);
# or we can save it as a variable and execute.
# but it was skipped as single usage.
# i.e.
# my $app = [∘] @app-chain;
# $app(N);
}
Thank you for reading~!!
please visit 🐪🦋PWC for more challenge and further update !!!
Top comments (0)