ASCII hamantaschen을 세어보세요!


18

오늘날 푸림은 hamantaschen (단수 : hamantasch ) 이라는 충전재로 삼각형 모양의 쿠키를 제공하는 하나의 관습입니다 . 또 다른 관습은 많이 마시는 것입니다.

나는 가장 완벽한 빵 굽는 사람이 아닙니다 .... 나는 불규칙한 크기의 hamantaschen을 줄 사람이 많고 친구들이 줄 것입니다! 쿠키 사진을 보냈다면 어떤 크기와 충전재를 몇 개나 가지고 있는지 알려 주실 수 있습니까? 그러나 Purim이고 많은 코드를 읽기에는 너무 취 했으므로 가능한 한 작은 코드 여야합니다.

정의

크기

hamantasch는 모든 크기 가 될 수 있습니다 . 가장 작은 hamantasch는 크기 1이며 다음과 같습니다.

/\  --
--  \/

때때로 여러 hamantaschen이 겹칠 수 있습니다 . 아래 모양은 2 개의 hamantaschen (1 크기 1, 1 크기 2)으로 계산됩니다.

 /\
/\ \
----

일부 hamantaschen이 작성했습니다 . 이것은 모든 공백을 문자로 채워서 표시됩니다. 크기 1 hamantaschen은 충전물을 가질 수 없습니다.

우리는 채우고 크기에 따라 hamantaschen 을 이름을 지정할 것 입니다. 형식을 사용하고 <filling> <size>채워지지 않은 경우 - <size>(대신 공백을 사용할 수 -있지만 마크 다운은 마음에 들지 않습니다)를 사용하십시오.

다음은 a . 2, a . 4및 a입니다 - 3.

          /\
         /./\
 ----   /./  \
 \../  /./    \
  \/   --------

이들은 a @ 3, a . 2및 a입니다 - 4.

          /\
         / /\
  /\    / /@@\
 /..\  / /@@@@\
 ----  --------

여기 더 어려운 것이 있습니다. & 2겹친 경사로 인해 예상보다 적은 양의 충전재가 어떻게 나타나는지 확인하십시오 - 3. a - 1, & 2a - 3및 a가 있습니다 & 4.

--------
\   \/&/
 \  /\/
  \/&/
   \/

입력

텍스트 파일 또는 단일 문자열 hamantaschen이 제공됩니다 (선택적 후행 줄 바꿈 및 선택적으로 채워진 후행 공백은 짝수).

제한

  • 문자열이 유효 할 것으로 예상 할 수 있습니다. 즉, 공백이 아닌 모든 문자는 맛있고 달콤한 hamantasch (왜 반죽을 낭비합니까?)에 기여합니다.
  • 당신은 또한 할 것으로 예상 할 수있다 적절하게 채워 즉, 각이 완전히 일치하는 ASCII 문자로 채워집니다 hamantasch - - 채워지지에 대한 ASCII (32), 또는 작성 (제외 아무것도 32..127 여부 /, \등을 -).
  • 이 hamantaschen은 3 칸으로 쌓이지 않습니다 . 모든 /과가 \표시됩니다. 모든 -의해 차단되지 않은 /및 \표시됩니다. 필링은 매우 마지막에 온다.
  • 모든 hamantaschen은 수평선의 반 이상 (반올림)을 볼 수 있습니다.
  • 연속적인 채우기 블록은 그것을 둘러싸고 있는 가장 작은 hamantasch 만 채 웁니다 .

산출

위의 기준을 충족하는 모든 hamantaschen의 "이름"목록을 반환하십시오. 출력은 원하는 형식 (문자열, 해시, stdout 등)이 될 수 있습니다.

테스트 사례

테스트 사례 # 1

입력 # 1 :

          /\
         / /\
  /\    / /@@\
 /..\  / /@@@@\
 ----  --------
    /\
   /**\
  /*/\*\
 /*/..\*\
 --------

출력 # 1 :

. 2
. 2
- 4
@ 3
* 4

테스트 사례 # 2

입력 # 2 :

  /\----
 /\/\*\/
/ /\d\/
------

출력 # 2 :

- 3
- 2
d 2
- 1    
* 2
- 1

테스트 # 3

입력 # 3 :

----
\/\/
/\/\  /\
---- /::\
     ----

출력 # 3 :

- 1
- 1
- 2
- 1
- 1
- 2
: 2

테스트 # 4

입력 # 4 :

 /\/\
/ /\$\
-/--/\\
 --/--\
  /xxx/\
 /xxx/##\
 ---/----\
   /      \
   -------- 

출력 # 4 :

$ 2
x 4
- 3
- 2
- 4
- 1
- 1
# 2

잘못된 테스트 사례 # 5

입력:

/\
\/

산출:

이것을 처리 할 필요는 없습니다.


hamentaschen이 겹치지 만 동일한 수평선이없는 테스트 사례는 어떻습니까? 다른 사람의 수평선을 막을 수도 있습니다.
— 자랑스런 Haskeller

@proudhaskeller 알았어. 그러나 저는 이것을 텍스트에 넣었습니다. 이것은 2 칸입니다. 우리는 것입니다 항상 모두를 참조 /하고 \ , 그리고 -비장의 충전 항상 것입니다.
— 찰스

2
@EasterlyIrk 에스더서를 읽고 (나쁜 사람들을 비난하고) 가난한 사람들에게주는, 의상을 입는 것과 같은 기초적인 것들이 덜 중요한 다른 것들도 있습니다.
— 찰스

1
다시 관련성!
— downrep_nation

1
초기 열을 0으로 설정하면를 제외한 모든 정점 열 (1,0)이에 의해 해제됩니다 +1. 아직도, 나는 당신이 무슨 뜻인지 알고 동의합니다. 두 상단 상단 의 오른쪽 상단과 왼쪽 상단이 아니라 (2, 2)a의 상단 중앙에 어떤 표시가 있습니까? 내가 볼 수있는 것은 없습니다. 같은 논리가에 적용됩니다 . 가능한 최대 hamantaschen을 가정하는 규칙을 추가하지 않는 한 ...- 2- 1(3, 2)
— Michael Plotke

답변:


4

C #, 496452 바이트

편집 : 범위 검사와 함께 버그를 발견했지만 내 코드를 이해하도록 강요 된 바이트로드를 스트라이프했습니다. 로컬 함수를 언 롤링하면 약간 도움이되었고 C # 7 특정 코드는 제거되었습니다. 이 질문은 정말 재미있었습니다.

using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,z=0,d,q,c,j,b;for(;(L=C.ReadLine())!=null;H+=W=L.Length)D+=L;var B=new int[H];for(d=W;(d=-d)>0||++z<H*H;)for(c=1,q=z%H;c<=z/H&q%W+c<W&q>=d&q<H+d&&D[q]==(d>0?92:47)&D[j=q+c]==(d<0?92:47);q-=d+1,c+=2){for(b=0;j>q;)b+=D[--j-d]==45?2:0;for(char h='-',e;c==z/H&b>c;C.WriteLine(h+" "+c/2))for(b=c++;b>1;j=q+=d+1,b-=2)for(;j<q+b;)B[j]=h=B[j]<1&h==45&(e=D[j++])!=47&e!=92&e>32?e:h;}}}

온라인으로 사용해보십시오

완전한 프로그램, 표준 입력에 대한 스페이스 패딩 입력, 표준 출력에 대한 출력 예상. 출력은 줄당 하나의 항목이며, 줄 바꿈이 있습니다. 쿠키는 왼쪽 상단부터 가장 큰 크기 순서로 출력됩니다. 규칙을 이해하는 데 시간이 많이 걸렸지 만 제공된 모든 예제를 통과했다고 생각합니다.

유효한 Hamantaschen에 대해 전체 그리드를 반복적으로 검색하여 '허용 된'크기를 증가시켜 작동합니다. 각 셀에 대해, 이는 다음의 상하를 확인 \하고 /양쪽까지로 할 수있다. 다음 행에 많은 수가 -있고 현재 크기가 '허용 된'크기 인 경우 채우기를 결정하고 항목을 인쇄합니다.

충전은 쿠키의 전체 공간을 탐색하여 '사용되지 않은'셀을 찾습니다. 사용하지 않는 셀이 발견되면 사용 된 것으로 표시됩니다 (허용 된 크기를 늘리고 셀이 포함 된 가장 작은 쿠키임을 알기 때문에).

형식화 및 주석 처리 된 코드 :

using C=System.Console;

class P
{
    static void Main()
    {
        //   32
        // - 45
        // / 47
        // \ 92
        // range 32..127 (no mod for you)

        string D="", // the whole map
            L; // initally each line of the map, later each line of output

        int W=0, // width
            H=0, // length (width * height)
            z=0, // search tracker
            d, // check direction (this is backwards (1 byte saving!))
            q, // check tracker
            c, // counter (truely, this is the distance from the right to the left)
            //M, // c max (now inlined as z/H)
            j, // horiontal tracker
            b; // - count, and reverse counter

        // read map and width
        for(;(L=C.ReadLine())!=null; // read a line, while we can
                H+=W=L.Length) // record the width, and increment height
            D+=L; // add the line to the map

        var B=new int[H]; // whether this filling has been used already (0 -> false, >0 -> true)

        for(d=W; // init direction
            (d=-d)>0|| // swap direction, else increment z (this allows us to run the check for the same z twice with opposite direction)
            ++z<H*H; // for all M, for all q (z<H -> M=z/H=0 -> no valid cookies, so we can safetly skip them)
            )
            for(//M=z/H, // c allow (now inlined)
                c=1, // reset counter
                q=z%H; // note position
                c<=z/H& // counter check
                // no need for a left check: if we run off the left end, then the right check will necessarily fail
                q%W+c<W& // right check
                q>=d& // high check
                q<H+d&& // low check (short-circuit lookups)
                D[q]==(d>0?92:47)&D[j=q+c]==(d<0?92:47); // /\ or \/ check, and set j=q+c
                    q-=d+1, // move left tracker
                    c+=2) // increase counter (move right tracker)
            {
                // count the number of '-' into b
                for(b=0; // zero b
                    j>q; // for each element in the row below
                        ) // empty
                    b+=D[--j-d]==45?2:0; // add 2 to b if we tap a '-'

                // j = q

                // check valid before looking up cHaracter (so we don't mark unused stuff as taken)
                // if we are at the current max count, and we have enough -, then we are valid and should be commited
                for( // this runs either one or zero times, we only have a for here (rather than an if) so we can ditch a pair of braces
                    char h='-', // default filling
                         e; // filling we are considering
                    c==z/H&b>c;
                        C.WriteLine(h+" "+c/2)) // print filling and count
                    // continuously compute character
                    for(b=c++; // count b backwards, starting from c (add 1 to c so we can /2 in print)
                        b>1;j=q+=d+1,b-=2) // count q backwards toward z%H (where q came from), and b backwards toward 1 (for each row)
                        for(;j<q+b;) // for each cell in row
                            B[j]= // mark cell as taken (h,e > 0)
                            h= // record filling
                                B[j]<1& // check cell not already used
                                h==45& // '-'
                                (e=D[j++])!=47& // '/'
                                e!=92& // '\'
                                e>32 // ' '
                                ?e:h; // take first filling we can
                    // c runs out after this (exists both loops), so no need to action
            }
    }
}

4 가지 테스트 사례에 대한 결과 :

testcase #1
. 2
. 2
@ 3
- 4
* 4

testcase #2
- 1
- 1
- 2
d 2
* 2
- 3

testcase #3
- 1
- 1
- 1
- 1
- 2
- 2
: 2

testcase #4
- 1
- 1
- 2
$ 2
# 2
- 3
x 4
- 4

이것이 C #에서 얼마나 컴팩트한지 놀랐습니다! 잘 했어!
— 찰스

유일하게 유효한 답변! 나는 거의 기능적이지만 약간의 오류가 있습니다 (그러나 어쨌든 승자로 설정하지는 않을 것입니다)
— Charles
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.