Weekly Challenge #088 Task #2 :: {Off The Challenge}
Tags: perl, raku, haskell, perlweeklychallenge
Published: 2020-11-30 04:58:18

I checked other's code after finishing my solutions, and I found that -- again -- many creative solution are waiting for me.

some solution shows that
1. read top of the matrix
2. cut top of the matrix
3. turning matrix count clock wise
4. until matrix exists go for another round.

This is simple and elegant solution I believe. and this is best solution in Raku. because Raku generally doesn't like many flow control and variables.

Here is the [Code](https://github.com/manwar/perlweeklychallenge-club/blob/master/challenge-088/juliodcs/raku/ch-2.raku) from juliodcs @ PWC

So I follow the step and make another solution for Haskell Task #2
```haskell
import Data.List (groupBy, transpose, unfoldr)
import Data.Maybe (catMaybes)

{- tested with:
echo "[a b c d][e f g h][i j k l]" | runhaskell ch-2.hs
echo "[1 2 3][4 5 6][7 8 9]" | runhaskell ch-2.hs
echo "[a b][c d][e f]" | runhaskell ch-2.hs
-}

getMatrixFromStdin :: IO [[String]]
getMatrixFromStdin =
  ( map words
    . filter ((0/=).length)             -- 5. (after 3) there is some empty row
    . map (filter (`notElem` "[]"))     -- 4. '[', ']' is not used
    . lines                             -- 3. devide it into rows
    . unlines                           -- 2. make it "]\n"
    . groupBy (\_ b -> b/= ']') )       -- 1. devide row by "]"
  `fmap` getContents

cutTopAndRotateCCW :: [[String]] -> Maybe [[String]]
cutTopAndRotateCCW mat
  | length mat <= 1 = Nothing
  | otherwise = Just $ ( reverse . transpose . drop 1 ) mat

getSpiralAarray :: [[String]] -> [String]
getSpiralAarray mat =
  foldr1 (++)
  ( unfoldr (\m ->
                 case m of
                   Nothing -> Nothing
                   Just m' -> case (cutTopAndRotateCCW m') of
                               Nothing   -> Just (topOf m', Nothing)
                               Just  m'' -> Just (topOf m', Just m''))
      (Just mat) )
  where topOf m = head m

main = do
  getSpiralAarray `fmap` getMatrixFromStdin
  >>= print
```

This is elegant solution. but I'm just curious how fast in real world? this solution definitely interpreted faster than [my previous solution](https://github.com/manwar/perlweeklychallenge-club/blob/master/challenge-088/jeongoon/haskell/ch-2.hs) because it is just simpler in length of code.

So I run 100 times for same matrix with each solution.

Firstly, I complied the code
```sh
> ghc -O2 ch-2.hs
> ghc -O2 ch-2a.hs
```

Secondly, I prepare the matrix by using Raku (100x100 matrix)
```perl
> my $fh = open "test.txt", :ra; my $a = 1; (^100).map( { $fh.say((^100).map( { $a++ } )) } ); close $fh;
```

Finally, compare them

**original solution**
```sh
time for i in (seq 1 100); cat haskell/test.txt | ./haskell/ch-2 > /dev/null; end

________________________________________________________
Executed in    2.97 secs   fish           external 
   usr time    2.71 secs   50.90 millis    2.66 secs 
   sys time    0.36 secs   76.69 millis    0.29 secs 
```

**new simple solution**
```sh
time for i in (seq 1 100); cat haskell/test.txt | ./haskell/ch-2a > /dev/null; end

________________________________________________________
Executed in    6.41 secs   fish           external 
   usr time    6.06 secs   42.69 millis    6.02 secs 
   sys time    0.45 secs   75.69 millis    0.37 secs 
```

But if the matrix is simpler, less difference expected.

## **Raku Has Different Story**
[This Link](https://github.com/manwar/perlweeklychallenge-club/blob/master/challenge-088/feng-chang/raku/ch-2.raku) a solution from feng-chang @ PWC
and the speed is fascinating.
```sh
time cat ~/my.github/pwc-by-me/088/haskell/test.txt | raku spiral-test.feng-chang.raku > /dev/null

________________________________________________________
Executed in  620.94 millis    fish           external 
   usr time  845.44 millis    0.00 micros  845.44 millis 
   sys time   47.49 millis  1321.00 micros   46.17 millis 
```

my solution is much slower than that. 😂
```sh
time cat ~/my.github/pwc-by-me/088/haskell/test.txt | raku ~/my.github/pwc-by-me/088/raku/ch-2.raku ^/dev/null > /dev/null
time cat 100x100.txt | raku ~/my.github/pwc-by-me/088/raku/ch-2.raku > /dev/null                                                       2116ms  Mon 30 Nov 2020 21:07:20
Input: (Ctrl-D or Ctrl-Z to finish to input.)

________________________________________________________
Executed in    2.04 secs   fish           external 
   usr time    2.58 secs  1042.00 micros    2.58 secs 
   sys time    0.08 secs  129.00 micros    0.08 secs 
```
But frankly speaking, I'm not very satisfied with the result. Raku is still mystery for me. but it is worth to learn.
If looking at the history of the common-lisp, we can see well-designed language will survive eventually!!!

Thank you!! That's all for today.