Bulmaca numaralandırma


9

Bir bulmaca ızgarasını doğru numaralandırmak için bir program üretin.

Giriş

Girdi, bulmaca ızgarasını temsil eden bir dosyanın adı olacaktır. Girdi dosya adı bir argüman olarak, standart girdi üzerinde veya sabit kodlama dışındaki diğer geleneksel yollarla geçirilebilir.

Izgara dosya biçimi: Bir metin dosyası. İlk satır iki boşlukla ayrılmış tamsayı sabitinden oluşur Mve N. Bu satırdan sonra, M her biri Nkarakterlerden oluşan satırlar (artı yeni bir satır) seçilir [#A-Z ]. Bu karakterler, '#' engellenmiş bir kareyi, ' 'bulmacada bilinen içeriği olmayan açık bir kareyi ve o harfi içeren açık bir kareyi gösteren bir şekilde yorumlanır.

Çıktı

Çıktı bir numaralandırma dosyası olacaktır ve standart çıktıya, adı girdi dosya adından türetilen bir dosyaya, kullanıcının belirlediği bir dosyaya veya başka bir geleneksel hedefe gönderilebilir.

Numaralandırma dosyası biçimi Bir metin dosyası. '#' İle başlayan satırlar yok sayılır ve yorumlar için kullanılabilir. Diğer tüm hatlar bir sekme ayrılmış üçlü içeren i, m, bir sayı ızgara üzerinde basılacak temsil eder ve ve bu basılmalıdır kare satır ve sütun temsil eder. Hem satırların hem de sütunların sayısı 1'den başlar.nimn

Numaralandırma şeması

Doğru numaralandırılmış bir ızgara aşağıdaki özelliklere sahiptir:

  1. Numaralandırma 1'den başlar.
  2. Hiçbir sütun veya açık karelerin sayısı numaralandırılmamıştır. (Sorunda tek bir karakter cevabı bulunmayacağını varsayabilirsiniz.)
  3. Sayım sırasına göre, her satırı soldan sağa alarak üst sıradan alta tarama yapılarak karşılaşılır. (Böylece, her yatay aralık en soldaki karede numaralandırılır ve her sütun en üstteki karede numaralandırılır.)

Test girişi ve beklenen çıktı

Giriş:

5   5
#  ##
#    
  #  
    #
##  #

Çıktı (yorum satırlarını ihmal etme):

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

bir kenara

Bu, umarım bulmaca ile ilgili birçok zorluğun ilkidir. Süre boyunca tutarlı bir dosya formatı seti kullanmayı ve bu süreçte saygın bir bulmaca ile ilgili yardımcı program oluşturmayı planlıyorum. Örneğin, sonraki bir bulmaca bu bulmacanın giriş ve çıkışına dayalı olarak bulmacanın ASCII versiyonunu yazdırmak için çağrıda bulunacaktır.


Tek karakterlik açıklıklar numaralandırılmamıştır, değil mi?
Keith Randall

@Kieth: Böyle bir açıklığın olmadığı kuralı tercih ederim, ancak ızgarayı doğrulamanın başka bir sorun olarak planlandığı için burada belirtmedim. Sanırım hangisini kullandığınız bir tat meselesi.
dmckee --- ex-moderatör kedi yavrusu

giriş dosyası txt olacak mı?
www0z0k

@ www0z0k: Evet. İçimdeki unix geek her zaman varsayılan metindir.
dmckee --- ex-moderatör kedi yavrusu

1
@ www0z0k: Platformunuzda yerel olan satır sonlarıdır. Bu benim için ASCII ondalık 20 ve '\n'tüm platformlarda c olarak temsil edilir . Varsayım, giriş dosyasının onu işleyecek aynı sistemde üretildiğinden, bu sorunun şeffaf olması gerekir. Code-golf hakkında genel bir not: Eğer garip bir dilde veya garip bir platformda çalışıyorsanız, okuyucuyu şaşırtabilecek herhangi bir şeyi not edin. İnsanlar, başvurunuzu değerlendirirken buna izin vereceklerdir.
dmckee --- ex-moderatör kedi yavrusu

Yanıtlar:


4

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

Yakut 1.9 ile test edildi.


Bunların çoğunu takip ediyorum. S.shift.split.map uygulamasının ne yaptığından emin değilim, ancak bu girdiden girdi oluşturuyor olmalıdır.
dmckee --- eski moderatör yavru kedi

BTW-- Bir unix komut satırında nasıl çağırmalıyım. Sistemime uygun bir şey vermeyi denedim ama şikayet ediyor ./temp.ruby:4: wrong argument type Symbol (expected Proc) (TypeError).
dmckee --- eski moderatör kedi yavrusu

s.shift ilk satırı alır, split döndürür ["m", "n"], harita döndürür [m, n]. Böyle ruby1.9 ile taratıyorum: 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);

Birisi 1d dizide ne zaman yapacağını merak ettim.
dmckee --- ex-moderatör kedi yavrusu

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

h.join(f)Bence kullanabilmelisin
gnibbler

ve next(f)yerine f.readline()eğer> = 2.6 elsef.next()
gnibbler

Python'um hiç bu kadar iyi olmamıştı, ama kenar vakalarını işlemek için ekstra '#' kullanıyorsunuz gibi görünüyor, değil mi? Ancak, ekstra sayılar da dahil olmak üzere test verilerinde bazı garip çıktılar alıyorum.
dmckee --- ex-moderatör kitten

@ dmckee, evet kenarı işaretlemek için ekstra #s kullanıyorum. Başarısız olduğunu düşündüğünüz bir test vakası gönderebilir misiniz?
Keith Randall

@Kieth: Yukarıdaki test durumu için 12 çıkış hattı alıyorum (ve ilk 10 tanesi eşleşmiyor). Mac bilgisayarımda python2.6 veya 2.7 kullanma. Onunla koşmak echo test_input_file_name | python golf.py, bu yanlış mı?
dmckee --- eski moderatör yavru kedi

2

C ++ ' 270 264 260 256 253 karakter

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

Kullanmak:

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

Güzel biçimlendirilmiş:

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

Tek bir seferde tüm bulmaca okuma ve tek bir döngü kullanarak denedim.
Ancak '\ n karakterini telafi etmenin maliyeti kazançlardan ağır bastı:

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

Sıkıştırılmış: 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);}

Bana doğru çağırmaya çalıştım. Kaygan.
dmckee --- eski moderatör kedi yavrusu

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

Burada söylenecek fazla bir şey yok; mantık oldukça basit. Program çalışma zamanında standart girdi üzerindeki dosya adını alır. (Programın bir dosya adıyla çalışması çok can sıkıcı ve dosya içeriğini doğrudan standart girdiden okuyamıyor. Ancak piper'i ödeyen kişi melodi çağırıyor!)

Garip fscanf()desen, yeni satır da dahil olmak üzere ilk satırın tamamını tarama girişimimdir, ancak sonraki satırda önde gelen boşluk içermez. Kimsenin kullanmamasının bir nedeni var scanf().


Bence satır ve sütun sayısını ters çeviriyorsunuz. Doğru anlarsam, ilk sayı satır sayısıdır, ancak sütun sayısı olarak kabul edersiniz.
ugoren

Söyleyebileceğim kadarıyla, programımın çıktısı açıklamada verilen örnekle ve referans uygulamasından çıktıyla eşleşiyor. Bana neye atıfta bulunduğunuzu gösteren özel bir örnek verebilir misiniz?
breadbox

Satır ve sütun sayılarının eşit olmadığı herhangi bir örnek.
ugoren

Tamam, ama lütfen spesifik olalım. Açıklamada verilen örnek tablo verildiğinde, programım 1 sayısı için (1,2) çıktı. Programımın (2,1) çıktı alması gerektiğini mi söylüyorsunuz?
ekmek kutusu

Ben girdiden bahsediyorum, çıktıdan değil. İlk satır olduğunda 5 5, ilk 5'i genişlik olarak alırsınız, ikinciyi almanız gerektiğinde (bu örnekte elbette önemli değildir).
ugoren

1

Referans uygulaması:

c99 kurtulmuş ve içinde hala çeşitli hata ayıklama frobs dahil 2000'den fazla karakter.

#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 (ama henüz golf oynamadım)

\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.txtSpec ile adlandırılan bir dosyaya ihtiyaç duyar , daha sonra

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

derleme ve çağırma:

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

örnek G / Ç:

./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

Solüsyon :) verilen özel durumda sadece geçici bir çözüm olup olmadığını sadece sağlanan I / O'dan anlamaya çalıştım gibi ben tam gereksinimleri anlaşılamamış olabilir, lütfen affet
Aman Zeek Verma

Benim /bin/shsize (sürüm numarası dahil) kullanıyorsanız shell ne olduğunu söylemek Could hat 11. şikayetçi?
dmckee --- eski moderatör yavru kedi

Satır 8, satır 11'e benziyor .. değil mi? $ bash - sürüm GNU bash, sürüm 3.1.17 (1) -çalışma (x86_64-suse-linux)
Aman ZeeK Verma

#! bin / sh değerini # /! / bin / bash olarak değiştirmeyi deneyin, Şimdi çalışmalı!
Aman ZeeK Verma

0

ANSI C 694 karakter

Bu, kenara veya '#' karakterine yaslanmış iki boşluğun yatay veya dikey çalışmalarını arayan bir C sürümüdür.

Girdi dosyası stdin'den alınmıştır ve şöyle olmalıdır:

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

Bunu sıkıştırmak için tüm ipuçları minnetle alınacaktır.

#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ğlanan Örnek için Çıktı

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

Bu kod, bağlantısız tek bir boşluk olarak oluşmasa da, örneğin yatay bir sözcüğün son harfi gibi, izin verilmiş gibi görünen # _ # dikey ve yatay tek boşluk boşluklarını doğru şekilde işler.
Jonathan Watmough
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.