diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2020-08-15 13:14:27 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-15 13:14:27 +0100 |
| commit | f9b6d3a9f9b04dda88b4f605e212a6c9fe4c071f (patch) | |
| tree | c515261fae8f55ec66513e69f04bd875e356d7c8 | |
| parent | 84a5caf1f9f3ea376c0affb3a5d2ad722aa21c4c (diff) | |
| parent | fae6d34a11eeb75a7a8ffeca68ea7b6c8e682c52 (diff) | |
| download | perlweeklychallenge-club-f9b6d3a9f9b04dda88b4f605e212a6c9fe4c071f.tar.gz perlweeklychallenge-club-f9b6d3a9f9b04dda88b4f605e212a6c9fe4c071f.tar.bz2 perlweeklychallenge-club-f9b6d3a9f9b04dda88b4f605e212a6c9fe4c071f.zip | |
Merge pull request #2075 from jeongoon/ch-073
[ch-073/jeongoon] All done.
| -rw-r--r-- | challenge-073/jeongoon/.gitignore | 3 | ||||
| -rw-r--r-- | challenge-073/jeongoon/common-lisp/ch-1.lsp | 118 | ||||
| -rw-r--r-- | challenge-073/jeongoon/common-lisp/ch-2.lsp | 75 | ||||
| -rw-r--r-- | challenge-073/jeongoon/haskell/JRandomList.hs | 49 | ||||
| -rw-r--r-- | challenge-073/jeongoon/haskell/ch-1.hs | 144 | ||||
| -rw-r--r-- | challenge-073/jeongoon/haskell/ch-2.hs | 53 | ||||
| -rw-r--r-- | challenge-073/jeongoon/perl/ch-1.pl | 175 | ||||
| -rw-r--r-- | challenge-073/jeongoon/perl/ch-2.pl | 49 | ||||
| -rw-r--r-- | challenge-073/jeongoon/raku/ch-1.raku | 91 | ||||
| -rw-r--r-- | challenge-073/jeongoon/raku/ch-2.raku | 32 |
10 files changed, 789 insertions, 0 deletions
diff --git a/challenge-073/jeongoon/.gitignore b/challenge-073/jeongoon/.gitignore new file mode 100644 index 0000000000..a109a701fc --- /dev/null +++ b/challenge-073/jeongoon/.gitignore @@ -0,0 +1,3 @@ +ch-1 +ch-2 +*~ diff --git a/challenge-073/jeongoon/common-lisp/ch-1.lsp b/challenge-073/jeongoon/common-lisp/ch-1.lsp new file mode 100644 index 0000000000..bd1c624095 --- /dev/null +++ b/challenge-073/jeongoon/common-lisp/ch-1.lsp @@ -0,0 +1,118 @@ +;; Ref: +;; http://cl-cookbook.sourceforge.net/loop.html +;; http://clhs.lisp.se/Body/f_mk_ar.htm +;; https://stackoverflow.com/questions/3950601/swapping-elements-in-a-common-lisp-list +;; http://clhs.lisp.se/Body/v_rnd_st.htm#STrandom-stateST +;; https://stackoverflow.com/questions/13359025/adding-to-the-end-of-list-in-lisp + +;; I've done with array not list -- which seems wrong choice... + +;; tested with +;; sbcl --script ch-1.lsp <number> + +(defun get-command-line () ;; from #072 + (or + #+CLISP *args* + #+SBCL *posix-argv* + #+LISPWORKS system:*line-arguments-list* + #+CMU extensions:*command-line-words* + nil)) + +(defun get-random-pairs (n) + (let ((*random-state* (make-random-state t))) + (loop for cnt from 1 to n + collect (list (random n) (random n))))) + +(defun make-range (minv maxv &optional (step 1)) ;; from #072 + (when (<= minv maxv) + (cons minv (make-range (+ minv step) maxv step)))) + +(defun make-vector-range (min max &optional (step 1)) + (let* ((range (make-range min max step)) + (size (length range))) + (make-array (list size) :initial-contents range))) + +;; not used here +(defun minimum-in-vector (arr &optional (i 0)) + (let ((j (+ i 1))) + (if (= (length arr) j) + (aref arr i) + ;; else + (when (> (length arr) j) + (min (aref arr i) (minimum-in-vector arr j)))))) + +(defun shuffle-array-by-swapping (arr) + (let* ((size (length arr)) + (shuffle-pairs (get-random-pairs size))) + (loop for pair in shuffle-pairs + do (let ((le (first pair)) (ri (second pair))) + (when (not (and (null le) (null ri))) + ;; rotatef: change in place ; I think *f means put in pyhsical memory + (rotatef (aref arr le) (aref arr ri))))))) + +;; tranlated from groupMinimumList in perl/ch-1.pl +(defun group-minimum-list (arr group-size) + (let* ((total-size (length arr)) + (min-val nil) + (idx-init (- 1 group-size)) + (idx-max (- total-size group-size)) + (idx-memo -1) + (result ())) + + (loop for b from 0 below total-size ;; b:index for value to be checked + ;; or last index in the gorup + do (let* ((idx (+ idx-init b)) ;; idx: first index in the group + (idx-memo-inboundp (> idx-memo idx)) + (group-inboundp (and (<= 0 idx) (<= idx idx-max))) + (cur-val (aref arr b))) + + (if (and group-inboundp (not idx-memo-inboundp)) + ;; compare everything in the group + (progn + (setq idx-memo idx) ;; restart from first index in the grp + (setq min-val (aref arr idx)) + (loop for d from 1 below group-size + do(let* ((j (+ idx d)) + (cur-val (aref arr j))) + (when (>= min-val cur-val) + (setq idx-memo j) + (setq min-val cur-val))))) + ;; else + (when (or (null min-val) (<= cur-val min-val)) + (setq min-val cur-val) + (setq idx-memo b)) ;; *real index* in the list not idx + ) + + (when group-inboundp + (if (null result) + (setq result (list min-val)) + (nconc result (list min-val)))))) + result )) + +(defparameter *cmdline* (get-command-line)) + +(defun print-usage () + (format t "Usage: sbcl --script ch-1.lsp <sliding-size>" (car *cmdline*))) + +(when (not (= (length *cmdline*) 2)) + (format t "Wrong Number of arguments: expected 1: but got: ~d~%" (- (length *cmdline*) 1)) + (print-usage) + (quit)) + +;; *slide-size* +(defparameter *slide-size* (parse-integer (second *cmdline*))) + +(when (< *slide-size* 3) + (format t "Too short slide size: ~d: using 3~%" *slide-size*) + (setq *slide-size* 3)) + +;; *frame-size* ; which is 3 times larger than slide at least +(defparameter *frame-size* (* 10 (round (* 0.3 *slide-size*) 1))) + +(format t "Frame Size: ~d~%Slide Size: ~d~%" *frame-size* *slide-size*) + +(defparameter *example* (make-vector-range 0 (- *frame-size* 1))) +(shuffle-array-by-swapping *example*) +(format t "Input: ~S~%" *example*) ;; used array not list :-/ +(defvar result (group-minimum-list *example* *slide-size*)) +(format t "Output: ~S~%" result) diff --git a/challenge-073/jeongoon/common-lisp/ch-2.lsp b/challenge-073/jeongoon/common-lisp/ch-2.lsp new file mode 100644 index 0000000000..d4e0fb06f8 --- /dev/null +++ b/challenge-073/jeongoon/common-lisp/ch-2.lsp @@ -0,0 +1,75 @@ +;; Ref: + +;; tested with +;; sbcl --script ch-2.lsp <number> + +(defun get-command-line () ;; from #072 + (or + #+CLISP *args* + #+SBCL *posix-argv* + #+LISPWORKS system:*line-arguments-list* + #+CMU extensions:*command-line-words* + nil)) + +(defun get-random-pairs (n) + (let ((*random-state* (make-random-state t))) + (loop for cnt from 1 to n + collect (list (random n) (random n))))) + +(defun make-range (minv maxv &optional (step 1)) ;; from #072 + (when (<= minv maxv) + (cons minv (make-range (+ minv step) maxv step)))) + +(defun make-vector-range (min max &optional (step 1)) + (let* ((range (make-range min max step)) + (size (length range))) + (make-array (list size) :initial-contents range))) + +(defun shuffle-array-by-swapping (arr) + (let* ((size (length arr)) + (shuffle-pairs (get-random-pairs size))) + (loop for pair in shuffle-pairs + do (let ((le (first pair)) (ri (second pair))) + (when (not (and (null le) (null ri))) + ;; rotatef: change in place ; I think *f means put in pyhsical memory + (rotatef (aref arr le) (aref arr ri))))))) + +;; tranlated from groupMinimumList in perl/ch-1.pl +(defun smallest-or-zero-list (arr) + (let* ((size (length arr)) + (smallest)) + + (loop for i from 0 below size + collect + (let ((cur-val (aref arr i))) + (if (null smallest) + (progn (setq smallest cur-val) 0) + ;; else + (if (< cur-val smallest) + (progn (setq smallest cur-val) 0) smallest )))))) + +(defparameter *cmdline* (get-command-line)) + +(defun print-usage () + (format t "Usage: sbcl --script ch-1.lsp <list-size>" (car *cmdline*))) + +(when (not (= (length *cmdline*) 2)) + (format t "Wrong Number of arguments: expected 1: but got: ~d~%" (- (length *cmdline*) 1)) + (print-usage) + (quit)) + +;; *size* +(defparameter *size* (parse-integer (second *cmdline*))) + +(when (< *size* 5) + (format t "Too short slide size: ~d: using 5~%" *size*) + (setq *size* 5)) + +(format t "Size: ~d~%" *size*) + +(defparameter *example* (make-vector-range *size* (- (* 2 *size*) 1))) +(shuffle-array-by-swapping *example*) +(format t "Input: ~S~%" *example*) +(defvar result (smallest-or-zero-list *example*)) +(format t "Output: ~S~%" result) + diff --git a/challenge-073/jeongoon/haskell/JRandomList.hs b/challenge-073/jeongoon/haskell/JRandomList.hs new file mode 100644 index 0000000000..685e05a840 --- /dev/null +++ b/challenge-073/jeongoon/haskell/JRandomList.hs @@ -0,0 +1,49 @@ +module JRandomList + ( shuffleByPickingAll, + ) where + +import Data.List ( unfoldr, splitAt, tails ) +import System.Random ( randomR, Random, StdGen ) +import System.Environment (getArgs) + + +{- Ref: +https://www.schoolofhaskell.com/school/starting-with-haskell/libraries-and-frameworks/randoms +https://hackage.haskell.org/package/containers-0.6.3.1/docs/Data-Sequence.html +https://stackoverflow.com/questions/9834433/convert-data-sequence-to-a-list +https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-List.html +https://en.wikibooks.org/wiki/Haskell/Libraries/Random +https://hackage.haskell.org/package/optparse-generic-1.2.3/docs/Options-Generic.html +-} + +descendingRandomR :: (Integral a, Ord a, Random a) => + ((a, a), StdGen) -> Maybe (a, ((a, a), StdGen)) +descendingRandomR ((lo, hi), g) = + let (rv, g') = randomR (lo, hi) g -- rv: random value from seed(g) + hi' = hi - 1 + in if lo > hi then Nothing else Just (rv, ((lo, hi'), g')) + +indicesToPick :: (Integral a, Random a) => + a -> StdGen -> [a] -- input: <highest value> <seed> +indicesToPick = (curry.curry $ unfoldr descendingRandomR) 0 -- 0: first index + +popAt :: Int -> [a] -> (Maybe a, [a]) +popAt = curry $ (\(le, ri) -> + ( if null ri then Nothing else Just (head ri), + le ++ tail ri ) ) . (uncurry splitAt) + +poping :: ([a], [Int]) -> Maybe (a, ([a], [Int])) +poping ([], _) = Nothing +poping (_, []) = Nothing +poping (ls, idcs) = + let (e, ls') = popAt (head idcs) ls + idcs' = tail idcs + in case e of + Nothing -> poping (ls', idcs') -- skip the index which is out of range + Just e' -> Just (e', (ls', idcs')) + +shuffleByPickingAll :: [a] -> StdGen -> [a] +shuffleByPickingAll ls seed = pick (ls, ( indicesToPick maxIdx seed )) + where + pick = unfoldr poping + maxIdx = ( length ls ) - 1 diff --git a/challenge-073/jeongoon/haskell/ch-1.hs b/challenge-073/jeongoon/haskell/ch-1.hs new file mode 100644 index 0000000000..79ff1f2312 --- /dev/null +++ b/challenge-073/jeongoon/haskell/ch-1.hs @@ -0,0 +1,144 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE OverloadedStrings #-} +import Options.Generic +import JRandomList +import System.Random ( StdGen, newStdGen ) +import Data.Maybe + +{- Tested with: +runhaskell -i. ch-1.hs 3 +-} + +aSample :: (Integral a, Num a) => + a -> StdGen -> [Int] +aSample winSize seed = + -- size 3 -> frameSize: 10 + let frameSize = 10 * round( 0.3 * fromIntegral winSize ) + in shuffleByPickingAll [ 0 .. (pred frameSize {-index-}) ] seed + +validateSizeIO :: (Ord a, Show a) => a -> a -> IO a +validateSizeIO def given = do + if given < def then + putStrLn ( "Given size is too short: " ++ (show given) + ++ ": using default size: " ++ (show def) ) + >> return def + else putStrLn( "Given Size:" ++ (show given) ) + >> return given + +groupMinimumListSimple_ :: (Ord a) => [a] -> [a] -> Int -> [a] +groupMinimumListSimple_ acc ls s + | length sld /= s = acc + | otherwise = groupMinimumListSimple_ acc' ls' s where + sld = take s ls + ls' = tail ls + acc' = acc ++ [ minimum sld ] + +groupMinimumListSimple = groupMinimumListSimple_ [] + +someMinValuesWithIndics' :: ( Ord a, Enum a ) + => a -> Maybe (([a], [Int]), Int) -> Maybe (([a], [Int]), Int) +-- set default offset value if nothign specified : not used here +--minValuesWithIndics' x Nothing = minValuesWithIndics' x (Just (([x], [0]), 1)) +someMinValuesWithIndics' x (Just ((min@(m:ms), idx), i)) + | x < m = Just((x:min, i:idx), pred i) + -- prepend the new minimum value + | otherwise = Just((min, idx), pred i) + -- keep record, change index number only + +someMinValuesWithIndics ls offset = + let i = (length ls) -1 +offset + res = foldr someMinValuesWithIndics' (Just(([last ls], [i]), pred i)) (init ls) + in fst( fromJust( res ) ) + +-- bascially same method which is described in ch-1.pl + +groupMinimumList_ :: (Ord a, Enum a) => + ( Maybe( [a], Int, [a], [Int] ), [a] ) -> Int -> [a] + +-- first step +groupMinimumList_ (Nothing, ls) s = + let x = head ls + a' = 2 - s in -- 2nd number of a (when a == 0 we get full size of group) + if 0 <= a' + then groupMinimumList_ (Just([x], a', [x], [0]), ls) s + else groupMinimumList_ (Just([], a', [x], [0]), ls) s +-- edge case (no more elements) +groupMinimumList_ (Just( acc, _, _, _ ), []) _ = acc +groupMinimumList_ (Just( acc, a, min, mem ), ls) s = + let b = a + s -1 -- index for beging checked + -- or last index in the group when inbound + a' = succ a + n = head min; m = head mem + ns = tail min; ms = tail mem + grp = take s $ drop (if a < 0 then 0 else a) ls + x = ls !! b + lsize = length ls + memInbound = (not (null mem)) && a <= m + grpInbound = ( 0 <= a && b < lsize ) in + + if b >= lsize then acc -- edge case + else if (not grpInbound) || (grpInbound && memInbound) then + let acc' q = if grpInbound then acc ++ [q] else acc + min' = if grpInbound then [] else min + mem' = if grpInbound then [] else mem + in + case ( x `compare` n ) of + LT -> -- new minimum + groupMinimumList_ (Just(acc' x, a', x:min, b:mem), ls) s + EQ -> -- better update index only + groupMinimumList_ (Just( (acc' n), a', min, b:ms), ls) s + GT -> {- just skipping : too complicate recalculate memos + better compare evertying in the goup -} + groupMinimumList_ (Just( (acc' n), a', min', mem'), ls) s + + else -- grpInbound && not memInbound + -- memorised value at leftmost not useful anymore + if (not (null mem) ) then -- but maybe we can use next available memo + groupMinimumList_ (Just(acc, a, ns, ms), ls) s + else -- compare everthing in the group + -- meanwhile making memo as well + let res = someMinValuesWithIndics grp a -- a: first index in the group + min' = fst res + mem' = snd res + acc' = acc ++ [ head min' ] in + groupMinimumList_ (Just(acc', a', min', mem'), ls) s + +groupMinimumList :: (Ord a, Enum a) => [a] -> Int -> [a] +groupMinimumList = curry groupMinimumList_ Nothing + +main :: IO () +main = do + args <- getRecord "Challenge #073 - Task #1" + let defS = 3 + sStr = show ( args :: Int ) + s = read sStr :: Int + getSize = validateSizeIO defS s in + do + size <- getSize; + seed <- newStdGen; + let ex = aSample size seed in do + putStr "Example\nInput: " + print $ ex + putStr "Output 1: " + print $ groupMinimumListSimple ex size + putStr "Output 2: " + print $ groupMinimumList ex size + +{- +Task #1 Min Sliding Window +You are given an array of integers @A and sliding window size $S. +Write a script to create an array of min from each sliding window. + +Example +Input: @A = (1, 5, 0, 2, 9, 3, 7, 6, 4, 8) and $S = 3 +Output: (0, 0, 0, 2, 3, 3, 4, 4) + +[(1 5 0) 2 9 3 7 6 4 8] = Min (0) +[1 (5 0 2) 9 3 7 6 4 8] = Min (0) +[1 5 (0 2 9) 3 7 6 4 8] = Min (0) +[1 5 0 (2 9 3) 7 6 4 8] = Min (2) +[1 5 0 2 (9 3 7) 6 4 8] = Min (3) +[1 5 0 2 9 (3 7 6) 4 8] = Min (3) +[1 5 0 2 9 3 (7 6 4) 8] = Min (4) +[1 5 0 2 9 3 7 (6 4 8)] = Min (4) +-} diff --git a/challenge-073/jeongoon/haskell/ch-2.hs b/challenge-073/jeongoon/haskell/ch-2.hs new file mode 100644 index 0000000000..2899246fdd --- /dev/null +++ b/challenge-073/jeongoon/haskell/ch-2.hs @@ -0,0 +1,53 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE OverloadedStrings #-} +import Options.Generic +import JRandomList +import System.Random ( StdGen, newStdGen ) +import Data.Maybe +import Data.List( unfoldr ) + +{- Tested with: +runhaskell -i. ch-2.hs 3 +-} + +aSample :: (Integral a, Num a, Enum a) => + a -> StdGen -> [Int] +-- skip small number an making an example: otherwise result is too boring +aSample size seed = + let s' = fromIntegral size in + shuffleByPickingAll [ s' .. (pred (2*s') {-index-}) ] seed + +validateSizeIO :: (Ord a, Show a) => a -> a -> IO a +validateSizeIO def given = do + if given < def then + putStrLn ( "Given size is too short: " ++ (show given) + ++ ": using default size: " ++ (show def) ) + >> return def + else putStrLn( "Given Size:" ++ (show given) ) + >> return given + +generateSmallest :: ( Integral a, Ord a ) + => ( Maybe a, [a] ) -> Maybe ( a, ( Maybe a, [a] ) ) +generateSmallest ( _, [] ) = Nothing +generateSmallest ( Nothing, ls@(c:ls') ) = Just( 0, ( Just c, ls' )) +generateSmallest ( Just s, ls@(c:ls') ) = + if c <= s then Just( 0, ( Just c, ls' )) -- couldn't find smallest on the left + else Just( s, ( Just s, ls' )) + +processSmallest = curry (unfoldr generateSmallest) Nothing + +main :: IO () +main = do + args <- getRecord "Challenge #073 - Task #2" + let defS = 3 + sStr = show ( args :: Int ) + s = read sStr :: Int + getSize = validateSizeIO defS s in + do + size <- getSize; + seed <- newStdGen; + let ex = aSample size seed in do + putStr "Input: " + print $ ex + putStr "Output: " + print $ processSmallest ex diff --git a/challenge-073/jeongoon/perl/ch-1.pl b/challenge-073/jeongoon/perl/ch-1.pl new file mode 100644 index 0000000000..b712c07e3e --- /dev/null +++ b/challenge-073/jeongoon/perl/ch-1.pl @@ -0,0 +1,175 @@ +#!/usr/bin/env perl +# -*- Mode: cperl; cperl-indent-level:4 tab-width: 8; indent-tabs-mode: nil -*- +# -*- coding: utf-8 -*- + +use strict; use warnings; + +BEGIN { + $::debugging = 0; + @ARGV = map { + my $d = /^--debug$/; + $d && ++$::debugging; + $d ? () : $_; + } @ARGV; + + our $dprint = sub( @ ) { + ++$|; + print "[DBG] ",@_; + }; + *::dprint = $::debugging ? $dprint : sub (@) {}; +} + +sub unsort ( @ ) { sort { (-1,1)[(rand 1)+0.46] } @_ } + +sub groupMinimumList ( @ ) { # $size, @_ + my $s = shift; + # let's memorise the position(index) when we find the mimum value + # if previous minimum position is gone, + # A compare everything in the group + # 1. memo the position, 2. push the value into result + # else e.g. if found + # B compare only between two values + # 1. memo the position, 2. push the value into result + my $min = undef; + my $i = -$s +1; # index when whole sliding door is ready + my $imax = scalar @_ -$s; # same as $#_ -$s +1 + my $memo = -1; + + map { + my $memo_inbound = $memo > $i; + my $door_inbound = 0 <= $i && $i <= $imax; + + if ( $door_inbound && ! $memo_inbound ) { + # compare everything in sliding door (A) + # XXX: no seprate function for debugging purpose + $min = $_[ $memo = $i ]; + ::dprint "(A) $i: min $min at $memo\n"; + for my $d ( 1 .. $s -1 ) { + if ( $min >= $_[$i+$d] ) { $min = $_[ ($memo = $i+$d) ] } + ::dprint "(A) $i: min $min at $memo\n"; + } + } + else { + if ( ! defined $min || $min >= $_ ) { + # keep comparing between two .. (B) + $min = $_; + $memo = $i + ($s -1); # memorise the *real* index in array + ::dprint "(B) $i: min $min at $memo\n"; + } + else { + ::dprint "(B) $i: min $min at $memo (no need to compare at all)\n"; + } + } + ++$i; + $door_inbound ? $min : (); + } @_; +} + +sub groupMinimumListComplex ( @ ) { # $size, @_ + my $s = shift; + + my @min = (); # using array + my @memo = (); # ditto + + my $i = -$s +1; + my $imax = scalar @_ -$s; + + # in this case we are comparing numbrers but. what if comparing + # more complex object and comparing process is not very delightful? + + map { + isEvil: + my $memo_inbound = scalar @memo && $memo[0] > $i; + my $door_inbound = 0 <= $i && $i <= $imax; + + if ( $door_inbound && ! $memo_inbound ) { + # compare everything in sliding door (A) + # Experiment: + # but what if we have another minimum value memorised + # in bound of the group (because we just disgard one element) + if ( scalar @memo ) { + shift @memo; shift @min; + if ( scalar @memo ) { + ::dprint "(B?) Found another minimum value in bound.\n"; + goto isEvil; + } + } + + # compare everything in group again + @memo = ( $i ); + @min = ( $_[ $i ] ); + ::dprint "(A0) $i: min $min[0] at $memo[0]\n"; + + for my $d ( 1 .. $s -1 ) { + my $k = $i+$d; + if ( $min[0] >= $_[$k] ) { # new value is minimum and + if ( $memo[0] > $k ) { # located in left hand side + unshift @min, $_[$k]; + unshift @memo, $k; + ::dprint "(A+) $i: min $min[0] at $memo[0]\n"; + } + else { # or just forget it. :( + @memo = ( $k ); + @min = ( $_[ $k ] ); + ::dprint "(A=) $i: min $min[0] at $memo[0]\n"; + } + } + } + } + else { + if ( scalar @min == 0 || $min[0] >= $_ ) { + # keep comparing between two .. (B) + if ( scalar @min && $memo[0] > $i ) { + unshift @min, $_; + unshift @memo, $i + ($s -1); # memorise the *real* index in array + ::dprint "(B+) $i: min $min[0] at $memo[0]\n"; + } + else { + @min = ( $_ ); + @memo = ( $i + ($s -1) ); + ::dprint "(B=) $i: min $min[0] at $memo[0]\n"; + } + } + else { + ::dprint "(B) $i: min $min[0] at $memo[0] (no need to compare at all)\n"; + # XXX: don't change anything + # because minimum value was not at leftmost + # we can check again in next loop + } + } + ++$i; + $door_inbound ? $min[0] : (); + } @_; +} + +sub map_ssprintf { map { sprintf "%#$_[0]s", $_ } @_[1..$#_] } + +package main; + +my $S = shift; + +(defined $S and $S > 2) or warn "Invalid sliding door size: USING ",$S = 3," !!"; +my $FS = 10*int( .3* $S +.5 ); # reasonable value for (F)rame(S)ize +my @A = unsort 0.. $FS-1; # simply using max number from frame size + +::dprint "Default My solution: \n"; +my @M = groupMinimumList $S, @A; +::dprint "Another one: \n"; +my @E = groupMinimumListComplex $S, @A; + +$" = ' '; +my $W = length( $FS-1 ); # for sprintf + +print "\$S = $S |-> \$FS = $FS\n"; +print "\@A = (${\"}@{[map_ssprintf($W, @A)]}${\"})\n"; + +my $diff = scalar @A - scalar @M; +my @G = ( " " ) x $diff; +my $gh = int .5 * (scalar @G); +my @adj = ( $diff % 2 ) ? ( $", '' ) : ( '', $" ); + +print "\@M = ( $adj[0]". + "@{[map_ssprintf($W,@G[0..$gh-1],@M,@G[$gh..$#G])]}$adj[1])\n"; +print "\@E = ( $adj[0]". + "@{[map_ssprintf($W,@G[0..$gh-1],@E,@G[$gh..$#G])]}$adj[1])\n"; +print "Complex Method Failed\n" unless "@M" eq "@E"; diff --git a/challenge-073/jeongoon/perl/ch-2.pl b/challenge-073/jeongoon/perl/ch-2.pl new file mode 100644 index 0000000000..0797cde8ee --- /dev/null +++ b/challenge-073/jeongoon/perl/ch-2.pl @@ -0,0 +1,49 @@ +#!/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 boolean qw(:all); + +sub unsort ( @ ) { sort { (-1,1)[(rand 1)+0.46] } @_; } +sub map_ssprintf { map { sprintf "%#$_[0]d", $_ } @_[1..$#_]; } + +sub gen_smallest_( $$ ) { + my ( $s, $c ) = @_; # (s)mallest (c)urrent + # return true if we couldn't find the smallest + # because we found new one + # return false if we couldn't find the smallest + # return current smallest if we find the one + if ( isBoolean( $s ) || $s > $c ) { + true # 0 && new smallest + } + else { + ( $s < $c ) ? $s # smallest && keep smallest + : false # 0 && keep smallest + } +} + +sub processSmallest ( @ ) { + my $smallest = boolean( not 'given' ); + map { + my $current_is_smallest_or_just = gen_smallest_ $smallest, $_; + isTrue( $current_is_smallest_or_just ) and $smallest = $_; + isBoolean( $current_is_smallest_or_just ) ? 0 : $smallest; + } @_; +} + +package main; + +my $S = shift; + +( defined $S and $S > 4 ) + or warn "Size not given: USING ",$S = 9," !!"; + +$" = ' '; +my ( @A, @S ); +my $W = length( 2*$S-1 ); # for sprintf + +@S = processSmallest ( @A = unsort $S.. 2*$S-1 ); + +print "\@A = (${\"}@{[map_ssprintf($W, @A)]}${\"})\n"; +print "\@S = (${\"}@{[map_ssprintf($W, @S)]}${\"})\n"; diff --git a/challenge-073/jeongoon/raku/ch-1.raku b/challenge-073/jeongoon/raku/ch-1.raku new file mode 100644 index 0000000000..0dde4e1327 --- /dev/null +++ b/challenge-073/jeongoon/raku/ch-1.raku @@ -0,0 +1,91 @@ +#!/usr/bin/env raku +# -*- Mode: Raku; indent-tabs-mode: nil; coding: utf-8 -*- +# vim: set et ts=4 sw=4: + +use v6.d; + +class memo { has ( $.idx, $.val ); } + +sub caculate-everytime ( :numbers(:@number-list), + Int :window-size(:$ssize) where $ssize > 2 ) { + @number-list.rotor( $ssize => -($ssize-1) ).map( *.min ).Array; +} + +sub caculate-sometime ( :numbers(:@number-list), + Int :window-size(:$ssize) where $ssize > 2 ) { + + my memo @memo = Empty; + my $i = -$ssize + 1; # pseudo index: starting from negative value + + @number-list.map( + -> $c { + my $b = $i + $ssize -1; # last index in the group or to be compared + my $mem-inbound = ( @memo.first.?idx andthen * >= $i ); + my $grp-inbound = 0 <= $i && $b < @number-list.elems; + + if $grp-inbound.not or ( $grp-inbound and $mem-inbound) { + given ( @memo.first.?val andthen $c cmp * or Less ) { + #say "A:$_"; + when Less { + @memo.unshift( memo.new( :idx($b), :val($c) ) ); + } + when Same { # same but better update index because + # if less value located in later, + # there less chance to recalculate + @memo.first.idx = $b; + } + when More { # leave memory: maybe too complex to reorder + # better recalculate everything again + # later + } + } + } + else { # grp-inbound && not mem-inbound + #say "B:trying memo"; + # memorised value at leftmost is not useful + if @memo.elems { # but maybe we can use next available memo + @memo.shift; + redo; # without changing map status + } + else { # no memo: compare evertying in the group + #say "B:no memo:compare everything"; + # first one + @memo.push( memo.new( :idx($i), :val( @number-list[$i] ))); + # and rest + for ( $i ^.. $b ) -> $k { + if @memo.first.val >= @number-list[$k] { # new value is min. + if @memo.first.idx > $k { # and located on the left + # save for next next chance + @memo.push( memo.new( :idx($k), :val( @number-list[$k] ))); + } + else { # too complicate if we re-arrange memo. + # just forget it :-( + @memo = memo.new( :idx($k), :val( @number-list[$k ] )); + } + } + } + } + } + #@memo.map( -> $m { print "{$m.val}\@{$m.idx} "; } ); + #print ": total {@memo.elems}"; + ++$i; + unless $grp-inbound { + #say ""; + next; + } + #say ">>> {@memo.first.val}"; + @memo.first.val; + } ).Array; +} + +sub MAIN ( Int \S where * > 2 #= sliding window size (>2) + ) { + + my \FS = 10 * ( .3 * S + .5 ).floor; # reasonable (F)rame (S)ize + my @sample = ( 0 .. FS -1 ).pick( FS ); + say "Input: {@sample.raku}"; + say "Correct: " ~ caculate-everytime( :numbers(@sample), :window-size(S) ).raku; + say "My Answer: " ~ caculate-sometime( :numbers(@sample), :window-size(S) ).raku; + + +} diff --git a/challenge-073/jeongoon/raku/ch-2.raku b/challenge-073/jeongoon/raku/ch-2.raku new file mode 100644 index 0000000000..2e2798a66c --- /dev/null +++ b/challenge-073/jeongoon/raku/ch-2.raku @@ -0,0 +1,32 @@ +#!/usr/bin/env raku +# -*- Mode: Raku; indent-tabs-mode: nil; coding: utf-8 -*- +# vim: set et ts=4 sw=4: + +use v6.d; + +role zero { method raku { "0" } } + +sub process-smallest ( @list ) { + my $smallest = Nil; + @list.map( + # always return minimum value (current one inclusive) + # but when call with .raku return what Task #2 asks. + -> $c { + if $smallest.defined.not or $c < $smallest { + $smallest = $c; + $c but zero + } else { + $smallest < $c ?? $smallest !! $c but zero + } + }); +} + +sub MAIN ( Int \S where * > 2 #= sliding window size (>2) + ) { + + my @sample = ( S .. 2*S -1 ).pick( S ); + say "Input: {@sample.raku}"; + my @answer = process-smallest( @sample ); + say "Output: {@answer.map( *.raku ).map( *.Int ).Array.raku}" + #say "Ouput: {@answer.raku}"; +} |
