매주 도전 #082 퀘스트 #2::(엘름, 라크)


업데이트 날짜: 2020년 10월 16일
나는 몇몇 사람들의 각본을 보았지만, 아래의 사례는 항상 통과되지는 않았다.
A: ABCDEFGHIJKLMNOPQRSTUVWXYZ
B: ABCDEFGHIJKLMNOPQRSTUVWXYZ
C: ABCABCDDEFGHIJEFKLGHIJKLMNMNOOPPQRQRSTUVSTWXYUVWXYZ
그러나 나의 해결 방안은 256개의 사례를 보여 주었다.

TASK #2 › Interleave String
제출자: 무함메드 S. 안바르
You are given 3 strings; $A, $B and $C.

Write a script to check if $C is created by interleave $A and $B.

Print 1 if check is success otherwise 0.
Example 1:

Input:
    $A = "XY"
    $B = "X"
    $C = "XXY"

Output: 1

EXPLANATION

"X" (from $B) + "XY" (from $A) = $C
Example 2:

Input:
    $A = "XXY"
    $B = "XXZ"
    $C = "XXXXZY"

Output: 1

EXPLANATION

"XX" (from $A) + "XXZ" (from $B) + "Y" (from $A) = $C
Example 3:

Input:
    $A = "YX"
    $B = "X"
    $C = "XXY"

Output: 0

사과하다.
잘못된 해결책이라서 미안해요.
참고Colin Crain's ultimate review네!!물론, 나는 단지 이것이 정확하지 않다는 것을 몰랐을 뿐이지만, 만약 내가 잘못된 정보로 몇몇 사람들을 오도했다면, 나는 정말 미안했다.나는 이 해결 방안이 같은 역할을 하지 않기를 바란다.
다음 회로 돌아온 걸 환영합니다.

왜 미션 2를 먼저 완수해야 합니까?
나는 내일의 임무 #1을 건너뛰었다. 왜냐하면 그것은 보기에 매우 쉽게 만력으로 완성할 수 있지만, 만약 우리가 '더 나은' 방식으로 그것을 완성한다면 매우 어려울 것이다.그런데 미션 2랑 미션 1은 난이도가 똑같아요.😂

Elm 솔루션
Elm과 함께 이 임무를 설명하고 싶었지만, 내 시간과 정력을 초과했기 때문에, 나는 아래의 링크를 남겼다
Ch2.elm

교차와 취소 교차
한 아이가 울고 있었고, 다른 아이는 동시에 나에게 큰소리로 외쳤다.
나는 왜 한 아이가 울고 있고, 다른 아이가 나에게 무엇을 묻는지 확실히 알아야 한다.이것은 짜증나는 육아 후에 완성할 수 있다. 예를 들어 A에게 물어보고 B를 둘러보며 다시 A를 안고 B에게 우호적인 말을 할 수 있다...그런데 다음은요?
예시와 같이 이 두 문자열의 사용은 불균형적일 수 있다.그래서 아마도 우리는 $C를 몇 개의 블록으로 나누어 문자열을 만들 수 있을 것이다. 나는 여기서 '비교차' 라고 부르고, 그것들을 주어진 a, B와 비교해서, 그것들이 C에서 조화롭게 교차할 수 있다는 것을 확인할 수 있을 것이다. 이것은 나에게 의미가 있기 때문에, 나는thissenario를 선택했다.
그래서 저희가 "abcdef"를 [1,2,3]로 나눠야 돼요.
우리는 스스로 할 수 있다. 예를 들면...
# abcdef
# 012345 # index
"abcdef".substr(^1)      # same as "abcdef".substr(0 .. 1)
"abcdef".substr(1 .. ^3) # same as "abcdef".substr(1 .. 2)
"abcdef".substr(3 .. ^6) # same as "abcdef".substr(1 .. 5)
그럼요!우리는 라쿠에게 더 많은 일자리를 줄 수 있다.그러나 하위 문자열을 얻기 전에 숫자가 필요합니다.
> my $i = 0;
> (0,1,2,3).map( -> $x { $i += $x; $i } ) # 0 prepended to easier caluation
(0 1 3 6)
우리는 다음과 같은 결과를 줄이거나 누적할 수 있다. 왜냐하면 라쿠는 고급 함수를 지원하기 때문이다. 이것은 내가 지난번 도전에서 배운 것이다.공헌이 많을수록 얻는 정보가 많습니다.👍
> [\+] (0,1,2,3)
(0 1 3 6)
좋습니다. 이 숫자를 더욱 의미 있게 하기 위해서 markus holzer code 다시 사용하겠습니다.
> ([\+] (0,1,2,3)).rotor( 2 => -1 );
((0 1) (1 3) (3 6))
아마도 너는 나의 첫 번째 시도에서 이 숫자들의 유사점을 발견할 수 있을 것이다.
재료 배합도를 그려봅시다!🤩
> ([\+] [0..3]).rotor( 2 => -1 ).map( -> ($a, $b) { "abcdef".substr( $a ..^ $b ) } );
(a bc def)
rotor
교차하지 않음(분해)(패리티)
취소 교차는 모든 홀수 색인 블록을 하나의 문자열로 합쳐서 완성할 수 있고 짝수 블록도 합칠 수 있습니다.아주 간단하게 들려요...그런데 구체적으로 어떡하지???
우리는 가지 방법이 있다.
> <a b c>.pairs # same as ("a", "b", "c").pairs
(0 => a 1 => b 2 => c)
우리.pairs가 바로 그들
보화영도팀이 지난주에 선물한 거예요.
<a b c>.pairs.classify( {.key %% 2 ?? "evens" !! "odds" } )
{evens => [0 => a 2 => c], odds => [1 => b]}
그러나 우리는 값만 필요하고 색인 (키) 은 필요 없다
> <a b c>.pairs.classify( {.key %% 2 ?? "evens" !! "odds" }, :as{.value} )
{evens => [a c], odds => [b]}
하지만 나는 하나의 수조로서 우리가 할 수 있는 것은
> <a b c>.pairs.classify( {.key %% 2 ?? "evens" !! "odds" }, :as{.value} )<odds evens>
([b] [a c])
대부분의 스크립트 언어에서 문자열 연결은 쉬울 것이다
> <a b c>.pairs.classify( {.key %% 2 ?? "evens" !! "odds" }, :as{.value} )<odds evens>.map({.join})
(b ac)
그래서 지금만약 우리가 문자열 $C와 블록의 크기를 알고 있다면, 우리는 두 개의 엇갈린 문자열을 만들 수 있습니다.
.classify
모험이야, 다 모험이야?🤔
"Task #2 단순한""예""또는""아니오""질문일 뿐입니다. 비록 이 질문이 우리의 업무를 더 쉽게 하지는 않지만."우리가 확신할 때까지 많은 병례나 모든 가능한 병례를 검사해야 하기 때문이다.

Porman은 교환

If a string has length of 5, deviding 5 into integers looks like

(1,1,1,1,1)
(1,1,1,2)
(1,1,2,1)
...
(4,1)
(5)
It is almost looks like permutations with repeatition as choosing 5 from 5 with repeatition. but number of cases should be less than that due to the same summation of of those number Let's make a perm... with repe ... things. with number of 3
Raku has
X 서브루틴의 실현이 좋지 않았다.저 X 진짜 좋아해요.
> (0..3) X (0..3) X (0..3)
((0 0 0) (0 0 1) (0 0 2) (0 0 3) (0 1 0) (0 1 1) (0 1 2) (0 1 3) (0 2 0) (0 2 1) (0 2 2) (0 2 3) (0 3 0) (0 3 1) (0 3 2) (0 3 3) (1 0 0) (1 0 1) (1 0 2) (1 0 3) (1 1 0) (1 1 1) (1 1 2) (1 1 3) (1 2 0) (1 2 1) (1 2 2) (1 2 3) (1 3 0) (1 3 1) (1 3 2) (1 3 3) (2 0 0) (2 0 1) (2 0 2) (2 0 3) (2 1 0) (2 1 1) (2 1 2) (2 1 3) (2 2 0) (2 2 1) (2 2 2) (2 2 3) (2 3 0) (2 3 1) (2 3 2) (2 3 3) (3 0 0) (3 0 1) (3 0 2) (3 0 3) (3 1 0) (3 1 1) (3 1 2) (3 1 3) (3 2 0) (3 2 1) (3 2 2) (3 2 3) (3 3 0) (3 3 1) (3 3 2) (3 3 3))
또는 귀속 호출을 통해 완성할 수 있다.
> sub p($num-cases, $internal-use = $num-cases) {
if $internal-use == 1 { (0...$num-cases).cache }
else { (((0..$num-cases) X p($num-cases, $internal-use.pred).List).map(*.flat.cache)) } }
&p
> p(3)
...
저희가 결과를 볼 수 있어요.
> p(3).  # unfolded for better reading
         # you need to concat. them if you want to check in shell.
grep(*.sum == 3).
map(*.cache.grep(*>0)).
sort.
unique( :with(&[eqv]) )
((1 1 1) (1 2) (2 1) (3))

더 똑똑한 방법
나는 앞의 실현을 좋아하지 않는다. 나는 차라리 이렇게 하는 것을 피하고 싶다. 왜냐하면 그것은 임무가 진정으로 필요로 하는 것을 소홀히 하기 쉽기 때문이다.
그러나 폭력의 방식은 항상 우리의 답안에 지도선을 제공한다.만약 우리가 정말 문제를 해결하느라 바쁘다면??
나도 귀속 호출 방법도 이런 문제를 해결하는 좋은 방법이라고 믿는다.
multi sub p( Int $n, Int $sum, $parts, $siblings ) {
    ().return if $sum == 0;

    my $parts-new = (|$parts, $n);

    if $n == $sum { # last case in the siblings (or depth)
        # (no more *next* cases in other word)
        # because we are checking from 1 to maximum
        (|$siblings, ($n,)).return; # comma required
    }
    else {
        # may have lower cases (if valid) and next cases
        my $lower-cases = samewith( 1, ($sum-$n), $parts-new,
                                   Empty );

        my $curr-cases = (($n,) X $lower-cases.List).map(*.flat);
        # note: .List is needed because it's itemized
        # and which makes slip and flattening very hard :-$
        # check next cases with current cases as a sibling
        samewith($n.succ, $sum, $parts,
                 (|$siblings, |$curr-cases) );

    }
}
multi sub p( Int $sum ) {
    samewith( 1, $sum, $empty, $empty );
}
> p(3)
((1 1 1) (1 2) (2 1) (3))
원소가 어떤 절단도 할 수 없기 때문에 우리는 필요없을지도 모른다.
> p(3).grep( *.elems > 1 )
((1 1 1) (1 2) (2 1))

과거의 미래로 돌아가기(교차)
이제 우리는 문자열을 두 단락으로 나누는 방법을 알게 되었다. 그러면 우리는 그것들을 두 번 비교할 수 있다. (a, B는 반드시 특정한 순서에 따라 배열된 것이 아니기 때문이다.) 만약 어떤 상황이 사실이라면, 이것은 가능한 방법이다.
> my $A = "X";
my $C = "XY";
my $C = "XXY";

> p(3).grep(*.elems > 1).map({([\+] (0,|$_)).rotor( 2 => -1 ).map( -> ($a, $b) { $C.substr( $a ..^ $b ) } ) });
}
((X X Y) (X XY) (XX Y)
너는 그들에게 가입할 수 있다.
>  p(3).grep(*.elems > 1).map({([\+] (0,|$_)).rotor( 2 => -1 ).map( -> ($a, $b) { $C.substr( $a ..^ $b ) } ) }).map({ .pairs.classify( {.key %% 2 ?? "evens" !! "odds" }, :as{.value} )<odds evens>}).map({.map(*.join(""))});
((X XY) (XY X) (Y XX))
앞의 일련의 코드는 Raku interactive 셸에 대한 것입니다. (따라서 복사, 붙여넣기, 테스트를 할 수 있습니다.) 만약 우리가 그것을 펼치면
p(3).                # possible block partitions
grep(*.elems > 1).   # skip unuseful parts
map({([\+] (0,|$_)). # making (index) ranges
rotor( 2 => -1 ).
map( -> ($a, $b) { $C.substr( $a ..^ $b ) } ) }). # make slices
map({ .pairs.
      classify( {.key %% 2 ?? "evens" !! "odds" },
      :as{.value} )<odds evens>}).    # group by (odd or even)
map({.map(*.join(""))});              # make two words
코드를 비교하는 것은 매우 어려운 일이 아니기 때문에...이 부분을 넘어가겠습니다.내 사과!!😱 하지만 나는 자신의 해결 방안에 코드 세션을 남겼다.
...
              ( (A,B)|(B,A) ).map( # |: any
                    {
                        my \om = ($^a, o)>>.chars.min;
                        my \em = ($^b, e)>>.chars.min;

                        [eq] ($^a,o)>>.substr(^om)
                        and
                        [eq] ($^b,e)>>.substr(^em)
                    })[0].so
...
(.so는 코드 또는 객체를 부울 값으로 계산합니다.)

최종 코드
나의 최종 코드는 내가 여기서 설명한 것과 다르다.나는 그것을 중간 수준의 문장으로 만들고 싶기 때문에, 나의 해결 방안은 마땅히 해야 할 것보다 더 복잡하다.
나는 더 많은 제약을 추가해서 더 많은 불필요한 상황을 필터했지만, 이것은 임무 2의 요구를 초과한 것 같다.만약 그것이 "우리는 2Kb의 텍스트 데이터를 가지고 있다..."로 시작한다면이 해결 방안은 그것에 적합하다.
#!/usr/bin/env raku
# -*- Mode: Raku; indent-tabs-mode: nil; coding: utf-8 -*-
# vim: set et ts=4 sw=4:

use v6.d;

sub all-possible-partitions( \A, \B, \C ) { # real entry point
    my $sum = C.chars;
    sps_( 1, $sum, Empty, Empty,
          sub (List $parts) {
                if ( $parts.elems <= 1 ) {
                    return True; # only needed to keep going through
                }
                # check interleaved **partially**
                my ( $splited, \o, \e ) = uninterleave( C, $parts );

                ( (A,B)|(B,A) ).map( # |: any
                    {
                        my \om = ($^a, o)>>.chars.min;
                        my \em = ($^b, e)>>.chars.min;

                        [eq] ($^a,o)>>.substr(^om)
                        and
                        [eq] ($^b,e)>>.substr(^em)
                    })[0].so
            } ).
    grep( *.elems > 0 ).
    map(
        {
            with uninterleave( C, $_.List ) { # .List needed
                (( A eq .[1] and B eq .[2])
                 or
                 ( B eq .[1] and A eq .[2])).so
                or next;

                $_; # return result of uninterleave() when True
            }
        });
}


# make permutations with repeatition and filtering
# to divide the given $sum into smaller natural numbers
# note: still need to sieve after work to get right result.
sub sps_ ( Int $n, Int $sum, $parts, $siblings, &is-valid ) returns List {
    ().return if $sum == 0;

    my $parts-new = (|$parts, $n);

    if is-valid( $parts-new ) {
        if $n == $sum { # last case in the siblings (or depth)
                        # (no more *next* cases in other word)
                        # because we are checking from 1 to maximum
            (|$siblings, ($n,)).return; # comma required
        }
        else {
            # may have lower cases (if valid) and next cases
            my $lower-cases = samewith( 1, ($sum-$n), $parts-new,
                                        Empty, &is-valid );

            my $curr-cases = (($n,) X $lower-cases.List).map(*.flat);
            # note: .List is needed because it's itemized
            # and which makes slip and flattening very hard :-$

            # check next cases with current cases as a sibling
            samewith($n.succ, $sum, $parts,
                     (|$siblings, |$curr-cases), &is-valid);
        }
    }
    else {
        $siblings.return;
    }
}

sub uninterleave( Str $str, List $split-rule ) {
    # return as ( <splited $str>, <odd joined> <even joined> ) )
    $split-rule.elems > 1 or Empty.return;

    with ( ([\+] (0, |$split-rule)). # each block size -> each index in string
            rotor( 2 => -1 ).         # two pairs of indices surrounding a block
            map({$str.substr(.[0] ..^ .[1])}) ).cache {
        ## return values ...

        .self,
        # `-> 1. string partitions itself
        (.pairs.
         classify( {.key %% 2 ?? "e" !! "o" },
                   :as{.value} )).<o e>>>.join("").Slip;

        # `-> 2. string joined out of odd indexed blocks
        #     3. string joined out of even indexed blocks

    }
}

sub MAIN ( *@str where { @str.elems == 3 and @str.all.chars > 0 } ) {
    my (\A, \B, \C) = @str;

    if A.chars + B.chars != C.chars {
        say "0 as length A + B != C";
        exit 0;
    }

    my @found-cases = all-possible-partitions( A, B, C );
    if @found-cases.elems == 0 {
        say "0 as no interleaved cases found"
    }
    else {
        say "1 as we found {@found-cases.elems} possible senario(s)\n" ~
        "e.g) `{C}' can be decomposed like below.\n";

        for @found-cases -> ($splited, $a, $b) {
            say "{$splited.Array.raku} -(uninterleave)-> $a, $b";
        }
    }
}

결과는요
$ raku ch-2.raku XXY XXZ XXXXZY
1 as we found 6 possible senario(s)
e.g) `XXXXZY' can be decomposed like below.

["X", "X", "X", "X", "Z", "Y"] -(uninterleave)-> XXY, XXZ
["X", "X", "X", "XZ", "Y"] -(uninterleave)-> XXZ, XXY
["X", "XX", "X", "Z", "Y"] -(uninterleave)-> XXZ, XXY
["X", "XX", "XZ", "Y"] -(uninterleave)-> XXY, XXZ
["XX", "XX", "Z", "Y"] -(uninterleave)-> XXY, XXZ
["XX", "XXZ", "Y"] -(uninterleave)-> XXZ, XXY

읽어주셔서 감사합니다~~

코멘트
임무2는 나의 기대를 초과했다.나는 라쿠의'.cache'와'.List','.flat'에 대해 많은 문제를 가지고 있다.다음 걸로 남겨놓을게요.
관심 있는 경우 언제든지 방문하십시오"Perl Weekly Challenge".
아까 드라마 봐요.😎

좋은 웹페이지 즐겨찾기