변신 상자


18

네 가지 상자 스타일을 정의합니다.

+-----+   ooooooo    ^^^^^   *******
|  1  |   o  2  o   <  3  >  *  4  *
|     |   o     o   <     >  *     *
+-----+   ooooooo    vvvvv   *******

정수와 문자열이 주어진 프로그램이나 함수를 작성하면 문자열에서 위의 상자 중 하나를 찾아 해당 스타일을 사용자가 요청한 상자 스타일로 변경합니다. 예를 들면 다음과 같습니다.

1
This is a test document.
It ********* has
no *purpose* other than
dem*onstrat*ion.
   *********

된다 :

This is a test document.
It +-------+ has
no |purpose| other than
dem|onstrat|ion.
   +-------+

입력에 3x3 이상의 유효한 상자가 정확히 하나 있다고 가정 할 수 있습니다. 코드는 불완전하거나 잘못된 상자를 무시해야합니다.

ooooooooooooooooooooooooooooooooo
o This is not a box. o This is. o
ooooooooooo ooooo ooooooooooooooo

      ^^^^     ######
     <NOPE>    #NOPE#
      vVVv     ######

바이트 단위의 최단 코드가 이깁니다.


마지막 예에서 대문자 V가 2 인 상자가 유효하지 않지만 소문자 v로 작성된 상자가 여전히 유효합니까? 또한 여러 상자가있는 경우 1 만 변경하면됩니까?
Kade

@ Vioz- 맞습니다. 대문자 V가있는 상자는 대소 문자가 일치하지 않기 때문에 유효하지 않습니다. 유효한 상자가 두 개 이상 없을 것이라고 가정 할 수 있습니다 . 입력에 항상 정확히 하나의 유효한 상자 가있을 것 입니다.
orlp

스타일 3에는 모서리에 공백이 필요합니까?
PurkkaKoodari

@ Pietu1998 예.
orlp

1
: 그것은 무엇 당신의 예 / 끝에 상자 아닌 그 안에 두 개의 유효한 상자를 가지고 ... 나는 내 "상자를 찾아"코드에서 이상한 출력을 얻는 이유를 알아 내기 위해 잠시했다 o This is. o,와 o This is no함께 ( o물론 위와 아래의 줄 ).
Glen O

답변:


5

줄리아, 995 818 713 613 바이트

g=(s,n)->(w=map;f=t->(t[z=end];for i=1:z-2,j=eachmatch(r"([*o]|(\+)|(\ ))(?(2)-|(?(3)\^|\1))+\1",t[i],1>0),k=i+2:z N=j.match;N[M=end];p=N[1];J=j.offset;u=w(i->i[[J:J+M-1]∩[1:end]],t);try p%3<1?for l=matchall(r"^([*o])\1+\1",u[k]),q=3:endof(l) w(r->r[[1,q]],u[i:k])⊆["$p$p"]&&return(i,k,J,J+q-1)end:u[k]==replace(N,"^","v")&&w(r->r[[1,M]],u[i+1:k-1])⊆[p<33?"<>":"||"]&&return(i,k,J,M+J-1)end;end);o=ones(5)';T=split(s,'\n');(i,j,k,l)=f(T);u=w(collect,T);(a,u[i][r=k+1:l-1],u[j][r],b,c)=41+[2 4 4 83 83;70o;-9 53 77 19 21;o][n,:];u[i][I]=u[j][I=[k,l]]=a;w(e->(e[k]=b;e[l]=c),u[i+1:j-1]);join(w(join,u),'\n'));

설명이없는 골퍼

function g(s,n)
  # First, we define function f(t), which finds the box
  function f(t)
    # determine the number of rows of text
    z=length(t)
    # Get an iterator of all of the matches to iterate over
    # Regex handles all four box styles
    temp=i->eachmatch(r"([*o]|(\+)|(\ ))(?(2)-|(?(3)\^|\1))+\1",t[i],1>0)
    # Iterate over rows up to third-last one (i)...
    # and over any possible box-tops on each of those rows (j)...
    # and all possible box-bottom rows for each possible box-top (k)
    for i=1:z-2,j=temp(i),k=i+2:z
      # N holds the matched box-top
      N=j.match
      # M stores the length of the match
      M=length(N)
      # p holds the first letter of the match, the corner character.
      p=N[1]
      # J holds the position of the first character of the match in row i
      J=j.offset
      # The intersection here allows truncation of each row to only those
      # parts that lie within the valid range of the box-top
      u=map(i->i[[J:J+M-1]∩[1:end]],t)
      # A try block is being used to skip if a BoundsError is encountered
      # this BoundsError will occur if a box cannot be formed due to
      # a row not being long enough to form both sides or to form bottom
      try
        # This distinguishes between simple boxes (types 2 and 4)
        # from fancy boxes (types 1 and 3), as code differs between them
        if p%3<1 # "then" for simple boxes
          # loop over l either doesn't run (if bottom won't form a match
          # from position 1 within u) or holds the unique match
          # then loop over q looks at all possible bottom-lengths
          for l=matchall(r"^([*o])\1+\1",u[k]),q=3:endof(l)
            # If box sides are found to match top and bottom...
            if map(r->r[[1,q]],u[i:k])⊆["$p$p"]
              # return the coordinates of the box
              return(i,k,J,J+q-1)
            end
          end
        else # "else" for fancy boxes
          # If the bottom matches the top (replace fixes for type 3)...
          if u[k]==replace(N,"^","v")
            # ... and the edges are also there...
            if map(r->r[[1,M]],u[i+1:k-1])⊆[p<33?"<>":"||"]
              # return the coordinates
              return(i,k,J,M+J-1)
            end
          end
        end
      end
    end
  end
  # That defines function f(t), now for the replacement part of the code
  # Input s is a single string with newlines, split into separate strings
  T=split(s,'\n')
  # Find the coordinates of the box using f(T)
  (i,j,k,l)=f(T)
  # u holds the same strings, but stored as char arrays
  u=map(collect,T)
  # Here, we have the appropriate replacement characters for each type
  # with n determining which character from each array is taken
  # Variable names are used here to make it clearer
  corners =  ['+';'o';' ';'*'][n]
  topedge =  ['-';'o';'^';'*'][n]
  bottomedge=['-';'o';'v';'*'][n]
  leftedge = ['|';'o';'<';'*'][n]
  rightedge= ['|';'o';'>';'*'][n]
  # Assign the appropriate characters in the appropriate places
  u[i][[k,l]]=corners
  u[j][[k,l]]=corners
  u[i][k+1:l-1]=topedge
  u[j][k+1:l-1]=bottomedge
  # Iteration is required here because it's an array of arrays
  for e=i+1:j-1
    u[e][k]=leftedge
    u[e][l]=rightedge
  end
  # All that's left to do is recombine to form a single string again
  # we join each internal char array into single-line strings...
  # then join the strings together with a newline delimiter, and return
  return join(map(join,u),'\n')
end

처음 접근 한 방식과 달리이 코드는 "유효한"유형 번호 (1, 2, 3 또는 4)에 대해서만 올바르게 작동합니다. 박스 파인더와 박스 교체기의 두 부분으로 나뉩니다. box-finder 코드 function f(t)은 정규식을 사용하여 상단을 찾고 간단한 박스 (유형 2 및 4)의 경우 하단을 찾습니다.

첫 번째 정규 표현식은 상자 상단을 찾는 가장 간단한 방법입니다. 그 논리는 다음과 같습니다.

r"([*o]|(\+)|(\ ))(?(2)-|(?(3)\^|\1))+\1"
  ([*o]|(\+)|(\ ))                        < This finds the first corner
        ( 2) ( 3)                         . if a + or space, conditionals
  (    1         )                        . kick in, so they're captured
                                          . separately
                  (?(2)-|           )     < If a +, top edge must be
                                          . at least one -
                         (?(3)\^|\1)      < Otherwise, if a space, top
                                          . edge must be at least one ^,
                                          . otherwise, repeat the corner
                                     +    < Allows more than one top-edge
                                          . character
                                      \1  < finish with the same corner
                                          . char found at the start

코드는 다음과 같이 사용됩니다 :

julia> s="""This is a test document.
       It************* has
       no *purpose* other than
       dem*onstrat*ion.
        ************o""";

julia> print(s)
This is a test document.
It************* has
no *purpose* other than
dem*onstrat*ion.
 ************o
julia> print(g(s,1))
This is a test document.
It*+-------+*** has
no |purpose| other than
dem|onstrat|ion.
 **+-------+*o

출력 형식이 지정되지 않았기 때문에 인쇄가 함수에 포함되지 않았습니다. 문자열 만 반환하면 위와 같이 나중에 인쇄 할 수 있습니다.

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