Penomoran teka-teki silang


9

Menghasilkan sebuah program untuk memberi nomor dengan benar pada grid silang.

Memasukkan

Input akan menjadi nama file yang mewakili kisi teka-teki silang. Nama file input dapat diberikan sebagai argumen, pada input standar, atau dengan cara konvensional lain selain hardcoding.

Format file kotak: File teks. Baris pertama terdiri dari dua konstanta integer putih-ruang yang dipisahkan Mdan N. Mengikuti garis itu adalah M garis yang masing-masing terdiri dari Nkarakter (ditambah garis baru) dipilih [#A-Z ]. Karakter-karakter ini diinterpretasikan sedemikian rupa sehingga '#' mengindikasikan kotak yang diblokir, ' 'kotak terbuka dalam teka-teki tanpa isi yang diketahui dan huruf apa pun berupa kotak terbuka yang berisi huruf itu.

Keluaran

Output akan berupa file penomoran, dan dapat dikirim ke output standar, ke file yang namanya berasal dari nama file input, ke file yang ditentukan pengguna, atau ke beberapa tujuan konvensional lainnya.

Format file penomoran File teks. Baris yang dimulai dengan '#' diabaikan dan dapat digunakan untuk komentar. Semua jalur lain mengandung tab terpisah triplet i, m, ndi mana imerupakan nomor yang akan dicetak di grid, dan mdan nmewakili baris dan kolom dari alun-alun di mana ia harus dicetak. Jumlah baris dan kolom dimulai dari 1.

Skema penomoran

Kisi bernomor yang benar memiliki properti berikut:

  1. Penomoran dimulai pada 1.
  2. Tidak ada kolom atau rentang kotak terbuka yang tidak dinomori. (Anda dapat berasumsi bahwa tidak ada jawaban karakter tunggal dalam masalah ini.)
  3. Angka akan ditemui dalam penghitungan urutan dengan memindai dari baris atas ke bawah mengambil setiap baris dari kiri ke kanan. (Jadi, setiap bentang horizontal diberi nomor di kuadrat paling kiri, dan setiap kolom diberi nomor di kuadrat paling atas.)

Uji input dan output yang diharapkan

Memasukkan:

5   5
#  ##
#    
  #  
    #
##  #

Output (mengabaikan baris komentar):

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

Ke samping

Ini adalah yang pertama dari apa yang diharapkan akan menjadi beberapa tantangan terkait teka-teki silang. Saya berencana untuk menggunakan serangkaian file-format yang konsisten di seluruh dan untuk membangun seperangkat utilitas terkait silang yang terhormat dalam prosesnya. Misalnya teka-teki selanjutnya akan meminta untuk mencetak versi ASCII dari teka-teki silang berdasarkan input dan output dari teka-teki ini.


Bentang karakter tunggal tidak diberi nomor, bukan?
Keith Randall

@ Kimeth: Saya lebih suka aturan di mana tidak ada rentang seperti itu, tapi saya belum menentukannya di sini karena memvalidasi grid direncanakan sebagai masalah lain. Saya kira yang Anda gunakan adalah masalah selera.
dmckee --- ex-moderator kitten

akankah file input dimasukkan dalam txt?
www0z0k

@ www0z0k: Ya. The unix geek in me selalu default ke teks.
dmckee --- ex-moderator kitten

1
@ www0z0k: Jeda baris adalah apa pun yang asli di platform Anda. Itu ASCII desimal 20 pada tambang dan diwakili '\n'dalam c pada semua platform. Asumsinya adalah bahwa file input diproduksi pada sistem yang sama yang akan memprosesnya, jadi masalah ini harus transparan. Catatan umum tentang kode-golf: jika Anda menggunakan bahasa asing atau platform aneh, catat apa saja yang mungkin mengejutkan pembaca. Orang akan memberikan kelonggaran untuk itu dalam menilai kiriman Anda.
dmckee --- ex-moderator kitten

Jawaban:


4

Ruby - 210 139 karakter

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

Diuji dengan ruby ​​1.9.


Saya mengikuti sebagian besar dari itu. Tidak yakin apa s.shift.split.map tidak, tetapi itu harus membentuk array dari input.
dmckee --- ex-moderator kitten

BTW - Bagaimana saya memohonnya pada baris perintah unix. Saya mencoba memberikannya shebang yang sesuai dengan sistem saya, tetapi komplain ./temp.ruby:4: wrong argument type Symbol (expected Proc) (TypeError).
dmckee --- ex-moderator kitten

s.shift mengambil baris pertama, membagi pengembalian ["m", "n"], peta mengembalikan [m, n]. Aku berlari dengan ruby1.9 seperti ini: ruby1.9 test.rb.
Arnaud Le Blanc

3

PHP - 175 karakter

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

Saya bertanya-tanya kapan seseorang akan melakukannya dalam array 1d.
dmckee --- ex-moderator kitten

3

Python, 194 177 176 172 karakter

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

Anda seharusnya bisa menggunakan h.join(f)saya pikir
gnibbler

dan next(f)alih-alih f.readline()jika Anda> = 2.6 lainnyaf.next()
gnibbler

Python saya tidak pernah sangat bagus, tetapi sepertinya Anda menggunakan ekstra untuk menangani kasus tepi, bukan? Namun, saya mendapatkan beberapa hasil aneh pada data uji, termasuk angka tambahan.
dmckee --- ex-moderator kitten

@ dmckee, ya saya menggunakan #s ekstra untuk menandai tepi. Bisakah Anda memposting test case yang menurut Anda gagal?
Keith Randall

@ Kimeth: Untuk test case di atas saya mendapatkan 12 jalur output (dan 10 yang pertama tidak cocok). Menggunakan python2.6 atau 2.7 di Mac saya. Dengan menjalankannya echo test_input_file_name | python golf.py, apakah itu salah?
dmckee --- ex-moderator kitten

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

Menggunakan:

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

Diformat dengan baik:

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

Saya mencoba membaca seluruh teka-teki silang sekaligus dan menggunakan satu loop.
Tetapi biaya kompensasi untuk karakter '\ n melebihi keuntungan apa pun:

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

Terkompresi: 260 karakter

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

Saya perlu beberapa upaya untuk memanggilnya dengan benar. Licin.
dmckee --- ex-moderator kitten

2

C, 184 189 karakter

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

Tidak banyak bicara di sini; Logikanya cukup mendasar. Program ini mengambil nama file pada input standar saat runtime. (Sangat menjengkelkan bahwa program harus bekerja dengan nama file, dan tidak bisa hanya membaca isi file langsung dari input standar. Tetapi orang yang membayar piper memanggil nada!)

fscanf()Pola aneh adalah upaya saya untuk memindai baris pertama penuh, termasuk baris baru tetapi tidak termasuk spasi putih pada baris berikut. Ada alasan mengapa tidak ada yang menggunakan scanf().


Saya pikir Anda membalikkan jumlah baris dan kolom. Jika saya mengerti dengan benar, angka pertama adalah jumlah baris, tetapi Anda memperlakukannya sebagai jumlah kolom.
ugoren

Dari apa yang saya tahu, output dari program saya cocok dengan contoh yang diberikan dalam deskripsi, dan output dari implementasi referensi. Bisakah Anda memberi saya contoh spesifik tentang apa yang Anda maksud?
kotak roti

Contoh apa pun di mana angka baris dan kolom tidak sama.
ugoren

Oke, tapi mari kita spesifik. Ketika diberi contoh kisi yang disediakan dalam deskripsi, program saya mengeluarkan (1,2) untuk nomor 1. Apakah Anda mengatakan bahwa program saya harus menampilkan (2,1)?
kotak roti

Saya berbicara tentang input, bukan output. Ketika baris pertama adalah 5 5, Anda mengambil 5 pertama sebagai lebar, ketika Anda seharusnya mengambil yang kedua (yang tidak masalah, tentu saja, dalam contoh ini).
ugoren

1

Implementasi referensi:

c99 ungolfed dan lebih dari 2000 karakter termasuk berbagai debugging frob masih ada di sana.

#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 karakter (tapi saya belum bermain golf )

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

Perlu file yang disebut grid.txtdengan spec, lalu kompilasi dengan

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

kompilasi dan doa:

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

0

SHELL SCRIPT

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

sampel 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

Saya mungkin belum memahami persyaratan sepenuhnya, karena saya hanya mencoba memahami dari I / O yang disediakan, maafkan jika solusinya hanya merupakan solusi untuk kasus tertentu :)
Aman ZeeK Verma

/bin/shKeluhan saya tentang baris 11. Bisakah Anda mengatakan cangkang apa yang Anda gunakan (termasuk nomor versi)?
dmckee --- ex-moderator kitten

Jalur 8 sepertinya mirip dengan jalur 11 .. bukan? $ bash --versi GNU bash, versi 3.1.17 (1) -release (x86_64-suse-linux)
Aman ZeeK Verma

coba ubah #! bin / sh ke # /! / bin / bash, seharusnya sudah berfungsi sekarang!
Aman ZeeK Verma

0

ANSI C 694 karakter

Ini adalah versi C yang mencari lintasan horizontal atau vertikal dari dua spasi yang ditabrak ke tepi, atau melawan karakter '#'.

File input diambil dari stdin dan harus:

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

Setiap tips untuk memadatkan ini akan diterima dengan penuh syukur.

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

Output untuk Contoh yang Disediakan

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

Kode ini menangani dengan benar # _ # kesenjangan spasi tunggal vertikal dan horisontal, yang walaupun tidak mungkin muncul sebagai ruang tunggal yang tidak terhubung, tampaknya diizinkan, misalnya sebagai huruf terakhir dari, misalnya, kata horizontal.
Jonathan Watmough
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.