Đánh số ô chữ


9

Sản xuất một chương trình để đánh số chính xác một lưới ô chữ.

Đầ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: Một tệp văn bản. 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 MN. Theo sau dòng đó là M mỗi dòng bao gồm các Nký 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

Đầu ra sẽ là một tệp đánh số và có thể được gửi đến đầu ra tiêu chuẩn, đến một tệp có tên được lấy từ tên tệp đầu vào, đến một tệp do người dùng chỉ định hoặc đến một số đích thông thường khác.

Định dạng tệp đánh số Một tệp văn bản. Các dòng bắt đầu bằng '#' được bỏ qua và có thể được sử dụng để nhận xét. Tất cả các dòng khác chứa một tab tách triplet i, m, nnơi iđại diện cho một số được in trên lưới và mnđại diện cho hàng và cột của quảng trường, nơi nó sẽ được in. Số lượng của cả hàng và cột bắt đầu từ 1.

Sơ đồ đánh số

Một lưới được đánh số chính xác có các thuộc tính sau:

  1. Việc đánh số bắt đầu từ 1.
  2. Không có cột hoặc khoảng của các ô vuông mở không bị đánh số. (Bạn có thể cho rằng sẽ không có câu trả lời nào cho nhân vật tồn tại trong vấn đề này.)
  3. Các số sẽ được bắt gặp theo thứ tự đếm bằng cách quét từ hàng trên xuống dưới lấy từng hàng từ trái sang phải. (Vì vậy, mỗi nhịp ngang được đánh số ở ô vuông ngoài cùng bên trái của nó và mỗi cột được đánh số ở ô vuông trên cùng của nó.)

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

Đầu vào:

5   5
#  ##
#    
  #  
    #
##  #

Đầu ra (bỏ qua các dòng bình luận):

1       1       2
2       1       3
3       2       2
4       2       4
5       2       5
6       3       1
7       3       4
8       4       1
9       4       3
10      5       3

Qua một bên

Đây là lần đầu tiên hy vọng sẽ có một vài 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.


Khoảng cách một ký tự không được đánh số, phải không?
Keith Randall

@Kieth: Tôi thích quy tắc không có các nhịp như vậy, nhưng tôi chưa chỉ định nó ở đây vì việc xác thực lưới được lên kế hoạch là một vấn đề khác. Tôi cho rằng bạn sử dụng là một vấn đề của hương vị.
dmckee --- ex-moderator mèo con

tập tin đầu vào sẽ ở txt?
www0z0k

@ www0z0k: Có. Sự đam mê unix trong tôi luôn mặc định để nhắn tin.
dmckee --- ex-moderator mèo con

1
@ www0z0k: Ngắt dòng là bất cứ điều gì có nguồn gốc trên nền tảng của bạn. Đó là số thập phân ASCII 20 của tôi và được thể hiện như '\n'trong c trên tất cả các nền tảng. Giả định là tệp đầu vào được sản xuất trên cùng một hệ thống sẽ xử lý nó, vì vậy vấn đề này cần được minh bạch. Một lưu ý chung về môn đánh gôn: nếu bạn đang làm việc bằng một ngôn ngữ lạ hoặc trên một nền tảng lạ, hãy ghi chú lại bất cứ điều gì có thể khiến người đọc ngạc nhiên. Mọi người sẽ thực hiện trợ cấp cho việc đó trong việc đánh giá trình của bạn.
dmckee --- ex-moderator mèo con

Câu trả lời:


4

Ruby - 210 139 ký tự

o=0
(n=(/#/=~d=$<.read.gsub("
",S='#'))+1).upto(d.size-1){|i|d[i]!=S&&(i<n*2||d[i-1]==S||d[i-n]==S)&&print("%d\t%d\t%d
"%[o+=1,i/n,i%n+1])}

Đã thử nghiệm với ruby ​​1.9.


Tôi làm theo hầu hết điều đó. Không chắc chắn s.shift.split.map làm gì, nhưng điều đó phải tạo thành mảng từ đầu vào.
dmckee --- ex-moderator mèo con

BTW-- Làm thế nào tôi nên gọi nó tại một dòng lệnh unix. Tôi đã thử cho nó một shebang phù hợp với hệ thống của tôi, nhưng nó phàn nàn ./temp.ruby:4: wrong argument type Symbol (expected Proc) (TypeError).
dmckee --- ex-moderator mèo con

s.shift lấy dòng đầu tiên, trả về tách ["m", "n"], trả về bản đồ [m, n]. Tôi đang chạy nó với ruby1.9 như thế này : ruby1.9 test.rb.
Arnaud Le Blanc

3

PHP - 175 ký tự

<?for($i=$n=strpos($d=strtr(`cat $argv[1]`,"\n",$_="#"),$_)+$o=1;isset($d[$i]);++$i)$d[$i]!=$_&($i<$n*2|$d[$i-1]==$_|$d[$i-$n]==$_)&&printf("%d\t%d\t%d\n",$o++,$i/$n,$i%$n+1);

Tôi tự hỏi khi ai đó sẽ làm điều đó trong một mảng 1d.
dmckee --- ex-moderator mèo con

3

Con trăn, 194 177 176 172 ký tự

f=open(raw_input())
V,H=map(int,next(f).split())
p=W=H+2
h='#'
t=W*h+h
n=1
for c in h.join(f):
 t=t[1:]+c;p+=1
 if'# 'in(t[-2:],t[::W]):print"%d\t%d\t%d"%(n,p/W,p%W);n+=1

Bạn nên có thể sử dụng h.join(f)Tôi nghĩ
gnibbler

next(f)thay vì f.readline()nếu bạn> = 2.6 người khácf.next()
gnibbler

Con trăn của tôi chưa bao giờ rất tốt, nhưng có vẻ như bạn đang sử dụng thêm '#' để xử lý các trường hợp cạnh, phải không? Tuy nhiên, tôi nhận được một số đầu ra kỳ lạ trên dữ liệu thử nghiệm, bao gồm cả số phụ.
dmckee --- ex-moderator mèo con

@dmckee, vâng, tôi đang sử dụng thêm #s để đánh dấu cạnh. Bạn có thể gửi một trường hợp thử nghiệm mà bạn nghĩ rằng nó thất bại?
Keith Randall

@Kieth: Đối với trường hợp thử nghiệm ở trên, tôi nhận được 12 dòng đầu ra (và 10 dòng đầu tiên không khớp). Sử dụng python2.6 hoặc 2.7 trên máy Mac của tôi. Chạy với nó echo test_input_file_name | python golf.py, điều đó có sai không?
dmckee --- ex-moderator mèo con

2

C ++ 270 264 260 256 253 char

#include<string>
#include<iostream>
#define X cin.getline(&l[1],C+2)
using namespace std;int main(){int r=0,c,R,C,a=0;cin>>R>>C;string l(C+2,35),o(l);X;for(;++r<=R;o=l)for(X,c=0;++c<=C;)if(l[c]!=35&&(l[c-1]==35||o[c]==35))printf("%d %d %d\n",++a,r,c);}

Để sử dụng:

g++ cross.cpp -o cross
cat puzzle |  cross

Định dạng độc đáo:

#include<string>
#include<iostream>
// using this #define saved 1 char
#define X cin.getline(&l[1],C+2)

using namespace std;

int main()
{
    int r=0,c,R,C,a=0;
    cin>>R>>C;
    string l(C+2,35),o(l);
    X;

    for(;++r<=R;o=l)
        for(X,c=0;++c<=C;)
            if(l[c]!=35&&(l[c-1]==35||o[c]==35))
                printf("%d %d %d\n",++a,r,c);
}

Tôi đã thử đọc toàn bộ ô chữ trong một lần và sử dụng một vòng lặp.
Nhưng chi phí bù đắp cho nhân vật '\ n lớn hơn bất kỳ lợi ích nào:

#include <iostream>
#include <string>
#define M cin.getline(&l[C+1],R*C
using namespace std;

int main()
{
    int R,C,a=0,x=0;
    cin>>R>>C;
    string l(++R*++C,35);
    M);M,0);

    for(;++x<R*C;)
        if ((l[x]+=l[x]==10?25:0)!=35&&(l[x-1]==35||l[x-C]==35))
            printf("%d %d %d\n",++a,x/C,x%C);
}

Nén: 260 ký tự

#include<iostream>
#include<string>
#define M cin.getline(&l[C+1],R*C
using namespace std;int main(){int R,C,a=0,x=0;cin>>R>>C;string l(++R*++C,35);M);M,0);for(;++x<R*C;)if((l[x]+=l[x]==10?25:0)!=35&&(l[x-1]==35||l[x-C]==35))printf("%d %d %d\n",++a,x/C,x%C);}

Đã cho tôi một vài cố gắng để gọi nó đúng. Nhếch nhác.
dmckee --- ex-moderator mèo con

2

C, 184 189 ký tự

char*f,g[999],*r=g;i,j,n;main(w){
for(fscanf(f=fopen(gets(g),"r"),"%*d%d%*[\n]",&w);fgets(r,99,f);++j)
for(i=0;i++<w;++r)
*r==35||j&&i>1&&r[-w]-35&&r[-1]-35||printf("%d\t%d\t%d\n",++n,j+1,i);}

Không có nhiều để nói ở đây; logic là khá cơ bản. Chương trình lấy tên tệp trên đầu vào tiêu chuẩn khi chạy. (Thật khó chịu khi chương trình phải làm việc với tên tệp và không thể chỉ đọc nội dung tệp trực tiếp từ đầu vào tiêu chuẩn. Nhưng người trả tiền cho piper gọi điều chỉnh!)

Mẫu lạ fscanf()là nỗ lực của tôi để quét toàn bộ dòng đầu tiên, bao gồm dòng mới nhưng không bao gồm khoảng trắng hàng đầu trên dòng sau. Có một lý do tại sao không ai sử dụng scanf().


Tôi nghĩ bạn đảo ngược số hàng và số cột. Nếu tôi hiểu chính xác, số đầu tiên là số hàng, nhưng bạn coi nó là số cột.
ugoren

Từ những gì tôi có thể nói, đầu ra của chương trình của tôi khớp với ví dụ được đưa ra trong mô tả và đầu ra từ việc thực hiện tham chiếu. Bạn có thể cho tôi một ví dụ cụ thể về những gì bạn đang đề cập đến?
hộp bánh mì

Bất kỳ ví dụ nào mà số hàng và số cột không bằng nhau.
ugoren

Được rồi, nhưng hãy làm cụ thể. Khi được cung cấp lưới ví dụ được cung cấp trong mô tả, chương trình của tôi xuất ra (1,2) cho số 1. Bạn có nói rằng chương trình của tôi phải xuất ra (2.1) không?
hộp bánh mì

Tôi đang nói về đầu vào, không phải đầu ra. Khi dòng đầu tiên là 5 5, bạn lấy 5 đầu tiên làm chiều rộng, khi đó bạn nên lấy dòng thứ hai (tất nhiên, điều này không quan trọng, trong ví dụ này).
ugoren

1

Thực hiện tham khảo:

c99 ungolfed và khá hơn 2000 ký tự bao gồm frobs gỡ lỗi khác nhau vẫn ở đó.

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

void printgrid(int m, int n, char grid[m][n]){
  fprintf(stderr,"===\n");
  for (int i=0; i<m; ++i){
    for (int j=0; j<n; ++j){
      switch (grid[i][j]) {
      case '\t': fputc('t',stderr); break;
      case '\0': fputc('0',stderr); break;
      case '\n': fputc('n',stderr); break;
      default: fputc(grid[i][j],stderr); break;
      }
    }
    fputc('\n',stderr);
  }
  fprintf(stderr,"===\n");
}

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 main(int argc, char** argv){
  const char *infname;
  FILE *inf=NULL;
  FILE *outf=stdout;

  /* deal with the command line */
  switch (argc) {
  case 3: /* two or more arguments. Take the second to be the output
         filename */
    if (!(outf = fopen(argv[2],"w"))) {
      fprintf(stderr,"%s: Couldn't open file '%s'. 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: Number a crossword grid.\n\t%s <grid file> [<output file>]\n",
       argv[0],argv[0]);
    return 0;
  }

  /* Read the grid size from the first line */
  int m=0,n=0;
  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]='#';
    }
  }

/*    printgrid(m,n,grid); */
  readgrid(inf,m,n,grid);
/*    printgrid(m,n,grid);  */

  /* loop through the grid  produce numbering output */
  fprintf(outf,"# Numbering for '%s'\n",infname);
  int num=1;
  for (int i=0; i<m; ++i){
    for (int j=0; j<n; ++j){
/*       fprintf(stderr,"\t\t\t (%d,%d): '%c' ['%c','%c']\n",i,j, */
/*        grid[i][j],grid[i-1][j],grid[i][j-1]); */
      if ( grid[i][j] != '#' &&
       ( (i == 0) || (j == 0) ||
         (grid[i-1][j] == '#') ||
         (grid[i][j-1] == '#') )
         ){
    fprintf(outf,"%d\t%d\t%d\n",num++,i+1,j+1);
      }
    }
  }
  fclose(outf);
  return 0;
}

1

PerlTeX : 1143 chars (nhưng tôi chưa chơi gôn)

\documentclass{article}

\usepackage{perltex}
\usepackage{tikz}

\perlnewcommand{\readfile}[1]{
  open my $fh, '<', shift;
  ($rm,$cm) = split /\s+/, scalar <$fh>;
  @m = map { chomp; [ map { /\s/ ? 1 : 0 } split // ] } <$fh>;
  return "";
}

\perldo{
  $n=1;
  sub num {
    my ($r,$c) = @_;
    if ($r == 0) {
      return $n++;
    }
    if ($c == 0) {
      return $n++;
    }
    unless ($m[$r][$c-1] and $m[$r-1][$c]) {
      return $n++;
    }
    return;
  }
}

\perlnewcommand{\makegrid}[0]{
  my $scale = 1;
  my $return;
  my ($x,$y) = (0,$r*$scale);
  my ($ri,$ci) = (0,0);
  for my $r (@m) {
    for my $open (@$r) {
      my $f = $open ? '' : '[fill]';
      my $xx = $x + $scale;
      my $yy = $y + $scale;
      $return .= "\\draw $f ($x,$y) rectangle ($xx,$yy);\n";

      my $num = $open ? num($ri,$ci) : 0;
      if ( $num ) {
        $return .= "\\node [below right] at ($x, $yy) {$num};";
      }

      $x += $scale;
      $ci++;
    }
    $ci = 0;
    $x = 0;
    $ri++;
    $y -= $scale;
  }
  return $return;
}

\begin{document}
\readfile{grid.txt}

\begin{tikzpicture}
  \makegrid
\end{tikzpicture}

\end{document}

Nó cần một tệp được gọi grid.txtvới thông số kỹ thuật, sau đó biên dịch với

perltex --nosafe --latex=pdflatex grid.tex

1

Scala 252:

object c extends App{val z=readLine.split("[ ]+")map(_.toInt-1)
val b=(0 to z(0)).map{r=>readLine}
var c=0
(0 to z(0)).map{y=>(0 to z(1)).map{x=>if(b(y)(x)==' '&&((x==0||b(y)(x-1)==35)||(y==0||b(y-1)(x)==35))){c+=1
println(c+"\t"+(y+1)+"\t"+(x+1))}}
}}

biên soạn và gọi

scalac cg-318-crossword.scala && cat cg-318-crossword | scala c

0

CHIA SẺ

#!/bin/sh
crossWordFile=$1

totLines=`head -1 $crossWordFile | cut -d" " -f1`
totChars=`head -1 $crossWordFile | awk -F' ' '{printf $2}'`

NEXT_NUM=1
for ((ROW=2; ROW<=(${totLines}+1); ROW++))
do
   LINE=`sed -n ${ROW}p $crossWordFile`
   for ((COUNT=0; COUNT<${totChars}; COUNT++))
   do
      lineNumber=`expr $ROW - 1`
      columnNumber=`expr $COUNT + 1`
      TOKEN=${LINE:$COUNT:1}
      if [ "${TOKEN}" != "#" ]; then
      if [ ${lineNumber} -eq 1 ] || [ ${columnNumber} -eq 1 ]; then
          printf "${NEXT_NUM}\t${lineNumber}\t${columnNumber}\n"
          NEXT_NUM=`expr $NEXT_NUM + 1`
      elif [ "${TOKEN}" != "#" ] ; then
          upGrid=`sed -n ${lineNumber}p $crossWordFile | cut -c"${columnNumber}"`
          leftGrid=`sed -n ${ROW}p $crossWordFile | cut -c${COUNT}`
          if [ "${leftGrid}" = "#" ] || [ "${upGrid}" = "#" ]; then
          printf "${NEXT_NUM}\t${lineNumber}\t${columnNumber}\n"
          NEXT_NUM=`expr $NEXT_NUM + 1`
          fi
      fi
      fi
   done
done

mẫu I / O:

./numberCrossWord.sh ô chữGrid.txt

1       1       2
2       1       3
3       2       2
4       2       4
5       2       5
6       3       1
7       3       4
8       4       1
9       4       3
10      5       3

Tôi có thể chưa hiểu đầy đủ các yêu cầu, vì tôi chỉ cố gắng hiểu từ I / O được cung cấp, xin vui lòng tha thứ nếu giải pháp chỉ là cách giải quyết cho trường hợp cụ thể :)
Aman ZeeK Verma

Tôi /bin/shphàn nàn về dòng 11. Bạn có thể nói bạn đang sử dụng shell nào (bao gồm số phiên bản) không?
dmckee --- ex-moderator mèo con

Dòng 8 dường như tương tự như dòng 11 .. phải không? $ bash --version GNU bash, phiên bản 3.1.17 (1) -release (x86_64-suse-linux)
Aman ZeeK Verma

hãy thử sửa đổi #! bin / sh thành # /! / bin / bash, Nó sẽ hoạt động ngay bây giờ!
Aman ZeeK Verma

0

ANSI C 694 ký tự

Đây là phiên bản C tìm kiếm các bước chạy ngang hoặc dọc của hai không gian được đặt ngược lên cạnh hoặc chống lại ký tự '#'.

Tập tin đầu vào được lấy từ stdin và phải:

<rows count> <cols count><newline>
<cols characters><newline> x rows
...

Bất kỳ lời khuyên cho việc nén này sẽ được nhận biết ơn.

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

#define H '#'

char *p,*g;
int m=0,d=0,r=0,c=0,R=0,C=0;
void n() {
    while(!isdigit(d=getchar()));
    m=d-'0';
    while(isdigit(d=getchar()))
        m=m*10+d-'0';
}

int t() {
    return (((c<1||*(p-1)==H)&&c<C-1&&*p!=H&&p[1]!=H)||
            ((r<1||*(p-C-1)==H)&&r<R-1&&*p!=H&&p[C+1]!=H));
}

int main (int argc, const char * argv[]) 
{
    n();R=m;m=0;n();C=m;
    p=g=malloc(R*C+R+1);
    while((d=getchar())!=EOF) {
        *p++=d;
    }
    int *a,*b;
    b=a=malloc(sizeof(int)*R*C+R+1);
    p=g;m=0;
    while(*p) {
        if(t()) {
            *a++=++m;
            *a++=r+1;
            *a++=c+1;
        }
        if(++c/C) r++,p++;
        c-=c/C*c;
        p++;
    }
    while(*b) {
        printf("%d\t%d\t%d\n",*b,b[1],b[2]);
        b+=3;
    }
}

Đầu ra cho ví dụ được cung cấp

1   1   2
2   1   3
3   2   2
4   2   4
5   2   5
6   3   1
7   3   4
8   4   1
9   4   3
10  5   3

Mã này xử lý chính xác các khoảng trống không gian đơn dọc và ngang # _ #, mặc dù chúng có thể không xảy ra dưới dạng một không gian không được kết nối duy nhất, dường như được cho phép, ví dụ như chữ cái cuối cùng của từ, nói, từ ngang.
Jonathan Watmough
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.