Numérotation des mots croisés

9

Produisez un programme pour numéroter correctement une grille de mots croisés.

Contribution

L'entrée sera le nom d'un fichier représentant la grille de mots croisés. Le nom du fichier d'entrée peut être passé sous forme d'argument, sur l'entrée standard ou par d'autres moyens conventionnels autres que le codage en dur.

Format de fichier de grille: un fichier texte. La première ligne se compose de deux constantes entières séparées par des espaces blancs Met N. À la suite de cette ligne se trouvent des M lignes composées chacune de Ncaractères (plus une nouvelle ligne) sélectionnés parmi [#A-Z ]. Ces caractères sont interprétés de manière à '#' indiquer un carré bloqué, ' 'un carré ouvert dans le puzzle sans contenu connu et toute lettre un carré ouvert contenant cette lettre.

Production

La sortie sera un fichier de numérotation et peut être envoyée à la sortie standard, à un fichier dont le nom est dérivé du nom de fichier d'entrée, à un fichier spécifié par l'utilisateur ou à une autre destination conventionnelle.

Format de fichier de numérotation Un fichier texte. Les lignes commençant par '#' sont ignorées et peuvent être utilisées pour les commentaires. Toutes les autres lignes contiennent un onglet séparé triplet i, m, nireprésente un nombre devant être imprimé sur la grille, et met nreprésentent la rangée et la colonne de la place où il doit être imprimé. Le nombre de lignes et de colonnes commence à 1.

Schéma de numérotation

Une grille correctement numérotée a les propriétés suivantes:

  1. La numérotation commence à 1.
  2. Aucune colonne ou étendue de carrés ouverts n'est non numérotée. (Vous pouvez supposer qu'aucune réponse de caractère unique n'existera dans le problème.)
  3. Les nombres seront rencontrés dans l'ordre de comptage en scannant de la ligne du haut vers le bas en prenant chaque ligne de gauche à droite. (Ainsi, chaque étendue horizontale est numérotée sur son carré le plus à gauche, et chaque colonne est numérotée sur son carré le plus haut.)

Entrée de test et sortie attendue

Contribution:

5   5
#  ##
#    
  #  
    #
##  #

Sortie (en négligeant les lignes de commentaire):

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

De côté

Il s'agit du premier de ce qui sera, espérons-le, plusieurs défis liés aux mots croisés. Je prévois d'utiliser un ensemble cohérent de formats de fichiers tout au long du processus et de créer une suite respectable d'utilitaires liés aux mots croisés. Par exemple, un puzzle ultérieur nécessitera l'impression d'une version ASCII des mots croisés en fonction de l'entrée et de la sortie de ce puzzle.

dmckee --- chaton ex-modérateur
la source
Les plages de caractères uniques ne sont pas numérotées, non?
Keith Randall
@Kieth: Je préfère la règle où il n'y a pas de telles plages, mais je ne l'ai pas spécifiée ici car la validation de la grille est planifiée comme un autre problème. Je suppose que ce que vous utilisez est une question de goût.
dmckee --- chaton ex-modérateur du
le fichier d'entrée sera-t-il en txt?
www0z0k
@ www0z0k: Oui. Le geek Unix en moi est toujours par défaut le texte.
dmckee --- chaton ex-modérateur
1
@ www0z0k: Les sauts de ligne sont tout ce qui est natif sur votre plate-forme. C'est ASCII décimal 20 sur le mien et représenté comme '\n'en c sur toutes les plateformes. L'hypothèse est que le fichier d'entrée a été produit sur le même système qui le traitera, donc ce problème devrait être transparent. Une note générale sur le code-golf: si vous travaillez dans une langue étrange ou sur une plate-forme étrange, notez simplement tout ce qui pourrait surprendre le lecteur. Les gens en tiendront compte pour juger votre soumission.
dmckee --- chaton ex-modérateur

Réponses:

4

Ruby - 210 139 caractères

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

Testé avec rubis 1.9.

Arnaud Le Blanc
la source
Je suis la plupart de ça. Je ne sais pas ce que fait s.shift.split.map, mais cela doit former le tableau à partir de l'entrée.
dmckee --- chaton ex-modérateur
BTW-- Comment dois-je l'invoquer sur une ligne de commande Unix. J'ai essayé de lui donner un shebang approprié à mon système, mais il se plaint ./temp.ruby:4: wrong argument type Symbol (expected Proc) (TypeError).
dmckee --- chaton ex-modérateur
s.shift prend la première ligne, split renvoie ["m", "n"], la carte retourne [m, n]. Je suis en avec ruby1.9 comme ceci: ruby1.9 test.rb.
Arnaud Le Blanc
3

PHP - 175 caractères

<?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);
Arnaud Le Blanc
la source
Je me demandais quand quelqu'un allait le faire dans un tableau 1d.
dmckee --- ex-modérateur chaton
3

Python, 194 177 177 176 172 caractères

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
Keith Randall
la source
Vous devriez pouvoir utiliser h.join(f)je pense
gnibbler
et next(f)au lieu de f.readline()si vous êtes> = 2,6 sinonf.next()
gnibbler
Mon python n'a jamais été très bon, mais il semble que vous utilisiez des «#» supplémentaires pour gérer les cas de bord, non? Cependant, je reçois une sortie étrange sur les données de test, y compris des nombres supplémentaires.
dmckee --- chaton ex-modérateur
@dmckee, oui j'utilise des # supplémentaires pour marquer le bord. Pouvez-vous publier un cas de test où vous pensez qu'il échoue?
Keith Randall
@Kieth: Pour le cas de test ci-dessus, je reçois 12 lignes de sortie (et les 10 premières ne correspondent pas). Utilisation de python2.6 ou 2.7 sur mon Mac. Courir avec echo test_input_file_name | python golf.py, est-ce mal?
dmckee --- chaton ex-modérateur
2

C ++ 270 264 260 256 253 car

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

Utiliser:

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

Joliment formaté:

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

J'ai essayé de lire les mots croisés en une seule fois et d'utiliser une seule boucle.
Mais le coût de la compensation du caractère '\ n l'emportait sur les gains:

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

Compressé: 260 caractères

#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);}
Martin York
la source
Il m'a fallu quelques essais pour l'invoquer correctement. Nappe.
dmckee --- chaton ex-modérateur
2

C, 184 189 caractères

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

Pas grand chose à dire ici; la logique est assez basique. Le programme prend le nom de fichier sur l'entrée standard lors de l'exécution. (C'est tellement ennuyeux que le programme doit travailler avec un nom de fichier, et ne peut pas simplement lire le contenu du fichier directement à partir de l'entrée standard. Mais celui qui paie le piper appelle l'air!)

Le fscanf()motif étrange est ma tentative de numériser la première ligne complète, y compris la nouvelle ligne, mais pas inclure les espaces de tête sur la ligne suivante. Il y a une raison pour laquelle personne n'utilise scanf().

boite à pain
la source
Je pense que vous inversez le nombre de lignes et de colonnes. Si je comprends bien, le premier nombre est le nombre de lignes, mais vous le traitez comme le nombre de colonnes.
ugoren
D'après ce que je peux dire, la sortie de mon programme correspond à l'exemple donné dans la description et à la sortie de l'implémentation de référence. Pouvez-vous me donner un exemple précis de ce à quoi vous faites référence?
boîte à pain
Tout exemple où les numéros de lignes et de colonnes ne sont pas égaux.
ugoren
D'accord, mais soyons précis s'il vous plaît. Quand on me donne l'exemple de grille fourni dans la description, mon programme affiche (1,2) pour le nombre 1. Êtes-vous en train de dire que mon programme devrait produire (2,1)?
boîte à pain
Je parle d'entrée, pas de sortie. Lorsque la première ligne est 5 5, vous prenez les 5 premiers comme largeur, alors que vous auriez dû prendre la seconde (ce qui n'a pas d'importance, bien sûr, dans cet exemple).
ugoren
1

Implémentation de référence:

c99 non- golfé et un peu plus de 2000 caractères comprenant diverses frobs de débogage toujours là.

#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;
}
dmckee --- chaton ex-modérateur
la source
1

PerlTeX : 1143 caractères (mais je ne l'ai pas encore joué au 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}

Il a besoin d'un fichier appelé grid.txtavec la spécification, puis compiler avec

perltex --nosafe --latex=pdflatex grid.tex
Joel Berger
la source
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))}}
}}

compilation et invocation:

scalac cg-318-crossword.scala && cat cg-318-crossword | scala c
Utilisateur inconnu
la source
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

exemple d'E / S:

./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
Aman ZeeK Verma
la source
Je n'ai peut-être pas entièrement compris les exigences, comme je viens d'essayer de comprendre à partir des E / S fournies, veuillez pardonner si la solution n'est qu'une solution de contournement pour un cas particulier donné :)
Aman ZeeK Verma
Mon se /bin/shplaint de la ligne 11. Pourriez-vous dire quel shell vous utilisez (y compris le numéro de version)?
dmckee --- chaton ex-modérateur
La ligne 8 semble être similaire à la ligne 11 .. n'est-ce pas? $ bash --version GNU bash, version 3.1.17 (1) -release (x86_64-suse-linux)
Aman ZeeK Verma
essayez de modifier #! bin / sh en # /! / bin / bash, cela devrait fonctionner maintenant!
Aman ZeeK Verma
0

Caractères ANSI C 694

Il s'agit d'une version C qui recherche des parcours horizontaux ou verticaux de deux espaces qui sont soit appuyés contre le bord, soit contre un caractère «#».

Le fichier d'entrée provient de stdin et doit être:

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

Tous les conseils pour le compactage seront reçus avec gratitude.

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

Sortie pour l'exemple fourni

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
Jonathan Watmough
la source
Ce code gère correctement # _ # les espaces verticaux et horizontaux à espace unique qui, bien qu'ils ne puissent pas apparaître comme un seul espace non connecté, semblent être autorisés, par exemple comme la dernière lettre d'un mot, par exemple, horizontal.
Jonathan Watmough