Xác minh ô chữ


8

Xác nhận một lưới ô chữ đề xuất.

Các mục nhập phải là các chương trình đầy đủ chỉ đơn giản là kiểm tra lưới được đề xuất để xác định xem nó có đáp ứng một tập hợp các điều kiện để làm cho người giải ô chữ hài lòng không.

Đầu vào

Đầu vào sẽ là tên của một tệp đại diện cho lưới ô chữ. Tên tệp đầu vào có thể được truyền dưới dạng đối số, trên đầu vào tiêu chuẩn hoặc bằng các phương tiện thông thường khác ngoài mã hóa cứng.

Định dạng tệp lưới: Dòng đầu tiên bao gồm hai hằng số nguyên được phân tách bằng khoảng trắng M và N. Theo sau dòng đó là các dòng M, mỗi dòng bao gồm N ký tự (cộng với một dòng mới) được chọn từ [#A-Z ]. Các ký tự này được giải thích sao '#' cho chỉ ra một hình vuông bị chặn, ' 'một hình vuông mở trong câu đố không có nội dung đã biết và bất kỳ chữ cái nào có hình vuông mở có chứa chữ cái đó.

Đầu ra

Chương trình sẽ không tạo ra đầu ra trên các lưới hợp lệ và thoát với trạng thái kết thúc bình thường. Nếu lưới được đề xuất không thành công, chương trình sẽ tạo ra một thông báo lỗi chẩn đoán và thoát với trạng thái chấm dứt bất thường (tức là 0 trên unix) nếu điều này được hỗ trợ bởi môi trường thực thi của bạn. Thông báo lỗi phải chỉ ra cả điều kiện nào cho tính hợp lệ bị vi phạm và vị trí của hình vuông vi phạm; bạn có thể tự do lựa chọn phương tiện truyền đạt những sự thật này.

Điều kiện hợp lệ

Các lưới hợp lệ sẽ không có câu trả lời (ngang hoặc xuống) chỉ dài 1 ký tự (tín dụng bổ sung để tạo độ dài tối thiểu làm tham số đầu vào) và sẽ thể hiện tính đối xứng thông thường. Đối xứng thông thường có nghĩa là ô chữ vẫn giữ nguyên sau (ba mô tả tương đương của cùng một hoạt động):

  • phản ánh thông qua trung tâm của chính nó
  • phản xạ cả theo chiều dọc và chiều ngang
  • Xoay 180 độ

Kiểm tra đầu vào và đầu ra dự kiến

Đèo

5   5
#  ##
#    
  #  
    #
##  #

Thất bại trong câu trả lời ngắn:

5   5
## ##
#    
  #  
    #
## ##

Thất bại về đối xứng:

5   5
#  ##
#    
  #  
#   #
##  #

Qua một bên

Đây là lần thứ hai trong một số thử thách liên quan đến ô chữ. Tôi dự định sử dụng một tập hợp các định dạng tệp nhất quán xuyên suốt và để xây dựng một bộ tiện ích liên quan đến ô chữ đáng kính trong quy trình. Ví dụ, một câu đố tiếp theo sẽ yêu cầu in một phiên bản ô chữ ASCII dựa trên đầu vào và đầu ra của câu đố này.

Những thách thức trước trong loạt bài này:


1
Có phải yêu cầu về biểu tượng cũng áp dụng cho các nội dung đã biết của lưới hoặc chỉ cho cấu trúc (# hoặc không #)?
JB

Chỉ để cấu trúc của các hình vuông bị chặn và trong chơi.
dmckee --- ex-moderator mèo con

Ồ, cái này đã có tiền thưởng rồi. Bummer. Tuy nhiên, tôi nghĩ rằng hai câu trả lời là một chút.
Joey

Đối xứng trung tâm và bảo vệ 180 ° là như nhau - không phải sao? Nhưng tôi không thấy sự đối xứng dọc, cũng không ngang. Nhưng bảo vệ 90 °.
người dùng không biết

Câu trả lời:


4

Hồng ngọc - 215 207

t,*d=$<.map &:chop;n,d,e=t.size+1,(d*S=?#).gsub(/[^#]/,W=" "),->c,i{puts [c,i/n+1,i%n+1]*" ";exit 1}
0.upto(d.size-1){|i|d[i]==d[-i-1]||e[?R,i];d[i]==W&&(d[i-1]!=W&&d[i+1]!=W||d[i-n]!=W&&d[i+n]!=W)&&e[?L,i]}

Ung dung:

h, *g = $<.map &:chop
w = h.size+1
g = (g*?#).gsub(/[^#]/," ")
error = ->c,i{ puts [c,i/w+1,i% w+1]*" "; exit 1 }
0.upto(size-1) { |i|
        error[?R, i] if g[i] != g[-i-1]
        error[?L,i] if g[i]==" " && (g[i-1]!=" " && g[i+1]!=" " || g[i-w]!=" " && g[i+w] != " ")
}

.

h, *g = $<.map &:chop

Điều này về cơ bản sẽ loại bỏ char cuối cùng (ngắt dòng) của mỗi dòng đầu vào bằng cách gọi chopphương thức trên chúng và trả về một mảng kết quả.

hlấy phần tử đầu tiên của mảng này và *glấy phần còn lại. Vì vậy, chúng tôi kết thúc với dòng đầu tiên trong hvà các dòng lưới ô chữ trong g.

g = (g*?#).gsub(/[^#]/," ")

g*?#tham gia ( *) mảng gvới "#"( ?#là một ký tự bằng chữ). Điều này giống như g.*("#"), hoặc g.join("#"). Sau đó, mỗi không #được thay thế bởi một không gian.

Đối với kiểm tra đối xứng, chúng ta chỉ cần kiểm tra xem char ở mọi chỉ số có bằng với char ở chỉ mục ngược lại trong chuỗi không:

0.upto(g.size-1) { |i| if g[i] != g[g.size - i - 1]; error() }

Trong Ruby, chúng ta có thể lập chỉ mục các chuỗi từ cuối bằng cách sử dụng các chỉ mục âm (bắt đầu từ -1thay vì 0), do đó g[-i-1]ngược lại với g[i]chuỗi. Điều này tiết kiệm một vài ký tự:

0.upto(g.size-1) { |i| if g[i] != g[-i-1]; error() }

Chúng ta có thể lưu a ;bằng cách sử dụng câu lệnh có điều kiện:

0.upto(g.size-1) { |i| error() if g[i] != g[-i-1] }

Trong phiên bản chơi gôn, chúng ta có thể tiết kiệm thêm một vài ký tự:

0.upto(g.size-1){|i|g[i]==g[-i-1]||error()}

Trong phiên bản trước tôi đã sử dụng đệ quy để lặp qua chuỗi:

(f=->i{g[i]&&f[i+1]&&g[i]!=g[-i-1]&&error()})[0]

Một truy cập ngoài ràng buộc để gtrả về nil, vì vậy một khi g[i]trả về nil, điều này dừng lặp lại.

Định dạng đầu ra:

{ L | R } line-number column-number

L cho lỗi chiều dài và R cho lỗi xoay ( L 1 2có nghĩa là lỗi độ dài ở dòng 1, cột 2)


Bạn có quan tâm để giải thích một chút cho những người trong chúng ta không nói ruby ​​không? Tôi có thể thấy cách bạn đã xóa bất kỳ người không phải người da đen nào khỏi các ô vuông đang chơi và cách kiểm tra độ dài câu trả lời hoạt động (đẹp, BTW), nhưng tôi không hoàn toàn kiểm tra đối xứng.
dmckee --- ex-moderator mèo con

Tôi thấy một vấn đề ở đây về cách xác định chiều rộng của lưới - bằng cách lấy chiều dài của dòng thứ nhất. Điều đó là không chính xác, nó sẽ chỉ hoạt động trên ví dụ trong đó dòng đó là "5 --- 5" (ba khoảng trắng ở giữa). Nếu là "5 5" thì nó không hoạt động!
Nas Banov

Ngoài ra tôi nghĩ rằng có một vấn đề với "bao quanh veritcal", khi đi qua hàng thứ 1 và nhìn xuống một hàng (+ n) và một hàng lên (-n) - hàng sau sẽ nhìn ở hàng cuối cùng và có thể nhầm đón không gian từ đó!
Nas Banov

Vâng, bạn đúng cho chiều rộng của lưới điện; Tôi giả sử rằng trên dòng đầu tiên, số thứ hai luôn được căn chỉnh đến cuối dòng.
Arnaud Le Blanc

1

Thực hiện tham khảo

c99

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void readgrid(FILE *f, int m, int n, char grid[m][n]){
  int i = 0;
  int j = 0;
  int c = 0;
  while ( (c = fgetc(f)) != EOF) {
    if (c == '\n') {
      if (j != n) fprintf(stderr,"Short input line (%d)\n",i);
      i++;
      j=0;
    } else {
      grid[i][j++] = c;
    }
  }
}

int isSymmetric(int m, int n, char g[m][n]){
  for (int i=0; i<m; ++i)
    for (int j=0; j<n; ++j)
      if ( (g[i][j]=='#') != (g[m-i-1][n-j-1]=='#') )
    return j*m+i;
  return -1;
}

int isLongEnough(int m, int n, char g[m][n], int min){
  /* Check the rows */
  for (int i=0; i<m; ++i) {
    int lo=-(min+1); /* last open square */
    int lb=-1;       /* last blocked square */
    for (int j=0; j<n; ++j) {
      if ( g[i][j] == '#' ) {
    /* blocked square */
    if ( (lo == j-1) && (j-lb <= min+1) ) return lo*m+i;
    lb=j;
      } else {
    /* In-play square */
    lo=j;
      }
    }
  }

  /* Check the columns */
  for (int j=0; j<n; ++j) {
    int lo=-(min+1); /* last open square */
    int lb=-1;       /* last blocked square */
    for (int i=0; i<m; ++i) {
      if ( g[i][j] == '#' ) {
    /* blocked square */
    if ( (lo == i-1) && (i-lb <= min+1) ) return lo*m+i;
    lb=i;
      } else {
    /* In-play square */
    lo=i;
      }
    }
  }

  /* Passed */
  return -1;
}

int main(int argc, char** argv){
  const char *infname;
  FILE *inf=NULL;
  FILE *outf=stdout;
  int min=1;

  /* deal with the command line */
  switch (argc) {
  case 3: /* two or more arguments. Take the second to be the minium
         answer length */
    if ( (min=atoi(argv[2]))<1 ) {
      fprintf(stderr,"%s: Minimum length '%s' too short. Exiting.",
          argv[0],argv[2]);
      return 2;
    }
    /* FALLTHROUGH */
  case 2: /* exactly one argument */
    infname = argv[1];
    if (!(inf = fopen(infname,"r"))) {
      fprintf(stderr,"%s: Couldn't open file '%s'. Exiting.",
          argv[0],argv[1]);
      return 1;
    };
    break;
  default:
    printf("%s: Verify crossword grid.\n\t%s <grid file> [<minimum length>]\n",
       argv[0],argv[0]);
    return 0;
  }

  /* Read the grid size from the first line */
  int m=0,n=0,e=-1;
  char lbuf[81];
  fgets(lbuf,81,inf);
  sscanf(lbuf,"%d %d",&m,&n);

  /* Intialize the grid */
  char grid[m][n];
  for(int i=0; i<m; ++i) {
    for(int j=0; j<n; ++j) {
      grid[i][j]='#';
    }
  }

  readgrid(inf,m,n,grid);

  if ((e=isSymmetric(m,n,grid))>=0) {
    fprintf(stderr,"Symmetry violation at %d,%d.\n",e/m+1,e%m+1);
    return 4;
  } else if ((e=isLongEnough(m,n,grid,min))>=0) {
    fprintf(stderr,"Short answer at %d,%d.\n",e/m+1,e%m+1);
    return 8;
  }
  return 0;
}

1

C, 278 ký tự

char*f,g[999],*r=g;i,j,h,w;main(e){
for(fscanf(f=fopen(gets(g),"r"),"%*d%d%*[\n]",&w);fgets(g+h*w,99,f);++h);
for(;j++<h;)for(i=0;i++<w;++r)if(e=*r==35^g[g+w*h-r-1]==35?83:
*r==35||i>1&r[-1]!=35|i<w&r[1]!=35&&j>1&r[-w]!=35|j<h&r[w]!=35?0:76)
exit(printf("%d%c%d\n",j,e,i));exit(0);}

Như bạn có thể mong đợi, các thông báo lỗi đã tự đánh gôn. Chúng có dạng sau:

11L8 - chỉ ra lỗi độ dài ở hàng 11 cột 8

4S10 - chỉ ra lỗi đối xứng ở hàng 4 cột 10


1

APL (115)

{∨/,k←⍵≠⌽⊖⍵:'⍉',(,k×⍳⍴k)~⊂2/0⋄×⍴d←(,⊃,/(g(⍉g←⍳⍴⍵))×{k↑1⌽1⊖0 1 0⍷¯1⌽¯1⊖⍵↑⍨2+k←⍴⍵}¨⍵(⍉⍵))~⊂2/0:'∘',d}d↑↑{'#'≠⍞}¨⍳⊃d←⎕

Nếu lưới không đối xứng, nó xuất ra theo tọa độ, ví dụ như ví dụ mà nó đưa ra

⍉ 2 5 4 1
Nếu lưới có câu trả lời ngắn, nó sẽ xuất ra theo tọa độ, ví dụ như ví dụ mà nó đưa ra
∘ 1 2 5 2

Giải trình:

  • d↑↑{'#'≠⍞}¨⍳⊃d←⎕: đọc dòng đầu tiên dưới dạng danh sách các số và lưu trữ d, sau đó đọc nhiều dòng như số đầu tiên và định hình lại dưới dạng ma trận kích thước d. Hình vuông 'Đóng' được lưu trữ dưới dạng hình vuông 0 và 'mở' là 1.
  • ∨/,k←⍵≠⌽⊖⍵: lưu trữ ở knhững nơi lưới không đối xứng. Nếu có một nơi như vậy ...
  • '⍉',(,k×⍳⍴k)~⊂2/0: xuất a ⍉ theo sau là tọa độ vi phạm
  • : nếu không thì...
  • ~⊂2/0: xóa tọa độ 0 khỏi danh sách sau:
  • ¨⍵(⍉⍵): cho cả lưới và chuyển vị của nó ...
  • ¯1⌽¯1⊖⍵↑⍨2+k←⍴⍵: bao quanh lưới với các số không (tức là các ô vuông kín)
  • 0 1 0⍷: xem nơi nó chứa một hình vuông 'mở' được bao quanh bởi hai hình vuông 'đóng' (= quá ngắn)
  • k↑1⌽1⊖: tháo vòng số 0 thêm một lần nữa
  • ,⊃,/(g(⍉g←⍳⍴⍵))×: nhân với tọa độ và tọa độ chuyển tiếp, và nối với nhau, để tạo thành một danh sách các tọa độ vi phạm (và rất nhiều số không mà chúng tôi loại bỏ).
  • ×⍴d←: lưu trữ tọa độ vi phạm trong dvà nếu có ...
  • :'∘',d: xuất a ∘ theo sau là tọa độ.
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.