From f3b73a726dfa294a9e585ed93284d41498a1a0e0 Mon Sep 17 00:00:00 2001 From: Myoungjin JEON Date: Wed, 25 Nov 2020 21:55:37 +1100 Subject: [ch-087/jeongoon] ch-2.hs added --- challenge-087/jeongoon/haskell/ch-2.hs | 106 +++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 challenge-087/jeongoon/haskell/ch-2.hs diff --git a/challenge-087/jeongoon/haskell/ch-2.hs b/challenge-087/jeongoon/haskell/ch-2.hs new file mode 100644 index 0000000000..02328a8458 --- /dev/null +++ b/challenge-087/jeongoon/haskell/ch-2.hs @@ -0,0 +1,106 @@ +import System.Exit +import Data.List (isPrefixOf, groupBy, subsequences, union + , intersperse, replicate) +import Data.Char (digitToInt) +import qualified Data.Map as M + +{- tested with: +echo '[000111][111111][001001][001111][001111]' | runhaskell ch-2.hs + +-} + +-- solution +getMatrixFromStdin :: IO [[Int]] +getMatrixFromStdin = ( convertToInteger + -- . filterEmptyRow + . parseMatrixLines + . toMatrixLines ) `fmap` getContents + where + parseMatrixLines = map (filter (not.isPrefixOf " "). + groupBy (\a b -> a == ' ' && a == b). + filter (\c -> c `elem` " 10")) + toMatrixLines = lines . unlines . groupBy (\_ b -> b /= ']') + --filterEmptyRow = filter ((0/=).length) + convertToInteger = map (map (\x -> (map digitToInt x)!!0)) + + -- a line between column A to B +data ConsecutivePoints = ConsecutivePoints { begin :: Int, + end :: Int } + deriving (Eq, Ord, Show) + +groupByConsecutiveNumber_ :: (Eq a, Num a) => [a] -> [[a]] +groupByConsecutiveNumber_ = + foldl (\acc x -> if ((not.null) acc) + then if (x -(last (last acc))) == 1 + then (init acc) ++ [(last acc) ++ [x]] + else acc ++ [[x]] + else [[x]] ) [] + +getConsecutivePointsFromMatrix :: [[Int]] -> [(ConsecutivePoints, Int)] +getConsecutivePointsFromMatrix = + ( foldr (\x acc -> let (pts, r) = x + in acc ++ (map (\p -> (p, r)) pts) ) [] + . zipWithRowNum -- -> [([ConsecutivePoints], Int)] + . map ( map toConsecutivePoints + . consecutiveLinesFromIndices + . binariesToIndices ) ) + where + subsequences' = filter ((0<).length) . subsequences + binariesToIndices :: [Int] -> [Int] + binariesToIndices row = foldl (\acc x -> if ((1==).snd) x + then acc ++ [(fst x)] + else acc ) [] (zip [0..] row) + consecutiveLinesFromIndices :: [Int] -> [[Int]] + consecutiveLinesFromIndices = ( foldr (++) [] -- flatten + . map subsequences' + . groupByConsecutiveNumber_ ) + zipWithRowNum = (flip zip) [0..] + + toConsecutivePoints :: [Int] -> ConsecutivePoints + toConsecutivePoints = (\xs -> ConsecutivePoints (head xs) (last xs)) + +groupByConsecutivePoints :: [(ConsecutivePoints, Int)] + -> [(ConsecutivePoints,[Int])] +groupByConsecutivePoints ls = (M.toList . M.fromListWith union) + $ map (\(k,v) -> (k,[v])) ls + +groupByArea :: [(ConsecutivePoints, [Int])] + -> [((ConsecutivePoints, [Int]), Int)] +groupByArea = + foldr (++) [] + . map (\(ps , rs) -> + map (\rs' -> ((ps, rs'), ((length rs') + * ((end ps) - (begin ps) + 1)))) + (groupByConsecutiveNumber_ rs)) + +findMaximumAreas :: [((ConsecutivePoints, [Int]), Int)] + -> [((ConsecutivePoints, [Int]), Int)] +findMaximumAreas = foldr (\x@(_, area) acc -> + let maxarea = if null acc then 0 + else (snd.head) acc + in if area > maxarea then [x] + else if area == maxarea then acc ++ [x] + else acc) [] +showMaxAreas :: [((ConsecutivePoints, [Int]), Int)] -> [[String]] +showMaxAreas = + map (\((cpts, rs), area) -> + if area == 1 then [] + else let nc = (end cpts) - (begin cpts) + 1 + nr = length rs + in (replicate nr.intersperse ' '. replicate nc) '1') + +-- testing +main = do + aSample <- getMatrixFromStdin; + putStrLn "Given Matrix:" + mapM_ (putStrLn.unwords.map show) aSample + + if length aSample < 1 + then die "0 as given data is not sufficient" + else let visibleMaxAreas = ( showMaxAreas + . findMaximumAreas + . groupByArea + . groupByConsecutivePoints + . getConsecutivePointsFromMatrix ) aSample + in if null visibleMaxAreas then putStrLn "0" + else mapM_ (mapM_ putStrLn) visibleMaxAreas -- cgit From 6bebdc5ac2c140f354a90face0ddf5739e1f7e84 Mon Sep 17 00:00:00 2001 From: Myoungjin JEON Date: Wed, 25 Nov 2020 22:27:51 +1100 Subject: [ch-086/jeongoon] ch-1.hs added --- challenge-086/jeongoon/haskell/ch-1.hs | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 challenge-086/jeongoon/haskell/ch-1.hs diff --git a/challenge-086/jeongoon/haskell/ch-1.hs b/challenge-086/jeongoon/haskell/ch-1.hs new file mode 100644 index 0000000000..235f84e555 --- /dev/null +++ b/challenge-086/jeongoon/haskell/ch-1.hs @@ -0,0 +1,41 @@ +import System.Environment +import System.Exit +import Data.Char (isNumber) +import Data.Maybe (isNothing, catMaybes) +import Data.List (sort) + +{- tested with: +runhaskell ch-1.hs 1 3 2 -1 -2 -3 6 7 9 1 +1 as 3 -2 = 1 +-} + +usageMessage = "Usage: runhaskell ch-1.hs " + ++ " ..." + +pairDifference _ [] = Nothing +pairDifference target ls = pairdiff target (head sorted) (tail sorted) 1 + where + sorted = sort ls + pairdiff _ _ [] _ = Nothing + pairdiff t f rst@(r:_) i = -- t: target, f: first, i: index + if i >= (length rst) then Nothing + else case ((rst !! i) - f) `compare` t of + LT -> pairdiff t f rst (succ i) + GT -> pairdiff t r rst 1 + EQ -> Just (f, (rst !! i)) + +main = do + ints <- (catMaybes.map (\nStr -> + if (all isNumber nStr) then Just(read nStr :: Int) + else Nothing )) `fmap` getArgs; + + let d = (head ints) in + + if (length ints) < 2 + then die usageMessage + else if d < 0 + then die usageMessage + else case pairDifference d (tail ints) of + Nothing -> putStrLn "0" + Just (a,b) -> putStrLn $ "1 as " ++ (show b) ++ " - " + ++ (show a) ++ " = " ++ (show d) -- cgit From 33a55e5a133102653ae742d8641d1c2947795527 Mon Sep 17 00:00:00 2001 From: Myoungjin JEON Date: Wed, 25 Nov 2020 22:42:23 +1100 Subject: allow negative integer value as input --- challenge-086/jeongoon/haskell/ch-1.hs | 31 ++++++++++++++++--------------- challenge-087/jeongoon/haskell/ch-1.hs | 6 ++++-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/challenge-086/jeongoon/haskell/ch-1.hs b/challenge-086/jeongoon/haskell/ch-1.hs index 235f84e555..59a46bb9ec 100644 --- a/challenge-086/jeongoon/haskell/ch-1.hs +++ b/challenge-086/jeongoon/haskell/ch-1.hs @@ -6,7 +6,7 @@ import Data.List (sort) {- tested with: runhaskell ch-1.hs 1 3 2 -1 -2 -3 6 7 9 1 -1 as 3 -2 = 1 +1 as 3 - 2 = 1 -} usageMessage = "Usage: runhaskell ch-1.hs " @@ -25,17 +25,18 @@ pairDifference target ls = pairdiff target (head sorted) (tail sorted) 1 EQ -> Just (f, (rst !! i)) main = do - ints <- (catMaybes.map (\nStr -> - if (all isNumber nStr) then Just(read nStr :: Int) - else Nothing )) `fmap` getArgs; - - let d = (head ints) in - - if (length ints) < 2 - then die usageMessage - else if d < 0 - then die usageMessage - else case pairDifference d (tail ints) of - Nothing -> putStrLn "0" - Just (a,b) -> putStrLn $ "1 as " ++ (show b) ++ " - " - ++ (show a) ++ " = " ++ (show d) + (catMaybes.map (\nStr -> + -- poor parser + if (all (`elem` "0123456789+-") nStr) + then Just(read nStr :: Int) + else Nothing )) `fmap` getArgs + >>= ( \ints -> + let d = (head ints) in + if (length ints) < 2 + then die usageMessage + else if d < 0 + then die usageMessage + else case pairDifference d (tail ints) of + Nothing -> putStrLn "0" + Just (a,b) -> putStrLn $ "1 as " ++ (show b) ++ " - " + ++ (show a) ++ " = " ++ (show d) ) diff --git a/challenge-087/jeongoon/haskell/ch-1.hs b/challenge-087/jeongoon/haskell/ch-1.hs index dc2d24e980..23879e69f2 100644 --- a/challenge-087/jeongoon/haskell/ch-1.hs +++ b/challenge-087/jeongoon/haskell/ch-1.hs @@ -1,6 +1,5 @@ import System.Environment import System.Exit -import Data.Char (isNumber) import Data.Maybe (catMaybes) import Data.List (sort, sortBy) @@ -8,6 +7,7 @@ import Data.List (sort, sortBy) (only shows one answer) -} + answerLongestConsecutiveSequence :: [Int] -> [Int] answerLongestConsecutiveSequence = ( head @@ -22,7 +22,9 @@ answerLongestConsecutiveSequence = main = do (catMaybes.map (\nStr -> - if (all isNumber nStr) then Just(read nStr :: Int) + -- poor parser + if (all (`elem` "0123456789+-") nStr) + then Just(read nStr :: Int) else Nothing )) `fmap` getArgs >>= (\nums -> if length nums < 1 then -- cgit From 8178fe5e04e95cfbc20c8bb2d4210bc848cb76af Mon Sep 17 00:00:00 2001 From: Myoungjin JEON Date: Sun, 29 Nov 2020 22:46:46 +1100 Subject: [ch-088/jeongoon] Perl, Raku, Haskell, Go, Common-lisp, Elm Solution added --- challenge-088/jeongoon/common-lisp/ch-1.lsp | 29 +++++++ challenge-088/jeongoon/common-lisp/ch-2.lsp | 105 ++++++++++++++++++++++ challenge-088/jeongoon/elm/elm.json | 24 ++++++ challenge-088/jeongoon/elm/src/Ch1.elm | 18 ++++ challenge-088/jeongoon/elm/src/Ch2.elm | 79 +++++++++++++++++ challenge-088/jeongoon/elm/src/Main.elm | 129 ++++++++++++++++++++++++++++ challenge-088/jeongoon/fish/ch-1.fish | 16 ++++ challenge-088/jeongoon/go/ch-1.go | 47 ++++++++++ challenge-088/jeongoon/go/ch-2.go | 94 ++++++++++++++++++++ challenge-088/jeongoon/haskell/ch-1.hs | 13 +++ challenge-088/jeongoon/haskell/ch-2.hs | 81 +++++++++++++++++ challenge-088/jeongoon/perl/ch-1.pl | 20 +++++ challenge-088/jeongoon/perl/ch-2.pl | 74 ++++++++++++++++ challenge-088/jeongoon/raku/ch-1.raku | 15 ++++ challenge-088/jeongoon/raku/ch-2.raku | 75 ++++++++++++++++ 15 files changed, 819 insertions(+) create mode 100644 challenge-088/jeongoon/common-lisp/ch-1.lsp create mode 100644 challenge-088/jeongoon/common-lisp/ch-2.lsp create mode 100644 challenge-088/jeongoon/elm/elm.json create mode 100644 challenge-088/jeongoon/elm/src/Ch1.elm create mode 100644 challenge-088/jeongoon/elm/src/Ch2.elm create mode 100644 challenge-088/jeongoon/elm/src/Main.elm create mode 100644 challenge-088/jeongoon/fish/ch-1.fish create mode 100644 challenge-088/jeongoon/go/ch-1.go create mode 100644 challenge-088/jeongoon/go/ch-2.go create mode 100644 challenge-088/jeongoon/haskell/ch-1.hs create mode 100644 challenge-088/jeongoon/haskell/ch-2.hs create mode 100644 challenge-088/jeongoon/perl/ch-1.pl create mode 100644 challenge-088/jeongoon/perl/ch-2.pl create mode 100644 challenge-088/jeongoon/raku/ch-1.raku create mode 100644 challenge-088/jeongoon/raku/ch-2.raku diff --git a/challenge-088/jeongoon/common-lisp/ch-1.lsp b/challenge-088/jeongoon/common-lisp/ch-1.lsp new file mode 100644 index 0000000000..2ca1933fb3 --- /dev/null +++ b/challenge-088/jeongoon/common-lisp/ch-1.lsp @@ -0,0 +1,29 @@ +;; tested with sbcl --script ch-1.lsp 5 2 1 4 3 + +;;; Comment: +;; I thought (sort x #'<) is sorted in place of x +;; however, it didn't work properly until I did (setq x (sort x #'<)) + + +(defun get-command-line () + (or + #+CLISP *args* + #+SBCL *posix-argv* + #+LISPWORKS system:*line-arguments-list* + #+CMU extensions:*command-line-words* + nil)) + +(defparameter *cmdline* (get-command-line)) + +(defun print-usage () + (format t "Usage: sbcl --script ch-1.lsp ...")) + +(when (< (length *cmdline*) 1) (print-usage) (quit)) + +(defparameter *integer-list* (map 'list #'parse-integer (rest *cmdline*))) + +;; (solution ...) +(let ((p (reduce #'* *integer-list*))) + (format t "~A~%" (map 'list #'(lambda (x) (/ p x)) *integer-list*))) + +(quit) diff --git a/challenge-088/jeongoon/common-lisp/ch-2.lsp b/challenge-088/jeongoon/common-lisp/ch-2.lsp new file mode 100644 index 0000000000..8c926259de --- /dev/null +++ b/challenge-088/jeongoon/common-lisp/ch-2.lsp @@ -0,0 +1,105 @@ +;; tested with: +;; echo "[a b c][d e f][g h i] | sbcl --script ch-2.lsp + +(defun get-command-line () + (or + #+CLISP *args* + #+SBCL *posix-argv* + #+LISPWORKS system:*line-arguments-list* + #+CMU extensions:*command-line-words* + nil)) + +(defparameter *cmdline* (get-command-line)) +(defparameter *rows-list* '()) +(defvar row '()) +(defvar wrd nil) + +;; read from stdin +(loop for line = (read-line *standard-input* nil) + while line + do(loop for ch in (coerce line 'list) + do(if (char= ch #\[) + Nil ;; ignore + (if (or (char= ch #\]) (char= ch #\Newline)) + (progn + (when (not (null wrd)) + (let ((word-str (coerce wrd 'string))) + (if (null row) + (setq row (list word-str)) + (nconc row (list word-str)))) + (setq wrd '())) + (when (not (null row)) + (if (null *rows-list*) + (setq *rows-list* (list row)) + (nconc *rows-list* (list row))) + (setq row '()))) + (if (char= ch #\Space) + ;; add a word to row + (when (not (null wrd)) + (let ((word-str (coerce wrd 'string))) + (if (null row) + (setq row (list word-str)) + (nconc row (list word-str)))) + (setq wrd '())) + ;; else: add a char to word + (progn + (if (null wrd) + (setq wrd (list ch)) + (nconc wrd (list ch))))))))) + +(defparameter *num-rows* (length *rows-list*)) +(defparameter *num-cols* (length (first *rows-list*))) + +;; convert it into 2 dimensional array +(defvar *matrix* (make-array (list *num-rows* *num-cols*) + :initial-contents *rows-list*)) + +;; confirm input +(format t "given matrix:~%") +(dotimes (r *num-rows*) + (setq row (loop for c from 0 below *num-cols* + collect (aref *matrix* r c))) + (format t "[~{~a~^ ~}]~%" row)) + +;; ( solution ... ) +;; this solution is only for reading +;; so I haven't check for any side effect +(defun get-spiral-array (mat) ;; take 2 dimensional array + (let* ((num-rows (array-dimension mat 0)) + (num-cols (array-dimension mat 1)) + (sarray '())) ;; result + (loop for o from 0 + for row-end = (1- (+ o num-rows)) + for col-end = (1- (+ o num-cols)) + do (progn + ;; north + (let ((north-side (loop for c from o upto col-end + collect (aref mat o c)))) + (if (null sarray) + (setq sarray north-side) + (nconc sarray north-side))) + ;; east + (let ((east-side (loop for r from (1+ o) upto row-end + collect (aref mat r col-end)))) + (when (not (null east-side)) + (nconc sarray east-side) + ;; south + (let ((south-side + (loop for c from (1- col-end) downto o + collect (aref mat row-end c)))) + (when (not (null south-side)) + (nconc sarray south-side) + ;; west + (let ((west-side + (loop for r from (1- row-end) above o + collect (aref mat r o)))) + (when (not (null west-side)) + (nconc sarray west-side)))))))) + ;; go inner + do (progn (setq num-rows (- num-rows 2) + num-cols (- num-cols 2))) + while (and (< 0 num-rows) (< 0 num-cols))) + + sarray)) ;; return + +(format t "[~{~a~^ ~}]~%" (get-spiral-array *matrix*)) diff --git a/challenge-088/jeongoon/elm/elm.json b/challenge-088/jeongoon/elm/elm.json new file mode 100644 index 0000000000..dea3450db1 --- /dev/null +++ b/challenge-088/jeongoon/elm/elm.json @@ -0,0 +1,24 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.1.3", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.2" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} diff --git a/challenge-088/jeongoon/elm/src/Ch1.elm b/challenge-088/jeongoon/elm/src/Ch1.elm new file mode 100644 index 0000000000..18baf715d0 --- /dev/null +++ b/challenge-088/jeongoon/elm/src/Ch1.elm @@ -0,0 +1,18 @@ +module Ch1 exposing (..) + +import List as L + +errEmptyList = "Empty List" +errSomeIsNotPostive = "Some of Element is not Postive Interger" + +arrayOfProduct : List Int -> Result String (List Int) +arrayOfProduct ints = + let len = (L.length ints) + in + case len of + 0 -> Err errEmptyList + 1 -> Ok [1] -- not in the spec; probably correct answer + _ -> if (L.any (\x -> x < 1) ints) == True then + Err errSomeIsNotPostive + else let p = L.foldr (*) 1 ints + in Ok (L.map (\x -> p // x) ints) -- // -> int div. diff --git a/challenge-088/jeongoon/elm/src/Ch2.elm b/challenge-088/jeongoon/elm/src/Ch2.elm new file mode 100644 index 0000000000..1841c81750 --- /dev/null +++ b/challenge-088/jeongoon/elm/src/Ch2.elm @@ -0,0 +1,79 @@ +module Ch2 exposing (..) + +import List as L +import String as S +import Array as A +import Result as R + +errEmptyMatrix = "Matrix is Empty" + +parseMatrix : String -> Result String (List (List String)) +parseMatrix str = + let parsed = str -- Elm's nice syntax: read from top to bottom + |> S.split "]" + |> S.join "\n" + |> S.lines + |> L.map (S.replace "[" "" + >> S.words >> L.filter (S.isEmpty >> not)) + |> L.filter (L.isEmpty >> not) + in if L.isEmpty parsed + || (case L.head parsed of + Nothing -> True + Just fr -> L.isEmpty fr) then + Err errEmptyMatrix + else + Ok parsed + +getSpiralArray_ : (List (List String)) -> Int -> Int -> Int -> List String +getSpiralArray_ mat nr nc o = -- number of rows, number of column + let re = o + nr - 1 -- abs index number of row end + ce = o + nc - 1 -- abs index number of column end + north = case (L.drop o >> L.head) mat of + Nothing -> [] + Just rw -> (L.take (o+nc) >> L.drop o) rw + east = if nr <= 1 then [] + else mat + |> L.drop (o+1) + |> L.take (nr-1) + |> L.filterMap (L.drop ce >> L.head) + south = {-if L.isEmpty east then [] + else-} + if nc <= 1 then [] + else case (L.drop re >> L.head) mat of + Nothing -> [] + Just rw -> rw |> L.reverse + |> L.drop (o+1) |> L.take (nc-1) + west = {-if L.isEmpty south then [] + else-} + if nr <= 2 then [] + else mat + |> L.drop (o+1) + |> L.take (nr-2) + |> L.reverse + |> L.filterMap (L.drop o >> L.head) + + nr2 = nr - 2 + nc2 = nc - 2 + + in ( if re < 0 || ce < 0 then [] + else north :: if L.isEmpty east then [] + else east :: if L.isEmpty south then [] + else south :: if L.isEmpty west then [] + else west + :: [ getSpiralArray_ + mat nr2 nc2 (o+1) ] ) + |> L.concat + +getSpiralArray : (List (List String)) -> List String +getSpiralArray mat = + let nr = L.length mat + nc = case L.head mat of + Nothing -> -1 + Just rw -> L.length rw + in if nr > 0 && nc > 0 then getSpiralArray_ mat nr nc 0 + else [] + +getSpiralArrayFromString : String -> Result String (List String) +getSpiralArrayFromString str = + str |> parseMatrix + |> R.map getSpiralArray diff --git a/challenge-088/jeongoon/elm/src/Main.elm b/challenge-088/jeongoon/elm/src/Main.elm new file mode 100644 index 0000000000..7a051aca5f --- /dev/null +++ b/challenge-088/jeongoon/elm/src/Main.elm @@ -0,0 +1,129 @@ +{- Tested with: +elm make src/Main.elm +# and access elm/index.html in a web browser(firefox in my case) +# which shows Task1 and Task2 altogether +# or ... +elm reactor +# and access localhost:8000 (again in a web browser) +# and click `Main.elm' +-} + +module Main exposing (..) + +import Browser +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput) + +import String as S +import List as L +import Result as R + +-- Solutions ... +import Ch1 exposing (..) +import Ch2 exposing (..) + +-- Main + +main = + Browser.sandbox { init = init, update = update, view = view } + +-- Model +type alias Model = + { ch1IntListStr : String + , ch1Result : Result String (List Int) + , ch2MatrixStr : String + , ch2Result : Result String (List String) + } + +init : Model +init = Model "" (Err "") "" (Err "") + +-- Update + +type Task = Task1 +type Msg = ArrayProductValueChanged String + | SpiralMatrixValueChanged String + +getPositiveIntegerListFromString : String -> Result String (List Int) +getPositiveIntegerListFromString str = + let trimed_str = S.trim str + sls = (S.split " " trimed_str) + ints = L.filterMap S.toInt sls + in if S.length trimed_str == 0 then + Err "" -- indicate initial state + else if (L.length sls) == (L.length ints) then Ok ints + else Err "Some element doesn't look like a POSITIVE integer" + +update : Msg -> Model -> Model +update msg m = + case msg of + ArrayProductValueChanged nv -> + let res = (getPositiveIntegerListFromString nv + |> R.andThen Ch1.arrayOfProduct) + in { m | ch1IntListStr = nv + , ch1Result = res } + SpiralMatrixValueChanged nv -> + let res = Ch2.getSpiralArrayFromString nv + in { m | ch2MatrixStr = nv + , ch2Result = res } + +-- View + +view : Model -> Html Msg +view m = + div [ style "padding" "20px", style "width" "90%" ] + [ h1 [] [ text "Task1: Array Product" ] + , viewInput "text" "Positive Integers" m.ch1IntListStr + ArrayProductValueChanged + , displayAnswerCh1 m.ch1Result + , h1 [] [ text "Task2: Spiral Matrix" ] + , viewInputTextArea "Please Input a matrix data.\nex)\n[a b c]\n[d e f]\n[g h i]" + m.ch2MatrixStr SpiralMatrixValueChanged + , displayAnswerCh2 m.ch2Result + ] + +viewInput : String -> String -> String -> (String -> msg) -> Html msg +viewInput t p v toMsg = + div [ style "dispay" "inline-block" ] + [ input [ size 150, type_ t, placeholder p, value v, onInput toMsg ] []] + +viewInputTextArea : String -> String -> (String -> msg) -> Html msg +viewInputTextArea p v toMsg = + div [ style "display" "inline-block" ] + [ textarea [ rows 5, cols 150 + , placeholder p, value v, onInput toMsg ] [] ] + +displayAnswerCh1 : Result String (List Int) -> Html msg +displayAnswerCh1 result = + displayAnswer "Result" + (case result of + Ok ints -> Ok ("(" ++ (S.join "," + (L.map S.fromInt ints)) ++")") + Err e -> Err e) + +displayAnswerCh2 : Result String (List String) -> Html msg +displayAnswerCh2 result = + displayAnswer "Result" + (case result of + Ok words -> Ok ("(" ++ (S.join "," words) ++ ")") + Err e -> Err e) + + +displayAnswer : String -> Result String String -> Html msg +displayAnswer entryString result = + case result of + Ok msg -> div [] + [ viewReadOnlyTextArea "green" msg ] + Err e -> + if e == "" + then div [] + [ viewReadOnlyTextArea "blue" + (entryString ++ ": please input all the entries") ] + else div [] + [ viewReadOnlyTextArea "red" e ] + +viewReadOnlyTextArea : String -> String -> Html msg +viewReadOnlyTextArea color str = + textarea [ readonly True, style "color" color + , rows 15, cols 150, value str ] [] diff --git a/challenge-088/jeongoon/fish/ch-1.fish b/challenge-088/jeongoon/fish/ch-1.fish new file mode 100644 index 0000000000..f7b957360a --- /dev/null +++ b/challenge-088/jeongoon/fish/ch-1.fish @@ -0,0 +1,16 @@ +#!/usr/bin/env fish + +set all_product 1 +set M () + +for x in $argv + set all_product (math "$all_product x $x") +end + +set i 1 +for x in $argv + set M[$i] (math -s0 "$all_product / $x") + set i (math "$i + 1") +end + +echo "[$M]" diff --git a/challenge-088/jeongoon/go/ch-1.go b/challenge-088/jeongoon/go/ch-1.go new file mode 100644 index 0000000000..c18be3d9a1 --- /dev/null +++ b/challenge-088/jeongoon/go/ch-1.go @@ -0,0 +1,47 @@ +package main + +import ( + "os" + "fmt" + "strconv" +) + +func usage() { + fmt.Println( "Usage: go run ch-1.go ..." ) +} + +func main() { + switch len(os.Args[1:]) { + case 0: + usage() + os.Exit(1); + case 1: + fmt.Println("1") + os.Exit(0); + } + + var ns []int + + for _, nstr := range os.Args[1:] { + n, err := strconv.Atoi(nstr) + if err == nil { + ns = append(ns, n) + } else { + fmt.Fprintln(os.Stderr, nstr, "is ignored: ", err) + } + } + + p := 1 + for _, v := range ns { + p *= v + } + + var ms []int + + for _,v := range ns { + ms = append(ms, (p/v)) + } + + fmt.Println(ms) + os.Exit(0) +} diff --git a/challenge-088/jeongoon/go/ch-2.go b/challenge-088/jeongoon/go/ch-2.go new file mode 100644 index 0000000000..bd0773749c --- /dev/null +++ b/challenge-088/jeongoon/go/ch-2.go @@ -0,0 +1,94 @@ +/* tested with: + * echo "[a b c][d e f][g h i]" | go run ch-2.go + * echo "[a b c d][e f g h][i j k l]" | go run ch-2.go + */ + +package main + +import ( + "os" + "bufio" + "fmt" + "strings" +) + +func usage() { + fmt.Println( "Usage: echo [a b c][d e f][g h i][j k l]' | go run ch-2.go" ) +} + +func parseMatrix (raw string) [][]string { + var mat [][]string + + lines := strings.Split(raw, "\n") + for _, line := range lines { + sublines := strings.Split(line, "]") + + for _, sl := range sublines { + if len(sl) < 1 { + continue + } + ws := strings.Split(sl, " ") + var words []string + for _, w := range ws { + if len(w) < 1 { + continue + } + words = append(words, + strings.Replace(w, "[", "", 1)) + } + mat = append(mat, words) + } + + } + return mat +} + +// translate from ch-2.lsp +func getSpiralArray (mat [][]string) []string { + var sarr []string + + num_rows := len(mat) + num_cols := len(mat[0]) + for o := 0 ; num_rows > 0 && num_cols > 0; o++ { + row_end := o + num_rows -1 + col_end := o + num_cols -1 + // north + sarr = append(sarr, mat[o][o:col_end+1]...) + // east + if num_rows > 1 { + for r := o+1; r <= row_end; r++ { + sarr = append(sarr, mat[r][col_end]) + } + // south + if num_cols > 1 { + for c := col_end -1; c >= o; c-- { + sarr = append(sarr, mat[row_end][c]) + } + // west + if num_rows > 2 { + for r := row_end -1; r > o; r-- { + sarr = append(sarr, mat[r][o]); + } + } + } + } + + // go inner + num_rows -= 2 + num_cols -= 2 + } + + return sarr +} + +func main() { + reader := bufio.NewReader(os.Stdin) + matrixString, _ := reader.ReadString('') + matrix := parseMatrix(matrixString) + if len(matrix) < 1 { + usage() + os.Exit(1) + } + + fmt.Println(getSpiralArray(matrix)) +} diff --git a/challenge-088/jeongoon/haskell/ch-1.hs b/challenge-088/jeongoon/haskell/ch-1.hs new file mode 100644 index 0000000000..d3d52dce8a --- /dev/null +++ b/challenge-088/jeongoon/haskell/ch-1.hs @@ -0,0 +1,13 @@ +import System.Environment +import System.Exit +import Data.Char (isNumber) +import Data.Maybe (catMaybes) + +arrayOfProduct [] = [1] -- assume 1 as spec doesn't consider this case +arrayOfProduct ns = let total = product ns in map (total `div`) ns + +main = do + ns <- (catMaybes.map (\nStr -> + if (all isNumber nStr) then Just(read nStr :: Int) + else Nothing )) `fmap` getArgs; + print $ arrayOfProduct ns diff --git a/challenge-088/jeongoon/haskell/ch-2.hs b/challenge-088/jeongoon/haskell/ch-2.hs new file mode 100644 index 0000000000..691aaad582 --- /dev/null +++ b/challenge-088/jeongoon/haskell/ch-2.hs @@ -0,0 +1,81 @@ +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 + +-- cut outside of a matrix +getInnerMatrix :: [[String]] -> Either String [[String]] +getInnerMatrix m + | length m <= 1 = Left "Too Short In Row" + | otherwise = mapCutColumns [] getShorterInRows + where + mapCutColumns acc [] = Right acc + mapCutColumns acc (r:rs) = + case getShorterInCols r of + Nothing -> Left "Too Short In Column" + Just r' -> mapCutColumns (acc ++ [r']) rs + getShorterInRows = (init.tail) m -- cut top and bottom + getShorterInCols row = + if (length row) <= 1 then Nothing + else Just $ (init.tail) row + +-- read outside cells starting from (0,0) in clockwise +readAroundMatrixCW :: [[String]] -> [String] +readAroundMatrixCW [] = [] +readAroundMatrixCW m = + foldr1 (++) $ + getNorth + : case findEast of + Nothing -> [] + Just e -> e + : case findSouth of + Nothing -> [] + Just s -> s + : case findWest of + Nothing -> [] + Just w -> [w] + where + tm = transpose m + getNorth = head m + findEast = if (length m) == 1 then Nothing + else Just $ (tail.last) tm + findSouth = {-if (length m) == 1 then Nothing + else-} -- already checked when findEast + let lm = (last m) + in if (length lm) == 1 then Nothing + else Just $ (reverse.init) lm + findWest = {-if (length m) == 1 then Nothing + else-} + let htm = (head tm) + in if (length htm) <= 2 then Nothing + else Just $ (reverse.tail.init) htm + +getSpiralAarray :: [[String]] -> [String] +getSpiralAarray mat = + foldr1 (++) + ( unfoldr (\m -> + case m of + Nothing -> Nothing + Just m' -> case (getInnerMatrix m') of + Left _ -> Just (outOf m', Nothing) + Right m'' -> Just (outOf m', Just m'')) + (Just mat) ) + where outOf m = readAroundMatrixCW m + +main = do + getSpiralAarray `fmap` getMatrixFromStdin + >>= print diff --git a/challenge-088/jeongoon/perl/ch-1.pl b/challenge-088/jeongoon/perl/ch-1.pl new file mode 100644 index 0000000000..63478dc908 --- /dev/null +++ b/challenge-088/jeongoon/perl/ch-1.pl @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +# -*- Mode: cperl; cperl-indent-level:4 tab-width: 8; indent-tabs-mode: nil -*- +# -*- coding: utf-8 -*- + +use strict; use warnings; +use v5.26; + +use List::Util qw(product); +use Scalar::Util qw(looks_like_number); + +my @n = grep {looks_like_number $_ and $_ > 0} @ARGV; + +warn "some value ignored." if scalar @ARGV != scalar @n; + +my $p = product @n; + +say "[", + join( ",", + map { $p / $_ } @n ), + "]"; diff --git a/challenge-088/jeongoon/perl/ch-2.pl b/challenge-088/jeongoon/perl/ch-2.pl new file mode 100644 index 0000000000..d8c3510b2f --- /dev/null +++ b/challenge-088/jeongoon/perl/ch-2.pl @@ -0,0 +1,74 @@ +#!/usr/bin/env perl +# -*- Mode: cperl; cperl-indent-level:4 tab-width: 8; indent-tabs-mode: nil -*- +# -*- coding: utf-8 -*- + +# tested with: +# echo "[a b c e f][g h i j k ][l m n o p][q r s t u]" | perl ch-2.pl + +use strict; use warnings; +use v5.26; + +++$|; + +sub readMatrixFromStdin () { + my @matrix = (); + while () { + push @matrix, map { s/\[//g; + [ split /\s+/ ] } ( grep { !/^$/ } + split "\n", + join "\n", + split /\]/ ); + } + + @matrix +} + +# translated from ch-2.go +sub getSpiralArrayFromMatrixRef ($) { + my @mat = @{$_[0]}; # copy + + my $num_rows = scalar @mat; + my $num_cols = scalar @{$mat[0]}; + + my @spiral_array; + for ( my $o = 0; $num_rows > 0 && $num_cols > 0; ++$o ) { + my ($row_end, $col_end) = map { $o + $_ -1 } $num_rows, $num_cols; + + # north + push @spiral_array, @{$mat[$o]}[$o .. $col_end]; + # east + if ( $num_rows > 1 ) { + push @spiral_array, + map { $_->[$col_end] } @mat[ $o + 1 .. $row_end ]; + # south + if ( $num_cols > 1 ) { + push @spiral_array, + @{$mat[$row_end]}[ reverse $o .. ($col_end -1) ]; + # west + if ( $num_rows > 2 ) { + push @spiral_array, + map { $_->[$o] } reverse @mat[ $o + 1 .. $row_end - 1 ]; + } + } + } + # go inner matrix + $num_rows -= 2; + $num_cols -= 2; + } + + @spiral_array +} + + +my @matrix = readMatrixFromStdin; +say STDERR "given matrix:"; +say STDERR "[@$_]" for @matrix; +say STDERR "\n"; + +#my $c = 0; +#say "@{[$c++]}: @$_" for @matrix; + +say "[", + ( join " ", + getSpiralArrayFromMatrixRef( \@matrix ) ), + "]"; diff --git a/challenge-088/jeongoon/raku/ch-1.raku b/challenge-088/jeongoon/raku/ch-1.raku new file mode 100644 index 0000000000..a308637c3f --- /dev/null +++ b/challenge-088/jeongoon/raku/ch-1.raku @@ -0,0 +1,15 @@ +#!/usr/bin/env raku +# -*- Mode: Raku; indent-tabs-mode: nil; coding: utf-8 -*- +# vim: set et ts=4 sw=4: + +# tested with: +# raku jeongoon/ch-1.raku 5 2 1 4 3 +# raku jeongoon/ch-1.raku 2 1 4 3 +# raku jeongoon/ch-1.raku 100 + +multi sub MAIN (*@postive-integer where { @postive-integer.all ~~ Int + and @postive-integer.all > 0 + and @postive-integer.elems > 0 } ) { + my \t = [*] @postive-integer; + @postive-integer.map(t/*).say; +} diff --git a/challenge-088/jeongoon/raku/ch-2.raku b/challenge-088/jeongoon/raku/ch-2.raku new file mode 100644 index 0000000000..d0b6626728 --- /dev/null +++ b/challenge-088/jeongoon/raku/ch-2.raku @@ -0,0 +1,75 @@ +#!/usr/bin/env raku +# -*- Mode: Raku; indent-tabs-mode: nil; coding: utf-8 -*- +# vim: set et ts=4 sw=4: + +use v6.d; + +sub USAGE { + say q:to{__USAGE__}; +Usage: + echo -e "[a b c][d e f][g h i]" | raku ch-2.raku + or input ending with EOF (Ctrl-D or Ctrl-Z) + (you might need to filter the STDERR to get only answer) +__USAGE__ +} + +unit sub MAIN; + +$*ERR.say("Input: (Ctrl-D or Ctrl-Z to finish to input.)"); +my @matrix = do with my @lines = $*IN.lines { + @lines = @lines. + split(/"]" \s* "\n"* | "\n"/). # split rows by newline or `]' + map( -> $ln { next if $ln eq ""; + (S:g/ ^\s+ || '[' || \s+$ // with $ln). + split(/\s+/).Array } ); + + if @lines[0] ~~ Array and @lines[0][0] ne "" { + @lines + } else { + < 1 2 3 4>, + < 5 6 7 8>, + < 9 10 11 12>, + <13 14 15 16> # example 2 + } +} + +# confirm user input +my $ww = @matrix>>.List.flat.max(*.chars).chars; + +$*ERR.say( "given matrix: " ); +$*ERR.say( .map({sprintf("%*s", $ww, $_)}).Array ) for @matrix; +$*ERR.say; + +sub peel-off( @a ) { + my ( $re, $ce ) = @a.end, @a[0].end; + + my @inside = @a[ 1 .. $re.pred; 1 .. $ce.pred ] // Empty; + my @outside = @a[ 0; * ]; # outside of top + + for ( [ 1 .. $re; $ce ], # outside of right + [ $re; $ce.pred, + $ce.pred. + pred ... 0 ], # outside of bottom + [ $re.pred, + $re.pred. + pred ... 1; 0 ] ) # outside of left + -> ( $rr, $cr ) { + last unless all( $rr.elems.so, $cr.elems.so ); # out of range + @outside.append: @a[$rr[*]; $cr[*]]; + } + + @inside, @outside +} + +my @spiral; +my @mat = @matrix.clone; + +my ( $in, $out ); +repeat { + ( $in, $out ) = peel-off( @mat ); + @spiral.append: |$out; + @mat = |$in; + +} while ( @mat[0] andthen { .elems > 0} ); + +@spiral.say; -- cgit