แปลงร่างกล่อง


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     ######

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ


เพื่อให้ชัดเจนในตัวอย่างสุดท้ายกล่องที่มี 2 ตัวพิมพ์ใหญ่ Vs จะไม่ถูกต้อง แต่ถ้าเป็นตัวพิมพ์เล็ก v จะกล่องนั้นยังใช้งานได้หรือไม่ นอกจากนี้หากมีหลายกล่องเราจำเป็นต้องเปลี่ยน 1 ถูกต้องหรือไม่
Kade

@ Vioz- ถูกต้องกล่องที่มีตัวพิมพ์ใหญ่ Vs จะไม่ถูกต้องเพราะตัวพิมพ์ใหญ่ที่ไม่ตรงกัน คุณอาจคิดว่าจะไม่มีกล่องที่ถูกต้องสองกล่องขึ้นไป - จะมีช่องที่ถูกต้องหนึ่งช่องเสมอในกล่องรับสัญญาณ
orlp

สไตล์ 3 ต้องการช่องว่างที่มุมหรือไม่?
PurkkaKoodari

@ Pietu1998 ใช่
orlp

1
ใช้เวลาสักครู่ในการคิดออกว่าทำไมฉันถึงได้รับผลลัพธ์ที่แปลกจากรหัส "find the box" ของฉัน ... ตัวอย่างของคุณในสิ่งที่ / ไม่ใช่กล่องท้ายที่สุดมีสองช่องที่ถูกต้องอยู่ในนั้น: o This is. oและo This is no (ด้วย แน่นอนว่าบรรทัดของoด้านบนและด้านล่าง)
เกลน O

คำตอบ:


5

Julia, 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 มันถูกแบ่งออกเป็นสองส่วน - ตัวค้นหากล่องและตัวจำลองกล่อง รหัสกล่องค้นหาฟังก์ชั่นf(t)ใช้ regex เพื่อหาเสื้อและสำหรับกล่องที่เรียบง่าย (ประเภท 2 และ 4) พื้น

regex แรกเป็นวิธีที่ง่ายที่สุดที่ฉันจะหากล่องที่เป็นท็อปส์ซู นี่คือตรรกะของมัน:

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.