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
- read top of the matrix
- cut top of the matrix
- turning matrix count clock wise
- 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 from juliodcs @ PWC
So I follow the step and make another solution for Haskell Task #2
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 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
> ghc -O2 ch-2.hs
> ghc -O2 ch-2a.hs
Secondly, I prepare the matrix by using Raku (100x100 matrix)
> my $fh = open "test.txt", :ra; my $a = 1; (^100).map( { $fh.say((^100).map( { $a++ } )) } ); close $fh;
Finally, compare them
original solution
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
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 a solution from feng-chang @ PWC
and the speed is fascinating.
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. 😂
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.
Top comments (0)