Myoungjin Jeon

Posted on

# Weekly Challenge #084 Task #1 :: (Raku)

## 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 !!!