Numeração de palavras cruzadas

9

Produza um programa para numerar corretamente uma grade de palavras cruzadas.

Entrada

A entrada será o nome de um arquivo que representa a grade de palavras cruzadas. O nome do arquivo de entrada pode ser passado como argumento, na entrada padrão ou por outros meios convencionais que não sejam codificados.

Formato de arquivo de grade: um arquivo de texto. A primeira linha consiste em duas constantes inteiras separadas por espaço em branco Me N. Após essa linha, são M linhas, cada uma composta por Ncaracteres (mais uma nova linha) selecionados a partir de [#A-Z ]. Esses caracteres são interpretados de forma a '#' indicar um quadrado bloqueado, ' 'um quadrado aberto no quebra-cabeça sem conteúdo conhecido e qualquer letra um quadrado aberto que contenha essa letra.

Resultado

A saída será um arquivo de numeração e poderá ser enviada para a saída padrão, para um arquivo cujo nome é derivado do nome do arquivo de entrada, para um arquivo especificado pelo usuário ou para outro destino convencional.

Formato do arquivo de numeração Um arquivo de texto. As linhas iniciadas com '#' são ignoradas e podem ser usadas para comentários. Todas as outras linhas contêm uma guia separada tripleto i, m, nonde irepresenta um número a ser impresso sobre a grade, e me nrepresentam a linha e a coluna do quadrado onde deve ser impresso. O número de linhas e colunas começa em 1.

Esquema de numeração

Uma grade numerada corretamente possui as seguintes propriedades:

  1. A numeração começa em 1.
  2. Nenhuma coluna ou extensão de quadrados abertos é numerada. (Você pode assumir que nenhuma resposta de caractere único existirá no problema.)
  3. Os números serão encontrados em ordem de contagem, digitalizando da linha superior para a inferior, levando cada linha da esquerda para a direita. (Portanto, cada intervalo horizontal é numerado no quadrado mais à esquerda e todas as colunas são numeradas no quadrado mais alto.)

Entrada de teste e saída esperada

Entrada:

5   5
#  ##
#    
  #  
    #
##  #

Saída (negligenciando linhas de comentário):

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

a parte, de lado

Este é o primeiro do que, espera-se, vários desafios relacionados às palavras cruzadas. Pretendo usar um conjunto consistente de formatos de arquivo e criar um conjunto respeitável de utilitários relacionados a palavras cruzadas no processo. Por exemplo, um quebra-cabeça subsequente exigirá a impressão de uma versão ASCII das palavras cruzadas com base na entrada e saída desse quebra-cabeça.

dmckee --- gatinho ex-moderador
fonte
As extensões de caracteres únicos não são numeradas, certo?
Keith Randall
@ Kieth: Prefiro a regra em que não existem extensões, mas não a especifiquei aqui porque a validação da grade é planejada como outro problema. Suponho que você use é uma questão de gosto.
dmckee --- ex-moderador gatinho
o arquivo de entrada estará em txt?
Www0z0k
@ www0z0k: Sim. O nerd unix em mim sempre assume como padrão o texto.
dmckee --- ex-moderador gatinho
11
@ www0z0k: Quebras de linha são nativas da sua plataforma. Isso é decimal ASCII 20 no meu e representado como '\n'em c em todas as plataformas. A suposição é de que o arquivo de entrada foi produzido no mesmo sistema que o processará, portanto esse problema deve ser transparente. Uma observação geral sobre o code-golf: se você estiver trabalhando em um idioma estranho ou em uma plataforma estranha, anote qualquer coisa que possa surpreender o leitor. As pessoas levarão em consideração isso ao julgar sua submissão.
dmckee --- ex-moderador gatinho

Respostas:

4

Ruby - 210 139 caracteres

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

Testado com ruby ​​1.9.

Arnaud Le Blanc
fonte
Eu sigo a maior parte disso. Não tenho certeza do que o s.shift.split.map faz, mas isso deve estar formando a matriz a partir da entrada.
dmckee --- ex-moderador gatinho
BTW-- Como devo invocá-lo em uma linha de comando unix. Tentei dar um shebang apropriado ao meu sistema, mas ele reclama ./temp.ruby:4: wrong argument type Symbol (expected Proc) (TypeError).
dmckee --- ex-moderador gatinho
s.shift pega a primeira linha, a divisão retorna ["m", "n"], o mapa retorna [m, n]. Estou correndo com ruby1.9 assim: ruby1.9 test.rb.
Arnaud Le Blanc
3

PHP - 175 caracteres

<?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
fonte
Gostaria de saber quando alguém iria fazê-lo em uma matriz 1d.
dmckee --- ex-moderador gatinho
3

Pitão, 194 177 176 172 caracteres

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
fonte
Você deve ser capaz de usar h.join(f)eu acho
gnibbler
e next(f)em vez de f.readline()se você for> = 2,6 outra coisaf.next()
gnibbler
Meu python nunca foi muito bom, mas parece que você está usando '#' extras para lidar com os casos extremos, não? No entanto, estou obtendo uma saída ímpar nos dados de teste, incluindo números extras.
dmckee --- ex-moderador gatinho
@ dmckee, sim, estou usando # extras para marcar a borda. Você pode postar um caso de teste em que você acha que ele falha?
Keith Randall
@ Kieth: Para o caso de teste acima, estou recebendo 12 linhas de saída (e as 10 primeiras não coincidem). Usando python2.6 ou 2.7 no meu Mac. Executá-lo com isso echo test_input_file_name | python golf.pyestá errado?
dmckee --- ex-moderador gatinho
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);}

Usar:

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

Bem formatado:

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

Tentei ler as palavras cruzadas inteiras de uma só vez e usar um único loop.
Mas o custo de compensar o caractere '\ n superou quaisquer ganhos:

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

Comprimido: 260 caracteres

#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
fonte
Levei algumas tentativas para invocá-lo direito. Liso.
dmckee --- ex-moderador gatinho
2

C, 184 189 caracteres

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

Não há muito a dizer aqui; a lógica é bastante básica. O programa leva o nome do arquivo na entrada padrão em tempo de execução. (É tão irritante que o programa precise trabalhar com um nome de arquivo e não possa simplesmente ler o conteúdo do arquivo diretamente da entrada padrão. Mas quem paga o flautista chama a música!)

O fscanf()padrão estranho é minha tentativa de varrer a primeira linha completa, incluindo a nova linha, mas não incluindo os espaços em branco à esquerda na linha a seguir. Há uma razão pela qual ninguém usa scanf().

caixa de pão
fonte
Eu acho que você inverte o número de linhas e colunas. Se bem entendi, o primeiro número é o número de linhas, mas você o trata como o número de colunas.
Ugoren
Pelo que sei, a saída do meu programa corresponde ao exemplo dado na descrição e a saída da implementação de referência. Você pode me dar um exemplo específico do que você está se referindo?
breadbox
Qualquer exemplo em que os números de linhas e colunas não sejam iguais.
Ugoren
Ok, mas vamos ser específicos, por favor. Quando é fornecida a grade de exemplo fornecida na descrição, meu programa gera (1,2) o número 1. Você está dizendo que meu programa deve gerar (2,1)?
breadbox
Estou falando de entrada, não de saída. Quando a primeira linha é 5 5, você assume os 5 primeiros como a largura, quando deveria ter escolhido a segunda (o que não importa, é claro, neste exemplo).
Ugoren
1

Implementação de referência:

c99 ungolfed e mais de 2000 caracteres, incluindo vários frobs de depuração ainda 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 --- gatinho ex-moderador
fonte
1

PerlTeX : 1143 caracteres (mas ainda não joguei)

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

Ele precisa de um arquivo chamado grid.txtcom a especificação e compile com

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

compilação e invocação:

scalac cg-318-crossword.scala && cat cg-318-crossword | scala c
Usuário desconhecido
fonte
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

E / S de amostra:

./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
fonte
Eu posso não ter entendido os requisitos totalmente, como eu apenas tentei entender a partir fornecida I / O, por favor, perdoe, se a solução é apenas uma solução para determinado caso particular :)
Aman Verma Zeek
Minhas /bin/shqueixas sobre a linha 11. Você poderia dizer qual shell está usando (incluindo o número da versão)?
dmckee --- ex-moderador gatinho
A linha 8 parece ser semelhante à linha 11 .. não é? $ bash --version GNU bash, versão 3.1.17 (1) -release (x86_64-suse-linux)
Aman ZeeK Verma
tente modificar #! bin / sh para # /! / bin / bash, ele deve funcionar agora!
Aman ZeeK Verma
0

ANSI C 694 caracteres

Esta é uma versão em C que procura execuções horizontais ou verticais de dois espaços que se encontram contra a borda ou contra um caractere '#'.

O arquivo de entrada é obtido do stdin e deve ser:

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

Quaisquer dicas para compactar isso serão recebidas com gratidão.

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

Saída para o exemplo fornecido

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
fonte
Este código manipula corretamente # _ # lacunas de espaço único verticais e horizontais, que, embora não ocorram como um único espaço não conectado, parecem ser permitidas, por exemplo, como a última letra de uma palavra, digamos, horizontal.
precisa saber é o seguinte