クロスワードの番号付け


9

クロスワードグリッドに正しく番号を付けるプログラムを作成します。

入力

入力は、クロスワードグリッドを表すファイルの名前になります。入力ファイル名は、引数として、標準入力で、またはハードコーディング以外の従来の方法で渡すことができます。

グリッドファイル形式:テキストファイル。1行目は、空白で区切られた2つの整数定数Mとで構成されていNます。その行に続くのは、M それぞれからN選択された文字(および新しい行)で構成される行[#A-Z ]です。これらの文字は'#' 、ブロックされた四角形、' '既知のコンテンツのないパズル内の開いた四角形、およびその文字を含む開いた四角形を示すように解釈されます。

出力

出力は番号付けファイルになり、標準出力、入力ファイル名から派生した名前のファイル、ユーザー指定のファイル、または他の従来の宛先に送信できます。

ナンバリングファイルフォーマットテキストファイル。「#」で始まる行は無視され、コメントに使用できます。他のすべての行はタブ区切りトリプレット含むim、数がグリッド上に印刷されるべきであり、そしてそれが印刷されるべきである正方形の行と列を表しています。行と列の両方の数は1から始まります。nimn

採番スキーマ

正しい番号のグリッドには、次のプロパティがあります。

  1. 番号は1から始まります。
  2. 開いている正方形の列またはスパンには番号が付けられていません。(問題には1文字の回答が存在しないと考えるかもしれません。)
  3. 番号は、各行を左から右に取って、上から下にスキャンすることにより、カウント順に発生します。(したがって、すべての水平スパンには左端の正方形から番号が付けられ、すべての列には一番上の正方形から番号が付けられます。)

テスト入力と期待される出力

入力:

5   5
#  ##
#    
  #  
    #
##  #

出力(コメント行を無視):

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

さておき

これは、いくつかのクロスワード関連の課題になると期待される最初のものです。私は一貫して一連のファイル形式を使用し、その過程でクロスワード関連ユーティリティの立派なスイートを構築する予定です。たとえば、後続のパズルでは、このパズルの入力と出力に基づいてクロスワードのASCIIバージョンを印刷する必要があります。


1文字のスパンは番号付けされていませんよね?
キースランドール

@キース:そのようなスパンがないルールを好みますが、グリッドの検証が別の問題として計画されているため、ここでは指定していません。どちらを使うかは好みの問題だと思います。
dmckee ---元モデレーターの子猫、2011

入力ファイルはtxtになりますか?
www0z0k

@ www0z0k:はい。私のUNIXオタクは常にデフォルトでテキストになります。
dmckee ---元モデレーターの子猫

1
@ www0z0k:改行はプラットフォームのネイティブなものです。これは、私の場合はASCII 10進数20で'\n'、すべてのプラットフォームでcのように表されます。入力ファイルは、それを処理するのと同じシステムで作成されたと想定されているため、この問題は透過的です。コードゴルフについての一般的な注意:奇妙な言語や奇妙なプラットフォームで作業している場合は、読者を驚かせるかもしれないことをメモしてください。人々はあなたの提出物を判断する際にそれを考慮に入れます。
dmckee ---元モデレーターの子猫

回答:


4

Ruby- 210 139文字

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])}

ruby 1.9でテスト済み。


私はそのほとんどに従います。s.shift.split.mapの機能はわかりませんが、入力から配列を形成している必要があります。
dmckee ---元モデレーターの子猫

ところで-UNIXコマンドラインでどのように呼び出すべきですか?私のシステムに適切なシバンを与えようとしましたが、それは不満./temp.ruby:4: wrong argument type Symbol (expected Proc) (TypeError)です。
dmckee ---元モデレーターの子猫11/02/04

s.shiftは最初の行を取り、splitは["m"、 "n"]を返し、mapは[m、n]を返します。次のようにruby1.9で実行していますruby1.9 test.rb
Arnaud Le Blanc


3

Python、194 177 176 172文字

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

あなたはh.join(f)私が思うに使用できるはずです
gnibbler

そして、あなたが> = 2.6 next(f)であるf.readline()場合の代わりに、elsef.next()
gnibbler

私のpythonは決して良いものではありませんでしたが、エッジケースを処理するために余分な「#」を使用しているようです。ただし、追加の数値を含めて、テストデータに関する奇妙な出力が表示されます。
dmckee ---元モデレーターの子猫

@dmckee、はい、エッジをマークするために余分な#を使用しています。失敗したと思われるテストケースを投稿できますか?
Keith Randall

@キース:上記のテストケースでは、12の出力行を取得しています(最初の10行は一致しません)。Macでpython2.6または2.7を使用しています。で実行するとecho test_input_file_name | python golf.py、間違っていますか?
dmckee ---元モデレーターの子猫

2

C ++ 270 264 260 256個の 253文字

#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);}

使用するには:

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

うまくフォーマットされた:

#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);
}

クロスワード全体を一度に読み、単一のループを使用してみました。
しかし、「\ n」キャラクターを補うためのコストは、利益を上回っていました。

#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);
}

圧縮:260文字

#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);}

数回試して、正しく起動しようとしました。スリック。
dmckee ---元モデレーターの子猫

2

C、184 189文字

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);}

ここで言うことはあまりありません。ロジックはかなり基本的です。プログラムは、実行時に標準入力でファイル名を受け取ります。(プログラムがファイル名を処理する必要があり、標準入力からファイルの内容を直接読み取ることができないのは非常に不愉快です。しかし、パイパーを支払う人が曲を呼び出します!)

奇妙なfscanf()パターンは、改行を含むが次の行の先頭の空白を含まない最初の行全体をスキャンしようとする私の試みです。誰もを使用しない理由がありますscanf()


行と列の番号を逆にすると思います。私が正しく理解していれば、最初の数は行数ですが、それは列数として扱います。
ugoren

私の知る限りでは、私のプログラムの出力は、説明に示されている例と、リファレンス実装からの出力と一致しています。あなたが言及している具体的な例を教えていただけますか?
ブレッドボックス、

行と列の番号が等しくない例。
ugoren

では、具体的に説明しましょう。説明で提供されているサンプルグリッドを指定すると、私のプログラムは数値1に対して(1,2)を出力します。私のプログラムは(2,1)を出力する必要があると言っていますか?
ブレッドボックス

私は出力ではなく入力について話している。最初の行がの5 5場合、最初の5行を幅として使用し、2行目を取得する必要があった場合(もちろん、この例では問題ではありません)。
ugoren

1

リファレンス実装:

c99 ungolfedであり、さまざまなデバッグフラグを含む2000文字以上がまだ残っています。

#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文字(しかし、まだゴルフしていません)

\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}

grid.txt仕様で呼び出されたファイルが必要です。次に、

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))}}
}}

コンパイルと呼び出し:

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

0

シェルスクリプト

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

サンプルI / O:

./numberCrossWord.sh crosswordGrid.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

提供されたI / Oから理解しようとしたばかりなので、要件を完全に理解していなかった可能性があります。解決策が特定のケースに対する回避策にすぎない場合は、ご容赦ください:)
Aman ZeeK Verma

私は、/bin/shあなたが(バージョン番号を含む)を使用しているシェル何を言うことができるライン11文句を言いますか?
dmckee ---元モデレーターの子猫

8行目は11行目と似ているようですね。$ bash --version GNU bash、バージョン3.1.17(1)-release(x86_64-
suse

#!bin / shを#/!/ bin / bashに変更してみてください。これで動作するはずです!
Aman ZeeK Verma

0

ANSI C 694文字

これは、エッジまたは「#」文字に対して突き合わされた2つのスペースの水平または垂直のランを探すCバージョンです。

入力ファイルはstdinから取得され、次のようにする必要があります。

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

これを圧縮するためのヒントはありがたく受け取られます。

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

提供された例の出力

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

このコードは、#_#の垂直および水平の単一スペースギャップを正しく処理します。これらのギャップは、単一の接続されていないスペースとしては発生しませんが、たとえば水平ワードの最後の文字として許可されているように見えます。
ジョナサンワトモフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.