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.