ASCII 다각형의 면적


31

ASCII 아트를 나타내는 문자열을 입력으로 받아 프로그램을 작성해야하며, ot는 폴리곤의 면적을 반환합니다.

입력은 문자로 구성 _ / \ L V space되고 간단한 다각형 (추가 세그먼트, 자체 터치 및 자체 교차가 없음)을 newline정의 하는 문자열 입니다.

단일 문자 셀의 영역은 2

  • _셀 크기로 분할 0하고2
  • \셀 크기로 분할 1하고1
  • /셀 크기로 분할 1하고1
  • L셀 크기로 분할 0하고2
  • V셀을 크기로 분할 1하고 1(의 양쪽 V은 항상 다각형의 같은쪽에 있으므로 목록에서 함께 처리됩니다.)

모든 문자는 예상되는 문자 셀의 두 모서리를 연결합니다 (예 :의 경우 왼쪽 상단 및 오른쪽 상단 V).

면적이 7 인 예 ( 1+2+1두 번째 행과 1+1+1세 번째 행 ) :

 _
/ \
V\/

입력

  • 입력은 사각형을 형성합니다. 즉, 개행 사이에 같은 수의 문자가 있습니다.
  • 다각형의 모든면에 추가 공백이있을 수 있습니다.
  • 후행 줄 바꿈은 선택 사항입니다.

산출

  • 다각형의 면적 인 단일 양의 정수

출력은 입력의 마지막 행 뒤에 있습니다.

  _  
  V  

1

/L
\/

3



    /VV\
    L  /
     L/
14

  ____/\ 
  \    /
/\/   /
\____/

32  

   /V\
  /   \__ 
  \     /
/\/   /V
L____/

45

이것은 코드 골프이므로 가장 짧은 항목이 이깁니다.


세 번째 예는 14
Optimizer입니다.

@Optimizer 감사합니다.
randomra

^ 의도적으로 부족 합니까?
RobAu

@RobAu 예, 충분하지 않습니다.
randomra

답변:


5

CJam, 48 43 29 바이트

qN-{i_9%2%U!^:U;J%D%1U2*?}%:+

업데이트 : orlp의 답변에서 수학과 state * 2 트릭을 사용하여 많은 골퍼를했습니다.

작동 방식 (구식, 곧 업데이트)

우리는 입력을 줄 바꿈으로 나누고 각 부분마다 경계 문자 발생 횟수를 유지합니다 L\/. 이 카운터 % 2는 모든 문자에 대해 선택할 두 파티션의 양을 알려줍니다. 그런 다음 문자열에서 각 문자의 색인을 찾습니다 L _. \/V줄 것이다 -1배열의 마지막 요소 참조. 인덱스를 얻은 후 4558Zb2/배열 [[2 0] [0 2] [0 2] [1 1]]을 만든 다음 카운터를 사용하여 올바른 카운트를 선택합니다.

qN/0f{                                  }      e# Split the input on newline and for each
      \{                             }/        e# swap the 0 to back and for each char in
                                               e# the line, run this loop
        _"L _"#                                e# Copy the char and get index of it in
                                               e# this string "L _"
               4558Zb                          e# This is basically 4558 3base
                                               e# which comes to be [2 0 0 2 0 2 1 1]
                     2/=                       e# Group into pairs of 2 and choose the
                                               e# correct one.
                        2$=                    e# Based on the counter, choose the correct
                                               e# partition amount
                           @@"\/L"&,+          e# Increment the counter if the char is one
                                               e# of \, / and L
                                       ;       e# Pop the counter after each line loop
                                         :+    e# Sum all the numbers to get area

여기에서 온라인으로 사용해보십시오


22

피스, 47 46 45 36 30

FNs.zx=Z}N"\/L"aY|}N"\/V"yZ;sY

설명:

FNs.z            For every character in input, except newlines...
  x=Z}N"\/L"     Swap state if /, \, or L.
  aY|}N"\/V"yZ;  Append 1 if /, \, or V, else 2 times the state to Y.
sY               Sum Y and print.

"다각형 안에"와 "다각형 안에"라는 두 가지 상태가 있습니다. 다음 문자는 왼쪽에서 오른쪽 아래로 읽을 때 각각 다음을 수행합니다.

/ \     swap state, add one to area
V                   add one to area
_ space             if in polygon, add two to area
L       swap state, if in polygon, add two to area

"영역에 하나 추가"와 "다각형에있는 경우 영역에 두 개 추가"는 상호 배타적입니다.


x=작동 방식이 정말 혼란 스러워요 . 이것은 어딘가에 기록되어 있습니까?
Jakube

@Jakube 확장 된 과제입니다.
orlp

@Jakube이의 등 +=이나 *=또는 무엇 이건. 이 경우 xxor로 사용되므로 Python과 정확히 동일 ^=합니다.
isaacg

14

망막 , 293 + 15 = 308 (314) 385 바이트

;`\s
_
;`\\
/
;`.+
o$0iio
;+`(o(?=/.*(i)|L.*(ii)|V.*(io)|_)|i(?=/.*(io)|L.*(o)|_.*(ii)|V.*(i))).
$1$2$3$4$5$6$7$8
;`o
<empty>
;`ii$
#:0123456789
;+`^(?=i)(i*)\1{9}(?=#.*(0)|i#.*(1)|ii#.*(2)|iii#.*(3)|iiii#.*(4)|iiiii#.*(5)|iiiiii#.*(6)|iiiiiii#.*(7)|iiiiiiii#.*(8)|iiiiiiiii#.*(9))
$1#$2$3$4$5$6$7$8$9$10$11
:.*|\D
<empty>

각 줄은 별도의 파일로 이동하므로 바이트 수에 13을 추가했습니다. 또는 모든 것을 단일 파일에 그대로 놓고 -s플래그를 사용할 수 있습니다 . <empty>실제로 빈 파일이나 라인 스탠드.

불행히도 결과를 단항에서 10 진수로 변환하려면 187 바이트가 필요합니다. 나는 정말로 이것을 곧 구현 해야한다고 생각한다 .

설명

Retina는 정규식 기반 언어입니다 (정규식으로 이와 같은 작업을 수행 할 수 있도록 정확하게 작성했습니다). 각 파일 / 라인 쌍은 대체 단계를 정의하며, 첫 번째 행은 패턴이고 두 번째 행은 대체 문자열입니다. 패턴 앞에-로 `구분 된 구성 문자열이있을 수 있습니다.이 문자열에는 일반적인 정규식 수정 자 및 일부 Retina 특정 옵션이 포함될 수 있습니다. 위 프로그램의 경우 관련 옵션은 ;해당 단계의 출력을 억제 +하고 결과 변경이 중지 될 때까지 루프에 대체를 적용합니다.

솔루션의 아이디어는 각 줄을 개별적으로 계산하는 것입니다. 다각형의 내부 또는 외부에서 이미 접한 문자로 항상 결정할 수 있기 때문입니다. 이것은 선의 시작과 끝이 항상 다각형 외부에 있기 때문에 전체 항목을 단일 선으로 결합 할 수 있음을 의미합니다. 우리는 또한주의 할 수있는 _공간이 라인 청소 알고리즘 완전히 동일하다뿐만 아니라 \/. 에 의해 그래서 첫 번째 단계로 나는 모든 줄 바꿈과 공백을 대체 _하고 모든 \함으로써 /나중에 몇 가지 코드를 단순화 할 수 있습니다.

문자 i와로 현재 내부 / 외부 상태를 추적 하고 o있으며 is를 사용 하여 영역을 계산합니다. 이렇게하려면 o결합 된 선을 앞에 추가 하여 다각형 외부에 있음을 표시합니다. 또한 iio입력의 맨 끝에를 추가하여 새 문자를 생성하는 조회로 사용할 것입니다.

그런 다음 첫 번째 큰 대체는 단순히 i또는 o뒤에 하나 /V_L의 문자를 다음 문자 세트로 바꾸어 전체를 넘치게합니다. 대체 테이블은 다음과 같습니다. 여기서 열은 해당 행의 마지막 문자에 해당하고 행은 다음 문자 ( S공백 및 <>빈 문자열)에 해당합니다. 나는 이미 사용했던 동등성을 보여주기 위해 입력의 모든 문자를 포함시켰다.

     i     o

/    io    i
\    io    i
L    o     ii
V    i     io
_    ii    <>
S    ii    <>

그러면 마지막 문자는 항상 문자가 다각형 내부 또는 외부에 있는지 여부 나타내며 is 의 수 는 다각형에 추가해야하는 영역에 해당합니다. 예를 들어 다음은 마지막 예제 입력에서 처음 네 번의 반복 결과입니다 (이것은 실제로 각 라인을 개별적으로 플러딩 한 이전 버전에서 생성되었지만 원칙은 여전히 ​​동일합니다).

o   /V\
o  /   \___
o  L     _/
o/\/   /V
oL__ _/
o   V

o  /V\
o /   \___
o L     _/
oi\/   /V
oii__ _/
o  V

o /V\
o/   \___
oL     _/
oiio/   /V
oiiii_ _/
o V

o/V\
oi   \___
oii     _/
oiioi   /V
oiiiiii _/
oV

oiV\
oiii  \___
oiiii    _/
oiioiii  /V
oiiiiiiii_/
oio

마지막으로, 나는 o일치하는 모든 것을 제거하여 모든 s 및 줄 바꿈을 제거 [^i]하고 나머지는 다소 지루한 십진수 대 단항 변환입니다.


4

펄, 65 58 바이트

map{map{$b^=2*y,/\\L,,;$a+=y,/\\V,,||$b}split//}<>;print$a
  • / \ 또는 L을 볼 때 $ b를 0과 2 사이에서 전환하십시오.
  • / \ 또는 V를 볼 때 1을 $ a에 더하십시오.
  • 다른 것을 볼 때 $ a를 $ a에 추가하십시오.

좋은 해결책, Perl은 놀라 울 정도로 컴팩트합니다.
orlp

1
더 많은 이득을 위해 입력 처리를 단순화 할 수 있습니다.$/=\1;$-^=2*y,/\\L,,,$a+=y,/\\V,,||$-for<>;print$a
nutki

4

GNU sed, 290 + 1

+ 1은 -rsed에 전달 된 스위치 를 설명하는 것 입니다. 점수에는 주석과 추가 공백이 포함되지 않습니다.

나는 자세히 보지 않았지만 이것이 아마도 Martin의 Retina 답변 과 비슷하다고 생각합니다 .

:                      # label to start processing next (or first) line
s/[0-9]//g             # remove the count of colons from previous lines
H                      # append the current line to the hold space
g                      # copy the hold space to the pattern space
y^_\\^ /^              # Replace '_' with ' ' and replace '\' with '/'
s/(\n| +$)//g          # strip newlines and trailing space
:o                     # start of "outside loop"
s/(^|:) *V/\1:/        # replace leading spaces and "V" with ":"
to                     #   if the above matches, stay outside
s/(^|:) *[|/]/\1:/     # replace leading spaces and "|" or "/" with ":"
ti                     #   if the above matches, go inside
s/(^|:) *L/\1::/       # replace leading spaces and "L" with "::"
:i                     # start of "inside" loop
s/: /:::/              # replace space with "::"
ti                     #   if the above matches, stay inside
s/:V/::/               # replace "V" with ":"
ti                     #   if the above matches, stay inside
s/:[|/]/::/            # replace "|" or "/" with ":"
to                     #    if the above matches, go outside
s/:L/:/                # remove "L"
to                     #    if the above matches, go outside
h                      # copy current string of colons to hold buffer
:b                     # start of colon count loop
s/:{10}/</g            # standard sed "arithmetic" to get string length
s/<([0-9]*)$/<0\1/
s/:{9}/9/
s/:{8}/8/
s/:{7}/7/
s/:{6}/6/
s/:{5}/5/
s/::::/4/
s/:::/3/
s/::/2/
s/:/1/
s/</:/g
tb                     # once arithmetic done, pattern buffer contains string length
N                      # append newline and next line to pattern buffer
b                      # loop back to process next line

개요

  • 각 지역 단위를 콜론으로 교체 :
  • 콜론 수를 센다

노트

  • sed행 지향적이므로 한 번에 여러 행을 처리하려면 약간의 작업이 필요합니다. N명령은 현재 패턴 공간에 다음 행을 개행 문자를 추가하여이 작업을 수행합니다. 에 어려움 N이 입력 스트림 EOF에 도달하면, 그것이 종료 것입니다 sed추가 처리를 할 수있는 옵션없이 완전히. 이 문제를 해결하기 위해 다음 줄을 읽기 직전에 각 줄의 끝에서 현재 콜론 세트를 계산합니다.

산출:

$ echo '   /V\
  /   \__ 
  \     /
/\/   /V
L____/' |sed -rf polyarea.sed
45
$

3

C, 93 96108 바이트

편집 : 주석에서 제안을 고려하고 while을 단일 문 for 루프로 변환하고 "i"변수를 완전히 제거했습니다.

int s,t;main(c,v)char**v;{for(;c=*v[1]++;t+=s+(c>46^!(c%19)^s))s^=c>13^c%9>4;printf("%d",t);}

원본 게시물 :

이것은 마침내 계정을 만들 수있는 재미 있고 간단한 문제인 것 같습니다.

main(c,v)char**v;{int i,t,s;i=t=s=0;while(c=v[1][i++]){s^=c>13^c%9>4;t+=s+(c>46^!(c%19)^s);}printf("%d",t);}

다각형 텍스트는 첫 번째 명령 줄 인수로 전달되어야합니다. 이것은 줄 바꿈 / 공백이 있거나 없어도 작동합니다.

이것은 다각형을 한 번에 한 문자 씩 읽습니다. s는 현재 다각형의 내부 또는 외부를 '/', 'L'또는 '\'로 전환하고 t는 '/', 'V'에서 1 씩 증가합니다. '\'또는 'L', '_', 공백 및 줄 바꿈의 외부에 있으면 / 0이면 2입니다.

모든 종류의 "골프"(또는 C, C ++과 다른 정도)에서 내 손을 시험해 본 것은 처음이므로, 모든 비판에 감사드립니다!


환영합니다! 당신은을 건너 뛸 수 있습니다 i=t=s=0;나는 C가 모두 초기화 생각 int0 어쨌든에들. 또한 while루프를 루프로 바꿀 수 있는지 확인하십시오 for. 종종 몇 바이트를 절약합니다.
Ypnypn

위의 for 루프 아이디어를 사용하여 다음과 같이 할 수 있다고 생각 합니다 ...int i,t,s;for(i=t=s=0;c=v[1][i++];t+=s+(c>46^!(c%19)^s))s^=c>13^c%9>4;.... 4 바이트를 절약해야합니다. 하나의 {, 하나의}와 두 개의;
DaedalusAlpha

또한 위에서 언급했듯이 전역 변수는 자동으로 0으로 설정되므로 내부 대신 int i,t,v;앞에 배치 main하면 i=t=s=0다른 7 바이트를 절약 할 수 있습니다.
DaedalusAlpha

3

POSIX는 나오지도 245 (244)

POSIX sed, 확장 또는 확장 정규 표현식이 없습니다. 입력은 sed의 최대 보류 공간 크기로 제한됩니다. POSIX는 8192 이상을 요구합니다. GNU는 더 많은 것을 관리합니다. 이 버전에서는 도형 앞뒤에 빈 줄이 없다고 가정합니다. 확장에 표시된 추가 10 바이트의 코드는 요구 사항 인 경우 (원래 질문이 지정하지 않음) 수용 할 수 있습니다.

H
/^\([L\\]_*\/\|V\| \)*$/!d
x
s/[_ ]/  /g
s/^/!/
s/$/!/
:g
s/\([^V]\)V/V\1/
tg
y/V/ /
s/L/!  /g
s,[/\\], ! ,g
s/![^!]*!//g
:d
/ /{
s/     /v/g
s/vv/x/g
/[ v]/!s/\b/0/2
s/  /b/g
s/bb/4/
s/b /3/
s/v /6/
s/vb/7/
s/v3/8/
s/v4/9/
y/ bvx/125 /
td
}

확장 및 주석 달기

#!/bin/sed -f

# If leading blank lines may exist, then delete them
# (and add 8 bytes to score)
#/^ *$/d

# Collect input into hold space until we reach the end of the figure
# The end is where all pieces look like \___/ or V
H
/^\([L\\]_*\/\|V\| \)*$/!d

x

# Space and underscore each count as two units
s/[_ ]/  /g

# Add an edge at the beginning and end, so we can delete matching pairs
s/^/!/
s/$/!/
# Move all the V's to the beginning and convert each
# to a single unit of area
:gather
s/\([^V]\)V/V\1/
tgather
y/V/ /

# L is a boundary to left of cell; / and \ in middle
s/L/!  /g
s,[/\\], ! ,g

# Strip out all the bits of outer region
s/![^!]*!//g

# Now, we have a space for each unit of area, and no other characters
# remaining (spaces are convenient because we will use \b to match
# where they end).  To count the spaces, we use roman numerals v and x
# to match five and ten, respectively.  We also match two (and call
# that 'b').  At the end of the loop, tens are turned back into spaces
# again.
:digit
/ /{
s/     /v/g
s/vv/x/g
/[ v]/!s/\b/0/2
s/  /b/g
s/bb/4/
s/b /3/
s/v /6/
s/vb/7/
s/v3/8/
s/v4/9/
y/ bvx/125 /
tdigit
}

# If trailing blank lines may exist, then stop now
# (and add 2 bytes to score)
#q

1

C, 84 바이트

a;i;f(char*s){for(;*s;a+=strchr("\\/V",*s++)?1:i+i)i^=!strchr("\nV_ ",*s);return a;}

우리는 우리가 볼 때마다 양측을 전환 \, /또는 L; 우리는 항상 하나 추가 \\, /또는 V, 그러나 2를 추가 (내 경우) 또는 0 (있는 경우 외부) 공간, 줄 바꿈, 대한 L_.

변수 a와는 i항목에 제로로 가정 - 함수가 한 번 이상 호출 할 경우 그들은 리셋을해야합니다.

언 골프 드 :

int a;                          /* total area */
int i;                          /* which side; 0=outside */
int f(char*s)
{
    while (*s) {
        i ^= !strchr("\nV_ ",*s);
        a += strchr("\\/V",*s++) ? 1 : i+i;
    }
    return a;
}

테스트 프로그램 :

#include <stdio.h>
int main()
{
    char* s;
    s = "  _  \n"
        "  V  \n";
    printf("%s\n%d\n", s, f(s));
    a=i=0;

    s = "/L\n"
        "\\/\n";
    printf("%s\n%d\n", s, f(s));
    a=i=0;


    s = "    /VV\\\n"
        "    L  /\n"
        "     L/";
    printf("%s\n%d\n", s, f(s));
    a=i=0;

    s = "  ____/\\ \n"
        "  \\    /\n"
        "/\\/   /\n"
        "\\____/";
    printf("%s\n%d\n", s, f(s));
    a=i=0;

    s = "   /V\\\n"
        "  /   \\__ \n"
        "  \\     /\n"
        "/\\/   /V\n"
        "L____/";
    printf("%s\n%d\n", s, f(s));
    a=i=0;

    return 0;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.