Cấu trúc liên kết ASCII pt 1: Tôi có thể tin tưởng vào bạn không?


28

Tôi có một vấn đề nghiêm trọng. Tôi có một số tệp văn bản nơi tôi giữ những con số rất quan trọng của mình - tất cả những số quan trọng! Và twos, và ba ..

Những con số này rất quan trọng đến nỗi tôi không thể giao phó chúng cho các hệ thống số thập phân hoặc số nhị phân mới lạ này. Tôi giữ mỗi số được mã hóa thành unary, như vậy:

            +--+
            |  |
+---+  +----+  |
|   |  |       |
+---+  +-------+
   ~/two.txt

Đơn giản và đáng tin cậy: hai vòng lặp ASCII cho số 2. Thật không may, những điều này có xu hướng bị rối theo thời gian và bây giờ tôi có một thời gian khó khăn để tìm ra có bao nhiêu vòng lặp trong mỗi tệp. Dưới đây là một số ví dụ mà tôi đã làm bằng tay:

Một:

   +---+
   |   |
+--+   |
|      |
+--+   |
   |   |
   |   |
   |   |
+--+   +--+
|         |
+---------+

Số ba:

+---------+
| +-----+ |
| | +-+ | |
| | | | | |
| | +-+ | |
| +-----+ |
+---------+

Bốn:

  +--------------+
  |  +--+  +--+  |
  |  |  |  |  |  |
+-|-----|-----|----+
| |  |  |  |  |  | |
| +--+  +--+  +--+ |
+------------------+

              +------------+
              |            |
        +-----+  +-----+   |
        |        |     |   |
  +-----|-----------+  |   |
  |     |  +--+  |  |  |   |
  +-+   +--|--|--+  +---------+
    |      |  +-+      |   |  |
    +------+    |      |   |  |
                +-------+  |  |
                       ||  |  |
                       |+-----+
                       |   |
                       +---+

Số năm:

+--------+  +--------+  +--------+
|        |  |        |  |        |
|     +--|-----+  +--|-----+     |
|     |  |  |  |  |  |  |  |     |
+-----|--+  +-----|--+  +--------+
      |        |  |        |
      +--------+  +--------+

Bạn có thể giúp tôi đếm vòng lặp của tôi?

Đây là các quy tắc:

  • Vì tôi lưu trữ mọi thứ trong unary được mã hóa ASCII, hiệu quả không gian rất quan trọng đối với tôi. Do đó, đây là mã golf. Chương trình nhỏ nhất tính bằng byte thắng.
  • Vòng lặp được vẽ với các ký tự +, -, |. Mọi góc trong vòng lặp được vẽ rõ ràng: chính xác một trong các ký tự bên trên và bên dưới dấu + sẽ là | và chính xác một ở bên phải hoặc bên trái sẽ là -. Hai dấu + không bao giờ liền kề.
  • Các sợi có thể vượt qua và dưới nhau. Khi các sợi chéo nhau, bạn sẽ có thể thấy dải "dưới" ngay lập tức ở cả hai phía của dải "trên".
  • Chương trình của bạn nên lấy một chuỗi đại diện của vòng lặp (từ stdin hoặc dưới dạng tham số hàm) và tạo ra một số (để xuất chuẩn hoặc làm giá trị trả về).
  • Độ dài dòng có thể không đồng nhất trong bản vẽ vòng lặp và có thể có các khoảng trắng ở mỗi dòng.
  • Bạn có thể cho rằng có ít nhất một vòng lặp trong đầu vào.

Tôi đang trông cậy vào bạn!


Một trong những mặt của 'dưới sợi' có thể là một +?
frageum

@feersum: Không, hai cạnh được gắn vào + sẽ luôn hiển thị.
Matt Noonan

1
@Martin: Tôi không sợ. Không gian lưu trữ của tôi thực sự ở mức cao, vì vậy tôi không thể dành tất cả những không gian thừa đó.
Matt Noonan

Tôi nghĩ bạn nên thêm cái này ( pastebin ) làm trường hợp thử trừ khi tôi thiếu thứ gì đó và nó không phải là đầu vào hợp lệ. Có 6 vòng; Tôi chỉ thử nghiệm trực tuyến với giải pháp SnakeEx và nó cho ra 12.
blutorange

1
Có lẽ bạn rõ ràng nên cấm hoặc cho phép các vòng lặp tự giao nhau (ví dụ: pastebin.com/5RLZuULG ) Hiện tại, chúng được phát hiện bởi giải pháp ruby, nhưng không phải bởi giải pháp SnakeEx.
blutorange

Câu trả lời:


19

SnakeEx - 98 byte với Javascript, 44 không có

Đây có vẻ là một vấn đề tốt để thử ngôn ngữ của tôi từ Thử thách nửa đêm về:

m:({e<>PE}\-[|\-]*<T>\+|[|\-]*<T>)+`\+
e:\+

Nơi tốt nhất để thử điều này là thông dịch viên trực tuyến của tôi .

SnakeEx khớp các mẫu trong văn bản bằng cách sử dụng "rắn" di chuyển xung quanh biểu thức khớp văn bản. Mã này đọc giống như một biểu thức chính quy, ngoại trừ:

  • Các <T>hướng dẫn. Đó là một lệnh chỉ đường phân nhánh con rắn trái và phải từ hướng hiện tại của nó.
  • {e<>PE}giống như một cuộc gọi chương trình con. Nó sinh ra một con rắn với định nghĩa edi chuyển về phía trước ( <>) và với các tham số P(cõng - rắn sinh sản theo con rắn mới) và E(độc quyền - không khớp với bất cứ thứ gì đã được khớp). Kiểm tra độc quyền này là điều duy nhất ngăn chặn con rắn lặp đi lặp lại vô tận.
  • Tiền tố `ở cuối chỉ ra rằng những gì tiếp theo chỉ nên được khớp nếu nó đã được khớp, mà chúng ta có thể sử dụng để buộc vòng lặp đóng lại.

Vì SnakeEx giống như regex và về mặt kỹ thuật không tạo ra kết quả như mong muốn, tôi đoán rằng chúng ta cần phải bọc nó trong một số Javascript gọi trình thông dịch:

function e(s){return snakeEx.run('m:({e<>PE}\\-[|\\-]*<T>\\+|[|\\-]*<T>)+`\\+\ne:\\+',s,1).length}

Chỉnh sửa : đã sửa nó để hoạt động với các trường hợp thử nghiệm bổ sung của blutorange


1
+1 Tôi thực sự thích điều này, có lẽ vì tôi có thể thử trực tuyến và làm nổi bật các vòng lặp. Nhưng bạn có thể muốn kiểm tra hai trường hợp thử nghiệm này: 1 , 2
blutorange

@blutorange Bắt tốt. Tôi đã thêm một sửa chữa hơi hack cho các vòng lặp tự vượt qua. Tuy nhiên, tôi sẽ phải suy nghĩ về trường hợp thử nghiệm thêm một chút nữa.
BMac

Đó là cách dễ dàng để sửa chữa, chỉ cần thay thế [^ ]bằng [|\-];)
blutorange

Hah, tôi đã mất một thời gian dài để tìm hiểu tại sao lại như vậy. Cuộc gọi tốt
BMac

Điều này thật tuyệt!
Ingo Bürk

10

C # - 338 388 433 byte

Đã lưu một loạt byte bằng cách thay đổi thành mảng 1 chiều.

using C=System.Console;using System.Linq;class P{static void Main(){var D=C.In.ReadToEnd().Split('\n');int z,w=D.Max(m=>m.Length)+1,d,c=0;var E=D.SelectMany(l=>l.PadRight(w)).ToList();for(z=E.Count;z-->1;)if(E[z-1]==43)for(d=1,c++;E[z+=d%2<1?w*d-w:d-2]>32;)if(E[z]<44){E[z]=' ';d=d%2>0?z<w||E[z-w]<99?2:0:E[z+1]!=45?1:3;}C.WriteLine(c);}}

Đầu tiên, nó đọc trong đầu vào, và làm cho nó đẹp và hình chữ nhật, với đường viền "" để chúng ta không phải thực hiện bất kỳ giới hạn nào khi kiểm tra theo chiều ngang (rẻ hơn để thực hiện kiểm tra theo chiều dọc so với đặt vào dòng phụ) . Sau đó, nó nhìn lại qua hình chữ nhật, vì vậy nó luôn chạm vào một góc dưới cùng bên phải. Khi nó chạm vào một trong những thứ này, nó sẽ tự hướng lên, theo bất kỳ + s nào nó gặp và xóa chúng khi nó đi (với một khoảng trắng). Nó dừng lại sau khi nó gặp một không gian. Đã thử nghiệm trên năm ví dụ cho trước.

using C=System.Console;
using System.Linq;

class P
{
    static void Main()
    {
        // read in
        var D=C.In.ReadToEnd().Split('\n');

        int z, // z is position in E
        w=D.Max(m=>m.Length)+1, // w is width
        d, // d is direction of travel (1 == horizontal?, 2 == down/right?)
        c=0; // c is loop count

        // make all the lines the same length
        var E=D.SelectMany(l=>l.PadRight(w)).ToList(); // say no to horizontal bounds checking

        // consume +s
        for(z=E.Count;z-->1;)
            if(E[z-1]==43) // right-most lower-most +
                for(d=1,c++; // go left, increment counter
                    E[z+=d%2<1?w*d-w:d-2]>32 // move z, then check we havn't hit a space (when we do, z is basiclly z - 1)
                    ;)
                    if(E[z]<44) // +
                    {
                        E[z]=' '; // toodles

                        d=
                            d%2>0? // currently horizontal, must go vertical
                                z<w||E[z-w]<99?2 // can't go up, must go down
                                :0 // can go up, go up
                            : // currently vertical, must go horizontal
                                E[z+1]!=45?1 // can't go right, must go left
                                :3 // can go right, go right
                            ;
                    }

        // output result
        C.WriteLine(c);
    }
}

Ồ Thật ấn tượng: o
Metoniem

6

Trượt , 51 41 + 2 = 43 byte

$a(`+`-[^ +]*`+(<|>)`|[^ +]*`+#(<|>))+?$A

(Hiện được cập nhật để hoạt động với trường hợp thử nghiệm của @ blutorange với chi phí lớn)

Vì @BMac đã sử dụng SnakeEx cho thử thách này, tôi nghĩ rằng tôi đã thử và sử dụng trình gửi ngôn ngữ phù hợp với mô hình 2D của mình , Trượt. Nhưng vì Trượt không có các tính năng cần thiết để giải quyết vấn đề này, tôi đã thêm chúng trong vài ngày qua. Nói cách khác, bài nộp này không đủ điều kiện để giành chiến thắng .

Chạy với ncờ cho số lượng trận đấu, ví dụ:

py -3 slip.py regex.txt input.txt n

Hãy thử trực tuyến .


Giải trình

Do rất nhiều tính năng mới trong bài đăng này, đây là một cơ hội tốt để giới thiệu chúng.

$a                Set custom anchor at current position
(
  `+`-            Match '+-'
  [^ +]*          Match any number of '|' or '-'
  `+              Match a '+'
  (<|>)           Either turn left or turn right
  `|              Match a '|'
  [^ +]*          Match any number of '|' or '-'
  `+              Match a '+'
  #               Prevent next match from moving the match pointer (doubling up on '+')
  (<|>)           Either turn left or turn right
)
+?                Do the above at least once, matching lazily
$A                Make sure we're back where we started

Trượt cố gắng khớp bắt đầu từ mọi vị trí và chỉ trả về các kết quả khớp duy nhất. Lưu ý rằng chúng tôi sử dụng [^ +]- trong khi sử dụng [-|]về mặt lý thuyết sẽ lưu hai byte, không được giải mã -ở đầu / cuối của các lớp ký tự chưa được triển khai trong Trượt.


1
@blutorange threecũng có +s không phải là một -, một |và 2 khoảng trắng, vì vậy tôi cho rằng đó không phải là một lỗi
Sp3000

5

Ruby 295

F=->i{l=i.lines
g={}
l.size.times{|y|i.size.times{|x|l[y][x]==?+&&g[[y,x]]=[[y,x]]}}
c=->a,b{w=g[b]+g[a];w.map{|x|g[x]=w}}
k=g.keys
k.product(k).map{|n,o|
r,p=n
s,q=o
((r==s&&p<q&&l[r][p...q]=~/^\+-[|-]*$/)||(p==q&&r<s&&l[r...s].map{|l|l[p]||c}.join=~/^\+\|[|-]*$/))&&c[n,o]}
g.values.uniq.size}

Dùng thử trực tuyến: http://ideone.com/kIKELi ( Tôi đã thêm một #to_acuộc gọi trên dòng đầu tiên, vì ideone.com sử dụng Ruby 1.9.3, không hỗ trợ #sizecho Enumerables. Trong Ruby 2.1.5+ mã chạy OK . )

Cách tiếp cận như sau:

  • lập danh sách tất cả các +dấu hiệu trong đầu vào và xem xét mỗi dấu hiệu có hình dạng riêng biệt
  • tìm các đường ngang và dọc liên kết hai +dấu hiệu và kết hợp các hình dạng của chúng thành một
  • cuối cùng, số lượng hình dạng riêng biệt phù hợp với kết quả

Đây là một phiên bản dễ đọc hơn:

def ascii_topology_count(input)
  lines = input.lines
  max_length = lines.map(&:size).max

  # hash in which the keys are corners ("+"s), represented by their [y, x] coords
  # and the values are arrays of corners, representing all corners in that group
  corner_groups = {}

  lines.size.times { |y|
    max_length.times { |x|
      if lines[y][x] == ?+
        corner_groups[[y, x]] = [[y, x]]
      end
    }
  }

  # function that combines the groups of two different corners
  # into only one group
  combine_groups =-> c1, c2 {
    g1 = corner_groups[c1]
    g2 = corner_groups[c2]

    g2 += g1
    corner_groups[c1] = g2
    g2.map{|x| corner_groups[x] = g2}
  }

  corner_groups.keys.product(corner_groups.keys).map{|c1, c2|
    y1,x1=c1
    y2,x2=c2
    if y1 == y2 && x1 < x2
      # test horizontal edge
      t = lines[y1][x1...x2]
      if t =~ /^\+-[|-]*$/
        # p "#{c1}, #{c2}, [H] #{t}"
        combine_groups[c1, c2]

      end
    end

    if x1 == x2 && y1 < y2
      # test vertical edge
      t=lines[y1...y2].map{|l|l[x1]||' '}.join

      if t =~ /^\+\|[|-]*$/
        # p "#{c1}, #{c2}, [V] #{t}"
        combine_groups[c1, c2]
      end
    end
  }

  corner_groups.values.uniq.count
end

5

JavaScript (ES6) 190 197 202 215 235 289 570

Chỉnh sửa mảng một chiều thay vì 2 chiều, kích thước hàng tối đa 999 ký tự (nhưng có thể nhiều hơn mà không mất phí, ví dụ: 1e5 thay vì 999)

Chỉnh sửa Đã thêm đoạn mã hoạt hình, xem bên dưới

F=s=>[...s.replace(/.+/g,r=>r+Array(e-r.length),e=999)]
  .map((c,x,z,d=1,f='-',g='|')=>{
    if(c=='+')
      for(++n;z[x+=d]!='+'||([f,g,e,d]=[g,f,d,z[x-e]==g?-e:z[x+e]==g&&e],d);)
        z[x]=z[x]==g&&g
  },n=0)|n

Ungolfed thử đầu tiên

f=s=>
{
  cnt=0
  s = (1+s+1).split(/[1\n]/)

  for(;x=-1, y=s.findIndex(r=>~(x=r.indexOf('+-'))), x>=0;++cnt)
  {
    //console.log(y+' '+x+' '+s.join('\n'))
    dx = 1
    for(;dx;)
    {
      a=s[y-1],b=s[y+1],
      r=[...s[y]]
      for(r[x]=' ';(c=r[x+=dx])!='+';)
      {
        if (c=='-')
          if((a[x]||b[x])=='|')r[x]='|';
          else r[x]=' ';
      }  

      if(a[x]=='|')dy=-1;
      else if(b[x]=='|')dy=1;
      else dy=0
      r[x]=' '
      s[y]=r.join('')
      if (dy) {
        for(;y+=dy,r=[...s[y]],(c=r[x])!='+'&c!=' ';)
        {
          if (c=='|') 
            if((r[x-1]||r[x+1])=='-')r[x]='-';
            else r[x]=' ';
          s[y]=r.join('')
        }  
        if(r[x-1]=='-')dx=-1;
        else if(r[x+1]=='-')dx=1;
        else dx=0;
      }
    }  
  }
  return cnt
}

Đoạn phim hoạt hình

Kiểm tra trong bảng điều khiển Firefox / FireBug

F('\
  +--------------+\n\
  |  +--+  +--+  |\n\
  |  |  |  |  |  |\n\
+-|-----|-----|----+\n\
| |  |  |  |  |  | |\n\
| +--+  +--+  +--+ |\n\
+------------------+\n\
\n\
              +------------+\n\
              |            |\n\
        +-----+  +-----+   |\n\
        |        |     |   |\n\
  +-----|-----------+  |   |\n\
  |     |  +--+  |  |  |   |\n\
  +-+   +--|--|--+  +---------+\n\
    |      |  +-+      |   |  |\n\
    +------+    |      |   |  |\n\
                +-------+  |  |\n\
                       ||  |  |\n\
                       |+-----+\n\
                       |   |\n\
                       +---+')

4

F('\
+--------+  +--------+  +--------+\n\
|        |  |        |  |        |\n\
|     +--|-----+  +--|-----+     |\n\
|     |  |  |  |  |  |  |  |     |\n\
+-----|--+  +-----|--+  +--------+\n\
      |        |  |        |\n\
      +--------+  +--------+')

5


Chắc chắn bạn sẽ tiết kiệm được một số byte bằng cách xếp một phiên bản golf? Bạn cũng có thể chỉ cần tạo một hàm ẩn danh (tôi nghĩ đó là trong các quy tắc của codegolf)
theonlygusti

@theonlygusti phiên bản chơi gôn được tính là một dòng (không có dòng mới và khoảng cách thụt lề nào được tính). Với một hàm ẩn danh tôi lưu 2 byte, tiết kiệm không đáng kể ...
edc65

4

Hồng ngọc, 178 187 199 212

Phiên bản ruby ​​tốt hơn, tạo chức năng F. Bây giờ với các cảnh báo phiên dịch viên ngon hơn liên tục.

b=->n{Q[I]=?~
d=Q[I+n]==(n>1??|:?-)?1:-1
loop{I+=d*n
b[n>1?1:N]if Q[I]==?+
Q[I]<?~?4:break}}
F=->s{N=s.size;Q=s+?\n
Q.gsub!(/^.*$/){$&.ljust N-1}
(0..N).find{!(I=Q=~/\+/)||b[1]}}

Kiểm tra trực tuyến: ideone

Về cơ bản, chức năng bbắt đầu tại bất kỳ +, đệ quy đi qua vòng lặp, thiết lập tất cả +thành u. Do đó, một vòng lặp được loại bỏ mỗi lần bđược gọi. Hàm Fchỉ thử tần suất chúng ta cần gọi bcho đến khi không còn vòng lặp nào.


2

Con trăn 2 - 390

Có một chuỗi với các dòng mới từ stdin. Đó là một phương pháp khá đơn giản, đánh golf một chút công bằng, nhưng tôi chắc chắn không nhiều như nó có thể xem xét nó dài bao nhiêu.

s=raw_input().split('\n');L=len
def R(x,y):
 b=p,q=x,y;u=v=f=0
 while b!=(p,q)or not f:
    p+=u;q+=v;f=u+v;c=s[q][p]
    if'+'==c:u,v=[(i,j)for i,j in{(-1,0),(1,0),(0,-1),(0,1)}-{(-u,-v)}if 0<=q+j<L(s)and 0<=p+i<L(s[q+j])and s[q+j][p+i]in['-+','|+'][j]][0];s[q]=s[q][:p]+' '+s[q][p+1:]
    if c+s[q+v][p+u]in'-|-':p+=u;q+=v
print L([R(x,y)for y in range(L(s))for x in range(L(s[y]))if'+'==s[y][x]])

1

Python 2 - 346 byte

Được thực hiện như một hàm clấy dữ liệu tệp làm đầu vào và trả về số vòng lặp.

Đầu tiên, hàm phân tách dữ liệu thành ánh xạ các vị trí phần tử vòng lặp thành loại phần tử tại vị trí đó (ví dụ {(0,0): '+'}). Sau đó, nó sử dụng hai hàm nội bộ đệ quy lẫn nhau. Cái đầu tiên loại bỏ một đoạn vòng khỏi ánh xạ và quyết định vị trí nào cần kiểm tra cho đoạn tiếp theo. Thứ hai kiểm tra loại phần tử vòng lặp nào trong các vị trí đã chọn và nếu nó tương thích với những gì được mong đợi, hãy gọi phần đầu tiên để loại bỏ phần mới tìm thấy.

e=enumerate
def c(d):
 D={(i,j):k for i,l in e(d.split('\n'))for j,k in e(l)if k in'+-|'}
 def f(r,c,R,C,t):
  if D.get((r,c),t)!=t:g(r,c)
  elif D.get((R,C),t)!=t:g(R,C)
 def g(r,c):
  t=D.pop((r,c))
  if t!='|':f(r,c-1,r,c-2,'|');f(r,c+1,r,c+2,'|')
  if t!='-':f(r-1,c,r-2,c,'-');f(r+1,c,r+2,c,'-')
 n=0
 while D:g(*D.keys()[0]);n+=1
 return n
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.