From e8e54f4afad9d72e41b64d20a671bf1445f97031 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 23 Nov 2020 18:36:13 -0500 Subject: Perl code for Challenge 88 Task 1 --- challenge-088/walt-mankowski/perl/ch-1.pl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 challenge-088/walt-mankowski/perl/ch-1.pl diff --git a/challenge-088/walt-mankowski/perl/ch-1.pl b/challenge-088/walt-mankowski/perl/ch-1.pl new file mode 100644 index 0000000000..b47524db20 --- /dev/null +++ b/challenge-088/walt-mankowski/perl/ch-1.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use feature qw(:5.32); +use experimental qw(signatures); + +# TASK #1 › Array of Product +# Submitted by: Mohammad S Anwar +# +# You are given an array of positive integers @N. +# +# Write a script to return an array @M where $M[i] is the product of +# all elements of @N except the index $N[i]. + +my @n = @ARGV; +my @res = map {1} 0..$#n; + +for my $i (0..$#n) { + for my $j (0..$#n) { + $res[$j] *= $n[$i] unless $i == $j; + } +} + +say "@res"; -- cgit From faa90e31db32bf327a43f0d1761bdc0b7e18edae Mon Sep 17 00:00:00 2001 From: Kang-min Liu Date: Tue, 24 Nov 2020 10:10:18 +0900 Subject: @gugod's solution to pwc 088.2 --- challenge-088/gugod/raku/ch-2.raku | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 challenge-088/gugod/raku/ch-2.raku diff --git a/challenge-088/gugod/raku/ch-2.raku b/challenge-088/gugod/raku/ch-2.raku new file mode 100644 index 0000000000..48f999db52 --- /dev/null +++ b/challenge-088/gugod/raku/ch-2.raku @@ -0,0 +1,77 @@ +my @directions = [ + [ 1, 0], # → + [ 0, 1], # ↓ + [-1, 0], # ← + [ 0,-1], # ↑ +]; + +sub turn ($curdir is rw, @boundary) of Nil { # ⤵ + @boundary[$curdir] += ($curdir == 0|3) ?? 1 !! -1; + $curdir = ($curdir + 1) % 4; + return; +} + +sub next-step (@cursor, $curdir) { + @cursor >>+<< @directions[$curdir]; +} + +sub inside-boundary(@cursor, @boundary) of Bool { + return ((@boundary[3] < @cursor[0] < @boundary[1]) + and (@boundary[0] < @cursor[1] < @boundary[2])); +} + +sub spiral-matrix (@M) { + my $width = @M[0].elems; + my $height = @M.elems; + my @cursor = [0,0]; + + # The index here is arranged in thee way to make it easier to implement turn(). + my $curdir = 0; + my @boundary = [ + -1, # ↑ + $width, # → + $height, # ↓ + -1, # ← + ]; + + my @spiral; + while inside-boundary(@cursor, @boundary) { + @spiral.push(@M[@cursor[1]][@cursor[0]]); + + my @next = next-step(@cursor, $curdir); + unless inside-boundary(@next, @boundary) { + turn($curdir, @boundary); + @next = next-step(@cursor, $curdir); + } + + @cursor = @next; + } + + return @spiral; +} + +sub print-matrix(@matrix) { + for ^@matrix -> $y { + say "[" ~ @matrix[$y].map(-> $it { sprintf("%2d", $it) }).join(" ") ~ "]"; + } +} + +my @examples = ( + [[1,2], + [3,4]], + [[1,2,3], + [4,5,6]], + [[1,2,3], + [4,5,6], + [7,8,9]], + [[1,2,3], + [4,5,6], + [7,8,9], + [10,11,12],], +); + +for @examples -> @M { + say "----\nInput: "; + print-matrix(@M); + say "Output: " ~ spiral-matrix(@M).gist; +} -- cgit From 4daef39f53ebc4f7395c538e17e628945696abb1 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 23 Nov 2020 20:13:53 -0500 Subject: Perl code for Challenge 88 Task 2 --- challenge-088/walt-mankowski/perl/ch-2.pl | 78 +++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 challenge-088/walt-mankowski/perl/ch-2.pl diff --git a/challenge-088/walt-mankowski/perl/ch-2.pl b/challenge-088/walt-mankowski/perl/ch-2.pl new file mode 100644 index 0000000000..e260462a73 --- /dev/null +++ b/challenge-088/walt-mankowski/perl/ch-2.pl @@ -0,0 +1,78 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use feature qw(:5.32); +use experimental qw(signatures); + +# TASK #2 › Spiral Matrix +# Submitted by: Mohammad S Anwar +# +# You are given m x n matrix of positive integers. +# +# Write a script to print spiral matrix as list. + +my $fname = $ARGV[0]; +my $grid = parse_input($fname); + +my $rows = $grid->@*; +my $cols = $grid->[0]->@*; + +my %turn = (e => 's', + s => 'w', + w => 'n', + n => 'e', + ); + +my %dir = (e => [0,1], + s => [1,0], + w => [0,-1], + n => [-1,0], + ); + +my %seen; +my @res; +my $r = 0; +my $c = 0; +my $dir = 'e'; + +while (@res < $rows * $cols) { + push @res, $grid->[$r][$c]; + $seen{"$r,$c"} = 1; + my $r1 = $r + $dir{$dir}->[0]; + my $c1 = $c + $dir{$dir}->[1]; + if ($r1 < 0 || $r1 >= $rows || + $c1 < 0 || $c1 >= $cols || + defined $seen{"$r1,$c1"}) { + + # turn and recalculate $r1 and $c1 + $dir = $turn{$dir}; + $r1 = $r + $dir{$dir}->[0]; + $c1 = $c + $dir{$dir}->[1]; + } + ($r,$c) = ($r1,$c1); +} + +say "@res"; + +# read in the matrix +sub parse_input($fname) { + my @grid; + + open my $fh, '<', $fname; + my $row = 0; + while (my $line = <$fh>) { + # remove whitespace; + $line =~ s/\s//g; + + # convert to array + my @c = split /,/, $line; + + for my $i (0..$#c) { + $grid[$row][$i] = $c[$i]; + } + $row++; + } + + # return the grid + return \@grid; +} -- cgit From bbf75140ed797dd1a263413258ce376022ae952a Mon Sep 17 00:00:00 2001 From: Kang-min Liu Date: Tue, 24 Nov 2020 18:09:15 +0900 Subject: add a test case --- challenge-088/gugod/raku/ch-2.raku | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/challenge-088/gugod/raku/ch-2.raku b/challenge-088/gugod/raku/ch-2.raku index 48f999db52..b630611493 100644 --- a/challenge-088/gugod/raku/ch-2.raku +++ b/challenge-088/gugod/raku/ch-2.raku @@ -64,6 +64,10 @@ my @examples = ( [[1,2,3], [4,5,6], [7,8,9]], + [[ 1, 2, 3, 4 ], + [ 5, 6, 7, 8 ], + [ 9, 10, 11, 12 ], + [ 13, 14, 15, 16 ]], [[1,2,3], [4,5,6], [7,8,9], -- cgit From 5389f71ab4b021f54bebce65de9002c403b81cad Mon Sep 17 00:00:00 2001 From: Kang-min Liu Date: Tue, 24 Nov 2020 18:19:50 +0900 Subject: add a naive solution for 088.1 --- challenge-088/gugod/raku/ch-1.raku | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 challenge-088/gugod/raku/ch-1.raku diff --git a/challenge-088/gugod/raku/ch-1.raku b/challenge-088/gugod/raku/ch-1.raku new file mode 100644 index 0000000000..a5723ffb40 --- /dev/null +++ b/challenge-088/gugod/raku/ch-1.raku @@ -0,0 +1,16 @@ +sub array-of-product (@N) { + my $p = [*] @N; + return @N.map(-> $n { $p / $n }); +} + +my @examples = [ + [5, 2, 1, 4, 3], + [2, 1, 4, 3], + [1, 3, 3, 7], +]; + +for @examples -> @N { + say "Input @N = { @N.gist }"; + say "Output @M = " ~ array-of-product(@N).gist; + say "----"; +} -- cgit From cb8e9359613d4b55fe20222f3ca1975d3c362e1e Mon Sep 17 00:00:00 2001 From: Kang-min Liu Date: Tue, 24 Nov 2020 19:01:43 +0900 Subject: put everything in the same subroutine. --- challenge-088/gugod/raku/ch-2.raku | 72 ++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/challenge-088/gugod/raku/ch-2.raku b/challenge-088/gugod/raku/ch-2.raku index b630611493..e5a21065b7 100644 --- a/challenge-088/gugod/raku/ch-2.raku +++ b/challenge-088/gugod/raku/ch-2.raku @@ -1,32 +1,20 @@ -my @directions = [ - [ 1, 0], # → - [ 0, 1], # ↓ - [-1, 0], # ← - [ 0,-1], # ↑ -]; - -sub turn ($curdir is rw, @boundary) of Nil { # ⤵ - @boundary[$curdir] += ($curdir == 0|3) ?? 1 !! -1; - $curdir = ($curdir + 1) % 4; - return; -} - -sub next-step (@cursor, $curdir) { - @cursor >>+<< @directions[$curdir]; -} - -sub inside-boundary(@cursor, @boundary) of Bool { - return ((@boundary[3] < @cursor[0] < @boundary[1]) - and (@boundary[0] < @cursor[1] < @boundary[2])); -} sub spiral-matrix (@M) { - my $width = @M[0].elems; - my $height = @M.elems; - my @cursor = [0,0]; + # Things don'tt change + my $width := @M[0].elems; + my $height := @M.elems; + my @directions := [ + [ 1, 0], # → + [ 0, 1], # ↓ + [-1, 0], # ← + [ 0,-1], # ↑ + ]; - # The index here is arranged in thee way to make it easier to implement turn(). + # Things change. + my @cursor = [0,0]; my $curdir = 0; + + # The order of boundary is arranged in thee way to make it easier to implement turn(). my @boundary = [ -1, # ↑ $width, # → @@ -34,20 +22,34 @@ sub spiral-matrix (@M) { -1, # ← ]; - my @spiral; - while inside-boundary(@cursor, @boundary) { - @spiral.push(@M[@cursor[1]][@cursor[0]]); + my sub turn ($curdir is rw, @boundary) of Nil { # ⤵ + @boundary[$curdir] += ($curdir == 0|3) ?? 1 !! -1; + $curdir = ($curdir + 1) % 4; + return; + } - my @next = next-step(@cursor, $curdir); - unless inside-boundary(@next, @boundary) { - turn($curdir, @boundary); - @next = next-step(@cursor, $curdir); - } + my sub next-step (@cursor, $curdir) { + @cursor >>+<< @directions[$curdir]; + } - @cursor = @next; + my sub inside-boundary(@cursor, @boundary) of Bool { + return ((@boundary[3] < @cursor[0] < @boundary[1]) + and (@boundary[0] < @cursor[1] < @boundary[2])); } - return @spiral; + return gather { + while inside-boundary(@cursor, @boundary) { + take @M[@cursor[1]][@cursor[0]]; + + my @next = next-step(@cursor, $curdir); + unless inside-boundary(@next, @boundary) { + turn($curdir, @boundary); + @next = next-step(@cursor, $curdir); + } + + @cursor = @next; + } + }; } sub print-matrix(@matrix) { -- cgit From 37e3de628deb7c89e06cb1a0d66d566cca636bda Mon Sep 17 00:00:00 2001 From: Kang-min Liu Date: Wed, 25 Nov 2020 08:32:44 +0900 Subject: links to blog posts. --- challenge-088/gugod/README | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/challenge-088/gugod/README b/challenge-088/gugod/README index 9a4443f23b..552c5afaa1 100644 --- a/challenge-088/gugod/README +++ b/challenge-088/gugod/README @@ -1,6 +1,6 @@ Solutions by Kang-min Liu. Blog posts: -- https://gugod.org/2020/11/pwc-087/ -- https://gugod.org/2020/11/pwc-087-en/ -- https://dev.to/gugod/solvintg-perl-weekly-challenge-087-1f09 +- https://gugod.org/2020/11/pwc-088/ +- https://gugod.org/2020/11/pwc-088-en/ +- https://dev.to/gugod/solving-perl-weekly-challenge-088-array-of-prodict-vs-spiral-matrix-13ni -- cgit 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 1862a29a638567ccae50bf2d35fa9237986773c6 Mon Sep 17 00:00:00 2001 From: Tyler Wardhaugh Date: Tue, 24 Nov 2020 23:06:44 -0800 Subject: Task 1 (Clojure): produce the full output --- .../tyler-wardhaugh/clojure/src/tw/weekly/c88/t1.clj | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/challenge-088/tyler-wardhaugh/clojure/src/tw/weekly/c88/t1.clj b/challenge-088/tyler-wardhaugh/clojure/src/tw/weekly/c88/t1.clj index 354eef276d..968eed77ad 100644 --- a/challenge-088/tyler-wardhaugh/clojure/src/tw/weekly/c88/t1.clj +++ b/challenge-088/tyler-wardhaugh/clojure/src/tw/weekly/c88/t1.clj @@ -14,11 +14,20 @@ product (transduce (map (partial apply math/expt)) * freqs) cache-xf (map (juxt key (comp (partial / product) key))) cache (into {} cache-xf freqs)] - (sequence (map cache) coll))) + (map cache coll))) + +(defn format-output + "Print the output according to the task description" + ([input products] (format-output true input products)) + ([stream input products] + (let [swap-out (fn [i] (concat (subvec input 0 i) (subvec input (inc i))))] + (cl-format stream "@M = (~{~a~^, ~})~%~%" products) + (cl-format stream "~:{$M[~a] = ~{~a~^ x ~} = ~a~%~}" + (map-indexed (fn [i v] [i (swap-out i) v]) products))))) (defn -main "Run Task 1 with a list of numbers N, defaulting to the first example given in the task description." [& args] - (let [N (or (some->> args (map edn/read-string)) [5 2 1 4 3])] - (cl-format true "@M = (~{~a~^, ~})" (array-of-product N)))) + (let [N (or (some->> args (mapv edn/read-string)) [5 2 1 4 3])] + (format-output N (array-of-product N)))) -- cgit From cc3d9b7fabfddcd1f14710498a246135f44e8201 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Sat, 28 Nov 2020 15:51:54 -0500 Subject: initialize @res with x operator instead of map --- challenge-088/walt-mankowski/perl/ch-1.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge-088/walt-mankowski/perl/ch-1.pl b/challenge-088/walt-mankowski/perl/ch-1.pl index b47524db20..960b226af6 100644 --- a/challenge-088/walt-mankowski/perl/ch-1.pl +++ b/challenge-088/walt-mankowski/perl/ch-1.pl @@ -13,7 +13,7 @@ use experimental qw(signatures); # all elements of @N except the index $N[i]. my @n = @ARGV; -my @res = map {1} 0..$#n; +my @res = (1) x @ARGV; for my $i (0..$#n) { for my $j (0..$#n) { -- cgit From da582d807fea1701d47da837ffdc3f9860e31d17 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Sat, 28 Nov 2020 15:56:54 -0500 Subject: replace @res with @m --- challenge-088/walt-mankowski/perl/ch-1.pl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/challenge-088/walt-mankowski/perl/ch-1.pl b/challenge-088/walt-mankowski/perl/ch-1.pl index 960b226af6..6e3bbeb004 100644 --- a/challenge-088/walt-mankowski/perl/ch-1.pl +++ b/challenge-088/walt-mankowski/perl/ch-1.pl @@ -13,12 +13,12 @@ use experimental qw(signatures); # all elements of @N except the index $N[i]. my @n = @ARGV; -my @res = (1) x @ARGV; +my @m = (1) x @ARGV; for my $i (0..$#n) { for my $j (0..$#n) { - $res[$j] *= $n[$i] unless $i == $j; + $m[$j] *= $n[$i] unless $i == $j; } } -say "@res"; +say "@m"; -- cgit From 9ce329ce2aa5a9ef3c0eadceb742e15d5b439e39 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Sat, 28 Nov 2020 15:59:09 -0500 Subject: replaced @ARGV with @n --- challenge-088/walt-mankowski/perl/ch-1.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge-088/walt-mankowski/perl/ch-1.pl b/challenge-088/walt-mankowski/perl/ch-1.pl index 6e3bbeb004..433dee3b12 100644 --- a/challenge-088/walt-mankowski/perl/ch-1.pl +++ b/challenge-088/walt-mankowski/perl/ch-1.pl @@ -13,7 +13,7 @@ use experimental qw(signatures); # all elements of @N except the index $N[i]. my @n = @ARGV; -my @m = (1) x @ARGV; +my @m = (1) x @n; for my $i (0..$#n) { for my $j (0..$#n) { -- cgit From d8cf0192bc577f3ed188813c739c7a856f680dc6 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Sat, 28 Nov 2020 16:02:42 -0500 Subject: added description of how I solved task 1 --- challenge-088/walt-mankowski/README.md | 44 +++++++--------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/challenge-088/walt-mankowski/README.md b/challenge-088/walt-mankowski/README.md index a9613da8c0..c9af5a2f18 100644 --- a/challenge-088/walt-mankowski/README.md +++ b/challenge-088/walt-mankowski/README.md @@ -1,45 +1,19 @@ Solutions by Walt Mankowski. -# Task #1: Longest Consecutive Sequence +# Task #1: Array of Product -For this task we're given an unsorted array of integers, and we need to find the longest unsorted sequence of consecutive number and print it out. If there are no consecutive numbers, we print 0. +For this task we're given an array of positive integers `@n`. We need to create a new array `@m` where `$m[i]` is the product of all elements of `@n` except `$n[i]`. -I start by sorting the sequence. Then I make a single pass through the sequence looking for entries that are one greater than the entry before them. I use 3 state variables to track my progress: -* `$best_start` is the start position of the best run I've found so far. -* `$best_run` is the length of the best run I've found so far. -* `$start` is the start of the current run, or -1 if there isn't a current run. -With these it's a straightforward task to loop through the sorted list and find the best sequence. +This was easy to solve in Perl. First I initialized `@m` to be an array of all 1s of the same length as `@n`: ```perl -my @n = sort {$a <=> $b} @ARGV; - -my $best_start = 0; -my $best_run = 0; -my $start = -1; - -for my $i (1..$#n) { - # are we in a run? - if ($n[$i] == $n[$i-1] + 1) { - # is this the start of a run? - $start = $i-1 if $start == -1; - - # do we have a new best run? - if ($i - $start > $best_run) { - $best_run = $i - $start; - $best_start = $start; - } - - } else { - # we're not in a run - $start = -1; - } -} +my @m = (1) x @n; ``` -Then I can print out the best sequence using an array slice: +Then I just used 2 nested loops to compute the result: ```perl -if ($best_run > 0) { - say "@n[$best_start..$best_start+$best_run]"; -} else { - say 0; +for my $i (0..$#n) { + for my $j (0..$#n) { + $m[$j] *= $n[$i] unless $i == $j; + } } ``` -- cgit From be55fe75cc17ebec1192672c010e0b3a7af5255b Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Sat, 28 Nov 2020 16:21:51 -0500 Subject: added description of how I solved task 2 --- challenge-088/walt-mankowski/README.md | 83 ++++++++++++++++------------------ 1 file changed, 38 insertions(+), 45 deletions(-) diff --git a/challenge-088/walt-mankowski/README.md b/challenge-088/walt-mankowski/README.md index c9af5a2f18..3bcf22f532 100644 --- a/challenge-088/walt-mankowski/README.md +++ b/challenge-088/walt-mankowski/README.md @@ -17,58 +17,51 @@ for my $i (0..$#n) { } ``` -# Task 2: Largest Rectangle +# Task 2: Spiral Matrix -For this task we're given an m x n matrix containing only 0s and 1s. We need to find the largest rectangle containing only 1s and print it out, or print 0 if none was found. While the problem didn't explicitly state it, I assumed that a "rectangle" needs to have at least 2 rows and 2 columns. +For this task we're given an m x n matrix of positive integers. We need to walk around the matrix in a spiral clockwise fashion, starting right across the top row, then down the last column, the left across the bottom row, etc., until we've visited every entry. We need to print out the values in the order we encounter them. -I didn't do anything fancy here. I just wrote code to check all the possible rectangles in the matrix by brute force. I did this by iterating over each row `$row` and column $col, and then iterating over all the heights and widths where `($row, $col`) is the upper left corner. +I used a number of state variables to solve this: the current row (`$r`), column (`$c`) and direction (`$dir`), which can be 'n', 's', 'e', or 'w'. The hash `%turn` shows what the new direction is every time we need to turn: ```perl -# loop over all the possible rectangles looking for the best one -my $best_area = 0; -my $best_row; -my $best_col; -my $best_height; -my $best_width; -for my $row1 (0..$rows-2) { - for my $col1 (0..$cols-2) { - for my $row2 ($row1+1..$rows-1) { - my $height = $row2 - $row1 + 1; - for my $col2 ($col1+1..$cols-1) { - my $width = $col2 - $col1 + 1; - my $area = $width * $height; - next if $area <= $best_area; - - if (all_ones($grid, $row1, $row2, $col1, $col2)) { - $best_area = $area; - $best_row = $row1; - $best_col = $col1; - $best_height = $height; - $best_width = $width; - } - } - } - } -} +my %turn = (e => 's', + s => 'w', + w => 'n', + n => 'e', + ); ``` -The function `all_ones()` checks if a rectangle in the grid is all ones: +`%dir` shows how the row and column should change each move for each direction: ```perl -sub all_ones($grid, $row1, $row2, $col1, $col2) { - for my $r ($row1..$row2) { - for my $c ($col1..$col2) { - return 0 if $grid->[$r][$c] == 0; - } - } - - return 1; -} +my %dir = (e => [0,1], + s => [1,0], + w => [0,-1], + n => [-1,0], + ); ``` -I thought about using an array slice to print out the largest rectangle, but that was going to be messy since Perl doesn't support 2-dimensional array slices. Then I realized that since I know the dimensions of the matrix, and since each value is 1, I could cheat and just have my code print out what it looks like! +Finally, `%seen` is used to keep track of which cells we've already visited. Its keys are "row,col"; for instance, when we've visited the cell at row=1, col=2, we will indicate this by setting `$seen{"1,2"} = 1;`. + +Then we set our initial row and column to 0 and our direction to 'e', and start iterating, storing every value we see in `@res`. We turn when we would otherwise visit a cell we've already seen, or if we under- or overflow the grid. Since we're guaranteed to visit each cell once, we stop when the length of `@res` equals the area of the grid. ```perl -if ($best_area == 0) { - say 0; -} else { - for my $r (1..$best_height) { - say "1 " x $best_width; +my @res; +my $r = 0; +my $c = 0; +my $dir = 'e'; + +while (@res < $rows * $cols) { + push @res, $grid->[$r][$c]; + $seen{"$r,$c"} = 1; + my $r1 = $r + $dir{$dir}->[0]; + my $c1 = $c + $dir{$dir}->[1]; + if ($r1 < 0 || $r1 >= $rows || + $c1 < 0 || $c1 >= $cols || + defined $seen{"$r1,$c1"}) { + + # turn and recalculate $r1 and $c1 + $dir = $turn{$dir}; + $r1 = $r + $dir{$dir}->[0]; + $c1 = $c + $dir{$dir}->[1]; } + ($r,$c) = ($r1,$c1); } + +say "@res"; ``` -- cgit From 9dfa59e83d71ded34b04ff78562abca8513966de Mon Sep 17 00:00:00 2001 From: Abigail Date: Sun, 29 Nov 2020 01:07:47 +0100 Subject: Week 88, part 2, Perl: Simplified the program. We don't have to move a pointer step-by-step, we're processing rows and columns, so we can just map{} got get a whole bunch. --- challenge-088/abigail/perl/ch-2.pl | 118 +++++++++++-------------------------- 1 file changed, 36 insertions(+), 82 deletions(-) diff --git a/challenge-088/abigail/perl/ch-2.pl b/challenge-088/abigail/perl/ch-2.pl index 5455a70ed6..16f6c6f801 100644 --- a/challenge-088/abigail/perl/ch-2.pl +++ b/challenge-088/abigail/perl/ch-2.pl @@ -21,32 +21,15 @@ use experimental 'lexical_subs'; # We solve this by keeping track of the boundaries (min_x, min_y, max_x, # max_y) of the part of the matrix which still needs to be processed. # Initially, min_x and min_y are 0, max_x is the index of the bottom row, -# and max_y is the index of the right most column. The boundaries are -# stored in an array @boundaries, using indices $MIN_X, $MIN_Y, $MAX_X, -# $MAX_Y. +# and max_y is the index of the right most column. # -# We also keep track of the current position, that is, the position -# of the value which should be printed next. This starts off as (0, 0), -# the index of the top left corner. +# We then process the matrix side by side, first going east (top row), +# south (left column), west (bottom row), then north (left row). After +# doing a side, we update the corresponding min/max value. That is, +# after doing the top row, we increment $min_x; right column, decrement +# $max_y; bottom row, decrement $max_x; left column, increment $min_y. # -# Next thing we keep track of is the direction of travel, the change in -# (x, y) coordinate we take at each step. This will be initialized as -# (0, 1), as we start off moving to the right. -# -# We now move through the matrix in the direction of travel, printing -# the current value. If we hit the end of the yet-to-be-printed matrix, -# we rotate the direction of movement by 90 degrees, and update one of -# the boundaries: -# - If we have travelled the top row, we increment $min_x; -# - If we have travelled the right column, we decrement $max_y; -# - If we have travelled the bottom row, we decrement $max_x; -# - If we have travelled the left column, we increment $min_y. -# -# Note that we always travel the edges in the same order: -# top row (left to right), right edge (top to bottom), -# bottom row (right to left), left edge (bottom to top), and then repeat. -# -# We stop if $min_x > $max_x, or $min_y > $max_y. +# We're done when $min_x > $max_x, or $min_y > $max_y. # my @matrix = map {[/[1-9][0-9]*/g]} <>; @@ -56,71 +39,42 @@ my @matrix = map {[/[1-9][0-9]*/g]} <>; # die "Not a matrix" if grep {@$_ != @{$matrix [0]}} @matrix; -# -# Boundaries -# -my @boundaries; - $boundaries [my $MIN_X = 0] = 0; - $boundaries [my $MAX_Y = 1] = $#{$matrix [0]}; - $boundaries [my $MAX_X = 2] = $#matrix; - $boundaries [my $MIN_Y = 3] = 0; -my $boundary_change = 0; +my $EAST = 0; +my $SOUTH = 1; +my $WEST = 2; +my $NORTH = 3; -my $X = 0; -my $Y = 1; +my $direction = $EAST; -# -# Current pointer and direction. -# -my (@position, @direction); - @position [$X, $Y] = (0, 0); - @direction [$X, $Y] = (0, 1); +my $min_x = 0, +my $max_x = $#matrix; +my $min_y = 0; +my $max_y = $#{$matrix [0]}; -my $comma = ""; -while ($boundaries [$MIN_X] <= $boundaries [$MAX_X] && - $boundaries [$MIN_Y] <= $boundaries [$MAX_Y]) { - # - # Print the value at the current position. - # - print $comma, $matrix [$position [$X]] [$position [$Y]]; - $comma = ", "; - - # - # Where would we end up if we move one step. - # - my @next_position = ($position [$X] + $direction [$X], - $position [$Y] + $direction [$Y]); - - # - # Next if we're still in bounds. - # - if ($boundaries [$MIN_X] <= $next_position [$X] && - $next_position [$X] <= $boundaries [$MAX_X] && - $boundaries [$MIN_Y] <= $next_position [$Y] && - $next_position [$Y] <= $boundaries [$MAX_Y]) { - @position = @next_position; - next; +my @out; +while ($min_x <= $max_x && $min_y <= $max_y) { + if ($direction == $EAST) { + push @out => map {$matrix [$min_x] [$_]} $min_y .. $max_y; + $min_x ++; + } + elsif ($direction == $SOUTH) { + push @out => map {$matrix [$_] [$max_y]} $min_x .. $max_x; + $max_y --; + } + elsif ($direction == $WEST) { + push @out => reverse map {$matrix [$max_x] [$_]} $min_y .. $max_y; + $max_x --; + } + elsif ($direction == $NORTH) { + push @out => reverse map {$matrix [$_] [$min_y]} $min_x .. $max_x; + $min_y ++; } - # - # We're running off of the matrix, change direction, and - # update or decrement a minimum or maximum value. - # Note that we always hit boundaries in the same order. - # - $boundaries [$boundary_change] += ($boundary_change == 0 || - $boundary_change == 3) ? 1 : -1; - $boundary_change = ($boundary_change + 1) %4; - - # - # Rotate the movement direction 90 degrees clockwise, - # and update the position. - # - @direction = ($direction [$Y], -$direction [$X]); - @position = ($position [$X] + $direction [$X], - $position [$Y] + $direction [$Y]); + $direction = ($direction + 1) % ($NORTH + 1); } -print "\n"; +$, = ", "; +say @out; __END__ -- cgit From 69edd3eb9851422493ddbd94e9a2b0b2e7071ef1 Mon Sep 17 00:00:00 2001 From: Abigail Date: Sun, 29 Nov 2020 01:15:56 +0100 Subject: Blog for week 88/part 2. --- challenge-088/abigail/blog1.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 challenge-088/abigail/blog1.txt diff --git a/challenge-088/abigail/blog1.txt b/challenge-088/abigail/blog1.txt new file mode 100644 index 0000000000..ab782c48d9 --- /dev/null +++ b/challenge-088/abigail/blog1.txt @@ -0,0 +1 @@ +https://wp.me/pcxd30-8Z -- cgit From 532108d34f2e84608409dc3de72488ba2fe2182b Mon Sep 17 00:00:00 2001 From: Abigail Date: Sun, 29 Nov 2020 01:52:30 +0100 Subject: Node solution for week 88, part 2. --- challenge-088/abigail/node/ch-2.js | 92 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 challenge-088/abigail/node/ch-2.js diff --git a/challenge-088/abigail/node/ch-2.js b/challenge-088/abigail/node/ch-2.js new file mode 100644 index 0000000000..e2a986836a --- /dev/null +++ b/challenge-088/abigail/node/ch-2.js @@ -0,0 +1,92 @@ +// +// Challenge +// +// You are given m x n matrix of positive integers. +// +// Write a script to print spiral matrix as list. +// + +// +// We solve this by keeping track of the boundaries (min_x, min_y, max_x, +// max_y) of the part of the matrix which still needs to be processed. +// Initially, min_x and min_y are 0, max_x is the index of the bottom row, +// and max_y is the index of the right most column. +// +// We then process the matrix side by side, first going east (top row), +// south (left column), west (bottom row), then north (left row). After +// doing a side, we update the corresponding min/max value. That is, +// after doing the top row, we increment min_x; right column, decrement +// max_y; bottom row, decrement max_x; left column, increment min_y. +// +// We're done when min_x > max_x, or min_y > max_y. +// + +// +// Read STDIN. Split on newlines, then on white space. +// +let matrix = require ("fs") + . readFileSync (0) // Read all. + . toString () // Turn it into a string. + . split ("\n") // Split on newlines. + . filter (_ => _ . length) // Filter empty lines. + . map (_ => _ . trim () // Trim white space. + . split (/\s+/)) // Split on whitespace. +; + +// +// Check if all rows are the same length +// +matrix . forEach (row => { + if (row . length != matrix [0] . length) { + throw "Not all rows are of equal length"; + } +}); + + +let EAST = 0; +let SOUTH = 1; +let WEST = 2; +let NORTH = 3; + +let direction = EAST; // Initial direction + +let min_x = 0; +let max_x = matrix . length - 1; +let min_y = 0; +let max_y = matrix [0] . length - 1; + + +let output = ""; +while (min_x <= max_x && min_y <= max_y) { + if (direction == EAST) { + for (let y = min_y; y <= max_y; y ++) { + output = output + ", " + matrix [min_x] [y]; + } + min_x ++; + } + if (direction == SOUTH) { + for (let x = min_x; x <= max_x; x ++) { + output = output + ", " + matrix [x] [max_y]; + } + max_y --; + } + if (direction == WEST) { + for (let y = max_y; y >= min_y; y --) { + output = output + ", " + matrix [max_x] [y]; + } + max_x --; + } + if (direction == NORTH) { + for (let x = max_x; x >= min_x; x --) { + output = output + ", " + matrix [x] [min_y]; + } + min_y ++; + } + + direction = (direction + 1) % (NORTH + 1); +} + +// +// Remove leading ", " and print result +// +process . stdout . write (output . slice (2) + "\n"); -- cgit From f5fa5aa61c4f26e1446b20c7a94d436eb3aa77de Mon Sep 17 00:00:00 2001 From: Aaron Smith Date: Sat, 28 Nov 2020 20:23:05 -0600 Subject: Add Challenge 88 Solutions --- challenge-088/aaronreidsmith/README | 1 + challenge-088/aaronreidsmith/raku/ch-1.raku | 9 ++++ challenge-088/aaronreidsmith/raku/ch-2.raku | 76 +++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 challenge-088/aaronreidsmith/README create mode 100644 challenge-088/aaronreidsmith/raku/ch-1.raku create mode 100644 challenge-088/aaronreidsmith/raku/ch-2.raku diff --git a/challenge-088/aaronreidsmith/README b/challenge-088/aaronreidsmith/README new file mode 100644 index 0000000000..b90b334a5a --- /dev/null +++ b/challenge-088/aaronreidsmith/README @@ -0,0 +1 @@ +Solution by Aaron Smith \ No newline at end of file diff --git a/challenge-088/aaronreidsmith/raku/ch-1.raku b/challenge-088/aaronreidsmith/raku/ch-1.raku new file mode 100644 index 0000000000..90133cee74 --- /dev/null +++ b/challenge-088/aaronreidsmith/raku/ch-1.raku @@ -0,0 +1,9 @@ +#!/usr/bin/env perl6 + +subset PositiveInt of Int where { $_ ~~ Int && $_ > 0 } + +sub MAIN(*@N where all(@N) ~~ PositiveInt) { + my $product = [*] @N; + my @M = @N.map: $product / *; + say @M; +} diff --git a/challenge-088/aaronreidsmith/raku/ch-2.raku b/challenge-088/aaronreidsmith/raku/ch-2.raku new file mode 100644 index 0000000000..aaad86aedd --- /dev/null +++ b/challenge-088/aaronreidsmith/raku/ch-2.raku @@ -0,0 +1,76 @@ +#!/usr/bin/env perl6 + +subset PositiveInt of Int where { $_ ~~ Int && $_ > 0 } + +enum Direction ; + +sub MAIN(*@input where all(@input) ~~ PositiveInt) { + # Ensure our input is exactly square + my $side-length = @input.elems.sqrt; + $side-length.Int == $side-length or die "Must be a square matrix"; + + # Turn our CLI input into a list of lists (containing both the value and a flag for if we have visted it) + my @matrix = gather { + loop (my $i = 0; $i < @input.elems; $i += $side-length) { + my @row = @input[$i..^$i + $side-length].map({ Hash.new('value', $_, 'visited', False) }); + take @row; + } + } + + # Output list and helper function for adding to it + my @output; + sub visit-cell($i, $j) { + my %cell = @matrix[$i][$j]; + if !%cell{'visited'} { + @output.push(%cell{'value'}); + } + @matrix[$i][$j]{'visited'} = True; + } + + # Control vars used below + my ($min-row, $min-col) = 0, 0; + my ($max-row, $max-col) = @matrix.elems - 1, @matrix.tail.elems - 1; + my ($current-row, $current-col, $current-direction) = $min-row, $min-col, EAST; + + # Iterate through matrix in the given directions. Check if we are in a corner or if we have already + # visited the next cell to determine if we should turn + while @output.elems != @input.elems { + visit-cell($current-row, $current-col); + given $current-direction { + when EAST { + if $current-col == $max-col || @matrix[$current-row][$current-col+1]{'visited'} { + $current-direction = SOUTH; + $current-row += 1; + } else { + $current-col += 1; + } + } + when SOUTH { + if ($current-row == $max-row && $current-col == $max-col) || @matrix[$current-row+1][$current-col]{'visited'} { + $current-direction = WEST; + $current-col -= 1; + } else { + $current-row += 1; + } + } + when WEST { + if $current-col == $min-col || @matrix[$current-row][$current-col-1]{'visited'} { + $current-direction = NORTH; + $current-row -= 1; + } else { + $current-col -= 1; + } + } + when NORTH { + # No need to check for special case here, because we always start in the top left + if @matrix[$current-row-1][$current-col]{'visited'} { + $current-direction = EAST; + $current-col += 1; + } else { + $current-row -= 1; + } + } + } + } + say @output; +} -- cgit From 0b769723fc7a074ef9caf109635742aa1ecd76ad Mon Sep 17 00:00:00 2001 From: Aaron Smith Date: Sat, 28 Nov 2020 20:29:55 -0600 Subject: Add usage --- challenge-088/aaronreidsmith/README | 2 +- challenge-088/aaronreidsmith/raku/ch-1.raku | 10 +++++++++- challenge-088/aaronreidsmith/raku/ch-2.raku | 10 +++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/challenge-088/aaronreidsmith/README b/challenge-088/aaronreidsmith/README index b90b334a5a..2fcfe1fdcc 100644 --- a/challenge-088/aaronreidsmith/README +++ b/challenge-088/aaronreidsmith/README @@ -1 +1 @@ -Solution by Aaron Smith \ No newline at end of file +Solution by Aaron Smith diff --git a/challenge-088/aaronreidsmith/raku/ch-1.raku b/challenge-088/aaronreidsmith/raku/ch-1.raku index 90133cee74..dfe19720d4 100644 --- a/challenge-088/aaronreidsmith/raku/ch-1.raku +++ b/challenge-088/aaronreidsmith/raku/ch-1.raku @@ -2,7 +2,15 @@ subset PositiveInt of Int where { $_ ~~ Int && $_ > 0 } -sub MAIN(*@N where all(@N) ~~ PositiveInt) { +sub USAGE { + print Q:c:to/EOH/; + Usage: {$*PROGRAM-NAME} + + Example: {$*PROGRAM-NAME} 1 2 3 4 5 +EOH +} + +sub MAIN(*@N where all(@N) ~~ PositiveInt && @N.elems > 0) { my $product = [*] @N; my @M = @N.map: $product / *; say @M; diff --git a/challenge-088/aaronreidsmith/raku/ch-2.raku b/challenge-088/aaronreidsmith/raku/ch-2.raku index aaad86aedd..b7911aae43 100644 --- a/challenge-088/aaronreidsmith/raku/ch-2.raku +++ b/challenge-088/aaronreidsmith/raku/ch-2.raku @@ -4,7 +4,15 @@ subset PositiveInt of Int where { $_ ~~ Int && $_ > 0 } enum Direction ; -sub MAIN(*@input where all(@input) ~~ PositiveInt) { +sub USAGE { + print Q:c:to/EOH/; + Usage: {$*PROGRAM-NAME} + + Example: {$*PROGRAM-NAME} 1 2 3 4 5 6 7 8 9 +EOH +} + +sub MAIN(*@input where all(@input) ~~ PositiveInt && @input.elems > 0) { # Ensure our input is exactly square my $side-length = @input.elems.sqrt; $side-length.Int == $side-length or die "Must be a square matrix"; -- cgit From 4e4d290ce26f47212137b786d84fa9bb3816b84f Mon Sep 17 00:00:00 2001 From: Samir Parikh Date: Sun, 29 Nov 2020 02:48:33 +0000 Subject: add challenge 088 solutions --- challenge-088/samir-parikh/blog.txt | 1 + challenge-088/samir-parikh/perl/ch-1.pl | 39 +++++++++++ challenge-088/samir-parikh/perl/ch-2.pl | 81 ++++++++++++++++++++++ challenge-088/samir-parikh/perl/ch-2.testinput.txt | 12 ++++ 4 files changed, 133 insertions(+) create mode 100644 challenge-088/samir-parikh/blog.txt create mode 100755 challenge-088/samir-parikh/perl/ch-1.pl create mode 100755 challenge-088/samir-parikh/perl/ch-2.pl create mode 100644 challenge-088/samir-parikh/perl/ch-2.testinput.txt diff --git a/challenge-088/samir-parikh/blog.txt b/challenge-088/samir-parikh/blog.txt new file mode 100644 index 0000000000..1b81a19ea3 --- /dev/null +++ b/challenge-088/samir-parikh/blog.txt @@ -0,0 +1 @@ +https://samirparikh.com/blog/perl-weekly-challenge-088.html diff --git a/challenge-088/samir-parikh/perl/ch-1.pl b/challenge-088/samir-parikh/perl/ch-1.pl new file mode 100755 index 0000000000..e9b672660b --- /dev/null +++ b/challenge-088/samir-parikh/perl/ch-1.pl @@ -0,0 +1,39 @@ +#!/usr/local/bin/perl + +use warnings; +use strict; +use diagnostics; +use v5.10; + +# run program as: +# $ ./ch-1.pl "100, 4, 50, 3, 2" +my @N = split /, /, $ARGV[0]; +my @M; +my $output_string = ""; + +for (my $i = 0; $i < scalar(@N); $i++) { + my $product = 1; + my $m_string = "\$M[" . $i . "] = "; + my $first = 1; + for (my $j = 0; $j < scalar(@N); $j++) { + my $print_x; + if ($i != $j) { + $product = $product * $N[$j]; + if ($first) { + $print_x = ""; + $first = 0; + } else { + $print_x = " x "; + } + $m_string .= $print_x . $N[$j]; + } + } + push (@M, $product); + $m_string .= " = " . $product; + $output_string .= "\t". $m_string . "\n"; +} + +say "Input:\n\t\@N = (", join(", ", @N), ")"; +say "Output:"; +say "\t\@M = (", join(", ", @M), ")\n"; +say "$output_string"; diff --git a/challenge-088/samir-parikh/perl/ch-2.pl b/challenge-088/samir-parikh/perl/ch-2.pl new file mode 100755 index 0000000000..2a7c6057a8 --- /dev/null +++ b/challenge-088/samir-parikh/perl/ch-2.pl @@ -0,0 +1,81 @@ +#!/usr/local/bin/perl + +use v5.10; +use warnings; +use strict; + +# assumptions: +# matrix does not have to be square +# spiral is clockwise + +sub define_matrix { + open (INPUT, '<', $_[0]) or die "$!: could not open file $_[0]"; + say "Input:"; + my (@line, @matrix); + while () { + chomp; + say $_; + s/\s+//g; # remove any whitespace + s/\[//; + s/\]//; + @line = split /,/, $_; + push (@matrix, [@line]); + } + close (INPUT) or die "$!: could not close file $_[0]"; + return ( @matrix ); +} + +sub return_spiral { + my @array = @_; + my @spiral; +# handle special cases +# just one row + if (scalar(@array) == 1) { + return ( @{$array[0]} ); +# just one column + } elsif ( scalar ( @{$array[0]} ) == 1 ) { + for (my $i = 0; $i < scalar(@array); $i++) { + push ( @spiral, @{$array[$i]}[0] ); + } + return ( @spiral ); +# we have at least a 2 x 2 array + } else { +# get first row + push ( @spiral, @{$array[0]} ); +# get right column + my $right_ci = scalar ( @{$array[0]} ) - 1; + for (my $y = 1; $y < scalar ( @array ); $y++) { + push ( @spiral, @{$array[$y]}[$right_ci] ); + } +# remove last element from last row + pop ( @{$array[$#array]} ); +# get last row in reversed order + push ( @spiral, reverse ( @{$array[$#array]} ) ); +# get left column + for (my $i = ($#array - 1); $i > 0; $i--) { + push ( @spiral, @{$array[$i]}[0] ); + } +# check if resulting array is empty (i.e. we were originally sent +# just a two-row or two-column array to begin with + if (scalar( @array ) == 2 || scalar ( @{$array[0]} ) == 2) { + return ( @spiral ); + } else { +# trim array +# trim top row: + shift @array; +# trim bottom row: + pop @array; +# remove first and last element from remaining rows + for (my $i = 0; $i < scalar(@array); $i++) { + shift ( @{$array[$i]} ); + pop ( @{$array[$i]} ); + } + return ( @spiral, &return_spiral(@array) ); + } + } +} + +my @matrix = &define_matrix($ARGV[0]); +my @spiral2 = &return_spiral(@matrix); +say "Output:"; +say "[ ", join(", ", @spiral2), " ]"; diff --git a/challenge-088/samir-parikh/perl/ch-2.testinput.txt b/challenge-088/samir-parikh/perl/ch-2.testinput.txt new file mode 100644 index 0000000000..1beacf322d --- /dev/null +++ b/challenge-088/samir-parikh/perl/ch-2.testinput.txt @@ -0,0 +1,12 @@ +[ 1, 2, 3, 4 ] +[ 5, 6, 7, 8 ] +[ 9, 10, 11, 12 ] +[ 13, 14, 15, 16 ] +[ 1, 2, 3, 4 ] +[ 5, 6, 7, 8 ] +[ 9, 10, 11, 12 ] +[ 13, 14, 15, 16 ] +[ 1, 2, 3, 4 ] +[ 5, 6, 7, 8 ] +[ 9, 10, 11, 12 ] +[ 13, 14, 15, 16 ] -- cgit From 82e66729dcd49fd94e66b51d842f32b82ccb3269 Mon Sep 17 00:00:00 2001 From: PerlMonk Athanasius Date: Sun, 29 Nov 2020 16:35:04 +1000 Subject: Perl & Raku solutions to Tasks 1 & 2 of the Perl Weekly Challenge #088 On branch branch-for-challenge-088 Changes to be committed: new file: challenge-088/athanasius/perl/ch-1.pl new file: challenge-088/athanasius/perl/ch-2.pl new file: challenge-088/athanasius/raku/ch-1.raku new file: challenge-088/athanasius/raku/ch-2.raku --- challenge-088/athanasius/perl/ch-1.pl | 136 +++++++++++++ challenge-088/athanasius/perl/ch-2.pl | 327 ++++++++++++++++++++++++++++++++ challenge-088/athanasius/raku/ch-1.raku | 113 +++++++++++ challenge-088/athanasius/raku/ch-2.raku | 294 ++++++++++++++++++++++++++++ 4 files changed, 870 insertions(+) create mode 100644 challenge-088/athanasius/perl/ch-1.pl create mode 100644 challenge-088/athanasius/perl/ch-2.pl create mode 100644 challenge-088/athanasius/raku/ch-1.raku create mode 100644 challenge-088/athanasius/raku/ch-2.raku diff --git a/challenge-088/athanasius/perl/ch-1.pl b/challenge-088/athanasius/perl/ch-1.pl new file mode 100644 index 0000000000..fa9d0d86b7 --- /dev/null +++ b/challenge-088/athanasius/perl/ch-1.pl @@ -0,0 +1,136 @@ +#!perl + +############################################################################### +=comment + +Perl Weekly Challenge 088 +========================= + +Task #1 +------- +*Array of Product* + +Submitted by: Mohammad S Anwar + +You are given an array of positive integers @N. + +Write a script to return an array @M where $M[i] is the product of all elements +of @N except the index $N[i]. + +Example 1: + + Input: + @N = (5, 2, 1, 4, 3) + Output: + @M = (24, 60, 120, 30, 40) + + $M[0] = 2 x 1 x 4 x 3 = 24 + $M[1] = 5 x 1 x 4 x 3 = 60 + $M[2] = 5 x 2 x 4 x 3 = 120 + $M[3] = 5 x 2 x 1 x 3 = 30 + $M[4] = 5 x 2 x 1 x 4 = 40 + +Example 2: + + Input: + @N = (2, 1, 4, 3) + Output: + @M = (12, 24, 6, 8) + + $M[0] = 1 x 4 x 3 = 12 + $M[1] = 2 x 4 x 3 = 24 + $M[2] = 2 x 1 x 3 = 6 + $M[3] = 2 x 1 x 4 = 8 + +=cut +############################################################################### + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +#============================================================================== +=comment + +Assumption: "Positive" integers are those which are greater than zero. + +Algorithm: First find $product, the product of *all* the elements in @N; then, + for each element in @N, divide $product by that element's value to + get the desired sub-product for that index, and store it in @M. + +=cut +#============================================================================== + +use strict; +use warnings; +use Const::Fast; +use List::Util qw( reduce ); +use Regexp::Common qw( number ); + +const my $USAGE => +"Usage: + perl $0 [ ...] + + [ ...] A non-empty, unsorted array of positive integers\n"; + +#------------------------------------------------------------------------------ +BEGIN +#------------------------------------------------------------------------------ +{ + $| = 1; + print "\nChallenge 088, Task #1: Array of Product (Perl)\n\n"; +} + +#============================================================================== +MAIN: +#============================================================================== +{ + my @N = parse_command_line(); + + print_array('Input', \@N); + + my $product = reduce { $a * $b } @N; # List reduction + my @M; + push @M, $product / $N[$_] for 0 .. $#N; + + print_array('Output', \@M); +} + +#------------------------------------------------------------------------------ +sub print_array +#------------------------------------------------------------------------------ +{ + my ($title, $array) = @_; + + print "$title:\n"; + + printf " (%s)\n", join ', ', @$array; +} + +#------------------------------------------------------------------------------ +sub parse_command_line +#------------------------------------------------------------------------------ +{ + my @N = @ARGV; + + scalar @N > 0 or error( 'The input array is empty' ); + + for (@N) + { + /\A$RE{num}{int}\z/ or error( qq["$_" is not an integer] ); + $_ > 0 or error( qq["$_" is not positive] ); + } + + return @N; +} + +#------------------------------------------------------------------------------ +sub error +#------------------------------------------------------------------------------ +{ + my ($message) = @_; + + die "ERROR: $message\n$USAGE"; +} + +############################################################################### diff --git a/challenge-088/athanasius/perl/ch-2.pl b/challenge-088/athanasius/perl/ch-2.pl new file mode 100644 index 0000000000..3b70506f65 --- /dev/null +++ b/challenge-088/athanasius/perl/ch-2.pl @@ -0,0 +1,327 @@ +#!perl + +############################################################################### +=comment + +Perl Weekly Challenge 088 +========================= + +Task #2 +------- +*Spiral Matrix* + +Submitted by: Mohammad S Anwar + +You are given m x n matrix of positive integers. + +Write a script to print spiral matrix as list. + +Example 1: + + Input: + [ 1, 2, 3 ] + [ 4, 5, 6 ] + [ 7, 8, 9 ] + Output: + [ 1, 2, 3, 6, 9, 8, 7, 4, 5 ] + +Example 2: + + Input: + [ 1, 2, 3, 4 ] + [ 5, 6, 7, 8 ] + [ 9, 10, 11, 12 ] + [ 13, 14, 15, 16 ] + Output: + [ 1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10 ] + +=cut +############################################################################### + +#--------------------------------------# +# Copyright © 2020 PerlMonk Athanasius # +#--------------------------------------# + +#============================================================================== +=comment + +Interface +--------- + +Two CLIs are provided: + +1. For an m x n matrix in which the elements are 1 to m * n in left-to-right, + top-to-bottom order, the user may simply specify m and n explicitly; for + example: + + perl ch-2.pl -m 4 -n 4 + + produces the matrix in Example 2. + +2. For all other cases, the user must specify rows as whitespace-separated + strings, each string being a comma-separated list of elements; for example: + + perl ch-2.pl 9,8,7 6,5,4 3,2,1 + + produces the matrix in Example 1, but with elements in reverse order. + +Algorithm +--------- + +1. The outer elements of the matrix are read in clockwise order, beginning at + the top left corner: + - top row: first to last columns + - right column: second to last rows + - bottom row: second-last to first column + - left column: second-last to second row. + +2. A new, "inner" matrix is constructed by removing the outer rows and columns + of the current matrix. + +3. Recursion: steps 1 and 2 above are applied to the new matrix. The recursion + ends when: + (1) the new matrix is a single row; or + (2) the new matrix is a single column; or + (3) the new matrix is empty. + +=cut +#============================================================================== + +use strict; +use warnings; +use Const::Fast; +use Getopt::Long; +use Regexp::Common qw( number ); + +const my $USAGE => +"Usage: + perl $0 [ ...] + perl $0 [-m ] [-n ] + + [ ...] One or more same-width rows, each a comma-separated list of +one or more positive integers + -m Positive integer: matrix height (total number of rows) + -n Positive integer: matrix width (total number of columns) +"; + +#------------------------------------------------------------------------------ +BEGIN +#------------------------------------------------------------------------------ +{ + $| = 1; + print "\nChallenge 088, Task #2: Spiral Matrix (Perl)\n\n"; +} + +#============================================================================== +MAIN: +#============================================================================== +{ + my $matrix = get_matrix(); + + print "Input:\n"; + print_matrix( $matrix ); + + my $spiral = find_spiral( $matrix ); + + print "Output:\n"; + printf " [ %s ]\n", join ' ', @$spiral; +} + +#------------------------------------------------------------------------------ +sub find_spiral # Recursive subroutine +#------------------------------------------------------------------------------ +{ + my ($matrix) = @_; + my $max_row = $#$matrix; + my $max_col = $#{ $matrix->[0] }; + my @spiral; + + if ($max_row == 0) # Base case (1): single row + { + push @spiral, @{ $matrix->[0] }[0 .. $max_col]; + } + elsif ($max_col == 0) # Base case (2): single column + { + push @spiral, $matrix->[$_][0] for 0 .. $max_row; + } + else + { + # Step 1: Read the outer matrix elements in clockwise order, beginning + # at the top left corner + + my @top = 0 .. $max_col; + my @right = 1 .. $max_row; + my @bottom = reverse 0 .. $max_col - 1; + my @left = reverse 1 .. $max_row - 1; + + push @spiral, @{ $matrix->[0 ] }[@top ]; + push @spiral, $matrix->[$_ ] [$max_col] for @right; + push @spiral, @{ $matrix->[$max_row] }[@bottom ]; + push @spiral, $matrix->[$_ ] [0 ] for @left; + + # Step 2: Construct a new ("inner") matrix by removing the outer rows + # and columns + + my @new_matrix; + + for my $row (1 .. $max_row - 1) + { + push @new_matrix, [ @{ $matrix->[$row] }[1 .. $max_col - 1] ]; + } + + if ($#new_matrix >= 0 && $#{ $new_matrix[0] } >= 0) + { + # Step 3: Recurse on the inner matrix + + push @spiral, @{ find_spiral( \@new_matrix ) }; + } + # else: Base case (3): the new matrix is empty + } + + return \@spiral; +} + +#------------------------------------------------------------------------------ +sub get_matrix +#------------------------------------------------------------------------------ +{ + scalar @ARGV > 0 or error( 'Missing input matrix' ); + + my ($m, $n); + + GetOptions + ( + "m:i" => \$m, + "n:i" => \$n, + ) or error( 'Invalid command line argument(s)' ); + + my $matrix; + + if (defined $m || defined $n) + { + scalar @ARGV == 0 or error( 'Extra command line argument(s) found' ); + + $matrix = construct_matrix( $m, $n ); + } + else + { + $matrix = read_matrix( @ARGV ); + } + + return $matrix; +} + +#------------------------------------------------------------------------------ +sub construct_matrix +#--------------------------------------------------